001 package cpw.mods.fml.common.asm; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.InputStreamReader; 005 import java.io.ObjectInputStream.GetField; 006 import java.io.StringReader; 007 import java.net.JarURLConnection; 008 import java.nio.charset.Charset; 009 import java.security.CodeSource; 010 import java.security.cert.CertPath; 011 import java.security.cert.CertPathValidator; 012 import java.security.cert.Certificate; 013 import java.security.cert.CertificateFactory; 014 import java.security.cert.PKIXCertPathValidatorResult; 015 import java.security.cert.PKIXParameters; 016 import java.security.cert.TrustAnchor; 017 import java.security.cert.X509Certificate; 018 import java.util.Arrays; 019 import java.util.Collections; 020 import java.util.Map; 021 022 import javax.swing.JOptionPane; 023 024 import org.objectweb.asm.ClassReader; 025 import org.objectweb.asm.ClassVisitor; 026 import org.objectweb.asm.FieldVisitor; 027 import org.objectweb.asm.Opcodes; 028 029 import cpw.mods.fml.common.CertificateHelper; 030 import cpw.mods.fml.common.FMLLog; 031 import cpw.mods.fml.relauncher.IFMLCallHook; 032 import cpw.mods.fml.relauncher.RelaunchClassLoader; 033 034 public class FMLSanityChecker implements IFMLCallHook 035 { 036 private static final String FMLFINGERPRINT = "AE:F6:54:79:96:E9:1B:D1:59:70:6C:B4:6B:F5:4A:89:C5:CE:08:1D".toLowerCase().replace(":",""); 037 private static final String FORGEFINGERPRINT = "DE:4C:F8:A3:F3:BC:15:63:58:10:04:4C:39:24:0B:F9:68:04:EA:7D".toLowerCase().replace(":", ""); 038 static class MLDetectorClassVisitor extends ClassVisitor 039 { 040 private boolean foundMarker = false; 041 private MLDetectorClassVisitor() 042 { 043 super(Opcodes.ASM4); 044 } 045 046 @Override 047 public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) 048 { 049 if ("fmlMarker".equals(arg1)) 050 { 051 foundMarker = true; 052 } 053 return null; 054 } 055 } 056 057 private RelaunchClassLoader cl; 058 059 @Override 060 public Void call() throws Exception 061 { 062 CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); 063 boolean goodFML = false; 064 if (codeSource.getLocation().getProtocol().equals("jar")) 065 { 066 Certificate[] certificates = codeSource.getCertificates(); 067 if (certificates!=null) 068 { 069 070 for (Certificate cert : certificates) 071 { 072 String fingerprint = CertificateHelper.getFingerprint(cert); 073 if (fingerprint.equals(FMLFINGERPRINT)) 074 { 075 FMLLog.info("Found valid fingerprint for FML. Certificate fingerprint %s", fingerprint); 076 goodFML = true; 077 } 078 else if (fingerprint.equals(FORGEFINGERPRINT)) 079 { 080 FMLLog.info("Found valid fingerprint for Minecraft Forge. Certificate fingerprint %s", fingerprint); 081 goodFML = true; 082 } 083 else 084 { 085 FMLLog.severe("Found invalid fingerprint for FML: %s", fingerprint); 086 } 087 } 088 } 089 } 090 else 091 { 092 goodFML = true; 093 } 094 if (!goodFML) 095 { 096 FMLLog.severe("FML appears to be missing any signature data. This is not a good thing"); 097 } 098 byte[] mlClass = cl.getClassBytes("ModLoader"); 099 // Only care in obfuscated env 100 if (mlClass == null) 101 { 102 return null; 103 } 104 MLDetectorClassVisitor mlTester = new MLDetectorClassVisitor(); 105 ClassReader cr = new ClassReader(mlClass); 106 cr.accept(mlTester, ClassReader.SKIP_CODE); 107 if (!mlTester.foundMarker) 108 { 109 JOptionPane.showMessageDialog(null, "<html>CRITICAL ERROR<br/>" + 110 "ModLoader was detected in this environment<br/>" + 111 "ForgeModLoader cannot be installed alongside ModLoader<br/>" + 112 "All mods should work without ModLoader being installed<br/>" + 113 "Because ForgeModLoader is 100% compatible with ModLoader<br/>" + 114 "Re-install Minecraft Forge or Forge ModLoader into a clean<br/>" + 115 "jar and try again.", 116 "ForgeModLoader critical error", 117 JOptionPane.ERROR_MESSAGE); 118 throw new RuntimeException("Invalid ModLoader class detected"); 119 } 120 return null; 121 } 122 123 @Override 124 public void injectData(Map<String, Object> data) 125 { 126 cl = (RelaunchClassLoader) data.get("classLoader"); 127 } 128 129 }