mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
More stuff for the thingy
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user