diff --git a/Mage.Client/release/cacerts b/Mage.Client/release/cacerts deleted file mode 100644 index f50115666131..000000000000 Binary files a/Mage.Client/release/cacerts and /dev/null differ diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 07ce7d54e7da..cfcf25b24f24 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -26,6 +26,7 @@ import mage.client.plugins.impl.Plugins; import mage.client.preference.MagePreferences; import mage.client.remote.CallbackClientImpl; +import mage.client.remote.XmageURLConnection; import mage.client.table.TablesPane; import mage.client.table.TablesPanel; import mage.client.tournament.TournamentPane; @@ -54,6 +55,7 @@ import net.java.truevfs.access.TConfig; import net.java.truevfs.kernel.spec.FsAccessOption; import org.apache.log4j.Logger; +import org.junit.Assert; import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.SvgUtils; import org.mage.plugins.card.images.DownloadPicturesService; @@ -196,19 +198,6 @@ private void handleEvent(AWTEvent event) { } public MageFrame() throws MageException { - File cacertsFile = new File(System.getProperty("user.dir") + "/release/cacerts").getAbsoluteFile(); - if (!cacertsFile.exists()) { // When running from the jar file the contents of the /release folder will have been expanded into the home folder as part of packaging - cacertsFile = new File(System.getProperty("user.dir") + "/cacerts").getAbsoluteFile(); - } - if (cacertsFile.exists()) { - LOGGER.info("Custom (or bundled) Java certificate file (cacerts) file found"); - String cacertsPath = cacertsFile.getPath(); - System.setProperty("javax.net.ssl.trustStore", cacertsPath); - System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); - } else { - LOGGER.info("custom Java certificate file not found at: " + cacertsFile.getAbsolutePath()); - } - setWindowTitle(); // mac os only: enable full screen support in java 8 (java 11+ try to use it all the time) @@ -403,6 +392,41 @@ public void componentResized(ComponentEvent e) { }); } + /** + * Init certificates store for https work (if java version is outdated) + * Debug with -Djavax.net.debug=SSL,trustmanager + */ + @Deprecated // TODO: replaced by enableAIAcaIssuers, delete that code after few releases (2025-01-01) + private void initSSLCertificates() { + // from dev build (runtime) + boolean cacertsUsed = false; + File cacertsFile = new File(System.getProperty("user.dir") + "/release/cacerts").getAbsoluteFile(); + if (cacertsFile.exists()) { + cacertsUsed = true; + LOGGER.info("SSL certificates: used runtime cacerts bundle"); + } + + // from release build (jar) + // When running from the jar file the contents of the /release folder will have been expanded into the home folder as part of packaging + if (!cacertsUsed) { + cacertsFile = new File(System.getProperty("user.dir") + "/cacerts").getAbsoluteFile(); + if (cacertsFile.exists()) { + cacertsUsed = true; + LOGGER.info("SSL certificates: used release cacerts bundle"); + } + } + + if (cacertsUsed && cacertsFile.exists()) { + String cacertsPath = cacertsFile.getPath(); + System.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); // cacerts file format from java 9+ instead "jks" from java 8 + System.setProperty("javax.net.ssl.trustStore", cacertsPath); + System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); + } else { + LOGGER.info("SSL certificates: used default cacerts bundle from " + System.getProperty("java.version")); + } + System.setProperty("com.sun.security.enableAIAcaIssuers", "true"); + } + private void bootstrapSetsAndFormats() { LOGGER.info("Loading sets and formats..."); ConstructedFormats.ensureLists(); diff --git a/Mage.Client/src/main/java/mage/client/remote/XmageURLConnection.java b/Mage.Client/src/main/java/mage/client/remote/XmageURLConnection.java index 2c9e7443be81..fb4c0aeb44a2 100644 --- a/Mage.Client/src/main/java/mage/client/remote/XmageURLConnection.java +++ b/Mage.Client/src/main/java/mage/client/remote/XmageURLConnection.java @@ -48,6 +48,12 @@ public class XmageURLConnection { private static final AtomicLong debugLastRequestTimeMs = new AtomicLong(0); private static final ReentrantLock debugLogsWriterlock = new ReentrantLock(); + static { + // add Authority Information Access (AIA) Extension support for certificates from Windows servers like gatherer website + // fix download errors like sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target + System.setProperty("com.sun.security.enableAIAcaIssuers", "true"); + } + final String url; Proxy proxy = null; HttpURLConnection connection = null; diff --git a/Mage.Client/src/test/java/mage/client/util/DownloaderTest.java b/Mage.Client/src/test/java/mage/client/util/DownloaderTest.java index 68034c475972..a26df5a73ec8 100644 --- a/Mage.Client/src/test/java/mage/client/util/DownloaderTest.java +++ b/Mage.Client/src/test/java/mage/client/util/DownloaderTest.java @@ -60,4 +60,21 @@ public void test_DownloadFile_ByHttps() throws IOException { Assert.assertNotNull(stream); Assert.assertTrue("must have image data", image.getWidth() > 0); } + + @Test + public void test_DownloadFromWindowsServers() throws IOException { + // symbols download from gatherer website + // error example: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target + InputStream stream = XmageURLConnection.downloadBinary("https://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=BIG&size=small&rarity=C"); + Assert.assertNotNull(stream); + BufferedImage image = null; + try { + image = ImageIO.read(stream); + } catch (IOException e) { + Assert.fail("Can't download image file due error: " + e); + } + Assert.assertNotNull(stream); + Assert.assertNotNull(image); + Assert.assertTrue("must have image data", image.getWidth() > 0); + } }