Index: java/org/apache/commons/httpclient/ConnectMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v retrieving revision 1.24 diff -u -r1.24 ConnectMethod.java --- java/org/apache/commons/httpclient/ConnectMethod.java 11 Dec 2003 01:19:32 -0000 1.24 +++ java/org/apache/commons/httpclient/ConnectMethod.java 12 Jan 2004 12:37:01 -0000 @@ -113,24 +113,6 @@ /** * This method does nothing. CONNECT request is not supposed - * to contain Authorization request header. - * - * @param state current state of http requests - * @param conn the connection to use for I/O - * - * @throws IOException when errors occur reading or writing to/from the - * connection - * @throws HttpException when a recoverable error occurs - * - * @see HttpMethodBase#addAuthorizationRequestHeader(HttpState, HttpConnection) - */ - protected void addAuthorizationRequestHeader(HttpState state, HttpConnection conn) - throws IOException, HttpException { - // Do nothing. Not applicable to CONNECT method - } - - /** - * This method does nothing. CONNECT request is not supposed * to contain Cookie request header. * * @param state current state of http requests Index: java/org/apache/commons/httpclient/HttpClient.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java,v retrieving revision 1.89 diff -u -r1.89 HttpClient.java --- java/org/apache/commons/httpclient/HttpClient.java 10 Nov 2003 23:19:49 -0000 1.89 +++ java/org/apache/commons/httpclient/HttpClient.java 12 Jan 2004 12:37:01 -0000 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java,v 1.89 2003/11/10 23:19:49 olegk Exp $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java,v 1.89 2003/11/10 23:19:49 olegk Exp $ * $Revision: 1.89 $ * $Date: 2003/11/10 23:19:49 $ * @@ -64,10 +64,10 @@ package org.apache.commons.httpclient; import java.io.IOException; -import java.security.Security; -import java.security.Provider; +import java.security.Provider; +import java.security.Security; -import org.apache.commons.httpclient.params.*; +import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; Index: java/org/apache/commons/httpclient/HttpMethodDirector.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodDirector.java,v retrieving revision 1.11 diff -u -r1.11 HttpMethodDirector.java --- java/org/apache/commons/httpclient/HttpMethodDirector.java 10 Dec 2003 21:04:13 -0000 1.11 +++ java/org/apache/commons/httpclient/HttpMethodDirector.java 12 Jan 2004 12:37:02 -0000 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodDirector.java,v 1.11 2003/12/10 21:04:13 olegk Exp $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodDirector.java,v 1.11 2003/12/10 21:04:13 olegk Exp $ * $Revision: 1.11 $ * $Date: 2003/12/10 21:04:13 $ * @@ -65,18 +65,14 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.commons.httpclient.auth.AuthChallengeParser; import org.apache.commons.httpclient.auth.AuthPolicy; import org.apache.commons.httpclient.auth.AuthScheme; import org.apache.commons.httpclient.auth.AuthenticationException; -import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; -import org.apache.commons.httpclient.auth.HttpAuthenticator; import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.httpclient.params.HttpParams; @@ -88,6 +84,18 @@ */ class HttpMethodDirector { + /** The www authenticate challange header. */ + public static final String WWW_AUTH_CHALLENGE = "WWW-Authenticate"; + + /** The www authenticate response header. */ + public static final String WWW_AUTH_RESP = "Authorization"; + + /** The proxy authenticate challange header. */ + public static final String PROXY_AUTH_CHALLENGE = "Proxy-Authenticate"; + + /** The proxy authenticate response header. */ + public static final String PROXY_AUTH_RESP = "Proxy-Authorization"; + /** Maximum number of redirects and authentications that will be followed */ private static final int MAX_FORWARDS = 100; @@ -108,18 +116,27 @@ /** A flag to indicate if the connection should be released after the method is executed. */ private boolean releaseConnection = false; - /** Realms that we tried to authenticate to */ - private Set realms = null; - - /** Proxy Realms that we tried to authenticate to */ - private Set proxyRealms = null; + private static final int AUTH_UNINITIATED = 0; + private static final int AUTH_PREEMPTIVE = 1; + private static final int AUTH_WWW_REQUIRED = 2; + private static final int AUTH_PROXY_REQUIRED = 3; + private static final int AUTH_NOT_REQUIRED = Integer.MAX_VALUE; + /** Actual state of authentication process */ + private int authState = AUTH_UNINITIATED; + /** Actual authentication scheme */ private AuthScheme authScheme = null; + /** Whether preemtive authentication is attempted */ + private boolean authPreemptive = false; + /** Actual proxy authentication scheme */ private AuthScheme proxyAuthScheme = null; + /** Whether preemtive proxy authentication is attempted */ + private boolean proxyAuthPreemptive = false; + //TODO: to be parameterized private static final List AUTH_PREFERENCES = new ArrayList(3); static { @@ -178,34 +195,41 @@ this.params.getConnectionManagerTimeout() ); this.conn.setLocked(true); + if (this.params.isAuthenticationPreemptive()) { - realms = new HashSet(); - proxyRealms = new HashSet(); - - addPreemtiveAuthenticationHeaders(method); + LOG.debug("Preemptively sending default basic credentials"); + this.authState = AUTH_PREEMPTIVE; + this.authScheme = AuthPolicy.getAuthScheme("basic"); + this.authPreemptive = true; + if (this.conn.isProxied()) { + this.proxyAuthPreemptive = true; + this.proxyAuthScheme = AuthPolicy.getAuthScheme("basic"); + } + } } + authenticate(method); executeWithRetry(method); if (this.connectMethod != null) { - //CONNECT method failed. Bow out. fakeResponse(method); break; - } else if (isRedirectNeeded(method)) { - //if the redirect is unsuccessful, return the statusCode - //otherwise, drop through the switch and try again. - if (!processRedirectResponse(method)) { - break; + } + + boolean retry = false; + if (isRedirectNeeded(method)) { + if (processRedirectResponse(method)) { + retry = true; } - } else if (isAuthenticationNeeded(method)) { - //if the authentication is unsuccessful, return the statusCode - //otherwise, drop through the switch and try again. - if (!processAuthenticationResponse(method)) { - break; + } + if (isAuthenticationNeeded(method)) { + if (processAuthenticationResponse(method)) { + retry = true; } } else { - // nope, no retry needed, exit loop. + this.authState = AUTH_NOT_REQUIRED; + } + if (!retry) { break; } - // retry - close previous stream. Caution - this causes // responseBodyConsumed to be called, which may also close the // connection. @@ -239,47 +263,93 @@ } } + - private void applyDefaultCredentials(final HttpMethod method) { + private void authenticate(final HttpMethod method) { try { - if (HttpAuthenticator.authenticateDefault(method, this.conn, state)) { - LOG.debug("Default basic credentials applied"); - } + authenticateProxy(method); + authenticateHost(method); } catch (AuthenticationException e) { - // Log error and move on LOG.error(e.getMessage(), e); } } - private void applyDefaultProxyCredentials(final HttpMethod method) { - try { - if (HttpAuthenticator.authenticateProxyDefault(method, this.conn, state)) { - LOG.debug("Default basic proxy credentials applied"); + + private void authenticateHost(final HttpMethod method) throws AuthenticationException { + // Clean up existing authentication headers + method.removeRequestHeader(WWW_AUTH_RESP); + if ((this.authScheme != null) + && ((this.authState == AUTH_WWW_REQUIRED) + || (!this.authScheme.isConnectionBased()))) + { + String host = conn.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + String realm = this.authScheme.getRealm(); + if (LOG.isDebugEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Authenticating with "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" authentication realm at "); + buffer.append(host); + LOG.info(buffer.toString()); + } + Credentials credentials = this.state.getCredentials(realm, host); + if (credentials != null) { + String authstring = this.authScheme.authenticate(credentials, method); + if (authstring != null) { + method.addRequestHeader(new Header(WWW_AUTH_RESP, authstring, true)); + } + } else { + LOG.warn("Required credentials not available"); } - } catch (AuthenticationException e) { - // Log error and move on - LOG.error(e.getMessage(), e); } } - - /** - * Adds authentication headers if authenticationPreemtive has been set. - * - * @see HttpClientParams#isAuthenticationPreemptive() - */ - private void addPreemtiveAuthenticationHeaders(final HttpMethod method) { - //pre-emptively add the authorization header, if required. - if (this.params.isAuthenticationPreemptive()) { - LOG.debug("Preemptively sending default basic credentials"); - applyDefaultCredentials(method); - if (this.conn.isProxied()) { - applyDefaultProxyCredentials(method); + private void authenticateProxy(final HttpMethod method) throws AuthenticationException { + // Clean up existing authentication headers + method.removeRequestHeader(PROXY_AUTH_RESP); + if ((this.proxyAuthScheme != null) + && ((this.authState == AUTH_PROXY_REQUIRED) + || (!this.proxyAuthScheme.isConnectionBased()))) + { + String host = conn.getProxyHost(); + String realm = this.proxyAuthScheme.getRealm(); + if (LOG.isDebugEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Authenticating with "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" proxy authentication realm at "); + buffer.append(host); + LOG.info(buffer.toString()); + } + Credentials credentials = this.state.getProxyCredentials(realm, host); + if (credentials != null) { + String authstring = this.proxyAuthScheme.authenticate(credentials, method); + if (authstring != null) { + method.addRequestHeader(new Header(PROXY_AUTH_RESP, authstring, true)); + } + } else { + LOG.warn("Required credentials not available"); } } } + /** * Executes a method with the current hostConfiguration. * @@ -379,17 +449,23 @@ this.connectMethod.getParams().setDefaults(this.params); int code; - if (this.params.isAuthenticationPreemptive()) { - applyDefaultProxyCredentials(this.connectMethod); - } for (;;) { + try { + authenticateProxy(this.connectMethod); + } catch (AuthenticationException e) { + LOG.error(e.getMessage(), e); + } executeWithRetry(this.connectMethod); code = this.connectMethod.getStatusCode(); + boolean retry = false; if (code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { - if (!processAuthenticationResponse(this.connectMethod)) { - break; + if (processAuthenticationResponse(this.connectMethod)) { + retry = true; } } else { + this.authState = AUTH_NOT_REQUIRED; + } + if (!retry) { break; } if (this.connectMethod.getResponseBodyAsStream() != null) { @@ -495,16 +571,6 @@ LOG.warn("Redirected location '" + location + "' is malformed"); return false; } - - //invalidate the list of authentication attempts - this.realms.clear(); - //remove exisitng authentication headers - if ((this.proxyAuthScheme != null) && (this.proxyAuthScheme.isConnectionBased())) { - method.removeRequestHeader(HttpAuthenticator.PROXY_AUTH); - } - method.removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); - //Invalidate present authentication scheme - this.authScheme = null; //update the current location with the redirect location. //avoiding use of URL.getPath() and URL.getQuery() to keep //jdk1.2 comliance. @@ -517,14 +583,15 @@ + "' to '" + redirectUri.getEscapedURI()); } + //And finally invalidate the actual authentication scheme + this.authScheme = null; return true; } /** * Processes a response that requires authentication * - * @param state the current state - * @param conn The connection + * @param method the current {@link HttpMethod HTTP method} * * @return true if the authentication challenge can be responsed to, * (that is, at least one of the requested authentication scheme is supported, @@ -534,92 +601,149 @@ LOG.trace("enter HttpMethodBase.processAuthenticationResponse(" + "HttpState, HttpConnection)"); - if ((this.proxyAuthScheme != null) && (this.proxyAuthScheme.isConnectionBased())) { - method.removeRequestHeader(HttpAuthenticator.PROXY_AUTH); - } - if ((this.authScheme != null) && (this.authScheme.isConnectionBased())) { - method.removeRequestHeader(HttpAuthenticator.WWW_AUTH); - } - boolean authenticated = false; try { switch (method.getStatusCode()) { case HttpStatus.SC_UNAUTHORIZED: - Map challenges = AuthChallengeParser.parseChallenges( - method.getResponseHeaders(HttpAuthenticator.WWW_AUTH)); - if (challenges.isEmpty()) { - return false; - } - if (this.authScheme != null) { - processChallenge(this.authScheme, challenges); - } else { - this.authScheme = processChallenge(challenges); - if (this.authScheme == null) { - return false; - } - } - String host = this.conn.getVirtualHost(); - if (host == null) { - host = this.conn.getHost(); - } - if (previousAttemptFailed(this.realms, host, - this.authScheme)) { - return false; - } - method.removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); - authenticated = HttpAuthenticator.authenticate( - this.authScheme, method, this.conn, this.state); - break; + return processWWWAuthChallenge(method); case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: - Map proxyChallenges = AuthChallengeParser.parseChallenges( - method.getResponseHeaders(HttpAuthenticator.PROXY_AUTH)); - if (proxyChallenges.isEmpty()) { - return false; - } - if (this.proxyAuthScheme != null) { - processChallenge(this.proxyAuthScheme, proxyChallenges); - } else { - this.proxyAuthScheme = processChallenge(proxyChallenges); - if (this.proxyAuthScheme == null) { - return false; - } - } - if (previousAttemptFailed(this.proxyRealms, this.conn.getProxyHost(), - this.proxyAuthScheme)) { - return false; - } - method.removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); - authenticated = HttpAuthenticator.authenticateProxy( - proxyAuthScheme, method, this.conn, this.state); - break; + return processProxyAuthChallenge(method); + default: + return false; } - } catch (MalformedChallengeException e) { + } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error(e.getMessage(), e); } return false; - } catch (CredentialsNotAvailableException e) { - if (LOG.isWarnEnabled()) { - LOG.warn(e.getMessage()); + } + } + + private boolean processWWWAuthChallenge(final HttpMethod method) + throws MalformedChallengeException, AuthenticationException + { + if (this.authPreemptive) { + this.authScheme = null; + this.authPreemptive = false; + } + Map challenges = AuthChallengeParser.parseChallenges( + method.getResponseHeaders(WWW_AUTH_CHALLENGE)); + if (challenges.isEmpty()) { + return false; + } + if (this.authScheme != null) { + processChallenge(this.authScheme, challenges); + } else { + this.authScheme = processChallenge(challenges); + } + if (this.authScheme == null) { + return false; + } + if ((this.authState == AUTH_WWW_REQUIRED) + && (this.authScheme.isComplete())) { + // Already tried and failed + if (LOG.isInfoEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Attempt to authenticate with '"); + buffer.append(this.authScheme.getRealm()); + buffer.append("' authentication realm at "); + String host = this.conn.getVirtualHost(); + if (host == null) { + host = this.conn.getHost(); + } + buffer.append(host); + buffer.append(" failed"); + LOG.info(buffer.toString()); } return false; - } catch (AuthenticationException e) { - if (LOG.isErrorEnabled()) { - LOG.error(e.getMessage(), e); + } else { + this.authState = AUTH_WWW_REQUIRED; + + String host = conn.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + String realm = this.authScheme.getRealm(); + Credentials credentials = this.state.getCredentials(realm, host); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("No credentials available for the "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" authentication realm at "); + buffer.append(host); + } + return false; + } else { + return true; } + } + } + + private boolean processProxyAuthChallenge(final HttpMethod method) + throws MalformedChallengeException, AuthenticationException + { + if (this.proxyAuthPreemptive) { + this.proxyAuthScheme = null; + this.proxyAuthPreemptive = false; + } + Map proxyChallenges = AuthChallengeParser.parseChallenges( + method.getResponseHeaders(PROXY_AUTH_CHALLENGE)); + if (proxyChallenges.isEmpty()) { + return false; + } + if (this.proxyAuthScheme != null) { + processChallenge(this.proxyAuthScheme, proxyChallenges); + } else { + this.proxyAuthScheme = processChallenge(proxyChallenges); + } + if (this.proxyAuthScheme == null) { return false; - } - if (!authenticated) { - // won't be able to authenticate to this challenge - // without additional information - LOG.debug("Credentials required to respond to authorization" + - " challenge are not available"); - } else { - LOG.debug("Credentials required to respond to authorization" + - " challenge have been provided"); - // let's try it again, using the credentials - } - return authenticated; - } + } + if ((this.authState == AUTH_PROXY_REQUIRED) + && (this.proxyAuthScheme.isComplete())) { + // Already tried and failed + if (LOG.isInfoEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Attempt to authenticate with '"); + buffer.append(this.authScheme.getRealm()); + buffer.append("' proxy authentication realm at "); + buffer.append(this.conn.getProxyHost()); + buffer.append(" failed"); + LOG.info(buffer.toString()); + } + return false; + } else { + this.authState = AUTH_PROXY_REQUIRED; + + String host = conn.getProxyHost(); + String realm = this.proxyAuthScheme.getRealm(); + Credentials credentials = this.state.getProxyCredentials(realm, host); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + StringBuffer buffer = new StringBuffer(); + buffer.append("No credentials available for the "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" proxy authentication realm at "); + buffer.append(host); + } + return false; + } else { + return true; + } + } + } private void processChallenge(final AuthScheme authscheme, final Map challenges) throws MalformedChallengeException, AuthenticationException @@ -679,34 +803,6 @@ return authscheme; } - - private boolean previousAttemptFailed(final Set realms, final String host, final AuthScheme authscheme) { - // See if authentication against the given realm & host has - // already been attempted - StringBuffer buffer = new StringBuffer(); - buffer.append(host); - buffer.append('#'); - buffer.append(authscheme.getID()); - String realm = buffer.toString(); - - if (realms.contains(realm)) { - // Already tried. Give up - if (LOG.isInfoEnabled()) { - buffer = new StringBuffer(); - buffer.append("Attempt to authenticate with '"); - buffer.append(authscheme.getRealm()); - buffer.append("' authentication realm at "); - buffer.append(host); - buffer.append(" failed"); - LOG.info(buffer.toString()); - } - return true; - } else { - realms.add(realm); - return false; - } - - } /** * Tests if the {@link HttpMethod method} requires a redirect to another location. * @@ -748,7 +844,7 @@ if (method.getDoAuthentication()) { //process authentication response return true; } else { //let the client handle the authenticaiton - LOG.info("Redirect requested but doAuthentication is " + LOG.info("Authentication requested but doAuthentication is " + "disabled"); return false; } @@ -785,4 +881,31 @@ return this.params; } + /** + * Returns the authentication scheme used to authenticate with the + * target host. + * + * @return the authentication scheme used to authenticate with the + * target host. Null is returned if target host authentication + * was not required. + * + * @since 2.1 + */ + public AuthScheme getAuthScheme() { + return authScheme; + } + + /** + * Returns the authentication scheme used to authenticate with the + * proxy host. + * + * @return the authentication scheme used to authenticate with the + * proxy host. Null is returned if proxy authentication was not + * required. + * + * @since 2.1 + */ + public AuthScheme getProxyAuthScheme() { + return proxyAuthScheme; + } } Index: java/org/apache/commons/httpclient/auth/AuthScheme.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/AuthScheme.java,v retrieving revision 1.7 diff -u -r1.7 AuthScheme.java --- java/org/apache/commons/httpclient/auth/AuthScheme.java 6 Jan 2004 20:08:56 -0000 1.7 +++ java/org/apache/commons/httpclient/auth/AuthScheme.java 12 Jan 2004 12:37:02 -0000 @@ -152,6 +152,8 @@ * * @return String a String identifying the authentication challenge. The * returned value may be null. + * + * @deprecated no longer used */ String getID(); @@ -164,6 +166,16 @@ */ boolean isConnectionBased(); + /** + * Authentication process may involve a series of challenge-response exchanges. + * This method tests if the authorization process has been completed, either + * successfully or unsuccessfully, that is, all the required authorization + * challenges have been processed in their entirety. + * + * @return true if the authentication process has been completed, + * false otherwise. + */ + boolean isComplete(); /** * @deprecated Use {@link #authenticate(Credentials, HttpMethod)} * Index: java/org/apache/commons/httpclient/auth/BasicScheme.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/BasicScheme.java,v retrieving revision 1.10 diff -u -r1.10 BasicScheme.java --- java/org/apache/commons/httpclient/auth/BasicScheme.java 6 Jan 2004 20:08:56 -0000 1.10 +++ java/org/apache/commons/httpclient/auth/BasicScheme.java 12 Jan 2004 12:37:03 -0000 @@ -92,12 +92,16 @@ /** Log object for this class. */ private static final Log LOG = LogFactory.getLog(BasicScheme.class); + /** Whether the basic authentication process is complete */ + private boolean complete; + /** * Default constructor for the basic authetication scheme. * */ public BasicScheme() { super(); + this.complete = false; } /** @@ -113,9 +117,9 @@ */ public BasicScheme(final String challenge) throws MalformedChallengeException { super(challenge); + this.complete = true; } - /** * Returns textual designation of the basic authentication scheme. * @@ -123,6 +127,31 @@ */ public String getSchemeName() { return "basic"; + } + + /** + * Processes the Basic challenge. + * + * @param the challenge string + * + * @throws MalformedChallengeException is thrown if the authentication challenge + * is malformed + */ + public void processChallenge(String challenge) + throws MalformedChallengeException + { + super.processChallenge(challenge); + this.complete = true; + } + + /** + * Tests if the Basic authentication process has been completed. + * + * @return true if Basic authorization has been processed, + * false otherwise. + */ + public boolean isComplete() { + return this.complete; } /** Index: java/org/apache/commons/httpclient/auth/DigestScheme.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/DigestScheme.java,v retrieving revision 1.14 diff -u -r1.14 DigestScheme.java --- java/org/apache/commons/httpclient/auth/DigestScheme.java 6 Jan 2004 20:08:56 -0000 1.14 +++ java/org/apache/commons/httpclient/auth/DigestScheme.java 12 Jan 2004 12:37:03 -0000 @@ -120,6 +120,9 @@ 'e', 'f' }; + /** Whether the digest authentication process is complete */ + private boolean complete; + //TODO: supply a real nonce-count, currently a server will interprete a repeated request as a replay private static final String NC = "00000001"; //nonce-count is always 1 private static final int QOP_MISSING = 0; @@ -135,12 +138,15 @@ */ public DigestScheme() { super(); + this.complete = false; } /** * Gets an ID based upon the realm and the nonce value. This ensures that requests * to the same realm with different nonce values will succeed. This differentiation * allows servers to request re-authentication using a fresh nonce value. + * + * @deprecated no longer used */ public String getID() { @@ -167,35 +173,7 @@ public DigestScheme(final String challenge) throws MalformedChallengeException { super(challenge); - - if (getParameter("nonce") == null) { - throw new MalformedChallengeException("missing nonce in challange"); - } - - boolean unsupportedQop = false; - // qop parsing - String qop = getParameter("qop"); - if (qop != null) { - StringTokenizer tok = new StringTokenizer(qop,","); - while (tok.hasMoreTokens()) { - String variant = tok.nextToken().trim(); - if (variant.equals("auth")) { - qopVariant = QOP_AUTH; - break; //that's our favourite, because auth-int is unsupported - } else if (variant.equals("auth-int")) { - qopVariant = QOP_AUTH_INT; - } else { - unsupportedQop = true; - LOG.warn("Unsupported qop detected: "+ variant); - } - } - } - - if (unsupportedQop && (qopVariant == QOP_MISSING)) { - throw new MalformedChallengeException("None of the qop methods is supported"); - } - - cnonce = createCnonce(); + this.complete = true; } /** @@ -238,8 +216,23 @@ } cnonce = createCnonce(); + this.complete = true; } + /** + * Tests if the Digest authentication process has been completed. + * + * @return true if Digest authorization has been processed, + * false otherwise. + */ + public boolean isComplete() { + String s = getParameter("stale"); + if ("true".equalsIgnoreCase(s)) { + return false; + } else { + return this.complete; + } + } /** * Returns textual designation of the digest authentication scheme. 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.15 diff -u -r1.15 HttpAuthenticator.java --- java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 11 Dec 2003 01:19:32 -0000 1.15 +++ java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 12 Jan 2004 12:37:04 -0000 @@ -100,6 +100,8 @@ * @author Adrian Sutton * @author Mike Bowler * @author Oleg Kalnichevski + * + * @deprecated no longer used */ public final class HttpAuthenticator { @@ -238,6 +240,8 @@ * @throws AuthenticationException when a parsing or other error occurs * * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme */ public static boolean authenticateDefault( HttpMethod method, @@ -269,6 +273,8 @@ * @throws AuthenticationException when a parsing or other error occurs * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme */ public static boolean authenticateProxyDefault( HttpMethod method, @@ -310,7 +316,7 @@ String realm = authscheme.getRealm(); if (LOG.isDebugEnabled()) { StringBuffer buffer = new StringBuffer(); - buffer.append("Authenticating with the "); + buffer.append("Using credentials for "); if (realm == null) { buffer.append("default"); } else { @@ -326,9 +332,18 @@ ? state.getProxyCredentials(realm, host) : state.getCredentials(realm, host); if (credentials == null) { - throw new CredentialsNotAvailableException( - "No credentials available for the '" + realm - + "' authentication realm at " + host); + StringBuffer buffer = new StringBuffer(); + buffer.append("No credentials available for the "); + if (realm == null) { + buffer.append("default"); + } else { + buffer.append('\''); + buffer.append(realm); + buffer.append('\''); + } + buffer.append(" authentication realm at "); + buffer.append(host); + throw new CredentialsNotAvailableException(buffer.toString()); } String auth = authscheme.authenticate(credentials, method); if (auth != null) { @@ -360,6 +375,8 @@ * @throws AuthenticationException when a parsing or other error occurs * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme */ public static boolean authenticate( AuthScheme authscheme, @@ -394,6 +411,8 @@ * @throws AuthenticationException when a parsing or other error occurs * @see HttpState#setCredentials(String,String,Credentials) + * + * @deprecated use AuthScheme */ public static boolean authenticateProxy( AuthScheme authscheme, Index: java/org/apache/commons/httpclient/auth/NTLM.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/NTLM.java,v retrieving revision 1.6 diff -u -r1.6 NTLM.java --- java/org/apache/commons/httpclient/auth/NTLM.java 6 Jan 2004 20:08:56 -0000 1.6 +++ java/org/apache/commons/httpclient/auth/NTLM.java 12 Jan 2004 12:37:04 -0000 @@ -263,7 +263,7 @@ * @param domain The domain to authenticate with. * @return String the message to add to the HTTP request header. */ - private String getType1Message(String host, String domain) { + public String getType1Message(String host, String domain) { host = host.toUpperCase(); domain = domain.toUpperCase(); byte[] hostBytes = EncodingUtil.getBytes(host, DEFAULT_CHARSET); @@ -338,7 +338,7 @@ * @return an array of 8 bytes that the server sent to be used when * hashing the password. */ - private byte[] parseType2Message(String message) { + public byte[] parseType2Message(String message) { // Decode the message first. byte[] msg = Base64.decodeBase64(EncodingUtil.getBytes(message, DEFAULT_CHARSET)); byte[] nonce = new byte[8]; @@ -362,7 +362,7 @@ * @return The type 3 message. * @throws AuthenticationException If {@encrypt(byte[],byte[])} fails. */ - private String getType3Message(String user, String password, + public String getType3Message(String user, String password, String host, String domain, byte[] nonce) throws AuthenticationException { Index: java/org/apache/commons/httpclient/auth/NTLMScheme.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/NTLMScheme.java,v retrieving revision 1.14 diff -u -r1.14 NTLMScheme.java --- java/org/apache/commons/httpclient/auth/NTLMScheme.java 6 Jan 2004 20:08:56 -0000 1.14 +++ java/org/apache/commons/httpclient/auth/NTLMScheme.java 12 Jan 2004 12:37:05 -0000 @@ -90,12 +90,21 @@ /** NTLM challenge string. */ private String ntlmchallenge = null; + private static final int UNINITIATED = 0; + private static final int INITIATED = 1; + private static final int TYPE1_MSG_GENERATED = 2; + private static final int TYPE2_MSG_RECEIVED = 3; + private static final int TYPE3_MSG_GENERATED = 4; + + /** Authentication process state */ + private int state; /** * Default constructor for the NTLM authentication scheme. * */ public NTLMScheme() { super(); + this.state = UNINITIATED; } /** @@ -128,12 +137,24 @@ if (i != -1) { s = challenge.substring(i, challenge.length()); this.ntlmchallenge = s.trim(); + this.state = TYPE2_MSG_RECEIVED; } else { this.ntlmchallenge = ""; + this.state = INITIATED; } } /** + * Tests if the NTLM authentication process has been completed. + * + * @return true if Basic authorization has been processed, + * false otherwise. + */ + public boolean isComplete() { + return this.state == TYPE3_MSG_GENERATED; + } + + /** * Returns textual designation of the NTLM authentication scheme. * * @return ntlm @@ -167,12 +188,13 @@ * * @return String a String identifying the authentication challenge. The * returned value may be null. + * + * @deprecated no longer used */ public String getID() { return ntlmchallenge; } - /** * Returns the authentication parameter with the given name, if available. * @@ -208,6 +230,8 @@ * * @return a ntlm authorization string * @throws AuthenticationException is thrown if authentication fails + * + * @deprecated Use non-static {@link #authenticate(Credentials, HttpMethod)} */ public static String authenticate( final NTCredentials credentials, final String challenge) @@ -236,6 +260,8 @@ * * @return a ntlm authorization string * @throws AuthenticationException is thrown if authentication fails + * + * @deprecated Use non-static {@link #authenticate(Credentials, HttpMethod)} */ public static String authenticate( final NTCredentials credentials, @@ -311,6 +337,10 @@ ) throws AuthenticationException { LOG.trace("enter NTLMScheme.authenticate(Credentials, HttpMethod)"); + if (this.state == UNINITIATED) { + throw new IllegalStateException("NTLM authentication process has not been initiated"); + } + NTCredentials ntcredentials = null; try { ntcredentials = (NTCredentials) credentials; @@ -319,9 +349,22 @@ "Credentials cannot be used for NTLM authentication: " + credentials.getClass().getName()); } - return NTLMScheme.authenticate( - ntcredentials, - this.ntlmchallenge, - method.getParams().getCredentialCharset()); + NTLM ntlm = new NTLM(); + String response = null; + if (this.state == INITIATED) { + response = ntlm.getType1Message( + ntcredentials.getHost(), + ntcredentials.getDomain()); + this.state = TYPE1_MSG_GENERATED; + } else { + response = ntlm.getType3Message( + ntcredentials.getUserName(), + ntcredentials.getPassword(), + ntcredentials.getHost(), + ntcredentials.getDomain(), + ntlm.parseType2Message(this.ntlmchallenge)); + this.state = TYPE3_MSG_GENERATED; + } + return "NTLM " + response; } } Index: java/org/apache/commons/httpclient/auth/RFC2617Scheme.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/RFC2617Scheme.java,v retrieving revision 1.5 diff -u -r1.5 RFC2617Scheme.java --- java/org/apache/commons/httpclient/auth/RFC2617Scheme.java 10 Dec 2003 21:04:13 -0000 1.5 +++ java/org/apache/commons/httpclient/auth/RFC2617Scheme.java 12 Jan 2004 12:37:05 -0000 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/RFC2617Scheme.java,v 1.5 2003/12/10 21:04:13 olegk Exp $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/RFC2617Scheme.java,v 1.5 2003/12/10 21:04:13 olegk Exp $ * $Revision: 1.5 $ * $Date: 2003/12/10 21:04:13 $ * @@ -144,6 +144,9 @@ if (name == null) { throw new IllegalArgumentException("Parameter name may not be null"); } + if (this.params == null) { + return null; + } return (String) this.params.get(name.toLowerCase()); } @@ -173,6 +176,8 @@ * * @return String a String identifying the authentication challenge. The * returned value may be null. + * + * @deprecated no longer used */ public String getID() { return getRealm(); 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.36 diff -u -r1.36 TestAuthenticator.java --- test/org/apache/commons/httpclient/TestAuthenticator.java 6 Jan 2004 20:08:56 -0000 1.36 +++ test/org/apache/commons/httpclient/TestAuthenticator.java 12 Jan 2004 12:37:06 -0000 @@ -70,9 +70,10 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.httpclient.auth.AuthChallengeParser; import org.apache.commons.httpclient.auth.AuthScheme; +import org.apache.commons.httpclient.auth.AuthenticationException; import org.apache.commons.httpclient.auth.BasicScheme; +import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; import org.apache.commons.httpclient.auth.DigestScheme; -import org.apache.commons.httpclient.auth.HttpAuthenticator; import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.auth.NTLMScheme; @@ -103,6 +104,71 @@ } + // ---------------------------------- Helper functions + + protected static boolean doAuthenticate( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state, + boolean proxy) + throws AuthenticationException { + + if (authscheme == null) { + throw new IllegalArgumentException("Authentication scheme may not be null"); + } + if (method == null) { + throw new IllegalArgumentException("HTTP method may not be null"); + } + if (state == null) { + throw new IllegalArgumentException("HTTP state may not be null"); + } + String host = null; + if (conn != null) { + if (proxy) { + host = conn.getProxyHost(); + } else { + host = conn.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + } + } + String realm = authscheme.getRealm(); + Credentials credentials = proxy + ? state.getProxyCredentials(realm, host) + : state.getCredentials(realm, host); + if (credentials == null) { + throw new CredentialsNotAvailableException("No credentials available"); + } + String auth = authscheme.authenticate(credentials, method); + if (auth != null) { + String s = proxy ? "Proxy-Authorization" : "Authorization"; + Header header = new Header(s, auth, true); + method.addRequestHeader(header); + return true; + } else { + return false; + } + } + + private static boolean authenticate( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state) + throws AuthenticationException { + return doAuthenticate(authscheme, method, conn, state, false); + } + + public static boolean authenticateProxy( + AuthScheme authscheme, + HttpMethod method, + HttpConnection conn, + HttpState state + ) throws AuthenticationException { + return doAuthenticate(authscheme, method, conn, state, true); + } // ---------------------------------- Test Methods for BasicScheme Authentication public void testCredentialConstructors() { @@ -139,7 +205,7 @@ try { AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -153,7 +219,7 @@ try { AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -167,7 +233,7 @@ try { AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -180,7 +246,7 @@ try { AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, null); + authenticate(authscheme, method, null, null); fail("Should have thrown IllegalArgumentException"); } catch(IllegalArgumentException e) { // expected @@ -194,7 +260,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WwW-AuThEnTiCaTe", challenge)); AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("username:password"))); @@ -206,7 +272,7 @@ HttpState state = new HttpState(); state.setCredentials(null, null, new UsernamePasswordCredentials("username","password")); HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate","Basic realm=\"realm1\"")); - assertTrue(HttpAuthenticator.authenticateDefault(method, null, state)); + assertTrue(authenticate(new BasicScheme(), method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("username:password"))); @@ -220,7 +286,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); AuthScheme authscheme = new BasicScheme(); authscheme.processChallenge(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("username:password"))); @@ -251,7 +317,7 @@ authscheme2.processChallenge(challenge2); { HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate",challenge1)); - assertTrue(HttpAuthenticator.authenticate(authscheme1, method, null, state)); + assertTrue(authenticate(authscheme1, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("username:password"))); @@ -259,7 +325,7 @@ } { HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge2)); - assertTrue(HttpAuthenticator.authenticate(authscheme2, method, null, state)); + assertTrue(authenticate(authscheme2, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("uname2:password2"))); @@ -267,20 +333,12 @@ } } - public void testPreemptiveAuthorizationTrueNoCreds() throws Exception { - HttpState state = new HttpState(); - HttpMethod method = new SimpleHttpMethod(); - - assertTrue(!HttpAuthenticator.authenticateDefault(method, null, state)); - assertTrue(null == method.getRequestHeader("Authorization")); - } - public void testPreemptiveAuthorizationTrueWithCreds() throws Exception { HttpState state = new HttpState(); HttpMethod method = new SimpleHttpMethod(); state.setCredentials(null, null, new UsernamePasswordCredentials("username","password")); - assertTrue(HttpAuthenticator.authenticateDefault(method, null, state)); + assertTrue(authenticate(new BasicScheme(), method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); String expected = "Basic " + HttpConstants.getString( Base64.encodeBase64(HttpConstants.getBytes("username:password"))); @@ -296,7 +354,7 @@ try { AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -310,7 +368,7 @@ try { AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -324,7 +382,7 @@ try { AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -337,7 +395,7 @@ try { AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, null); + authenticate(authscheme, method, null, null); fail("Should have thrown IllegalArgumentException"); } catch(IllegalArgumentException e) { // expected @@ -352,7 +410,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WwW-AuThEnTiCaTe", challenge)); AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); } @@ -365,7 +423,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); assertEquals("username", table.get("username")); @@ -383,7 +441,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); AuthScheme authscheme = new DigestScheme(); authscheme.processChallenge(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); assertEquals("username", table.get("username")); @@ -446,7 +504,7 @@ authscheme2.processChallenge(challenge2); { HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate",challenge1)); - assertTrue(HttpAuthenticator.authenticate(authscheme1, method, null, state)); + assertTrue(authenticate(authscheme1, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); assertEquals("username", table.get("username")); @@ -457,7 +515,7 @@ } { HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate",challenge2)); - assertTrue(HttpAuthenticator.authenticate(authscheme2, method, null, state)); + assertTrue(authenticate(authscheme2, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); assertEquals("uname2", table.get("username")); @@ -494,7 +552,7 @@ authscheme.processChallenge(challenge); HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); - assertTrue(HttpAuthenticator.authenticate( + assertTrue(authenticate( authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); @@ -536,7 +594,7 @@ authscheme.processChallenge(challenge); HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); - assertTrue(HttpAuthenticator.authenticate( + assertTrue(authenticate( authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); Map table = AuthChallengeParser.extractParams(method.getRequestHeader("Authorization").getValue()); @@ -594,7 +652,7 @@ method.addRequestHeader("Host", "host"); try { AuthScheme authscheme = new NTLMScheme(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, state); + authenticate(authscheme, method, null, state); fail("Should have thrown HttpException"); } catch(HttpException e) { // expected @@ -607,7 +665,7 @@ method.addRequestHeader("Host", "host"); try { AuthScheme authscheme = new NTLMScheme(challenge); - HttpAuthenticator.authenticate(authscheme, method, null, null); + authenticate(authscheme, method, null, null); fail("Should have thrown IllegalArgumentException"); } catch(IllegalArgumentException e) { // expected @@ -622,7 +680,7 @@ state.setCredentials(null, null, cred); HttpMethod method = new SimpleHttpMethod(new Header("WwW-AuThEnTiCaTe", challenge)); AuthScheme authscheme = new NTLMScheme(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); } @@ -636,7 +694,7 @@ state.setCredentials(null, null, cred); HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); AuthScheme authscheme = new NTLMScheme(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); assertEquals(expected, method.getRequestHeader("Authorization").getValue()); @@ -659,7 +717,7 @@ state.setCredentials(null, null, cred); HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); AuthScheme authscheme = new NTLMScheme(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); assertEquals(expected, method.getRequestHeader("Authorization").getValue()); @@ -682,7 +740,7 @@ HttpMethod method = new SimpleHttpMethod(new Header("WWW-Authenticate", challenge)); method.addRequestHeader("Host", "host"); AuthScheme authscheme = new NTLMScheme(challenge); - assertTrue(HttpAuthenticator.authenticate(authscheme, method, null, state)); + assertTrue(authenticate(authscheme, method, null, state)); assertTrue(null != method.getRequestHeader("Authorization")); assertEquals(expected, method.getRequestHeader("Authorization").getValue()); Index: test/org/apache/commons/httpclient/server/ProxyAuthRequestHandler.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/server/ProxyAuthRequestHandler.java,v retrieving revision 1.5 diff -u -r1.5 ProxyAuthRequestHandler.java --- test/org/apache/commons/httpclient/server/ProxyAuthRequestHandler.java 6 Jan 2004 20:08:56 -0000 1.5 +++ test/org/apache/commons/httpclient/server/ProxyAuthRequestHandler.java 12 Jan 2004 12:37:08 -0000 @@ -69,7 +69,6 @@ import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.auth.AuthenticationException; import org.apache.commons.httpclient.auth.BasicScheme; -import org.apache.commons.httpclient.auth.HttpAuthenticator; import org.apache.commons.httpclient.auth.MalformedChallengeException; /** @@ -83,6 +82,16 @@ private Credentials credentials; /** + * The proxy authenticate challange header. + */ + public static final String PROXY_AUTH = "Proxy-Authenticate"; + + /** + * The proxy authenticate response header. + */ + public static final String PROXY_AUTH_RESP = "Proxy-Authorization"; + + /** * TODO replace creds parameter with a class specific to an auth scheme * encapsulating all required information for a specific scheme * @@ -96,7 +105,7 @@ public boolean processRequest(SimpleHttpServerConnection conn) throws IOException { Header[] headers = conn.getHeaders(); - Header clientAuth = findHeader(headers, HttpAuthenticator.PROXY_AUTH_RESP); + Header clientAuth = findHeader(headers, PROXY_AUTH_RESP); if (clientAuth != null) { boolean ok = checkAuthorization(clientAuth); if (ok) @@ -128,7 +137,7 @@ */ private Header createChallenge() { Header header = new Header(); - header.setName(HttpAuthenticator.PROXY_AUTH); + header.setName(PROXY_AUTH); //TODO add more auth schemes String challenge = "basic realm=test"; header.setValue(challenge);