-----Original Message-----
From: Robert Owen
Sent: 17 January 2002 15:33
To: '[EMAIL PROTECTED]'
Subject: Digest authentication
Here are the beginnings of a digest authentication implementation for
HttpClient. It's a start as the client only supports the md5 algorithm and
does not use a generated client nonce or nonceCount (these are static), but
it does work against an Apache web server with digest authentication.[Rob]
I hope this helps as we would like to see support for digest authentication.
Cheers,
Rob.
--- HttpClient.java.orig Thu Jan 17 15:02:22 2002
+++ HttpClient.java Thu Jan 17 15:23:25 2002
@@ -972,7 +972,7 @@
if (state.getAuthenticateToken() != null) {
String challengeResponse = Authenticator.challengeResponse
- (state, credentials);
+ (method, state, credentials);
if (challengeResponse != null) {
if (debug > 1)
System.out.print("Authorization: "
--- Authenticator.java.orig Thu Jan 17 15:19:11 2002
+++ Authenticator.java Thu Jan 17 15:21:09 2002
@@ -90,7 +90,7 @@
* @param credentials Credentials to use to answser the challenge
* @return String response to the challenge
*/
- public static String challengeResponse(State state,
+ public static String challengeResponse(HttpMethod method, State state,
Credentials credentials)
throws HttpException {
@@ -110,7 +110,7 @@
if (challengeName.equalsIgnoreCase("basic")) {
return basic(state, credentials);
} else if (challengeName.equalsIgnoreCase("digest")) {
- return digest(state, credentials);
+ return digest(method, state, credentials);
} else {
}
@@ -134,14 +134,94 @@
/**
- * Generate a basic response.
+ * Generate a digest response.
*
* @param credentials Credentials to use to answser the challenge
*/
- public static String digest(State state, Credentials credentials) {
-
- return null;
+ public static String digest(HttpMethod method, State state, Credentials
+credentials) {
+ int p1, p2;
+ String realm = "";
+ String nonce = "";
+ String CNonce = "0a4f113b";
+ String algorithm = "";
+ String nonceCount = "00000001";
+ String qop = "";
+ String domain = "";
+ String opaque = "";
+
+ String user = credentials.getUserName();
+ String pw = credentials.getPassword();
+ String methodName = method.getName();
+ String uri = method.getPath();
+
+ String challenge = state.getAuthenticateToken();
+ if (challenge == null) return null;
+
+ java.security.MessageDigest md5;
+ try {
+ md5 = java.security.MessageDigest.getInstance("MD5");
+ } catch (java.security.NoSuchAlgorithmException nsa) {
+ return null;
+ }
+
+ // Assumes that none of the field values has a comma
+ java.util.StringTokenizer st = new java.util.StringTokenizer(
+challenge.substring("digest ".length()), "," );
+ String aField, aFieldName, aFieldValue;
+ int equals;
+ while (st.hasMoreTokens())
+ {
+ aField = st.nextToken();
+ equals = aField.indexOf('=');
+ if (equals < 0) continue;
+
+ aFieldName = aField.substring(0,equals).trim();
+ aFieldValue = aField.substring(equals+1);
+ if (aFieldValue.indexOf('"') >= 0)
+ {
+ aFieldValue = aFieldValue.replace('"', ' ');
+ aFieldValue = aFieldValue.trim();
+ }
+
+ if (aFieldName.equalsIgnoreCase("realm")) realm =
+aFieldValue;
+ else if (aFieldName.equalsIgnoreCase("domain")) domain =
+aFieldValue;
+ else if (aFieldName.equalsIgnoreCase("nonce")) nonce =
+aFieldValue;
+ else if (aFieldName.equalsIgnoreCase("algorithm")) algorithm =
+aFieldValue;
+ else if (aFieldName.equalsIgnoreCase("qop")) qop =
+aFieldValue;
+ else if (aFieldName.equalsIgnoreCase("opaque")) opaque =
+aFieldValue;
+ }
+ if (!algorithm.equalsIgnoreCase("md5")) return null;
+
+ MD5Encoder md5enc = new MD5Encoder();
+ String A1 = user+":"+realm+":"+pw;
+ byte[] HA1 = md5.digest(A1.getBytes());
+ String HA1HEX = md5enc.encode(HA1);
+
+ String A2 = methodName+":"+uri;
+ byte[] HA2 = md5.digest(A2.getBytes());
+ String HA2HEX = md5enc.encode(HA2);
+
+ String request_digest_String =
+HA1HEX+":"+nonce+":"+nonceCount+":"+CNonce+":"+qop+":"+HA2HEX;
+ byte[] request_digest_bytes =
+md5.digest(request_digest_String.getBytes());
+ String request_digest = md5enc.encode(request_digest_bytes);
+
+ StringBuffer retStr = new StringBuffer("Digest
+username=\""+user+"\",realm=\""+realm+
+ "\",nonce=\""+nonce+"\",uri=\""+uri+"\"");
+ if (!qop.equals(""))
+ {
+ retStr.append(",qop=");
+ retStr.append(qop);
+ retStr.append(",nc=\"");
+ retStr.append(nonceCount);
+ retStr.append("\",cnonce=\"");
+ retStr.append(CNonce);
+ retStr.append("\"");
+ }
+ retStr.append(",response=\"");
+ retStr.append(request_digest);
+ retStr.append("\"");
+ if (!opaque.equals(""))retStr.append(",opaque=\""+opaque+"\"");
+ return retStr.toString();
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>