views:

576

answers:

1

We have a kerberos domain at my company and I'm running a few of the Java/Kerberos examples. The question I have is around the login mechanism from the server's perspective. When running the server example GssServer.java, I need to get a javax.security.auth.Subject; in the supplied code this is via a LoginContext thus:

// Create a LoginContext with a callback handler and login
LoginContext context = new LoginContext(name, new TextCallbackHandler());
context.login();

Subject subject = context.getSubject();

This is all OK and when I run the example I see a lovely login prompt. However my issue is that this is not really how my server will run and nor how I've been led to understand how I should be presenting up services from within a kerberos domain. In the GssServer example, the problem is my server (read: service) should not need to authenticate itself to the KDC in order to present its service to clients. Access to the server-side keytab file should be sufficient to do this. So for the example config:

//jaas-krb5.conf
server {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/home/myusr/my-server.keytab"
    principal="myserv/mymachine.some.domain";
};

And in the Java code:

GSSManager manager = GSSManager.getInstance();
Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
GSSName gssName = manager.createName("myserv/[email protected]", 
                                     GSSName.NT_HOSTBASED_SERVICE);
GSSCredential serverCreds = manager.createCredential(gssName,
                                     GSSCredential.DEFAULT_LIFETIME,
                                     krb5Mechanism,
                                     GSSCredential.ACCEPT_ONLY);

The trouble with this is that the server information in the jaas-krb5.conf file is not available unless I authenticate myself via the line:

Jaas.loginAndAction("server", action);

I shouldn't have to go thru this authentication! But if I don't authenticate myself, I end up with:

Exception in thread "main" GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new ACCEPT credentials failed!)
    at sun.security.jgss.krb5.Krb5AcceptCredential.getKeysFromSubject(Krb5AcceptCredential.java:188)
    at sun.security.jgss.krb5.Krb5AcceptCredential.getInstance(Krb5AcceptCredential.java:73)
    at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:77)
    at sun.security.jgss.GSSManagerImpl.getCredentialElement(GSSManagerImpl.java:149)
    at sun.security.jgss.GSSCredentialImpl.add(GSSCredentialImpl.java:389)
    at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.java:45)
    at sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerImpl.java:102)
    at gsa.hk.GssServer$GssServerAction.run(GssServer.java:79)
    at gsa.hk.GssServer.main(GssServer.java:57)
Caused by: javax.security.auth.login.LoginException: No LoginModules configured for com.sun.security.jgss.accept
    at javax.security.auth.login.LoginContext.init(LoginContext.java:256)
    at javax.security.auth.login.LoginContext.<init>(LoginContext.java:403)
    at sun.security.jgss.LoginUtility.login(LoginUtility.java:72)
    at sun.security.jgss.krb5.Krb5Util.getKeysFromSubject(Krb5Util.java:205)
    at sun.security.jgss.krb5.Krb5AcceptCredential$1.run(Krb5AcceptCredential.java:184)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.jgss.krb5.Krb5AcceptCredential.getKeysFromSubject(Krb5AcceptCredential.java:181)
    ... 8 more

It's not surprising that there is a problem. After all, unless I have a handle on the server subject, how can I know where my keytab is, or what service I am providing?

So my question is: how can I tell the GSS API about the keytab/service without authenticating myself in code?

A: 

OK. So this turns out to be extremely easy assuming you know that the keytab file can be used instead of authentication. This is outlined a bit in the JavaDoc for Krb5LoginModule

Basically, if I

loginAndAction("anything", action)

Then my config should look like:

//jaas-krb5.conf
anything {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    doNotPrompt=true
    keyTab="/home/myusr/my-server.keytab"
    principal="myserv/mymachine.some.domain";
};

The important bit is the addition of doNotPrompt=true. When this property is set, the server code uses the information in the keytab

oxbow_lakes