Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6979329

CCacheInputStream fails to read ticket cache files from Kerberos 1.8.1

XMLWordPrintable

    • b121
    • x86
    • linux
    • Verified

        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";
        >

              weijun Weijun Wang
              weijun Weijun Wang
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: