diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java index 5327c619cf..0c3d1a45c6 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java @@ -49,7 +49,7 @@ public abstract class FMLCommonLaunchHandler // standard libs "joptsimple.", "org.lwjgl.", "com.mojang.guava.", "com.google.", "org.apache.commons.", "io.netty.", "org.apache.logging.log4j.", "org.apache.http.", "org.apache.maven.", "org.objectweb.asm.", - "paulscode.sound.", "com.ibm.icu.", "sun.", "gnu.trove.", "com.electronwill.nightconfig.", + "paulscode.sound.", "com.ibm.icu.", "sun.", "javax.", "gnu.trove.", "com.electronwill.nightconfig.", "net.minecraftforge.fml.loading.", "net.minecraftforge.fml.language.", "net.minecraftforge.eventbus.", "net.minecraftforge.api.", "com.mojang.util.QueueLogAppender" ); diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java index 4197d3db2b..7c4f216ee5 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -113,6 +113,8 @@ public class FMLLoader coreModProvider = coreModProviders.get(0); final Package coremodPackage = coreModProvider.getClass().getPackage(); LOGGER.debug(CORE,"FML found CoreMod version : {}", coremodPackage.getImplementationVersion()); + + FixSSL.fixup(); } static void setupLaunchHandler(final IEnvironment environment, final Map arguments) diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FixSSL.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/FixSSL.java new file mode 100644 index 0000000000..6739f18e53 --- /dev/null +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/FixSSL.java @@ -0,0 +1,91 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.loading; + +import org.apache.logging.log4j.LogManager; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + +import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowBiConsumer; +import static cpw.mods.modlauncher.api.LamdbaExceptionUtils.rethrowFunction; +import static net.minecraftforge.fml.loading.LogMarkers.CORE; + + +/** + * This class fixes older Java SSL setups which don't contain the correct root certificates to trust Let's Encrypt + * https endpoints. + * + * It uses a secondary JKS keystore: lekeystore.jks, which contains the two root certificate keys as documented here: + * https://letsencrypt.org/certificates/ + * + * To create the keystore, the following commands were run: + *
+ *     keytool -import -alias letsencryptisrgx1 -file isrgrootx1.pem -keystore lekeystore.jks -storetype jks -storepass supersecretpassword -v
+ *     keytool -import -alias identrustx3 -file identrustx3.pem -keystore lekeystore.jks -storetype jks -storepass supersecretpassword -v
+ * 
+ * + * The PEM files were obtained from the above URL. + */ +class FixSSL { + static void fixup() { + try { + final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + Path ksPath = Paths.get(System.getProperty("java.home"),"lib", "security", "cacerts"); + keyStore.load(Files.newInputStream(ksPath), "changeit".toCharArray()); + final Map jdkTrustStore = Collections.list(keyStore.aliases()).stream().collect(Collectors.toMap(a -> a, rethrowFunction(keyStore::getCertificate))); + + final KeyStore leKS = KeyStore.getInstance(KeyStore.getDefaultType()); + final InputStream leKSFile = FixSSL.class.getResourceAsStream("/lekeystore.jks"); + leKS.load(leKSFile, "supersecretpassword".toCharArray()); + final Map leTrustStore = Collections.list(leKS.aliases()).stream().collect(Collectors.toMap(a -> a, rethrowFunction(leKS::getCertificate))); + + final KeyStore mergedTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + mergedTrustStore.load(null, new char[0]); + jdkTrustStore.forEach(rethrowBiConsumer(mergedTrustStore::setCertificateEntry)); + leTrustStore.forEach(rethrowBiConsumer(mergedTrustStore::setCertificateEntry)); + + final TrustManagerFactory instance = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + instance.init(mergedTrustStore); + final SSLContext tls = SSLContext.getInstance("TLS"); + tls.init(null, instance.getTrustManagers(), null); + HttpsURLConnection.setDefaultSSLSocketFactory(tls.getSocketFactory()); + LogManager.getLogger().info(CORE, "Added Lets Encrypt root certificates as additional trust"); + } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) { + LogManager.getLogger().fatal(CORE,"Failed to load lets encrypt certificate. Expect problems", e); + } + + } +} diff --git a/src/fmllauncher/resources/lekeystore.jks b/src/fmllauncher/resources/lekeystore.jks new file mode 100644 index 0000000000..b8a56b6a00 Binary files /dev/null and b/src/fmllauncher/resources/lekeystore.jks differ diff --git a/src/main/java/net/minecraftforge/fml/VersionChecker.java b/src/main/java/net/minecraftforge/fml/VersionChecker.java index 7b66b75890..96f351a87f 100644 --- a/src/main/java/net/minecraftforge/fml/VersionChecker.java +++ b/src/main/java/net/minecraftforge/fml/VersionChecker.java @@ -271,7 +271,7 @@ public class VersionChecker } catch (Exception e) { - LOGGER.debug("Failed to process update information", e); + LOGGER.warn("Failed to process update information", e); status = FAILED; } results.put(mod, new CheckResult(status, target, changes, display_url));