Index: java/org/apache/commons/httpclient/Authenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Authenticator.java,v retrieving revision 1.41 diff -u -r1.41 Authenticator.java --- java/org/apache/commons/httpclient/Authenticator.java 28 Mar 2003 16:37:49 -0000 1.41 +++ java/org/apache/commons/httpclient/Authenticator.java 1 Apr 2003 08:58:16 -0000 @@ -199,12 +199,17 @@ * @see HttpMethod#addRequestHeader */ private static boolean authenticate(HttpMethod method, HttpState state, - boolean proxy) + boolean proxy) throws HttpException, UnsupportedOperationException { LOG.trace("enter Authenticator.authenticate(HttpMethod, HttpState, " + "Header, String)"); + return authenticate(method, null, state, proxy); + } + private static boolean authenticate(HttpMethod method, String host, + HttpState state, boolean proxy) + throws HttpException, UnsupportedOperationException { String challengeheader = proxy ? PROXY_AUTH : WWW_AUTH; // I REALLY hate doing this, but I need to avoid multiple autorization @@ -240,9 +245,9 @@ LOG.debug("Using " + authscheme.getSchemeName() + " authentication scheme"); } if (proxy) { - return HttpAuthenticator.authenticateProxy(authscheme, method, state); + return HttpAuthenticator.authenticateProxy(authscheme, method, host, state); } else { - return HttpAuthenticator.authenticate(authscheme, method, state); + return HttpAuthenticator.authenticate(authscheme, method, host, state); } } Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.127 diff -u -r1.127 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 1 Apr 2003 00:25:24 -0000 1.127 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 1 Apr 2003 08:58:29 -0000 @@ -76,7 +76,6 @@ import org.apache.commons.httpclient.cookie.MalformedCookieException; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.cookie.CookieSpec; -import org.apache.commons.httpclient.cookie.MalformedCookieException; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.logging.Log; @@ -1338,7 +1337,7 @@ if (challenges.length > 0) { try { AuthScheme authscheme = HttpAuthenticator.selectAuthScheme(challenges); - HttpAuthenticator.authenticate(authscheme, this, state); + HttpAuthenticator.authenticate(authscheme, this, conn.getHost(), state); } catch (HttpException e) { // log and move on if (LOG.isErrorEnabled()) { @@ -1485,7 +1484,7 @@ if (challenges.length > 0) { try { AuthScheme authscheme = HttpAuthenticator.selectAuthScheme(challenges); - HttpAuthenticator.authenticateProxy(authscheme, this, state); + HttpAuthenticator.authenticateProxy(authscheme, this, conn.getProxyHost(), state); } catch (HttpException e) { // log and move on if (LOG.isErrorEnabled()) { @@ -2340,11 +2339,11 @@ switch (statusCode) { case HttpStatus.SC_UNAUTHORIZED: removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); - authenticated = HttpAuthenticator.authenticate(authscheme, this, state); + authenticated = HttpAuthenticator.authenticate(authscheme, this, conn.getHost(), state); break; case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); - authenticated = HttpAuthenticator.authenticateProxy(authscheme, this, state); + authenticated = HttpAuthenticator.authenticateProxy(authscheme, this, conn.getProxyHost(), state); break; } } catch (AuthenticationException e) { Index: java/org/apache/commons/httpclient/HttpState.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpState.java,v retrieving revision 1.18 diff -u -r1.18 HttpState.java --- java/org/apache/commons/httpclient/HttpState.java 27 Mar 2003 20:58:27 -0000 1.18 +++ java/org/apache/commons/httpclient/HttpState.java 1 Apr 2003 08:58:33 -0000 @@ -64,7 +64,6 @@ package org.apache.commons.httpclient; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -378,7 +377,6 @@ this.cookiePolicy = policy; } - /** * Set the Credentials for the given authentication realm. * @@ -390,40 +388,117 @@ *
* Any previous credentials for this realm will be overwritten.
*
+ * @deprecated This method does not distinguish between realms with the
+ * same name on different hosts. Use
+ * {@link HttpState#setCredentials(String, Credentials)} instead.
+ *
* @param realm the authentication realm
* @param credentials the authentication credentials for the given realm
*
- * @see #getCredentials(String)
- * @see #setProxyCredentials(String, Credentials)
+ * @see #getCredentials(String, String)
+ * @see #setProxyCredentials(String, String, Credentials)
*
*/
+
public synchronized void setCredentials(String realm, Credentials credentials) {
LOG.trace("enter HttpState.setCredentials(String, Credentials)");
- credMap.put(realm, credentials);
+ setCredentials(realm, null, credentials);
+ }
+
+ /** Sets the credentials for realm on host.
+ * with no host.
+ *
+ * When realm is null, I'll use the given
+ * credentials when no other {@link Credentials} have
+ * been supplied for the given challenging realm.
+ * (I.e., use a null realm to set the "default"
+ * credentials.)
+ *
+ * Any previous credentials for this realm will be overwritten.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm belongs to
+ * @param credentials the authentication credentials for the given realm.
+ *
+ * @see #getCredentials(String, String)
+ * @see #setProxyCredentials(String, String, Credentials)
+ */
+
+ public synchronized void setCredentials(String realm, String host, Credentials credentials) {
+ LOG.trace(
+ "enter HttpState.setCredentials(String realm, String host, Credentials credentials)");
+ if (host != null) {
+ if (realm == null) {
+ credMap.put(host.toLowerCase(), credentials);
+ } else {
+ credMap.put(host.toLowerCase() + realm, credentials);
+ }
+ } else {
+ credMap.put(realm, credentials);
+ }
+ }
+
+ /**
+ * Get the Credentials for the given authentication realm.
+ *
+ * If the realm exists on host, return the coresponding credentials.
+ * If the host exists with a null realm, return the corresponding
+ * credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there are no default credentials, return
+ * null.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm is on
+ * @return the credentials
+ *
+ * @see #setCredentials(String, String, Credentials)
+ *
+ */
+
+ public synchronized Credentials getCredentials(String realm, String host) {
+ LOG.trace("enter HttpState.getCredentials(String, String");
+ Credentials creds = null;
+ if (host != null) {
+ creds = (Credentials) credMap.get(host.toLowerCase() + realm);
+ if (creds == null) {
+ creds = (Credentials) credMap.get(host.toLowerCase());
+ }
+ }
+ if (creds == null) {
+ creds = (Credentials) credMap.get(realm);
+ if (creds == null) {
+ creds = (Credentials) credMap.get(null);
+ }
+ }
+ return creds;
}
-
/**
* Get the Credentials for the given authentication realm.
*
- * If the realm exists, return the coresponding credentials. If the
- * realm does not exist, return the default Credentials. If there is
- * no default credentials, return null.
+ * If the realm exists on host, return the coresponding credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there is no default credentials, return
+ * null.
*
+ * @deprecated This method does not distinguish between realms on different
+ * servers with the same name. Use {@link #getCredentials(String, String)}
+ * instead.
+ *
* @param realm the authentication realm
* @return the credentials
*
- * @see #setCredentials(String, Credentials)
+ * @see #setCredentials(String, String, Credentials)
*
*/
+
public synchronized Credentials getCredentials(String realm) {
LOG.trace("enter HttpState.getCredentials(String)");
- Credentials creds = (Credentials) credMap.get(realm);
- if (creds == null) {
- creds = (Credentials) credMap.get(null);
- }
- return creds;
+ return getCredentials(realm, null);
}
/**
@@ -438,6 +513,10 @@
*
* Any previous credentials for this realm will be overwritten.
*
+ * @depreciated This method does not differentiate between realms with
+ * the same name on different servers. Use
+ * {@link #setProxyCredentials(String, String, Credentials)} instead.
+ *
* @param realm the authentication realm
* @param credentials the authentication credentials for the given realm
*
@@ -445,11 +524,44 @@
* @see #setCredentials(String, Credentials)
*
*/
+
public synchronized void setProxyCredentials(String realm, Credentials credentials) {
LOG.trace("enter HttpState.setProxyCredentials(String, credentials)");
- proxyCred.put(realm, credentials);
+ setProxyCredentials(realm, null, credentials);
+ }
+
+ /**
+ * Set the for the proxy with the given authentication realm.
+ *
+ * When realm and host are null, I'll use the given
+ * credentials when no other {@link Credentials} have
+ * been supplied for the given challenging realm.
+ * (I.e., use a null realm to set the "default"
+ * credentials.) Realms rarely make much sense with proxies, so
+ * null is normally a good choice here.
+ *
+ * Any previous credentials for this realm will be overwritten.
+ *
+ * @param realm the authentication realm
+ * @param credentials the authentication credentials for the given realm
+ *
+ * @see #getProxyCredentials(String)
+ * @see #setCredentials(String, Credentials)
+ *
+ */
+
+ public synchronized void setProxyCredentials(String realm, String proxyHost, Credentials credentials) {
+ LOG.trace("enter HttpState.setProxyCredentials(String, String, Credentials");
+ if (proxyHost != null) {
+ if (realm == null) {
+ proxyCred.put(proxyHost.toLowerCase(), credentials);
+ } else {
+ proxyCred.put(proxyHost.toLowerCase() + realm, credentials);
+ }
+ } else {
+ proxyCred.put(realm, credentials);
+ }
}
-
/**
* Get the Credentials for the proxy with the given authentication realm.
@@ -457,19 +569,58 @@
* If the realm exists, return the coresponding credentials. If the
* realm does not exist, return the default Credentials. If there is
* no default credentials, return null.
+ *
+ * @deprecated This method does not distinguish between realms on different hosts.
+ * Use {@link #getProxyCredentials(String, String)} instead.
*
* @param realm the authentication realm
* @return the credentials
- * @see #setProxyCredentials
+ * @see #setProxyCredentials(String, String, Credentials)
*/
+
public synchronized Credentials getProxyCredentials(String realm) {
LOG.trace("enter HttpState.getProxyCredentials(String)");
- Credentials creds = (Credentials) proxyCred.get(realm);
- if (creds == null) {
- creds = (Credentials) proxyCred.get(null);
- }
- return creds;
+ return getProxyCredentials(realm, null);
}
+
+ /**
+ * Get the Credentials for the proxy with the given authentication realm on the given
+ * host.
+ *
+ * If the realm exists on host, return the coresponding credentials.
+ * If the host exists with a null realm, return the corresponding
+ * credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there are no default credentials, return
+ * null.
+ *
+ * @deprecated This method does not distinguish between realms on different hosts.
+ * Use {@link #getProxyCredentials(String, String)} instead.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm is on
+ * @return the credentials
+ * @see #setProxyCredentials(String, String, Credentials)
+ */
+
+ public synchronized Credentials getProxyCredentials(String realm, String proxyHost) {
+ LOG.trace("enter HttpState.getCredentials(String, String");
+ Credentials creds = null;
+ if (proxyHost != null) {
+ creds = (Credentials) proxyCred.get(proxyHost.toLowerCase() + realm);
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(proxyHost.toLowerCase());
+ }
+ }
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(realm);
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(null);
+ }
+ }
+ return creds;
+ }
/**
* Return a string representation of this object.
Index: java/org/apache/commons/httpclient/NTLM.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/NTLM.java,v
retrieving revision 1.12
diff -u -r1.12 NTLM.java
--- java/org/apache/commons/httpclient/NTLM.java 11 Feb 2003 03:41:14 -0000 1.12
+++ java/org/apache/commons/httpclient/NTLM.java 1 Apr 2003 08:58:37 -0000
@@ -280,10 +280,14 @@
}
/**
- * TODO: Figure out what this method really does.
- * @param host The host
- * @param domain The domain
- * @return String
+ * Creates the "type 1" response for NTLM authentication. This is the initial
+ * response to the server which identifies the host and domain of the client.
+ *
+ *
User credentials are supplied in the type 3 message.
+ * + * @param host The host name of the client for authentication. + * @param domain The NT domain the authentication is to occur within. + * @return String The response to send back to the server. */ private String getType1Message(String host, String domain) { host = host.toUpperCase(); @@ -373,12 +377,12 @@ /** * Creates the type 3 message using the given server nonce. - * @param user The user. + * @param user The username. * @param password The password. - * @param host The host. - * @param domain The domain. + * @param host The host name of the client for authentication. + * @param domain The NT domain to authenticate within. * @param nonce the 8 byte array the server sent. - * @return The type 3 message. + * @return The type 3 message to return to the server. * @throws HttpException If {@encrypt(byte[],byte[])} fails. */ private String getType3Message(String user, String password, @@ -477,7 +481,7 @@ * given nonce. * @param password the password to create a hash for. * @param nonce the nonce sent by the server. - * @return The response. + * @return The hashed password to include in the type 3 message. * @throws HttpException If {@link #encrypt(byte[],byte[])} fails. */ private byte[] hashPassword(String password, byte[] nonce) @@ -544,9 +548,9 @@ * plaintext is encrypted with each key and the resulting 24 bytes are * stored in the results array. * - * @param keys The keys. + * @param keys The byte array containing the 21 bytes to use as the keys. * @param plaintext The plain text to encrypt. - * @param results Where the results are stored. + * @param results Where the results are stored. This must be at least 24 bytes long. * @throws HttpException If {@link #encrypt(byte[],byte[])} fails. */ private void calcResp(byte[] keys, byte[] plaintext, byte[] results) Index: java/org/apache/commons/httpclient/auth/HttpAuthenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/HttpAuthenticator.java,v retrieving revision 1.1 diff -u -r1.1 HttpAuthenticator.java --- java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 27 Mar 2003 20:58:27 -0000 1.1 +++ java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 1 Apr 2003 08:58:39 -0000 @@ -247,8 +247,8 @@ } - private static boolean doAuthenticate(AuthScheme authscheme, HttpMethod method, HttpState state, - boolean proxy) + private static boolean doAuthenticate(AuthScheme authscheme, HttpMethod method, String host, + HttpState state, boolean proxy) throws AuthenticationException { if (authscheme == null) { throw new IllegalArgumentException("Authentication scheme may not be null"); @@ -273,8 +273,9 @@ LOG.debug("Using '" + realm + "' authentication realm"); } } + Credentials credentials = proxy ? - state.getProxyCredentials(realm) : state.getCredentials(realm); + state.getProxyCredentials(realm, host) : state.getCredentials(realm, host); if (credentials == null) { throw new AuthenticationException( "No credentials available for the " + authscheme.getSchemeName() + @@ -308,8 +309,29 @@ */ public static boolean authenticate(AuthScheme authscheme, HttpMethod method, HttpState state) throws AuthenticationException { + return authenticate(authscheme, method, null, state); + } + + /** + * Attempt to provide requisite authentication credentials to the + * given method in the given state using the given + * authentication scheme and host. + * + * @param authscheme The authentication scheme to be used + * @param method The HttpMethod which requires authentication + * @param host The host being connected to. + * @param state The HttpState object providing Credentials + * + * @return true if the Authenticate response header was added + * + * @throws AuthenticationException when a parsing or other error occurs + + * @see HttpState#setCredentials(String,Credentials) + */ + public static boolean authenticate(AuthScheme authscheme, HttpMethod method, String host, + HttpState state) throws AuthenticationException { LOG.trace("enter HttpAuthenticator.authenticate(AuthScheme, HttpMethod, HttpState)"); - return doAuthenticate(authscheme, method, state, false); + return doAuthenticate(authscheme, method, host, state, false); } @@ -329,9 +351,9 @@ * @see HttpState#setCredentials(String,Credentials) */ - public static boolean authenticateProxy(AuthScheme authscheme, HttpMethod method, HttpState state) + public static boolean authenticateProxy(AuthScheme authscheme, HttpMethod method, String host, HttpState state) throws AuthenticationException { LOG.trace("enter HttpAuthenticator.authenticateProxy(AuthScheme, HttpMethod, HttpState)"); - return doAuthenticate(authscheme, method, state, true); + return doAuthenticate(authscheme, method, host, state, true); } } Index: test/org/apache/commons/httpclient/TestAuthenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestAuthenticator.java,v retrieving revision 1.23 diff -u -r1.23 TestAuthenticator.java --- test/org/apache/commons/httpclient/TestAuthenticator.java 28 Mar 2003 16:37:50 -0000 1.23 +++ test/org/apache/commons/httpclient/TestAuthenticator.java 1 Apr 2003 08:58:45 -0000 @@ -666,5 +666,53 @@ } - + // --------------------------------- Test Methods for Selecting Credentials + + public void testDefaultCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials(null, expected); + Credentials got = state.getCredentials("realm", "host"); + assertEquals(got, expected); + } + + public void testRealmCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials("realm", expected); + Credentials got = state.getCredentials("realm", "host"); + assertEquals(expected, got); + } + + public void testHostCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials(null, "host", expected); + Credentials got = state.getCredentials("realm", "host"); + assertEquals(expected, got); + } + + public void testBothCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials("realm", "host", expected); + Credentials got = state.getCredentials("realm", "host"); + assertEquals(expected, got); + } + + public void testWrongHostCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials(null, "host1", expected); + Credentials got = state.getCredentials("realm", "host2"); + assertNotSame(expected, got); + } + + public void testWrongRealmCredentials() throws Exception { + HttpState state = new HttpState(); + Credentials expected = new UsernamePasswordCredentials("name", "pass"); + state.setCredentials("realm1", "host", expected); + Credentials got = state.getCredentials("realm2", "host"); + assertNotSame(expected, got); + } }