001/* 002 * Forge Mod Loader 003 * Copyright (c) 2012-2013 cpw. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser Public License v2.1 006 * which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 008 * 009 * Contributors: 010 * cpw - implementation 011 */ 012 013package cpw.mods.fml.common.asm; 014 015import java.io.ByteArrayInputStream; 016import java.io.File; 017import java.io.InputStreamReader; 018import java.io.ObjectInputStream.GetField; 019import java.io.StringReader; 020import java.net.JarURLConnection; 021import java.nio.charset.Charset; 022import java.security.CodeSource; 023import java.security.cert.CertPath; 024import java.security.cert.CertPathValidator; 025import java.security.cert.Certificate; 026import java.security.cert.CertificateFactory; 027import java.security.cert.PKIXCertPathValidatorResult; 028import java.security.cert.PKIXParameters; 029import java.security.cert.TrustAnchor; 030import java.security.cert.X509Certificate; 031import java.util.Arrays; 032import java.util.Collections; 033import java.util.Map; 034 035import javax.swing.JOptionPane; 036 037import org.objectweb.asm.ClassReader; 038import org.objectweb.asm.ClassVisitor; 039import org.objectweb.asm.FieldVisitor; 040import org.objectweb.asm.Opcodes; 041 042import cpw.mods.fml.common.CertificateHelper; 043import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; 044import cpw.mods.fml.relauncher.FMLRelaunchLog; 045import cpw.mods.fml.relauncher.IFMLCallHook; 046import cpw.mods.fml.relauncher.RelaunchClassLoader; 047 048public class FMLSanityChecker implements IFMLCallHook 049{ 050 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(":",""); 051 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(":", ""); 052 static class MLDetectorClassVisitor extends ClassVisitor 053 { 054 private boolean foundMarker = false; 055 private MLDetectorClassVisitor() 056 { 057 super(Opcodes.ASM4); 058 } 059 060 @Override 061 public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) 062 { 063 if ("fmlMarker".equals(arg1)) 064 { 065 foundMarker = true; 066 } 067 return null; 068 } 069 } 070 071 private RelaunchClassLoader cl; 072 073 @Override 074 public Void call() throws Exception 075 { 076 CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); 077 boolean goodFML = false; 078 if (codeSource.getLocation().getProtocol().equals("jar")) 079 { 080 Certificate[] certificates = codeSource.getCertificates(); 081 if (certificates!=null) 082 { 083 084 for (Certificate cert : certificates) 085 { 086 String fingerprint = CertificateHelper.getFingerprint(cert); 087 if (fingerprint.equals(FMLFINGERPRINT)) 088 { 089 FMLRelaunchLog.info("Found valid fingerprint for FML. Certificate fingerprint %s", fingerprint); 090 goodFML = true; 091 } 092 else if (fingerprint.equals(FORGEFINGERPRINT)) 093 { 094 FMLRelaunchLog.info("Found valid fingerprint for Minecraft Forge. Certificate fingerprint %s", fingerprint); 095 goodFML = true; 096 } 097 else 098 { 099 FMLRelaunchLog.severe("Found invalid fingerprint for FML: %s", fingerprint); 100 } 101 } 102 } 103 } 104 else 105 { 106 goodFML = true; 107 } 108 if (!goodFML) 109 { 110 FMLRelaunchLog.severe("FML appears to be missing any signature data. This is not a good thing"); 111 } 112 byte[] mlClass = cl.getClassBytes("ModLoader"); 113 // Only care in obfuscated env 114 if (mlClass == null) 115 { 116 return null; 117 } 118 MLDetectorClassVisitor mlTester = new MLDetectorClassVisitor(); 119 ClassReader cr = new ClassReader(mlClass); 120 cr.accept(mlTester, ClassReader.SKIP_CODE); 121 if (!mlTester.foundMarker) 122 { 123 JOptionPane.showMessageDialog(null, "<html>CRITICAL ERROR<br/>" + 124 "ModLoader was detected in this environment<br/>" + 125 "ForgeModLoader cannot be installed alongside ModLoader<br/>" + 126 "All mods should work without ModLoader being installed<br/>" + 127 "Because ForgeModLoader is 100% compatible with ModLoader<br/>" + 128 "Re-install Minecraft Forge or Forge ModLoader into a clean<br/>" + 129 "jar and try again.", 130 "ForgeModLoader critical error", 131 JOptionPane.ERROR_MESSAGE); 132 throw new RuntimeException("Invalid ModLoader class detected"); 133 } 134 return null; 135 } 136 137 @Override 138 public void injectData(Map<String, Object> data) 139 { 140 cl = (RelaunchClassLoader) data.get("classLoader"); 141 FMLDeobfuscatingRemapper.INSTANCE.setup((File)data.get("mcLocation"), cl, (String) data.get("deobfuscationFileName")); 142 } 143 144}