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    }