diff options
Diffstat (limited to 'src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java')
-rw-r--r-- | src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java b/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java index f4e64f6..86deda9 100644 --- a/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java +++ b/src/main/java/de/cowtipper/cowlection/config/CredentialStorage.java @@ -4,8 +4,23 @@ import de.cowtipper.cowlection.Cowlection; import de.cowtipper.cowlection.util.ApiUtils; import de.cowtipper.cowlection.util.Utils; import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; +import org.apache.http.conn.ssl.SSLContexts; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Key and secret holder in its own file to avoid people leaking their keys accidentally. @@ -13,6 +28,7 @@ import net.minecraftforge.common.config.Property; public class CredentialStorage { public static String moo; public static boolean isMooValid; + public static SSLContext sslContext; private Property propMoo; private Property propIsMooValid; private final Configuration cfg; @@ -20,17 +36,18 @@ public class CredentialStorage { public CredentialStorage(Configuration configuration) { cfg = configuration; initConfig(); + verifyNewerHttpsSupport(); } private void initConfig() { cfg.load(); propMoo = cfg.get(Configuration.CATEGORY_CLIENT, - "moo", "", "Don't share this with anybody! Do not edit this entry manually either!", Utils.VALID_UUID_PATTERN) + "moo", "", "Don't share this with anybody! Do not edit this entry manually either!", Utils.VALID_UUID_PATTERN) .setShowInGui(false); propMoo.setLanguageKey(Cowlection.MODID + ".config." + propMoo.getName()); propIsMooValid = cfg.get(Configuration.CATEGORY_CLIENT, - "isMooValid", false, "Is the value valid?") + "isMooValid", false, "Is the value valid?") .setShowInGui(false); moo = propMoo.getString(); isMooValid = propIsMooValid.getBoolean(); @@ -39,6 +56,81 @@ public class CredentialStorage { } } + private void verifyNewerHttpsSupport() { + String javaVersion = System.getProperty("java.version", "unknown java version"); + Pattern javaVersionPattern = Pattern.compile("1\\.8\\.0_(\\d+)"); // e.g. 1.8.0_51 + Matcher javaVersionMatcher = javaVersionPattern.matcher(javaVersion); + if (!javaVersionMatcher.matches() + || MathHelper.parseIntWithDefault(javaVersionMatcher.group(1), 1337) >= 101) { + // newer Java version (>=8u101): *should* already have support by default + return; + } + + // running Java <8u101 + if (testNewHttps()) { + // uhm... looks like someone added the certs to the default JKS already + return; + } + System.out.println("Injecting Let's Encrypt support due to ancient Java version..."); + try { + KeyStore originalKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + originalKeyStore.load(Files.newInputStream(Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts")), "changeit".toCharArray()); + + KeyStore mooKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + mooKeyStore.load(getClass().getResourceAsStream("/https-for-ancient-java.jks"), "mooveit".toCharArray()); + + KeyStore tempKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + tempKeyStore.load(null, "moovedit".toCharArray()); + + for (Enumeration<String> aliases = originalKeyStore.aliases(); aliases.hasMoreElements(); ) { + String alias = aliases.nextElement(); + tempKeyStore.setCertificateEntry(alias, originalKeyStore.getCertificate(alias)); + } + for (Enumeration<String> aliases = mooKeyStore.aliases(); aliases.hasMoreElements(); ) { + String alias = aliases.nextElement(); + tempKeyStore.setCertificateEntry(alias, mooKeyStore.getCertificate(alias)); + } + sslContext = SSLContexts.custom() + .loadKeyMaterial(tempKeyStore, "moovedit".toCharArray()) + .loadTrustMaterial(tempKeyStore, null) + .build(); + + if (!testNewHttps()) { + System.err.println("Error while trying to add Let's Encrypt support: Could not contact site after running setup"); + } + } catch (GeneralSecurityException | IOException e) { + System.err.println("Error while trying to add Let's Encrypt support:"); + e.printStackTrace(); + } + } + + /** + * Tests accessing a site that uses Let's Encrypt + * + * @return true, if connection was successful + */ + private boolean testNewHttps() { + try { + URLConnection connection = new URL("https://helloworld.letsencrypt.org/").openConnection(); + connection.setConnectTimeout(5000); + connection.setReadTimeout(8000); + connection.setDoInput(false); + connection.setDoOutput(false); + connection.addRequestProperty("User-Agent", "Forge Mod " + Cowlection.MODNAME + "/" + Cowlection.VERSION + " (" + Cowlection.GITURL + ")"); + if (CredentialStorage.sslContext != null && connection instanceof HttpsURLConnection) { + ((HttpsURLConnection) connection).setSSLSocketFactory(CredentialStorage.sslContext.getSocketFactory()); + } + + connection.connect(); + + // seems to be working since there was no IOException! + return true; + } catch (IOException ignored) { + // most likely a newer https related issue, so setup might fix things + } + return false; + } + public void setMooIfValid(String moo, boolean commandTriggered) { ApiUtils.fetchApiKeyInfo(moo, hyApiKey -> { if (hyApiKey != null && hyApiKey.isSuccess()) { |