I have a program which dynamically loads and runs class files from disk as well as remote servers. I want to integrate a User Management system which allows me to call a user authentication method before a high-risk function call is allowed, such as reading/writing files, opening a socket, classloading, etc... The SecurityManager seems like the perfect resource to complete this, but is being removed in future releases of the JDK. My current implementation uses a PermittedThread class that holds an authenticated User object, which is retrieved from the Thread and checked against a permissions database to ensure that this User has permission to run this high-risk function call, as shown in the code block below.
My current implementation is as such (in brief)
PermittedThread:
public class PermittedThread extends Thread {
private final User user;
// Create a PermittedThread inheriting the User object from the current thread.
public PermittedThread(Runnable target) {
super(target);
Thread t = currentThread();
if (t instanceof PermittedThread) {
user = ((PermittedThread) t).retrieveUser();
} else
user = null;
}
// Create a PermittedThread with the specified User object
public PermittedThread(Runnable target, User user) {
super(target);
this.user = user;
}
public User retrieveUser() {
return user;
}
}
From my SecurityManager:
// Ensure that the current Thread is a PermittedThread, otherwise the Thread is not
// allowed to make high-risk function calls (user = null).
private User checkThreadWrapping() {
Thread t = Thread.currentThread();
if (t instanceof PermittedThread) {
User u = ((PermittedThread) t).retrieveUser();
if (u != null)
return u;
}
throw new SecurityException();
}
@Override
public void checkPermission(Permission perm, Object context) {
User threadUser = checkThreadWrapping();
// Check if the specific User has access to this permission, and throw a
// SecurityException accordingly
UserManagement.checkUserPermissionAccess(perm, threadUser);
}
Without the SecurityManager, I can't imagine anyway I would be able to interrupt high-risk function calls and force an authentication check, especially on a Thread based leve. What might be a good work around for this?
I looked into bytecode manipulation as a means of completing this as referenced by this article. However I don't believe I can modify java.base bytecode, which I would need to in order to watch for these function calls.