-
Bug
-
Resolution: Incomplete
-
P3
-
None
-
7u76
-
x86
-
windows_8
FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600]
A DESCRIPTION OF THE PROBLEM :
Up to JDK6, Krb5LoginModule has been working fine without any default realm configured, as long as the provided principal name includes a realm. In JDK7 (and supposedly in JDK8 also), it fails with saying "Cannot locate default realm."
The error occurs at the point where it initializes a PrincipalName for krbtgt service principal before accessing the AS. It uses an overloaded constructor for PrincipalName which initializes its realm with the default realm. In JDK6, krb5.Config.getDefaultRealm() silently returned null if no default realm is set; in JDK7, it throws KrbException. The change occurred with the commit for implementing the following RFE.
JDK-6785456 : Read Kerberos setting from Windows environment variables
Since the realm name for this service principal is never used, it is no use setting it to the default realm or anything. So I suppose it should use another overloaded constructor for PrincipalName which leaves the realm part uninitialized.
KrbAsReq(...)
if (sname == null) {
sname = new PrincipalName("krbtgt" +
PrincipalName.NAME_COMPONENT_SEPARATOR +
cname.getRealmAsString(),
PrincipalName.KRB_NT_SRV_INST);
}
->
if (sname == null) {
String[] snameParts = new String[] { "krbtgt", cname.getRealmAsString() };
sname = new PrincipalName(snameParts, PrincipalName.KRB_NT_SRV_INST);
}
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please change the domain name / the user name / the password according to your test environment.
* Create krb.conf as follows:
[realms]
MYDOMAIN.LOCAL = {
kdc = mydc.mydomain.local:88
}
* Create login.conf as follows:
Krb5Login {
com.sun.security.auth.module.Krb5LoginModule required debug=true;
};
* Reset USERDNSDOMAIN environment variable if set (since you are logging in as a domain user)
set USERDNSDOMAIN=
Compile and run the test case as follows:
java -Djava.security.krb5.conf=krb5.conf -Djava.security.auth.login.config=login.conf TestAuth
Note that as long as you have ANYTHING set to default_realm in krb5.conf or USERDNSDOMAIN, it would pass.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
As you get with JDK6, the login attempt shoud succeed.
Debug is true storeKey false useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
[Krb5LoginModule] user entered username: DomUser01@MYDOMAIN.LOCAL
Acquire TGT using AS Exchange
principal is DomUser01@MYDOMAIN.LOCAL
EncryptionKey: keyType=3 keyBytes (hex dump)=0000: 73 F4 3D 23 BF 75 83 A8
EncryptionKey: keyType=1 keyBytes (hex dump)=0000: 73 F4 3D 23 BF 75 83 A8
EncryptionKey: keyType=23 keyBytes (hex dump)=0000: D9 DE A9 F7 8F 03 ED A5 D0 EE D3 7B FD 2B 02 25 .............+.%
EncryptionKey: keyType=16 keyBytes (hex dump)=0000: 9E 2F FD 0E D3 92 E9 FE E0 5E 29 AB E3 64 F1 F7 ./.......^)..d..
0010: 15 4A 57 AE EF A4 F4 4A
EncryptionKey: keyType=17 keyBytes (hex dump)=0000: FB 57 7A 00 40 76 D1 CB 06 D5 36 9D E8 F5 45 63 .Wz.@v....6...Ec
Commit Succeeded
サブジェクト:
主体: DomUser01@MYDOMAIN.LOCAL
非公開資格: Ticket (hex) = ...
Client Principal = DomUser01@MYDOMAIN.LOCAL
Server Principal = krbtgt/MYDOMAIN.LOCAL@MYDOMAIN.LOCAL
Session Key = EncryptionKey: keyType=23 keyBytes (hex dump)=
0000: 8E D9 A6 AD 0F 72 87 57 C1 BC F4 46 B1 BC 07 2E .....r.W...F....
Forwardable Ticket false
Forwarded Ticket false
Proxiable Ticket false
Proxy Ticket false
Postdated Ticket false
Renewable Ticket false
Initial Ticket false
Auth Time = Thu Mar 12 13:06:24 JST 2015
Start Time = Thu Mar 12 13:06:24 JST 2015
End Time = Thu Mar 12 23:06:24 JST 2015
Renew Till = null
Client Addresses Null
ACTUAL -
The login attempt fails.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Debug is true storeKey false useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
[Krb5LoginModule] user entered username: DomUser01@MYDOMAIN.LOCAL
[Krb5LoginModule] authentication failed
Cannot locate default realm
Exception in thread "main" javax.security.auth.login.LoginException: Cannot locate default realm
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:763)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:584)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:687)
at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
at TestAuth.main(TestAuth.java:25)
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:367)
at sun.security.krb5.KrbAsReq.<init>(KrbAsReq.java:118)
at sun.security.krb5.KrbAsReqBuilder.build(KrbAsReqBuilder.java:268)
at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:318)
at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:725)
... 13 more
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.Config.getDefaultRealm(Config.java:1181)
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:365)
... 18 more
Caused by: KrbException: Generic error (description in e-text) (60) - Unable to locate Kerberos realm
at sun.security.krb5.Config.getRealmFromDNS(Config.java:1277)
at sun.security.krb5.Config.getDefaultRealm(Config.java:1162)
... 19 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
public class TestAuth {
public static void main(String[] args) throws Exception {
CallbackHandler ch = new CallbackHandler() {
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {
TextOutputCallback toc = (TextOutputCallback)callbacks[i];
System.out.println(toc.getMessage());
} else if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName("DomUser01@MYDOMAIN.LOCAL");
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword("P@ssword0".toCharArray());
}
}
}
};
LoginContext lc = new LoginContext("Krb5Login", ch);
lc.login();
System.out.println(lc.getSubject());
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Set ANYTHING as default_realm in krb5.conf
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600]
A DESCRIPTION OF THE PROBLEM :
Up to JDK6, Krb5LoginModule has been working fine without any default realm configured, as long as the provided principal name includes a realm. In JDK7 (and supposedly in JDK8 also), it fails with saying "Cannot locate default realm."
The error occurs at the point where it initializes a PrincipalName for krbtgt service principal before accessing the AS. It uses an overloaded constructor for PrincipalName which initializes its realm with the default realm. In JDK6, krb5.Config.getDefaultRealm() silently returned null if no default realm is set; in JDK7, it throws KrbException. The change occurred with the commit for implementing the following RFE.
Since the realm name for this service principal is never used, it is no use setting it to the default realm or anything. So I suppose it should use another overloaded constructor for PrincipalName which leaves the realm part uninitialized.
KrbAsReq(...)
if (sname == null) {
sname = new PrincipalName("krbtgt" +
PrincipalName.NAME_COMPONENT_SEPARATOR +
cname.getRealmAsString(),
PrincipalName.KRB_NT_SRV_INST);
}
->
if (sname == null) {
String[] snameParts = new String[] { "krbtgt", cname.getRealmAsString() };
sname = new PrincipalName(snameParts, PrincipalName.KRB_NT_SRV_INST);
}
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please change the domain name / the user name / the password according to your test environment.
* Create krb.conf as follows:
[realms]
MYDOMAIN.LOCAL = {
kdc = mydc.mydomain.local:88
}
* Create login.conf as follows:
Krb5Login {
com.sun.security.auth.module.Krb5LoginModule required debug=true;
};
* Reset USERDNSDOMAIN environment variable if set (since you are logging in as a domain user)
set USERDNSDOMAIN=
Compile and run the test case as follows:
java -Djava.security.krb5.conf=krb5.conf -Djava.security.auth.login.config=login.conf TestAuth
Note that as long as you have ANYTHING set to default_realm in krb5.conf or USERDNSDOMAIN, it would pass.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
As you get with JDK6, the login attempt shoud succeed.
Debug is true storeKey false useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
[Krb5LoginModule] user entered username: DomUser01@MYDOMAIN.LOCAL
Acquire TGT using AS Exchange
principal is DomUser01@MYDOMAIN.LOCAL
EncryptionKey: keyType=3 keyBytes (hex dump)=0000: 73 F4 3D 23 BF 75 83 A8
EncryptionKey: keyType=1 keyBytes (hex dump)=0000: 73 F4 3D 23 BF 75 83 A8
EncryptionKey: keyType=23 keyBytes (hex dump)=0000: D9 DE A9 F7 8F 03 ED A5 D0 EE D3 7B FD 2B 02 25 .............+.%
EncryptionKey: keyType=16 keyBytes (hex dump)=0000: 9E 2F FD 0E D3 92 E9 FE E0 5E 29 AB E3 64 F1 F7 ./.......^)..d..
0010: 15 4A 57 AE EF A4 F4 4A
EncryptionKey: keyType=17 keyBytes (hex dump)=0000: FB 57 7A 00 40 76 D1 CB 06 D5 36 9D E8 F5 45 63 .Wz.@v....6...Ec
Commit Succeeded
サブジェクト:
主体: DomUser01@MYDOMAIN.LOCAL
非公開資格: Ticket (hex) = ...
Client Principal = DomUser01@MYDOMAIN.LOCAL
Server Principal = krbtgt/MYDOMAIN.LOCAL@MYDOMAIN.LOCAL
Session Key = EncryptionKey: keyType=23 keyBytes (hex dump)=
0000: 8E D9 A6 AD 0F 72 87 57 C1 BC F4 46 B1 BC 07 2E .....r.W...F....
Forwardable Ticket false
Forwarded Ticket false
Proxiable Ticket false
Proxy Ticket false
Postdated Ticket false
Renewable Ticket false
Initial Ticket false
Auth Time = Thu Mar 12 13:06:24 JST 2015
Start Time = Thu Mar 12 13:06:24 JST 2015
End Time = Thu Mar 12 23:06:24 JST 2015
Renew Till = null
Client Addresses Null
ACTUAL -
The login attempt fails.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Debug is true storeKey false useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
[Krb5LoginModule] user entered username: DomUser01@MYDOMAIN.LOCAL
[Krb5LoginModule] authentication failed
Cannot locate default realm
Exception in thread "main" javax.security.auth.login.LoginException: Cannot locate default realm
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:763)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:584)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:687)
at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
at TestAuth.main(TestAuth.java:25)
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:367)
at sun.security.krb5.KrbAsReq.<init>(KrbAsReq.java:118)
at sun.security.krb5.KrbAsReqBuilder.build(KrbAsReqBuilder.java:268)
at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:318)
at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:725)
... 13 more
Caused by: KrbException: Cannot locate default realm
at sun.security.krb5.Config.getDefaultRealm(Config.java:1181)
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:365)
... 18 more
Caused by: KrbException: Generic error (description in e-text) (60) - Unable to locate Kerberos realm
at sun.security.krb5.Config.getRealmFromDNS(Config.java:1277)
at sun.security.krb5.Config.getDefaultRealm(Config.java:1162)
... 19 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
public class TestAuth {
public static void main(String[] args) throws Exception {
CallbackHandler ch = new CallbackHandler() {
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {
TextOutputCallback toc = (TextOutputCallback)callbacks[i];
System.out.println(toc.getMessage());
} else if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName("DomUser01@MYDOMAIN.LOCAL");
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword("P@ssword0".toCharArray());
}
}
}
};
LoginContext lc = new LoginContext("Krb5Login", ch);
lc.login();
System.out.println(lc.getSubject());
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Set ANYTHING as default_realm in krb5.conf