HTTPCLIENT-1053: Fixed the way DigestScheme generates nonce-count values
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1068546 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cae0917efd
commit
4e64d3961a
|
@ -1,3 +1,9 @@
|
|||
Changes since 4.1
|
||||
|
||||
* [HTTPCLIENT-1053] Fixed the way DigestScheme generates nonce-count values.
|
||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||
|
||||
|
||||
Release 4.1
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ package org.apache.http.impl.auth;
|
|||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
|
@ -88,14 +90,15 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
/** 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 lastNonce;
|
||||
private long nounceCount;
|
||||
private String cnonce;
|
||||
private String nc;
|
||||
|
||||
/**
|
||||
* Default constructor for the digest authetication scheme.
|
||||
|
@ -146,8 +149,6 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
if (unsupportedQop && (qopVariant == QOP_MISSING)) {
|
||||
throw new MalformedChallengeException("None of the qop methods is supported");
|
||||
}
|
||||
// Reset cnonce
|
||||
this.cnonce = null;
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
|
@ -195,6 +196,16 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
return this.cnonce;
|
||||
}
|
||||
|
||||
private String getNc() {
|
||||
if (this.nc == null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter formatter = new Formatter(sb, Locale.US);
|
||||
formatter.format("%08x", this.nounceCount);
|
||||
this.nc = sb.toString();
|
||||
}
|
||||
return this.nc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a digest authorization string for the given set of
|
||||
* {@link Credentials}, method name and URI.
|
||||
|
@ -266,6 +277,11 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
if (nonce == null) {
|
||||
throw new IllegalStateException("Nonce may not be null");
|
||||
}
|
||||
|
||||
// Reset
|
||||
this.cnonce = null;
|
||||
this.nc = null;
|
||||
|
||||
// If an algorithm is not specified, default to MD5.
|
||||
if (algorithm == null) {
|
||||
algorithm = "MD5";
|
||||
|
@ -285,6 +301,14 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
if (digAlg.equalsIgnoreCase("MD5-sess")) {
|
||||
digAlg = "MD5";
|
||||
}
|
||||
|
||||
if (nonce.equals(this.lastNonce)) {
|
||||
this.nounceCount++;
|
||||
} else {
|
||||
this.nounceCount = 1;
|
||||
this.lastNonce = nonce;
|
||||
}
|
||||
|
||||
MessageDigest digester = createMessageDigest(digAlg);
|
||||
|
||||
String uname = credentials.getUserPrincipal().getName();
|
||||
|
@ -345,14 +369,14 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
} else {
|
||||
String qopOption = getQopVariantString();
|
||||
String cnonce = getCnonce();
|
||||
|
||||
String nc = getNc();
|
||||
StringBuilder tmp2 = new StringBuilder(hasha1.length() + nonce.length()
|
||||
+ NC.length() + cnonce.length() + qopOption.length() + hasha2.length() + 5);
|
||||
+ nc.length() + cnonce.length() + qopOption.length() + hasha2.length() + 5);
|
||||
tmp2.append(hasha1);
|
||||
tmp2.append(':');
|
||||
tmp2.append(nonce);
|
||||
tmp2.append(':');
|
||||
tmp2.append(NC);
|
||||
tmp2.append(nc);
|
||||
tmp2.append(':');
|
||||
tmp2.append(cnonce);
|
||||
tmp2.append(':');
|
||||
|
@ -406,7 +430,7 @@ public class DigestScheme extends RFC2617Scheme {
|
|||
|
||||
if (qopVariant != QOP_MISSING) {
|
||||
params.add(new BasicNameValuePair("qop", getQopVariantString()));
|
||||
params.add(new BasicNameValuePair("nc", NC));
|
||||
params.add(new BasicNameValuePair("nc", getNc()));
|
||||
params.add(new BasicNameValuePair("cnonce", getCnonce()));
|
||||
}
|
||||
if (algorithm != null) {
|
||||
|
|
|
@ -304,4 +304,32 @@ public class TestDigestScheme {
|
|||
return map;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigestNouceCount() throws Exception {
|
||||
String challenge1 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||
Header authChallenge1 = new BasicHeader(AUTH.WWW_AUTH, challenge1);
|
||||
HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(authChallenge1);
|
||||
Header authResponse1 = authscheme.authenticate(cred, request);
|
||||
Map<String, String> table1 = parseAuthResponse(authResponse1);
|
||||
Assert.assertEquals("00000001", table1.get("nc"));
|
||||
Header authResponse2 = authscheme.authenticate(cred, request);
|
||||
Map<String, String> table2 = parseAuthResponse(authResponse2);
|
||||
Assert.assertEquals("00000002", table2.get("nc"));
|
||||
String challenge2 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||
Header authChallenge2 = new BasicHeader(AUTH.WWW_AUTH, challenge2);
|
||||
authscheme.processChallenge(authChallenge2);
|
||||
Header authResponse3 = authscheme.authenticate(cred, request);
|
||||
Map<String, String> table3 = parseAuthResponse(authResponse3);
|
||||
Assert.assertEquals("00000003", table3.get("nc"));
|
||||
String challenge3 = "Digest realm=\"realm1\", nonce=\"e273f1776275974f1a120d8b92c5b3cb\", qop=auth";
|
||||
Header authChallenge3 = new BasicHeader(AUTH.WWW_AUTH, challenge3);
|
||||
authscheme.processChallenge(authChallenge3);
|
||||
Header authResponse4 = authscheme.authenticate(cred, request);
|
||||
Map<String, String> table4 = parseAuthResponse(authResponse4);
|
||||
Assert.assertEquals("00000001", table4.get("nc"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue