001package org.intellimate.izou.security;
002
003import org.intellimate.izou.addon.AddOnModel;
004import org.intellimate.izou.main.Main;
005import ro.fortsoft.pf4j.IzouPluginClassLoader;
006
007import java.lang.reflect.ReflectPermission;
008import java.security.Permission;
009
010/**
011 * The ReflectionPermissionModule stops any illegal reflection calls on Izou.
012 * <p>
013 *     For example, if an addOn were to reflect on the secure access class to get root access, then the
014 *     ReflectionPermissionModule would stop that reflection.
015 * </p>
016 */
017public class ReflectionPermissionModule extends PermissionModule {
018
019    /**
020     * Creates a new ReflectionPermissionModule
021     *
022     * @param main the main class of Izou
023     * @param securityManager the security manager in Izou
024     */
025    public ReflectionPermissionModule(Main main, SecurityManager securityManager) {
026        super(main, securityManager);
027    }
028
029    @Override
030    public boolean canCheckPermission(Permission permission) {
031        return permission instanceof ReflectPermission && "suppressAccessChecks".equals(permission.getName());
032    }
033
034    @Override
035    public void checkPermission(Permission permission, AddOnModel addon) throws SecurityException {
036        boolean reflectionUsedInStack = false;
037        boolean addOnInStack = false;
038
039        SecurityManager securityManager = (SecurityManager) System.getSecurityManager();
040        Class[] classes = securityManager.getClassContextPkg();
041
042        for (Class clazz : classes) {
043            if (clazz.getPackage().getName().toLowerCase().contains("reflect")) {
044                reflectionUsedInStack = true;
045            } else if (clazz.getClassLoader() instanceof IzouPluginClassLoader) {
046                addOnInStack = true;
047            }
048
049            if (reflectionUsedInStack && addOnInStack) {
050                throw getException("reflection");
051            }
052        }
053    }
054}