Issue
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 [email protected]
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)
Solution
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: Krb5Context InquireType
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.
- Support cross-realm MSSFU
- Support for canonicalize in krb5.conf
- Support for Kerberos Cross-Realm Referrals (RFC 6806)
- LDAP Channel Binding Support for Java GSS/Kerberos
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.
Answered By - Tris
Answer Checked By - Marie Seifert (JavaFixing Admin)