java 11 Error with Kerberos Authentication principal - KRB_CRED not generated correctly

Viewed 3340
java.sql.SQLRecoverableException: IO Error: The service in process is not supported. Operation unavailable (Mechanism level: KRB_CRED not generated correctly.)

I am getting this exception when my HikariDataSource is attempting to establish a connection with my oracle database by using kerberos as the means of authentication.

I am confident the issue is something to do with my principle not being accepted despite my credential cache file working perfectly fine for my other java 8 projects.

The reason I believe its an issue with the principal is because I have a separate credential cache file that is generated on my server that uses a different principal than the one I would use locally. That credential cache file from my server works perfectly fine when it is used locally for this java 11 project. However, I cannot locally generate credential cache files with that principal.

Additionally, I am using the same krb5.conf file so I don't understand how my principal is being accepted by 1 service but, not another... I also made sure to use the java 11 version of the kinit.exe file when executing the below command although, I don't think that should matter.

$kinit -c credential_cache_file instance@domain.realm

Using other flags such as -A -p -f also gives me a separate error but, that type of credential cache file won't work for any of my java 8 or java 11 services.

java.nio.BufferOverflowException: null

EDIT: The lowest level error I am actually getting is this.

Caused by: sun.security.krb5.KrbException: Invalid option in ticket request. (101)
1 Answers

Actually a bit more information and stacktrace would have helped in debugging the issue. As per the information provided above,

This exception happens when there is a mismatch in the kerberos credential. Then GSSException occurs and this message is generated.

Operation unavailable (Mechanism level: KRB_CRED not generated correctly.)

Code Flow

Step 1: This message is part of Krb5Context class. Here InquireType is KRB5_GET_KRB_CRED which means it is an attribute type for retrieving the KRB_CRED message that an initiator is about to send to an acceptor.
Links: Krb5ContextInquireType

try {
     byte[] krbCred = new KrbCred(tgt, serviceCreds, key).getMessage();
      return new KerberosCredMessage( sender, recipient, krbCred);
    } catch (KrbException | IOException e) {
       GSSException gsse = new GSSException(GSSException.UNAVAILABLE, -1,
                            "KRB_CRED not generated correctly.");
        gsse.initCause(e);
        throw gsse;
   }

Step 2: Then it calls KrbCred class and here validation fails. This class encapsulates the KRB-CRED message that a client uses to send its delegated credentials to a server. In the condition check there is a mismatch in the Client of the Service Ticket with the client in Ticket Granting Ticket. So, as you mentioned it seems to me as a Principal issue.   Link : KrbCred

PrincipalName client = tgt.getClient();
PrincipalName tgService = tgt.getServer();
if (!serviceTicket.getClient().equals(client))
    throw new KrbException(Krb5.KRB_ERR_GENERIC,

Step 3: First KrbException is thrown thereafter it is caught by the catch block and GSSException is thrown back with message as Operation unavailable.   Link:  GSSException

Changes between Java 8 and Java 11

There has been a lot changes for kerberos in Java 11. You can find it in the changelog. E.g.

The are fewer InquireType in Krb5Context of Java 8 compared to Krb5Context of Java 11.

Possible Solution

The Kerberos client which you are using may not currently support the 'canonicalize' setting in the configuration file (krb5.conf). As a result, Name Canonicalization behavior cannot be customized. The client will claim support for it in every TGT request if sun.security.krb5.disableReferrals is false, and the KDC service may change the client name.

JDK 11: The 'canonicalize' flag in the krb5.conf file is now supported by the JDK Kerberos implementation. When set to true. The new default behavior is different from previous releases where name canonicalization was always requested by clients in TGT requests to KDC services (provided that support for RFC 6806 was not explicitly disabled with the sun.security.krb5.disableReferrals system or security properties)

This issue was seen in few minor Java 8 version(1.8.0_242) as well. You can try the example in the ticket to reproduce. JDK-8239385
Some more information JDK-8244465

Cross-Realm Referrals Support is enabled by default and 5 is the maximum number of referral hops allowed. To turn it off, set the sun.security.krb5.disableReferrals security or system property to false. To configure a custom maximum number of referral hops, set the sun.security.krb5.maxReferrals security or system property to any positive value.

You can try changing the JAAS config to use a ticket in the ticket cache created upfront using kinit.
You can try to upgrade the java version as well.

Update from discussion in the comments section:

by: sun.security.krb5.KrbException: Invalid option in ticket request. (101)

This could be linked to proxiable=true in your krb5.conf. Removing the value can help in resolving the issue.

Kerberos authentication fails with “java.nio.BufferOverflowException"

This issue could be related to the JDBC driver. The current version may not support the operation. Upgrading or Downgrading oracle jdbc driver may lead to the resolution.

Related