B4678055.java revision 6073:cea72c2bf071
1/*
2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 4678055
27 * @library ../../../sun/net/www/httptest/
28 * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction
29 * @run main B4678055
30 * @summary Basic Authentication fails with multiple realms
31 */
32
33import java.io.*;
34import java.net.*;
35
36public class B4678055 implements HttpCallback {
37
38    static int count = 0;
39    static String authstring;
40
41    void errorReply (HttpTransaction req, String reply) throws IOException {
42        req.addResponseHeader ("Connection", "close");
43        req.addResponseHeader ("WWW-Authenticate", reply);
44        req.sendResponse (401, "Unauthorized");
45        req.orderlyClose();
46    }
47
48    void okReply (HttpTransaction req) throws IOException {
49        req.setResponseEntityBody ("Hello .");
50        req.sendResponse (200, "Ok");
51        req.orderlyClose();
52    }
53
54    public void request (HttpTransaction req) {
55        try {
56            authstring = req.getRequestHeader ("Authorization");
57            System.out.println (authstring);
58            switch (count) {
59            case 0:
60                errorReply (req, "Basic realm=\"wallyworld\"");
61                break;
62            case 1:
63                /* client stores a username/pw for wallyworld
64                 */
65                okReply (req);
66                break;
67            case 2:
68                /* emulates a server that has configured a second
69                 * realm, but by misconfiguration uses the same
70                 * realm string as the previous one.
71                 *
72                 * An alternative (more likely) scenario that shows this behavior is
73                 * the case where the password in the original realm has changed
74                 */
75                errorReply (req, "Basic realm=\"wallyworld\"");
76                break;
77            case 3:
78                /* The client replies with the username/password
79                 * from the first realm, which is wrong (unexpectedly)
80                 */
81                errorReply (req, "Basic realm=\"wallyworld\"");
82                break;
83            case 4:
84                /* The client re-prompts for a password and
85                 * we now reply with an OK. The client with the bug
86                 * will throw NPE at this point.
87                 */
88            case 5:
89                /* Repeat the OK, to make sure the same new auth string is sent */
90                okReply (req);
91                break;
92            }
93            count ++;
94        } catch (IOException e) {
95            e.printStackTrace();
96        }
97    }
98
99    static void read (InputStream is) throws IOException {
100        int c;
101        System.out.println ("reading");
102        while ((c=is.read()) != -1) {
103            System.out.write (c);
104        }
105        System.out.println ("");
106        System.out.println ("finished reading");
107    }
108
109    static boolean checkFinalAuth () {
110        return authstring.equals ("Basic dXNlcjpwYXNzMg==");
111    }
112
113    static void client (String u) throws Exception {
114        URL url = new URL (u);
115        System.out.println ("client opening connection to: " + u);
116        URLConnection urlc = url.openConnection ();
117        InputStream is = urlc.getInputStream ();
118        read (is);
119        is.close();
120    }
121
122    static TestHttpServer server;
123
124    public static void main (String[] args) throws Exception {
125        MyAuthenticator auth = new MyAuthenticator ();
126        Authenticator.setDefault (auth);
127        try {
128            server = new TestHttpServer (new B4678055(), 1, 10, 0);
129            System.out.println ("Server: listening on port: " + server.getLocalPort());
130            client ("http://localhost:"+server.getLocalPort()+"/d1/foo.html");
131            client ("http://localhost:"+server.getLocalPort()+"/d2/foo.html");
132            client ("http://localhost:"+server.getLocalPort()+"/d2/foo.html");
133        } catch (Exception e) {
134            if (server != null) {
135                server.terminate();
136            }
137            throw e;
138        }
139        int f = auth.getCount();
140        if (f != 2) {
141            except ("Authenticator was called "+f+" times. Should be 2");
142        }
143        /* this checks the authorization string corresponding to second password "pass2"*/
144        if (!checkFinalAuth()) {
145            except ("Wrong authorization string received from client");
146        }
147        server.terminate();
148    }
149
150    public static void except (String s) {
151        server.terminate();
152        throw new RuntimeException (s);
153    }
154
155    static class MyAuthenticator extends Authenticator {
156        MyAuthenticator () {
157            super ();
158        }
159
160        int count = 0;
161
162        public PasswordAuthentication getPasswordAuthentication () {
163            PasswordAuthentication pw;
164            if (count == 0) {
165                pw = new PasswordAuthentication ("user", "pass1".toCharArray());
166            } else {
167                pw = new PasswordAuthentication ("user", "pass2".toCharArray());
168            }
169            count ++;
170            return pw;
171        }
172
173        public int getCount () {
174            return (count);
175        }
176    }
177}
178