More stuff for the thingy

This commit is contained in:
Christian committed 2012-12-15 22:30:16 -05:00
1 parent 16651d6994
commit d811fea82c
4 files changed
+202 -45

No files matched your search

@@ -0,0 +1,52 @@
package cpw.mods.fml.common;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.cert.Certificate;
public class CertificateHelper {
private static final String HEXES = "0123456789abcdef";
public static String getFingerprint(Certificate certificate)
{
try
{
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] der = certificate.getEncoded();
md.update(der);
byte[] digest = md.digest();
return hexify(digest);
}
catch (Exception e)
{
return null;
}
}
public static String getFingerprint(ByteBuffer buffer)
{
try
{
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(buffer);
byte[] chksum = digest.digest();
return hexify(chksum);
}
catch (Exception e)
{
return null;
}
}
private static String hexify(byte[] chksum)
{
final StringBuilder hex = new StringBuilder( 2 * chksum.length );
for ( final byte b : chksum ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
}
@@ -1,5 +1,9 @@
package cpw.mods.fml.common.asm;
import java.io.ObjectInputStream.GetField;
import java.net.JarURLConnection;
import java.security.CodeSource;
import java.security.cert.Certificate;
import java.util.Map;
import javax.swing.JOptionPane;
@@ -9,11 +13,14 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import cpw.mods.fml.common.CertificateHelper;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.RelaunchClassLoader;
public class FMLSanityChecker implements IFMLCallHook
{
private static final String FMLFINGERPRINT = "";
static class MLDetectorClassVisitor extends ClassVisitor
{
private boolean foundMarker = false;
@@ -38,6 +45,29 @@ public class FMLSanityChecker implements IFMLCallHook
@Override
public Void call() throws Exception
{
CodeSource codeSource = getClass().getProtectionDomain().getCodeSource();
boolean goodFML = false;
if (codeSource.getLocation().getProtocol().equals("jar"))
{
Certificate[] certificates = codeSource.getCertificates();
if (certificates!=null && certificates.length>0)
{
Certificate certificate = certificates[0];
String fingerprint = CertificateHelper.getFingerprint(certificate);
if (fingerprint.equals(FMLFINGERPRINT))
{
goodFML = true;
}
}
}
else
{
goodFML = true;
}
if (!goodFML)
{
FMLLog.severe("FML appears to be missing it's signature data. This is not a good thing");
}
byte[] mlClass = cl.getClassBytes("ModLoader");
// Only care in obfuscated env
if (mlClass == null)
@@ -3,8 +3,12 @@ package cpw.mods.fml.relauncher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -13,8 +17,15 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes.Name;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import cpw.mods.fml.common.FMLLog;
public class RelaunchClassLoader extends URLClassLoader
{
private List<URL> sources;
@@ -26,6 +37,9 @@ public class RelaunchClassLoader extends URLClassLoader
private Set<String> classLoaderExceptions = new HashSet<String>();
private Set<String> transformerExceptions = new HashSet<String>();
private Map<Package,Manifest> packageManifests = new HashMap<Package,Manifest>();
private static Manifest EMPTY = new Manifest();
public RelaunchClassLoader(URL[] sources)
{
@@ -41,6 +55,7 @@ public class RelaunchClassLoader extends URLClassLoader
// standard classloader exclusions
addClassLoaderExclusion("java.");
addClassLoaderExclusion("sun.");
addClassLoaderExclusion("org.lwjgl.");
addClassLoaderExclusion("cpw.mods.fml.relauncher.");
addClassLoaderExclusion("net.minecraftforge.classloading.");
@@ -103,18 +118,58 @@ public class RelaunchClassLoader extends URLClassLoader
try
{
CodeSigner[] signers = null;
int lastDot = name.lastIndexOf('.');
if (lastDot > -1)
String pkgname = name.substring(0, lastDot);
String fName = name.replace('.', '/').concat(".class");
String pkgPath = pkgname.replace('.', '/');
URLConnection urlConnection = findCodeSourceConnectionFor(fName);
if (urlConnection instanceof JarURLConnection && lastDot > -1)
{
String pkgname = name.substring(0, lastDot);
if (getPackage(pkgname)==null)
JarURLConnection jarUrlConn = (JarURLConnection)urlConnection;
JarFile jf = jarUrlConn.getJarFile();
if (jf != null && jf.getManifest() != null)
{
definePackage(pkgname, null, null, null, null, null, null, null);
Manifest mf = jf.getManifest();
JarEntry ent = jf.getJarEntry(fName);
Package pkg = getPackage(pkgname);
if (pkg == null)
{
pkg = definePackage(pkgname, mf, jarUrlConn.getJarFileURL());
packageManifests.put(pkg, mf);
// need to read the bytes to force the signing to be checked
getClassBytes(name);
signers = ent.getCodeSigners();
}
else
{
if (pkg.isSealed() && !pkg.isSealed(jarUrlConn.getJarFileURL()))
{
FMLLog.severe("The jar file %s is trying to seal already secured path %s", jf.getName(), pkgname);
}
else if (isSealed(pkgname, mf))
{
FMLLog.severe("The jar file %s has a security seal for path %s, but that path is defined and not secure", jf.getName(), pkgname);
}
}
}
}
else if (lastDot > -1)
{
Package pkg = getPackage(pkgname);
if (pkg == null)
{
pkg = definePackage(pkgname, null, null, null, null, null, null, null);
packageManifests.put(pkg, EMPTY);
}
else if (pkg.isSealed())
{
FMLLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname);
}
}
byte[] basicClass = getClassBytes(name);
byte[] transformedClass = runTransformers(name, basicClass);
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length);
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers));
cachedClasses.put(name, cl);
return cl;
}
@@ -125,33 +180,39 @@ public class RelaunchClassLoader extends URLClassLoader
}
}
public byte[] getClassBytes(String name) throws IOException
private boolean isSealed(String path, Manifest man)
{
InputStream classStream = null;
try
{
URL classResource = findResource(name.replace('.', '/').concat(".class"));
if (classResource == null)
{
return null;
}
classStream = classResource.openStream();
return readFully(classStream);
Attributes attr = man.getAttributes(path);
String sealed = null;
if (attr != null) {
sealed = attr.getValue(Name.SEALED);
}
finally
{
if (classStream != null)
{
try
{
classStream.close();
}
catch (IOException e)
{
// Swallow the close exception
}
if (sealed == null) {
if ((attr = man.getMainAttributes()) != null) {
sealed = attr.getValue(Name.SEALED);
}
}
return "true".equalsIgnoreCase(sealed);
}
private URLConnection findCodeSourceConnectionFor(String name)
{
URL res = findResource(name);
if (res != null)
{
try
{
return res.openConnection();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
else
{
return null;
}
}
private byte[] runTransformers(String name, byte[] basicClass)
@@ -210,4 +271,33 @@ public class RelaunchClassLoader extends URLClassLoader
{
transformerExceptions.add(toExclude);
}
public byte[] getClassBytes(String name) throws IOException
{
InputStream classStream = null;
try
{
URL classResource = findResource(name.replace('.', '/').concat(".class"));
if (classResource == null)
{
return null;
}
classStream = classResource.openStream();
return readFully(classStream);
}
finally
{
if (classStream != null)
{
try
{
classStream.close();
}
catch (IOException e)
{
// Swallow the close exception
}
}
}
}
}
@@ -25,6 +25,7 @@ import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.logging.Level;
import cpw.mods.fml.common.CertificateHelper;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
public class RelaunchLibraryManager
@@ -488,7 +489,6 @@ public class RelaunchLibraryManager
return loadedLibraries;
}
private static final String HEXES = "0123456789abcdef";
private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 22);
static IDownloadDisplay downloadMonitor;
@@ -560,21 +560,6 @@ public class RelaunchLibraryManager
private static String generateChecksum(ByteBuffer buffer)
{
try
{
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(buffer);
byte[] chksum = digest.digest();
final StringBuilder hex = new StringBuilder( 2 * chksum.length );
for ( final byte b : chksum ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
catch (Exception e)
{
return null;
}
return CertificateHelper.getFingerprint(buffer);
}
}