6578647: Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
Reviewed-by: chegar, valeriep
This commit is contained in:
parent
105735aeb6
commit
8a52d1a9d5
@ -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;
|
||||
|
@ -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 = "";
|
||||
}
|
||||
}
|
@ -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 =
|
||||
|
@ -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. <code>pw</code> 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.<br>
|
||||
* 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.<br>
|
||||
*
|
||||
* If this method is called for the second time on a hostname, the answer is
|
||||
* already saved in <code>supported</code>, 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 <String, Boolean>();
|
||||
cache = new HashMap <String, Negotiator>();
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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<callbacks.length; i++) {
|
||||
@ -51,8 +58,8 @@ public class NegotiateCallbackHandler implements CallbackHandler {
|
||||
if (username == null) {
|
||||
PasswordAuthentication passAuth =
|
||||
Authenticator.requestPasswordAuthentication(
|
||||
null, null, 0, null,
|
||||
null, "Negotiate");
|
||||
hci.host, hci.addr, hci.port, hci.protocol,
|
||||
hci.prompt, hci.scheme, hci.url, hci.authType);
|
||||
username = passAuth.getUserName();
|
||||
password = passAuth.getPassword();
|
||||
}
|
||||
@ -66,8 +73,8 @@ public class NegotiateCallbackHandler implements CallbackHandler {
|
||||
if (password == null) {
|
||||
PasswordAuthentication passAuth =
|
||||
Authenticator.requestPasswordAuthentication(
|
||||
null, null, 0, null,
|
||||
null, "Negotiate");
|
||||
hci.host, hci.addr, hci.port, hci.protocol,
|
||||
hci.prompt, hci.scheme, hci.url, hci.authType);
|
||||
username = passAuth.getUserName();
|
||||
password = passAuth.getPassword();
|
||||
}
|
||||
@ -76,7 +83,7 @@ public class NegotiateCallbackHandler implements CallbackHandler {
|
||||
} else {
|
||||
throw new UnsupportedCallbackException(callBack,
|
||||
"Call back not supported");
|
||||
}//else
|
||||
}//for
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2008 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
|
||||
@ -34,9 +34,10 @@ import org.ietf.jgss.Oid;
|
||||
|
||||
import sun.security.jgss.GSSManagerImpl;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
import sun.security.jgss.HttpCaller;
|
||||
|
||||
/**
|
||||
* This class encapsulates all JAAS and JGSS API calls in a seperate class
|
||||
* This class encapsulates all JAAS and JGSS API calls in a separate class
|
||||
* outside NegotiateAuthentication.java so that J2SE build can go smoothly
|
||||
* without the presence of it.
|
||||
*
|
||||
@ -54,21 +55,16 @@ public class NegotiatorImpl extends Negotiator {
|
||||
|
||||
/**
|
||||
* Initialize the object, which includes:<ul>
|
||||
* <li>Find out what GSS mechanism to use from <code>http.negotiate.mechanism.oid</code>,
|
||||
* defaults SPNEGO
|
||||
* <li>Find out what GSS mechanism to use from the system property
|
||||
* <code>http.negotiate.mechanism.oid</code>, defaults SPNEGO
|
||||
* <li>Creating the GSSName for the target host, "HTTP/"+hostname
|
||||
* <li>Creating GSSContext
|
||||
* <li>A first call to initSecContext</ul>
|
||||
* @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");
|
||||
|
40
jdk/src/share/classes/sun/security/jgss/GSSCaller.java
Normal file
40
jdk/src/share/classes/sun/security/jgss/GSSCaller.java
Normal file
@ -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();
|
||||
}
|
||||
|
@ -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(){
|
||||
|
@ -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;
|
||||
}
|
||||
/*
|
||||
|
45
jdk/src/share/classes/sun/security/jgss/HttpCaller.java
Normal file
45
jdk/src/share/classes/sun/security/jgss/HttpCaller.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<PreferencesEntry, MechanismFactory>(5);
|
||||
private HashSet<Oid> mechs = new HashSet<Oid>(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) {
|
||||
|
@ -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
|
||||
|
@ -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<KerberosKey[]>() {
|
||||
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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<KerberosTicket>() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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<Subject>() {
|
||||
public Subject run() throws Exception {
|
||||
return Krb5Util.getSubject(
|
||||
GSSUtil.CALLER_SSL_CLIENT,
|
||||
GSSCaller.CALLER_SSL_CLIENT,
|
||||
getAccSE());
|
||||
}});
|
||||
} catch (PrivilegedActionException e) {
|
||||
|
@ -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<KerberosTicket>() {
|
||||
public KerberosTicket run() throws Exception {
|
||||
return Krb5Util.getTicketFromSubjectAndTgs(
|
||||
GSSUtil.CALLER_SSL_CLIENT,
|
||||
GSSCaller.CALLER_SSL_CLIENT,
|
||||
clientPrincipal, serverPrincipal,
|
||||
tgsPrincipal, acc);
|
||||
}});
|
||||
|
@ -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<Subject>() {
|
||||
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
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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...
|
||||
|
341
jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
Normal file
341
jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
Normal file
@ -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<String, String> map = new HashMap<String, String>();
|
||||
Map<String, Object> shared = new HashMap<String, Object>();
|
||||
|
||||
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<GSSCredential>() {
|
||||
@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<GSSContext>() {
|
||||
@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";
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* Attention: This method references krb5.conf settings. If you need to
|
||||
* setup krb5.conf later, please call <code>Config.refresh()</code> after
|
||||
* the new setting. For example:
|
||||
* <pre>
|
||||
* 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();
|
||||
* </pre>
|
||||
@ -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
|
||||
|
@ -0,0 +1 @@
|
||||
HttpNegotiateServer
|
Loading…
Reference in New Issue
Block a user