Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kerberos broken after upgrading from Java6 to Java7

I have a working application using the spring-security kerberos extension, running on jboss, running java 6.

I'm in the process of upgrading my jvm from java 6 to java 7. When I do that, using the same codebase and the same keytab that worked on java 6, I now receive an error when using java 7.

I consistently receive: java.security.PrivilegedActionException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC)

I've tried to regenerate the keytab with the different /crypto options that have been described in other forums to no avail.

I have debugged the java 7 code and indeed, the classes that deal with reading the keytab on startup changed from 6 to 7. Could it be that my keytab isn't being read into the app correctly anymore? Some of the debug messages that I see on startup using Java6 don't appear anymore in 7, but I can't tell if that's by design or if that indicates something else is in play? Has anybody else had problems upgrading from 6 to 7 and had their kerberos integration break on them? Any advice?

With spnego and kerberos debug logging on for startup, my log shows:

2012-12-10 10:29:30,886  Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is jndi:/localhost/docfinity/WEB-INF/classes/config/common/security/http-docfinity.keytab refreshKrb5Config is false principal is HTTP/[email protected] tryFirstPass is false useFirstPass is false storePass is false clearPass is false
2012-12-10 10:30:26,322  principal is HTTP/[email protected]
2012-12-10 10:30:29,794  Will use keytab
2012-12-10 10:30:29,807  Ordering keys wrt default_tkt_enctypes list
2012-12-10 10:30:29,821  Config name: C:\Windows\krb5.ini
2012-12-10 10:30:29,827  Using builtin default etypes for default_tkt_enctypes
2012-12-10 10:30:29,832  default etypes for default_tkt_enctypes:
2012-12-10 10:30:29,837   17    aes128-cts-hmac-sha1-96
2012-12-10 10:30:29,839   16    des3-cbc-sha1-kd
2012-12-10 10:30:29,842   23    rc4-hmac
2012-12-10 10:30:29,846   1     des-cbc-crc
2012-12-10 10:30:29,849   3     des-cbc-md5
2012-12-10 10:30:29,851  .
2012-12-10 10:30:29,855  Commit Succeeded 

One other question - you'll see it's trying to read C:\Windows\krb5.ini. I don't have such a file on my server. Do I need one? I didn't have one with java 6 either and that worked.

aaron

like image 759
A Ehrensberger Avatar asked Dec 10 '12 15:12

A Ehrensberger


3 Answers

Yes! We patched SunJaasKerberosTicketValidator to look like this and it worked:

String keyTabPath = this.keyTabLocation.getURL().toExternalForm();
String runtimeVersion = System.getProperty("java.version");
if (runtimeVersion.startsWith("1.7")) 
{
      LOG.info("Detected jdk 7. Modifying keytabpath");
      if (keyTabPath != null)
      {
        if (keyTabPath.startsWith("file:")) 
        {
            keyTabPath = keyTabPath.substring(5);
        }
      }
}
LOG.info("KeyTabPath: " + keyTabPath);
LoginConfig loginConfig = new LoginConfig(keyTabPath, this.servicePrincipal,
                this.debug);
like image 94
Ken DeLong Avatar answered Nov 06 '22 07:11

Ken DeLong


Here are two potential issues that might be affecting you:

  1. Java 7 appears to switch the default encryption type order. Details:

    • Java 7 Kerberos Issue - AES128 Corrupt checksum

  2. You did't say what specific version of JDK 7 you are using, but there was a bug in earlier versions of JDK 7 that prevented loading keytab files via "file:" URLs:

    • http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=2221392

Another user on SO worked around the last issue by modifying Spring source:

  • BadCredentialsException: Kerberos validation not succesfull
like image 25
kaliatech Avatar answered Nov 06 '22 09:11

kaliatech


Change the keyTabLocation object to a string.

So private String keyTabLocaiton.

      @Override
        public void afterPropertiesSet() throws Exception {
            Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified");
            Assert.notNull(this.keyTabLocation, "keyTab must be specified");
            // if (keyTabLocation instanceof ClassPathResource) {
            // LOG.warn("Your keytab is in the classpath. This file needs special protection and shouldn't be in the classpath. JAAS may also not be able to load this file from classpath.");
            // }
            LoginConfig loginConfig = new LoginConfig(this.keyTabLocation, this.servicePrincipal,
                    this.debug);
            Set<Principal> princ = new HashSet<Principal>(1);
            princ.add(new KerberosPrincipal(this.servicePrincipal));
            Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
            LoginContext lc = new LoginContext("", sub, null, loginConfig);
            lc.login();
            this.serviceSubject = lc.getSubject();
        }

Also where the LoginConfig guy, set the isInitiator flag to true.

 public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
            HashMap<String, String> options = new HashMap<String, String>();
            options.put("useKeyTab", "true");
            options.put("keyTab", this.keyTabLocation);
            options.put("principal", this.servicePrincipalName);
            options.put("storeKey", "true");
            options.put("doNotPrompt", "true");
            if (this.debug) {
                options.put("debug", "true");
            }
            options.put("isInitiator", "true");
            //options.put("isInitiator", "false");

            return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), };
        }

Hopefully this helps you fix your issue.

like image 1
Zoharat Avatar answered Nov 06 '22 09:11

Zoharat