Reputation: 954
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
Reputation: 5594
In your question, you've asked three questions. I'll tackle each one and explain how to solve this. It looks straightforward.
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.
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.
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