blob: e21cd869daf98f06de7977f5bdcf2c391b2ca519 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/**
25 * @test
26 * @bug 4769350
27 * @library ../../../sun/net/www/httptest/
28 * @build HttpCallback HttpServer ClosedChannelList HttpTransaction AbstractCallback
29 * @run main B4769350 server
30 * @run main B4769350 proxy
31 * @summary proxy authentication username and password caching only works in serial case
32 */
33
34import java.io.*;
35import java.net.*;
36
37public class B4769350 {
38
39 static int count = 0;
40 static boolean error = false;
41
42 static void read (InputStream is) throws IOException {
43 int c;
44 while ((c=is.read()) != -1) {
45 //System.out.write (c);
46 }
47 }
48
49 static class Client extends Thread {
50 String authority, path;
51 boolean allowerror;
52
53 Client (String authority, String path, boolean allowerror) {
54 this.authority = authority;
55 this.path = path;
56 this.allowerror = allowerror;
57 }
58
59 public void run () {
60 try {
61 URI u = new URI ("http", authority, path, null, null);
62 URL url = u.toURL();
63 URLConnection urlc = url.openConnection ();
64 InputStream is = urlc.getInputStream ();
65 read (is);
66 is.close();
67 } catch (URISyntaxException e) {
68 System.out.println (e);
69 error = true;
70 } catch (IOException e) {
71 if (!allowerror) {
72 System.out.println (e);
73 error = true;
74 }
75 }
76 }
77 }
78
79 static class CallBack extends AbstractCallback {
80
81 void errorReply (HttpTransaction req, String reply) throws IOException {
82 req.addResponseHeader ("Connection", "close");
83 req.addResponseHeader ("WWW-Authenticate", reply);
84 req.sendResponse (401, "Unauthorized");
85 req.orderlyClose();
86 }
87
88 void proxyReply (HttpTransaction req, String reply) throws IOException {
89 req.addResponseHeader ("Proxy-Authenticate", reply);
90 req.sendResponse (407, "Proxy Authentication Required");
91 }
92
93 void okReply (HttpTransaction req) throws IOException {
94 req.setResponseEntityBody ("Hello .");
95 req.sendResponse (200, "Ok");
96 req.orderlyClose();
97 }
98
99 public void request (HttpTransaction req, int count) {
100 try {
101 URI uri = req.getRequestURI();
102 String path = uri.getPath();
103 if (path.endsWith ("/t1a")) {
104 doT1a (req, count);
105 } else if (path.endsWith ("/t1b")) {
106 doT1b (req, count);
107 } else if (path.endsWith ("/t1c")) {
108 doT1c (req, count);
109 } else if (path.endsWith ("/t1d")) {
110 doT1d (req, count);
111 } else if (path.endsWith ("/t2a")) {
112 doT2a (req, count);
113 } else if (path.endsWith ("/t2b")) {
114 doT2b (req, count);
115 } else if (path.endsWith ("/t3a")) {
116 doT3a (req, count);
117 } else if (path.endsWith ("/t3b")) {
118 doT3bc (req, count);
119 } else if (path.endsWith ("/t3c")) {
120 doT3bc (req, count);
121 } else {
122 System.out.println ("unexpected request URI");
123 }
124 } catch (IOException e) {
125 e.printStackTrace();
126 }
127 }
128
129 /* T1 tests the client by sending 4 requests to 2 different realms
130 * in parallel. The client should recognise two pairs of dependent requests
131 * and execute the first of each pair in parallel. When they both succeed
132 * the second requests should be executed without calling the authenticator.
133 * The test succeeds if the authenticator was only called twice.
134 */
135 void doT1a (HttpTransaction req, int count) throws IOException {
136 switch (count) {
137 case 0:
138 errorReply (req, "Basic realm=\"realm1\"");
139 HttpServer.rendezvous ("one", 2);
140 break;
141 case 1:
142 HttpServer.waitForCondition ("cond2");
143 okReply (req);
144 break;
145 default:
146 System.out.println ("Unexpected request");
147 }
148 }
149
150
151 void doT1b (HttpTransaction req, int count) throws IOException {
152 switch (count) {
153 case 0:
154 errorReply (req, "Basic realm=\"realm2\"");
155 HttpServer.rendezvous ("one", 2);
156 HttpServer.setCondition ("cond1");
157 break;
158 case 1:
159 HttpServer.waitForCondition ("cond2");
160 okReply (req);
161 break;
162 default:
163 System.out.println ("Unexpected request");
164 }
165 }
166
167 void doT1c (HttpTransaction req, int count) throws IOException {
168 switch (count) {
169 case 0:
170 errorReply (req, "Basic realm=\"realm1\"");
171 HttpServer.rendezvous ("two", 2);
172 break;
173 case 1:
174 okReply (req);
175 break;
176 default:
177 System.out.println ("Unexpected request");
178 }
179 }
180
181 void doT1d (HttpTransaction req, int count) throws IOException {
182 switch (count) {
183 case 0:
184 errorReply (req, "Basic realm=\"realm2\"");
185 HttpServer.rendezvous ("two", 2);
186 HttpServer.setCondition ("cond2");
187 break;
188 case 1:
189 okReply (req);
190 break;
191 default:
192 System.out.println ("Unexpected request");
193 }
194 }
195
196
197 /* T2 tests to check that if initial authentication fails, the second will
198 * succeed, and the authenticator is called twice
199 */
200
201 void doT2a (HttpTransaction req, int count) throws IOException {
202 /* This will be called several times */
203 if (count == 1) {
204 HttpServer.setCondition ("T2cond1");
205 }
206 errorReply (req, "Basic realm=\"realm3\"");
207 }
208
209 void doT2b (HttpTransaction req, int count) throws IOException {
210 switch (count) {
211 case 0:
212 errorReply (req, "Basic realm=\"realm3\"");
213 break;
214 case 1:
215 okReply (req);
216 break;
217 default:
218 System.out.println ("Unexpected request");
219 }
220 }
221
222 /* T3 tests proxy and server authentication. three threads request same
223 * resource at same time. Authenticator should be called once for server
224 * and once for proxy
225 */
226 void doT3a (HttpTransaction req, int count) throws IOException {
227 switch (count) {
228 case 0:
229 proxyReply (req, "Basic realm=\"proxy\"");
230 HttpServer.setCondition ("T3cond1");
231 break;
232 case 1:
233 errorReply (req, "Basic realm=\"realm4\"");
234 break;
235 case 2:
236 okReply (req);
237 break;
238 default:
239 System.out.println ("Unexpected request");
240 }
241 }
242
243 void doT3bc (HttpTransaction req, int count) throws IOException {
244 switch (count) {
245 case 0:
246 proxyReply (req, "Basic realm=\"proxy\"");
247 break;
248 case 1:
249 okReply (req);
250 break;
251 default:
252 System.out.println ("Unexpected request");
253 }
254 }
255 };
256
257 static HttpServer server;
258 static MyAuthenticator auth = new MyAuthenticator ();
259
260 static int redirects = 4;
261
262 static Client c1,c2,c3,c4,c5,c6,c7,c8,c9;
263
264 static void doServerTests (String authority) throws Exception {
265 System.out.println ("Doing Server tests");
266 System.out.println ("T1");
267 c1 = new Client (authority, "/test/realm1/t1a", false);
268 c2 = new Client (authority, "/test/realm2/t1b", false);
269 c3 = new Client (authority, "/test/realm1/t1c", false);
270 c4 = new Client (authority, "/test/realm2/t1d", false);
271
272 c1.start(); c2.start();
273 HttpServer.waitForCondition ("cond1");
274 c3.start(); c4.start();
275 c1.join(); c2.join(); c3.join(); c4.join();
276
277 int f = auth.getCount();
278 if (f != 2) {
279 except ("Authenticator was called "+f+" times. Should be 2");
280 }
281 if (error) {
282 except ("error occurred");
283 }
284
285 auth.resetCount();
286 System.out.println ("T2");
287
288 c5 = new Client (authority, "/test/realm3/t2a", true);
289 c6 = new Client (authority, "/test/realm3/t2b", false);
290 c5.start ();
291 HttpServer.waitForCondition ("T2cond1");
292 c6.start ();
293 c5.join(); c6.join();
294
295 f = auth.getCount();
296 if (f != redirects+1) {
297 except ("Authenticator was called "+f+" times. Should be: " + redirects+1);
298 }
299 if (error) {
300 except ("error occurred");
301 }
302 }
303
304 static void doProxyTests (String authority) throws Exception {
305 System.out.println ("Doing Proxy tests");
306 c7 = new Client (authority, "/test/realm4/t3a", false);
307 c8 = new Client (authority, "/test/realm4/t3b", false);
308 c9 = new Client (authority, "/test/realm4/t3c", false);
309 c7.start ();
310 HttpServer.waitForCondition ("T3cond1");
311 c8.start ();
312 c9.start ();
313 c7.join(); c8.join(); c9.join();
314
315 int f = auth.getCount();
316 if (f != 2) {
317 except ("Authenticator was called "+f+" times. Should be: " + 2);
318 }
319 if (error) {
320 except ("error occurred");
321 }
322 }
323
324 public static void main (String[] args) throws Exception {
325 System.setProperty ("http.maxRedirects", Integer.toString (redirects));
326 System.setProperty ("http.auth.serializeRequests", "true");
327 Authenticator.setDefault (auth);
328 boolean proxy = args[0].equals ("proxy");
329 try {
330 server = new HttpServer (new CallBack(), 10, 1, 0);
331 System.out.println ("Server: listening on port: " + server.getLocalPort());
332 if (proxy) {
333 System.setProperty ("http.proxyHost", "localhost");
334 System.setProperty ("http.proxyPort",Integer.toString(server.getLocalPort()));
335 doProxyTests ("www.foo.com");
336 } else {
337 doServerTests ("localhost:"+server.getLocalPort());
338 }
339 server.terminate();
340
341 } catch (Exception e) {
342 if (server != null) {
343 server.terminate();
344 }
345 throw e;
346 }
347 }
348
349 static void pause (int millis) {
350 try {
351 Thread.sleep (millis);
352 } catch (InterruptedException e) {}
353 }
354
355 public static void except (String s) {
356 server.terminate();
357 throw new RuntimeException (s);
358 }
359
360 static class MyAuthenticator extends Authenticator {
361 MyAuthenticator () {
362 super ();
363 }
364
365 int count = 0;
366
367 public PasswordAuthentication getPasswordAuthentication () {
368 //System.out.println ("Authenticator called: " + getRequestingPrompt());
369 //try {
370 //Thread.sleep (1000);
371 //} catch (InterruptedException e) {}
372 PasswordAuthentication pw;
373 pw = new PasswordAuthentication ("user", "pass1".toCharArray());
374 count ++;
375 return pw;
376 }
377
378 public void resetCount () {
379 count = 0;
380 }
381
382 public int getCount () {
383 return (count);
384 }
385 }
386}