5
votes

I'm trying to set-up Spring based security Web application in our environment. As described in http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/#setupwinkerberos

To confirm that everything set-up properly I'm trying to run Spring Boot Security sample application (built as described here: http://docs.spring.io/spring-security-kerberos/docs/1.0.1.RELEASE/reference/htmlsingle/#samples-sec-server-win-auth )

Here is our test environment under TEST domain:

Active Directory (referred as AD Server) Domain Controller, Windows 2008 R2 64-bit
Computer Name: adjavatest1
Full Computer Name: adjavatest1.test.company.info
User: TEST\administrator

Client PC, Windows 7
Computer Name: adjavatest2
Full Computer Name: adjavatest2.test.company.info
User: TEST\administrator

Application Server (referred as Web Server )
Computer Name: kpiq-dev
Full Computer Name: kpiq-dev.test.company.info
User: TEST\administrator

So far I have made following steps to configure environment and application

1) set SPN on AD Server

setspn -A HTTP/adjavatest1.test.company.info TEST\administrator

(many sources advice to create SPN "HTTP/adjavatest1" and "HOST/adjavatest1" - I've try that without any difference.)

2) verify SPN on AD Server

>setspn -L TEST\administrator
Registered ServicePrincipalNames for CN=Administrator,CN=Users,DC=test,DC=company,DC=info:
HTTP/adjavatest1.test.company.info

3) Map user/service and generate keytab file on AD Server

>ktpass -princ HTTP/[email protected] -pass pswd123 -mapuser TEST\Administrator -out .\ adjavatest1.HTTP.keytab -ptype KRB5_NT_PRINCIPAL -crypto All
Targeting domain controller:  adjavatest1.test.company.info
Using legacy password setting method
Successfully mapped HTTP/adjavatest1.test.company.info to Administrator.
Key created.
Key created.
Key created.
Key created.
Key created.
Output keytab to .\ adjavatest1.HTTP.keytab:
Keytab version: 0x502
keysize 85 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x1 (DES-CBC-CRC) keylength 8 (0x6da81379831f37ad)
keysize 85 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x3 (DES-CBC-MD5) keylength 8 (0x6da81379831f37ad)
keysize 93 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x17 (RC4-HMAC ) keylength 16 (0xe32edb70a8df744e3b0f87ea7ff515f7)
keysize 109 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x12 (AES256-SHA1) keylength 32 (0xf744e212c2e48e34c815364c0b5290a68b37b6c65a7cd0befcbcc2625e3e6c79)
keysize 93 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 5 etype 0x11 (AES128-SHA1) keylength 16 (0x20f3474a818d4d326136449a8a660e2c)

4) copy keytab file on to Web Server in C;\SpringSSO directory

5) Validate keytab on Web Server
With kinit from MIT kerberos tool c:\SpringSSO>kinit -V -k -t adjavatest1.HTTP.keytab HTTP/[email protected] Using existing cache: Initial default ccache Using principal: HTTP/[email protected] Using keytab: adjavatest1.HTTP.keytab Authenticated to Kerberos v5 With kinit from jdk c:\SpringSSO>kinit -k -t adjavatest1.HTTP.keytab HTTP/[email protected] New ticket is stored in cache file C:\Users\administrator.TEST\krb5cc_administrator

6) Install 'Kerberos and Unlimited Strength Policy' in jre/lib/security on Web Server in both locations:

c:\Program Files\Java\jre1.8.0_65\lib\security\
c:\Program Files\Java\jdk1.8.0_65\jre\lib\security\

7) Check windows registry on Web Server :

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\
Value Name: allowtgtsessionkey
Value: 0x1

8) build spring-security-kerberos-samples\sec-server-win-auth application taken from https://github.com/spring-projects/spring-security-kerberos/tree/master/spring-security-kerberos-samples with config properties in application.yml

server:
    port: 80
app:
    ad-domain: TEST.COMPANY.INFO
    ad-server: ldap://ADJAVATEST1.TEST.COMPANY.INFO/
    service-principal: HTTP/[email protected]
    keytab-location:  adjavatest1.HTTP.keytab
    ldap-search-base: DC=TEST,DC=COMPANY,DC=INFO
    ldap-search-filter: "(| (userPrincipalName={0}) (sAMAccountName={0}))"

9) deploy Spring boot application to Web Server in C:\SpringSSO directory

10) Start web application on Web Server c:\SpringSSO>java -Dsun.security.krb5.debug=true -Djava.security.krb5.conf=.\krb5.conf -jar sec-server-win-auth-1.0.2.BUILD-SNAPSHOT.jar

Kerberos configuration in krb5.conf (I've try different enctypes and "arcfour-hmac-md5" is just last experiment)

[libdefaults]
 default_realm = TEST.COMPANY.INFO
 permitted_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 default_tgs_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 default_tkt_enctypes = arcfour-hmac-md5 rc4-hmac aes256-cts aes128-cts des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 dns_lookup_kdc = true
 dns_lookup_realm = false

[realms]
 TEST.COMPANY.INFO = {
     kdc =  ADJAVATEST1.TEST.COMPANY.INFO
     admin_server =  ADJAVATEST1.TEST.COMPANY.INFO
     master_kdc =  ADJAVATEST1.TEST.COMPANY.INFO
     default_domain = TEST.COMPANY.INFO
 }

[domain_realm]
 .TEST.COMPANY.INFO = TEST.COMPANY.INFO
 TEST.COMPANY.INFO = TEST.COMPANY.INFO

11) In IE browser on Client add path *.test.company.info to IE browser as intranet pattern point browser to http:// kpiq-dev.test.company.info/hello

12) Point browser to http:// kpiq-dev.test.company.info/hello

13) Check the log on Web Server indicating that server can't encode

2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Received Negotiate Header for request http:// kpiq-dev.test.company.info/hello: Negotiate YIIH ...trucated... H4qgvsM
2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider
2015-12-17 08:55:35.893 DEBUG 1876 --- [p-nio-80-exec-3] .a.KerberosServiceAuthenticationProvider : Try to validate Kerberos Token
Found KeyTab c:\SpringSSO\ adjavatest1.HTTP.keytab for HTTP/[email protected]
Found KeyTab c:\SpringSSO\ adjavatest1.HTTP.keytab for HTTP/[email protected]
Entered Krb5Context.acceptSecContext with state=STATE_NEW
Java config name: .\krb5.conf
Loaded from Java config
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 85; type: 1
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 85; type: 3
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 93; type: 23
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 109; type: 18
>>> KeyTabInputStream, readName(): TEST.COMPANY.INFO
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName():  adjavatest1.test.company.info
>>> KeyTab: load() entry length: 93; type: 17
Looking for keys for: HTTP/[email protected]
Added key: 17version: 5
Added key: 18version: 5
Added key: 23version: 5
Found unsupported keytype (3) for HTTP/[email protected]
Found unsupported keytype (1) for HTTP/[email protected]
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
2015-12-17 08:55:36.236  WARN 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIIHNAYGKwYBBQU ...trucated... dH4qgvsM

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:71)
            at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64)
            at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
            at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
            at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:446)
            at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145)
            at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
...trucated...
            at java.lang.Thread.run(Unknown Source)
Caused by: java.security.PrivilegedActionException: null
            at java.security.AccessController.doPrivileged(Native Method)
            at javax.security.auth.Subject.doAs(Unknown Source)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:68)
            ... 45 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)
            at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(Unknown Source)
            at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:170)
            at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:153)
            ... 48 common frames omitted
Caused by: sun.security.krb5.KrbCryptoException: Checksum failed
            at sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Unknown Source)
            at sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Unknown Source)
            at sun.security.krb5.EncryptedData.decrypt(Unknown Source)
            at sun.security.krb5.KrbApReq.authenticate(Unknown Source)
            at sun.security.krb5.KrbApReq.<init>(Unknown Source)
            at sun.security.jgss.krb5.InitSecContextToken.<init>(Unknown Source)
            ... 57 common frames omitted
Caused by: java.security.GeneralSecurityException: Checksum failed
            at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decryptCTS(Unknown Source)
            at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decrypt(Unknown Source)
            at sun.security.krb5.internal.crypto.Aes256.decrypt(Unknown Source)
            ... 63 common frames omitted

Why security try to encript Aes256CtsHmacSha1EType, instead of rc4-hmac?
Any suggestion what I can try next?

Thank you in advance.

2
Maybe try to simplify things by just using one enctype, e.g RC4-HMAC. Generate the keytab with -crypto RC4-HMAC-NT and *__enctypes=rc4-hmac in your krb5.conf?Gunnar Kiesel
With keytab file generated for only RC4-HMAC-NT, I could not run kinit (from MIT). kinit: Generic preauthentication failure while getting initial credentialsAlexeiP
Did you try to run the app with that keytab anyway? It's a pitty kinit is not working, but it's not required for the solution... the supported encryptions may be different. AD and Spring/Java both support RC4-HMAC.Gunnar Kiesel

2 Answers

0
votes

Two possible errors :

1) krb5.conf not loaded properly

2) Service principal not configured properly

Solution for 1st :

  • in point 8) add app : kerberos-conf: /home/xyz/krb5.conf in application.yaml
  • create additional class in spring security project

        @Configuration
        public class KerberosGlobalConfig {
    
            @Value("${app.kerberos-conf}")
            private String kerberosGlobalConfPath;
    
            @Bean
            public GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig() {
                GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig = new 
                GlobalSunJaasKerberosConfig();
                //TODO remove hardcoding
                globalSunJaasKerberosConfig.setDebug(true);
                globalSunJaasKerberosConfig.setKrbConfLocation(kerberosGlobalConfPath);
                return globalSunJaasKerberosConfig;
            }
    
        } 
    
0
votes

The reason it is failing is because in the ticket validator, you are trying to validate a NTLM token, not a kerberos ticket. This line shows you this in your log:

>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType 2015-12-17 08:55:36.236 WARN 1876 --- [p-nio-80-exec-3] w.a.SpnegoAuthenticationProcessingFilter : Negotiate Header was invalid: Negotiate YIIHNAYGKwYBBQU ...trucated... dH4qgvsM

Headers starting with YII are NTLM, which means that your initial validation fails to get a Kerberos ticket, so the browser tries the next protocol in order of priority, in this case NTLM.

It looks like your SPN is correct, there are some things that I would suggest checking with respect to the account and the keytab file. Make sure that the user account you are mapping to the SPN and using to generate the keytab has the proper options selected in the active directory user management, that is, to allow for 126 and 256 bit encryption with Kerberos, and to allow the account to be used for kerberos delegation.

Also, this link is important to read: https://www.chromium.org/developers/design-documents/http-authentication

This link outlines how Chrome constructs the SPN from the request URL to do SPNEGO/SSO. Basically, it is possible that you might have to set up a forward zone in DNS to help with the issue that you are experiencing. Chrome browser gets settings from IE, so setting intranet settings in IE should handle that, but with respect to SPN resolution, it will try to resolve the value in the URL to a CNAME and then to an A entry in DNS. This could cause the behavior you are seeing. Normally, when you are seeing an NTLM token sent instead of a Kerberos ticket, it can be traced to the browser attempting to use the wrong SPN to query and obtain a Kerberos ticket. If you can get the SPN that is constructed from the browser to be in sync with the one that you are mapping to the service account that you are using, you should be good to go.