1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.auth;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.io.ObjectInputStream;
33 import java.io.ObjectOutputStream;
34 import java.security.MessageDigest;
35 import java.util.HashMap;
36 import java.util.Map;
37
38 import org.apache.http.Header;
39 import org.apache.http.HeaderElement;
40 import org.apache.http.HttpEntityEnclosingRequest;
41 import org.apache.http.HttpRequest;
42 import org.apache.http.auth.AUTH;
43 import org.apache.http.auth.AuthScheme;
44 import org.apache.http.auth.AuthenticationException;
45 import org.apache.http.auth.Credentials;
46 import org.apache.http.auth.MalformedChallengeException;
47 import org.apache.http.auth.UsernamePasswordCredentials;
48 import org.apache.http.entity.InputStreamEntity;
49 import org.apache.http.entity.StringEntity;
50 import org.apache.http.message.BasicHeader;
51 import org.apache.http.message.BasicHeaderValueParser;
52 import org.apache.http.message.BasicHttpEntityEnclosingRequest;
53 import org.apache.http.message.BasicHttpRequest;
54 import org.apache.http.protocol.BasicHttpContext;
55 import org.apache.http.protocol.HTTP;
56 import org.apache.http.protocol.HttpContext;
57 import org.junit.Assert;
58 import org.junit.Test;
59
60
61
62
63 public class TestDigestScheme {
64
65 @Test(expected=MalformedChallengeException.class)
66 public void testDigestAuthenticationEmptyChallenge1() throws Exception {
67 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, "Digest");
68 final AuthScheme authscheme = new DigestScheme();
69 authscheme.processChallenge(authChallenge);
70 }
71
72 @Test(expected=MalformedChallengeException.class)
73 public void testDigestAuthenticationEmptyChallenge2() throws Exception {
74 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, "Digest ");
75 final AuthScheme authscheme = new DigestScheme();
76 authscheme.processChallenge(authChallenge);
77 }
78
79 @Test
80 public void testDigestAuthenticationWithDefaultCreds() throws Exception {
81 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
82 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
83 final HttpRequest request = new BasicHttpRequest("Simple", "/");
84 final Credentials cred = new UsernamePasswordCredentials("username","password");
85 final DigestScheme authscheme = new DigestScheme();
86 final HttpContext context = new BasicHttpContext();
87 authscheme.processChallenge(authChallenge);
88 final Header authResponse = authscheme.authenticate(cred, request, context);
89 Assert.assertTrue(authscheme.isComplete());
90 Assert.assertFalse(authscheme.isConnectionBased());
91
92 final Map<String, String> table = parseAuthResponse(authResponse);
93 Assert.assertEquals("username", table.get("username"));
94 Assert.assertEquals("realm1", table.get("realm"));
95 Assert.assertEquals("/", table.get("uri"));
96 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
97 Assert.assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
98 }
99
100 @Test
101 public void testDigestAuthentication() throws Exception {
102 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
103 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
104 final HttpRequest request = new BasicHttpRequest("Simple", "/");
105 final Credentials cred = new UsernamePasswordCredentials("username","password");
106 final DigestScheme authscheme = new DigestScheme();
107 final HttpContext context = new BasicHttpContext();
108 authscheme.processChallenge(authChallenge);
109 final Header authResponse = authscheme.authenticate(cred, request, context);
110
111 final Map<String, String> table = parseAuthResponse(authResponse);
112 Assert.assertEquals("username", table.get("username"));
113 Assert.assertEquals("realm1", table.get("realm"));
114 Assert.assertEquals("/", table.get("uri"));
115 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
116 Assert.assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
117 }
118
119 @Test
120 public void testDigestAuthenticationInvalidInput() throws Exception {
121 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
122 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
123 final HttpRequest request = new BasicHttpRequest("Simple", "/");
124 final Credentials cred = new UsernamePasswordCredentials("username","password");
125 final DigestScheme authscheme = new DigestScheme();
126 final HttpContext context = new BasicHttpContext();
127 authscheme.processChallenge(authChallenge);
128 try {
129 authscheme.authenticate(null, request, context);
130 Assert.fail("IllegalArgumentException should have been thrown");
131 } catch (final IllegalArgumentException ex) {
132 }
133 try {
134 authscheme.authenticate(cred, null, context);
135 Assert.fail("IllegalArgumentException should have been thrown");
136 } catch (final IllegalArgumentException ex) {
137 }
138 }
139
140 @Test
141 public void testDigestAuthenticationOverrideParameter() throws Exception {
142 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
143 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
144 final HttpRequest request = new BasicHttpRequest("Simple", "/");
145 final Credentials cred = new UsernamePasswordCredentials("username","password");
146 final DigestScheme authscheme = new DigestScheme();
147 final HttpContext context = new BasicHttpContext();
148 authscheme.processChallenge(authChallenge);
149 authscheme.overrideParamter("realm", "other realm");
150 final Header authResponse = authscheme.authenticate(cred, request, context);
151
152 final Map<String, String> table = parseAuthResponse(authResponse);
153 Assert.assertEquals("username", table.get("username"));
154 Assert.assertEquals("other realm", table.get("realm"));
155 Assert.assertEquals("/", table.get("uri"));
156 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
157 Assert.assertEquals("3f211de10463cbd055ab4cd9c5158eac", table.get("response"));
158 }
159
160 @Test
161 public void testDigestAuthenticationWithSHA() throws Exception {
162 final String challenge = "Digest realm=\"realm1\", " +
163 "nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
164 "algorithm=SHA";
165 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
166 final HttpRequest request = new BasicHttpRequest("Simple", "/");
167 final Credentials cred = new UsernamePasswordCredentials("username","password");
168 final HttpContext context = new BasicHttpContext();
169 final DigestScheme authscheme = new DigestScheme();
170 authscheme.processChallenge(authChallenge);
171 final Header authResponse = authscheme.authenticate(cred, request, context);
172
173 final Map<String, String> table = parseAuthResponse(authResponse);
174 Assert.assertEquals("username", table.get("username"));
175 Assert.assertEquals("realm1", table.get("realm"));
176 Assert.assertEquals("/", table.get("uri"));
177 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
178 Assert.assertEquals("8769e82e4e28ecc040b969562b9050580c6d186d", table.get("response"));
179 }
180
181 @Test
182 public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
183 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
184 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
185 final HttpRequest request = new BasicHttpRequest("Simple", "/?param=value");
186 final Credentials cred = new UsernamePasswordCredentials("username","password");
187 final HttpContext context = new BasicHttpContext();
188 final DigestScheme authscheme = new DigestScheme();
189 authscheme.processChallenge(authChallenge);
190 final Header authResponse = authscheme.authenticate(cred, request, context);
191
192 final Map<String, String> table = parseAuthResponse(authResponse);
193 Assert.assertEquals("username", table.get("username"));
194 Assert.assertEquals("realm1", table.get("realm"));
195 Assert.assertEquals("/?param=value", table.get("uri"));
196 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
197 Assert.assertEquals("a847f58f5fef0bc087bcb9c3eb30e042", table.get("response"));
198 }
199
200 @Test
201 public void testDigestAuthenticationWithMultipleRealms() throws Exception {
202 final String challenge1 = "Digest realm=\"realm1\", nonce=\"abcde\"";
203 final String challenge2 = "Digest realm=\"realm2\", nonce=\"123546\"";
204 final Credentials cred = new UsernamePasswordCredentials("username","password");
205 final Credentials cred2 = new UsernamePasswordCredentials("uname2","password2");
206
207 Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge1);
208 final HttpRequest request = new BasicHttpRequest("Simple", "/");
209 final HttpContext context = new BasicHttpContext();
210 final DigestScheme authscheme = new DigestScheme();
211 authscheme.processChallenge(authChallenge);
212 Header authResponse = authscheme.authenticate(cred, request, context);
213
214 Map<String, String> table = parseAuthResponse(authResponse);
215 Assert.assertEquals("username", table.get("username"));
216 Assert.assertEquals("realm1", table.get("realm"));
217 Assert.assertEquals("/", table.get("uri"));
218 Assert.assertEquals("abcde", table.get("nonce"));
219 Assert.assertEquals("786f500303eac1478f3c2865e676ed68", table.get("response"));
220
221 authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge2);
222 final DigestScheme authscheme2 = new DigestScheme();
223 authscheme2.processChallenge(authChallenge);
224 authResponse = authscheme2.authenticate(cred2, request, context);
225
226 table = parseAuthResponse(authResponse);
227 Assert.assertEquals("uname2", table.get("username"));
228 Assert.assertEquals("realm2", table.get("realm"));
229 Assert.assertEquals("/", table.get("uri"));
230 Assert.assertEquals("123546", table.get("nonce"));
231 Assert.assertEquals("0283edd9ef06a38b378b3b74661391e9", table.get("response"));
232 }
233
234 @Test(expected=AuthenticationException.class)
235 public void testDigestAuthenticationNoRealm() throws Exception {
236 final String challenge = "Digest no-realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
237 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
238 final HttpContext context = new BasicHttpContext();
239 final DigestScheme authscheme = new DigestScheme();
240 authscheme.processChallenge(authChallenge);
241
242 final Credentials cred = new UsernamePasswordCredentials("username","password");
243 final HttpRequest request = new BasicHttpRequest("Simple", "/");
244 authscheme.authenticate(cred, request, context);
245 }
246
247 @Test(expected=AuthenticationException.class)
248 public void testDigestAuthenticationNoNonce() throws Exception {
249 final String challenge = "Digest realm=\"realm1\", no-nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
250 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
251 final HttpContext context = new BasicHttpContext();
252 final DigestScheme authscheme = new DigestScheme();
253 authscheme.processChallenge(authChallenge);
254
255 final Credentials cred = new UsernamePasswordCredentials("username","password");
256 final HttpRequest request = new BasicHttpRequest("Simple", "/");
257 authscheme.authenticate(cred, request, context);
258 }
259
260
261
262
263 @Test
264 public void testDigestAuthenticationMD5Sess() throws Exception {
265
266
267 final String realm="realm";
268 final String username="username";
269 final String password="password";
270 final String nonce="e273f1776275974f1a120d8b92c5b3cb";
271
272 final String challenge="Digest realm=\"" + realm + "\", "
273 + "nonce=\"" + nonce + "\", "
274 + "opaque=\"SomeString\", "
275 + "stale=false, "
276 + "algorithm=MD5-sess, "
277 + "qop=\"auth,auth-int\"";
278
279 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
280
281 final Credentials cred = new UsernamePasswordCredentials(username, password);
282 final HttpRequest request = new BasicHttpRequest("Simple", "/");
283 final HttpContext context = new BasicHttpContext();
284
285 final DigestScheme authscheme = new DigestScheme();
286 authscheme.processChallenge(authChallenge);
287 final Header authResponse = authscheme.authenticate(cred, request, context);
288 final String response = authResponse.getValue();
289
290 Assert.assertTrue(response.indexOf("nc=00000001") > 0);
291 Assert.assertTrue(response.indexOf("qop=auth") > 0);
292
293 final Map<String, String> table = parseAuthResponse(authResponse);
294 Assert.assertEquals(username, table.get("username"));
295 Assert.assertEquals(realm, table.get("realm"));
296 Assert.assertEquals("MD5-sess", table.get("algorithm"));
297 Assert.assertEquals("/", table.get("uri"));
298 Assert.assertEquals(nonce, table.get("nonce"));
299 Assert.assertEquals(1, Integer.parseInt(table.get("nc"),16));
300 Assert.assertTrue(null != table.get("cnonce"));
301 Assert.assertEquals("SomeString", table.get("opaque"));
302 Assert.assertEquals("auth", table.get("qop"));
303
304 Assert.assertTrue(null != table.get("response"));
305 }
306
307
308
309
310 @Test
311 public void testDigestAuthenticationMD5SessNoQop() throws Exception {
312
313
314 final String realm="realm";
315 final String username="username";
316 final String password="password";
317 final String nonce="e273f1776275974f1a120d8b92c5b3cb";
318
319 final String challenge="Digest realm=\"" + realm + "\", "
320 + "nonce=\"" + nonce + "\", "
321 + "opaque=\"SomeString\", "
322 + "stale=false, "
323 + "algorithm=MD5-sess";
324
325 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
326
327 final Credentials cred = new UsernamePasswordCredentials(username, password);
328
329 final HttpRequest request = new BasicHttpRequest("Simple", "/");
330 final HttpContext context = new BasicHttpContext();
331
332 final DigestScheme authscheme = new DigestScheme();
333 authscheme.processChallenge(authChallenge);
334 final Header authResponse = authscheme.authenticate(cred, request, context);
335
336 final Map<String, String> table = parseAuthResponse(authResponse);
337 Assert.assertEquals(username, table.get("username"));
338 Assert.assertEquals(realm, table.get("realm"));
339 Assert.assertEquals("MD5-sess", table.get("algorithm"));
340 Assert.assertEquals("/", table.get("uri"));
341 Assert.assertEquals(nonce, table.get("nonce"));
342 Assert.assertTrue(null == table.get("nc"));
343 Assert.assertEquals("SomeString", table.get("opaque"));
344 Assert.assertTrue(null == table.get("qop"));
345
346 Assert.assertTrue(null != table.get("response"));
347 }
348
349
350
351
352 @Test(expected=AuthenticationException.class)
353 public void testDigestAuthenticationMD5SessUnknownQop() throws Exception {
354
355
356 final String realm="realm";
357 final String username="username";
358 final String password="password";
359 final String nonce="e273f1776275974f1a120d8b92c5b3cb";
360
361 final String challenge="Digest realm=\"" + realm + "\", "
362 + "nonce=\"" + nonce + "\", "
363 + "opaque=\"SomeString\", "
364 + "stale=false, "
365 + "algorithm=MD5-sess, "
366 + "qop=\"stuff\"";
367
368 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
369
370 final DigestScheme authscheme = new DigestScheme();
371 authscheme.processChallenge(authChallenge);
372
373 final Credentials cred = new UsernamePasswordCredentials(username, password);
374 final HttpRequest request = new BasicHttpRequest("Simple", "/");
375 final HttpContext context = new BasicHttpContext();
376 authscheme.authenticate(cred, request, context);
377 }
378
379
380
381
382 @Test(expected=AuthenticationException.class)
383 public void testDigestAuthenticationUnknownAlgo() throws Exception {
384
385
386 final String realm="realm";
387 final String username="username";
388 final String password="password";
389 final String nonce="e273f1776275974f1a120d8b92c5b3cb";
390
391 final String challenge="Digest realm=\"" + realm + "\", "
392 + "nonce=\"" + nonce + "\", "
393 + "opaque=\"SomeString\", "
394 + "stale=false, "
395 + "algorithm=stuff, "
396 + "qop=\"auth\"";
397
398 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
399
400 final DigestScheme authscheme = new DigestScheme();
401 authscheme.processChallenge(authChallenge);
402
403 final Credentials cred = new UsernamePasswordCredentials(username, password);
404 final HttpRequest request = new BasicHttpRequest("Simple", "/");
405 final HttpContext context = new BasicHttpContext();
406 authscheme.authenticate(cred, request, context);
407 }
408
409 @Test
410 public void testDigestAuthenticationWithStaleNonce() throws Exception {
411 final String challenge = "Digest realm=\"realm1\", " +
412 "nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", stale=\"true\"";
413 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
414 final AuthScheme authscheme = new DigestScheme();
415 authscheme.processChallenge(authChallenge);
416
417 Assert.assertFalse(authscheme.isComplete());
418 }
419
420 private static Map<String, String> parseAuthResponse(final Header authResponse) {
421 final String s = authResponse.getValue();
422 if (!s.startsWith("Digest ")) {
423 return null;
424 }
425 final HeaderElement[] elements = BasicHeaderValueParser.parseElements(s.substring(7), null);
426 final Map<String, String> map = new HashMap<String, String>(elements.length);
427 for (final HeaderElement element : elements) {
428 map.put(element.getName(), element.getValue());
429 }
430 return map;
431 }
432
433 @Test
434 public void testDigestNouceCount() throws Exception {
435 final String challenge1 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
436 final Header authChallenge1 = new BasicHeader(AUTH.WWW_AUTH, challenge1);
437 final HttpRequest request = new BasicHttpRequest("GET", "/");
438 final Credentials cred = new UsernamePasswordCredentials("username","password");
439 final HttpContext context = new BasicHttpContext();
440 final DigestScheme authscheme = new DigestScheme();
441 authscheme.processChallenge(authChallenge1);
442 final Header authResponse1 = authscheme.authenticate(cred, request, context);
443 final Map<String, String> table1 = parseAuthResponse(authResponse1);
444 Assert.assertEquals("00000001", table1.get("nc"));
445 final Header authResponse2 = authscheme.authenticate(cred, request, context);
446 final Map<String, String> table2 = parseAuthResponse(authResponse2);
447 Assert.assertEquals("00000002", table2.get("nc"));
448 final String challenge2 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
449 final Header authChallenge2 = new BasicHeader(AUTH.WWW_AUTH, challenge2);
450 authscheme.processChallenge(authChallenge2);
451 final Header authResponse3 = authscheme.authenticate(cred, request, context);
452 final Map<String, String> table3 = parseAuthResponse(authResponse3);
453 Assert.assertEquals("00000003", table3.get("nc"));
454 final String challenge3 = "Digest realm=\"realm1\", nonce=\"e273f1776275974f1a120d8b92c5b3cb\", qop=auth";
455 final Header authChallenge3 = new BasicHeader(AUTH.WWW_AUTH, challenge3);
456 authscheme.processChallenge(authChallenge3);
457 final Header authResponse4 = authscheme.authenticate(cred, request, context);
458 final Map<String, String> table4 = parseAuthResponse(authResponse4);
459 Assert.assertEquals("00000001", table4.get("nc"));
460 }
461
462 @Test
463 public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
464 final String challenge1 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
465 "charset=utf-8, realm=\"subnet.domain.com\"";
466 final Header authChallenge1 = new BasicHeader(AUTH.WWW_AUTH, challenge1);
467 final HttpRequest request = new BasicHttpRequest("GET", "/");
468 final Credentials cred = new UsernamePasswordCredentials("username","password");
469 final HttpContext context = new BasicHttpContext();
470 final DigestScheme authscheme = new DigestScheme();
471 authscheme.processChallenge(authChallenge1);
472 final Header authResponse1 = authscheme.authenticate(cred, request, context);
473 final Map<String, String> table1 = parseAuthResponse(authResponse1);
474 Assert.assertEquals("00000001", table1.get("nc"));
475 final String cnonce1 = authscheme.getCnonce();
476 final String sessionKey1 = authscheme.getA1();
477
478 final Header authResponse2 = authscheme.authenticate(cred, request, context);
479 final Map<String, String> table2 = parseAuthResponse(authResponse2);
480 Assert.assertEquals("00000002", table2.get("nc"));
481 final String cnonce2 = authscheme.getCnonce();
482 final String sessionKey2 = authscheme.getA1();
483
484 Assert.assertEquals(cnonce1, cnonce2);
485 Assert.assertEquals(sessionKey1, sessionKey2);
486
487 final String challenge2 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
488 "charset=utf-8, realm=\"subnet.domain.com\"";
489 final Header authChallenge2 = new BasicHeader(AUTH.WWW_AUTH, challenge2);
490 authscheme.processChallenge(authChallenge2);
491 final Header authResponse3 = authscheme.authenticate(cred, request, context);
492 final Map<String, String> table3 = parseAuthResponse(authResponse3);
493 Assert.assertEquals("00000003", table3.get("nc"));
494
495 final String cnonce3 = authscheme.getCnonce();
496 final String sessionKey3 = authscheme.getA1();
497
498 Assert.assertEquals(cnonce1, cnonce3);
499 Assert.assertEquals(sessionKey1, sessionKey3);
500
501 final String challenge3 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"fedcba0987654321\", " +
502 "charset=utf-8, realm=\"subnet.domain.com\"";
503 final Header authChallenge3 = new BasicHeader(AUTH.WWW_AUTH, challenge3);
504 authscheme.processChallenge(authChallenge3);
505 final Header authResponse4 = authscheme.authenticate(cred, request, context);
506 final Map<String, String> table4 = parseAuthResponse(authResponse4);
507 Assert.assertEquals("00000001", table4.get("nc"));
508
509 final String cnonce4 = authscheme.getCnonce();
510 final String sessionKey4 = authscheme.getA1();
511
512 Assert.assertFalse(cnonce1.equals(cnonce4));
513 Assert.assertFalse(sessionKey1.equals(sessionKey4));
514 }
515
516 @Test
517 public void testHttpEntityDigest() throws Exception {
518 final HttpEntityDigester digester = new HttpEntityDigester(MessageDigest.getInstance("MD5"));
519 Assert.assertNull(digester.getDigest());
520 digester.write('a');
521 digester.write('b');
522 digester.write('c');
523 digester.write(0xe4);
524 digester.write(0xf6);
525 digester.write(0xfc);
526 digester.write(new byte[] { 'a', 'b', 'c'});
527 Assert.assertNull(digester.getDigest());
528 digester.close();
529 Assert.assertEquals("acd2b59cd01c7737d8069015584c6cac", DigestScheme.encode(digester.getDigest()));
530 try {
531 digester.write('a');
532 Assert.fail("IOException should have been thrown");
533 } catch (final IOException ex) {
534 }
535 try {
536 digester.write(new byte[] { 'a', 'b', 'c'});
537 Assert.fail("IOException should have been thrown");
538 } catch (final IOException ex) {
539 }
540 }
541
542 @Test
543 public void testDigestAuthenticationQopAuthInt() throws Exception {
544 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
545 "qop=\"auth,auth-int\"";
546 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
547 final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
548 request.setEntity(new StringEntity("abc\u00e4\u00f6\u00fcabc", HTTP.DEF_CONTENT_CHARSET));
549 final Credentials cred = new UsernamePasswordCredentials("username","password");
550 final DigestScheme authscheme = new DigestScheme();
551 final HttpContext context = new BasicHttpContext();
552 authscheme.processChallenge(authChallenge);
553 final Header authResponse = authscheme.authenticate(cred, request, context);
554
555 Assert.assertEquals("Post:/:acd2b59cd01c7737d8069015584c6cac", authscheme.getA2());
556
557 final Map<String, String> table = parseAuthResponse(authResponse);
558 Assert.assertEquals("username", table.get("username"));
559 Assert.assertEquals("realm1", table.get("realm"));
560 Assert.assertEquals("/", table.get("uri"));
561 Assert.assertEquals("auth-int", table.get("qop"));
562 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
563 }
564
565 @Test
566 public void testDigestAuthenticationQopAuthIntNullEntity() throws Exception {
567 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
568 "qop=\"auth,auth-int\"";
569 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
570 final HttpRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
571 final Credentials cred = new UsernamePasswordCredentials("username","password");
572 final DigestScheme authscheme = new DigestScheme();
573 final HttpContext context = new BasicHttpContext();
574 authscheme.processChallenge(authChallenge);
575 final Header authResponse = authscheme.authenticate(cred, request, context);
576
577 Assert.assertEquals("Post:/:d41d8cd98f00b204e9800998ecf8427e", authscheme.getA2());
578
579 final Map<String, String> table = parseAuthResponse(authResponse);
580 Assert.assertEquals("username", table.get("username"));
581 Assert.assertEquals("realm1", table.get("realm"));
582 Assert.assertEquals("/", table.get("uri"));
583 Assert.assertEquals("auth-int", table.get("qop"));
584 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
585 }
586
587 @Test
588 public void testDigestAuthenticationQopAuthOrAuthIntNonRepeatableEntity() throws Exception {
589 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
590 "qop=\"auth,auth-int\"";
591 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
592 final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
593 request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
594 final Credentials cred = new UsernamePasswordCredentials("username","password");
595 final DigestScheme authscheme = new DigestScheme();
596 final HttpContext context = new BasicHttpContext();
597 authscheme.processChallenge(authChallenge);
598 final Header authResponse = authscheme.authenticate(cred, request, context);
599
600 Assert.assertEquals("Post:/", authscheme.getA2());
601
602 final Map<String, String> table = parseAuthResponse(authResponse);
603 Assert.assertEquals("username", table.get("username"));
604 Assert.assertEquals("realm1", table.get("realm"));
605 Assert.assertEquals("/", table.get("uri"));
606 Assert.assertEquals("auth", table.get("qop"));
607 Assert.assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
608 }
609
610 @Test
611 public void testParameterCaseSensitivity() throws Exception {
612 final String challenge = "Digest Realm=\"-\", " +
613 "nonce=\"YjYuNGYyYmJhMzUuY2I5ZDhlZDE5M2ZlZDM 1Mjk3NGJkNTIyYjgyNTcwMjQ=\", " +
614 "opaque=\"98700A3D9CE17065E2246B41035C6609\", qop=\"auth\"";
615 final Header authChallenge = new BasicHeader(AUTH.PROXY_AUTH, challenge);
616 final HttpRequest request = new BasicHttpRequest("GET", "/");
617 final Credentials cred = new UsernamePasswordCredentials("username","password");
618 final DigestScheme authscheme = new DigestScheme();
619 final HttpContext context = new BasicHttpContext();
620 authscheme.processChallenge(authChallenge);
621 Assert.assertEquals("-", authscheme.getRealm());
622
623 authscheme.authenticate(cred, request, context);
624 }
625
626 @Test(expected=AuthenticationException.class)
627 public void testDigestAuthenticationQopIntOnlyNonRepeatableEntity() throws Exception {
628 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
629 "qop=\"auth-int\"";
630 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
631 final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
632 request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
633 final Credentials cred = new UsernamePasswordCredentials("username","password");
634 final DigestScheme authscheme = new DigestScheme();
635 final HttpContext context = new BasicHttpContext();
636 authscheme.processChallenge(authChallenge);
637 authscheme.authenticate(cred, request, context);
638 }
639
640 @Test
641 public void testSerialization() throws Exception {
642 final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
643 "qop=\"auth,auth-int\"";
644 final Header authChallenge = new BasicHeader(AUTH.WWW_AUTH, challenge);
645 final DigestScheme digestScheme = new DigestScheme();
646 digestScheme.processChallenge(authChallenge);
647
648 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
649 final ObjectOutputStream out = new ObjectOutputStream(buffer);
650 out.writeObject(digestScheme);
651 out.flush();
652 final byte[] raw = buffer.toByteArray();
653 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
654 final DigestScheme authScheme = (DigestScheme) in.readObject();
655
656 Assert.assertEquals(digestScheme.getSchemeName(), authScheme.getSchemeName());
657 Assert.assertEquals(digestScheme.getRealm(), authScheme.getRealm());
658 Assert.assertEquals(digestScheme.isComplete(), authScheme.isComplete());
659 Assert.assertEquals(digestScheme.getA1(), authScheme.getA1());
660 Assert.assertEquals(digestScheme.getA2(), authScheme.getA2());
661 Assert.assertEquals(digestScheme.getCnonce(), authScheme.getCnonce());
662 }
663
664 }