From 8a52d1a9d5a5ac8caaca0b83079f70259de2a5ea Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 9 Jun 2009 14:17:05 +0800 Subject: [PATCH] 6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication() Reviewed-by: chegar, valeriep --- .../protocol/http/AuthenticationHeader.java | 27 +- .../net/www/protocol/http/HttpCallerInfo.java | 108 ++++++ .../www/protocol/http/HttpURLConnection.java | 21 +- .../http/NegotiateAuthentication.java | 68 ++-- .../http/NegotiateCallbackHandler.java | 21 +- .../net/www/protocol/http/NegotiatorImpl.java | 33 +- .../classes/sun/security/jgss/GSSCaller.java | 40 ++ .../sun/security/jgss/GSSManagerImpl.java | 10 +- .../classes/sun/security/jgss/GSSUtil.java | 20 +- .../classes/sun/security/jgss/HttpCaller.java | 45 +++ .../sun/security/jgss/LoginConfigImpl.java | 33 +- .../sun/security/jgss/ProviderList.java | 13 +- .../sun/security/jgss/krb5/InitialToken.java | 6 +- .../jgss/krb5/Krb5AcceptCredential.java | 9 +- .../sun/security/jgss/krb5/Krb5Context.java | 17 +- .../jgss/krb5/Krb5InitCredential.java | 12 +- .../security/jgss/krb5/Krb5MechFactory.java | 10 +- .../sun/security/jgss/krb5/Krb5Util.java | 11 +- .../jgss/spnego/SpNegoMechFactory.java | 4 +- .../jgss/wrapper/NativeGSSFactory.java | 14 +- .../sun/security/ssl/ClientHandshaker.java | 7 +- .../ssl/KerberosClientKeyExchange.java | 9 +- .../sun/security/ssl/ServerHandshaker.java | 8 +- .../sun/security/jgss/DefaultGssConfig.java | 7 +- jdk/test/sun/security/jgss/GssNPE.java | 5 +- .../krb5/auto/HttpNegotiateServer.java | 341 ++++++++++++++++++ jdk/test/sun/security/krb5/auto/KDC.java | 35 +- ....net.spi.nameservice.NameServiceDescriptor | 1 + 28 files changed, 717 insertions(+), 218 deletions(-) create mode 100644 jdk/src/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java create mode 100644 jdk/src/share/classes/sun/security/jgss/GSSCaller.java create mode 100644 jdk/src/share/classes/sun/security/jgss/HttpCaller.java create mode 100644 jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java create mode 100644 jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 8eb05bf9702..68262442e0a 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. 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 @@ -81,8 +81,7 @@ public class AuthenticationHeader { MessageHeader rsp; // the response to be parsed HeaderParser preferred; String preferred_r; // raw Strings - String host = null; // the hostname for server, - // used in checking the availability of Negotiate + private final HttpCallerInfo hci; // un-schemed, need check // When set true, do not use Negotiate even if the response // headers suggest so. @@ -113,24 +112,13 @@ public class AuthenticationHeader { String hdrname; // Name of the header to look for - /** - * parse a set of authentication headers and choose the preferred scheme - * that we support - */ - public AuthenticationHeader (String hdrname, MessageHeader response) { - rsp = response; - this.hdrname = hdrname; - schemes = new HashMap(); - parse(); - } - /** * parse a set of authentication headers and choose the preferred scheme * that we support for a given host */ public AuthenticationHeader (String hdrname, MessageHeader response, - String host, boolean dontUseNegotiate) { - this.host = host; + HttpCallerInfo hci, boolean dontUseNegotiate) { + this.hci = hci; this.dontUseNegotiate = dontUseNegotiate; rsp = response; this.hdrname = hdrname; @@ -138,6 +126,9 @@ public class AuthenticationHeader { parse(); } + public HttpCallerInfo getHttpCallerInfo() { + return hci; + } /* we build up a map of scheme names mapped to SchemeMapValue objects */ static class SchemeMapValue { SchemeMapValue (HeaderParser h, String r) {raw=r; parser=h;} @@ -186,7 +177,7 @@ public class AuthenticationHeader { if(v == null && !dontUseNegotiate) { SchemeMapValue tmp = (SchemeMapValue)schemes.get("negotiate"); if(tmp != null) { - if(host == null || !NegotiateAuthentication.isSupported(host, "Negotiate")) { + if(hci == null || !NegotiateAuthentication.isSupported(new HttpCallerInfo(hci, "Negotiate"))) { tmp = null; } v = tmp; @@ -206,7 +197,7 @@ public class AuthenticationHeader { // // The only chance this line get executed is that the server // only suggest the Kerberos scheme. - if(host == null || !NegotiateAuthentication.isSupported(host, "Kerberos")) { + if(hci == null || !NegotiateAuthentication.isSupported(new HttpCallerInfo(hci, "Kerberos"))) { tmp = null; } v = tmp; diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java new file mode 100644 index 00000000000..3aeba81e0a4 --- /dev/null +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java @@ -0,0 +1,108 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.net.www.protocol.http; + +import java.net.Authenticator.RequestorType; +import java.net.InetAddress; +import java.net.URL; + +/** + * Used in HTTP/Negotiate, to feed HTTP request info into JGSS as a HttpCaller, + * so that special actions can be taken, including special callback handler, + * special useSubjectCredsOnly value. + * + * This is an immutable class. It can be instantiated in two styles; + * + * 1. Un-schemed: Create at the beginning before the preferred scheme is + * determined. This object can be fed into AuthenticationHeader to check + * for the preference. + * + * 2. Schemed: With the scheme field filled, can be used in JGSS-API calls. + */ +final public class HttpCallerInfo { + // All info that an Authenticator needs. + final public URL url; + final public String host, protocol, prompt, scheme; + final public int port; + final public InetAddress addr; + final public RequestorType authType; + + /** + * Create a schemed object based on an un-schemed one. + */ + public HttpCallerInfo(HttpCallerInfo old, String scheme) { + this.url = old.url; + this.host = old.host; + this.protocol = old.protocol; + this.prompt = old.prompt; + this.port = old.port; + this.addr = old.addr; + this.authType = old.authType; + this.scheme = scheme; + } + + /** + * Constructor an un-schemed object for site access. + */ + public HttpCallerInfo(URL url) { + this.url= url; + prompt = ""; + host = url.getHost(); + + int p = url.getPort(); + if (p == -1) { + port = url.getDefaultPort(); + } else { + port = p; + } + + InetAddress ia; + try { + ia = InetAddress.getByName(url.getHost()); + } catch (Exception e) { + ia = null; + } + addr = ia; + + protocol = url.getProtocol(); + authType = RequestorType.SERVER; + scheme = ""; + } + + /** + * Constructor an un-schemed object for proxy access. + */ + public HttpCallerInfo(URL url, String host, int port) { + this.url= url; + this.host = host; + this.port = port; + prompt = ""; + addr = null; + protocol = url.getProtocol(); + authType = RequestorType.PROXY; + scheme = ""; + } +} diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 770ffba36d6..aacab5f238d 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2009 Sun Microsystems, Inc. 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 @@ -1165,7 +1165,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { AuthenticationHeader authhdr = new AuthenticationHeader ( "Proxy-Authenticate", responses, - http.getProxyHostUsed(), dontUseNegotiate + new HttpCallerInfo(url, http.getProxyHostUsed(), + http.getProxyPortUsed()), + dontUseNegotiate ); if (!doingNTLMp2ndStage) { @@ -1230,7 +1232,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { srvHdr = new AuthenticationHeader ( "WWW-Authenticate", responses, - url.getHost().toLowerCase(), dontUseNegotiate + new HttpCallerInfo(url), + dontUseNegotiate ); String raw = srvHdr.raw(); @@ -1595,7 +1598,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { AuthenticationHeader authhdr = new AuthenticationHeader ( "Proxy-Authenticate", responses, - http.getProxyHostUsed(), dontUseNegotiate + new HttpCallerInfo(url, http.getProxyHostUsed(), + http.getProxyPortUsed()), + dontUseNegotiate ); if (!doingNTLMp2ndStage) { proxyAuthentication = @@ -1811,9 +1816,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { tryTransparentNTLMProxy = false; } else if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) { - ret = new NegotiateAuthentication(true, host, port, null, "Negotiate"); + ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); } else if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) { - ret = new NegotiateAuthentication(true, host, port, null, "Kerberos"); + ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); } } // For backwards compatibility, we also try defaultAuth @@ -1897,7 +1902,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } catch (Exception e) { url1 = url; } - ret = new NegotiateAuthentication(false, url1, null, "Kerberos"); + ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); } if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) { URL url1; @@ -1906,7 +1911,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } catch (Exception e) { url1 = url; } - ret = new NegotiateAuthentication(false, url1, null, "Negotiate"); + ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); } if (schemeID == BasicAuthentication.BASIC_AUTH) { PasswordAuthentication a = diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index 81353fc1fea..db5d509a364 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -25,17 +25,15 @@ package sun.net.www.protocol.http; -import java.util.Arrays; import java.util.HashMap; -import java.util.Map; import sun.net.www.HeaderParser; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.net.URL; -import java.net.PasswordAuthentication; import java.io.IOException; +import java.net.Authenticator.RequestorType; /** @@ -49,7 +47,7 @@ class NegotiateAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; - private String scheme = null; + final private HttpCallerInfo hci; static final char NEGOTIATE_AUTH = 'S'; static final char KERBEROS_AUTH = 'K'; @@ -66,25 +64,16 @@ class NegotiateAuthentication extends AuthenticationInfo { private Negotiator negotiator = null; /** - * Constructor used for WWW entries. pw is not used because - * for GSS there is only one single PasswordAuthentication which is - * independant of host/port/... info. + * Constructor used for both WWW and proxy entries. + * @param hci a schemed object. */ - public NegotiateAuthentication(boolean isProxy, URL url, - PasswordAuthentication pw, String scheme) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, - NEGOTIATE_AUTH, url, ""); - this.scheme = scheme; - } - - /** - * Constructor used for proxy entries - */ - public NegotiateAuthentication(boolean isProxy, String host, int port, - PasswordAuthentication pw, String scheme) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, - NEGOTIATE_AUTH,host, port, ""); - this.scheme = scheme; + public NegotiateAuthentication(HttpCallerInfo hci) { + super(RequestorType.PROXY==hci.authType? + PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, + hci.scheme.equalsIgnoreCase("Negotiate")? + NEGOTIATE_AUTH:KERBEROS_AUTH, + hci.url, ""); + this.hci = hci; } /** @@ -95,32 +84,29 @@ class NegotiateAuthentication extends AuthenticationInfo { } /** - * Find out if a hostname supports Negotiate protocol. In order to find - * out yes or no, an initialization of a Negotiator object against - * hostname and scheme is tried. The generated object will be cached - * under the name of hostname at a success try.
+ * Find out if the HttpCallerInfo supports Negotiate protocol. In order to + * find out yes or no, an initialization of a Negotiator object against it + * is tried. The generated object will be cached under the name of ths + * hostname at a success try.
* - * If this method is called for the second time on a hostname, the answer is - * already saved in supported, so no need to try again. + * If this method is called for the second time on an HttpCallerInfo with + * the same hostname, the answer is retrieved from cache. * - * @param hostname hostname to test - * @param scheme scheme to test * @return true if supported */ - synchronized public static boolean isSupported(String hostname, - String scheme) { + synchronized public static boolean isSupported(HttpCallerInfo hci) { if (supported == null) { supported = new HashMap (); cache = new HashMap (); } - + String hostname = hci.host; hostname = hostname.toLowerCase(); if (supported.containsKey(hostname)) { return supported.get(hostname); } try { - Negotiator neg = Negotiator.getSupported(hostname, scheme); + Negotiator neg = Negotiator.getSupported(hci); supported.put(hostname, true); // the only place cache.put is called. here we can make sure // the object is valid and the oneToken inside is not null @@ -179,7 +165,7 @@ class NegotiateAuthentication extends AuthenticationInfo { if (parts.length > 1) { incoming = new BASE64Decoder().decodeBuffer(parts[1]); } - response = scheme + " " + new B64Encoder().encode( + response = hci.scheme + " " + new B64Encoder().encode( incoming==null?firstToken():nextToken(incoming)); conn.setAuthenticationProperty(getHeaderName(), response); @@ -207,7 +193,7 @@ class NegotiateAuthentication extends AuthenticationInfo { } if (negotiator == null) { try { - negotiator = Negotiator.getSupported(getHost(), scheme); + negotiator = Negotiator.getSupported(hci); } catch(Exception e) { IOException ioe = new IOException("Cannot initialize Negotiator"); ioe.initCause(e); @@ -255,18 +241,18 @@ class NegotiateAuthentication extends AuthenticationInfo { * NegotiatorImpl, so that JAAS and JGSS calls can be made */ abstract class Negotiator { - static Negotiator getSupported(String hostname, String scheme) + static Negotiator getSupported(HttpCallerInfo hci) throws Exception { // These lines are equivalent to - // return new NegotiatorImpl(hostname, scheme); + // return new NegotiatorImpl(hci); // The current implementation will make sure NegotiatorImpl is not // directly referenced when compiling, thus smooth the way of building // the J2SE platform where HttpURLConnection is a bootstrap class. Class clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl"); - java.lang.reflect.Constructor c = clazz.getConstructor(String.class, String.class); - return (Negotiator) (c.newInstance(hostname, scheme)); + java.lang.reflect.Constructor c = clazz.getConstructor(HttpCallerInfo.class); + return (Negotiator) (c.newInstance(hci)); } abstract byte[] firstToken() throws IOException; diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java index 8ab6eb66c84..7ac25933cee 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -36,12 +36,19 @@ import javax.security.auth.callback.UnsupportedCallbackException; /** * @since 1.6 + * Special callback handler used in JGSS for the HttpCaller. */ public class NegotiateCallbackHandler implements CallbackHandler { private String username; private char[] password; + private final HttpCallerInfo hci; + + public NegotiateCallbackHandler(HttpCallerInfo hci) { + this.hci = hci; + } + public void handle(Callback[] callbacks) throws UnsupportedCallbackException, IOException { for (int i=0; i - *
  • Find out what GSS mechanism to use from http.negotiate.mechanism.oid, - * defaults SPNEGO + *
  • Find out what GSS mechanism to use from the system property + * http.negotiate.mechanism.oid, defaults SPNEGO *
  • Creating the GSSName for the target host, "HTTP/"+hostname *
  • Creating GSSContext *
  • A first call to initSecContext - * @param hostname name of peer server - * @param scheme auth scheme requested, Negotiate ot Kerberos - * @throws GSSException if any JGSS-API call fails */ - private void init(final String hostname, String scheme) throws GSSException { - // "1.2.840.113554.1.2.2" Kerberos - // "1.3.6.1.5.5.2" SPNEGO + private void init(HttpCallerInfo hci) throws GSSException { final Oid oid; - if (scheme.equalsIgnoreCase("Kerberos")) { + if (hci.scheme.equalsIgnoreCase("Kerberos")) { // we can only use Kerberos mech when the scheme is kerberos oid = GSSUtil.GSS_KRB5_MECH_OID; } else { @@ -89,9 +85,11 @@ public class NegotiatorImpl extends Negotiator { } GSSManagerImpl manager = new GSSManagerImpl( - GSSUtil.CALLER_HTTP_NEGOTIATE); + new HttpCaller(hci)); - String peerName = "HTTP@" + hostname; + // RFC 4559 4.1 uses uppercase service name "HTTP". + // RFC 4120 6.2.1 demands the host be lowercase + String peerName = "HTTP@" + hci.host.toLowerCase(); GSSName serverName = manager.createName(peerName, GSSName.NT_HOSTBASED_SERVICE); @@ -114,16 +112,15 @@ public class NegotiatorImpl extends Negotiator { /** * Constructor - * @param hostname name of peer server - * @param scheme auth scheme requested, Negotiate ot Kerberos * @throws java.io.IOException If negotiator cannot be constructed */ - public NegotiatorImpl(String hostname, String scheme) throws IOException { + public NegotiatorImpl(HttpCallerInfo hci) throws IOException { try { - init(hostname, scheme); + init(hci); } catch (GSSException e) { if (DEBUG) { - System.out.println("Negotiate support not initiated, will fallback to other scheme if allowed. Reason:"); + System.out.println("Negotiate support not initiated, will " + + "fallback to other scheme if allowed. Reason:"); e.printStackTrace(); } IOException ioe = new IOException("Negotiate support not initiated"); diff --git a/jdk/src/share/classes/sun/security/jgss/GSSCaller.java b/jdk/src/share/classes/sun/security/jgss/GSSCaller.java new file mode 100644 index 00000000000..e38c348ac2f --- /dev/null +++ b/jdk/src/share/classes/sun/security/jgss/GSSCaller.java @@ -0,0 +1,40 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.security.jgss; + +/** + * Denotes what client is calling the JGSS-API. The object can be sent deep + * into the mechanism level so that special actions can be performed for + * different callers. + */ +public class GSSCaller { + public static final GSSCaller CALLER_UNKNOWN = new GSSCaller(); + public static final GSSCaller CALLER_INITIATE = new GSSCaller(); + public static final GSSCaller CALLER_ACCEPT = new GSSCaller(); + public static final GSSCaller CALLER_SSL_CLIENT = new GSSCaller(); + public static final GSSCaller CALLER_SSL_SERVER = new GSSCaller(); +} + diff --git a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java index a886b87009f..eeb23fc940a 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -27,8 +27,6 @@ package sun.security.jgss; import org.ietf.jgss.*; import sun.security.jgss.spi.*; -import java.io.*; -import java.security.NoSuchProviderException; import java.security.Provider; import java.security.AccessController; import java.security.PrivilegedAction; @@ -63,17 +61,17 @@ public class GSSManagerImpl extends GSSManager { private ProviderList list; // Used by java SPNEGO impl to make sure native is disabled - public GSSManagerImpl(int caller, boolean useNative) { + public GSSManagerImpl(GSSCaller caller, boolean useNative) { list = new ProviderList(caller, useNative); } // Used by HTTP/SPNEGO NegotiatorImpl - public GSSManagerImpl(int caller) { + public GSSManagerImpl(GSSCaller caller) { list = new ProviderList(caller, USE_NATIVE); } public GSSManagerImpl() { - list = new ProviderList(GSSUtil.CALLER_UNKNOWN, USE_NATIVE); + list = new ProviderList(GSSCaller.CALLER_UNKNOWN, USE_NATIVE); } public Oid[] getMechs(){ diff --git a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java index 4c161b2250c..12a791dc4a6 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -72,13 +72,6 @@ public class GSSUtil { private static final String DEFAULT_HANDLER = "auth.login.defaultCallbackHandler"; - public static final int CALLER_UNKNOWN = -1; - public static final int CALLER_INITIATE = 1; - public static final int CALLER_ACCEPT = 2; - public static final int CALLER_SSL_CLIENT = 3; - public static final int CALLER_SSL_SERVER = 4; - public static final int CALLER_HTTP_NEGOTIATE = 5; - static final boolean DEBUG; static { DEBUG = (AccessController.doPrivileged @@ -240,11 +233,12 @@ public class GSSUtil { * @param mech the mech to be used * @return the authenticated subject */ - public static Subject login(int caller, Oid mech) throws LoginException { + public static Subject login(GSSCaller caller, Oid mech) throws LoginException { CallbackHandler cb = null; - if (caller == GSSUtil.CALLER_HTTP_NEGOTIATE) { - cb = new sun.net.www.protocol.http.NegotiateCallbackHandler(); + if (caller instanceof HttpCaller) { + cb = new sun.net.www.protocol.http.NegotiateCallbackHandler( + ((HttpCaller)caller).info()); } else { String defaultHandler = java.security.Security.getProperty(DEFAULT_HANDLER); @@ -274,12 +268,12 @@ public class GSSUtil { * The application indicates this by explicitly setting the system * property javax.security.auth.useSubjectCredsOnly to false. */ - public static boolean useSubjectCredsOnly(int caller) { + public static boolean useSubjectCredsOnly(GSSCaller caller) { // HTTP/SPNEGO doesn't use the standard JAAS framework. Instead, it // uses the java.net.Authenticator style, therefore always return // false here. - if (caller == CALLER_HTTP_NEGOTIATE) { + if (caller instanceof HttpCaller) { return false; } /* diff --git a/jdk/src/share/classes/sun/security/jgss/HttpCaller.java b/jdk/src/share/classes/sun/security/jgss/HttpCaller.java new file mode 100644 index 00000000000..4ec4398d9ec --- /dev/null +++ b/jdk/src/share/classes/sun/security/jgss/HttpCaller.java @@ -0,0 +1,45 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.security.jgss; + +import sun.net.www.protocol.http.HttpCallerInfo; + +/** + * A special kind of GSSCaller, which origins from HTTP/Negotiate and contains + * info about what triggers the JGSS calls. + */ +public class HttpCaller extends GSSCaller { + final private HttpCallerInfo hci; + + public HttpCaller(HttpCallerInfo hci) { + this.hci = hci; + } + + public HttpCallerInfo info() { + return hci; + } +} + diff --git a/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java b/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java index a421e517f3a..72629659e53 100644 --- a/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -39,7 +39,7 @@ import org.ietf.jgss.Oid; public class LoginConfigImpl extends Configuration { private final Configuration config; - private final int caller; + private final GSSCaller caller; private final String mechName; private static final sun.security.util.Debug debug = sun.security.util.Debug.getInstance("gssloginconfig", "\t[GSS LoginConfigImpl]"); @@ -50,7 +50,7 @@ public class LoginConfigImpl extends Configuration { * @param caller defined in GSSUtil as CALLER_XXX final fields * @param oid defined in GSSUtil as XXX_MECH_OID final fields */ - public LoginConfigImpl(int caller, Oid mech) { + public LoginConfigImpl(GSSCaller caller, Oid mech) { this.caller = caller; @@ -88,40 +88,31 @@ public class LoginConfigImpl extends Configuration { // entry name is not provided. if ("krb5".equals(mechName)) { - switch (caller) { - case GSSUtil.CALLER_INITIATE: + if (caller == GSSCaller.CALLER_INITIATE) { alts = new String[] { "com.sun.security.jgss.krb5.initiate", "com.sun.security.jgss.initiate", }; - break; - case GSSUtil.CALLER_ACCEPT: + } else if (caller == GSSCaller.CALLER_ACCEPT) { alts = new String[] { "com.sun.security.jgss.krb5.accept", "com.sun.security.jgss.accept", }; - break; - case GSSUtil.CALLER_SSL_CLIENT: + } else if (caller == GSSCaller.CALLER_SSL_CLIENT) { alts = new String[] { "com.sun.security.jgss.krb5.initiate", "com.sun.net.ssl.client", }; - break; - case GSSUtil.CALLER_SSL_SERVER: + } else if (caller == GSSCaller.CALLER_SSL_SERVER) { alts = new String[] { "com.sun.security.jgss.krb5.accept", "com.sun.net.ssl.server", }; - break; - case GSSUtil.CALLER_HTTP_NEGOTIATE: + } else if (caller instanceof HttpCaller) { alts = new String[] { "com.sun.security.jgss.krb5.initiate", }; - break; - case GSSUtil.CALLER_UNKNOWN: - // should never use - throw new AssertionError("caller cannot be unknown"); - default: + } else if (caller == GSSCaller.CALLER_UNKNOWN) { throw new AssertionError("caller not defined"); } } else { @@ -199,8 +190,8 @@ public class LoginConfigImpl extends Configuration { return null; } - private static boolean isServerSide (int caller) { - return GSSUtil.CALLER_ACCEPT == caller || - GSSUtil.CALLER_SSL_SERVER == caller; + private static boolean isServerSide (GSSCaller caller) { + return GSSCaller.CALLER_ACCEPT == caller || + GSSCaller.CALLER_SSL_SERVER == caller; } } diff --git a/jdk/src/share/classes/sun/security/jgss/ProviderList.java b/jdk/src/share/classes/sun/security/jgss/ProviderList.java index 8df718c61be..45e69b26b86 100644 --- a/jdk/src/share/classes/sun/security/jgss/ProviderList.java +++ b/jdk/src/share/classes/sun/security/jgss/ProviderList.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -28,8 +28,6 @@ package sun.security.jgss; import java.lang.reflect.InvocationTargetException; import org.ietf.jgss.*; import java.security.AccessController; -import java.security.AccessControlContext; -import java.security.PrivilegedAction; import java.security.Provider; import java.security.Security; import java.util.ArrayList; @@ -37,7 +35,6 @@ import java.util.HashSet; import java.util.HashMap; import java.util.Enumeration; import java.util.Iterator; -import javax.security.auth.Subject; import sun.security.jgss.spi.*; import sun.security.jgss.wrapper.NativeGSSFactory; import sun.security.jgss.wrapper.SunNativeProvider; @@ -124,9 +121,9 @@ public final class ProviderList { new HashMap(5); private HashSet mechs = new HashSet(5); - final private int caller; + final private GSSCaller caller; - public ProviderList(int caller, boolean useNative) { + public ProviderList(GSSCaller caller, boolean useNative) { this.caller = caller; Provider[] provList; if (useNative) { @@ -274,7 +271,7 @@ public final class ProviderList { private static MechanismFactory getMechFactoryImpl(Provider p, String className, Oid mechOid, - int caller) + GSSCaller caller) throws GSSException { try { @@ -301,7 +298,7 @@ public final class ProviderList { if (baseClass.isAssignableFrom(implClass)) { java.lang.reflect.Constructor c = - implClass.getConstructor(Integer.TYPE); + implClass.getConstructor(GSSCaller.class); MechanismFactory mf = (MechanismFactory) (c.newInstance(caller)); if (mf instanceof NativeGSSFactory) { diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java b/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java index 45338132edf..7ce0b449978 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -34,7 +34,7 @@ import java.net.Inet6Address; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import sun.security.krb5.*; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.HttpCaller; import sun.security.krb5.internal.Krb5; abstract class InitialToken extends Krb5Token { @@ -85,7 +85,7 @@ abstract class InitialToken extends Krb5Token { CHECKSUM_FLAGS_SIZE; if (context.getCredDelegState()) { - if (context.getCaller() == GSSUtil.CALLER_HTTP_NEGOTIATE && + if (context.getCaller() instanceof HttpCaller && !serviceTicket.getFlags()[Krb5.TKT_OPTS_DELEGATE]) { // When the caller is HTTP/SPNEGO and OK-AS-DELEGATE // is not present in the service ticket, delegation diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java index 3fb48351a9c..ddbd48b04eb 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -26,11 +26,10 @@ package sun.security.jgss.krb5; import org.ietf.jgss.*; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.spi.*; import sun.security.krb5.*; import javax.security.auth.kerberos.*; -import java.io.IOException; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.AccessController; @@ -80,7 +79,7 @@ public class Krb5AcceptCredential } } - static Krb5AcceptCredential getInstance(final int caller, Krb5NameElement name) + static Krb5AcceptCredential getInstance(final GSSCaller caller, Krb5NameElement name) throws GSSException { final String serverPrinc = (name == null? null: @@ -93,7 +92,7 @@ public class Krb5AcceptCredential new PrivilegedExceptionAction() { public KerberosKey[] run() throws Exception { return Krb5Util.getKeys( - caller == GSSUtil.CALLER_UNKNOWN ? GSSUtil.CALLER_ACCEPT: caller, + caller == GSSCaller.CALLER_UNKNOWN ? GSSCaller.CALLER_ACCEPT: caller, serverPrinc, acc); }}); } catch (PrivilegedActionException e) { diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java index 9e92a6fd81e..f2ef7d59875 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -28,6 +28,7 @@ package sun.security.jgss.krb5; import org.ietf.jgss.*; import sun.misc.HexDumpEncoder; import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.spi.*; import sun.security.jgss.TokenTracker; import sun.security.krb5.*; @@ -37,8 +38,6 @@ import java.io.IOException; import java.security.Provider; import java.security.AccessController; import java.security.AccessControlContext; -import java.security.GeneralSecurityException; -import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import javax.crypto.Cipher; @@ -113,14 +112,14 @@ class Krb5Context implements GSSContextSpi { // stored elsewhere private Credentials serviceCreds; private KrbApReq apReq; - final private int caller; + final private GSSCaller caller; private static final boolean DEBUG = Krb5Util.DEBUG; /** * Constructor for Krb5Context to be called on the context initiator's * side. */ - Krb5Context(int caller, Krb5NameElement peerName, Krb5CredElement myCred, + Krb5Context(GSSCaller caller, Krb5NameElement peerName, Krb5CredElement myCred, int lifetime) throws GSSException { @@ -138,7 +137,7 @@ class Krb5Context implements GSSContextSpi { * Constructor for Krb5Context to be called on the context acceptor's * side. */ - Krb5Context(int caller, Krb5CredElement myCred) + Krb5Context(GSSCaller caller, Krb5CredElement myCred) throws GSSException { this.caller = caller; this.myCred = myCred; @@ -148,7 +147,7 @@ class Krb5Context implements GSSContextSpi { /** * Constructor for Krb5Context to import a previously exported context. */ - public Krb5Context(int caller, byte [] interProcessToken) + public Krb5Context(GSSCaller caller, byte [] interProcessToken) throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "GSS Import Context not available"); @@ -573,7 +572,7 @@ class Krb5Context implements GSSContextSpi { // SubjectComber.find // instead of Krb5Util.getTicket return Krb5Util.getTicket( - GSSUtil.CALLER_UNKNOWN, + GSSCaller.CALLER_UNKNOWN, // since it's useSubjectCredsOnly here, // don't worry about the null myName.getKrb5PrincipalName().getName(), @@ -1280,7 +1279,7 @@ class Krb5Context implements GSSContextSpi { } } - int getCaller() { + GSSCaller getCaller() { // Currently used by InitialToken only return caller; } diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java index 8e9cd1b8fec..1aac87223e1 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -26,7 +26,7 @@ package sun.security.jgss.krb5; import org.ietf.jgss.*; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.spi.*; import sun.security.krb5.*; import sun.security.krb5.Config; @@ -138,7 +138,7 @@ public class Krb5InitCredential this.krb5Credentials = delegatedCred; } - static Krb5InitCredential getInstance(int caller, Krb5NameElement name, + static Krb5InitCredential getInstance(GSSCaller caller, Krb5NameElement name, int initLifetime) throws GSSException { @@ -305,7 +305,7 @@ public class Krb5InitCredential // XXX call to this.destroy() should destroy the locally cached copy // of krb5Credentials and then call super.destroy(). - private static KerberosTicket getTgt(int caller, Krb5NameElement name, + private static KerberosTicket getTgt(GSSCaller caller, Krb5NameElement name, int initLifetime) throws GSSException { @@ -337,8 +337,8 @@ public class Krb5InitCredential final AccessControlContext acc = AccessController.getContext(); try { - final int realCaller = (caller == GSSUtil.CALLER_UNKNOWN) - ? GSSUtil.CALLER_INITIATE + final GSSCaller realCaller = (caller == GSSCaller.CALLER_UNKNOWN) + ? GSSCaller.CALLER_INITIATE : caller; return AccessController.doPrivileged( new PrivilegedExceptionAction() { diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java index 3977777426a..5e32977c644 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. 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 @@ -27,12 +27,10 @@ package sun.security.jgss.krb5; import org.ietf.jgss.*; import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.spi.*; import javax.security.auth.kerberos.ServicePermission; import java.security.Provider; -import sun.security.util.DerOutputStream; -import sun.security.util.ObjectIdentifier; -import java.io.IOException; import java.util.Vector; /** @@ -62,7 +60,7 @@ public final class Krb5MechFactory implements MechanismFactory { GSSName.NT_EXPORT_NAME, NT_GSS_KRB5_PRINCIPAL}; - final private int caller; + final private GSSCaller caller; private static Krb5CredElement getCredFromSubject(GSSNameSpi name, boolean initiate) @@ -88,7 +86,7 @@ public final class Krb5MechFactory implements MechanismFactory { return result; } - public Krb5MechFactory(int caller) { + public Krb5MechFactory(GSSCaller caller) { this.caller = caller; } diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java index 62b5795155a..849dbc450cb 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. 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 @@ -32,6 +32,7 @@ import javax.security.auth.Subject; import javax.security.auth.login.LoginException; import java.security.AccessControlContext; import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.krb5.Credentials; import sun.security.krb5.EncryptionKey; @@ -67,7 +68,7 @@ public class Krb5Util { * * NOTE: This method is used by JSSE Kerberos Cipher Suites */ - public static KerberosTicket getTicketFromSubjectAndTgs(int caller, + public static KerberosTicket getTicketFromSubjectAndTgs(GSSCaller caller, String clientPrincipal, String serverPrincipal, String tgsPrincipal, AccessControlContext acc) throws LoginException, KrbException, IOException { @@ -138,7 +139,7 @@ public class Krb5Util { * useSubjectCredsOnly is false, then obtain ticket from * a LoginContext. */ - static KerberosTicket getTicket(int caller, + static KerberosTicket getTicket(GSSCaller caller, String clientPrincipal, String serverPrincipal, AccessControlContext acc) throws LoginException { @@ -168,7 +169,7 @@ public class Krb5Util { * * NOTE: This method is used by JSSE Kerberos Cipher Suites */ - public static Subject getSubject(int caller, + public static Subject getSubject(GSSCaller caller, AccessControlContext acc) throws LoginException { // Try to get the Subject from acc @@ -190,7 +191,7 @@ public class Krb5Util { * * NOTE: This method is used by JSSE Kerberos Cipher Suites */ - public static KerberosKey[] getKeys(int caller, + public static KerberosKey[] getKeys(GSSCaller caller, String serverPrincipal, AccessControlContext acc) throws LoginException { diff --git a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoMechFactory.java b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoMechFactory.java index d7829672ed8..ae12d6b3a78 100644 --- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoMechFactory.java +++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoMechFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -90,7 +90,7 @@ public final class SpNegoMechFactory implements MechanismFactory { return result; } - public SpNegoMechFactory(int caller) { + public SpNegoMechFactory(GSSCaller caller) { manager = new GSSManagerImpl(caller, false); Oid[] mechs = manager.getMechs(); availableMechs = new Oid[mechs.length-1]; diff --git a/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSFactory.java b/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSFactory.java index 315e560065a..7e2146c9e3f 100644 --- a/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSFactory.java +++ b/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -26,17 +26,11 @@ package sun.security.jgss.wrapper; import java.io.UnsupportedEncodingException; -import java.security.AccessController; -import java.security.AccessControlContext; -import java.security.PrivilegedAction; import java.security.Provider; -import java.util.Set; import java.util.Vector; -import java.util.Iterator; -import javax.security.auth.Subject; -import javax.security.auth.kerberos.*; import org.ietf.jgss.*; import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.GSSExceptionImpl; import sun.security.jgss.spi.*; @@ -49,7 +43,7 @@ import sun.security.jgss.spi.*; public final class NativeGSSFactory implements MechanismFactory { GSSLibStub cStub = null; - private final int caller; + private final GSSCaller caller; private GSSCredElement getCredFromSubject(GSSNameElement name, boolean initiate) @@ -74,7 +68,7 @@ public final class NativeGSSFactory implements MechanismFactory { return result; } - public NativeGSSFactory(int caller) { + public NativeGSSFactory(GSSCaller caller) { this.caller = caller; // Have to call setMech(Oid) explicitly before calling other // methods. Otherwise, NPE may be thrown unexpectantly diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java index f29397da25a..08877ba1c83 100644 --- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -46,13 +46,12 @@ import javax.net.ssl.*; import javax.security.auth.Subject; import javax.security.auth.kerberos.KerberosPrincipal; import sun.security.jgss.krb5.Krb5Util; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager; import sun.security.ssl.HandshakeMessage.*; import sun.security.ssl.CipherSuite.*; -import static sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.KeyExchange.*; /** @@ -364,7 +363,7 @@ final class ClientHandshaker extends Handshaker { new PrivilegedExceptionAction() { public Subject run() throws Exception { return Krb5Util.getSubject( - GSSUtil.CALLER_SSL_CLIENT, + GSSCaller.CALLER_SSL_CLIENT, getAccSE()); }}); } catch (PrivilegedActionException e) { diff --git a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java index cb7543b3fd5..e79026e48e4 100644 --- a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. 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 @@ -34,19 +34,16 @@ import java.security.PrivilegedActionException; import java.security.SecureRandom; import java.net.InetAddress; -import javax.net.ssl.SSLException; import javax.security.auth.kerberos.KerberosTicket; import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.ServicePermission; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; -import sun.security.krb5.Config; import sun.security.krb5.EncryptionKey; import sun.security.krb5.EncryptedData; import sun.security.krb5.PrincipalName; import sun.security.krb5.Realm; -import sun.security.krb5.KrbException; import sun.security.krb5.internal.Ticket; import sun.security.krb5.internal.EncTicketPart; import sun.security.krb5.internal.crypto.KeyUsage; @@ -310,7 +307,7 @@ final class KerberosClientKeyExchange extends HandshakeMessage { new PrivilegedExceptionAction() { public KerberosTicket run() throws Exception { return Krb5Util.getTicketFromSubjectAndTgs( - GSSUtil.CALLER_SSL_CLIENT, + GSSCaller.CALLER_SSL_CLIENT, clientPrincipal, serverPrincipal, tgsPrincipal, acc); }}); diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java index ab2ebd3d8f7..772cdb65838 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. 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 @@ -43,7 +43,7 @@ import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.ServicePermission; import sun.security.jgss.krb5.Krb5Util; -import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager; @@ -367,7 +367,7 @@ final class ServerHandshaker extends Handshaker { new PrivilegedExceptionAction() { public Subject run() throws Exception { return Krb5Util.getSubject( - GSSUtil.CALLER_SSL_SERVER, + GSSCaller.CALLER_SSL_SERVER, getAccSE()); }}); } catch (PrivilegedActionException e) { @@ -918,7 +918,7 @@ final class ServerHandshaker extends Handshaker { public KerberosKey[] run() throws Exception { // get kerberos key for the default principal return Krb5Util.getKeys( - GSSUtil.CALLER_SSL_SERVER, null, acc); + GSSCaller.CALLER_SSL_SERVER, null, acc); }}); // check permission to access and use the secret key of the diff --git a/jdk/test/sun/security/jgss/DefaultGssConfig.java b/jdk/test/sun/security/jgss/DefaultGssConfig.java index 5959f8ebcbc..672be7481f5 100644 --- a/jdk/test/sun/security/jgss/DefaultGssConfig.java +++ b/jdk/test/sun/security/jgss/DefaultGssConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2009 Sun Microsystems, Inc. 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 @@ -34,6 +34,7 @@ import java.security.NoSuchAlgorithmException; import java.security.URIParameter; import javax.security.auth.login.Configuration; import sun.security.jgss.GSSUtil; +import sun.security.jgss.GSSCaller; import sun.security.jgss.LoginConfigImpl; public class DefaultGssConfig { @@ -56,11 +57,11 @@ public class DefaultGssConfig { Configuration.getConfiguration(); // 3. Make sure there're default entries for GSS krb5 client/server - LoginConfigImpl lc = new LoginConfigImpl(GSSUtil.CALLER_INITIATE, GSSUtil.GSS_KRB5_MECH_OID); + LoginConfigImpl lc = new LoginConfigImpl(GSSCaller.CALLER_INITIATE, GSSUtil.GSS_KRB5_MECH_OID); if (lc.getAppConfigurationEntry("").length == 0) { throw new Exception("No default config for GSS krb5 client"); } - lc = new LoginConfigImpl(GSSUtil.CALLER_ACCEPT, GSSUtil.GSS_KRB5_MECH_OID); + lc = new LoginConfigImpl(GSSCaller.CALLER_ACCEPT, GSSUtil.GSS_KRB5_MECH_OID); if (lc.getAppConfigurationEntry("").length == 0) { throw new Exception("No default config for GSS krb5 server"); } diff --git a/jdk/test/sun/security/jgss/GssNPE.java b/jdk/test/sun/security/jgss/GssNPE.java index 9d9b14470c0..815e248ab73 100644 --- a/jdk/test/sun/security/jgss/GssNPE.java +++ b/jdk/test/sun/security/jgss/GssNPE.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. 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 @@ -27,7 +27,6 @@ * @summary GSS throws NPE when the JAAS config file does not exist */ -import org.ietf.jgss.*; import sun.security.jgss.*; public class GssNPE { @@ -40,7 +39,7 @@ public class GssNPE { // not exist. New caller-enabled JGSS changed this. this bug fix will // revert to the old behavior. try { - GSSUtil.login(GSSUtil.CALLER_INITIATE, GSSUtil.GSS_KRB5_MECH_OID); + GSSUtil.login(GSSCaller.CALLER_INITIATE, GSSUtil.GSS_KRB5_MECH_OID); } catch (SecurityException se) { if (se.getCause() instanceof java.io.IOException) { // what had been and should be... diff --git a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java new file mode 100644 index 00000000000..9505455f947 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java @@ -0,0 +1,341 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6578647 + * @summary Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication() + * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock HttpNegotiateServer + */ + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpPrincipal; +import com.sun.security.auth.module.Krb5LoginModule; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.InetAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URL; +import java.security.PrivilegedExceptionAction; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.Subject; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSManager; +import sun.security.jgss.GSSUtil; +import sun.net.spi.nameservice.NameService; +import sun.net.spi.nameservice.NameServiceDescriptor; +import sun.security.krb5.Config; + +/** + * Basic JGSS/krb5 test with 3 parties: client, server, backend server. Each + * party uses JAAS login to get subjects and executes JGSS calls using + * Subject.doAs. + */ +public class HttpNegotiateServer implements NameServiceDescriptor { + + // Two realm, web server in one, proxy server in another + final static String REALM_WEB = "WEB.DOMAIN"; + final static String REALM_PROXY = "PROXY.DOMAIN"; + final static String KRB5_CONF = "web.conf"; + final static String KRB5_TAB = "web.ktab"; + + // user principals + final static String WEB_USER = "web"; + final static char[] WEB_PASS = "webby".toCharArray(); + final static String PROXY_USER = "pro"; + final static char[] PROXY_PASS = "proxy".toCharArray(); + final static int WEB_PORT = 17840; + + final static String WEB_HOST = "host.web.domain"; + final static String PROXY_HOST = "host.proxy.domain"; + final static int PROXY_PORT = 17841; + + // web page content + final static String CONTENT = "Hello, World!"; + + // URLs for web test, proxy test. The proxy server is not a real proxy + // since it fakes the same content for any URL. :) + final static URL webUrl, proxyUrl; + static { + URL u1 = null, u2 = null; + try { + u1 = new URL("http://" + WEB_HOST +":" + WEB_PORT + "/a/b/c"); + u2 = new URL("http://nosuchplace/a/b/c"); + } catch (Exception e) { + } + webUrl = u1; proxyUrl = u2; + } + + /** + * This Authenticator checks everything: + * scheme, protocol, requestor type, host, port, and url + */ + static class KnowAllAuthenticator extends java.net.Authenticator { + public PasswordAuthentication getPasswordAuthentication () { + if (!getRequestingScheme().equalsIgnoreCase("Negotiate")) { + throw new RuntimeException("Bad scheme"); + } + if (!getRequestingProtocol().equalsIgnoreCase("HTTP")) { + throw new RuntimeException("Bad protocol"); + } + if (getRequestorType() == RequestorType.SERVER) { + if (!this.getRequestingHost().equalsIgnoreCase(webUrl.getHost())) { + throw new RuntimeException("Bad host"); + } + if (this.getRequestingPort() != webUrl.getPort()) { + throw new RuntimeException("Bad port"); + } + if (!this.getRequestingURL().equals(webUrl)) { + throw new RuntimeException("Bad url"); + } + return new PasswordAuthentication( + WEB_USER+"@"+REALM_WEB, WEB_PASS); + } else if (getRequestorType() == RequestorType.PROXY) { + if (!this.getRequestingHost().equalsIgnoreCase(PROXY_HOST)) { + throw new RuntimeException("Bad host"); + } + if (this.getRequestingPort() != PROXY_PORT) { + throw new RuntimeException("Bad port"); + } + if (!this.getRequestingURL().equals(proxyUrl)) { + throw new RuntimeException("Bad url"); + } + return new PasswordAuthentication( + PROXY_USER+"@"+REALM_PROXY, PROXY_PASS); + } else { + throw new RuntimeException("Bad requster type"); + } + } + } + + public static void main(String[] args) + throws Exception { + + KDC kdcw = new KDC(REALM_WEB, 0, true); + kdcw.addPrincipal(WEB_USER, WEB_PASS); + kdcw.addPrincipalRandKey("krbtgt/" + REALM_WEB); + kdcw.addPrincipalRandKey("HTTP/" + WEB_HOST); + + KDC kdcp = new KDC(REALM_PROXY, 0, true); + kdcp.addPrincipal(PROXY_USER, PROXY_PASS); + kdcp.addPrincipalRandKey("krbtgt/" + REALM_PROXY); + kdcp.addPrincipalRandKey("HTTP/" + PROXY_HOST); + + KDC.writeMultiKtab(KRB5_TAB, kdcw, kdcp); + KDC.saveConfig(KRB5_CONF, kdcw, kdcp, + "default_keytab_name = " + KRB5_TAB, + "[domain_realm]", + "", + ".web.domain="+REALM_WEB, + ".proxy.domain="+REALM_PROXY); + + System.setProperty("java.security.krb5.conf", KRB5_CONF); + Config.refresh(); + + HttpServer h1 = httpd(WEB_PORT, "Negotiate", false, + "HTTP/" + WEB_HOST + "@" + REALM_WEB, KRB5_TAB); + HttpServer h2 = httpd(PROXY_PORT, "Negotiate", true, + "HTTP/" + PROXY_HOST + "@" + REALM_PROXY, KRB5_TAB); + + try { + + BufferedReader reader; + java.net.Authenticator.setDefault(new KnowAllAuthenticator()); + + reader = new BufferedReader(new InputStreamReader( + webUrl.openConnection().getInputStream())); + if (!reader.readLine().equals(CONTENT)) { + throw new RuntimeException("Bad content"); + } + + reader = new BufferedReader(new InputStreamReader( + proxyUrl.openConnection( + new Proxy(Proxy.Type.HTTP, + new InetSocketAddress(PROXY_HOST, PROXY_PORT))) + .getInputStream())); + if (!reader.readLine().equals(CONTENT)) { + throw new RuntimeException("Bad content"); + } + } finally { + // Must stop. Seems there's no HttpServer.startAsDaemon() + if (h1 != null) h1.stop(0); + if (h2 != null) h2.stop(0); + } + } + + /** + * Creates and starts an HTTP or proxy server that requires + * Negotiate authentication. + * @param scheme "Negotiate" or "Kerberos" + * @param principal the krb5 service principal the server runs with + * @return the server + */ + public static HttpServer httpd(int port, String scheme, boolean proxy, + String principal, String ktab) throws Exception { + MyHttpHandler h = new MyHttpHandler(); + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + HttpContext hc = server.createContext("/", h); + hc.setAuthenticator(new MyServerAuthenticator( + proxy, scheme, principal, ktab)); + server.start(); + return server; + } + + static class MyHttpHandler implements HttpHandler { + public void handle(HttpExchange t) throws IOException { + t.sendResponseHeaders(200, 0); + t.getResponseBody().write(CONTENT.getBytes()); + t.close(); + } + } + + static class MyServerAuthenticator + extends com.sun.net.httpserver.Authenticator { + Subject s = new Subject(); + GSSManager m = null; + GSSCredential cred = null; + String scheme = null; + String reqHdr = "WWW-Authenticate"; + String respHdr = "Authorization"; + int err = HttpURLConnection.HTTP_UNAUTHORIZED; + + public MyServerAuthenticator(boolean proxy, String scheme, + String principal, String ktab) throws Exception { + + this.scheme = scheme; + if (proxy) { + reqHdr = "Proxy-Authenticate"; + respHdr = "Proxy-Authorization"; + err = HttpURLConnection.HTTP_PROXY_AUTH; + } + + Krb5LoginModule krb5 = new Krb5LoginModule(); + Map map = new HashMap(); + Map shared = new HashMap(); + + map.put("storeKey", "true"); + map.put("isInitiator", "false"); + map.put("useKeyTab", "true"); + map.put("keyTab", ktab); + map.put("principal", principal); + krb5.initialize(s, null, shared, map); + krb5.login(); + krb5.commit(); + m = GSSManager.getInstance(); + cred = Subject.doAs(s, new PrivilegedExceptionAction() { + @Override + public GSSCredential run() throws Exception { + System.err.println("Creating GSSCredential"); + return m.createCredential( + null, + GSSCredential.INDEFINITE_LIFETIME, + MyServerAuthenticator.this.scheme.equalsIgnoreCase("Negotiate")? + GSSUtil.GSS_SPNEGO_MECH_OID: + GSSUtil.GSS_KRB5_MECH_OID, + GSSCredential.ACCEPT_ONLY); + } + }); + } + + @Override + public Result authenticate(HttpExchange exch) { + // The GSContext is stored in an HttpContext attribute named + // "GSSContext" and is created at the first request. + GSSContext c = null; + String auth = exch.getRequestHeaders().getFirst(respHdr); + try { + c = (GSSContext)exch.getHttpContext().getAttributes().get("GSSContext"); + if (auth == null) { // First request + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme); // Challenge! + c = Subject.doAs(s, new PrivilegedExceptionAction() { + @Override + public GSSContext run() throws Exception { + return m.createContext(cred); + } + }); + exch.getHttpContext().getAttributes().put("GSSContext", c); + return new com.sun.net.httpserver.Authenticator.Retry(err); + } else { // Later requests + byte[] token = new sun.misc.BASE64Decoder() + .decodeBuffer(auth.split(" ")[1]); + token = c.acceptSecContext(token, 0, token.length); + Headers map = exch.getResponseHeaders(); + map.set (reqHdr, scheme + " " + new sun.misc.BASE64Encoder() + .encode(token).replaceAll("\\s", "")); + if (c.isEstablished()) { + return new com.sun.net.httpserver.Authenticator.Success( + new HttpPrincipal(c.getSrcName().toString(), "")); + } else { + return new com.sun.net.httpserver.Authenticator.Retry(err); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + public NameService createNameService() throws Exception { + NameService ns = new NameService() { + @Override + public InetAddress[] lookupAllHostAddr(String host) + throws UnknownHostException { + // Everything is localhost + return new InetAddress[]{ + InetAddress.getByAddress(host, new byte[]{127,0,0,1}) + }; + } + @Override + public String getHostByAddr(byte[] addr) + throws UnknownHostException { + // No reverse lookup + throw new UnknownHostException(); + } + }; + return ns; + } + + @Override + public String getProviderName() { + return "mock"; + } + + @Override + public String getType() { + return "ns"; + } +} + diff --git a/jdk/test/sun/security/krb5/auto/KDC.java b/jdk/test/sun/security/krb5/auto/KDC.java index 3e6a7792644..14767c4085c 100644 --- a/jdk/test/sun/security/krb5/auto/KDC.java +++ b/jdk/test/sun/security/krb5/auto/KDC.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. 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 @@ -201,14 +201,14 @@ public class KDC { } /** - * Write all principals' keys into a keytab file. Note that the keys for - * the krbtgt principal for this realm will not be written. + * Write all principals' keys from multiple KDCsinto one keytab file. + * Note that the keys for the krbtgt principals will not be written. *

    * Attention: This method references krb5.conf settings. If you need to * setup krb5.conf later, please call Config.refresh() after * the new setting. For example: *

    -     * kdc.writeKtab("/etc/kdc/ktab");  // Config is initialized,
    +     * KDC.writeKtab("/etc/kdc/ktab", kdc);  // Config is initialized,
          * System.setProperty("java.security.krb5.conf", "/home/mykrb5.conf");
          * Config.refresh();
          * 
    @@ -223,20 +223,31 @@ public class KDC { * @throws sun.security.krb5.KrbException for any realm and/or principal * name error. */ - public void writeKtab(String tab) throws IOException, KrbException { + public static void writeMultiKtab(String tab, KDC... kdcs) + throws IOException, KrbException { KeyTab ktab = KeyTab.create(tab); - for (String name : passwords.keySet()) { - if (name.equals("krbtgt/" + realm)) { - continue; + for (KDC kdc: kdcs) { + for (String name : kdc.passwords.keySet()) { + if (name.equals("krbtgt/" + kdc.realm)) { + continue; + } + ktab.addEntry(new PrincipalName(name + "@" + kdc.realm, + name.indexOf('/') < 0 ? + PrincipalName.KRB_NT_UNKNOWN : + PrincipalName.KRB_NT_SRV_HST), + kdc.passwords.get(name)); } - ktab.addEntry(new PrincipalName(name + "@" + realm, - name.indexOf('/') < 0 ? - PrincipalName.KRB_NT_UNKNOWN : - PrincipalName.KRB_NT_SRV_HST), passwords.get(name)); } ktab.save(); } + /** + * Write a ktab for this KDC. + */ + public void writeKtab(String tab) throws IOException, KrbException { + KDC.writeMultiKtab(tab, this); + } + /** * Adds a new principal to this realm with a given password. * @param user the principal's name. For a service principal, use the diff --git a/jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor new file mode 100644 index 00000000000..32f3a09bb47 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor @@ -0,0 +1 @@ +HttpNegotiateServer