Here is my current knowledge dump on how try to get Tomcat 6.x to support Microsoft SPNEGO and Kerberos. I am not working to support NTLM currently, but may in the future.
THIS INFORMATION DOESN’T SOLVE THE PROBLEM YET
UNTIL I REMOVE THIS TEXT, THIS INFORMATION IS NOT COMPLETE OR ACCURATE TO THE BEST OF MY KNOWLEDGE
Update! – Success
Update I have successfully done a SPNEGO negotiation over HTTP with IE 7 to Tomcat 6 and Java 6. I will work to get this document updated with details.
Something that I haven’t properly discussed here is user requirements inside Active Directory primarily because that was the last step I worked on.
Digging into the IT environment I was programming against, I found out that while we were using Active Directory 2003, we were running it in a 2000 mode. As such I made sure enable “Use DES” for the account I was running the Tomcat instance under. I can’t find the original page that I found the information that indicated Microsoft changed it’s implementation of RC4-HMAC between 2000 and 2003 (the RFC was released in between versions), so I played it safe. If someone can provide more information on this, or if I get time to verify the settings with IT to disable this, I will update this page.
When SPNEGO is requested to a host, the client is requesting the server ticket of
HTTP/<hostname>. Under my setup, even though the server was running on port 8080, it didn’t seem to care about the port number. I have seen information floating around that should should also bind the port as part of the service name but this wasn’t required in my particular instance.
The switch from Active Directory 2000 to 2003 also changed how service principles can be delegated, instead of 2000’s all or nothing setup, 2003 has finer grained control.
Architecture
This setup is targeted at the following environment.
Auth Side
- Active Directory Server acting as Trusted Third Party
Server Side
- Windows 2003 Server
- Tomcat 6.x
- SPNEGO with only Kerberos
Client Side
- IE 7 or Firefox 3 (Properly configured for MS SPNEGO)
Kerberos
NTLM / NTLMSSP
I won’t be working on supporting NTLM since Microsoft has depreciated it and is seeking to remove it from future OS releases. The information that I’m going on may not be accurate, as it was last revised April 2007, I have yet to verify the situation Vista or Windows Server 2008, and that they got the acronym wrong (NTLMSSSP instead of NTLMSSP).
Limitations
Microsoft’s Kerberos ticket has an extended piece of information called the PAC. This contains group information for the user.
Microsoft
Windows Server 2003
MS KB Article ID 308339
I am using Java based KeyTab file so this article shouldn’t be relevant.
Microsoft Kerberos PAC
I won’t be decoding the PAC, instead will be using another channel to acquire group information for a user who has been successfully authenticated. Currently planning to use LDAP against Active Directory. This allows for mobility later on.
SPNEGO
Troubleshooting
Registry
The following are some of the options that can be enabled for Kerberos operation on Windows.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
| AllowTGTSesionKey | DWORD | 0×1 | Allows third party access to local Ticket Granting Tickets in Kerberos Store |
| LogLevel | DWORD | 0×1 | Enables logging to Event Viewer under System. Useful for trouble shooting |
Kerb Tray
This tool shows Windows based Kerberos tickets your system currently has. This is a separate store then the Keytab system used by Java, but it is helpful to ensure that you are getting Kerberos tickets in the first place from your Active Directory server.
Java
You need to be using Java 1.6.x or greater to ensure that Kerberos and SPNEGO are functional. Before Java 1.6 rc4-hmac and arcfour-hmac-md5 wasn’t supported.
- RFC 2853
- Java GSS Trouble Shooting
- Java GSS Tutorial – Advanced JGSS Security Programming
- Note at bottom
Note: Microsoft has implemented certain variations of the SPNEGO protocol, hence to inter-operate with Microsoft, we have added an MS mode via a new system property “sun.security.spnego.msinterop”. This property is enabled to “true” by default. To disable it, you need to explicitly set this property to “false”. To enable SPNEGO debugging, you can set the system property “sun.security.spnego.debug=true”.
- Note at bottom
KeyTab
Java has it’s own Kerberos settings, and it’s own key tab file to store login info (username/pass). Kinit will created a credential cache, but we want to create a keytab entry for the account the server will be authenticating under. Don’t really want to be entering passwords on launch of the server (in case of a reboot etc). Ideally when the server is running under Windows we would use the Kerberos tickets already created, but just getting things working if the first priority.
klist -k
ktab
kinit
ktab -a <principal name>
Tomcat 6
Launch Configs
-Djava.security.auth.login.config="jass_config_file_path"
-Djavax.security.auth.useSubjectCredsOnly=false
-Djava.security.krb5.conf="c:\windows\krb5.ini"
javax.security.auth.useSubjectCredsOnly
Documentation on this flag is located here
You either need to initiate a JAAS Subject manually to create the GSSCredentials, or you can set this flag which will allow the underlying systems to pull what ever is convenient.
java.security.auth.login.config
Defines the JAAS security settings. One = indicates to add to baseline policy for JVM, two == indicates to override master settings. In my case using only =.
Example file
com.sun.security.jgss.krb5.accept {
com.sun.security.auth.module.Krb5LoginModule
required
useKeyTab=true
principal="<user acct>"
debug=true
storeKey=true
doNotPrompt=true
useTicketCache=false;
};
Refer to JavaDoc for JAAS Krb5LoginModule for more detailed configuration information.
krb5.ini
When configuring this java file, please refer to Java GSS Security Enhancement List As it lists the supported encryption types.
[libdefaults]
default_realm = AD.MUSTEAT.ORG
default_keytab_name = FILE:c:\windows\krb5.keytab
default_tkt_enctypes = des-cbc-md5 rc4-hmac
default_tgs_enctypes = des-cbc-md5 rc4-hmac
[realms]
AD.MUSTEAT.ORG = {
kdc = ad.musteat.org:88
default_domain = ad.musteat.org
}
[domain_realm]
.musteat.org = AD.MUSTEAT.ORG