Saturday, June 18, 2011

Some help with Kerberos SSO

Oracle Java SE 1.6 has an inbuild HTTP client that now supports SPNEGO Negotiate HTTP authentication scheme, with the Kerberos as well as NTLM mechanism. We can harness this client and use it in place of Internet Explorer (IE) to troubleshoot Kerberos SSO issues against Weblogic instance. This makes sense as one faces great challenge in making IE run in debug mode so that one can see what is going on behind the scene. Using JSE HTTP client, we can enable debug flags and see lot of "relevant" information easily.


Here you go!

1. We will code a simple JAVA class that will use JSE 1.6 HTTP API (to turn itself into an HTTP client). Here is the sample class:

1:  import java.io.BufferedReader;
  
2:  import java.io.InputStream;
  
3:  import java.io.InputStreamReader;
  
4:  import java.net.URL;
  
5:  import java.net.CookieHandler;
  
6:  import java.net.CookieManager;
  
7:  import java.net.CookiePolicy;
  
8:  public class JSEHTTPClient{
  
9:     public static void main(String[] args) throws Exception {
  
10:      try {               
  
11:                 if(CookieHandler.getDefault() == null)
  
12:                      CookieHandler.setDefault(new CookieManager());
  
13:                 ((CookieManager)CookieHandler.getDefault()).setCookiePolicy(CookiePolicy.ACCEPT_ALL);
  
14:                 URL url = new URL(args[0]);
  
15:                 System.out.println(url);
  
16:                 InputStream ins = url.openConnection().getInputStream();
  
17:                 BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
  
18:                 String str;
  
19:                 while((str = reader.readLine()) != null)
  
20:                   System.out.println(str);
  
21:            } catch (Exception e) {
  
22:                 e.printStackTrace();
  
23:            }
  
24:    }
  
25:  }
  

  
There is virtually no change that you need to make in this code. Create a directory "C:\client" and place the above code into "C:\client\JSEHTTPClient.java"


2. set JAVA_HOME environment variable:

         C:\client>set JAVA_HOME="C:\Program Files\Java\jdk1.6.0_23"

3. Compile the source file:

         C:\client>%JAVA_HOME%\bin\javac JSEHTTPClient.java

4. We need a client keytab file that HTTP client will use to talk to KDC. Before creating the keytab file, we have to be sure we have the right username and password for the account. The client keytab can be created using "ktab.exe" on client machine:

         C:\client>%JAVA_HOME%\bin\ktab.exe -a user123 mypassword1 -k client.keytab
         Done!
         Service key for user123 is saved in client.keytab

  • "user123" is the username
  • "mypassword1" is the password for above user


5. Create a configuration file "krbf.conf" file for the client and place it inside "C:\client". It is from here that client will pick up data pertaining to KDC.

 
[libdefaults]
default_realm = LOCALDOMAIN.COM
default_tkt_enctypes = des-cbc-md5
default_tgs_enctypes = des-cbc-md5
ticket_lifetime = 2600


[realms]
LOCALDOMAIN.COM = {
kdc = 192.169.0.4
admin_server = win2003sp2
default_domain = LOCALDOMAIN.COM
}


[domain_realm]
.localdomain.com = LOCALDOMAIN.COM


[appdefaults]
autologin = true
forward = true
forwardable = true
encrypt = true

6. Create a JAAS login configuration file "login.conf" and place it inside "C:\client":

com.sun.security.jgss.krb5.login {
com.sun.security.auth.module.Krb5LoginModule required principal="user123" useKeyTab=true keyTab=client.keytab storeKey=true debug=true;};


com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required principal="user123" useKeyTab=true keyTab=client.keytab storeKey=true debug=true;};


com.sun.security.jgss.krb5.accept {
com.sun.security.auth.module.Krb5LoginModule required principal="user123" useKeyTab=true keyTab=client.keytab storeKey=true debug=true;};

7. And now finally we are ready to run the client:
C:\client>%JAVA_HOME%\bin\java -Djava.security.krb5.conf=krb5.conf -Djava.security.auth.login.config=login.conf -Djavax.security.auth.useSubjectCredsOnly=false -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true -Dhttp.auth.preference=spnego JSEHTTPClient http://mac5.localdomain.com/examplesWebApp/restricted/restricted.jsp

Note that we I have supplied the resource URL as a command line argument to the JAVA program
And finally that debug output will follow; Ah! what a sight!
http://mac5.mac5.localdomain.com/examplesWebApp/restricted/restricted.jsp
Entered SpNego.initSecContext with state=STATE_NEW
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt fal
se ticketCache is null isInitiator true KeyTab is client.keytab refreshKrb5Confi
g is false principal is user123 tryFirstPass is false useFirstPass is fals
e storePass is false clearPass is false
>>> KeyTabInputStream, readName(): LOCALDOMAIN.COM
>>> KeyTabInputStream, readName(): user123
>>> KeyTab: load() entry length: 49; type: 3
Added key: 3version: 1
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 3.
0: EncryptionKey: keyType=3 kvno=1 keyValue (hex dump)=
0000: 86 C4 92 25 64 C7 B3 C8


principal's key obtained from the keytab
Acquire TGT using AS Exchange
default etypes for default_tkt_enctypes: 3.
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=192.169.0.4 UDP:88, timeout=30000, number of retries =3,
#bytes=136
>>> KDCCommunication: kdc=192.169.0.4 UDP:88, timeout=30000,Attempt =1, #bytes=1
36
>>> KrbKdcReq send: #bytes read=166
>>> KrbKdcReq send: #bytes read=166
>>> KdcAccessibility: remove 192.169.0.4
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is Sat Jun 18 10:24:42 MDT 2011 1308414282000
suSec is 381281
error code is 25
error Message is Additional pre-authentication required
realm is LOCALDOMAIN.COM
sname is krbtgt/LOCALDOMAIN.COM
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 3
>>>Pre-Authentication Data:
PA-DATA type = 2
PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
PA-DATA type = 15
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ
Updated salt from pre-auth = LOCALDOMAIN.COMuser123
>>>KrbAsReq salt is LOCALDOMAIN.COMuser123
Pre-Authenticaton: find key for etype = 3
AS-REQ: Add PA_ENC_TIMESTAMP now
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=192.169.0.4 UDP:88, timeout=30000, number of retries =3,
#bytes=223
>>> KDCCommunication: kdc=192.169.0.4 UDP:88, timeout=30000,Attempt =1, #bytes=2
23
>>> KrbKdcReq send: #bytes read=1282
>>> KrbKdcReq send: #bytes read=1282
>>> KdcAccessibility: remove 192.169.0.4
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
>>> KrbAsRep cons in KrbAsReq.getReply user123
principal is user123@LOCALDOMAIN.COM
EncryptionKey: keyType=3 keyBytes (hex dump)=0000: 86 C4 92 25 64 C7 B3 C8
Added server's keyKerberos Principal user123@LOCALDOMAIN.COMKey Version 1key Enc
ryptionKey: keyType=3 keyBytes (hex dump)=
0000: 86 C4 92 25 64 C7 B3 C8


[Krb5LoginModule] added Krb5Principal user123@LOCALDOMAIN.COM t
o Subject
Commit Succeeded


Found ticket for user123@LOCALDOMAIN.COM to go to krbtgt/LOCALDOMAIN.COM@LOCALDOMAIN.COM exp
iring on Sat Jun 18 20:24:42 MDT 2011
Entered Krb5Context.initSecContext with state=STATE_NEW
Service ticket not found in the subject
>>> Credentials acquireServiceCreds: same realm
default etypes for default_tgs_enctypes: 3.
>>> CksumType: sun.security.krb5.internal.crypto.RsaMd5CksumType
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
>>> KrbKdcReq send: kdc=192.169.0.4 UDP:88, timeout=30000, number of retries =3,
#bytes=1258
>>> KDCCommunication: kdc=192.169.0.4 UDP:88, timeout=30000,Attempt =1, #bytes=1
258
>>> KrbKdcReq send: #bytes read=1231
>>> KrbKdcReq send: #bytes read=1231
>>> KdcAccessibility: remove 192.169.0.4
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
>>> KrbApReq: APOptions are 00100000 00000000 00000000 00000000
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType
Krb5Context setting mySeqNumber to: 317455858
Created InitSecContextToken:
0000: 01 00 6E 82 04 8B 30 82 04 87 A0 03 02 01 05 A1 ..n...0.........
0010: 03 02 01 0E A2 07 03 05 00 20 00 00 00 A3 82 03 ......... ......
0020: AF 61 82 03 AB 30 82 03 A7 A0 03 02 01 05 A1 0B .a...0..........
.
.
.
.
0440: 49 BD 12 D2 53 DE E2 EB F2 3F EA 7E BA FA 98 91 I...S....?......
0450: C7 14 2F C7 4B 06 43 4C 71 48 46 57 FD D2 F7 63 ../.K.CLqHFW...c
0460: 4D 22 37 00 94 91 74 94 B4 25 62 B3 56 92 16 69 M"7...t..%b.V..i
0470: B9 21 70 97 8E 4E 22 57 76 70 71 DE D8 21 E7 F0 .!p..N"Wvpq..!..
0480: 25 47 19 5A 75 49 44 8B 0F 29 CD D6 5C 7E 52 FA %G.ZuID..)..\.R.
0490: C5 .


SpNegoContext.initSecContext: sending token of type = SPNEGO NegTokenInit
SNegoContext.initSecContext: sending token = a0 82 04 .
.
.
.
.
.
.
f0 25 47 19 5a 75 49 44 8b
0f 29 cd d6 5c 7e 52 fa c5
<html>
<head>
<h2>restricted.jsp</h2>
</head>

</html>
 

1 comment:

  1. hi..
    i tried ur code for spnego . bt 401-Unathorized error is thrown . Any suggestion?

    ReplyDelete