Exception while processing 'no-addresses' flag in KrbApReq.java
Szabolcs Pota
Szabolcs.Pota at morganstanley.com
Wed Mar 23 12:16:58 UTC 2011
Hi All,
I am testing Kerberos implementation in Open JDK (build 133,
http://download.java.net/openjdk/jdk7/promoted/b133/) and run into an
issue that maybe a bug in the KrbApReq class. I have started to
investigate the issue in more details when I found that the same test
setup runs without problem with JDK 6u21 to 6u23 but consistently
fails with Open JDK. (I needed JDK 6u21+ because of a bug fix that
caused lot of problems for us before:
http://bugs.sun.com/view_bug.do?bug_id=6893158).
Sorry for the verbose mail but I wanted to include all information.
In my setup there is a client and a server that use the JGSS API (with
Krb5LoginModule) and TCP connection to authenticate each other.
However the server always fails with the following exception when it
accepts client credentials:
> Caused by: sun.security.krb5.internal.KrbApErrException: Incorrect net address (38)
> at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:329) ~[na:na]
> at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:146) ~[na:na]
> at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108) ~[na:na]
> at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:761) ~[na:na]
I have looked into the KrbApReq class and found the Exception is
related to handling the 'no-addresses' flag (coming from krb5.conf).
Related code can be found from line 315 to 333 of KrbApReq.java.
Analyzing the code I've managed to identify a scenario when the code
cannot succeed but always throws the already mentioned exception. This
scenario is when both on the client and server side the 'no-addresses'
flag is set to 'false'. Here is a small table on the code behavior
given the different values of the 'no-addresses' flag:
+---------------------------------------------------------------------------------------------------------------------------+
| | Client ‘no-addresses’
true | Client ‘no-addresses’ false |
+---------------------------------------------------------------------------------------------------------------------------+
| Server ‘no-addresses’ true | Success |
Success |
+---------------------------------------------------------------------------------------------------------------------------+
| Server ‘no-addresses’ false | Success |
Always throws exception |
+---------------------------------------------------------------------------------------------------------------------------+
Our global krb5.conf files have 'noaddresses=false' for both client
and server hence we get this exception. Please correct me if someone
thinks that setting this flag to false on the server side would be
incorrect.
To better understand what's happening in KrbApReq I've transformed the
code from line 315 to 333 to have the same functionality but a more
expressive structure. Besides two lines the comments are added by me.
> // check to use addresses in tickets
> // In my case 'noaddresses=false' hence useAddresses is true.
> if (Config.getInstance().useAddresses()) {
> KDC_EMPTY_ADDRESSES_ALLOWED = false;
> }
>
> // sender host address
> HostAddress sender = null;
> // If we are the client
> if (initiator != null) {
> sender = new HostAddress(initiator);
> if (enc_ticketPart.caddr != null) {
> if (!enc_ticketPart.caddr.inList(sender))
> throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
> }
> }
> // This else-if block executes only on the server side. On the server side
> // if 'no-addresses' == false and on the client side it was set to false too
> // (i.e. enc_ticketPart.caddr is not null) then this block will always throw
> // exception.
> //
> // Given that sender is always null on the server side the internal if blocks
> // make no sense.
> //
> else if (!KDC_EMPTY_ADDRESSES_ALLOWED) {
> // should we obtain sender from the connection?
> if (enc_ticketPart.caddr != null) {
> if (sender == null)
> throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
> if (!enc_ticketPart.caddr.inList(sender))
> throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
> }
> }
You can deduce the same from the original code, however I think in
this form it is easier to understand.
At this point I am not really sure what is the correct behavior on the
server side. However, reading RFC 4120 about the use of the
EncTicketPart.caddr field it seems that server should identify the
sender from the client connection. Though the RFC itself admits that
it cannot be done reliable and only a best effort way to make stolen
credential use harder (RFC 4120, page 71):
> Note that the network address from which a connection is received
> cannot be reliably determined. Even if it could be, an attacker
> who has compromised the client's workstation could use the
> credentials from there. Including the network addresses only
> makes it more difficult, not impossible, for an attacker to walk
> off with stolen credentials and then to use them from a "safe"
> location.
Could you please comment on this issue? Unfortunately we cannot change
global krb5.conf settings easily (large financial corporation having
offices world-wide) and this error prevents us using JGSS with
OpenJDK.
Best Regards,
Szabolcs Pota
More information about the security-dev
mailing list