JDK-6587676 : Krb5LoginModule failure if useTicketCache=true on Vista
  • Type: Bug
  • Component: security-libs
  • Sub-Component: org.ietf.jgss:krb5
  • Affected Version: 6,7
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows,windows_vista
  • CPU: x86
  • Submitted: 2007-08-01
  • Updated: 2010-11-04
  • Resolved: 2009-04-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b57Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Any Java version >= 1.5, 1.6 update 2 included

ADDITIONAL OS VERSION INFORMATION :
Windows Vista 6.0.6000

EXTRA RELEVANT SYSTEM CONFIGURATION :
KDC = Windows 2003 Server


A DESCRIPTION OF THE PROBLEM :
  Description
=========
Get a KRB5KRB_AP_ERR_BAD_INTEGRITY (31) on Vista (GSS client) while running totorial http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html.

with the following JAAS configuration:

com.sun.security.jgss.initiate {
  com.sun.security.auth.module.Krb5LoginModule required debug=true useTicketCache=true doNotPrompt=true renewTGT=true;
};

com.sun.security.jgss.accept {
  com.sun.security.auth.module.Krb5LoginModule required storeKey=true debug=true doNotPrompt=true useKeyTab=true keyTab=s-j-wcbz0115.keytab principal="HTTP/###@###.###" useTicketCache=true isInitiator=false;
};

Other infos
=========
1) On Vista, allowtgtsessionkey has been set.
2) SampleClient on Vista, SampleServer on W2K. Bringing the SampleClient  on W2K with the same config WORKS!
3) Happen with and Java version >= 1.5
4) Initializing the cache with kinit makes the SampleClient on Vista to work as expected!!!!!

The Krb5LoginModule when configured with useTicketCache=true uses the Windows LSA API to get the Kerberos TGT.
In Vindows Vista introduces some more restrictions on LSA API, here is the mail from Microsoft support:

  To answer your question, in looking at the Vista source I can see that the AllowTgtSessionKey registry key is still read from under Lsa\Kerberos\Parameters. It should be a DWORD value.

However comparing the XP and Vista Sources where AllowTgtSessionKey is used I can see that in the case of Vista additional checking is done which relate to whether the caller (user) is using an LUA (Least User Access) security token which would be the case if the operation was triggered by a "normal" logged on user. This would prevent access.


It seams that using Windows SSPI instead on LSA should work


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the SampleClient and SampleServer with the following bcsLogin.conf (configured for your Kerberos SPN)

/**
* Used by the client
*/
com.sun.security.jgss.initiate {
  com.sun.security.auth.module.Krb5LoginModule required debug=true useTicketCache=true doNotPrompt=true renewTGT=true;
};

/**
* Used by the server
*/
com.sun.security.jgss.accept {
  com.sun.security.auth.module.Krb5LoginModule required storeKey=true debug=true doNotPrompt=true useKeyTab=true keyTab=s-j-wcbz0115.keytab principal="HTTP/###@###.###" useTicketCache=true isInitiator=false;
};

SampleClient on Vista!


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Leam less SSO Authentication
ACTUAL -
client:
     [java] Connected to server wcbz0115/10.168.24.84
     [java] Debug is  true storeKey false useTicketCache true useKeyTab false do
NotPrompt true ticketCache is null KeyTab is null refreshKrb5Config is false pri
ncipal is null tryFirstPass is false useFirstPass is false storePass is false cl
earPass is false
     [java] Acquire TGT from Cache
     [java] Ticket could not be renewed : This ticket is not renewable
     [java] Principal is null
     [java] null credentials from Ticket Cache
     [java]             [Krb5LoginModule] authentication failed
     [java] Unable to obtain Princpal Name for authentication
     [java] GSSException: No valid credentials provided (Mechanism level: Attemp
t to obtain new INITIATE credentials failed! (null))
     [java]     at sun.security.jgss.krb5.Krb5InitCredential.getTgtFromSubject(K
rb5InitCredential.java:336)
     [java]     at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5Ini
tCredential.java:131)
     [java]     at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(K
rb5MechFactory.java:72)
     [java]     at sun.security.jgss.GSSManagerImpl.getCredentialElement(GSSMana
gerImpl.java:149)
     [java]     at sun.security.jgss.GSSCredentialImpl.add(GSSCredentialImpl.jav
a:389)
     [java]     at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.
java:60)
     [java]     at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.
java:37)
     [java]     at sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerI
mpl.java:96)
     [java]     at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImp
l.java:178)
     [java]     at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImp
l.java:158)
     [java]     at SampleClient.main(Unknown Source)
     [java] Caused by: javax.security.auth.login.LoginException: Unable to obtai
n Princpal Name for authentication
     [java]     at com.sun.security.auth.module.Krb5LoginModule.promptForName(Kr
b5LoginModule.java:689)
     [java]     at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentic
ation(Krb5LoginModule.java:599)
     [java]     at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginM
odule.java:512)
     [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcces
sorImpl.java:39)
     [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMet
hodAccessorImpl.java:25)
     [java]     at java.lang.reflect.Method.invoke(Method.java:585)
     [java]     at javax.security.auth.login.LoginContext.invoke(LoginContext.ja
va:769)
     [java]     at javax.security.auth.login.LoginContext.access$000(LoginContex
t.java:186)
     [java]     at javax.security.auth.login.LoginContext$4.run(LoginContext.jav
a:683)
     [java]     at java.security.AccessController.doPrivileged(Native Method)
     [java]     at javax.security.auth.login.LoginContext.invokePriv(LoginContex
t.java:680)
     [java]     at javax.security.auth.login.LoginContext.login(LoginContext.jav
a:579)
     [java]     at sun.security.jgss.LoginUtility.login(LoginUtility.java:74)
     [java]     at sun.security.jgss.krb5.Krb5Util.getTicketFromSubject(Krb5Util
.java:137)
     [java]     at sun.security.jgss.krb5.Krb5InitCredential$1.run(Krb5InitCrede
ntial.java:331)
     [java]     at java.security.AccessController.doPrivileged(Native Method)
     [java]     at sun.security.jgss.krb5.Krb5InitCredential.getTgtFromSubject(K
rb5InitCredential.java:328)
     [java]     ... 10 more
     [java] Exception in thread "main" GSSException: No valid credentials provid
ed
     [java]     at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.
java:69)
     [java]     at sun.security.jgss.GSSCredentialImpl.<init>(GSSCredentialImpl.
java:37)
     [java]     at sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerI
mpl.java:96)
     [java]     at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImp
l.java:178)
     [java]     at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImp
l.java:158)
     [java]     at SampleClient.main(Unknown Source)

BUILD FAILED
C:\WORK\GSS-API\build.xml:38: Java returned: 1

ERROR MESSAGES/STACK TRACES THAT OCCUR :
See actual result. With ethereal on the vista client:

No.     Time        Source                Destination           Protocol Info
   1713 6.357615    138.191.82.26         10.168.24.44          KRB5     KRB Error: KRB5KRB_AP_ERR_BAD_INTEGRITY

Frame 1713 (151 bytes on wire, 151 bytes captured)
Ethernet II, Src: Cisco_94:db:ff (00:0a:41:94:db:ff), Dst: 10.168.24.44 (00:14:c2:0c:41:09)
Internet Protocol, Src: 138.191.82.26 (138.191.82.26), Dst: 10.168.24.44 (10.168.24.44)
Transmission Control Protocol, Src Port: kerberos (88), Dst Port: 49289 (49289), Seq: 1, Ack: 4091, Len: 97
Kerberos KRB-ERROR
    Record Mark: 93 bytes
        0... .... .... .... .... .... .... .... = Reserved: Not set
        .000 0000 0000 0000 0000 0000 0101 1101 = Record Length: 93
    Pvno: 5
    MSG Type: KRB-ERROR (30)
    stime: 2007-06-19 09:25:27 (Z)
    susec: 856008
    error_code: KRB5KRB_AP_ERR_BAD_INTEGRITY (31)
    Realm: PNET.CH
    Server Name (Principal): HTTP/wcbz0115.pnet.ch
        Name-type: Principal (1)
        Name: HTTP
        Name: wcbz0115.pnet.ch


REPRODUCIBILITY :
This bug can be reproduced always.

Comments
EVALUATION No regression tests since a Windows AD setup is needed.
10-04-2009

EVALUATION Without a change inside Windows, there's nothing I can really do here. The fix actually deals with the problem in another way: For a long time, we return the TGT ccache in LSA even if the session key is zero. However, since the TGT is always used to acquire a service key, this *always* leads to an error. So I decide to never return such a TGT: If the session key is zero, we act as if there's no ccache in LSA, and fallback to other ways to get the TGT (say, user/pass and a AS-REQ). I add the zero check after line 970. Another change in the code fix is DEBUG output. The -Dsun.security.k5b5.debug command line option now applies to the native debug info also.
10-04-2009

EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/897b2d42995a
10-04-2009

EVALUATION Should acquire the service ticket through Win API directly.
18-12-2007

EVALUATION I've tried on a Windows Vista Ultimate 6.0.6000 with a Windows 2003 Server using JDK 5.0, 6, 7, login with an Active Directory normal user (member of Domain Users only), and I can get the LSA ticket. Can you please try this tiny program on the Vista client? import com.sun.security.auth.module.Krb5LoginModule; import java.util.HashMap; import java.util.Map; import javax.security.auth.Subject; public class Temp3 { public static void main(String[] args) throws Exception { System.setProperty("sun.security.krb5.debug", "true"); Subject subject = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); Map <String, String> map = new HashMap <String, String>(); map.put("useTicketCache", "true"); map.put("doNotPrompt", "true"); map.put("renewTGT", "true"); krb5.initialize(subject, null, null, map); krb5.login(); krb5.commit(); System.out.println(subject); } } Looking at the debug output, it seems that the LSA ticket is still retrievable, but since it's not renewable, it does not match the client's request. Have you config the Active Directiry user account info so that its TGT is always tagged "not renewable"?
02-08-2007