FULL PRODUCT VERSION :
java version " 1.7.0_25 "
Java(TM) SE Runtime Environment (build 1.7.0_25-b16)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7600]
A DESCRIPTION OF THE PROBLEM :
I have an application that relies on the JDK's Kerberos support for user authentication. To reduce configuration burden related to krb5.conf, this app is attempting to use DNS to retrieve a list of KDCs --which is done when creating a javax.security.auth.login.LoginContext. However, when multiple SRV records are retrieved, the JDK will only ever use one of them to establish the context. This becomes a problem when the KDC selected is unavailable --i.e. failover does not occur.
From reading the source code it appears there is an intent to iterate over all SRV records until a connection can be made to a KDC. However, there seems to be some incorrect parsing logic that is preventing all KDCs from being tried. More details below.
sun.security.krb5.Config.getKDCList(String realm) is supposed to return a space delimited list of KDCs that can be used when creating the LoginContext. It relies on sun.security.krb5.Config.getKDCFromDNS(String realm) to build this list. Config.getKDCFromDNS correctly retrieves all KDC SRV records using KrbServiceLocator.getKerberosService(realm, " _udp " ). However, these SRV records are incorrectly converted to a space delimited list of KDCs. See the following code snippet (located in sun.security.krb5.Config)...
private String getKDCFromDNS(String realm) throws KrbException {
String kdcs = null;
....
for (int i = 0; i < srvs.length; i++) {
String value = srvs[i];
for (int j = 0; j < srvs[i].length(); j++) {
// filter the KDC name
if (value.charAt(j) == ':') {
kdcs = (value.substring(0, j)).trim();
}
}
}
return kdcs;
}
" kdcs " should be a space delimited list of KDCs. However, because the equal (=) operator is used to assign SRV values to this string list, only the last KDC is ever returned.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expecting that more than one KDC can be used when creating the LoginContext.
ACTUAL -
One 1 KDC is used when creating the LoginContext
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caused by: javax.security.auth.login.LoginException: Receive timed out
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:763)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:580)
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:784)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695)
at javax.security.auth.login.LoginContext.login(LoginContext.java:594)
at com.pingidentity.common.util.KerberosUtil.establishLoginContext(KerberosUtil.java:288)
at com.pingidentity.common.util.KerberosUtil.validateTicket(KerberosUtil.java:356)
... 51 more
Caused by: java.net.SocketTimeoutException: Receive timed out
at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.receive0(DualStackPlainDatagramSocketImpl.java:121)
at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:145)
at java.net.DatagramSocket.receive(DatagramSocket.java:786)
at sun.security.krb5.internal.UDPClient.receive(NetClient.java:207)
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:386)
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:339)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.krb5.KdcComm.send(KdcComm.java:323)
at sun.security.krb5.KdcComm.send(KdcComm.java:219)
at sun.security.krb5.KdcComm.send(KdcComm.java:191)
at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319)
at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:721)
... 65 more
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER SUBMITTED WORKAROUND :
No workaround known.