web-dev-qa-db-fra.com

Kerberos - Impossible de trouver la clé du type approprié pour déchiffrer AP REP - RC4 avec HMAC

J'essaie d'installer SSO pour une application Web Java à l'aide de Kerberos/SpNego. J'utilise:

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

Après avoir surmonté le problème décrit dans Comment configurer Kerberos sur un serveur Tomcat/Linux? , je suis maintenant coincé avec l'erreur suivante:

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

Cependant, il semble que la clé devrait être là, car au démarrage de l'application, j'ai eu le débogage suivant:

  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

Donc enctype 23 = RC4 avec HMAC est le type de l'entrée KeyTab et le type enctype par défaut . Je peux également voir que le navigateur envoie un jeton avec ce type enctype (j'ai supprimé la partie binaire de ce qui suit):

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    

Donc tout semble être encytpe 23 (RC4 avec HMAC). Lorsque j’ai jeté un coup d’œil au code, j’ai trouvé que Sun.security.krb5.EncryptionKey, utilisé par KrbApReq (qui renvoie l’erreur dans la pile ci-dessus), est en fait non seulement une comparaison du type d’enct, mais également de la version. Donc, je suppose que c'est ce qui doit être faux dans mon cas. Dans le ticket ci-dessus, Kvno = 4 pour EncryptedData et pour Authenticator EncryptedData, il s'agit de Kvno = rien. Ceux-ci devraient-ils correspondre?

Comment puis-je résoudre ça? Est-ce que cela est influencé par la génération du keytab?

13
Gunnar Kiesel

Il s’est avéré que l’erreur ci-dessus résultait de deux problèmes:

  1. Le service principal dans la configuration de printemps était faux. C'é[email protected], mais HTTP/[email protected] est correct.

  2. Le Kvno dans le clavier n'était pas identique au Kvno stocké dans le Active Directory. Comme indiqué à la page suivante, __. https://Tomcat.Apache.org/Tomcat-7.0-doc/windows-auth-howto.html Active Directory élève le Kvno à chaque exécution de ktpass ..__ Cependant, je n'ai pas pu trouver la valeur (msDS-KeyVersionNumber) pourit dans notre AD et je ne pouvais le saisir qu'à partir de la requête.

Résumé de l'erreur "Impossible de trouver la clé du type approprié à déchiffrer ..." peut résulter de l'un des problèmes suivants:

  1. Le prinicpal de service dans la configuration de sécurité du ressort n’est pas identique à celui du keytab (param/princ de ktpass). 
  2. Il n’existe pas de clé pour le type avec lequel l’AD a envoyé le ticket (param/crypto de ktpass et défini dans krb5.conf/allowed_enctypes + default_tkt_enctypes).
  3. Le Kvno du ticket est différent du Kvno dans le keytab (param/kvno de ktpass).
  4. Le chemin d'accès au clavier est incorrect (voir la réponse de Xavier Portebois)
  5. Le processus n'a pas l'autorisation de lire le fichier de clés (voir le commentaire de user7610
17
Gunnar Kiesel

Nous avons également eu une erreur Invalid argument (400) - Cannot find key of appropriate type to decrypt ....

Cela peut simplement être jeté si le chemin d'accès au keytab est faux (dans notre cas, nous avons oublié que nous avions un mappage de volume dans le menu fixe).

Assurez-vous donc que le chemin d'accès au clavier est le bon chemin, car cela pourrait déclencher cette exception bizarre.

4
Xavier Portebois

Cela peut également être levé si vous utilisez Active Directory en tant que KDC et l'utilisateur keytab est configuré pour un paramètre de cryptage différent de celui utilisé par votre keytab. Dans mon cas, AES 128 a été configuré et je m'attendais à AES 256. Un simple changement de configuration dans AD a résolu le problème.

0
KWoodie