package co.forsaken.projectindigo.security; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.security.Permission; import java.security.Policy; import java.util.ArrayList; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.SwingWorker; import co.forsaken.projectindigo.IndigoLauncher; import co.forsaken.projectindigo.utils.DirectoryLocations; import co.forsaken.projectindigo.utils.FileUtils; public class PolicyManager { private ArrayList<String> additionalPerms = new ArrayList<String>(); private String policyLocation = ""; private Logger logger = Logger.getLogger("launcher"); public boolean copySecurityPolicy() { InputStream policy = IndigoLauncher.class.getResourceAsStream("/co/forsaken/projectindigo/resources/security/security.policy"); File newPolicyFile = new File(DirectoryLocations.BACKEND_DATA_DIR.format("security.policy")); policyLocation = newPolicyFile.getAbsolutePath(); logger.log(Level.INFO, "Copying over new security policy."); FileUtils.writeStreamToFile(policy, new File(policyLocation)); return true; } public void addAdditionalPerm(String perm) { additionalPerms.add("\ngrant{" + perm + ";};"); } public void writeAdditionalPerms(String location) { try { FileWriter out = new FileWriter(location, true); out.write("\n//AUTO-GENERATED PERMS BEGIN\n"); for (String perm : additionalPerms) { logger.log(Level.INFO, "Writing additional perm " + perm.replaceAll("\n", "")); out.write(perm); } out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } public String getPolicyLocation() { return policyLocation; } public void enforceSecurityManager(String basepath, String nativesDir) { copySecurityPolicy(); addAdditionalPerm("permission java.lang.RuntimePermission \"*\""); addAdditionalPerm("permission java.io.FilePermission \"" + new File(basepath).getParentFile().getAbsolutePath().replaceAll("\\\\", "/") + "/-\", \"read, write, delete\""); addAdditionalPerm("permission java.io.FilePermission \"" + nativesDir.replaceAll("\\\\", "/") + "/-\", \"read\""); addAdditionalPerm("permission java.io.FilePermission \"" + System.getProperty("java.io.tmpdir").replaceAll("\\\\", "/") + "-\", \"read, write, delete\""); addAdditionalPerm("permission java.io.FilePermission \"" + System.getProperty("java.io.tmpdir").replaceAll("\\\\", "/") + "\", \"read, write, delete\""); addAdditionalPerm("permission java.io.FilePermission \"" + System.getProperty("java.home").replaceAll("\\\\", "/") + "/-\", \"read\""); addAdditionalPerm("permission java.io.FilePermission \"" + System.getProperty("java.home").replaceAll("\\\\", "/").replaceAll(" ", "%20") + "/-\", \"read\""); addAdditionalPerm("permission java.io.FilePermission \"" + IndigoLauncher.class.getProtectionDomain().getCodeSource().getLocation().getPath().replaceAll("\\\\", "/") + "\", \"read\""); writeAdditionalPerms(getPolicyLocation()); System.out.println("Setting security policy to " + getPolicyLocation()); System.setProperty("java.security.policy", getPolicyLocation()); Policy.getPolicy().refresh(); File[] natives = new File(nativesDir).listFiles(); System.setSecurityManager(getSecurityManager(natives)); } private SecurityManager getSecurityManager(final File[] natives) { SecurityManager manager = new SecurityManager() { @Override public void checkPermission(Permission perm) { try { super.checkPermission(perm); } catch (SecurityException e) { if ((perm.getName().toLowerCase().contains(".ttf") || perm.getName().toLowerCase().contains(".ttc")) && perm.getActions().equals("read")) { return; } if (perm.getName().contains("loadLibrary.")) { System.out.println("LOADLIB: " + perm.getName()); String libPath = perm.getName().replaceAll("loadLibrary.", ""); File file = new File(libPath); System.out.println("Minecraft is attempting to load native : " + file.getAbsolutePath()); for (File nv : natives) { if (file.getAbsolutePath().equals(nv.getAbsolutePath())) { System.out.println("Native loading permitted."); return; } } } final Permission fPerm = perm; SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() { @Override public Boolean doInBackground() { System.out.println("Asking user for perm " + fPerm.toString()); return (JOptionPane.showConfirmDialog(null, "A mod is trying to access something stoopid:\n" + fPerm.toString() + "\nDo you want to allow it?\nWarning this could allow the mod to access sensitive info.") == JOptionPane.YES_OPTION); } }; worker.execute(); boolean allowed = false; try { System.out.println("Waiting for response..."); allowed = (Boolean) worker.get(); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (ExecutionException e1) { e1.printStackTrace(); } if (!allowed) { System.out.println("Not allowing permission."); throw e; } } } }; return manager; } }