JDK-6979329 : CCacheInputStream fails to read ticket cache files from Kerberos 1.8.1
  • Type: Bug
  • Component: security-libs
  • Sub-Component: org.ietf.jgss:krb5
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2010-08-24
  • Updated: 2011-11-10
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u27Fixed 7 b121Fixed OpenJDK6Fixed
Description
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";
>

Comments
EVALUATION Fixed. Any entry with unparseable ticket or second_ticket is ignored.
22-11-2010

EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/c1734c00a8ba
22-11-2010