DigestScheme can use an arbitrary digest algorithm requested by the target server (such SHA) as long as this algorithm is supported by the Java runtime
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@708595 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c3b6c426ca
commit
e434f1367a
|
@ -1,6 +1,11 @@
|
||||||
Changes since 4.0 beta 1
|
Changes since 4.0 beta 1
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* DigestScheme can use an arbitrary digest algorithm requested by the
|
||||||
|
target server (such SHA) as long as this algorithm is supported by
|
||||||
|
the Java runtime.
|
||||||
|
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||||
|
|
||||||
* Fixed parsing and validation of RFC2109 compliant Set-Cookie headers
|
* Fixed parsing and validation of RFC2109 compliant Set-Cookie headers
|
||||||
by the Best-Match cookie spec.
|
by the Best-Match cookie spec.
|
||||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||||
|
|
|
@ -288,7 +288,11 @@ public class DigestScheme extends RFC2617Scheme {
|
||||||
"Unsupported qop in HTTP Digest authentication");
|
"Unsupported qop in HTTP Digest authentication");
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageDigest md5Helper = createMessageDigest("MD5");
|
String digAlg = algorithm;
|
||||||
|
if (digAlg.equalsIgnoreCase("MD5-sess")) {
|
||||||
|
digAlg = "MD5";
|
||||||
|
}
|
||||||
|
MessageDigest digester = createMessageDigest(digAlg);
|
||||||
|
|
||||||
String uname = credentials.getUserPrincipal().getName();
|
String uname = credentials.getUserPrincipal().getName();
|
||||||
String pwd = credentials.getPassword();
|
String pwd = credentials.getPassword();
|
||||||
|
@ -304,25 +308,25 @@ public class DigestScheme extends RFC2617Scheme {
|
||||||
String a1 = tmp.toString();
|
String a1 = tmp.toString();
|
||||||
|
|
||||||
//a1 is suitable for MD5 algorithm
|
//a1 is suitable for MD5 algorithm
|
||||||
if(algorithm.equals("MD5-sess")) {
|
if (algorithm.equalsIgnoreCase("MD5-sess")) {
|
||||||
// H( unq(username-value) ":" unq(realm-value) ":" passwd )
|
// H( unq(username-value) ":" unq(realm-value) ":" passwd )
|
||||||
// ":" unq(nonce-value)
|
// ":" unq(nonce-value)
|
||||||
// ":" unq(cnonce-value)
|
// ":" unq(cnonce-value)
|
||||||
|
|
||||||
|
algorithm = "MD5";
|
||||||
String cnonce = getCnonce();
|
String cnonce = getCnonce();
|
||||||
|
|
||||||
String tmp2=encode(md5Helper.digest(EncodingUtils.getBytes(a1, charset)));
|
String tmp2 = encode(digester.digest(EncodingUtils.getBytes(a1, charset)));
|
||||||
StringBuilder tmp3 = new StringBuilder(tmp2.length() + nonce.length() + cnonce.length() + 2);
|
StringBuilder tmp3 = new StringBuilder(
|
||||||
|
tmp2.length() + nonce.length() + cnonce.length() + 2);
|
||||||
tmp3.append(tmp2);
|
tmp3.append(tmp2);
|
||||||
tmp3.append(':');
|
tmp3.append(':');
|
||||||
tmp3.append(nonce);
|
tmp3.append(nonce);
|
||||||
tmp3.append(':');
|
tmp3.append(':');
|
||||||
tmp3.append(cnonce);
|
tmp3.append(cnonce);
|
||||||
a1 = tmp3.toString();
|
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 hasha1 = encode(digester.digest(EncodingUtils.getBytes(a1, charset)));
|
||||||
|
|
||||||
String a2 = null;
|
String a2 = null;
|
||||||
if (qopVariant == QOP_AUTH_INT) {
|
if (qopVariant == QOP_AUTH_INT) {
|
||||||
|
@ -332,25 +336,26 @@ public class DigestScheme extends RFC2617Scheme {
|
||||||
} else {
|
} else {
|
||||||
a2 = method + ':' + uri;
|
a2 = method + ':' + uri;
|
||||||
}
|
}
|
||||||
String md5a2 = encode(md5Helper.digest(EncodingUtils.getAsciiBytes(a2)));
|
String hasha2 = encode(digester.digest(EncodingUtils.getAsciiBytes(a2)));
|
||||||
|
|
||||||
// 3.2.2.1
|
// 3.2.2.1
|
||||||
String serverDigestValue;
|
String serverDigestValue;
|
||||||
if (qopVariant == QOP_MISSING) {
|
if (qopVariant == QOP_MISSING) {
|
||||||
StringBuilder tmp2 = new StringBuilder(md5a1.length() + nonce.length() + md5a2.length());
|
StringBuilder tmp2 = new StringBuilder(
|
||||||
tmp2.append(md5a1);
|
hasha1.length() + nonce.length() + hasha1.length());
|
||||||
|
tmp2.append(hasha1);
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
tmp2.append(nonce);
|
tmp2.append(nonce);
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
tmp2.append(md5a2);
|
tmp2.append(hasha2);
|
||||||
serverDigestValue = tmp2.toString();
|
serverDigestValue = tmp2.toString();
|
||||||
} else {
|
} else {
|
||||||
String qopOption = getQopVariantString();
|
String qopOption = getQopVariantString();
|
||||||
String cnonce = getCnonce();
|
String cnonce = getCnonce();
|
||||||
|
|
||||||
StringBuilder tmp2 = new StringBuilder(md5a1.length() + nonce.length()
|
StringBuilder tmp2 = new StringBuilder(hasha1.length() + nonce.length()
|
||||||
+ NC.length() + cnonce.length() + qopOption.length() + md5a2.length() + 5);
|
+ NC.length() + cnonce.length() + qopOption.length() + hasha2.length() + 5);
|
||||||
tmp2.append(md5a1);
|
tmp2.append(hasha1);
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
tmp2.append(nonce);
|
tmp2.append(nonce);
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
|
@ -360,12 +365,12 @@ public class DigestScheme extends RFC2617Scheme {
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
tmp2.append(qopOption);
|
tmp2.append(qopOption);
|
||||||
tmp2.append(':');
|
tmp2.append(':');
|
||||||
tmp2.append(md5a2);
|
tmp2.append(hasha2);
|
||||||
serverDigestValue = tmp2.toString();
|
serverDigestValue = tmp2.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
String serverDigest =
|
String serverDigest =
|
||||||
encode(md5Helper.digest(EncodingUtils.getAsciiBytes(serverDigestValue)));
|
encode(digester.digest(EncodingUtils.getAsciiBytes(serverDigestValue)));
|
||||||
|
|
||||||
return serverDigest;
|
return serverDigest;
|
||||||
}
|
}
|
||||||
|
@ -449,12 +454,9 @@ public class DigestScheme extends RFC2617Scheme {
|
||||||
* @return encoded MD5, or <CODE>null</CODE> if encoding failed
|
* @return encoded MD5, or <CODE>null</CODE> if encoding failed
|
||||||
*/
|
*/
|
||||||
private static String encode(byte[] binaryData) {
|
private static String encode(byte[] binaryData) {
|
||||||
if (binaryData.length != 16) {
|
int n = binaryData.length;
|
||||||
return null;
|
char[] buffer = new char[n * 2];
|
||||||
}
|
for (int i = 0; i < n; i++) {
|
||||||
|
|
||||||
char[] buffer = new char[32];
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
int low = (binaryData[i] & 0x0f);
|
int low = (binaryData[i] & 0x0f);
|
||||||
int high = ((binaryData[i] & 0xf0) >> 4);
|
int high = ((binaryData[i] & 0xf0) >> 4);
|
||||||
buffer[i * 2] = HEXADECIMAL[high];
|
buffer[i * 2] = HEXADECIMAL[high];
|
||||||
|
|
|
@ -130,6 +130,25 @@ public class TestDigestScheme extends TestCase {
|
||||||
assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
|
assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDigestAuthenticationWithSHA() throws Exception {
|
||||||
|
String challenge = "Digest realm=\"realm1\", " +
|
||||||
|
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
|
"algorithm=SHA";
|
||||||
|
Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
|
||||||
|
HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||||
|
Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||||
|
AuthScheme authscheme = new DigestScheme();
|
||||||
|
authscheme.processChallenge(authChallenge);
|
||||||
|
Header authResponse = authscheme.authenticate(cred, request);
|
||||||
|
|
||||||
|
Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
|
assertEquals("username", table.get("username"));
|
||||||
|
assertEquals("realm1", table.get("realm"));
|
||||||
|
assertEquals("/", table.get("uri"));
|
||||||
|
assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
|
||||||
|
assertEquals("8769e82e4e28ecc040b969562b9050580c6d186d", table.get("response"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
|
public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
|
||||||
String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
|
Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
|
||||||
|
|
Loading…
Reference in New Issue