6893238: Move NTLM and SPNEGO implementations into separate packages
Reviewed-by: michaelm, alanb
--- a/jdk/make/java/net/Makefile Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/make/java/net/Makefile Wed Oct 21 15:41:42 2009 +0100
@@ -83,7 +83,7 @@
#
# 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
--- a/jdk/make/sun/net/FILES_java.gmk Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/make/sun/net/FILES_java.gmk Wed Oct 21 15:41:42 2009 +0100
@@ -89,11 +89,12 @@
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 @@
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)
--- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Wed Oct 21 15:41:42 2009 +0100
@@ -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 @@
// 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 @@
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 @@
* 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 @@
/**
* @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 @@
* @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 @@
* @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 @@
* 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.
--- a/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java Wed Oct 21 15:41:42 2009 +0100
@@ -131,22 +131,12 @@
/**
* @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.
* @param conn The connection to apply the header(s) to
@@ -154,7 +144,8 @@
* @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 @@
/**
* @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 @@
* 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;
}
--- a/jdk/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java Wed Oct 21 15:41:42 2009 +0100
@@ -200,22 +200,12 @@
/**
* @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.
*
* <P> Used in the common case where the requestURI is simply the
@@ -229,7 +219,8 @@
*
* @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 @@
* 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 @@
* @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"));
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Oct 21 15:41:42 2009 +0100
@@ -243,7 +243,7 @@
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 @@
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 @@
// 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);
}
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java Wed Oct 21 15:41:42 2009 +0100
@@ -36,7 +36,7 @@
*/
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();
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Oct 21 15:41:42 2009 +0100
@@ -25,17 +25,13 @@
package sun.net.www.protocol.http;
+import java.net.URL;
+import java.io.IOException;
+import java.net.Authenticator.RequestorType;
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 static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
@@ -78,7 +74,8 @@
/**
* @return true if this authentication supports preemptive authorization
*/
- boolean supportsPreemptiveAuthorization() {
+ @Override
+ public boolean supportsPreemptiveAuthorization() {
return false;
}
@@ -104,34 +101,24 @@
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 @@
* 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 @@
* @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 @@
/**
* 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 @@
}
}
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 @@
// 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);
- }
-}
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java Mon Oct 19 16:31:48 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * 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
- * 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.net.Authenticator;
-import java.net.PasswordAuthentication;
-import java.util.Arrays;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-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++) {
- Callback callBack = callbacks[i];
-
- if (callBack instanceof NameCallback) {
- if (username == null) {
- PasswordAuthentication passAuth =
- Authenticator.requestPasswordAuthentication(
- hci.host, hci.addr, hci.port, hci.protocol,
- hci.prompt, hci.scheme, hci.url, hci.authType);
- username = passAuth.getUserName();
- password = passAuth.getPassword();
- }
- NameCallback nameCallback =
- (NameCallback)callBack;
- nameCallback.setName(username);
-
- } else if (callBack instanceof PasswordCallback) {
- PasswordCallback passwordCallback =
- (PasswordCallback)callBack;
- if (password == null) {
- PasswordAuthentication passAuth =
- Authenticator.requestPasswordAuthentication(
- hci.host, hci.addr, hci.port, hci.protocol,
- hci.prompt, hci.scheme, hci.url, hci.authType);
- username = passAuth.getUserName();
- password = passAuth.getPassword();
- }
- passwordCallback.setPassword(password);
- Arrays.fill(password, ' ');
- } else {
- throw new UnsupportedCallbackException(callBack,
- "Call back not supported");
- }
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java Wed Oct 21 15:41:42 2009 +0100
@@ -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);
+ }
+}
+
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiatorImpl.java Mon Oct 19 16:31:48 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * 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
- * 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 org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSName;
-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 separate class
- * outside NegotiateAuthentication.java so that J2SE build can go smoothly
- * without the presence of it.
- *
- * @author weijun.wang@sun.com
- * @since 1.6
- */
-public class NegotiatorImpl extends Negotiator {
-
- private static final boolean DEBUG =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
-
- private GSSContext context;
- private byte[] oneToken;
-
- /**
- * Initialize the object, which includes:<ul>
- * <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>
- */
- private void init(HttpCallerInfo hci) throws GSSException {
- final Oid oid;
-
- if (hci.scheme.equalsIgnoreCase("Kerberos")) {
- // we can only use Kerberos mech when the scheme is kerberos
- oid = GSSUtil.GSS_KRB5_MECH_OID;
- } else {
- String pref = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<String>() {
- public String run() {
- return System.getProperty(
- "http.auth.preference",
- "spnego");
- }
- });
- if (pref.equalsIgnoreCase("kerberos")) {
- oid = GSSUtil.GSS_KRB5_MECH_OID;
- } else {
- // currently there is no 3rd mech we can use
- oid = GSSUtil.GSS_SPNEGO_MECH_OID;
- }
- }
-
- GSSManagerImpl manager = new GSSManagerImpl(
- new HttpCaller(hci));
-
- // 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);
- context = manager.createContext(serverName,
- oid,
- null,
- GSSContext.DEFAULT_LIFETIME);
-
- // In order to support credential delegation in HTTP/SPNEGO,
- // we always request it before initSecContext. The current
- // implementation will check the OK-AS-DELEGATE flag inside
- // the service ticket of the web server, and only enable
- // delegation when this flag is set. This check is only
- // performed when the GSS caller is CALLER_HTTP_NEGOTIATE,
- // so all other normal GSS-API calls are not affected.
-
- context.requestCredDeleg(true);
- oneToken = context.initSecContext(new byte[0], 0, 0);
- }
-
- /**
- * Constructor
- * @throws java.io.IOException If negotiator cannot be constructed
- */
- public NegotiatorImpl(HttpCallerInfo hci) throws IOException {
- try {
- init(hci);
- } catch (GSSException e) {
- if (DEBUG) {
- 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");
- ioe.initCause(e);
- throw ioe;
- }
- }
-
- /**
- * Return the first token of GSS, in SPNEGO, it's called NegTokenInit
- * @return the first token
- */
- public byte[] firstToken() {
- return oneToken;
- }
-
- /**
- * Return the rest tokens of GSS, in SPNEGO, it's called NegTokenTarg
- * @param token the token received from server
- * @return the next token
- * @throws java.io.IOException if the token cannot be created successfully
- */
- public byte[] nextToken(byte[] token) throws IOException {
- try {
- return context.initSecContext(token, 0, token.length);
- } catch (GSSException e) {
- if (DEBUG) {
- System.out.println("Negotiate support cannot continue. Reason:");
- e.printStackTrace();
- }
- IOException ioe = new IOException("Negotiate support cannot continue");
- ioe.initCause(e);
- throw ioe;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java Wed Oct 21 15:41:42 2009 +0100
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * 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.spnego;
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.util.Arrays;
+import javax.security.auth.callback.Callback;
+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
+ * 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++) {
+ Callback callBack = callbacks[i];
+
+ if (callBack instanceof NameCallback) {
+ if (username == null) {
+ PasswordAuthentication passAuth =
+ Authenticator.requestPasswordAuthentication(
+ hci.host, hci.addr, hci.port, hci.protocol,
+ hci.prompt, hci.scheme, hci.url, hci.authType);
+ username = passAuth.getUserName();
+ password = passAuth.getPassword();
+ }
+ NameCallback nameCallback =
+ (NameCallback)callBack;
+ nameCallback.setName(username);
+
+ } else if (callBack instanceof PasswordCallback) {
+ PasswordCallback passwordCallback =
+ (PasswordCallback)callBack;
+ if (password == null) {
+ PasswordAuthentication passAuth =
+ Authenticator.requestPasswordAuthentication(
+ hci.host, hci.addr, hci.port, hci.protocol,
+ hci.prompt, hci.scheme, hci.url, hci.authType);
+ username = passAuth.getUserName();
+ password = passAuth.getPassword();
+ }
+ passwordCallback.setPassword(password);
+ Arrays.fill(password, ' ');
+ } else {
+ throw new UnsupportedCallbackException(callBack,
+ "Call back not supported");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Wed Oct 21 15:41:42 2009 +0100
@@ -0,0 +1,163 @@
+/*
+ * 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
+ * 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.spnego;
+
+import java.io.IOException;
+
+import org.ietf.jgss.GSSContext;
+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;
+
+/**
+ * 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.
+ *
+ * @author weijun.wang@sun.com
+ * @since 1.6
+ */
+public class NegotiatorImpl extends Negotiator {
+
+ private static final boolean DEBUG =
+ java.security.AccessController.doPrivileged(
+ new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
+
+ private GSSContext context;
+ private byte[] oneToken;
+
+ /**
+ * Initialize the object, which includes:<ul>
+ * <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>
+ */
+ private void init(HttpCallerInfo hci) throws GSSException {
+ final Oid oid;
+
+ if (hci.scheme.equalsIgnoreCase("Kerberos")) {
+ // we can only use Kerberos mech when the scheme is kerberos
+ oid = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ String pref = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(
+ "http.auth.preference",
+ "spnego");
+ }
+ });
+ if (pref.equalsIgnoreCase("kerberos")) {
+ oid = GSSUtil.GSS_KRB5_MECH_OID;
+ } else {
+ // currently there is no 3rd mech we can use
+ oid = GSSUtil.GSS_SPNEGO_MECH_OID;
+ }
+ }
+
+ GSSManagerImpl manager = new GSSManagerImpl(
+ new HttpCaller(hci));
+
+ // 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);
+ context = manager.createContext(serverName,
+ oid,
+ null,
+ GSSContext.DEFAULT_LIFETIME);
+
+ // In order to support credential delegation in HTTP/SPNEGO,
+ // we always request it before initSecContext. The current
+ // implementation will check the OK-AS-DELEGATE flag inside
+ // the service ticket of the web server, and only enable
+ // delegation when this flag is set. This check is only
+ // performed when the GSS caller is CALLER_HTTP_NEGOTIATE,
+ // so all other normal GSS-API calls are not affected.
+
+ context.requestCredDeleg(true);
+ oneToken = context.initSecContext(new byte[0], 0, 0);
+ }
+
+ /**
+ * Constructor
+ * @throws java.io.IOException If negotiator cannot be constructed
+ */
+ public NegotiatorImpl(HttpCallerInfo hci) throws IOException {
+ try {
+ init(hci);
+ } catch (GSSException e) {
+ if (DEBUG) {
+ 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");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Return the first token of GSS, in SPNEGO, it's called NegTokenInit
+ * @return the first token
+ */
+ @Override
+ public byte[] firstToken() {
+ return oneToken;
+ }
+
+ /**
+ * Return the rest tokens of GSS, in SPNEGO, it's called NegTokenTarg
+ * @param token the token received from server
+ * @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);
+ } catch (GSSException e) {
+ if (DEBUG) {
+ System.out.println("Negotiate support cannot continue. Reason:");
+ e.printStackTrace();
+ }
+ IOException ioe = new IOException("Negotiate support cannot continue");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+}
--- a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java Mon Oct 19 16:31:48 2009 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java Wed Oct 21 15:41:42 2009 +0100
@@ -237,7 +237,7 @@
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 =
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Wed Oct 21 15:41:42 2009 +0100
@@ -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;
+ }
+}
--- a/jdk/src/windows/classes/sun/net/www/protocol/http/NTLMAuthSequence.java Mon Oct 19 16:31:48 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright 2002 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 sun.misc.BASE64Encoder;
-import sun.misc.BASE64Decoder;
-
-/*
- * Hooks into Windows implementation of NTLM.
- * This class will be replaced if a cross-platform version of NTLM
- * is implemented in the future.
- */
-
-public class NTLMAuthSequence {
-
- private String username;
- private String password;
- private String ntdomain;
- private int state;
- private long crdHandle;
- private long ctxHandle;
-
- static {
- initFirst();
- }
-
- NTLMAuthSequence (String username, String password, String ntdomain)
- throws IOException
- {
- this.username = username;
- this.password = password;
- this.ntdomain = ntdomain;
- state = 0;
- crdHandle = getCredentialsHandle (username, ntdomain, password);
- if (crdHandle == 0) {
- throw new IOException ("could not get credentials handle");
- }
- }
-
- public String getAuthHeader (String token) throws IOException {
- byte[] input = null;
- if (token != null)
- input = (new BASE64Decoder()).decodeBuffer(token);
- byte[] b = getNextToken (crdHandle, input);
- if (b == null)
- throw new IOException ("Internal authentication error");
- return (new B64Encoder()).encode (b);
- }
-
- private native static void initFirst ();
-
- private native long getCredentialsHandle (String user, String domain, String password);
-
- private native byte[] getNextToken (long crdHandle, byte[] lastToken);
-}
-
-class B64Encoder extends BASE64Encoder {
- protected int bytesPerLine () {
- return 1024;
- }
-}
--- a/jdk/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java Mon Oct 19 16:31:48 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright 2002-2005 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.net.InetAddress;
-import java.net.PasswordAuthentication;
-import java.net.UnknownHostException;
-import java.net.URL;
-import sun.net.www.HeaderParser;
-
-/**
- * NTLMAuthentication:
- *
- * @author Michael McMahon
- */
-
-class NTLMAuthentication extends AuthenticationInfo {
-
- private static final long serialVersionUID = 100L;
-
- 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"));
- };
-
- private void init0() {
-
- 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);
- }
- }
-
- 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;
- if (pw != null) {
- 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());
- } else {
- /* credentials will be acquired from OS */
- username = null;
- ntdomain = null;
- password = null;
- }
- 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
- */
- boolean supportsPreemptiveAuthorization() {
- return false;
- }
-
- /**
- * @return true if NTLM supported transparently (no password needed, SSO)
- */
- 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) {
- 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.
- */
- 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.
- */
- synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
-
- try {
- NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj;
- if (seq == null) {
- seq = new NTLMAuthSequence (username, password, ntdomain);
- conn.authObj = seq;
- }
- String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
- conn.setAuthenticationProperty(getHeaderName(), response);
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java Wed Oct 21 15:41:42 2009 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002 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 sun.misc.BASE64Encoder;
+import sun.misc.BASE64Decoder;
+
+/*
+ * Hooks into Windows implementation of NTLM.
+ * This class will be replaced if a cross-platform version of NTLM
+ * is implemented in the future.
+ */
+
+public class NTLMAuthSequence {
+
+ private String username;
+ private String password;
+ private String ntdomain;
+ private int state;
+ private long crdHandle;
+ private long ctxHandle;
+
+ static {
+ initFirst();
+ }
+
+ NTLMAuthSequence (String username, String password, String ntdomain)
+ throws IOException
+ {
+ this.username = username;
+ this.password = password;
+ this.ntdomain = ntdomain;
+ state = 0;
+ crdHandle = getCredentialsHandle (username, ntdomain, password);
+ if (crdHandle == 0) {
+ throw new IOException ("could not get credentials handle");
+ }
+ }
+
+ public String getAuthHeader (String token) throws IOException {
+ byte[] input = null;
+ if (token != null)
+ input = (new BASE64Decoder()).decodeBuffer(token);
+ byte[] b = getNextToken (crdHandle, input);
+ if (b == null)
+ throw new IOException ("Internal authentication error");
+ return (new B64Encoder()).encode (b);
+ }
+
+ private native static void initFirst ();
+
+ private native long getCredentialsHandle (String user, String domain, String password);
+
+ private native byte[] getNextToken (long crdHandle, byte[] lastToken);
+}
+
+class B64Encoder extends BASE64Encoder {
+ protected int bytesPerLine () {
+ return 1024;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Wed Oct 21 15:41:42 2009 +0100
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2002-2005 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.net.InetAddress;
+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:
+ *
+ * @author Michael McMahon
+ */
+
+public class NTLMAuthentication extends AuthenticationInfo {
+
+ private static final long serialVersionUID = 100L;
+
+ 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"));
+ };
+
+ private void init0() {
+
+ 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);
+ }
+ }
+
+ 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;
+ if (pw != null) {
+ 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());
+ } else {
+ /* credentials will be acquired from OS */
+ username = null;
+ ntdomain = null;
+ password = null;
+ }
+ 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;
+ }
+
+ /**
+ * @return true if NTLM supported transparently (no password needed, SSO)
+ */
+ public static boolean supportsTransparentAuth() {
+ return true;
+ }
+
+ /**
+ * 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 {
+ NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj();
+ if (seq == null) {
+ seq = new NTLMAuthSequence (username, password, ntdomain);
+ conn.authObj(seq);
+ }
+ String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
+ conn.setAuthenticationProperty(getHeaderName(), response);
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+}
--- a/jdk/src/windows/native/sun/net/www/protocol/http/NTLMAuthSequence.c Mon Oct 19 16:31:48 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,311 +0,0 @@
-/*
- * Copyright 2002-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.
- */
-
-#include <jni.h>
-#include <windows.h>
-#include <rpc.h>
-#include <winsock.h>
-#include <lm.h>
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <tchar.h>
-#include <fcntl.h>
-
-#include "jni_util.h"
-
-#define SECURITY_WIN32
-#include "sspi.h"
-
-
-/*
- * OS calls loaded from DLL on intialization
- */
-
-static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
-static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
-static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
-static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
-static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
-static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
-
-static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
-
-static jfieldID ntlm_ctxHandleID;
-static jfieldID ntlm_crdHandleID;
-
-static HINSTANCE lib = NULL;
-
-JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_initFirst
-(JNIEnv *env, jclass clazz)
-{
- OSVERSIONINFO version;
- UCHAR libName[MAX_PATH];
-
- ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
- ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
-
- version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- GetVersionEx (&version);
-
- if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- strcpy (libName, "security.dll" );
- }
- else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- strcpy (libName, "secur32.dll" );
- }
-
- lib = LoadLibrary (libName);
-
- pFreeCredentialsHandle
- = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
- lib, "FreeCredentialsHandle" );
-
- pAcquireCredentialsHandle
- = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
- lib, "AcquireCredentialsHandleA" );
-
- pFreeContextBuffer
- = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
- lib, "FreeContextBuffer" );
-
- pInitializeSecurityContext
- = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
- lib, "InitializeSecurityContextA" );
-
- pCompleteAuthToken
- = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
- lib, "CompleteAuthToken" );
-
- pDeleteSecurityContext
- = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
- lib, "DeleteSecurityContext" );
-
-}
-
-/*
- * Class: sun_net_www_protocol_http_NTLMAuthSequence
- * Method: getCredentialsHandle
- * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
- */
-
-JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getCredentialsHandle
-(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
-{
- SEC_WINNT_AUTH_IDENTITY AuthId;
- SEC_WINNT_AUTH_IDENTITY * pAuthId;
- const CHAR *pUser = 0;
- const CHAR *pDomain = 0;
- const CHAR *pPassword = 0;
- CredHandle *pCred;
- TimeStamp ltime;
- jboolean isCopy;
- SECURITY_STATUS ss;
-
- if (user != 0) {
- pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
- if (pUser == NULL)
- return 0; // pending Exception
- }
- if (domain != 0) {
- pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
- if (pDomain == NULL) {
- if (pUser != NULL)
- JNU_ReleaseStringPlatformChars(env, user, pUser);
- return 0; // pending Exception
- }
- }
- if (password != 0) {
- pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
- if (pPassword == NULL) {
- if(pUser != NULL)
- JNU_ReleaseStringPlatformChars(env, user, pUser);
- if(pDomain != NULL)
- JNU_ReleaseStringPlatformChars(env, domain, pDomain);
- return 0; // pending Exception
- }
- }
- pCred = (CredHandle *)malloc(sizeof (CredHandle));
-
- if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
- pAuthId = &AuthId;
-
- memset( &AuthId, 0, sizeof( AuthId ));
-
- if ( pUser != NULL ) {
- AuthId.User = (unsigned char *) pUser;
- AuthId.UserLength = strlen( pUser );
- }
-
- if ( pPassword != NULL ) {
- AuthId.Password = (unsigned char *) pPassword;
- AuthId.PasswordLength = strlen( pPassword );
- }
-
- if ( pDomain != NULL ) {
- AuthId.Domain = (unsigned char *) pDomain;
- AuthId.DomainLength = strlen( pDomain );
- }
-
- AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
- } else {
- pAuthId = NULL;
- }
-
- ss = pAcquireCredentialsHandle(
- NULL, "NTLM", SECPKG_CRED_OUTBOUND,
- NULL, pAuthId, NULL, NULL,
- pCred, <ime
- );
-
- /* Release resources held by JNU_GetStringPlatformChars */
- if (pUser != NULL)
- JNU_ReleaseStringPlatformChars(env, user, pUser);
- if (pPassword != NULL)
- JNU_ReleaseStringPlatformChars(env, password, pPassword);
- if (pDomain != NULL)
- JNU_ReleaseStringPlatformChars(env, domain, pDomain);
-
- if (ss == 0) {
- return (jlong) pCred;
- } else {
- return 0;
- }
-}
-
-JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getNextToken
-(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
-{
-
- VOID *pInput = 0;
- DWORD inputLen;
- CHAR buffOut[512];
- jboolean isCopy;
- SECURITY_STATUS ss;
- SecBufferDesc OutBuffDesc;
- SecBuffer OutSecBuff;
- SecBufferDesc InBuffDesc;
- SecBuffer InSecBuff;
- ULONG ContextAttributes;
- CredHandle *pCred = (CredHandle *)crdHandle;
- CtxtHandle *pCtx;
- CtxtHandle *newContext;
- TimeStamp ltime;
- jbyteArray result;
-
-
- pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
- if (pCtx == 0) { /* first call */
- newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
- (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
- } else {
- newContext = pCtx;
- }
-
- OutBuffDesc.ulVersion = 0;
- OutBuffDesc.cBuffers = 1;
- OutBuffDesc.pBuffers = &OutSecBuff;
-
- OutSecBuff.cbBuffer = 512;
- OutSecBuff.BufferType = SECBUFFER_TOKEN;
- OutSecBuff.pvBuffer = buffOut;
-
- /*
- * Prepare our Input buffer - Note the server is expecting the client's
- * negotiation packet on the first call
- */
-
- if (lastToken != 0)
- {
- pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
- inputLen = (*env)->GetArrayLength(env, lastToken);
-
- InBuffDesc.ulVersion = 0;
- InBuffDesc.cBuffers = 1;
- InBuffDesc.pBuffers = &InSecBuff;
-
- InSecBuff.cbBuffer = inputLen;
- InSecBuff.BufferType = SECBUFFER_TOKEN;
- InSecBuff.pvBuffer = pInput;
- }
-
- /*
- * will return success when its done but we still
- * need to send the out buffer if there are bytes to send
- */
-
- ss = pInitializeSecurityContext(
- pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
- lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
- &ContextAttributes, <ime
- );
-
- if (pInput != 0) {
- (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
- }
-
- if (ss < 0) {
- endSequence (pCred, pCtx);
- return 0;
- }
-
- if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
- ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
-
- if (ss < 0) {
- endSequence (pCred, pCtx);
- return 0;
- }
- }
-
- if ( OutSecBuff.cbBuffer > 0 ) {
- jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
- (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
- OutSecBuff.pvBuffer);
- if (lastToken != 0) // 2nd stage
- endSequence (pCred, pCtx);
- result = ret;
- }
-
- if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
- endSequence (pCred, pCtx);
- }
-
- return result;
-}
-
-static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
- if (credHand != 0) {
- pFreeCredentialsHandle (credHand);
- free (credHand);
- }
-
- if (ctxHandle != 0) {
- pDeleteSecurityContext(ctxHandle);
- free (ctxHandle);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c Wed Oct 21 15:41:42 2009 +0100
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2002-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.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include <rpc.h>
+#include <winsock.h>
+#include <lm.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tchar.h>
+#include <fcntl.h>
+
+#include "jni_util.h"
+
+#define SECURITY_WIN32
+#include "sspi.h"
+
+
+/*
+ * OS calls loaded from DLL on intialization
+ */
+
+static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
+static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
+static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
+static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
+static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
+static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
+
+static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
+
+static jfieldID ntlm_ctxHandleID;
+static jfieldID ntlm_crdHandleID;
+
+static HINSTANCE lib = NULL;
+
+JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
+(JNIEnv *env, jclass clazz)
+{
+ OSVERSIONINFO version;
+ UCHAR libName[MAX_PATH];
+
+ ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
+ ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
+
+ version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx (&version);
+
+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ strcpy (libName, "security.dll" );
+ }
+ else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ strcpy (libName, "secur32.dll" );
+ }
+
+ lib = LoadLibrary (libName);
+
+ pFreeCredentialsHandle
+ = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
+ lib, "FreeCredentialsHandle" );
+
+ pAcquireCredentialsHandle
+ = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
+ lib, "AcquireCredentialsHandleA" );
+
+ pFreeContextBuffer
+ = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
+ lib, "FreeContextBuffer" );
+
+ pInitializeSecurityContext
+ = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
+ lib, "InitializeSecurityContextA" );
+
+ pCompleteAuthToken
+ = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
+ lib, "CompleteAuthToken" );
+
+ pDeleteSecurityContext
+ = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
+ lib, "DeleteSecurityContext" );
+
+}
+
+/*
+ * Class: sun_net_www_protocol_http_NTLMAuthSequence
+ * Method: getCredentialsHandle
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
+ */
+
+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;
+ SEC_WINNT_AUTH_IDENTITY * pAuthId;
+ const CHAR *pUser = 0;
+ const CHAR *pDomain = 0;
+ const CHAR *pPassword = 0;
+ CredHandle *pCred;
+ TimeStamp ltime;
+ jboolean isCopy;
+ SECURITY_STATUS ss;
+
+ if (user != 0) {
+ pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
+ if (pUser == NULL)
+ return 0; // pending Exception
+ }
+ if (domain != 0) {
+ pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
+ if (pDomain == NULL) {
+ if (pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ return 0; // pending Exception
+ }
+ }
+ if (password != 0) {
+ pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
+ if (pPassword == NULL) {
+ if(pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ if(pDomain != NULL)
+ JNU_ReleaseStringPlatformChars(env, domain, pDomain);
+ return 0; // pending Exception
+ }
+ }
+ pCred = (CredHandle *)malloc(sizeof (CredHandle));
+
+ if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
+ pAuthId = &AuthId;
+
+ memset( &AuthId, 0, sizeof( AuthId ));
+
+ if ( pUser != NULL ) {
+ AuthId.User = (unsigned char *) pUser;
+ AuthId.UserLength = strlen( pUser );
+ }
+
+ if ( pPassword != NULL ) {
+ AuthId.Password = (unsigned char *) pPassword;
+ AuthId.PasswordLength = strlen( pPassword );
+ }
+
+ if ( pDomain != NULL ) {
+ AuthId.Domain = (unsigned char *) pDomain;
+ AuthId.DomainLength = strlen( pDomain );
+ }
+
+ AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+ } else {
+ pAuthId = NULL;
+ }
+
+ ss = pAcquireCredentialsHandle(
+ NULL, "NTLM", SECPKG_CRED_OUTBOUND,
+ NULL, pAuthId, NULL, NULL,
+ pCred, <ime
+ );
+
+ /* Release resources held by JNU_GetStringPlatformChars */
+ if (pUser != NULL)
+ JNU_ReleaseStringPlatformChars(env, user, pUser);
+ if (pPassword != NULL)
+ JNU_ReleaseStringPlatformChars(env, password, pPassword);
+ if (pDomain != NULL)
+ JNU_ReleaseStringPlatformChars(env, domain, pDomain);
+
+ if (ss == 0) {
+ return (jlong) pCred;
+ } else {
+ return 0;
+ }
+}
+
+JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
+(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
+{
+
+ VOID *pInput = 0;
+ DWORD inputLen;
+ CHAR buffOut[512];
+ jboolean isCopy;
+ SECURITY_STATUS ss;
+ SecBufferDesc OutBuffDesc;
+ SecBuffer OutSecBuff;
+ SecBufferDesc InBuffDesc;
+ SecBuffer InSecBuff;
+ ULONG ContextAttributes;
+ CredHandle *pCred = (CredHandle *)crdHandle;
+ CtxtHandle *pCtx;
+ CtxtHandle *newContext;
+ TimeStamp ltime;
+ jbyteArray result;
+
+
+ pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
+ if (pCtx == 0) { /* first call */
+ newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
+ (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
+ } else {
+ newContext = pCtx;
+ }
+
+ OutBuffDesc.ulVersion = 0;
+ OutBuffDesc.cBuffers = 1;
+ OutBuffDesc.pBuffers = &OutSecBuff;
+
+ OutSecBuff.cbBuffer = 512;
+ OutSecBuff.BufferType = SECBUFFER_TOKEN;
+ OutSecBuff.pvBuffer = buffOut;
+
+ /*
+ * Prepare our Input buffer - Note the server is expecting the client's
+ * negotiation packet on the first call
+ */
+
+ if (lastToken != 0)
+ {
+ pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
+ inputLen = (*env)->GetArrayLength(env, lastToken);
+
+ InBuffDesc.ulVersion = 0;
+ InBuffDesc.cBuffers = 1;
+ InBuffDesc.pBuffers = &InSecBuff;
+
+ InSecBuff.cbBuffer = inputLen;
+ InSecBuff.BufferType = SECBUFFER_TOKEN;
+ InSecBuff.pvBuffer = pInput;
+ }
+
+ /*
+ * will return success when its done but we still
+ * need to send the out buffer if there are bytes to send
+ */
+
+ ss = pInitializeSecurityContext(
+ pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
+ lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
+ &ContextAttributes, <ime
+ );
+
+ if (pInput != 0) {
+ (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
+ }
+
+ if (ss < 0) {
+ endSequence (pCred, pCtx);
+ return 0;
+ }
+
+ if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
+ ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
+
+ if (ss < 0) {
+ endSequence (pCred, pCtx);
+ return 0;
+ }
+ }
+
+ if ( OutSecBuff.cbBuffer > 0 ) {
+ jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
+ (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
+ OutSecBuff.pvBuffer);
+ if (lastToken != 0) // 2nd stage
+ endSequence (pCred, pCtx);
+ result = ret;
+ }
+
+ if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
+ endSequence (pCred, pCtx);
+ }
+
+ return result;
+}
+
+static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
+ if (credHand != 0) {
+ pFreeCredentialsHandle (credHand);
+ free (credHand);
+ }
+
+ if (ctxHandle != 0) {
+ pDeleteSecurityContext(ctxHandle);
+ free (ctxHandle);
+ }
+}