Programmatically grant Permissions without using policy file

点点圈 提交于 2019-12-03 12:10:46

Based on @EJP's advice, I have debugged using -Djava.security.debug=access and found all the needed permissions in a policy file :

grant { permission java.net.SocketPermission "*:1024-", "connect, resolve"; };

grant { permission java.util.PropertyPermission "*", "read, write"; };

grant { permission java.io.FilePermission "<>", "read"; };

But because I didn't want to create a policy file, I found a way to replicate this programmatically by extending java.security.Policy class and setting the policy at the startup of my application using Policy.setPolicy(new MinimalPolicy());

public class MinimalPolicy extends Policy {

    private static PermissionCollection perms;

    public MinimalPolicy() {
        super();
        if (perms == null) {
            perms = new MyPermissionCollection();
            addPermissions();
        }
    }

    @Override
    public PermissionCollection getPermissions(CodeSource codesource) {
        return perms;
    }

    private void addPermissions() {
        SocketPermission socketPermission = new SocketPermission("*:1024-", "connect, resolve");
        PropertyPermission propertyPermission = new PropertyPermission("*", "read, write");
        FilePermission filePermission = new FilePermission("<<ALL FILES>>", "read");

        perms.add(socketPermission);
        perms.add(propertyPermission);
        perms.add(filePermission);
    }

}

class MyPermissionCollection extends PermissionCollection {

    private static final long serialVersionUID = 614300921365729272L;

    ArrayList<Permission> perms = new ArrayList<Permission>();

    public void add(Permission p) {
        perms.add(p);
    }

    public boolean implies(Permission p) {
        for (Iterator<Permission> i = perms.iterator(); i.hasNext();) {
            if (((Permission) i.next()).implies(p)) {
                return true;
            }
        }
        return false;
    }

    public Enumeration<Permission> elements() {
        return Collections.enumeration(perms);
    }

    public boolean isReadOnly() {
        return false;
    }

}

Because your

new AllPermission()).newPermissionCollection()

is treated by Java as immutable (why add permissions to a collection that already allows all permissions?), and because Java will try to add permissions to the collection. That's where the error message comes from - Java tried to add a java.io.FilePermission to your AllPermission.

Instead, do this:

class MyPolicy extends Policy {
    @Override
    public PermissionCollection getPermissions(CodeSource codesource) {
        Permissions p = new Permissions();
        p.add(new PropertyPermission("java.class.path", "read"));
        p.add(new FilePermission("/home/.../classes/*", "read"));
        ... etc ...
        return p;
    }
}

Don't install the SecurityManager. You only need it if you're using the codebase feature, and if you need that you need a proper .policy file,

Short solution

Extend your updated solution to:

public class MyPolicy extends Policy
{
    @Override
    public PermissionCollection getPermissions(CodeSource codesource)
    {
        Permissions p = new Permissions();
        p.add(new AllPermission());
        return p;
    }
}

Consider, that Policy.getPermissions() must always return a mutable PermissionCollection

Returns: ...If this operation is supported, the returned set of permissions must be a new mutable instance and it must support heterogeneous Permission types...

This solution works already, since it adds an AllPermission object into every call of the Policy.getPermissions(ProtectionDomain), that refers to Policy.getPermissions(CodeSource).

Clean solution

But there is a cleaner solution, that doesn't track any unnecessary other Permissions, since AllPermissions allows pretty everything already.

public class MyPolicy extends Policy
{
    private static class AllPermissionsSingleton extends PermissionCollection
    {
        private static final long serialVersionUID = 1L;
        private static final Vector<Permission> ALL_PERMISSIONS_VECTOR = new Vector<Permission>(Arrays.asList(new AllPermission()));

        @Override
        public void add(Permission permission)
        {
        }

        @Override
        public boolean implies(Permission permission)
        {
            return true;
        }

        @Override
        public Enumeration<Permission> elements()
        {
            return ALL_PERMISSIONS_VECTOR.elements();
        }

        @Override
        public boolean isReadOnly()
        {
            return false;
        }
    }

    private static final AllPermissionsSingleton ALL_PERMISSIONS_SINGLETON = new AllPermissionsSingleton();

    @Override
    public PermissionCollection getPermissions(CodeSource codesource)
    {
        return ALL_PERMISSIONS_SINGLETON;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!