FULL PRODUCT VERSION : java version "1.6.0_20" Java(TM) SE Runtime Environment (build 1.6.0_20-b02) Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01, mixed mode) ADDITIONAL OS VERSION INFORMATION : Linux thomas 2.6.32-24-generic #39-Ubuntu SMP Wed Jul 28 05:14:15 UTC 2010 x86_64 GNU/Linux EXTRA RELEVANT SYSTEM CONFIGURATION : Kerberos 1.8.1 A DESCRIPTION OF THE PROBLEM : Kerberos 1.8.1 introduced a new feature by which configuration settings can be stored in the ticket cache file using a special principal name: http://krbdev.mit.edu/rt/Ticket/Display.html?user=guest&pass=guest&id=6206 This breaks CCacheInputStream in such a way that the entire ticket cache file is unreadable. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : - Install Kerberos 1.8.1 or later - kinit - strings /path/to/ticketcache | grep X-CACHE If X-CACHE is in the file, then the Krb5Login module will not be able to make use of the cache. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Ticket cache is parsed correctly with new-style configuration credentials ignored. ACTUAL - Ticket cache fails to load. Debug output shows an exception trying to parse the configuration variable "yes" as if it were an encrypted ticket. ERROR MESSAGES/STACK TRACES THAT OCCUR : >>>DEBUG <CCacheInputStream> client principal is atm@ATM-LOCAL >>>DEBUG <CCacheInputStream> server principal is X-CACHECONF:/krb5_ccache_conf_data/fast_avail/krbtgt/ATM-LOCAL@ATM-LOCAL >>>DEBUG <CCacheInputStream> key type: 0 >>>DEBUG <CCacheInputStream> auth time: Wed Dec 31 16:00:00 PST 1969 >>>DEBUG <CCacheInputStream> start time: Wed Dec 31 16:00:00 PST 1969 >>>DEBUG <CCacheInputStream> end time: Wed Dec 31 16:00:00 PST 1969 >>>DEBUG <CCacheInputStream> renew_till time: Wed Dec 31 16:00:00 PST 1969 >>> CCacheInputStream: readFlags() java.io.IOException: extra data given to DerValue constructor at sun.security.util.DerValue.init(DerValue.java:368) at sun.security.util.DerValue.<init>(DerValue.java:277) at sun.security.krb5.internal.Ticket.<init>(Ticket.java:81) at sun.security.krb5.internal.ccache.CCacheInputStream.readData(CCacheInputStream.java:250) at sun.security.krb5.internal.ccache.CCacheInputStream.readCred(CCacheInputStream.java:357) at sun.security.krb5.internal.ccache.FileCredentialsCache.load(FileCredentialsCache.java:225) at sun.security.krb5.internal.ccache.FileCredentialsCache.acquireInstance(FileCredentialsCache.java:104) at sun.security.krb5.internal.ccache.CredentialsCache.getInstance(CredentialsCache.java:75) at sun.security.krb5.Credentials.acquireTGTFromCache(Credentials.java:309) at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:589) at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542) REPRODUCIBILITY : This bug can be reproduced always. CUSTOMER SUBMITTED WORKAROUND : On Kerberos 1.8.1, renewing the local kerberos ticket with "kinit -R" drops the special configuration credential initially added by "kinit", allowing this to succeed. The following patch resolves the problem: diff -r krb5.orig/internal/ccache/CCacheInputStream.java krb5.new/internal/ccache/CCacheInputStream.java 362a363,367 > if (isConfigurationPrincipal(spname)) { > skipLengthPrefixedData(); // skip ticket > skipLengthPrefixedData(); // skip secondary ticket > return null; > } 375a381,400 > > /** > * Return true if the given principal corresponds to a non-ticket configuration > * entry in the cache file. > */ > private boolean isConfigurationPrincipal(PrincipalName princ) { > String[] components = princ.getNameStrings(); > return (components.length > 2 && > PrincipalName.CONFIGURATION_REALM.equals(components[0]) && > PrincipalName.CONFIGURATION_NAME.equals(components[1])); > } > > /** > * Read a 32-bit length from the stream and skip an equal number of bytes. > */ > private void skipLengthPrefixedData() throws IOException { > int skip = read(4); > byte[] skipbuf = new byte[skip]; > read(skipbuf, 0, skip); > } diff -r krb5.orig/internal/ccache/FileCredentialsCache.java krb5.new/internal/ccache/FileCredentialsCache.java 189c189,192 < credentialsList.addElement(cis.readCred(version)); --- > Credentials cred = cis.readCred(version); > if (cred != null) { > credentialsList.addElement(cred); > } diff -r krb5.orig/PrincipalName.java krb5.new/PrincipalName.java 89a90,99 > /** > * The realm used for non-ticket configuration data stored in ccache > */ > public static final String CONFIGURATION_REALM = "X-CACHECONF:"; > > /** > * The nameused for non-ticket configuration data stored in ccache > */ > public static final String CONFIGURATION_NAME = "krb5_ccache_conf_data"; >
|