提交 08f56866 编写于 作者: C chegar

6882594: Remove static dependancy on NTLM authentication

Reviewed-by: alanb, weijun
上级 94102e29
......@@ -86,9 +86,11 @@ FILES_java = \
sun/net/www/protocol/http/AuthCache.java \
sun/net/www/protocol/http/AuthCacheImpl.java \
sun/net/www/protocol/http/AuthCacheValue.java \
sun/net/www/protocol/http/AuthScheme.java \
sun/net/www/protocol/http/BasicAuthentication.java \
sun/net/www/protocol/http/DigestAuthentication.java \
sun/net/www/protocol/http/NTLMAuthentication.java \
sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
sun/net/www/protocol/http/NegotiateAuthentication.java \
sun/net/www/protocol/http/NegotiatorImpl.java \
sun/net/www/protocol/http/NegotiateCallbackHandler.java \
......
......@@ -25,14 +25,6 @@
package sun.net.www.protocol.http;
import java.io.IOException;
import java.net.URL;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Enumeration;
import java.util.HashMap;
/**
* @author Michael McMahon
*
......@@ -49,7 +41,7 @@ public interface AuthCache {
* A:[B:]C:D:E[:F] Between 4 and 6 fields separated by ":"
* where the fields have the following meaning:
* A is "s" or "p" for server or proxy authentication respectively
* B is optional and is "D", "B", or "N" for digest, basic or ntlm auth.
* B is optional and is the {@link AuthScheme}, e.g. BASIC, DIGEST, NTLM, etc
* C is either "http" or "https"
* D is the hostname
* E is the port number
......
......@@ -25,15 +25,8 @@
package sun.net.www.protocol.http;
import java.io.IOException;
import java.io.Serializable;
import java.net.*;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Enumeration;
import java.util.HashMap;
import java.net.PasswordAuthentication;
/**
* AuthCacheValue: interface to minimise exposure to authentication cache
......@@ -62,8 +55,16 @@ public abstract class AuthCacheValue implements Serializable {
AuthCacheValue() {}
/**
* Proxy or Server
*/
abstract Type getAuthType ();
/**
* Authentication scheme
*/
abstract AuthScheme getAuthScheme();
/**
* name of server/proxy
*/
......
/*
* 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;
/* Authentication schemes supported by the http implementation. New schemes, if
* supported, should be defined here.
*/
public enum AuthScheme {
BASIC,
DIGEST,
NTLM,
NEGOTIATE,
KERBEROS,
UNKNOWN;
}
......@@ -85,6 +85,11 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
AuthCacheValue.Type.Server:
AuthCacheValue.Type.Proxy;
}
AuthScheme getAuthScheme() {
return authScheme;
}
public String getHost() {
return host;
}
......@@ -151,7 +156,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
}
//public String toString () {
//return ("{"+type+":"+authType+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
//return ("{"+type+":"+authScheme+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
//}
// REMIND: This cache just grows forever. We should put in a bounded
......@@ -160,8 +165,8 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
/** The type (server/proxy) of authentication this is. Used for key lookup */
char type;
/** The authentication type (basic/digest). Also used for key lookup */
char authType;
/** The authentication scheme (basic/digest). Also used for key lookup */
AuthScheme authScheme;
/** The protocol/scheme (i.e. http or https ). Need to keep the caches
* logically separate for the two protocols. This field is only used
......@@ -183,9 +188,9 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
String path;
/** Use this constructor only for proxy entries */
AuthenticationInfo(char type, char authType, String host, int port, String realm) {
AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
this.type = type;
this.authType = authType;
this.authScheme = authScheme;
this.protocol = "";
this.host = host.toLowerCase();
this.port = port;
......@@ -206,9 +211,9 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
* Constructor used to limit the authorization to the path within
* the URL. Use this constructor for origin server entries.
*/
AuthenticationInfo(char type, char authType, URL url, String realm) {
AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
this.type = type;
this.authType = authType;
this.authScheme = authScheme;
this.protocol = url.getProtocol().toLowerCase();
this.host = url.getHost().toLowerCase();
this.port = url.getPort();
......@@ -264,12 +269,12 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
* In this case we do not use the path because the protection space
* is identified by the host:port:realm only
*/
static AuthenticationInfo getServerAuth(URL url, String realm, char atype) {
static AuthenticationInfo getServerAuth(URL url, String realm, AuthScheme scheme) {
int port = url.getPort();
if (port == -1) {
port = url.getDefaultPort();
}
String key = SERVER_AUTHENTICATION + ":" + atype + ":" + url.getProtocol().toLowerCase()
String key = SERVER_AUTHENTICATION + ":" + scheme + ":" + url.getProtocol().toLowerCase()
+ ":" + url.getHost().toLowerCase() + ":" + port + ":" + realm;
AuthenticationInfo cached = getAuth(key, null);
if ((cached == null) && requestIsInProgress (key)) {
......@@ -308,8 +313,8 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
* Used in response to a challenge. Note, the protocol field is always
* blank for proxies.
*/
static AuthenticationInfo getProxyAuth(String host, int port, String realm, char atype) {
String key = PROXY_AUTHENTICATION + ":" + atype + "::" + host.toLowerCase()
static AuthenticationInfo getProxyAuth(String host, int port, String realm, AuthScheme scheme) {
String key = PROXY_AUTHENTICATION + ":" + scheme + "::" + host.toLowerCase()
+ ":" + port + ":" + realm;
AuthenticationInfo cached = (AuthenticationInfo) cache.get(key, null);
if ((cached == null) && requestIsInProgress (key)) {
......@@ -409,7 +414,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
// This must be kept in sync with the getXXXAuth() methods in this
// class.
if (includeRealm) {
return type + ":" + authType + ":" + protocol + ":"
return type + ":" + authScheme + ":" + protocol + ":"
+ host + ":" + port + ":" + realm;
} else {
return type + ":" + protocol + ":" + host + ":" + port;
......
......@@ -44,8 +44,6 @@ class BasicAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 100L;
static final char BASIC_AUTH = 'B';
/** The authentication string for this host, port, and realm. This is
a simple BASE64 encoding of "login:password". */
String auth;
......@@ -56,7 +54,7 @@ class BasicAuthentication extends AuthenticationInfo {
public BasicAuthentication(boolean isProxy, String host, int port,
String realm, PasswordAuthentication pw) {
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
BASIC_AUTH, host, port, realm);
AuthScheme.BASIC, host, port, realm);
String plain = pw.getUserName() + ":";
byte[] nameBytes = null;
try {
......@@ -86,7 +84,7 @@ class BasicAuthentication extends AuthenticationInfo {
public BasicAuthentication(boolean isProxy, String host, int port,
String realm, String auth) {
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
BASIC_AUTH, host, port, realm);
AuthScheme.BASIC, host, port, realm);
this.auth = "Basic " + auth;
}
......@@ -96,7 +94,7 @@ class BasicAuthentication extends AuthenticationInfo {
public BasicAuthentication(boolean isProxy, URL url, String realm,
PasswordAuthentication pw) {
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
BASIC_AUTH, url, realm);
AuthScheme.BASIC, url, realm);
String plain = pw.getUserName() + ":";
byte[] nameBytes = null;
try {
......@@ -126,7 +124,7 @@ class BasicAuthentication extends AuthenticationInfo {
public BasicAuthentication(boolean isProxy, URL url, String realm,
String auth) {
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
BASIC_AUTH, url, realm);
AuthScheme.BASIC, url, realm);
this.auth = "Basic " + auth;
}
......
......@@ -38,7 +38,6 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT;
/**
* DigestAuthentication: Encapsulate an http server authentication using
* the "Digest" scheme, as described in RFC2069 and updated in RFC2617
......@@ -50,8 +49,6 @@ class DigestAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 100L;
static final char DIGEST_AUTH = 'D';
private String authMethod;
// Authentication parameters defined in RFC2617.
......@@ -178,7 +175,10 @@ class DigestAuthentication extends AuthenticationInfo {
public DigestAuthentication(boolean isProxy, URL url, String realm,
String authMethod, PasswordAuthentication pw,
Parameters params) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,url, realm);
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
AuthScheme.DIGEST,
url,
realm);
this.authMethod = authMethod;
this.pw = pw;
this.params = params;
......@@ -187,7 +187,11 @@ class DigestAuthentication extends AuthenticationInfo {
public DigestAuthentication(boolean isProxy, String host, int port, String realm,
String authMethod, PasswordAuthentication pw,
Parameters params) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,host, port, realm);
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
AuthScheme.DIGEST,
host,
port,
realm);
this.authMethod = authMethod;
this.pw = pw;
this.params = params;
......
......@@ -62,6 +62,12 @@ import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.net.MalformedURLException;
import java.nio.ByteBuffer;
import static sun.net.www.protocol.http.AuthScheme.BASIC;
import static sun.net.www.protocol.http.AuthScheme.DIGEST;
import static sun.net.www.protocol.http.AuthScheme.NTLM;
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
import static sun.net.www.protocol.http.AuthScheme.UNKNOWN;
/**
* A class to represent an HTTP connection to a remote object.
......@@ -231,9 +237,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
boolean needToCheck = true;
private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */
private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */
/* try auth without calling Authenticator */
private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();
private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth();
/* try auth without calling Authenticator. Used for transparent NTLM authentication */
private boolean tryTransparentNTLMServer = true;
private boolean tryTransparentNTLMProxy = true;
/* Used by Windows specific code */
Object authObj;
......@@ -1270,7 +1278,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
String raw = srvHdr.raw();
if (!doingNTLM2ndStage) {
if ((serverAuthentication != null)&&
!(serverAuthentication instanceof NTLMAuthentication)) {
serverAuthentication.getAuthScheme() != NTLM) {
if (serverAuthentication.isAuthorizationStale (raw)) {
/* we can retry with the current credentials */
disconnectInternal();
......@@ -1523,8 +1531,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
*/
private AuthenticationInfo
resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) {
if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof
NTLMAuthentication)) {
if ((proxyAuthentication != null )&&
proxyAuthentication.getAuthScheme() != NTLM) {
String raw = auth.raw();
if (proxyAuthentication.isAuthorizationStale (raw)) {
/* we can retry with the current credentials */
......@@ -1776,28 +1784,31 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
HeaderParser p = authhdr.headerParser();
String realm = p.findValue("realm");
String scheme = authhdr.scheme();
char schemeID;
AuthScheme authScheme = UNKNOWN;
if ("basic".equalsIgnoreCase(scheme)) {
schemeID = BasicAuthentication.BASIC_AUTH;
authScheme = BASIC;
} else if ("digest".equalsIgnoreCase(scheme)) {
schemeID = DigestAuthentication.DIGEST_AUTH;
authScheme = DIGEST;
} else if ("ntlm".equalsIgnoreCase(scheme)) {
schemeID = NTLMAuthentication.NTLM_AUTH;
authScheme = NTLM;
doingNTLMp2ndStage = true;
} else if ("Kerberos".equalsIgnoreCase(scheme)) {
schemeID = NegotiateAuthentication.KERBEROS_AUTH;
authScheme = KERBEROS;
doingNTLMp2ndStage = true;
} else if ("Negotiate".equalsIgnoreCase(scheme)) {
schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
authScheme = NEGOTIATE;
doingNTLMp2ndStage = true;
} else {
schemeID = 0;
}
if (realm == null)
realm = "";
ret = AuthenticationInfo.getProxyAuth(host, port, realm, schemeID);
ret = AuthenticationInfo.getProxyAuth(host,
port,
realm,
authScheme);
if (ret == null) {
if (schemeID == BasicAuthentication.BASIC_AUTH) {
switch (authScheme) {
case BASIC:
InetAddress addr = null;
try {
final String finalHost = host;
......@@ -1818,9 +1829,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (a != null) {
ret = new BasicAuthentication(true, host, port, realm, a);
}
} else if (schemeID == DigestAuthentication.DIGEST_AUTH) {
PasswordAuthentication a =
privilegedRequestPasswordAuthentication(
break;
case DIGEST:
a = privilegedRequestPasswordAuthentication(
host, null, port, url.getProtocol(),
realm, scheme, url, RequestorType.PROXY);
if (a != null) {
......@@ -1829,29 +1840,49 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
ret = new DigestAuthentication(true, host, port, realm,
scheme, a, params);
}
} else if (schemeID == NTLMAuthentication.NTLM_AUTH) {
PasswordAuthentication a = null;
if (!tryTransparentNTLMProxy) {
a = privilegedRequestPasswordAuthentication(
host, null, port, url.getProtocol(),
"", scheme, url, RequestorType.PROXY);
}
/* If we are not trying transparent authentication then
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username
* and password will be picked up from the current logged
* on users credentials.
*/
if (tryTransparentNTLMProxy ||
(!tryTransparentNTLMProxy && a != null)) {
ret = new NTLMAuthentication(true, host, port, a);
}
break;
case NTLM:
if (NTLMAuthenticationProxy.proxy.supported) {
/* tryTransparentNTLMProxy will always be true the first
* time around, but verify that the platform supports it
* otherwise don't try. */
if (tryTransparentNTLMProxy) {
tryTransparentNTLMProxy =
NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
}
a = null;
if (tryTransparentNTLMProxy) {
HttpCapture.finest("Trying Transparent NTLM authentication");
} else {
a = privilegedRequestPasswordAuthentication(
host, null, port, url.getProtocol(),
"", scheme, url, RequestorType.PROXY);
}
/* If we are not trying transparent authentication then
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username
* and password will be picked up from the current logged
* on users credentials.
*/
if (tryTransparentNTLMProxy ||
(!tryTransparentNTLMProxy && a != null)) {
ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
}
tryTransparentNTLMProxy = false;
} else if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
/* set to false so that we do not try again */
tryTransparentNTLMProxy = false;
}
break;
case NEGOTIATE:
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
} else if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
break;
case KERBEROS:
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
break;
case UNKNOWN:
HttpCapture.finest("Unknown/Unsupported authentication scheme: " + scheme);
default:
throw new AssertionError("should not reach here");
}
}
// For backwards compatibility, we also try defaultAuth
......@@ -1896,27 +1927,26 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
HeaderParser p = authhdr.headerParser();
String realm = p.findValue("realm");
String scheme = authhdr.scheme();
char schemeID;
AuthScheme authScheme = UNKNOWN;
if ("basic".equalsIgnoreCase(scheme)) {
schemeID = BasicAuthentication.BASIC_AUTH;
authScheme = BASIC;
} else if ("digest".equalsIgnoreCase(scheme)) {
schemeID = DigestAuthentication.DIGEST_AUTH;
authScheme = DIGEST;
} else if ("ntlm".equalsIgnoreCase(scheme)) {
schemeID = NTLMAuthentication.NTLM_AUTH;
authScheme = NTLM;
doingNTLM2ndStage = true;
} else if ("Kerberos".equalsIgnoreCase(scheme)) {
schemeID = NegotiateAuthentication.KERBEROS_AUTH;
authScheme = KERBEROS;
doingNTLM2ndStage = true;
} else if ("Negotiate".equalsIgnoreCase(scheme)) {
schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
authScheme = NEGOTIATE;
doingNTLM2ndStage = true;
} else {
schemeID = 0;
}
domain = p.findValue ("domain");
if (realm == null)
realm = "";
ret = AuthenticationInfo.getServerAuth(url, realm, schemeID);
ret = AuthenticationInfo.getServerAuth(url, realm, authScheme);
InetAddress addr = null;
if (ret == null) {
try {
......@@ -1931,13 +1961,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
port = url.getDefaultPort();
}
if (ret == null) {
if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
switch(authScheme) {
case KERBEROS:
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
}
if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
break;
case NEGOTIATE:
ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
}
if (schemeID == BasicAuthentication.BASIC_AUTH) {
break;
case BASIC:
PasswordAuthentication a =
privilegedRequestPasswordAuthentication(
url.getHost(), addr, port, url.getProtocol(),
......@@ -1945,45 +1976,60 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (a != null) {
ret = new BasicAuthentication(false, url, realm, a);
}
}
if (schemeID == DigestAuthentication.DIGEST_AUTH) {
PasswordAuthentication a =
privilegedRequestPasswordAuthentication(
break;
case DIGEST:
a = privilegedRequestPasswordAuthentication(
url.getHost(), addr, port, url.getProtocol(),
realm, scheme, url, RequestorType.SERVER);
if (a != null) {
digestparams = new DigestAuthentication.Parameters();
ret = new DigestAuthentication(false, url, realm, scheme, a, digestparams);
}
}
break;
case NTLM:
if (NTLMAuthenticationProxy.proxy.supported) {
URL url1;
try {
url1 = new URL (url, "/"); /* truncate the path */
} catch (Exception e) {
url1 = url;
}
if (schemeID == NTLMAuthentication.NTLM_AUTH) {
URL url1;
try {
url1 = new URL (url, "/"); /* truncate the path */
} catch (Exception e) {
url1 = url;
}
PasswordAuthentication a = null;
if (!tryTransparentNTLMServer) {
a = privilegedRequestPasswordAuthentication(
url.getHost(), addr, port, url.getProtocol(),
"", scheme, url, RequestorType.SERVER);
}
/* tryTransparentNTLMServer will always be true the first
* time around, but verify that the platform supports it
* otherwise don't try. */
if (tryTransparentNTLMServer) {
tryTransparentNTLMServer =
NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
}
a = null;
if (tryTransparentNTLMServer) {
HttpCapture.finest("Trying Transparent NTLM authentication");
} else {
a = privilegedRequestPasswordAuthentication(
url.getHost(), addr, port, url.getProtocol(),
"", scheme, url, RequestorType.SERVER);
}
/* If we are not trying transparent authentication then
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username
* and password will be picked up from the current logged
* on users credentials.
*/
if (tryTransparentNTLMServer ||
(!tryTransparentNTLMServer && a != null)) {
ret = new NTLMAuthentication(false, url1, a);
}
/* If we are not trying transparent authentication then
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username
* and password will be picked up from the current logged
* on users credentials.
*/
if (tryTransparentNTLMServer ||
(!tryTransparentNTLMServer && a != null)) {
ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
}
tryTransparentNTLMServer = false;
/* set to false so that we do not try again */
tryTransparentNTLMServer = false;
}
break;
case UNKNOWN:
HttpCapture.finest("Unknown/Unsupported authentication scheme: " + scheme);
default:
throw new AssertionError("should not reach here");
}
}
......
/*
* 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.URL;
import java.net.PasswordAuthentication;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import sun.net.www.http.HttpCapture;
/**
* Proxy class for loading NTLMAuthentication, so as to remove static
* dependancy.
*/
class NTLMAuthenticationProxy {
private static Method supportsTA;
private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication";
private static final String supportsTAStr = "supportsTransparentAuth";
static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
static final boolean supported = proxy != null ? true : false;
static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false;
private final Constructor<? extends AuthenticationInfo> threeArgCtr;
private final Constructor<? extends AuthenticationInfo> fiveArgCtr;
private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> threeArgCtr,
Constructor<? extends AuthenticationInfo> fiveArgCtr) {
this.threeArgCtr = threeArgCtr;
this.fiveArgCtr = fiveArgCtr;
}
AuthenticationInfo create(boolean isProxy,
URL url,
PasswordAuthentication pw) {
try {
return threeArgCtr.newInstance(isProxy, url, pw);
} catch (ReflectiveOperationException roe) {
log(roe);
}
return null;
}
AuthenticationInfo create(boolean isProxy,
String host,
int port,
PasswordAuthentication pw) {
try {
return fiveArgCtr.newInstance(isProxy, host, port, pw);
} catch (ReflectiveOperationException roe) {
log(roe);
}
return null;
}
/* Returns true if the NTLM implementation supports transparent
* authentication (try with the current users credentials before
* prompting for username and password, etc).
*/
private static boolean supportsTransparentAuth(Method method) {
try {
return (Boolean)method.invoke(null);
} catch (ReflectiveOperationException roe) {
log(roe);
}
return false;
}
/**
* Loads the NTLM authentiation implementation through reflection. If
* the class is present, then it must have the required constructors and
* method. Otherwise, it is considered an error.
*/
@SuppressWarnings("unchecked")
private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() {
Class<? extends AuthenticationInfo> cl;
Constructor<? extends AuthenticationInfo> threeArg, fiveArg;
try {
cl = (Class<? extends AuthenticationInfo>)Class.forName(clazzStr, true, null);
if (cl != null) {
threeArg = cl.getConstructor(boolean.class,
URL.class,
PasswordAuthentication.class);
fiveArg = cl.getConstructor(boolean.class,
String.class,
int.class,
PasswordAuthentication.class);
supportsTA = cl.getDeclaredMethod(supportsTAStr);
return new NTLMAuthenticationProxy(threeArg,
fiveArg);
}
} catch (ClassNotFoundException cnfe) {
log(cnfe);
} catch (ReflectiveOperationException roe) {
throw new AssertionError(roe);
}
return null;
}
static void log(Exception e) {
if (HttpCapture.isLoggable("FINEST")) {
HttpCapture.finest("NTLMAuthenticationProxy: " + e);
}
}
}
......@@ -34,7 +34,10 @@ import sun.misc.BASE64Encoder;
import java.net.URL;
import java.io.IOException;
import java.net.Authenticator.RequestorType;
import java.lang.reflect.Constructor;
import sun.net.www.http.HttpCapture;
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
/**
* NegotiateAuthentication:
......@@ -49,9 +52,6 @@ class NegotiateAuthentication extends AuthenticationInfo {
final private HttpCallerInfo hci;
static final char NEGOTIATE_AUTH = 'S';
static final char KERBEROS_AUTH = 'K';
// These maps are used to manage the GSS availability for diffrent
// hosts. The key for both maps is the host name.
// <code>supported</code> is set when isSupported is checked,
......@@ -68,11 +68,10 @@ class NegotiateAuthentication extends AuthenticationInfo {
* @param hci a schemed object.
*/
public NegotiateAuthentication(HttpCallerInfo hci) {
super(RequestorType.PROXY==hci.authType?
PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
hci.scheme.equalsIgnoreCase("Negotiate")?
NEGOTIATE_AUTH:KERBEROS_AUTH,
hci.url, "");
super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS,
hci.url,
"");
this.hci = hci;
}
......@@ -249,13 +248,42 @@ abstract class Negotiator {
// 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.
//
// Makes NegotiatorImpl, and the security classes it references, a
// runtime dependency rather than a static one.
Class clazz;
Constructor c;
try {
clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null);
c = clazz.getConstructor(HttpCallerInfo.class);
} catch (ClassNotFoundException cnfe) {
log(cnfe);
throw cnfe;
} catch (ReflectiveOperationException roe) {
// if the class is there then something seriously wrong if
// the constructor is not.
throw new AssertionError(roe);
}
Class clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl");
java.lang.reflect.Constructor c = clazz.getConstructor(HttpCallerInfo.class);
return (Negotiator) (c.newInstance(hci));
try {
return (Negotiator) (c.newInstance(hci));
} catch (ReflectiveOperationException roe) {
log(roe);
Throwable t = roe.getCause();
if (t != null && t instanceof Exception)
log((Exception)t);
throw roe;
}
}
abstract byte[] firstToken() throws IOException;
abstract byte[] nextToken(byte[] in) throws IOException;
static void log(Exception e) {
if (HttpCapture.isLoggable("FINEST")) {
HttpCapture.finest("NegotiateAuthentication: " + e);
}
}
}
......@@ -25,18 +25,23 @@
package sun.net.www.protocol.http;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.Random;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.UnknownHostException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import sun.net.www.HeaderParser;
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.net.*;
/**
* NTLMAuthentication:
*
......@@ -66,8 +71,6 @@ import java.net.*;
class NTLMAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = -2403849171106437142L;
static char NTLM_AUTH = 'N';
private byte[] type1;
private byte[] type3;
......@@ -142,7 +145,10 @@ class NTLMAuthentication extends AuthenticationInfo {
* from a system property: "http.auth.ntlm.domain".
*/
public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, "");
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
AuthScheme.NTLM,
url,
"");
init (pw);
}
......@@ -166,7 +172,11 @@ class NTLMAuthentication extends AuthenticationInfo {
*/
public NTLMAuthentication(boolean isProxy, String host, int port,
PasswordAuthentication pw) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, "");
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
AuthScheme.NTLM,
host,
port,
"");
init (pw);
}
......
......@@ -25,18 +25,13 @@
package sun.net.www.protocol.http;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.Random;
import java.io.IOException;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.UnknownHostException;
import java.net.URL;
import sun.net.www.HeaderParser;
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.net.*;
/**
* NTLMAuthentication:
*
......@@ -47,7 +42,6 @@ class NTLMAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 100L;
static final char NTLM_AUTH = 'N';
private String hostname;
private static String defaultDomain; /* Domain to use if not specified by user */
......@@ -88,7 +82,10 @@ class NTLMAuthentication extends AuthenticationInfo {
* from a system property: "http.auth.ntlm.domain".
*/
public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, "");
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
AuthScheme.NTLM,
url,
"");
init (pw);
}
......@@ -119,7 +116,11 @@ class NTLMAuthentication extends AuthenticationInfo {
*/
public NTLMAuthentication(boolean isProxy, String host, int port,
PasswordAuthentication pw) {
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, "");
super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
AuthScheme.NTLM,
host,
port,
"");
init (pw);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册