From 0720038dcc8b9a7313293c5872e9fd7221b44260 Mon Sep 17 00:00:00 2001
From: Sollace <sollacea@gmail.com>
Date: Fri, 11 Nov 2022 23:41:04 +0100
Subject: [PATCH] Added SSL fix (since I'm not sure letsencryptcraft has a
 liteloader version)

---
 .../voxelmodpack/hdskins/LiteModHDSkins.java  |   8 ++
 .../hdskins/server/ValhallaSkinServer.java    |   3 +
 .../voxelmodpack/hdskins/util/SslHelper.java  | 101 ++++++++++++++++++
 .../lets-encrypt-x3-cross-signed.der          | Bin 0 -> 1174 bytes
 4 files changed, 112 insertions(+)
 create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/util/SslHelper.java
 create mode 100644 src/hdskins/resources/lets-encrypt-x3-cross-signed.der

diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java
index 5a025e68..5bb78a57 100644
--- a/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java
+++ b/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java
@@ -17,6 +17,7 @@ import com.voxelmodpack.hdskins.gui.HDSkinsConfigPanel;
 import com.voxelmodpack.hdskins.gui.RenderPlayerModel;
 import com.voxelmodpack.hdskins.server.*;
 import com.voxelmodpack.hdskins.upload.GLWindow;
+import com.voxelmodpack.hdskins.util.SslHelper;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.ScaledResolution;
@@ -46,6 +47,9 @@ public class LiteModHDSkins implements InitCompleteListener, ViewportListener, C
     @Expose
     public String lastChosenFile = "";
 
+    @Expose
+    public boolean skipLetsEncrypt = false;
+
     public LiteModHDSkins() {
         instance = this;
     }
@@ -72,6 +76,10 @@ public class LiteModHDSkins implements InitCompleteListener, ViewportListener, C
 
         IReloadableResourceManager irrm = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager();
         irrm.registerReloadListener(HDSkinManager.INSTANCE);
+
+        if (!skipLetsEncrypt) {
+            SslHelper.doStuff(HDSkinManager.logger);
+        }
     }
 
     @Override
diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/server/ValhallaSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/server/ValhallaSkinServer.java
index f5b8c319..b2ef5b6f 100644
--- a/src/hdskins/java/com/voxelmodpack/hdskins/server/ValhallaSkinServer.java
+++ b/src/hdskins/java/com/voxelmodpack/hdskins/server/ValhallaSkinServer.java
@@ -36,6 +36,9 @@ public class ValhallaSkinServer implements SkinServer {
     private transient String accessToken;
 
     public ValhallaSkinServer(String address) {
+        if (address.startsWith("http:")) {
+            address = address.replace("http:", "https:");
+        }
         this.address = address;
     }
 
diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/util/SslHelper.java b/src/hdskins/java/com/voxelmodpack/hdskins/util/SslHelper.java
new file mode 100644
index 00000000..2c090799
--- /dev/null
+++ b/src/hdskins/java/com/voxelmodpack/hdskins/util/SslHelper.java
@@ -0,0 +1,101 @@
+package com.voxelmodpack.hdskins.util;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.*;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Credit to https://github.com/Cloudhunter/LetsEncryptCraft
+ */
+public class SslHelper {
+
+    public static void addLetsEncryptCertificate() throws Exception {
+        InputStream cert = SslHelper.class.getResourceAsStream("lets-encrypt-x3-cross-signed.der");
+
+        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");
+
+        InputStream caInput = new BufferedInputStream(cert);
+        Certificate crt = cf.generateCertificate(caInput);
+
+        keyStore.setCertificateEntry("lets-encrypt-x3-cross-signed", crt);
+
+        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 doStuff(Logger mod) {
+        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.valueOf(matcher.group(2));
+        } else {
+            majorVersion = "1.7";
+            minorVersion = 110;
+            mod.info("Regex to parse Java version failed - applying LetsEncrypt anyway.");
+        }
+
+        switch (majorVersion)
+        {
+            case "1.7":
+                if (minorVersion >= 111)
+                {
+                    mod.info("LetsEncrypt is not needed as Java version is at least Java 7u111.");
+                    return;
+                }
+                break;
+            case "1.8":
+                if (minorVersion >= 101)
+                {
+                    mod.info("LetsEncrypt is not needed as Java version is at least Java 8u101.");
+                    return;
+                }
+                break;
+        }
+
+        String body = "";
+        try {
+            mod.info("Adding Let's Encrypt certificate...");
+            addLetsEncryptCertificate();
+            mod.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);
+            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
+                body = reader.readLine();
+            }
+        } catch (Exception e) {
+            mod.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()) {
+            mod.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 {
+            mod.info("Done - you are now able to access resources with a Let's Encrypt certificate :D");
+        }
+    }
+}
diff --git a/src/hdskins/resources/lets-encrypt-x3-cross-signed.der b/src/hdskins/resources/lets-encrypt-x3-cross-signed.der
new file mode 100644
index 0000000000000000000000000000000000000000..e08466c5a7cc64b2bf97e9e7e658a00543bf3211
GIT binary patch
literal 1174
zcmXqLVwq&n#9Xz2nTe5!Nq~#d(TRb9F}Srji@WvBat;GtHcqWJkGAi;jEvl@3<maw
zDh5hy%%Ln?!qP68>6s;oISRp<>3NAIrA4U<Aw{LdB?`{@dWPZ#q99ew!h9~lAqqkH
z`9NVug$QE<IdNV?GXrBob3-!|0~50-ab6=sB(8y%A-4f1NGqE#Q)sZEn1KkyHeR39
z67^yQ*SzGS%7PL@WdlWs`BEt23XY{E8Tmz-C6yq%ni!Rk-OtF%z}&>h&j1wXVrpV!
zWSDcA=R?#}J@@TJvF6R2Gm;HnT{l&eRDHO2pXtYfN&4G&cssJLUOCT{BjU|Qts@!j
z+>0NVK6&<ec~ar7%Ekow>l0_q|9qh$z3@aP-_(ic|2>=eGQq~<Ox-Epav_zu?$S}O
zcfOG`XONk*rg}N+t8-qj_c}f`o3Zos-&~t%8TXa7oF?$Jm874jUpi|?P@;&ied^1m
z_S3h2@r8YB>-^kmKfP`JhC5R4vw5eA)gIAakh*Cmi&<$y_8PCx(i1!@^cPL@*HTc`
zWI0xH;DX`VenX3?V!Kut?{NOOQU0(&{h~@kVOw3ZACLchGS1p*X?S$~kzQWe6fxsf
zzgjf6UEw}(qxSG*CT2zk#>GvHwZIUmG!Oy?sH`v}<9`+o12!PV#K>U42NL54iLn6F
zN1H)C8;3R<BP%OABO^<(L7{;WjBmi$rj}7sQedU8pIKa#u2%v|37IK+`N_ovdYLJy
zd0+v(<osL%Yq%b!Hhrj`#DaoiRAu@_z%)~=pHf@`Vk9S480!_7CmYCv9Hh)5VIbBZ
za%B0&CDl5GzivPDo>2P#h-gA<r+`5SNPz;2uYtD#2OC>@BM&1Jqk%meH_+KEj7|4}
z{$n&SFwld!fr(K}3F?Mqpc6oL=~fu(<)oGrr$UmNUVc%!fepx1c@|RxV*|ql`U`a1
zv|*Zxa?sojOz%Pd{vpne5ys9zK6=STIR>&I-Fz%!EFvqsvXWV9@9uhb(Q^AT*VOl)
zSG-w>oJ4_H446b28SWZi7yO(YVR2VN^fzbdzOt~L1s+Q?-PNlPsc=mC7$xr|q-m~F
z5-5|DvE%I2g7l}~m+bM=2s}Ic#k%&nuWsy$TF5x-&WF2MvROCm!j<POlVeGm_5V8S
zsqOOi2e>@;Oxdt4HR-{@kf)2a)+!u%`E2){6W_KTHd;L6O!<mum8tC7r#1dri3K&D
z3*ym>Z+>x=&G>hD&N+uyM)Tw+#W)@;$%&5TiZ?#vJAaME2mNZDq`5a2Ps~@9)}OFZ
z(#`f;o%FJ*_MMBXawUGLE}hse`rwn8e#8bgeVq)oW8O2)-kQ(zvwp%`XD=Zazx?7V
bjaN%n<yHICw%>hllF4Ox`})Hs(OaAVarCE7

literal 0
HcmV?d00001