Index: examples/BasicAuthenticationExample.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/examples/BasicAuthenticationExample.java,v retrieving revision 1.1 diff -u -r1.1 BasicAuthenticationExample.java --- examples/BasicAuthenticationExample.java 13 Aug 2003 20:30:40 -0000 1.1 +++ examples/BasicAuthenticationExample.java 30 Jan 2004 19:43:35 -0000 @@ -59,7 +59,8 @@ * [Additional notices, if required by prior licensing conditions] * */ - import org.apache.commons.httpclient.HttpClient; + +import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.methods.GetMethod; @@ -77,6 +78,7 @@ * Constructor for BasicAuthenticatonExample. */ public BasicAuthenticationExample() { + super(); } public static void main(String[] args) throws Exception { @@ -103,13 +105,16 @@ // It will then be up to the client to handle the authentication. get.setDoAuthentication( true ); - // execute the GET - int status = client.executeMethod( get ); - - // print the status and response - System.out.println(status + "\n" + get.getResponseBodyAsString()); - - // release any connection resources used by the method - get.releaseConnection(); + try { + // execute the GET + int status = client.executeMethod( get ); + + // print the status and response + System.out.println(status + "\n" + get.getResponseBodyAsString()); + + } finally { + // release any connection resources used by the method + get.releaseConnection(); + } } } Index: examples/InteractiveAuthenticationExample.java =================================================================== RCS file: examples/InteractiveAuthenticationExample.java diff -N examples/InteractiveAuthenticationExample.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ examples/InteractiveAuthenticationExample.java 30 Jan 2004 19:43:35 -0000 @@ -0,0 +1,168 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NTCredentials; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScheme; +import org.apache.commons.httpclient.auth.CredentialsProvider; +import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; +import org.apache.commons.httpclient.auth.NTLMScheme; +import org.apache.commons.httpclient.auth.RFC2617Scheme; +import org.apache.commons.httpclient.methods.GetMethod; + +/** + * A simple example that uses HttpClient to perform interactive + * authentication. + * + * @author Oleg Kalnichevski + */ +public class InteractiveAuthenticationExample { + + /** + * Constructor for InteractiveAuthenticationExample. + */ + public InteractiveAuthenticationExample() { + super(); + } + + public static void main(String[] args) throws Exception { + + InteractiveAuthenticationExample demo = new InteractiveAuthenticationExample(); + demo.doDemo(); + } + + private void doDemo() throws IOException { + + HttpClient client = new HttpClient(); + client.getParams().setParameter( + CredentialsProvider.PROVIDER, new ConsoleAuthPrompter()); + GetMethod httpget = new GetMethod("http://target-host/requires-auth.html"); + httpget.setDoAuthentication(true); + try { + // execute the GET + int status = client.executeMethod(httpget); + // print the status and response + System.out.println(httpget.getStatusLine().toString()); + System.out.println(httpget.getResponseBodyAsString()); + } finally { + // release any connection resources used by the method + httpget.releaseConnection(); + } + } + + public class ConsoleAuthPrompter implements CredentialsProvider { + + private BufferedReader in = null; + public ConsoleAuthPrompter() { + super(); + this.in = new BufferedReader(new InputStreamReader(System.in)); + } + + private String readConsole() throws IOException { + return this.in.readLine(); + } + + public Credentials getCredentials( + final AuthScheme authscheme, + final String host, + int port, + boolean proxy) + throws CredentialsNotAvailableException + { + if (authscheme == null) { + return null; + } + try{ + if (authscheme instanceof NTLMScheme) { + System.out.println(host + ":" + port + " requires Windows authentication"); + System.out.print("Enter domain: "); + String domain = readConsole(); + System.out.print("Enter username: "); + String user = readConsole(); + System.out.print("Enter password: "); + String password = readConsole(); + return new NTCredentials(user, password, host, domain); + } else + if (authscheme instanceof RFC2617Scheme) { + System.out.println(host + ":" + port + " requires authentication with the realm '" + + authscheme.getRealm() + "'"); + System.out.print("Enter username: "); + String user = readConsole(); + System.out.print("Enter password: "); + String password = readConsole(); + return new UsernamePasswordCredentials(user, password); + } else { + throw new CredentialsNotAvailableException("Unsupported authentication scheme: " + + authscheme.getSchemeName()); + } + } catch (IOException e) { + throw new CredentialsNotAvailableException(e.getMessage(), e); + } + } + } +} 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.15 diff -u -r1.15 HttpMethodDirector.java --- java/org/apache/commons/httpclient/HttpMethodDirector.java 28 Jan 2004 21:39:16 -0000 1.15 +++ java/org/apache/commons/httpclient/HttpMethodDirector.java 30 Jan 2004 19:43:36 -0000 @@ -72,6 +72,9 @@ 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.CredentialsProvider; +import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; +import org.apache.commons.httpclient.auth.HttpAuthRealm; import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.httpclient.params.HttpParams; @@ -278,22 +281,15 @@ if (host == null) { host = conn.getHost(); } - String realm = this.authScheme.getRealm(); + int port = conn.getPort(); + HttpAuthRealm realm = new HttpAuthRealm( + host, port, + this.authScheme.getRealm(), + this.authScheme.getSchemeName()); 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()); + LOG.debug("Authenticating with " + realm); } - Credentials credentials = this.state.getCredentials(realm, host); + Credentials credentials = this.state.getCredentials(realm); if (credentials != null) { String authstring = this.authScheme.authenticate(credentials, method); if (authstring != null) { @@ -313,23 +309,14 @@ && ((this.authState == AUTH_PROXY_REQUIRED) || (!this.proxyAuthScheme.isConnectionBased()))) { - String host = conn.getProxyHost(); - String realm = this.proxyAuthScheme.getRealm(); + HttpAuthRealm realm = new HttpAuthRealm( + conn.getProxyHost(), conn.getProxyPort(), + this.proxyAuthScheme.getRealm(), + this.proxyAuthScheme.getSchemeName()); 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()); + LOG.debug("Authenticating with " + realm); } - Credentials credentials = this.state.getProxyCredentials(realm, host); + Credentials credentials = this.state.getProxyCredentials(realm); if (credentials != null) { String authstring = this.proxyAuthScheme.authenticate(credentials, method); if (authstring != null) { @@ -633,45 +620,38 @@ if (this.authScheme == null) { return false; } + String host = conn.getVirtualHost(); + if (host == null) { + host = conn.getHost(); + } + int port = conn.getPort(); + HttpAuthRealm realm = new HttpAuthRealm( + host, port, + this.authScheme.getRealm(), + this.authScheme.getSchemeName()); + 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()); + Credentials credentials = promptForCredentials(method.getParams(), realm); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("Failure authenticating with " + realm); + } + return false; + } else { + return true; } - return false; } else { this.authState = AUTH_WWW_REQUIRED; - String host = conn.getVirtualHost(); - if (host == null) { - host = conn.getHost(); + Credentials credentials = this.state.getCredentials(realm); + if (credentials == null) { + credentials = promptForCredentials(method.getParams(), realm); } - 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); + LOG.info("No credentials available for the " + realm); } return false; } else { @@ -700,38 +680,33 @@ if (this.proxyAuthScheme == null) { return false; } + HttpAuthRealm realm = new HttpAuthRealm( + conn.getProxyHost(), conn.getProxyPort(), + this.proxyAuthScheme.getRealm(), + this.proxyAuthScheme.getSchemeName()); + 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()); + Credentials credentials = promptForProxyCredentials(method.getParams(), realm); + if (credentials == null) { + if (LOG.isInfoEnabled()) { + LOG.info("Failure authenticating with " + realm); + } + return false; + } else { + return true; } - return false; } else { this.authState = AUTH_PROXY_REQUIRED; - String host = conn.getProxyHost(); - String realm = this.proxyAuthScheme.getRealm(); - Credentials credentials = this.state.getProxyCredentials(realm, host); + Credentials credentials = this.state.getProxyCredentials(realm); + if (credentials == null) { + credentials = promptForProxyCredentials(method.getParams(), realm); + } 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); + LOG.info("No proxy credentials available for the " + realm); } return false; } else { @@ -853,6 +828,54 @@ default: return false; } //end of switch + } + + private Credentials promptForCredentials( + final HttpParams params, + final HttpAuthRealm realm) + { + Credentials creds = null; + CredentialsProvider credProvider = + (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER); + if (credProvider != null) { + try { + creds = credProvider.getCredentials( + this.authScheme, realm.getHost(), realm.getPort(), false); + } catch (CredentialsNotAvailableException e) { + LOG.warn(e.getMessage()); + } + if (creds != null) { + this.state.setCredentials(realm, creds); + if (LOG.isDebugEnabled()) { + LOG.debug("New credentials for " + realm); + } + } + } + return creds; + } + + private Credentials promptForProxyCredentials( + final HttpParams params, + final HttpAuthRealm realm) + { + Credentials creds = null; + CredentialsProvider credProvider = + (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER); + if (credProvider != null) { + try { + creds = credProvider.getCredentials( + this.proxyAuthScheme, realm.getHost(), realm.getPort(), true); + } catch (CredentialsNotAvailableException e) { + LOG.warn(e.getMessage()); + } + if (creds != null) { + this.state.setProxyCredentials(realm, creds); + if (LOG.isDebugEnabled()) { + LOG.debug("New proxy credentials for " + realm); + } + } + } + return creds; } /** 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.29 diff -u -r1.29 HttpState.java --- java/org/apache/commons/httpclient/HttpState.java 29 Oct 2003 03:12:27 -0000 1.29 +++ java/org/apache/commons/httpclient/HttpState.java 30 Jan 2004 19:43:36 -0000 @@ -116,11 +116,6 @@ private HashMap proxyCred = new HashMap(); /** - * The default authentication realm. - */ - public static final HttpAuthRealm DEFAULT_AUTH_REALM = new HttpAuthRealm(null, null); - - /** * Array of {@link Cookie cookies} that this HTTP state contains. */ private ArrayList cookies = new ArrayList(); @@ -364,42 +359,55 @@ */ public synchronized void setCredentials(String realm, String host, Credentials credentials) { - LOG.trace( - "enter HttpState.setCredentials(String realm, String host, Credentials credentials)"); + LOG.trace("enter HttpState.setCredentials(String, String, Credentials)"); credMap.put(new HttpAuthRealm(host, realm), credentials); } + /** + * Sets the {@link Credentials credentials} for the given authentication + * realm. Any previous credentials for the given realm will be overwritten. + * + * @param realm the {@link HttpAuthRealm authentication realm} + * @param credentials the authentication {@link Credentials credentials} + * for the given realm. + * + * @see #getCredentials(HttpAuthRealm) + * @see #setProxyCredentials(HttpAuthRealm, Credentials) + */ + public synchronized void setCredentials(final HttpAuthRealm realm, Credentials credentials) { + if (realm == null) { + throw new IllegalArgumentException("Authentication realm token may not be null"); + } + LOG.trace("enter HttpState.setCredentials(HttpAuthRealm, Credentials)"); + credMap.put(realm, credentials); + } /** - * Find matching {@link Credentials credentials} for the given authentication realm and 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. + * Find matching {@link Credentials credentials} for the given authentication realm. * * @param map the credentials hash map - * @param realm the authentication realm - * @param host the host the realm is on + * @param token the {@link HttpAuthRealm authentication realm token} * @return the credentials * */ - private static Credentials matchCredentials(HashMap map, String realm, String host) { - HttpAuthRealm entry = new HttpAuthRealm(host, realm); - Credentials creds = (Credentials) map.get(entry); - if (creds == null && host != null && realm != null) { - entry = new HttpAuthRealm(host, null); - creds = (Credentials) map.get(entry); - if (creds == null) { - entry = new HttpAuthRealm(null, realm); - creds = (Credentials) map.get(entry); - } + private static Credentials matchCredentials(HashMap map, HttpAuthRealm token) { + HttpAuthRealm key = token; + Credentials creds = (Credentials) map.get(key); + if (creds == null && token.getScheme() != null) { + key = new HttpAuthRealm(token.getHost(), token.getPort(), token.getRealm()); + creds = (Credentials) map.get(key); + } + if (creds == null && token.getRealm() != null) { + key = new HttpAuthRealm(token.getHost(), token.getPort()); + creds = (Credentials) map.get(key); } - if (creds == null) { - creds = (Credentials) map.get(DEFAULT_AUTH_REALM); + if (creds == null && token.getPort() >= 0) { + key = new HttpAuthRealm(token.getHost(), -1); + creds = (Credentials) map.get(key); + } + if (creds == null && token.getHost() != null) { + key = new HttpAuthRealm(); + creds = (Credentials) map.get(key); } return creds; } @@ -425,7 +433,24 @@ public synchronized Credentials getCredentials(String realm, String host) { LOG.trace("enter HttpState.getCredentials(String, String"); - return matchCredentials(this.credMap, realm, host); + return matchCredentials(this.credMap, new HttpAuthRealm(realm, host)); + } + + /** + * Get the {@link Credentials credentials} for the given authentication realm. + * + * @param realm the {@link HttpAuthRealm authentication realm} + * @return the credentials + * + * @see #setCredentials(HttpAuthRealm, Credentials) + */ + + public synchronized Credentials getCredentials(HttpAuthRealm realm) { + if (realm == null) { + throw new IllegalArgumentException("Authentication realm token may not be null"); + } + LOG.trace("enter HttpState.getCredentials(HttpAuthRealm)"); + return matchCredentials(this.credMap, realm); } /** @@ -445,7 +470,6 @@ * * @see #getProxyCredentials(String,String) * @see #setCredentials(String, String, Credentials) - * */ public synchronized void setProxyCredentials( String realm, @@ -456,6 +480,27 @@ proxyCred.put(new HttpAuthRealm(proxyHost, realm), credentials); } + /** + * Sets the {@link Credentials credentials} for the given proxy authentication + * realm. Any previous credentials for the given realm will be overwritten. + * + * @param realm the {@link HttpAuthRealm authentication realm} + * @param credentials the authentication {@link Credentials credentials} + * for the given realm. + * + * @see #getProxyCredentials(HttpAuthRealm) + * @see #setCredentials(HttpAuthRealm, Credentials) + */ + public synchronized void setProxyCredentials(final HttpAuthRealm realm, + Credentials credentials) + { + if (realm == null) { + throw new IllegalArgumentException("Authentication realm token may not be null"); + } + LOG.trace("enter HttpState.setProxyCredentials(HttpAuthRealm, Credentials)"); + proxyCred.put(realm, credentials); + } + /** * Get the {@link Credentials credentials} for the proxy host with the given * authentication realm. @@ -475,10 +520,26 @@ */ public synchronized Credentials getProxyCredentials(String realm, String proxyHost) { LOG.trace("enter HttpState.getCredentials(String, String"); - return matchCredentials(this.proxyCred, realm, proxyHost); + return matchCredentials(this.proxyCred, new HttpAuthRealm(realm, proxyHost)); } /** + * Get the {@link Credentials credentials} for the given proxy authentication realm. + * + * @param realm the {@link HttpAuthRealm authentication realm} + * @return the credentials + * + * @see #setProxyCredentials(HttpAuthRealm, Credentials) + */ + public synchronized Credentials getProxyCredentials(HttpAuthRealm realm) { + if (realm == null) { + throw new IllegalArgumentException("Authentication realm token may not be null"); + } + LOG.trace("enter HttpState.getProxyCredentials(HttpAuthRealm)"); + return matchCredentials(this.proxyCred, realm); + } + + /** * Returns a string representation of this HTTP state. * * @return The string representation of the HTTP state. @@ -489,37 +550,16 @@ StringBuffer sbResult = new StringBuffer(); sbResult.append("["); - sbResult.append(getProxyCredentialsStringRepresentation(proxyCred)); - sbResult.append(" | "); sbResult.append(getCredentialsStringRepresentation(proxyCred)); sbResult.append(" | "); + sbResult.append(getCredentialsStringRepresentation(credMap)); + sbResult.append(" | "); sbResult.append(getCookiesStringRepresentation(cookies)); sbResult.append("]"); String strResult = sbResult.toString(); return strResult; - } - - /** - * Returns a string representation of the proxy credentials - * @param proxyCredMap The proxy credentials - * @return The string representation. - */ - private static String getProxyCredentialsStringRepresentation(final Map proxyCredMap) { - StringBuffer sbResult = new StringBuffer(); - Iterator iter = proxyCredMap.keySet().iterator(); - while (iter.hasNext()) { - Object key = iter.next(); - Credentials cred = (Credentials) proxyCredMap.get(key); - if (sbResult.length() > 0) { - sbResult.append(", "); - } - sbResult.append(key); - sbResult.append("#"); - sbResult.append(cred.toString()); - } - return sbResult.toString(); } /** Index: java/org/apache/commons/httpclient/auth/CredentialsProvider.java =================================================================== RCS file: java/org/apache/commons/httpclient/auth/CredentialsProvider.java diff -N java/org/apache/commons/httpclient/auth/CredentialsProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/org/apache/commons/httpclient/auth/CredentialsProvider.java 30 Jan 2004 19:43:37 -0000 @@ -0,0 +1,78 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ + +package org.apache.commons.httpclient.auth; + +import org.apache.commons.httpclient.Credentials; + +public interface CredentialsProvider { + + public static final String PROVIDER = "http.authentication.credential-provider"; + + public Credentials getCredentials( + final AuthScheme scheme, + final String host, + int port, + boolean proxy) throws CredentialsNotAvailableException; + +} Index: java/org/apache/commons/httpclient/auth/HttpAuthRealm.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/HttpAuthRealm.java,v retrieving revision 1.4 diff -u -r1.4 HttpAuthRealm.java --- java/org/apache/commons/httpclient/auth/HttpAuthRealm.java 14 Dec 2003 22:39:04 -0000 1.4 +++ java/org/apache/commons/httpclient/auth/HttpAuthRealm.java 30 Jan 2004 19:43:37 -0000 @@ -70,50 +70,167 @@ */ public class HttpAuthRealm { + /** The authentication scheme the credentials apply to. */ + private String scheme = null; + /** The realm the credentials apply to. */ private String realm = null; - /** The domain the credentials apply to. */ - private String domain = null; + /** The host the credentials apply to. */ + private String host = null; + + /** The port the credentials apply to. */ + private int port = -1; - /** Creates a new HttpAuthRealm for the given domain and - * realm. + /** Creates a new authentication realm token for the given + * host, port, realm, and + * authentication scheme. * - * @param domain the domain the credentials apply to. May be set + * @param host the host the credentials apply to. May be set * to null if credenticals are applicable to - * any domain. + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. * @param realm the realm the credentials apply to. May be set * to null if credenticals are applicable to * any realm. - * + * @param scheme the authentication scheme the credentials apply to. + * May be set to null if credenticals are applicable to + * any authentication scheme. */ - public HttpAuthRealm(final String domain, final String realm) { - this.domain = domain; + public HttpAuthRealm(final String host, int port, + final String realm, final String scheme) + { + this.host = host; + this.port = port; this.realm = realm; + this.scheme = scheme; + } + + /** Creates a new authentication realm token for the given + * host, port, realm, and any + * authentication scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. + * @param realm the realm the credentials apply to. May be set + * to null if credenticals are applicable to + * any realm. + */ + public HttpAuthRealm(final String host, int port, final String realm) { + this(host, port, realm, null); + } + + /** Creates a new authentication realm token for the given + * host, port, any realm name, and any + * authentication scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param port the port the credentials apply to. May be set + * to negative value if credenticals are applicable to + * any port. + */ + public HttpAuthRealm(final String host, int port) { + this(host, port, null, null); + } + + /** Creates a new authentication realm token for the given + * host, realm, any port, and any authentication + * scheme. + * + * @param host the host the credentials apply to. May be set + * to null if credenticals are applicable to + * any host. + * @param realm the realm the credentials apply to. May be set + * to null if credenticals are applicable to + * any realm. + */ + public HttpAuthRealm(final String host, final String realm) { + this(host, -1, realm, null); + } + + /** + * Creates a new authentication realm token that matches any + * authentication realm. + */ + public HttpAuthRealm() { + this(null, -1, null, null); + } + + /** + * Creates a copy of the given authentication realm token. + */ + public HttpAuthRealm(final HttpAuthRealm token) { + this(token.host, token.port, token.realm, token.scheme); } - /** Determines if the given domains match. Note that null acts as a - * wildcard so if either of the domains are null, it is considered a match. + /** + * @return the host + */ + public String getHost() { + return this.host; + } + + /** + * @return the port + */ + public int getPort() { + return this.port; + } + + /** + * @return the realm name + */ + public String getRealm() { + return this.realm; + } + + /** + * @return the scheme type + */ + public String getScheme() { + return this.scheme; + } + + /** Determines if the given parameters match. Note that null acts as a + * wildcard so if either of the parameters are null, it is considered a match. * - * @param d1 the domain - * @param d2 the other domain - * @return boolean true if the domains match, otherwise false. - */ - private static boolean domainAttribMatch(final String d1, final String d2) { - return d1 == null || d2 == null || d1.equalsIgnoreCase(d2); - } - - /** Determines if the given realms match. Note that null acts as a - * wildcard so if either realm is null, this function will return true. - * - * @param r1 the realm - * @param r2 the other realm - * @return boolean true if the realms match, otherwise false. - */ - private static boolean realmAttribMatch(final String r1, final String r2) { - return r1 == null || r2 == null || r1.equals(r2); + * @param p1 the parameter + * @param p2 the other parameter + * @return boolean true if the parameters match, otherwise false. + */ + private static boolean paramsMatchIgnoreCase(final String p1, final String p2) { + return p1 == null || p2 == null || p1.equalsIgnoreCase(p2); } + /** Determines if the given parameters match. Note that null acts as a + * wildcard so if either of the parameters are null, it is considered a match. + * + * @param p1 the parameter + * @param p2 the other parameter + * @return boolean true if the parameters match, otherwise false. + */ + private static boolean paramsMatch(final String p1, final String p2) { + return p1 == null || p2 == null || p1.equals(p2); + } + + /** Determines if the given parameters match. Note that negative value acts as a + * wildcard so if either of the parameters are negative, it is considered a match. + * + * @param p1 the parameter + * @param p2 the other parameter + * @return boolean true if the parameters match, otherwise false. + */ + private static boolean paramsMatch(int p1, int p2) { + return p1 < 0 || p2 < 0 || p1 == p2; + } /** * @see java.lang.Object#equals(Object) @@ -130,8 +247,10 @@ } HttpAuthRealm that = (HttpAuthRealm) o; return - domainAttribMatch(this.domain, that.domain) - && realmAttribMatch(this.realm, that.realm); + paramsMatchIgnoreCase(this.host, that.host) + && paramsMatch(this.port, that.port) + && paramsMatch(this.realm, that.realm) + && paramsMatchIgnoreCase(this.scheme, that.scheme); } /** @@ -139,21 +258,34 @@ */ public String toString() { StringBuffer buffer = new StringBuffer(); - buffer.append("Authentication domain: '"); - buffer.append(this.domain); - buffer.append("', authentication realm: '"); - buffer.append(this.realm); - buffer.append("'"); + if (this.scheme != null) { + buffer.append(this.scheme); + buffer.append(' '); + } + if (this.realm != null) { + buffer.append("authentication realm '"); + buffer.append(this.realm); + buffer.append("'"); + } else { + buffer.append("default authentication realm "); + } + if (this.host != null) { + buffer.append('@'); + buffer.append(this.host); + if (this.port >= 0) { + buffer.append(':'); + buffer.append(this.port); + } + } return buffer.toString(); } /** * @see java.lang.Object#hashCode() */ public int hashCode() { - StringBuffer buffer = new StringBuffer(); - buffer.append(this.domain); - buffer.append(this.realm); - return buffer.toString().hashCode(); + return ((this.host != null) ? this.host.toLowerCase().hashCode() : 0) + + ((this.port >= 0) ? this.port : -1) + + ((this.realm != null) ? this.realm.hashCode() : 0) + + ((this.scheme != null) ? this.scheme.toLowerCase().hashCode() : 0); } - } 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.17 diff -u -r1.17 NTLMScheme.java --- java/org/apache/commons/httpclient/auth/NTLMScheme.java 21 Jan 2004 21:10:44 -0000 1.17 +++ java/org/apache/commons/httpclient/auth/NTLMScheme.java 30 Jan 2004 19:43:37 -0000 @@ -356,7 +356,7 @@ } NTLM ntlm = new NTLM(); String response = null; - if (this.state == INITIATED) { + if (this.state == INITIATED || this.state == FAILED) { response = ntlm.getType1Message( ntcredentials.getHost(), ntcredentials.getDomain());