From 494e14233a3208c7f5faaf4bffacefded0dd2686 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 20 Nov 2023 15:50:36 +0000 Subject: [PATCH] Integrate LetsEncryptAdder to fix https downloads in Curse (#757) * Integrate LetsEncryptAdder to fix https downloads in Curse * Switch to ISRG roots * binary for certificates --------- Co-authored-by: bombcar --- .gitattributes | 1 + .../com/dreammaster/coremod/DepLoader.java | 6 + .../dreammaster/coremod/LetsEncryptAdder.java | 145 ++++++++++++++++++ .../assets/letsencryptroot/isrg-root-x1.der | Bin 0 -> 1391 bytes .../assets/letsencryptroot/isrg-root-x2.der | Bin 0 -> 543 bytes 5 files changed, 152 insertions(+) create mode 100644 src/main/java/com/dreammaster/coremod/LetsEncryptAdder.java create mode 100644 src/main/resources/assets/letsencryptroot/isrg-root-x1.der create mode 100644 src/main/resources/assets/letsencryptroot/isrg-root-x2.der diff --git a/.gitattributes b/.gitattributes index fd2792b6c..067247605 100644 --- a/.gitattributes +++ b/.gitattributes @@ -42,3 +42,4 @@ *.[pP][sS]1 text eol=crlf *[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary +*.der binary diff --git a/src/main/java/com/dreammaster/coremod/DepLoader.java b/src/main/java/com/dreammaster/coremod/DepLoader.java index af4735c2b..c7dea0317 100644 --- a/src/main/java/com/dreammaster/coremod/DepLoader.java +++ b/src/main/java/com/dreammaster/coremod/DepLoader.java @@ -148,6 +148,12 @@ public void windowClosing(WindowEvent e) { for (Dependency d : deps) if (!d.isDisabled() && !d.isFound()) count++; if (count > 0) { LOGGER.info("{} dependencies to download.", count); + try { + LetsEncryptAdder.addLetsEncryptCertificates(); + } catch (Exception e) { + LOGGER.warn( + "Could not ensure Let's Encrypt root certificates are present, downloads might fail on older Java versions."); + } downloaded = true; dialog.setJobCount(count); SwingUtilities.invokeLater(() -> dialog.setVisible(true)); diff --git a/src/main/java/com/dreammaster/coremod/LetsEncryptAdder.java b/src/main/java/com/dreammaster/coremod/LetsEncryptAdder.java new file mode 100644 index 000000000..8c4fcbff6 --- /dev/null +++ b/src/main/java/com/dreammaster/coremod/LetsEncryptAdder.java @@ -0,0 +1,145 @@ +package com.dreammaster.coremod; + +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.cert.CertificateFactory; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * Adds the Let's encrypt X3 root SSL certificate to fix HTTPS connection problems.
+ * + * Taken from: LetsEncryptCraft + *
+ * Original code license: + * + *
+ * MIT License
+ *
+ * Copyright (c) 2018 Cloudhunter
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ */ +public class LetsEncryptAdder { + + private static boolean alreadyAdded = false; + private static final Logger LOGGER = LogManager.getLogger(LetsEncryptAdder.class); + + private static void trustLetsEncryptRoots() throws Exception { + final InputStream cert1 = Objects.requireNonNull( + LetsEncryptAdder.class.getResourceAsStream("/assets/letsencryptroot/isrg-root-x1.der"), + "Embedded let's encrypt certificate X1 not found"); + final InputStream cert2 = Objects.requireNonNull( + LetsEncryptAdder.class.getResourceAsStream("/assets/letsencryptroot/isrg-root-x2.der"), + "Embedded let's encrypt certificate X2 not found"); + + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + Path ksPath = Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts"); + keyStore.load(Files.newInputStream(ksPath), "changeit".toCharArray()); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + keyStore.setCertificateEntry("isrg-root-x1", cf.generateCertificate(new BufferedInputStream(cert1))); + keyStore.setCertificateEntry("isrg-root-x2", cf.generateCertificate(new BufferedInputStream(cert2))); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(keyStore); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, tmf.getTrustManagers(), null); + SSLContext.setDefault(sslContext); + } + + public static void addLetsEncryptCertificates() { + if (alreadyAdded) { + return; + } + + String version = System.getProperty("java.version"); + Pattern p = Pattern.compile("^(\\d+\\.\\d+).*?_(\\d+).*"); + Matcher matcher = p.matcher(version); + String majorVersion; + int minorVersion; + if (matcher.matches()) { + majorVersion = matcher.group(1); + minorVersion = Integer.parseInt(matcher.group(2)); + } else { + majorVersion = "1.7"; + minorVersion = 110; + LOGGER.info("Regex to parse Java version failed - applying anyway."); + } + + switch (majorVersion) { + case "1.7": + if (minorVersion >= 111) { + LOGGER.info("Not running as Java version is at least Java 7u111."); + alreadyAdded = true; + return; + } + break; + case "1.8": + if (minorVersion >= 101) { + LOGGER.info("Not running as Java version is at least Java 8u101."); + alreadyAdded = true; + return; + } + break; + } + + String body = ""; + try { + LOGGER.info("Adding Let's Encrypt certificate..."); + LetsEncryptAdder.trustLetsEncryptRoots(); + LOGGER.info("Done, attempting to connect to https://helloworld.letsencrypt.org..."); + URL url = new URL("https://helloworld.letsencrypt.org"); + URLConnection conn = url.openConnection(); + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + InputStream inputStream = conn.getInputStream(); + body = IOUtils.toString(inputStream); + } catch (Exception e) { + LOGGER.error( + "An error occurred whilst adding the Let's Encrypt root certificate. I'm afraid you wont be able to access resources with a Let's Encrypt certificate D:", + e); + } + + if (body.isEmpty()) { + LOGGER.error( + "An unknown error occurred whilst adding the Let's Encrypt root certificate. I'm afraid you may not be able to access resources with a Let's Encrypt certificate D:"); + } else { + LOGGER.info("Done - you are now able to access resources with a Let's Encrypt certificate :D"); + } + alreadyAdded = true; + } +} diff --git a/src/main/resources/assets/letsencryptroot/isrg-root-x1.der b/src/main/resources/assets/letsencryptroot/isrg-root-x1.der new file mode 100644 index 0000000000000000000000000000000000000000..9d2132e7f1e352fabac7eafb231488b5da91ffb2 GIT binary patch literal 1391 zcmXqLV$C*aVh&!w%*4pVB*@StaDKxjhsTjF$q#lXH+3@@@Un4gwRyCC=VfH%W@Rw& zH{>?pWMd9xVH0Kw4K~y?PzQ0igcUsVN>YpRQcDzqQMi96N{2F6x@sQ zOA8D|4TM2TnT2^ggM-`^g7WiA6e0`_)UeSUJ_S;M+V-u>HW)=goaf7yL{%}fvF;1?F_{JHX*^)7mb z_cWAjyQP1@qPLp4KvBB%lYz~z{&jb6C9i%h=6|S9(7WzD_ly5q%k{o&s`h%|Bc#ex z(95j3;9;=J8{wPpB=-w!_Uf_kT$~tqZ%sS8l;RAn=gy-c5l%vESRjulRoaDHHpQelw1#&mWmj<25Ut_nWV1qwMTG%s)L@ zZ#3Rz-J*5P@#PxEvZ-ABH|}5EDDklY(M=kbokat@+bL(=ez`Qo=d9_8$g;*;h-`WLMh;lRc_g>Iv-DFqo zCF5PpD)i^rs|NwXHO`YuHlHea-Y3t;=GdnK4#`;nE(6$dNYTB&bR(NQ2+$oz?wqHJLsjX!HYm3h*_fBZ@a%uek ze*2NA(-ox)>ah}I#svAgPldH?sMd^L9VXJTe#U|j5E;9$T9Os}&1 zjEw(TSb({M&43@o7Y6ZJ4VZzHfhFz=l^iUlGsD^9O_ z?o;@C)1`#9mMgeli7SS+ehlD?e0}ag-X~KPhVT7{&D4o6YKug*3J5*#Pa(8&H7gpwUsuC^Ywq~GKr43@rUtb$j%*V zXSzC!JAHIpY?|)Bn-;WsJ~s2)HigcR z-KW{sqcnToqipMNtEK|qJDkTmPjj*R=DdjQJNf?H>f^h&YWulf^SYpR=4sI>j;y6q zAB!&hzU1vmo%p4{|F6+t(%W~vdiUeP>Iq_(+2h=TYs}f5dM+QCHs|Whty&MJN;P<_ z^RZ+cWl3o${YKsGG(t*4WP8`@Gk9!gJ;MzXRq} z=D1zmBD#56Ufpb-X;wRebnUN2Km5&csO6u^ip8C`)?_`D(Av1dIWhXO{2lAwvQN4% zdQ0z%8|T;t|E@mm82|syq6>)@52x)|6WeWmz4WT_ftiBq<~klMDs9=va+>1r8-Ysu9sFU+jzdgu+i;Y98&EuRc3p2BUzah5) zCmVAp3!5-gXt1HCfjWr8C9L3?SCU$kms+9_oSIx(lvz@#5R_V+npl*aq2OMWUs_-& zY9I_!$}G&|864!U5R{)^q7Y$ZAScdiWME)vU}69UQR2KnmZhP&p&5uDMSTm)30&A6SaOKU4F2Dcb zm*X4DJEf;G*m>k%Ep{?+FyI4*fGj^F<9`+wU|6#m@PqimAU>-BGmtWn1qtx6h_Q&& zI89r3&)dWL*Q6iwdd}x|uPid3iX0Qn84L!gOa|4Jer^FRhg{m-q+JXCN6ftUORkyhaa