Kerberos - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC
Asked Answered
B

9

18

I'm trying to setup SSO for Java WebApp using Kerberos/SpNego. I'm using:

  • Java 1.7u67
  • org.springframework.security.kerberos 1.0.0.RELEASE
  • Active Directory
  • Tomcat 7 on Linux

After overcoming the problem discribed in How to configure kerberos on Tomcat/linux server?, I'm now stuck with the following error:

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesful
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:70) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145) ~[spring-security-kerberos-web-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.lightadmin.core.view.TilesContainerEnrichmentFilter.doFilterInternal(TilesContainerEnrichmentFilter.java:40) [lightadmin-1.2.0.RC1.jar:1.2.0.RC1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.55]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [catalina.jar:7.0.55]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.55]
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.55]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.55]
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) [tomcat-coyote.jar:7.0.55]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) [tomcat-coyote.jar:7.0.55]
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) [tomcat-coyote.jar:7.0.55]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_67]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_67]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.55]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_67]
Caused by: java.security.PrivilegedActionException: null
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_67]
        at javax.security.auth.Subject.doAs(Subject.java:415) ~[na:1.7.0_67]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:67) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        ... 42 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC)
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:788) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
        at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:875) ~[na:1.7.0_67]
        at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:548) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:162) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:152) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        ... 45 common frames omitted
Caused by: sun.security.krb5.KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC
        at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:273) ~[na:1.7.0_67]
        at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:144) ~[na:1.7.0_67]
        at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108) ~[na:1.7.0_67]
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:771) ~[na:1.7.0_67]
        ... 53 common frames omitted

However it seems that the key should be there, since on startup of the application I got the following debug:

  Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is /opt/pksvc/tomcat_edl/current/conf/TestSpnego.keytab refreshKrb5Config is false principal is [email protected] tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal is [email protected]
Will use keytab
>>> KeyTabInputStream, readName(): MYREALM.DE
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): lxdetstpksvc01.mydomain.de
>>> KeyTab: load() entry length: 83; type: 23
Ordering keys wrt default_tkt_enctypes list
Java config name: /opt/pksvc/tomcat_edl/current/conf/krb5.conf
Loaded from Java config
default etypes for default_tkt_enctypes: 23.
Commit Succeeded

So enctype 23 = RC4 with HMAC is the type of the KeyTab entry and the default enctype. I can also see that the browser sends a token with this enctype (I removed the binary part from the following):

Ticket  TicketType{TktVno=5,Realm=MYREALM.DE,Sname=HTTP/lxdetstpksvc01.mydomain.de,EncPart=EncryptedData{Etype=23,Kvno=4,Cipher=binary[...  352 16728   KerberosV5.TicketType   
Authenticator   EncryptedData{Etype=23,Kvno=nothing,Cipher=binary[...   17080   2872    KerberosV5.EncryptedData    

So everything seems to be encytpe 23 (RC4 with HMAC). When I had a look at the code I found that sun.security.krb5.EncryptionKey which is used by KrbApReq (which throws the error in the stack above) is indeed not only comparing the enctype, but also the version. So I guess that is what must be wrong in my case. In the ticket above is Kvno=4 for EncryptedData and for Authenticator EncryptedData it is Kvno=nothing. Should these match?

How can I resolve this? Is this influenced by the generation of the keytab?

Banner answered 7/8, 2015 at 11:49 Comment(2)
The info on kvno at tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html looks promising. I will try that.Banner
Can I ask how did you view the ticket in the browser, I am having a similar problem and tried your solutions with no success. #60381212Mayolamayon
B
27

It turned out the error above resulted from two problems:

  1. The service principal in the spring configuration was wrong. It was [email protected], but HTTP/[email protected] is correct.

  2. The Kvno in the keytab was not identical with the Kvno stored in the active directory. As stated on https://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html Active Directory is raising the Kvno with every execution of ktpass. However I wasn't able to find the value (msDS-KeyVersionNumber) for it in our AD and could only grap it from the request.

Summarized the 'Cannot find key of appropriate type to decrypt ...' error can result from one of the following problems:

  1. The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).
  2. There is no key for the enctype the AD has send the ticket with (param /crypto from ktpass and set in the krb5.conf/permitted_enctypes+default_tkt_enctypes).
  3. The Kvno from the ticket is different then the Kvno in the keytab (param /kvno from ktpass).
  4. The path to the keytab is wrong (see answer from Xavier Portebois)
  5. The process does not have permissions to read the keytab (See comment from user7610)
Banner answered 13/8, 2015 at 8:44 Comment(1)
Actually, there are ways to peek at the msDSKeyVersionNumber attribute of the host in AD, see serverfault.com/questions/601270Often
L
11

We also got a Invalid argument (400) - Cannot find key of appropriate type to decrypt ... error.

This can simply be thrown if the path to the keytab is wrong (in our case, we forgot we got a docker volume mapping there).

So, be sure the keytab path is the right one, as this could fire this weird exception.

Lunette answered 26/6, 2017 at 15:11 Comment(1)
You'll also see this when your process doesn't have permission to read the keytab file.Kynthia
L
2

If you are using Spring Boot then please pay attention how you specify keytab file.

Note that the classpath: it will work when you run spring-boot:run However it wont when you run java -jar xyz.jar Because JAAS cant read it from classpath. So please prefer file: while specifying keytab file path. (This is typical case when you use docker to package and run your application)

Latrena answered 20/8, 2021 at 14:17 Comment(2)
Caught such issue, glad to see your answer and not to waste time!Burka
I had to change code: SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); ticketValidator.setServicePrincipal(principalName); //it works ticketValidator.setKeyTabLocation(new FileSystemResource(keytab)); //don't work in jar ticketValidator.setKeyTabLocation(new ClassPathResource(keytab));Ghiselin
T
1

This can also be thrown if your using Active Directory as the KDC and the keytab user is configured for a different encryption setting than your keytab is using. In my case AES 128 was configured and I was expecting AES 256. A simple change of the configuration within AD resolved the issue.

Tetracycline answered 17/7, 2017 at 12:36 Comment(2)
That's an example of the 2nd case in my answer - encytpe in the ticket and keytab don't match - isn't it?Banner
Sort of. What was not clear to me debugging this is that I should fix both the supported enctype in the AD computer AND the AD service user in question. Actually this post cleared things up a lot better than your answer: posts.specterops.io/kerberoasting-revisited-d434351bd4d1Often
D
0

In my case, the jaas config file of the server needed the parameter "storeKey" set to true.

Dee answered 24/7, 2018 at 16:6 Comment(0)
B
0

The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).

In my case they were the same, but param /princ was not correct. HTTP and domain part must be uppercase.

Correct example:

HTTP/[email protected]

Incorrect example:

http/[email protected]

Bound answered 28/6, 2019 at 13:39 Comment(0)
H
0

I've been struggling with this during 4 hours

the parameter "storeKey" set to true in the jaas file resolved the issue

Hekker answered 26/1, 2020 at 22:40 Comment(1)
this worked for me as well. And after debugging deep in the kerberos legacy source code, in fact this flag has the effect. wonder why someone downvoted this.Germanophile
L
0

I had the same error because the keytab file was generated with the wrong /crypto configuration.

Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400)
Cannot find key of appropriate type to decrypt AP-REQ - RC4 with HMAC)

Generate a new keytab file using /crypto ALL with the ktpass command:

ktpass /out "server.keytab" /crypto ALL /princ HTTP/server@REALM /mapuser KERBEROS_SERVICEUSER /pass PASSWORD /ptype KRB5_NT_PRINCIPAL

Replace HTTP/server@REALM, KERBEROS_SERVICEUSER and PASSWORD with according values.

Logarithmic answered 15/12, 2021 at 10:53 Comment(0)
N
0

In my case, I got the below log,

WARN SpnegoAuthenticationProcessingFilter:149 - Negotiate Header was invalid: Negotiate XXX
org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful
Caused by: java.security.PrivilegedActionException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)

and it was a permission issue.

The executing user didn't have the permission to read the keytab file, so I changed the permission with chmod command.

Navel answered 12/1, 2022 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.