ILya Cyclone
ILya Cyclone

Reputation: 954

Tomcat integrated Windows authentication: Client not found in Kerberos database

Trying to archieve integrated windows authentification on Tomcat 7 (Windows Server 2012) so that Intranet users won't need to enter their credentials when accessing my web application. Following tomcat manual: https://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html#Built-in_Tomcat_support

On a computer that runs tomcat. Checking network properties: Control Panel -> System

Full Computer Name: tomcatserver.global.lpl.top

Domain: global.lpl.top

gpresult /R

Group Policy was applied from: cdc.global.lpl.top

Domain Name: GLOBAL

A bit confused about those two different "domain" values. Is it "global.lpl.top" or "GLOBAL"?

There's a technical user that runs Tomcat: tomcatuser with password tomcatuserpassword.

I asked system administrator to call two commands:

setspn -A HTTP/tomcatserver.global.lpl.top tomcatuser

ktpass /out c:\tomcat.keytab /mapuser tomcatuser@GLOBAL /princ HTTP/tomcatserver.global.lpl.top@GLOBAL /pass tomcatuserpassword /kvno 0

Now I have tomcat.keytab file.

Let's verify.

1.

PS > setspn -l tomcatuser Registered ServicePrincipalNames for CN=tomcatuser,OU=Services,OU=Accounts,OU=...,OU=Delegated,DC=global,DC=lpl,DC=top: HTTP/tomcatserver.global.lpl.top

This seems right.

2.

jdk1.7.0_79\bin>klist -kt C:\tomcat.keytab

Key tab: C:\tomcat.keytab, 1 entry found.

[1] Service principal: HTTP/tomcatserver.global.lpl.top@GLOBAL KVNO: 0

Seems right.

3. Creating krb5.ini file:

[libdefaults]
default_realm = GLOBAL
default_keytab_name = FILE:C:\tomcat.keytab
default_tkt_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
default_tgs_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
forwardable=true

[realms]
GLOBAL = {
        kdc = cdc.global.lpl.top:88
}

[domain_realm]
global= GLOBAL
.global= GLOBAL
global.lpl.top= GLOBAL
.global.lpl.top= GLOBAL

Where did that ":88" in "kdc = cdc.global.lpl.top:88" come from? Should I leave it there?

According to http://www.itadmintools.com/2011/07/creating-kerberos-keytab-files.html placing krb5.ini file to c:\Windows\krb5.ini and use kinit:

jdk1.7.0_79\bin\kinit HTTP/tomcatserver.global.lpl.top@GLOBAL

Password for HTTP/tomcatserver.global.lpl.top@GLOBAL: tomcatserpassword Exception: krb_error 6 Client not found in Kerberos database (6) Client not foun d in Kerberos database KrbException: Client not found in Kerberos database (6) at sun.security.krb5.KrbAsRep.(KrbAsRep.java:76) at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319) at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364) at sun.security.krb5.internal.tools.Kinit.(Kinit.java:221) at sun.security.krb5.internal.tools.Kinit.main(Kinit.java:113) Caused by: KrbException: Identifier doesn't match expected value (906) at sun.security.krb5.internal.KDCRep.init(KDCRep.java:143) at sun.security.krb5.internal.ASRep.init(ASRep.java:65) at sun.security.krb5.internal.ASRep.(ASRep.java:60) at sun.security.krb5.KrbAsRep.(KrbAsRep.java:60) ... 4 more

Now something is bad. And trying with keytab file:

jdk1.7.0_79\bin>kinit -k -t C:\tomcat.keytab HTTP/tomcatserver.global.lpl.top@GLOBAL Exception: krb_error 6 Client not found in Kerberos database (6) Client not foun d in Kerberos database KrbException: Client not found in Kerberos database (6) at sun.security.krb5.KrbAsRep.(KrbAsRep.java:76) at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319) at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364) at sun.security.krb5.internal.tools.Kinit.(Kinit.java:221) at sun.security.krb5.internal.tools.Kinit.main(Kinit.java:113) Caused by: KrbException: Identifier doesn't match expected value (906) at sun.security.krb5.internal.KDCRep.init(KDCRep.java:143) at sun.security.krb5.internal.ASRep.init(ASRep.java:65) at sun.security.krb5.internal.ASRep.(ASRep.java:60) at sun.security.krb5.KrbAsRep.(KrbAsRep.java:60) ... 4 more

Doesn't feel right either.

Also tried to run a test application on tomcat with SPNEGO filter and got following exceptin in logs:

SEVERE: Exception starting filter SpnegoHttpFilter javax.servlet.ServletException: javax.security.auth.login.LoginException: Client not found in Kerberos database (6) Caused by: KrbException: Identifier doesn't match expected value (906)

I wouldn't mind seeing which identifiers does it compare - any ideas how to do it?

Yes, there are a lot of questions of same kind on stackoverflow nad most aren't answered. I read plenty of them and still can't see an error in my configs. Would be grateful for any help. Thanks.


Edit: I added Kerberos debug options to tomcat:

2017-08-03 12:51:33 Commons Daemon procrun stdout initialized
Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true
  ticketCache is null isInitiator true KeyTab is ///C:/tomcat7/conf/tomcat.keytab
  refreshKrb5Config is false principal is HTTP/tomcatserver.global.lpl.top@GLOBAL
  tryFirstPass is false useFirstPass is false storePass is false clearPass is false
>>> KeyTabInputStream, readName(): GLOBAL
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): tomcatserver.global.lpl.top
>>> KeyTab: load() entry length: 72; type: 23
Java config name: C:\tomcat7\conf\krb5.conf
Loaded from Java config
Added key: 23version: 0
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 23 17.
>>> KdcAccessibility: reset
Added key: 23version: 0
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 23 17.
default etypes for default_tkt_enctypes: 23 17.
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=cdc.global.lpl.top UDP:88, timeout=30000, number of retries =3, #bytes=150
>>> KDCCommunication: kdc=cdc.global.lpl.top UDP:88, timeout=30000,Attempt =1, #bytes=150
>>> KrbKdcReq send: #bytes read=84
>>> KdcAccessibility: remove cdc.global.lpl.top:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
     sTime is Thu Aug 03 12:51:40 MSK 2017 1501753900000
     suSec is 36472
     error code is 6
     error Message is Client not found in Kerberos database
     realm is GLOBAL
     sname is krbtgt/GLOBAL
     msgType is 30
        [Krb5LoginModule] authentication failed 
Client not found in Kerberos database (6)

Edit 2: I asked system admin to check tomcatuser in AD and its logon name is still "tomcatuser". Shouldn't it change to "HTTP/tomcatserver.global.lpl.top@GLOBAL"?

Upvotes: 1

Views: 2640

Answers (1)

T-Heron
T-Heron

Reputation: 5594

In your question, you've asked three questions. I'll tackle each one and explain how to solve this. It looks straightforward.

  1. "A bit confused about those two different "domain" values. Is it "global.lpl.top" or "GLOBAL"?"

Answer: It is global.lpl.top. This is the properly written, fully-qualified DNS Domain name referring to your Active Directory domain, which is also its DNS domain name, and which is also the Kerberos realm name when written in upper case (I will get to that in a second). Kerberos requires DNS in order to function properly, which means you cannot refer to your AD domain name in your config files or in the keytab as just "GLOBAL". As mentioned, your Kerberos realm would properly be written as GLOBAL.LPL.TOP and that is what should have been encoded into your keytab (I will talk about that in point #3). You used the shortened name "GLOBAL" throughout this effort, and I strongly suspect that is why Kerberos SSO is not working.

  1. "Where did that ":88" in "kdc = cdc.global.lpl.top:88" come from? Should I leave it there?"

Answer: You may leave it in there. Note, it will actually still work even if you remove it, since Kerberos always assumes port 88 its the standard. BUT NOTE: The actual problem in this file is that it needs to reflect the fully-qualified name GLOBAL.LPL.TOP - not the shortened name as we talked about in point #1.

  1. "I wouldn't mind seeing which identifiers does it compare - any ideas how to do it?"

Answer: Well, this would get down to actually solving the problem. To do this, after you fix the krb5.ini, you'll need to re-generate the keytab using the correct fully-qualified Kerberos realm name which is GLOBAL.LPL.TOP. Before doing that, remove the SPN from the tomcatuser AD account. So the two separate commands would look like this and run them in this order:

Run this first:

setspn -D HTTP/tomcatserver.global.lpl.top tomcatuser

Then run this afterwards.

ktpass /out c:\tomcat.keytab /mapuser [email protected] /princ
HTTP/[email protected] /pass
tomcatuserpassword /kvno 0

Note: Please see my article for more on how to properly create Kerberos keytabs. It looks like you are missing some additional parameters related to encryption, ptype and the /kvno switch is not necessary and may cause problems if you use it. To be sure, if I were you, I would run it like this:

ktpass -out c:\tomcat.keytab /mapUser [email protected] +rndPass /mapOp set +DumpSalt /crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL /princ HTTP/[email protected]

EDIT: (made in response to your edit which I just noticed)

"Edit 2: I asked system admin to check tomcatuser in AD and its logon name is still "tomcatuser". Shouldn't it change to "HTTP/tomcatserver.global.lpl.top@GLOBAL"?"

Answer: No - because the keytab generation command does this. Let the keytab generation command do that, not your system admin.

Upvotes: 1

Related Questions