diff --git a/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java b/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java index 87d330b..2dadf9d 100644 --- a/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java +++ b/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; +import org.ultramine.server.UltramineSecurityManager; import com.google.common.base.Throwables; import com.google.common.collect.Lists; @@ -32,7 +33,8 @@ System.setProperty("java.net.preferIPv4Stack", "true"); //Lets do this as early as possible. Vanilla does it in Main.main try { - System.setSecurityManager(new FMLSecurityManager()); + FMLSecurityManager mgr = (FMLSecurityManager)(this instanceof FMLServerTweaker ? new UltramineSecurityManager() : new FMLSecurityManager()); + System.setSecurityManager(mgr); } catch (SecurityException se) { diff --git a/src/main/java/cpw/mods/fml/relauncher/FMLSecurityManager.java b/src/main/java/cpw/mods/fml/relauncher/FMLSecurityManager.java index 8fac41a..a6f1d20 100644 --- a/src/main/java/cpw/mods/fml/relauncher/FMLSecurityManager.java +++ b/src/main/java/cpw/mods/fml/relauncher/FMLSecurityManager.java @@ -10,6 +10,13 @@ * */ public class FMLSecurityManager extends SecurityManager { + private final boolean um; + + public FMLSecurityManager(){this(false);} + public FMLSecurityManager(boolean um) + { + this.um = um; + } @Override public void checkPermission(Permission perm) { @@ -17,8 +24,8 @@ if (permName.startsWith("exitVM")) { Class[] classContexts = getClassContext(); - String callingClass = classContexts.length > 3 ? classContexts[4].getName() : "none"; - String callingParent = classContexts.length > 4 ? classContexts[5].getName() : "none"; + String callingClass = classContexts.length > (um ? 4 : 3) ? classContexts[(um ? 5 : 4)].getName() : "none"; + String callingParent = classContexts.length > (um ? 5 : 4) ? classContexts[(um ? 6 : 5)].getName() : "none"; // FML is allowed to call system exit and the Minecraft applet (from the quit button) if (!(callingClass.startsWith("cpw.mods.fml.") || ( "net.minecraft.client.Minecraft".equals(callingClass) && "net.minecraft.client.Minecraft".equals(callingParent)) || ("net.minecraft.server.dedicated.DedicatedServer".equals(callingClass) && "net.minecraft.server.MinecraftServer".equals(callingParent)))) { diff --git a/src/main/java/org/ultramine/server/UltramineSecurityManager.java b/src/main/java/org/ultramine/server/UltramineSecurityManager.java new file mode 100644 index 0000000..4a2adc9 --- /dev/null +++ b/src/main/java/org/ultramine/server/UltramineSecurityManager.java @@ -0,0 +1,48 @@ +package org.ultramine.server; + +import java.io.File; +import java.io.FilePermission; +import java.io.IOException; +import java.security.Permission; + +import cpw.mods.fml.relauncher.FMLSecurityManager; + +public class UltramineSecurityManager extends FMLSecurityManager +{ + private static final boolean PREVENT_FILESYSTEM_ACCESS = !Boolean.parseBoolean(System.getProperty("org.ultramine.security.allow_out_of_dir_access")); + private static final String JAVA_HOME = System.getProperty("java.home"); + private final String dir; + + public UltramineSecurityManager() + { + super(true); + try + { + dir = new File(".").getCanonicalFile().getParentFile().getPath(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + @Override + public void checkPermission(Permission perm) + { + super.checkPermission(perm); + if(PREVENT_FILESYSTEM_ACCESS && perm instanceof FilePermission) + { + String name = perm.getName(); + try + { + String path = new File(name).getCanonicalFile().getParentFile().getPath(); + if(!path.startsWith(dir) && !path.startsWith("/dev") && !path.startsWith(JAVA_HOME)) + throw new SecurityException("Illegal out-of-dir filesystem access: "+path); + } + catch(IOException e) + { + throw new RuntimeException("Failed to resolve canonical path for: "+name, e); + } + } + } +}