summaryrefslogtreecommitdiffstats
path: root/src/org/apache/http/impl/auth
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/apache/http/impl/auth')
-rw-r--r--src/org/apache/http/impl/auth/AuthSchemeBase.java128
-rw-r--r--src/org/apache/http/impl/auth/BasicScheme.java185
-rw-r--r--src/org/apache/http/impl/auth/BasicSchemeFactory.java50
-rw-r--r--src/org/apache/http/impl/auth/DigestScheme.java484
-rw-r--r--src/org/apache/http/impl/auth/DigestSchemeFactory.java50
-rw-r--r--src/org/apache/http/impl/auth/NTLMEngine.java76
-rw-r--r--src/org/apache/http/impl/auth/NTLMEngineException.java70
-rw-r--r--src/org/apache/http/impl/auth/NTLMScheme.java149
-rw-r--r--src/org/apache/http/impl/auth/RFC2617Scheme.java119
-rw-r--r--src/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java71
-rw-r--r--src/org/apache/http/impl/auth/package.html4
11 files changed, 1386 insertions, 0 deletions
diff --git a/src/org/apache/http/impl/auth/AuthSchemeBase.java b/src/org/apache/http/impl/auth/AuthSchemeBase.java
new file mode 100644
index 0000000..689ce5d
--- /dev/null
+++ b/src/org/apache/http/impl/auth/AuthSchemeBase.java
@@ -0,0 +1,128 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/AuthSchemeBase.java $
+ * $Revision: 653867 $
+ * $Date: 2008-05-06 11:17:29 -0700 (Tue, 06 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.FormattedHeader;
+import org.apache.http.Header;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.util.CharArrayBuffer;
+
+/**
+ * Abstract authentication scheme class that serves as a basis
+ * for all authentication schemes supported by HttpClient. This class
+ * defines the generic way of parsing an authentication challenge. It
+ * does not make any assumptions regarding the format of the challenge
+ * nor does it impose any specific way of responding to that challenge.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+*/
+public abstract class AuthSchemeBase implements AuthScheme {
+
+ /**
+ * Flag whether authenticating against a proxy.
+ */
+ private boolean proxy;
+
+ public AuthSchemeBase() {
+ super();
+ }
+
+ /**
+ * Processes the given challenge token. Some authentication schemes
+ * may involve multiple challenge-response exchanges. Such schemes must be able
+ * to maintain the state information when dealing with sequential challenges
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ public void processChallenge(final Header header) throws MalformedChallengeException {
+ if (header == null) {
+ throw new IllegalArgumentException("Header may not be null");
+ }
+ String authheader = header.getName();
+ if (authheader.equalsIgnoreCase(AUTH.WWW_AUTH)) {
+ this.proxy = false;
+ } else if (authheader.equalsIgnoreCase(AUTH.PROXY_AUTH)) {
+ this.proxy = true;
+ } else {
+ throw new MalformedChallengeException("Unexpected header name: " + authheader);
+ }
+
+ CharArrayBuffer buffer;
+ int pos;
+ if (header instanceof FormattedHeader) {
+ buffer = ((FormattedHeader) header).getBuffer();
+ pos = ((FormattedHeader) header).getValuePos();
+ } else {
+ String s = header.getValue();
+ if (s == null) {
+ throw new MalformedChallengeException("Header value is null");
+ }
+ buffer = new CharArrayBuffer(s.length());
+ buffer.append(s);
+ pos = 0;
+ }
+ while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ int beginIndex = pos;
+ while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+ pos++;
+ }
+ int endIndex = pos;
+ String s = buffer.substring(beginIndex, endIndex);
+ if (!s.equalsIgnoreCase(getSchemeName())) {
+ throw new MalformedChallengeException("Invalid scheme identifier: " + s);
+ }
+
+ parseChallenge(buffer, pos, buffer.length());
+ }
+
+ protected abstract void parseChallenge(
+ CharArrayBuffer buffer, int pos, int len) throws MalformedChallengeException;
+
+ /**
+ * Returns <code>true</code> if authenticating against a proxy, <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if authenticating against a proxy, <code>false</code>
+ * otherwise
+ */
+ public boolean isProxy() {
+ return this.proxy;
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/BasicScheme.java b/src/org/apache/http/impl/auth/BasicScheme.java
new file mode 100644
index 0000000..88ea110
--- /dev/null
+++ b/src/org/apache/http/impl/auth/BasicScheme.java
@@ -0,0 +1,185 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/BasicScheme.java $
+ * $Revision: 658430 $
+ * $Date: 2008-05-20 14:04:27 -0700 (Tue, 20 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.params.AuthParams;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.util.CharArrayBuffer;
+import org.apache.http.util.EncodingUtils;
+
+/**
+ * <p>
+ * Basic authentication scheme as defined in RFC 2617.
+ * </p>
+ *
+ * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
+ * @author Rodney Waldhoff
+ * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
+ * @author Ortwin Glueck
+ * @author Sean C. Sullivan
+ * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
+ * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+
+public class BasicScheme extends RFC2617Scheme {
+
+ /** Whether the basic authentication process is complete */
+ private boolean complete;
+
+ /**
+ * Default constructor for the basic authetication scheme.
+ */
+ public BasicScheme() {
+ super();
+ this.complete = false;
+ }
+
+ /**
+ * Returns textual designation of the basic authentication scheme.
+ *
+ * @return <code>basic</code>
+ */
+ public String getSchemeName() {
+ return "basic";
+ }
+
+ /**
+ * Processes the Basic challenge.
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ @Override
+ public void processChallenge(
+ final Header header) throws MalformedChallengeException {
+ super.processChallenge(header);
+ this.complete = true;
+ }
+
+ /**
+ * Tests if the Basic authentication process has been completed.
+ *
+ * @return <tt>true</tt> if Basic authorization has been processed,
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+ /**
+ * Returns <tt>false</tt>. Basic authentication scheme is request based.
+ *
+ * @return <tt>false</tt>.
+ */
+ public boolean isConnectionBased() {
+ return false;
+ }
+
+ /**
+ * Produces basic authorization header for the given set of {@link Credentials}.
+ *
+ * @param credentials The set of credentials to be used for athentication
+ * @param request The request being authenticated
+ * @throws org.apache.http.auth.InvalidCredentialsException if authentication credentials
+ * are not valid or not applicable for this authentication scheme
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return a basic authorization string
+ */
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+
+ if (credentials == null) {
+ throw new IllegalArgumentException("Credentials may not be null");
+ }
+ if (request == null) {
+ throw new IllegalArgumentException("HTTP request may not be null");
+ }
+
+ String charset = AuthParams.getCredentialCharset(request.getParams());
+ return authenticate(credentials, charset, isProxy());
+ }
+
+ /**
+ * Returns a basic <tt>Authorization</tt> header value for the given
+ * {@link Credentials} and charset.
+ *
+ * @param credentials The credentials to encode.
+ * @param charset The charset to use for encoding the credentials
+ *
+ * @return a basic authorization header
+ */
+ public static Header authenticate(
+ final Credentials credentials,
+ final String charset,
+ boolean proxy) {
+ if (credentials == null) {
+ throw new IllegalArgumentException("Credentials may not be null");
+ }
+ if (charset == null) {
+ throw new IllegalArgumentException("charset may not be null");
+ }
+
+ StringBuilder tmp = new StringBuilder();
+ tmp.append(credentials.getUserPrincipal().getName());
+ tmp.append(":");
+ tmp.append((credentials.getPassword() == null) ? "null" : credentials.getPassword());
+
+ byte[] base64password = Base64.encodeBase64(
+ EncodingUtils.getBytes(tmp.toString(), charset));
+
+ CharArrayBuffer buffer = new CharArrayBuffer(32);
+ if (proxy) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": Basic ");
+ buffer.append(base64password, 0, base64password.length);
+
+ return new BufferedHeader(buffer);
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/BasicSchemeFactory.java b/src/org/apache/http/impl/auth/BasicSchemeFactory.java
new file mode 100644
index 0000000..c5d28b0
--- /dev/null
+++ b/src/org/apache/http/impl/auth/BasicSchemeFactory.java
@@ -0,0 +1,50 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/BasicSchemeFactory.java $
+ * $Revision: 534839 $
+ * $Date: 2007-05-03 06:03:41 -0700 (Thu, 03 May 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthSchemeFactory;
+import org.apache.http.params.HttpParams;
+
+/**
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+public class BasicSchemeFactory implements AuthSchemeFactory {
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new BasicScheme();
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/DigestScheme.java b/src/org/apache/http/impl/auth/DigestScheme.java
new file mode 100644
index 0000000..803807b
--- /dev/null
+++ b/src/org/apache/http/impl/auth/DigestScheme.java
@@ -0,0 +1,484 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/DigestScheme.java $
+ * $Revision: 659595 $
+ * $Date: 2008-05-23 09:47:14 -0700 (Fri, 23 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.params.AuthParams;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.message.BasicHeaderValueFormatter;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.util.CharArrayBuffer;
+import org.apache.http.util.EncodingUtils;
+
+/**
+ * <p>
+ * Digest authentication scheme as defined in RFC 2617.
+ * Both MD5 (default) and MD5-sess are supported.
+ * Currently only qop=auth or no qop is supported. qop=auth-int
+ * is unsupported. If auth and auth-int are provided, auth is
+ * used.
+ * </p>
+ * <p>
+ * Credential charset is configured via the
+ * {@link org.apache.http.auth.params.AuthPNames#CREDENTIAL_CHARSET
+ * credential charset} parameter.
+ * Since the digest username is included as clear text in the generated
+ * Authentication header, the charset of the username must be compatible
+ * with the
+ * {@link org.apache.http.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET
+ * http element charset}.
+ * </p>
+ *
+ * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
+ * @author Rodney Waldhoff
+ * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
+ * @author Ortwin Glueck
+ * @author Sean C. Sullivan
+ * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
+ * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+
+public class DigestScheme extends RFC2617Scheme {
+
+ /**
+ * Hexa values used when creating 32 character long digest in HTTP DigestScheme
+ * in case of authentication.
+ *
+ * @see #encode(byte[])
+ */
+ private static final char[] HEXADECIMAL = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+ '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;
+ private static final int QOP_AUTH_INT = 1;
+ private static final int QOP_AUTH = 2;
+
+ private int qopVariant = QOP_MISSING;
+ private String cnonce;
+
+ /**
+ * Default constructor for the digest authetication scheme.
+ */
+ public DigestScheme() {
+ super();
+ this.complete = false;
+ }
+
+ /**
+ * Processes the Digest challenge.
+ *
+ * @param header the challenge header
+ *
+ * @throws MalformedChallengeException is thrown if the authentication challenge
+ * is malformed
+ */
+ @Override
+ public void processChallenge(
+ final Header header) throws MalformedChallengeException {
+ super.processChallenge(header);
+
+ if (getParameter("realm") == null) {
+ throw new MalformedChallengeException("missing realm in challange");
+ }
+ 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;
+ }
+ }
+ }
+
+ if (unsupportedQop && (qopVariant == QOP_MISSING)) {
+ throw new MalformedChallengeException("None of the qop methods is supported");
+ }
+ // Reset cnonce
+ this.cnonce = null;
+ this.complete = true;
+ }
+
+ /**
+ * Tests if the Digest authentication process has been completed.
+ *
+ * @return <tt>true</tt> if Digest authorization has been processed,
+ * <tt>false</tt> 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.
+ *
+ * @return <code>digest</code>
+ */
+ public String getSchemeName() {
+ return "digest";
+ }
+
+ /**
+ * Returns <tt>false</tt>. Digest authentication scheme is request based.
+ *
+ * @return <tt>false</tt>.
+ */
+ public boolean isConnectionBased() {
+ return false;
+ }
+
+ public void overrideParamter(final String name, final String value) {
+ getParameters().put(name, value);
+ }
+
+ private String getCnonce() {
+ if (this.cnonce == null) {
+ this.cnonce = createCnonce();
+ }
+ return this.cnonce;
+ }
+
+ /**
+ * Produces a digest authorization string for the given set of
+ * {@link Credentials}, method name and URI.
+ *
+ * @param credentials A set of credentials to be used for athentication
+ * @param request The request being authenticated
+ *
+ * @throws org.apache.http.auth.InvalidCredentialsException if authentication credentials
+ * are not valid or not applicable for this authentication scheme
+ * @throws AuthenticationException if authorization string cannot
+ * be generated due to an authentication failure
+ *
+ * @return a digest authorization string
+ */
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+
+ if (credentials == null) {
+ throw new IllegalArgumentException("Credentials may not be null");
+ }
+ if (request == null) {
+ throw new IllegalArgumentException("HTTP request may not be null");
+ }
+
+ // Add method name and request-URI to the parameter map
+ getParameters().put("methodname", request.getRequestLine().getMethod());
+ getParameters().put("uri", request.getRequestLine().getUri());
+ String charset = getParameter("charset");
+ if (charset == null) {
+ charset = AuthParams.getCredentialCharset(request.getParams());
+ getParameters().put("charset", charset);
+ }
+ String digest = createDigest(credentials);
+ return createDigestHeader(credentials, digest);
+ }
+
+ private static MessageDigest createMessageDigest(
+ final String digAlg) throws UnsupportedDigestAlgorithmException {
+ try {
+ return MessageDigest.getInstance(digAlg);
+ } catch (Exception e) {
+ throw new UnsupportedDigestAlgorithmException(
+ "Unsupported algorithm in HTTP Digest authentication: "
+ + digAlg);
+ }
+ }
+
+ /**
+ * Creates an MD5 response digest.
+ *
+ * @return The created digest as string. This will be the response tag's
+ * value in the Authentication HTTP header.
+ * @throws AuthenticationException when MD5 is an unsupported algorithm
+ */
+ private String createDigest(final Credentials credentials) throws AuthenticationException {
+ // Collecting required tokens
+ String uri = getParameter("uri");
+ String realm = getParameter("realm");
+ String nonce = getParameter("nonce");
+ String method = getParameter("methodname");
+ String algorithm = getParameter("algorithm");
+ if (uri == null) {
+ throw new IllegalStateException("URI may not be null");
+ }
+ if (realm == null) {
+ throw new IllegalStateException("Realm may not be null");
+ }
+ if (nonce == null) {
+ throw new IllegalStateException("Nonce may not be null");
+ }
+ // If an algorithm is not specified, default to MD5.
+ if (algorithm == null) {
+ algorithm = "MD5";
+ }
+ // If an charset is not specified, default to ISO-8859-1.
+ String charset = getParameter("charset");
+ if (charset == null) {
+ charset = "ISO-8859-1";
+ }
+
+ if (qopVariant == QOP_AUTH_INT) {
+ throw new AuthenticationException(
+ "Unsupported qop in HTTP Digest authentication");
+ }
+
+ MessageDigest md5Helper = createMessageDigest("MD5");
+
+ String uname = credentials.getUserPrincipal().getName();
+ String pwd = credentials.getPassword();
+
+ // 3.2.2.2: Calculating digest
+ StringBuilder tmp = new StringBuilder(uname.length() + realm.length() + pwd.length() + 2);
+ tmp.append(uname);
+ tmp.append(':');
+ tmp.append(realm);
+ tmp.append(':');
+ tmp.append(pwd);
+ // unq(username-value) ":" unq(realm-value) ":" passwd
+ String a1 = tmp.toString();
+
+ //a1 is suitable for MD5 algorithm
+ if(algorithm.equals("MD5-sess")) {
+ // H( unq(username-value) ":" unq(realm-value) ":" passwd )
+ // ":" unq(nonce-value)
+ // ":" unq(cnonce-value)
+
+ String cnonce = getCnonce();
+
+ String tmp2=encode(md5Helper.digest(EncodingUtils.getBytes(a1, charset)));
+ StringBuilder tmp3 = new StringBuilder(tmp2.length() + nonce.length() + cnonce.length() + 2);
+ tmp3.append(tmp2);
+ tmp3.append(':');
+ tmp3.append(nonce);
+ tmp3.append(':');
+ tmp3.append(cnonce);
+ a1 = tmp3.toString();
+ } else if (!algorithm.equals("MD5")) {
+ throw new AuthenticationException("Unhandled algorithm " + algorithm + " requested");
+ }
+ String md5a1 = encode(md5Helper.digest(EncodingUtils.getBytes(a1, charset)));
+
+ String a2 = null;
+ if (qopVariant == QOP_AUTH_INT) {
+ // Unhandled qop auth-int
+ //we do not have access to the entity-body or its hash
+ //TODO: add Method ":" digest-uri-value ":" H(entity-body)
+ } else {
+ a2 = method + ':' + uri;
+ }
+ String md5a2 = encode(md5Helper.digest(EncodingUtils.getAsciiBytes(a2)));
+
+ // 3.2.2.1
+ String serverDigestValue;
+ if (qopVariant == QOP_MISSING) {
+ StringBuilder tmp2 = new StringBuilder(md5a1.length() + nonce.length() + md5a2.length());
+ tmp2.append(md5a1);
+ tmp2.append(':');
+ tmp2.append(nonce);
+ tmp2.append(':');
+ tmp2.append(md5a2);
+ serverDigestValue = tmp2.toString();
+ } else {
+ String qopOption = getQopVariantString();
+ String cnonce = getCnonce();
+
+ StringBuilder tmp2 = new StringBuilder(md5a1.length() + nonce.length()
+ + NC.length() + cnonce.length() + qopOption.length() + md5a2.length() + 5);
+ tmp2.append(md5a1);
+ tmp2.append(':');
+ tmp2.append(nonce);
+ tmp2.append(':');
+ tmp2.append(NC);
+ tmp2.append(':');
+ tmp2.append(cnonce);
+ tmp2.append(':');
+ tmp2.append(qopOption);
+ tmp2.append(':');
+ tmp2.append(md5a2);
+ serverDigestValue = tmp2.toString();
+ }
+
+ String serverDigest =
+ encode(md5Helper.digest(EncodingUtils.getAsciiBytes(serverDigestValue)));
+
+ return serverDigest;
+ }
+
+ /**
+ * Creates digest-response header as defined in RFC2617.
+ *
+ * @param credentials User credentials
+ * @param digest The response tag's value as String.
+ *
+ * @return The digest-response as String.
+ */
+ private Header createDigestHeader(
+ final Credentials credentials,
+ final String digest) throws AuthenticationException {
+
+ CharArrayBuffer buffer = new CharArrayBuffer(128);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": Digest ");
+
+ String uri = getParameter("uri");
+ String realm = getParameter("realm");
+ String nonce = getParameter("nonce");
+ String opaque = getParameter("opaque");
+ String response = digest;
+ String algorithm = getParameter("algorithm");
+
+ String uname = credentials.getUserPrincipal().getName();
+
+ List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>(20);
+ params.add(new BasicNameValuePair("username", uname));
+ params.add(new BasicNameValuePair("realm", realm));
+ params.add(new BasicNameValuePair("nonce", nonce));
+ params.add(new BasicNameValuePair("uri", uri));
+ params.add(new BasicNameValuePair("response", response));
+
+ if (qopVariant != QOP_MISSING) {
+ params.add(new BasicNameValuePair("qop", getQopVariantString()));
+ params.add(new BasicNameValuePair("nc", NC));
+ params.add(new BasicNameValuePair("cnonce", getCnonce()));
+ }
+ if (algorithm != null) {
+ params.add(new BasicNameValuePair("algorithm", algorithm));
+ }
+ if (opaque != null) {
+ params.add(new BasicNameValuePair("opaque", opaque));
+ }
+
+ for (int i = 0; i < params.size(); i++) {
+ BasicNameValuePair param = params.get(i);
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ boolean noQuotes = "nc".equals(param.getName()) ||
+ "qop".equals(param.getName());
+ BasicHeaderValueFormatter.DEFAULT
+ .formatNameValuePair(buffer, param, !noQuotes);
+ }
+ return new BufferedHeader(buffer);
+ }
+
+ private String getQopVariantString() {
+ String qopOption;
+ if (qopVariant == QOP_AUTH_INT) {
+ qopOption = "auth-int";
+ } else {
+ qopOption = "auth";
+ }
+ return qopOption;
+ }
+
+ /**
+ * Encodes the 128 bit (16 bytes) MD5 digest into a 32 characters long
+ * <CODE>String</CODE> according to RFC 2617.
+ *
+ * @param binaryData array containing the digest
+ * @return encoded MD5, or <CODE>null</CODE> if encoding failed
+ */
+ private static String encode(byte[] binaryData) {
+ if (binaryData.length != 16) {
+ return null;
+ }
+
+ char[] buffer = new char[32];
+ for (int i = 0; i < 16; i++) {
+ int low = (binaryData[i] & 0x0f);
+ int high = ((binaryData[i] & 0xf0) >> 4);
+ buffer[i * 2] = HEXADECIMAL[high];
+ buffer[(i * 2) + 1] = HEXADECIMAL[low];
+ }
+
+ return new String(buffer);
+ }
+
+
+ /**
+ * Creates a random cnonce value based on the current time.
+ *
+ * @return The cnonce value as String.
+ * @throws UnsupportedDigestAlgorithmException if MD5 algorithm is not supported.
+ */
+ public static String createCnonce() {
+ String cnonce;
+
+ MessageDigest md5Helper = createMessageDigest("MD5");
+
+ cnonce = Long.toString(System.currentTimeMillis());
+ cnonce = encode(md5Helper.digest(EncodingUtils.getAsciiBytes(cnonce)));
+
+ return cnonce;
+ }
+}
diff --git a/src/org/apache/http/impl/auth/DigestSchemeFactory.java b/src/org/apache/http/impl/auth/DigestSchemeFactory.java
new file mode 100644
index 0000000..38f2e12
--- /dev/null
+++ b/src/org/apache/http/impl/auth/DigestSchemeFactory.java
@@ -0,0 +1,50 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/DigestSchemeFactory.java $
+ * $Revision: 534839 $
+ * $Date: 2007-05-03 06:03:41 -0700 (Thu, 03 May 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthSchemeFactory;
+import org.apache.http.params.HttpParams;
+
+/**
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+public class DigestSchemeFactory implements AuthSchemeFactory {
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new DigestScheme();
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/NTLMEngine.java b/src/org/apache/http/impl/auth/NTLMEngine.java
new file mode 100644
index 0000000..7b6bf42
--- /dev/null
+++ b/src/org/apache/http/impl/auth/NTLMEngine.java
@@ -0,0 +1,76 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java $
+ * $Revision: 659788 $
+ * $Date: 2008-05-24 03:42:23 -0700 (Sat, 24 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+/**
+ * Abstract NTLM authentication engine. The engine can be used to
+ * generate Type1 messages and Type3 messages in response to a
+ * Type2 challenge.
+ * <p/>
+ * For details see <a href="http://davenport.sourceforge.net/ntlm.html">this resource</a>
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+*/
+public interface NTLMEngine {
+
+ /**
+ * Generates a Type1 message given the domain and workstation.
+ *
+ * @param domain Optional Windows domain name. Can be <code>null</code>.
+ * @param workstation Optional Windows workstation name. Can be
+ * <code>null</code>.
+ * @return Type1 message
+ * @throws NTLMEngineException
+ */
+ String generateType1Msg(
+ String domain,
+ String workstation) throws NTLMEngineException;
+
+ /**
+ * Generates a Type3 message given the user credentials and the
+ * authentication challenge.
+ *
+ * @param username Windows user name
+ * @param password Password
+ * @param domain Windows domain name
+ * @param workstation Windows workstation name
+ * @param challenge Type2 challenge.
+ * @return Type3 response.
+ * @throws NTLMEngineException
+ */
+ String generateType3Msg(
+ String username,
+ String password,
+ String domain,
+ String workstation,
+ String challenge) throws NTLMEngineException;
+
+}
diff --git a/src/org/apache/http/impl/auth/NTLMEngineException.java b/src/org/apache/http/impl/auth/NTLMEngineException.java
new file mode 100644
index 0000000..73baabc
--- /dev/null
+++ b/src/org/apache/http/impl/auth/NTLMEngineException.java
@@ -0,0 +1,70 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java $
+ * $Revision: 655048 $
+ * $Date: 2008-05-10 04:22:12 -0700 (Sat, 10 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.auth.AuthenticationException;
+
+/**
+ * Signals NTLM protocol failure.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+public class NTLMEngineException extends AuthenticationException {
+
+ private static final long serialVersionUID = 6027981323731768824L;
+
+ public NTLMEngineException() {
+ super();
+ }
+
+ /**
+ * Creates a new NTLMEngineException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public NTLMEngineException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new NTLMEngineException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public NTLMEngineException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/NTLMScheme.java b/src/org/apache/http/impl/auth/NTLMScheme.java
new file mode 100644
index 0000000..8dfdbba
--- /dev/null
+++ b/src/org/apache/http/impl/auth/NTLMScheme.java
@@ -0,0 +1,149 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java $
+ * $Revision: 655048 $
+ * $Date: 2008-05-10 04:22:12 -0700 (Sat, 10 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.InvalidCredentialsException;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.NTCredentials;
+import org.apache.http.impl.auth.AuthSchemeBase;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.util.CharArrayBuffer;
+
+public class NTLMScheme extends AuthSchemeBase {
+
+ enum State {
+ UNINITIATED,
+ CHALLENGE_RECEIVED,
+ MSG_TYPE1_GENERATED,
+ MSG_TYPE2_RECEVIED,
+ MSG_TYPE3_GENERATED,
+ FAILED,
+ }
+
+ private final NTLMEngine engine;
+
+ private State state;
+ private String challenge;
+
+ public NTLMScheme(final NTLMEngine engine) {
+ super();
+ if (engine == null) {
+ throw new IllegalArgumentException("NTLM engine may not be null");
+ }
+ this.engine = engine;
+ this.state = State.UNINITIATED;
+ this.challenge = null;
+ }
+
+ public String getSchemeName() {
+ return "ntlm";
+ }
+
+ public String getParameter(String name) {
+ // String parameters not supported
+ return null;
+ }
+
+ public String getRealm() {
+ // NTLM does not support the concept of an authentication realm
+ return null;
+ }
+
+ public boolean isConnectionBased() {
+ return true;
+ }
+
+ @Override
+ protected void parseChallenge(
+ final CharArrayBuffer buffer, int pos, int len) throws MalformedChallengeException {
+ String challenge = buffer.substringTrimmed(pos, len);
+ if (challenge.length() == 0) {
+ if (this.state == State.UNINITIATED) {
+ this.state = State.CHALLENGE_RECEIVED;
+ } else {
+ this.state = State.FAILED;
+ }
+ this.challenge = null;
+ } else {
+ this.state = State.MSG_TYPE2_RECEVIED;
+ this.challenge = challenge;
+ }
+ }
+
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+ NTCredentials ntcredentials = null;
+ try {
+ ntcredentials = (NTCredentials) credentials;
+ } catch (ClassCastException e) {
+ throw new InvalidCredentialsException(
+ "Credentials cannot be used for NTLM authentication: "
+ + credentials.getClass().getName());
+ }
+ String response = null;
+ if (this.state == State.CHALLENGE_RECEIVED || this.state == State.FAILED) {
+ response = this.engine.generateType1Msg(
+ ntcredentials.getDomain(),
+ ntcredentials.getWorkstation());
+ this.state = State.MSG_TYPE1_GENERATED;
+ } else if (this.state == State.MSG_TYPE2_RECEVIED) {
+ response = this.engine.generateType3Msg(
+ ntcredentials.getUserName(),
+ ntcredentials.getPassword(),
+ ntcredentials.getDomain(),
+ ntcredentials.getWorkstation(),
+ this.challenge);
+ this.state = State.MSG_TYPE3_GENERATED;
+ } else {
+ throw new AuthenticationException("Unexpected state: " + this.state);
+ }
+ CharArrayBuffer buffer = new CharArrayBuffer(32);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": NTLM ");
+ buffer.append(response);
+ return new BufferedHeader(buffer);
+ }
+
+ public boolean isComplete() {
+ return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/RFC2617Scheme.java b/src/org/apache/http/impl/auth/RFC2617Scheme.java
new file mode 100644
index 0000000..0ed0a28
--- /dev/null
+++ b/src/org/apache/http/impl/auth/RFC2617Scheme.java
@@ -0,0 +1,119 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/RFC2617Scheme.java $
+ * $Revision: 659595 $
+ * $Date: 2008-05-23 09:47:14 -0700 (Fri, 23 May 2008) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.http.HeaderElement;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.message.BasicHeaderValueParser;
+import org.apache.http.message.HeaderValueParser;
+import org.apache.http.message.ParserCursor;
+import org.apache.http.util.CharArrayBuffer;
+
+/**
+ * Abstract authentication scheme class that lays foundation for all
+ * RFC 2617 compliant authetication schemes and provides capabilities common
+ * to all authentication schemes defined in RFC 2617.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+*/
+public abstract class RFC2617Scheme extends AuthSchemeBase {
+
+ /**
+ * Authentication parameter map.
+ */
+ private Map<String, String> params;
+
+ /**
+ * Default constructor for RFC2617 compliant authetication schemes.
+ */
+ public RFC2617Scheme() {
+ super();
+ }
+
+ @Override
+ protected void parseChallenge(
+ final CharArrayBuffer buffer, int pos, int len) throws MalformedChallengeException {
+ HeaderValueParser parser = BasicHeaderValueParser.DEFAULT;
+ ParserCursor cursor = new ParserCursor(pos, buffer.length());
+ HeaderElement[] elements = parser.parseElements(buffer, cursor);
+ if (elements.length == 0) {
+ throw new MalformedChallengeException("Authentication challenge is empty");
+ }
+
+ this.params = new HashMap<String, String>(elements.length);
+ for (HeaderElement element : elements) {
+ this.params.put(element.getName(), element.getValue());
+ }
+ }
+
+ /**
+ * Returns authentication parameters map. Keys in the map are lower-cased.
+ *
+ * @return the map of authentication parameters
+ */
+ protected Map<String, String> getParameters() {
+ if (this.params == null) {
+ this.params = new HashMap<String, String>();
+ }
+ return this.params;
+ }
+
+ /**
+ * Returns authentication parameter with the given name, if available.
+ *
+ * @param name The name of the parameter to be returned
+ *
+ * @return the parameter with the given name
+ */
+ public String getParameter(final String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Parameter name may not be null");
+ }
+ if (this.params == null) {
+ return null;
+ }
+ return this.params.get(name.toLowerCase(Locale.ENGLISH));
+ }
+
+ /**
+ * Returns authentication realm. The realm may not be null.
+ *
+ * @return the authentication realm
+ */
+ public String getRealm() {
+ return getParameter("realm");
+ }
+
+}
diff --git a/src/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java b/src/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java
new file mode 100644
index 0000000..abd0a66
--- /dev/null
+++ b/src/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java
@@ -0,0 +1,71 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/UnsupportedDigestAlgorithmException.java $
+ * $Revision: 527479 $
+ * $Date: 2007-04-11 05:55:12 -0700 (Wed, 11 Apr 2007) $
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+/**
+ * Authentication credentials required to respond to a authentication
+ * challenge are invalid
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @since 4.0
+ */
+public class UnsupportedDigestAlgorithmException extends RuntimeException {
+
+ private static final long serialVersionUID = 319558534317118022L;
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with a <tt>null</tt> detail message.
+ */
+ public UnsupportedDigestAlgorithmException() {
+ super();
+ }
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with the specified message.
+ *
+ * @param message the exception detail message
+ */
+ public UnsupportedDigestAlgorithmException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new UnsupportedAuthAlgoritmException with the specified detail message and cause.
+ *
+ * @param message the exception detail message
+ * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+ * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+ */
+ public UnsupportedDigestAlgorithmException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/org/apache/http/impl/auth/package.html b/src/org/apache/http/impl/auth/package.html
new file mode 100644
index 0000000..e301283
--- /dev/null
+++ b/src/org/apache/http/impl/auth/package.html
@@ -0,0 +1,4 @@
+<body>
+
+</body>
+