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
28
29 package org.apache.commons.httpclient.auth;
30
31 import java.io.IOException;
32 import java.util.Map;
33
34 import org.apache.commons.httpclient.FakeHttpMethod;
35 import org.apache.commons.httpclient.Header;
36 import org.apache.commons.httpclient.HttpClient;
37 import org.apache.commons.httpclient.HttpStatus;
38 import org.apache.commons.httpclient.HttpVersion;
39 import org.apache.commons.httpclient.UsernamePasswordCredentials;
40 import org.apache.commons.httpclient.protocol.Protocol;
41 import org.apache.commons.httpclient.server.HttpService;
42 import org.apache.commons.httpclient.server.RequestLine;
43 import org.apache.commons.httpclient.server.SimpleHttpServer;
44 import org.apache.commons.httpclient.server.SimpleRequest;
45 import org.apache.commons.httpclient.server.SimpleResponse;
46
47 import junit.framework.Test;
48 import junit.framework.TestCase;
49 import junit.framework.TestSuite;
50
51 /***
52 * Test Methods for DigestScheme Authentication.
53 *
54 * @author Rodney Waldhoff
55 * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
56 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
57 */
58 public class TestDigestAuth extends TestCase {
59
60
61 public TestDigestAuth(String testName) {
62 super(testName);
63 }
64
65
66 public static void main(String args[]) {
67 String[] testCaseName = { TestDigestAuth.class.getName() };
68 junit.textui.TestRunner.main(testCaseName);
69 }
70
71
72
73 public static Test suite() {
74 return new TestSuite(TestDigestAuth.class);
75 }
76
77 public void testDigestAuthenticationWithNoRealm() throws Exception {
78 String challenge = "Digest";
79 try {
80 AuthScheme authscheme = new DigestScheme();
81 authscheme.processChallenge(challenge);
82 fail("Should have thrown MalformedChallengeException");
83 } catch(MalformedChallengeException e) {
84
85 }
86 }
87
88 public void testDigestAuthenticationWithNoRealm2() throws Exception {
89 String challenge = "Digest ";
90 try {
91 AuthScheme authscheme = new DigestScheme();
92 authscheme.processChallenge(challenge);
93 fail("Should have thrown MalformedChallengeException");
94 } catch(MalformedChallengeException e) {
95
96 }
97 }
98
99 public void testDigestAuthenticationWithDefaultCreds() throws Exception {
100 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
101 FakeHttpMethod method = new FakeHttpMethod("/");
102 UsernamePasswordCredentials cred = new UsernamePasswordCredentials("username","password");
103 AuthScheme authscheme = new DigestScheme();
104 authscheme.processChallenge(challenge);
105 String response = authscheme.authenticate(cred, method);
106 Map table = AuthChallengeParser.extractParams(response);
107 assertEquals("username", table.get("username"));
108 assertEquals("realm1", table.get("realm"));
109 assertEquals("/", table.get("uri"));
110 assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
111 assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
112 }
113
114 public void testDigestAuthentication() throws Exception {
115 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
116 UsernamePasswordCredentials cred = new UsernamePasswordCredentials("username","password");
117 FakeHttpMethod method = new FakeHttpMethod("/");
118 AuthScheme authscheme = new DigestScheme();
119 authscheme.processChallenge(challenge);
120 String response = authscheme.authenticate(cred, method);
121 Map table = AuthChallengeParser.extractParams(response);
122 assertEquals("username", table.get("username"));
123 assertEquals("realm1", table.get("realm"));
124 assertEquals("/", table.get("uri"));
125 assertEquals("f2a3f18799759d4f1a1c068b92b573cb", table.get("nonce"));
126 assertEquals("e95a7ddf37c2eab009568b1ed134f89a", table.get("response"));
127 }
128
129 public void testDigestAuthenticationWithMultipleRealms() throws Exception {
130 String challenge1 = "Digest realm=\"realm1\", nonce=\"abcde\"";
131 String challenge2 = "Digest realm=\"realm2\", nonce=\"123546\"";
132 UsernamePasswordCredentials cred = new UsernamePasswordCredentials("username","password");
133 UsernamePasswordCredentials cred2 = new UsernamePasswordCredentials("uname2","password2");
134
135 FakeHttpMethod method = new FakeHttpMethod("/");
136 AuthScheme authscheme1 = new DigestScheme();
137 authscheme1.processChallenge(challenge1);
138 String response1 = authscheme1.authenticate(cred, method);
139 Map table = AuthChallengeParser.extractParams(response1);
140 assertEquals("username", table.get("username"));
141 assertEquals("realm1", table.get("realm"));
142 assertEquals("/", table.get("uri"));
143 assertEquals("abcde", table.get("nonce"));
144 assertEquals("786f500303eac1478f3c2865e676ed68", table.get("response"));
145
146 AuthScheme authscheme2 = new DigestScheme();
147 authscheme2.processChallenge(challenge2);
148 String response2 = authscheme2.authenticate(cred2, method);
149 table = AuthChallengeParser.extractParams(response2);
150 assertEquals("uname2", table.get("username"));
151 assertEquals("realm2", table.get("realm"));
152 assertEquals("/", table.get("uri"));
153 assertEquals("123546", table.get("nonce"));
154 assertEquals("0283edd9ef06a38b378b3b74661391e9", table.get("response"));
155 }
156
157 /***
158 * Test digest authentication using the MD5-sess algorithm.
159 */
160 public void testDigestAuthenticationMD5Sess() throws Exception {
161
162
163 String realm="realm";
164 String username="username";
165 String password="password";
166 String nonce="e273f1776275974f1a120d8b92c5b3cb";
167
168 String challenge="Digest realm=\"" + realm + "\", "
169 + "nonce=\"" + nonce + "\", "
170 + "opaque=\"SomeString\", "
171 + "stale=false, "
172 + "algorithm=MD5-sess, "
173 + "qop=\"auth,auth-int\"";
174
175 UsernamePasswordCredentials cred =
176 new UsernamePasswordCredentials(username, password);
177 FakeHttpMethod method = new FakeHttpMethod("/");
178
179 AuthScheme authscheme = new DigestScheme();
180 authscheme.processChallenge(challenge);
181 String response = authscheme.authenticate(cred, method);
182
183 Map table = AuthChallengeParser.extractParams(response);
184 assertEquals(username, table.get("username"));
185 assertEquals(realm, table.get("realm"));
186 assertEquals("MD5-sess", table.get("algorithm"));
187 assertEquals("/", table.get("uri"));
188 assertEquals(nonce, table.get("nonce"));
189 assertEquals(1, Integer.parseInt((String) table.get("nc"),16));
190 assertTrue(null != table.get("cnonce"));
191 assertEquals("SomeString", table.get("opaque"));
192 assertEquals("auth", table.get("qop"));
193
194 assertTrue(null != table.get("response"));
195 }
196
197 /***
198 * Test digest authentication using the MD5-sess algorithm.
199 */
200 public void testDigestAuthenticationMD5SessNoQop() throws Exception {
201
202
203 String realm="realm";
204 String username="username";
205 String password="password";
206 String nonce="e273f1776275974f1a120d8b92c5b3cb";
207
208 String challenge="Digest realm=\"" + realm + "\", "
209 + "nonce=\"" + nonce + "\", "
210 + "opaque=\"SomeString\", "
211 + "stale=false, "
212 + "algorithm=MD5-sess";
213
214 UsernamePasswordCredentials cred =
215 new UsernamePasswordCredentials(username, password);
216 FakeHttpMethod method = new FakeHttpMethod("/");
217
218 AuthScheme authscheme = new DigestScheme();
219 authscheme.processChallenge(challenge);
220 String response = authscheme.authenticate(cred, method);
221
222 Map table = AuthChallengeParser.extractParams(response);
223 assertEquals(username, table.get("username"));
224 assertEquals(realm, table.get("realm"));
225 assertEquals("MD5-sess", table.get("algorithm"));
226 assertEquals("/", table.get("uri"));
227 assertEquals(nonce, table.get("nonce"));
228 assertTrue(null == table.get("nc"));
229 assertEquals("SomeString", table.get("opaque"));
230 assertTrue(null == table.get("qop"));
231
232 assertTrue(null != table.get("response"));
233 }
234
235 /***
236 * Test digest authentication with invalud qop value
237 */
238 public void testDigestAuthenticationMD5SessInvalidQop() throws Exception {
239
240
241 String realm="realm";
242 String username="username";
243 String password="password";
244 String nonce="e273f1776275974f1a120d8b92c5b3cb";
245
246 String challenge="Digest realm=\"" + realm + "\", "
247 + "nonce=\"" + nonce + "\", "
248 + "opaque=\"SomeString\", "
249 + "stale=false, "
250 + "algorithm=MD5-sess, "
251 + "qop=\"jakarta\"";
252
253 UsernamePasswordCredentials cred =
254 new UsernamePasswordCredentials(username, password);
255 try {
256 AuthScheme authscheme = new DigestScheme();
257 authscheme.processChallenge(challenge);
258 fail("MalformedChallengeException exception expected due to invalid qop value");
259 } catch(MalformedChallengeException e) {
260 }
261 }
262
263 private class StaleNonceService implements HttpService {
264
265 public StaleNonceService() {
266 super();
267 }
268
269 public boolean process(final SimpleRequest request, final SimpleResponse response)
270 throws IOException
271 {
272 RequestLine requestLine = request.getRequestLine();
273 HttpVersion ver = requestLine.getHttpVersion();
274 Header auth = request.getFirstHeader("Authorization");
275 if (auth == null) {
276 response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
277 response.addHeader(new Header("WWW-Authenticate",
278 "Digest realm=\"realm1\", nonce=\"ABC123\""));
279 response.setBodyString("Authorization required");
280 return true;
281 } else {
282 Map table = AuthChallengeParser.extractParams(auth.getValue());
283 String nonce = (String)table.get("nonce");
284 if (nonce.equals("ABC123")) {
285 response.setStatusLine(ver, HttpStatus.SC_UNAUTHORIZED);
286 response.addHeader(new Header("WWW-Authenticate",
287 "Digest realm=\"realm1\", nonce=\"321CBA\", stale=\"true\""));
288 response.setBodyString("Authorization required");
289 return true;
290 } else {
291 response.setStatusLine(ver, HttpStatus.SC_OK);
292 response.setBodyString("Authorization successful");
293 return true;
294 }
295 }
296 }
297 }
298
299
300 public void testDigestAuthenticationWithStaleNonce() throws Exception {
301
302 SimpleHttpServer server = new SimpleHttpServer();
303 server.setTestname(getName());
304 server.setHttpService(new StaleNonceService());
305
306
307 HttpClient client = new HttpClient();
308 client.getHostConfiguration().setHost(
309 server.getLocalAddress(), server.getLocalPort(),
310 Protocol.getProtocol("http"));
311
312 client.getState().setCredentials(AuthScope.ANY,
313 new UsernamePasswordCredentials("username","password"));
314
315 FakeHttpMethod httpget = new FakeHttpMethod("/");
316 try {
317 client.executeMethod(httpget);
318 } finally {
319 httpget.releaseConnection();
320 }
321 assertNotNull(httpget.getStatusLine());
322 assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
323 Map table = AuthChallengeParser.extractParams(
324 httpget.getRequestHeader("Authorization").getValue());
325 assertEquals("username", table.get("username"));
326 assertEquals("realm1", table.get("realm"));
327 assertEquals("/", table.get("uri"));
328 assertEquals("321CBA", table.get("nonce"));
329 assertEquals("7f5948eefa115296e9279225041527b3", table.get("response"));
330 server.destroy();
331 }
332
333 }