6893238: Move NTLM and SPNEGO implementations into separate packages
Reviewed-by: michaelm, alanb
This commit is contained in:
parent
c225292004
commit
6a460a3b96
@ -83,7 +83,7 @@ endif
|
||||
#
|
||||
# Find platform specific native code
|
||||
#
|
||||
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http $(PLATFORM_SRC)/native/sun/net/spi
|
||||
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
|
||||
|
||||
#
|
||||
# Include rules
|
||||
|
@ -89,11 +89,12 @@ FILES_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 \
|
||||
sun/net/www/protocol/http/Negotiator.java \
|
||||
sun/net/www/protocol/http/ntlm/NTLMAuthentication.java \
|
||||
sun/net/www/protocol/http/spnego/NegotiatorImpl.java \
|
||||
sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java \
|
||||
sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
|
||||
sun/net/www/protocol/https/HttpsClient.java \
|
||||
sun/net/www/protocol/https/DefaultHostnameVerifier.java \
|
||||
@ -128,7 +129,7 @@ FILES_java = \
|
||||
sun/net/idn/StringPrep.java
|
||||
|
||||
ifeq ($(PLATFORM), windows)
|
||||
FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java
|
||||
FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), solaris)
|
||||
|
@ -25,12 +25,10 @@
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Enumeration;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
||||
import sun.net.www.HeaderParser;
|
||||
@ -51,12 +49,12 @@ import sun.net.www.HeaderParser;
|
||||
// policy in HttpURLConnection. A failure on baz.foo.com shouldn't
|
||||
// uncache foo.com!
|
||||
|
||||
abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
public abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
|
||||
// Constants saying what kind of authroization this is. This determines
|
||||
// the namespace in the hash table lookup.
|
||||
static final char SERVER_AUTHENTICATION = 's';
|
||||
static final char PROXY_AUTHENTICATION = 'p';
|
||||
public static final char SERVER_AUTHENTICATION = 's';
|
||||
public static final char PROXY_AUTHENTICATION = 'p';
|
||||
|
||||
/**
|
||||
* If true, then simultaneous authentication requests to the same realm/proxy
|
||||
@ -188,7 +186,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
String path;
|
||||
|
||||
/** Use this constructor only for proxy entries */
|
||||
AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
|
||||
public AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
|
||||
this.type = type;
|
||||
this.authScheme = authScheme;
|
||||
this.protocol = "";
|
||||
@ -211,7 +209,7 @@ 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, AuthScheme authScheme, URL url, String realm) {
|
||||
public AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
|
||||
this.type = type;
|
||||
this.authScheme = authScheme;
|
||||
this.protocol = url.getProtocol().toLowerCase();
|
||||
@ -358,13 +356,19 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
abstract boolean supportsPreemptiveAuthorization();
|
||||
public abstract boolean supportsPreemptiveAuthorization();
|
||||
|
||||
/**
|
||||
* @return the name of the HTTP header this authentication wants set.
|
||||
* This is used for preemptive authorization.
|
||||
*/
|
||||
abstract String getHeaderName();
|
||||
public String getHeaderName() {
|
||||
if (type == SERVER_AUTHENTICATION) {
|
||||
return "Authorization";
|
||||
} else {
|
||||
return "Proxy-authorization";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and returns the authentication header value based
|
||||
@ -375,7 +379,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
* @return the value of the HTTP header this authentication wants set.
|
||||
* Used for preemptive authorization.
|
||||
*/
|
||||
abstract String getHeaderValue(URL url, String method);
|
||||
public abstract String getHeaderValue(URL url, String method);
|
||||
|
||||
/**
|
||||
* Set header(s) on the given connection. Subclasses must override
|
||||
@ -386,7 +390,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
* @param raw The raw header field (if needed)
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw);
|
||||
public abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw);
|
||||
|
||||
/**
|
||||
* Check if the header indicates that the current auth. parameters are stale.
|
||||
@ -396,7 +400,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
|
||||
* returning false means we have to go back to the user to ask for a new
|
||||
* username password.
|
||||
*/
|
||||
abstract boolean isAuthorizationStale (String header);
|
||||
public abstract boolean isAuthorizationStale (String header);
|
||||
|
||||
/**
|
||||
* Give a key for hash table lookups.
|
||||
|
@ -131,21 +131,11 @@ class BasicAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
boolean supportsPreemptiveAuthorization() {
|
||||
@Override
|
||||
public boolean supportsPreemptiveAuthorization() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the HTTP header this authentication wants set
|
||||
*/
|
||||
String getHeaderName() {
|
||||
if (type == SERVER_AUTHENTICATION) {
|
||||
return "Authorization";
|
||||
} else {
|
||||
return "Proxy-authorization";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set header(s) on the given connection. This will only be called for
|
||||
* definitive (i.e. non-preemptive) authorization.
|
||||
@ -154,7 +144,8 @@ class BasicAuthentication extends AuthenticationInfo {
|
||||
* @param raw The raw header values for this connection, if needed.
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
@Override
|
||||
public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
conn.setAuthenticationProperty(getHeaderName(), getHeaderValue(null,null));
|
||||
return true;
|
||||
}
|
||||
@ -162,7 +153,8 @@ class BasicAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* @return the value of the HTTP header this authentication wants set
|
||||
*/
|
||||
String getHeaderValue(URL url, String method) {
|
||||
@Override
|
||||
public String getHeaderValue(URL url, String method) {
|
||||
/* For Basic the authorization string does not depend on the request URL
|
||||
* or the request method
|
||||
*/
|
||||
@ -174,7 +166,8 @@ class BasicAuthentication extends AuthenticationInfo {
|
||||
* In other words there is no possibility to reuse the credentials.
|
||||
* They are always either valid or invalid.
|
||||
*/
|
||||
boolean isAuthorizationStale (String header) {
|
||||
@Override
|
||||
public boolean isAuthorizationStale (String header) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -200,21 +200,11 @@ class DigestAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
boolean supportsPreemptiveAuthorization() {
|
||||
@Override
|
||||
public boolean supportsPreemptiveAuthorization() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the HTTP header this authentication wants set
|
||||
*/
|
||||
String getHeaderName() {
|
||||
if (type == SERVER_AUTHENTICATION) {
|
||||
return "Authorization";
|
||||
} else {
|
||||
return "Proxy-Authorization";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reclaculates the request-digest and returns it.
|
||||
*
|
||||
@ -229,7 +219,8 @@ class DigestAuthentication extends AuthenticationInfo {
|
||||
*
|
||||
* @return the value of the HTTP header this authentication wants set
|
||||
*/
|
||||
String getHeaderValue(URL url, String method) {
|
||||
@Override
|
||||
public String getHeaderValue(URL url, String method) {
|
||||
return getHeaderValueImpl(url.getFile(), method);
|
||||
}
|
||||
|
||||
@ -259,7 +250,8 @@ class DigestAuthentication extends AuthenticationInfo {
|
||||
* returning false means we have to go back to the user to ask for a new
|
||||
* username password.
|
||||
*/
|
||||
boolean isAuthorizationStale (String header) {
|
||||
@Override
|
||||
public boolean isAuthorizationStale (String header) {
|
||||
HeaderParser p = new HeaderParser (header);
|
||||
String s = p.findValue ("stale");
|
||||
if (s == null || !s.equals("true"))
|
||||
@ -279,7 +271,8 @@ class DigestAuthentication extends AuthenticationInfo {
|
||||
* @param raw Raw header values for this connection, if needed.
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
@Override
|
||||
public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
params.setNonce (p.findValue("nonce"));
|
||||
params.setOpaque (p.findValue("opaque"));
|
||||
params.setQop (p.findValue("qop"));
|
||||
|
@ -243,7 +243,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
private boolean tryTransparentNTLMProxy = true;
|
||||
|
||||
/* Used by Windows specific code */
|
||||
Object authObj;
|
||||
private Object authObj;
|
||||
|
||||
/* Set if the user is manually setting the Authorization or Proxy-Authorization headers */
|
||||
boolean isUserServerAuth;
|
||||
@ -332,6 +332,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
return logger;
|
||||
}
|
||||
|
||||
/* Used for Windows NTLM implementation */
|
||||
public Object authObj() {
|
||||
return authObj;
|
||||
}
|
||||
|
||||
public void authObj(Object authObj) {
|
||||
this.authObj = authObj;
|
||||
}
|
||||
|
||||
/*
|
||||
* checks the validity of http message header and throws
|
||||
* IllegalArgumentException if invalid.
|
||||
@ -2529,7 +2538,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
// Set a property for authentication. This can safely disregard
|
||||
// the connected test.
|
||||
//
|
||||
void setAuthenticationProperty(String key, String value) {
|
||||
public void setAuthenticationProperty(String key, String value) {
|
||||
checkMessageHeader(key, value);
|
||||
requests.set(key, value);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import sun.util.logging.PlatformLogger;
|
||||
*/
|
||||
class NTLMAuthenticationProxy {
|
||||
private static Method supportsTA;
|
||||
private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication";
|
||||
private static final String clazzStr = "sun.net.www.protocol.http.ntlm.NTLMAuthentication";
|
||||
private static final String supportsTAStr = "supportsTransparentAuth";
|
||||
|
||||
static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
|
||||
|
@ -25,17 +25,13 @@
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import sun.net.www.HeaderParser;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.net.URL;
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator.RequestorType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
import sun.net.www.HeaderParser;
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
|
||||
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
|
||||
|
||||
@ -78,7 +74,8 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
boolean supportsPreemptiveAuthorization() {
|
||||
@Override
|
||||
public boolean supportsPreemptiveAuthorization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -104,34 +101,24 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
return supported.get(hostname);
|
||||
}
|
||||
|
||||
try {
|
||||
Negotiator neg = Negotiator.getSupported(hci);
|
||||
Negotiator neg = Negotiator.getNegotiator(hci);
|
||||
if (neg != null) {
|
||||
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
|
||||
cache.put(hostname, neg);
|
||||
return true;
|
||||
} catch(Exception e) {
|
||||
} else {
|
||||
supported.put(hostname, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the HTTP header this authentication wants to set
|
||||
*/
|
||||
String getHeaderName() {
|
||||
if (type == SERVER_AUTHENTICATION) {
|
||||
return "Authorization";
|
||||
} else {
|
||||
return "Proxy-Authorization";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Must use the setHeaders() method
|
||||
*/
|
||||
String getHeaderValue(URL url, String method) {
|
||||
@Override
|
||||
public String getHeaderValue(URL url, String method) {
|
||||
throw new RuntimeException ("getHeaderValue not supported");
|
||||
}
|
||||
|
||||
@ -143,7 +130,8 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
* returning false means we have to go back to the user to ask for a new
|
||||
* username password.
|
||||
*/
|
||||
boolean isAuthorizationStale (String header) {
|
||||
@Override
|
||||
public boolean isAuthorizationStale (String header) {
|
||||
return false; /* should not be called for Negotiate */
|
||||
}
|
||||
|
||||
@ -155,7 +143,8 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
* @param raw The raw header field.
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
@Override
|
||||
public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
|
||||
try {
|
||||
String response;
|
||||
@ -177,7 +166,7 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* return the first token.
|
||||
* @returns the token
|
||||
* @throws IOException if <code>Negotiator.getSupported()</code> or
|
||||
* @throws IOException if <code>Negotiator.getNegotiator()</code> or
|
||||
* <code>Negotiator.firstToken()</code> failed.
|
||||
*/
|
||||
private byte[] firstToken() throws IOException {
|
||||
@ -191,11 +180,9 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
}
|
||||
}
|
||||
if (negotiator == null) {
|
||||
try {
|
||||
negotiator = Negotiator.getSupported(hci);
|
||||
} catch(Exception e) {
|
||||
negotiator = Negotiator.getNegotiator(hci);
|
||||
if (negotiator == null) {
|
||||
IOException ioe = new IOException("Cannot initialize Negotiator");
|
||||
ioe.initCause(e);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
@ -228,55 +215,3 @@ class NegotiateAuthentication extends AuthenticationInfo {
|
||||
// Currently we ignore this header.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This abstract class is a bridge to connect NegotiteAuthentication and
|
||||
* NegotiatorImpl, so that JAAS and JGSS calls can be made
|
||||
*/
|
||||
abstract class Negotiator {
|
||||
static Negotiator getSupported(HttpCallerInfo hci)
|
||||
throws Exception {
|
||||
|
||||
// These lines are equivalent to
|
||||
// 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.
|
||||
//
|
||||
// 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) {
|
||||
finest(cnfe);
|
||||
throw cnfe;
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
// if the class is there then something seriously wrong if
|
||||
// the constructor is not.
|
||||
throw new AssertionError(roe);
|
||||
}
|
||||
|
||||
try {
|
||||
return (Negotiator) (c.newInstance(hci));
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
finest(roe);
|
||||
Throwable t = roe.getCause();
|
||||
if (t != null && t instanceof Exception)
|
||||
finest((Exception)t);
|
||||
throw roe;
|
||||
}
|
||||
}
|
||||
|
||||
abstract byte[] firstToken() throws IOException;
|
||||
|
||||
abstract byte[] nextToken(byte[] in) throws IOException;
|
||||
|
||||
static void finest(Exception e) {
|
||||
PlatformLogger logger = HttpURLConnection.getHttpLogger();
|
||||
logger.finest("NegotiateAuthentication: " + e);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
/**
|
||||
* This abstract class is a bridge to connect NegotiteAuthentication and
|
||||
* NegotiatorImpl, so that JAAS and JGSS calls can be made
|
||||
*/
|
||||
public abstract class Negotiator {
|
||||
static Negotiator getNegotiator(HttpCallerInfo hci) {
|
||||
|
||||
// These lines are equivalent to
|
||||
// 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.
|
||||
//
|
||||
// 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.spnego.NegotiatorImpl", true, null);
|
||||
c = clazz.getConstructor(HttpCallerInfo.class);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
finest(cnfe);
|
||||
return null;
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
// if the class is there then something seriously wrong if
|
||||
// the constructor is not.
|
||||
throw new AssertionError(roe);
|
||||
}
|
||||
|
||||
try {
|
||||
return (Negotiator) (c.newInstance(hci));
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
finest(roe);
|
||||
Throwable t = roe.getCause();
|
||||
if (t != null && t instanceof Exception)
|
||||
finest((Exception)t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract byte[] firstToken() throws IOException;
|
||||
|
||||
public abstract byte[] nextToken(byte[] in) throws IOException;
|
||||
|
||||
private static void finest(Exception e) {
|
||||
PlatformLogger logger = HttpURLConnection.getHttpLogger();
|
||||
logger.finest("NegotiateAuthentication: " + e);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,8 @@
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
package sun.net.www.protocol.http.spnego;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.PasswordAuthentication;
|
||||
@ -33,6 +34,7 @@ import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import sun.net.www.protocol.http.HttpCallerInfo;
|
||||
|
||||
/**
|
||||
* @since 1.6
|
@ -23,7 +23,7 @@
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
package sun.net.www.protocol.http.spnego;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -32,6 +32,8 @@ import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
import sun.net.www.protocol.http.HttpCallerInfo;
|
||||
import sun.net.www.protocol.http.Negotiator;
|
||||
import sun.security.jgss.GSSManagerImpl;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
import sun.security.jgss.HttpCaller;
|
||||
@ -133,6 +135,7 @@ public class NegotiatorImpl extends Negotiator {
|
||||
* Return the first token of GSS, in SPNEGO, it's called NegTokenInit
|
||||
* @return the first token
|
||||
*/
|
||||
@Override
|
||||
public byte[] firstToken() {
|
||||
return oneToken;
|
||||
}
|
||||
@ -143,6 +146,7 @@ public class NegotiatorImpl extends Negotiator {
|
||||
* @return the next token
|
||||
* @throws java.io.IOException if the token cannot be created successfully
|
||||
*/
|
||||
@Override
|
||||
public byte[] nextToken(byte[] token) throws IOException {
|
||||
try {
|
||||
return context.initSecContext(token, 0, token.length);
|
@ -237,7 +237,7 @@ public class GSSUtil {
|
||||
|
||||
CallbackHandler cb = null;
|
||||
if (caller instanceof HttpCaller) {
|
||||
cb = new sun.net.www.protocol.http.NegotiateCallbackHandler(
|
||||
cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler(
|
||||
((HttpCaller)caller).info());
|
||||
} else {
|
||||
String defaultHandler =
|
||||
|
@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright 2005-2008 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.ntlm;
|
||||
|
||||
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 sun.net.www.protocol.http.AuthenticationInfo;
|
||||
import sun.net.www.protocol.http.AuthScheme;
|
||||
import sun.net.www.protocol.http.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* NTLMAuthentication:
|
||||
*
|
||||
* @author Michael McMahon
|
||||
*/
|
||||
|
||||
/*
|
||||
* NTLM authentication is nominally based on the framework defined in RFC2617,
|
||||
* but differs from the standard (Basic & Digest) schemes as follows:
|
||||
*
|
||||
* 1. A complete authentication requires three request/response transactions
|
||||
* as shown below:
|
||||
* REQ ------------------------------->
|
||||
* <---- 401 (signalling NTLM) --------
|
||||
*
|
||||
* REQ (with type1 NTLM msg) --------->
|
||||
* <---- 401 (with type 2 NTLM msg) ---
|
||||
*
|
||||
* REQ (with type3 NTLM msg) --------->
|
||||
* <---- OK ---------------------------
|
||||
*
|
||||
* 2. The scope of the authentication is the TCP connection (which must be kept-alive)
|
||||
* after the type2 response is received. This means that NTLM does not work end-to-end
|
||||
* through a proxy, rather between client and proxy, or between client and server (with no proxy)
|
||||
*/
|
||||
|
||||
public class NTLMAuthentication extends AuthenticationInfo {
|
||||
private static final long serialVersionUID = -2403849171106437142L;
|
||||
|
||||
private byte[] type1;
|
||||
private byte[] type3;
|
||||
|
||||
private SecretKeyFactory fac;
|
||||
private Cipher cipher;
|
||||
private MessageDigest md4;
|
||||
private String hostname;
|
||||
private static String defaultDomain; /* Domain to use if not specified by user */
|
||||
|
||||
static {
|
||||
defaultDomain = java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
|
||||
"domain"));
|
||||
};
|
||||
|
||||
public static boolean supportsTransparentAuth () {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void init0() {
|
||||
type1 = new byte[256];
|
||||
type3 = new byte[256];
|
||||
System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,1}, 0, type1, 0, 9);
|
||||
type1[12] = (byte) 3;
|
||||
type1[13] = (byte) 0xb2;
|
||||
type1[28] = (byte) 0x20;
|
||||
System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,3}, 0, type3, 0, 9);
|
||||
type3[12] = (byte) 0x18;
|
||||
type3[14] = (byte) 0x18;
|
||||
type3[20] = (byte) 0x18;
|
||||
type3[22] = (byte) 0x18;
|
||||
type3[32] = (byte) 0x40;
|
||||
type3[60] = (byte) 1;
|
||||
type3[61] = (byte) 0x82;
|
||||
|
||||
try {
|
||||
hostname = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
String localhost;
|
||||
try {
|
||||
localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
|
||||
} catch (UnknownHostException e) {
|
||||
localhost = "localhost";
|
||||
}
|
||||
return localhost;
|
||||
}
|
||||
});
|
||||
int x = hostname.indexOf ('.');
|
||||
if (x != -1) {
|
||||
hostname = hostname.substring (0, x);
|
||||
}
|
||||
fac = SecretKeyFactory.getInstance ("DES");
|
||||
cipher = Cipher.getInstance ("DES/ECB/NoPadding");
|
||||
md4 = sun.security.provider.MD4.getInstance();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
assert false;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
assert false;
|
||||
}
|
||||
};
|
||||
|
||||
PasswordAuthentication pw;
|
||||
String username;
|
||||
String ntdomain;
|
||||
String password;
|
||||
|
||||
/**
|
||||
* Create a NTLMAuthentication:
|
||||
* Username may be specified as domain<BACKSLASH>username in the application Authenticator.
|
||||
* If this notation is not used, then the domain will be taken
|
||||
* from a system property: "http.auth.ntlm.domain".
|
||||
*/
|
||||
public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
|
||||
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
|
||||
AuthScheme.NTLM,
|
||||
url,
|
||||
"");
|
||||
init (pw);
|
||||
}
|
||||
|
||||
private void init (PasswordAuthentication pw) {
|
||||
this.pw = pw;
|
||||
String s = pw.getUserName();
|
||||
int i = s.indexOf ('\\');
|
||||
if (i == -1) {
|
||||
username = s;
|
||||
ntdomain = defaultDomain;
|
||||
} else {
|
||||
ntdomain = s.substring (0, i).toUpperCase();
|
||||
username = s.substring (i+1);
|
||||
}
|
||||
password = new String (pw.getPassword());
|
||||
init0();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for proxy entries
|
||||
*/
|
||||
public NTLMAuthentication(boolean isProxy, String host, int port,
|
||||
PasswordAuthentication pw) {
|
||||
super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
|
||||
AuthScheme.NTLM,
|
||||
host,
|
||||
port,
|
||||
"");
|
||||
init (pw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsPreemptiveAuthorization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Must use the setHeaders() method
|
||||
*/
|
||||
@Override
|
||||
public String getHeaderValue(URL url, String method) {
|
||||
throw new RuntimeException ("getHeaderValue not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the header indicates that the current auth. parameters are stale.
|
||||
* If so, then replace the relevant field with the new value
|
||||
* and return true. Otherwise return false.
|
||||
* returning true means the request can be retried with the same userid/password
|
||||
* returning false means we have to go back to the user to ask for a new
|
||||
* username password.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAuthorizationStale (String header) {
|
||||
return false; /* should not be called for ntlm */
|
||||
}
|
||||
|
||||
/**
|
||||
* Set header(s) on the given connection.
|
||||
* @param conn The connection to apply the header(s) to
|
||||
* @param p A source of header values for this connection, not used because
|
||||
* HeaderParser converts the fields to lower case, use raw instead
|
||||
* @param raw The raw header field.
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
@Override
|
||||
public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
|
||||
try {
|
||||
String response;
|
||||
if (raw.length() < 6) { /* NTLM<sp> */
|
||||
response = buildType1Msg ();
|
||||
} else {
|
||||
String msg = raw.substring (5); /* skip NTLM<sp> */
|
||||
response = buildType3Msg (msg);
|
||||
}
|
||||
conn.setAuthenticationProperty(getHeaderName(), response);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
} catch (GeneralSecurityException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void copybytes (byte[] dest, int destpos, String src, String enc) {
|
||||
try {
|
||||
byte[] x = src.getBytes(enc);
|
||||
System.arraycopy (x, 0, dest, destpos, x.length);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
private String buildType1Msg () {
|
||||
int dlen = ntdomain.length();
|
||||
type1[16]= (byte) (dlen % 256);
|
||||
type1[17]= (byte) (dlen / 256);
|
||||
type1[18] = type1[16];
|
||||
type1[19] = type1[17];
|
||||
|
||||
int hlen = hostname.length();
|
||||
type1[24]= (byte) (hlen % 256);
|
||||
type1[25]= (byte) (hlen / 256);
|
||||
type1[26] = type1[24];
|
||||
type1[27] = type1[25];
|
||||
|
||||
copybytes (type1, 32, hostname, "ISO8859_1");
|
||||
copybytes (type1, hlen+32, ntdomain, "ISO8859_1");
|
||||
type1[20] = (byte) ((hlen+32) % 256);
|
||||
type1[21] = (byte) ((hlen+32) / 256);
|
||||
|
||||
byte[] msg = new byte [32 + hlen + dlen];
|
||||
System.arraycopy (type1, 0, msg, 0, 32 + hlen + dlen);
|
||||
String result = "NTLM " + (new B64Encoder()).encode (msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Convert a 7 byte array to an 8 byte array (for a des key with parity)
|
||||
* input starts at offset off
|
||||
*/
|
||||
private byte[] makeDesKey (byte[] input, int off) {
|
||||
int[] in = new int [input.length];
|
||||
for (int i=0; i<in.length; i++ ) {
|
||||
in[i] = input[i]<0 ? input[i]+256: input[i];
|
||||
}
|
||||
byte[] out = new byte[8];
|
||||
out[0] = (byte)in[off+0];
|
||||
out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
|
||||
out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
|
||||
out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
|
||||
out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
|
||||
out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
|
||||
out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
|
||||
out[7] = (byte)((in[off+6] << 1) & 0xFF);
|
||||
return out;
|
||||
}
|
||||
|
||||
private byte[] calcLMHash () throws GeneralSecurityException {
|
||||
byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
|
||||
byte[] pwb = password.toUpperCase ().getBytes();
|
||||
byte[] pwb1 = new byte [14];
|
||||
int len = password.length();
|
||||
if (len > 14)
|
||||
len = 14;
|
||||
System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
|
||||
|
||||
DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
|
||||
DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
|
||||
|
||||
SecretKey key1 = fac.generateSecret (dks1);
|
||||
SecretKey key2 = fac.generateSecret (dks2);
|
||||
cipher.init (Cipher.ENCRYPT_MODE, key1);
|
||||
byte[] out1 = cipher.doFinal (magic, 0, 8);
|
||||
cipher.init (Cipher.ENCRYPT_MODE, key2);
|
||||
byte[] out2 = cipher.doFinal (magic, 0, 8);
|
||||
|
||||
byte[] result = new byte [21];
|
||||
System.arraycopy (out1, 0, result, 0, 8);
|
||||
System.arraycopy (out2, 0, result, 8, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
private byte[] calcNTHash () throws GeneralSecurityException {
|
||||
byte[] pw = null;
|
||||
try {
|
||||
pw = password.getBytes ("UnicodeLittleUnmarked");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
assert false;
|
||||
}
|
||||
byte[] out = md4.digest (pw);
|
||||
byte[] result = new byte [21];
|
||||
System.arraycopy (out, 0, result, 0, 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* key is a 21 byte array. Split it into 3 7 byte chunks,
|
||||
* Convert each to 8 byte DES keys, encrypt the text arg with
|
||||
* each key and return the three results in a sequential []
|
||||
*/
|
||||
private byte[] calcResponse (byte[] key, byte[] text)
|
||||
throws GeneralSecurityException {
|
||||
assert key.length == 21;
|
||||
DESKeySpec dks1 = new DESKeySpec (makeDesKey (key, 0));
|
||||
DESKeySpec dks2 = new DESKeySpec (makeDesKey (key, 7));
|
||||
DESKeySpec dks3 = new DESKeySpec (makeDesKey (key, 14));
|
||||
SecretKey key1 = fac.generateSecret (dks1);
|
||||
SecretKey key2 = fac.generateSecret (dks2);
|
||||
SecretKey key3 = fac.generateSecret (dks3);
|
||||
cipher.init (Cipher.ENCRYPT_MODE, key1);
|
||||
byte[] out1 = cipher.doFinal (text, 0, 8);
|
||||
cipher.init (Cipher.ENCRYPT_MODE, key2);
|
||||
byte[] out2 = cipher.doFinal (text, 0, 8);
|
||||
cipher.init (Cipher.ENCRYPT_MODE, key3);
|
||||
byte[] out3 = cipher.doFinal (text, 0, 8);
|
||||
byte[] result = new byte [24];
|
||||
System.arraycopy (out1, 0, result, 0, 8);
|
||||
System.arraycopy (out2, 0, result, 8, 8);
|
||||
System.arraycopy (out3, 0, result, 16, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
private String buildType3Msg (String challenge) throws GeneralSecurityException,
|
||||
IOException {
|
||||
/* First decode the type2 message to get the server nonce */
|
||||
/* nonce is located at type2[24] for 8 bytes */
|
||||
|
||||
byte[] type2 = (new sun.misc.BASE64Decoder()).decodeBuffer (challenge);
|
||||
byte[] nonce = new byte [8];
|
||||
System.arraycopy (type2, 24, nonce, 0, 8);
|
||||
|
||||
int ulen = username.length()*2;
|
||||
type3[36] = type3[38] = (byte) (ulen % 256);
|
||||
type3[37] = type3[39] = (byte) (ulen / 256);
|
||||
int dlen = ntdomain.length()*2;
|
||||
type3[28] = type3[30] = (byte) (dlen % 256);
|
||||
type3[29] = type3[31] = (byte) (dlen / 256);
|
||||
int hlen = hostname.length()*2;
|
||||
type3[44] = type3[46] = (byte) (hlen % 256);
|
||||
type3[45] = type3[47] = (byte) (hlen / 256);
|
||||
|
||||
int l = 64;
|
||||
copybytes (type3, l, ntdomain, "UnicodeLittleUnmarked");
|
||||
type3[32] = (byte) (l % 256);
|
||||
type3[33] = (byte) (l / 256);
|
||||
l += dlen;
|
||||
copybytes (type3, l, username, "UnicodeLittleUnmarked");
|
||||
type3[40] = (byte) (l % 256);
|
||||
type3[41] = (byte) (l / 256);
|
||||
l += ulen;
|
||||
copybytes (type3, l, hostname, "UnicodeLittleUnmarked");
|
||||
type3[48] = (byte) (l % 256);
|
||||
type3[49] = (byte) (l / 256);
|
||||
l += hlen;
|
||||
|
||||
byte[] lmhash = calcLMHash();
|
||||
byte[] lmresponse = calcResponse (lmhash, nonce);
|
||||
byte[] nthash = calcNTHash();
|
||||
byte[] ntresponse = calcResponse (nthash, nonce);
|
||||
System.arraycopy (lmresponse, 0, type3, l, 24);
|
||||
type3[16] = (byte) (l % 256);
|
||||
type3[17] = (byte) (l / 256);
|
||||
l += 24;
|
||||
System.arraycopy (ntresponse, 0, type3, l, 24);
|
||||
type3[24] = (byte) (l % 256);
|
||||
type3[25] = (byte) (l / 256);
|
||||
l += 24;
|
||||
type3[56] = (byte) (l % 256);
|
||||
type3[57] = (byte) (l / 256);
|
||||
|
||||
byte[] msg = new byte [l];
|
||||
System.arraycopy (type3, 0, msg, 0, l);
|
||||
String result = "NTLM " + (new B64Encoder()).encode (msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class B64Encoder extends sun.misc.BASE64Encoder {
|
||||
/* to force it to to the entire encoding in one line */
|
||||
protected int bytesPerLine () {
|
||||
return 1024;
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
package sun.net.www.protocol.http.ntlm;
|
||||
|
||||
import java.io.IOException;
|
||||
import sun.misc.BASE64Encoder;
|
@ -23,7 +23,7 @@
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.net.www.protocol.http;
|
||||
package sun.net.www.protocol.http.ntlm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
@ -31,6 +31,9 @@ import java.net.PasswordAuthentication;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.URL;
|
||||
import sun.net.www.HeaderParser;
|
||||
import sun.net.www.protocol.http.AuthenticationInfo;
|
||||
import sun.net.www.protocol.http.AuthScheme;
|
||||
import sun.net.www.protocol.http.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* NTLMAuthentication:
|
||||
@ -38,7 +41,7 @@ import sun.net.www.HeaderParser;
|
||||
* @author Michael McMahon
|
||||
*/
|
||||
|
||||
class NTLMAuthentication extends AuthenticationInfo {
|
||||
public class NTLMAuthentication extends AuthenticationInfo {
|
||||
|
||||
private static final long serialVersionUID = 100L;
|
||||
|
||||
@ -127,32 +130,23 @@ class NTLMAuthentication extends AuthenticationInfo {
|
||||
/**
|
||||
* @return true if this authentication supports preemptive authorization
|
||||
*/
|
||||
boolean supportsPreemptiveAuthorization() {
|
||||
@Override
|
||||
public boolean supportsPreemptiveAuthorization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if NTLM supported transparently (no password needed, SSO)
|
||||
*/
|
||||
static boolean supportsTransparentAuth() {
|
||||
public static boolean supportsTransparentAuth() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the HTTP header this authentication wants set
|
||||
*/
|
||||
String getHeaderName() {
|
||||
if (type == SERVER_AUTHENTICATION) {
|
||||
return "Authorization";
|
||||
} else {
|
||||
return "Proxy-authorization";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Must use the setHeaders() method
|
||||
*/
|
||||
String getHeaderValue(URL url, String method) {
|
||||
@Override
|
||||
public String getHeaderValue(URL url, String method) {
|
||||
throw new RuntimeException ("getHeaderValue not supported");
|
||||
}
|
||||
|
||||
@ -164,7 +158,8 @@ class NTLMAuthentication extends AuthenticationInfo {
|
||||
* returning false means we have to go back to the user to ask for a new
|
||||
* username password.
|
||||
*/
|
||||
boolean isAuthorizationStale (String header) {
|
||||
@Override
|
||||
public boolean isAuthorizationStale (String header) {
|
||||
return false; /* should not be called for ntlm */
|
||||
}
|
||||
|
||||
@ -176,13 +171,14 @@ class NTLMAuthentication extends AuthenticationInfo {
|
||||
* @param raw The raw header field.
|
||||
* @return true if all goes well, false if no headers were set.
|
||||
*/
|
||||
synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
@Override
|
||||
public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
|
||||
|
||||
try {
|
||||
NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj;
|
||||
NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj();
|
||||
if (seq == null) {
|
||||
seq = new NTLMAuthSequence (username, password, ntdomain);
|
||||
conn.authObj = seq;
|
||||
conn.authObj(seq);
|
||||
}
|
||||
String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
|
||||
conn.setAuthenticationProperty(getHeaderName(), response);
|
@ -60,7 +60,7 @@ static jfieldID ntlm_crdHandleID;
|
||||
|
||||
static HINSTANCE lib = NULL;
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_initFirst
|
||||
JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
OSVERSIONINFO version;
|
||||
@ -113,7 +113,7 @@ JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_initFirst
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
|
||||
*/
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getCredentialsHandle
|
||||
JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getCredentialsHandle
|
||||
(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY AuthId;
|
||||
@ -197,7 +197,7 @@ JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getCrede
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getNextToken
|
||||
JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
|
||||
(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user