diff --git a/src/share/classes/sun/security/krb5/Config.java b/src/share/classes/sun/security/krb5/Config.java index eb2f335c551785cc89250331e16c643117a7d875..fe6565cbab697e8541026faeec91eb4dd798dbbe 100644 --- a/src/share/classes/sun/security/krb5/Config.java +++ b/src/share/classes/sun/security/krb5/Config.java @@ -291,7 +291,11 @@ public class Config { } /** - * Gets all values for the specified keys. + * Gets all values (at least one) for the specified keys separated by + * a whitespace, or null if there is no such keys. + * The values can either be provided on a single line, or on multiple lines + * using the same key. When provided on a single line, the value can be + * comma or space separated. * @throws IllegalArgumentException if any of the keys is illegal * (See {@link #get}) */ @@ -301,6 +305,7 @@ public class Config { StringBuilder sb = new StringBuilder(); boolean first = true; for (String s: v) { + s = s.replaceAll("[\\s,]+", " "); if (first) { sb.append(s); first = false; diff --git a/src/share/classes/sun/security/krb5/KrbCred.java b/src/share/classes/sun/security/krb5/KrbCred.java index 8dfe36c49b876ebe697248de61a78946993bc7da..7f02df8ef063efd8ec1e8701b5539a040d749bd6 100644 --- a/src/share/classes/sun/security/krb5/KrbCred.java +++ b/src/share/classes/sun/security/krb5/KrbCred.java @@ -34,6 +34,9 @@ package sun.security.krb5; import sun.security.krb5.internal.*; import sun.security.krb5.internal.crypto.KeyUsage; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; + import sun.security.util.DerValue; /** @@ -76,10 +79,24 @@ public class KrbCred { options.set(KDCOptions.FORWARDABLE, true); HostAddresses sAddrs = null; - // XXX Also NT_GSS_KRB5_PRINCIPAL can be a host based principal + // GSSName.NT_HOSTBASED_SERVICE should display with KRB_NT_SRV_HST - if (server.getNameType() == PrincipalName.KRB_NT_SRV_HST) - sAddrs= new HostAddresses(server); + if (server.getNameType() == PrincipalName.KRB_NT_SRV_HST) { + sAddrs = new HostAddresses(server); + } else if (server.getNameType() == PrincipalName.KRB_NT_UNKNOWN) { + // Sometimes this is also a server + if (server.getNameStrings().length >= 2) { + String host = server.getNameStrings()[1]; + try { + InetAddress[] addr = InetAddress.getAllByName(host); + if (addr != null && addr.length > 0) { + sAddrs = new HostAddresses(addr); + } + } catch (UnknownHostException ioe) { + // maybe we guessed wrong, let sAddrs be null + } + } + } KrbTgsReq tgsReq = new KrbTgsReq(options, tgt, tgService, null, null, null, null, null, diff --git a/src/share/classes/sun/security/krb5/internal/HostAddresses.java b/src/share/classes/sun/security/krb5/internal/HostAddresses.java index 7f18b98f9c3d20fde76b1e75cfde5a5634977ce6..04eeb5de9940db2a6c4926bea31fb715bf032ce4 100644 --- a/src/share/classes/sun/security/krb5/internal/HostAddresses.java +++ b/src/share/classes/sun/security/krb5/internal/HostAddresses.java @@ -31,16 +31,14 @@ package sun.security.krb5.internal; +import sun.security.krb5.Config; import sun.security.krb5.PrincipalName; import sun.security.krb5.KrbException; import sun.security.krb5.Asn1Exception; import sun.security.util.*; -import java.util.Vector; -import java.util.ArrayList; -import java.net.InetAddress; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.UnknownHostException; + +import java.net.*; +import java.util.*; import java.io.IOException; import sun.security.krb5.internal.ccache.CCacheOutputStream; @@ -293,34 +291,35 @@ public class HostAddresses implements Cloneable { */ public static HostAddresses getLocalAddresses() throws IOException { - String hostname = null; - InetAddress[] inetAddresses = null; + Set all = new LinkedHashSet<>(); try { - InetAddress localHost = InetAddress.getLocalHost(); - hostname = localHost.getHostName(); - inetAddresses = InetAddress.getAllByName(hostname); - HostAddress[] hAddresses = new HostAddress[inetAddresses.length]; - for (int i = 0; i < inetAddresses.length; i++) - { - hAddresses[i] = new HostAddress(inetAddresses[i]); - } if (DEBUG) { - System.out.println(">>> KrbKdcReq local addresses for " - + hostname + " are: "); - - for (int i = 0; i < inetAddresses.length; i++) { - System.out.println("\n\t" + inetAddresses[i]); - if (inetAddresses[i] instanceof Inet4Address) - System.out.println("IPv4 address"); - if (inetAddresses[i] instanceof Inet6Address) - System.out.println("IPv6 address"); + System.out.println(">>> KrbKdcReq local addresses are:"); + } + String extra = Config.getInstance().getAll( + "libdefaults", "extra_addresses"); + if (extra != null) { + for (String s: extra.split("\\s+")) { + all.add(InetAddress.getByName(s)); + if (DEBUG) { + System.out.println(" extra_addresses: " + + InetAddress.getByName(s)); + } } } - return (new HostAddresses(hAddresses)); + for (NetworkInterface ni: + Collections.list(NetworkInterface.getNetworkInterfaces())) { + if (DEBUG) { + System.out.println(" NetworkInterface " + ni + ":"); + System.out.println(" " + + Collections.list(ni.getInetAddresses())); + } + all.addAll(Collections.list(ni.getInetAddresses())); + } + return new HostAddresses(all.toArray(new InetAddress[all.size()])); } catch (Exception exc) { throw new IOException(exc.toString()); } - } /** diff --git a/test/sun/security/krb5/auto/Addresses.java b/test/sun/security/krb5/auto/Addresses.java new file mode 100644 index 0000000000000000000000000000000000000000..0bd62e496b01b5be5cdf5cf40b0ed58e6a20a0ca --- /dev/null +++ b/test/sun/security/krb5/auto/Addresses.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031111 + * @summary fix krb5 caddr + * @compile -XDignore.symbol.file Addresses.java + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Addresses + */ + +import sun.security.krb5.Config; + +import javax.security.auth.kerberos.KerberosTicket; +import java.net.Inet4Address; +import java.net.InetAddress; + +public class Addresses { + + public static void main(String[] args) throws Exception { + + KDC.saveConfig(OneKDC.KRB5_CONF, new OneKDC(null), + "noaddresses = false", + "extra_addresses = 10.0.0.10, 10.0.0.11 10.0.0.12"); + Config.refresh(); + + KerberosTicket ticket = + Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false) + .s().getPrivateCredentials(KerberosTicket.class) + .iterator().next(); + + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetAddress extra1 = InetAddress.getByName("10.0.0.10"); + InetAddress extra2 = InetAddress.getByName("10.0.0.11"); + InetAddress extra3 = InetAddress.getByName("10.0.0.12"); + + boolean loopbackFound = false; + boolean extra1Found = false; + boolean extra2Found = false; + boolean extra3Found = false; + boolean networkFound = false; + + for (InetAddress ia: ticket.getClientAddresses()) { + System.out.println(ia); + if (ia.equals(loopback)) { + loopbackFound = true; + System.out.println(" loopback found"); + } else if (ia.equals(extra1)) { + extra1Found = true; + System.out.println(" extra1 found"); + } else if (ia.equals(extra2)) { + extra2Found = true; + System.out.println(" extra2 found"); + } else if (ia.equals(extra3)) { + extra3Found = true; + System.out.println(" extra3 found"); + } else if (ia instanceof Inet4Address) { + networkFound = true; + System.out.println(" another address (" + ia + + "), assumed real network"); + } + } + + if (!loopbackFound || !networkFound + || !extra1Found || !extra2Found || !extra3Found ) { + throw new Exception(); + } + } +} diff --git a/test/sun/security/krb5/auto/Forwarded.java b/test/sun/security/krb5/auto/Forwarded.java new file mode 100644 index 0000000000000000000000000000000000000000..0bdc3f5ebb73425dbe43916f808a7750eee2aa7b --- /dev/null +++ b/test/sun/security/krb5/auto/Forwarded.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031111 + * @summary fix krb5 caddr + * @compile -XDignore.symbol.file Forwarded.java + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Forwarded + */ + +import sun.security.jgss.GSSUtil; +import sun.security.krb5.internal.KDCOptions; +import sun.security.krb5.internal.KDCReqBody; +import sun.security.krb5.internal.TGSReq; + +public class Forwarded { + + public static void main(String[] args) throws Exception { + + new OneKDC(null).setOption(KDC.Option.CHECK_ADDRESSES, true); + + Context c; + c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + + c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + c.x().requestCredDeleg(true); + + c.take(new byte[0]); + } +} diff --git a/test/sun/security/krb5/auto/KDC.java b/test/sun/security/krb5/auto/KDC.java index 6d25837b156c4562ff3a513d915e303813c95e8f..fa4ab5a65856a47c66020e55b75f3b1ced6348f3 100644 --- a/test/sun/security/krb5/auto/KDC.java +++ b/test/sun/security/krb5/auto/KDC.java @@ -245,6 +245,10 @@ public class KDC { * Sensitive accounts can never be delegated. */ SENSITIVE_ACCOUNTS, + /** + * If true, will check if TGS-REQ contains a non-null addresses field. + */ + CHECK_ADDRESSES, }; //static { @@ -899,6 +903,11 @@ public class KDC { bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true; } } + if (options.containsKey(Option.CHECK_ADDRESSES) + && body.kdcOptions.get(KDCOptions.FORWARDED) + && body.addresses == null) { + throw new KrbException(Krb5.KDC_ERR_BADOPTION); + } if (body.kdcOptions.get(KDCOptions.FORWARDED) || etp.flags.get(Krb5.TKT_OPTS_FORWARDED)) { bFlags[Krb5.TKT_OPTS_FORWARDED] = true; @@ -979,10 +988,8 @@ public class KDC { timeAfter(0), from, till, renewTill, - body.addresses != null // always set caddr - ? body.addresses - : new HostAddresses( - new InetAddress[]{InetAddress.getLocalHost()}), + body.addresses != null ? body.addresses + : etp.caddr, null); EncryptionKey skey = keyForUser(service, e3, true); if (skey == null) { @@ -1007,10 +1014,7 @@ public class KDC { from, till, renewTill, service, - body.addresses != null // always set caddr - ? body.addresses - : new HostAddresses( - new InetAddress[]{InetAddress.getLocalHost()}), + body.addresses, null ); EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(),