-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
GraalVM and environment:
- OS: Linux
- GraalVM version 20.1.0 (both CE and EE)
- JDK: 1.8
Issue:
The same java application code for kerberos authentication works fine in JVM, but failed to get GSSCredential in native image. We noticed JVM and native image have different behavior when handling AccessControlContext.
Steps to reproduce:
- On Linux, run 'kinit -f' to retrieve valid kerberos ticket and store to the cache.
- build and run the blow java code:
import javax.security.auth.Subject;
import javax.security.auth.SubjectDomainCombiner;
import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.;
import java.util.;
public static void kerberosTest() throws PrivilegedActionException, LoginException {
class LoginConfiguration extends Configuration
{
private AppConfigurationEntry entry;
private LoginConfiguration(Map<String, String> options)
{
entry = new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
new HashMap<>(options)
);
}
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
{
return new AppConfigurationEntry[] {entry};
}
}
//Kerberos login and get subject
Subject subject = null;
Map<String, String> options = new HashMap<>();
options.put("doNotPrompt", "true");
options.put("useTicketCache", "true");
Configuration configuration = new LoginConfiguration(options);
LoginContext loginContext = new LoginContext("", null, null, configuration);
loginContext.login();
subject = loginContext.getSubject();
Subject.doAs(subject, new PrivilegedExceptionAction<Boolean>() {
@Override
public Boolean run() throws Exception
{
final AccessControlContext acc = AccessController.getContext();
DomainCombiner dc = acc.getDomainCombiner();
//run the code in JVM will retrieve valid dc but native image will return null for dc
if (dc == null ) {
System.out.println("dc is null");
return Boolean.FALSE;
}
System.out.println("dc is NOT null");
return Boolean.TRUE;
}
});
}
Our analysis:
We debugged the code, and learned Subject.doAs(subject) is supposed to push a AccessControlContext with the subject to the stack and later the AccessController.getContext() will retrieve it. However, in native image, it failed to retrieve it from the stack. We noticed two native java methods were called in the process, so we add them to the jni-config.json as below, but it didn't help.
{
"name":"java.security.AccessController",
"methods":[
{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction", "java.security.AccessControlContext"] },
{"name":"getStackAccessControlContext" }
]
},