1 /*
2  * Copyright (c) 2019, 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 8217237
27  * @library /test/lib
28  * @modules java.net.http
29  * @run main/othervm AuthSchemesTest
30  * @summary HttpClient does not deal well with multi-valued WWW-Authenticate challenge headers
31  */
32 
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.net.*;
37 import java.net.Authenticator;
38 import java.net.http.HttpClient;
39 import java.net.http.HttpRequest;
40 import java.net.http.HttpResponse;
41 import jdk.test.lib.net.URIBuilder;
42 
43 public class AuthSchemesTest {
44     static class BasicServer extends Thread {
45 
46         ServerSocket server;
47 
48         Socket s;
49         InputStream is;
50         OutputStream os;
51         static final String RESPONSE = "Hello world";
52         static final String respLength = Integer.toString(RESPONSE.length());
53         static final String realm = "wally world";
54 
55         String reply1 = "HTTP/1.1 401 Unauthorized\r\n"+
56                 "WWW-Authenticate: BarScheme\r\n" +
57                 "WWW-Authenticate: FooScheme realm=\""+realm+"\"\r\n" +
58                 "WWW-Authenticate: Basic realm=\""+realm+"\"\r\n" +
59                 "WWW-Authenticate: WoofScheme\r\n\r\n";
60 
61         String reply2 = "HTTP/1.1 200 OK\r\n"+
62                 "Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
63                 "Server: Apache/1.3.14 (Unix)\r\n" +
64                 "Connection: close\r\n" +
65                 "Content-Type: text/html; charset=iso-8859-1\r\n" +
66                 "Content-Length: " + respLength + "\r\n\r\n";
67 
BasicServer(ServerSocket s)68         BasicServer(ServerSocket s) {
69             server = s;
70         }
71 
response()72         String response() {
73             return RESPONSE;
74         }
75 
readAll(Socket s)76         void readAll(Socket s) throws IOException {
77             byte[] buf = new byte [128];
78             InputStream is = s.getInputStream();
79             s.setSoTimeout(1000);
80             try {
81                 while (is.read(buf) > 0) ;
82             } catch (SocketTimeoutException x) { }
83         }
84 
run()85         public void run() {
86             try {
87                 System.out.println("Server 1: accept");
88                 s = server.accept();
89                 System.out.println("accepted");
90                 os = s.getOutputStream();
91                 os.write(reply1.getBytes());
92                 readAll(s);
93                 s.close();
94 
95                 System.out.println("Server 2: accept");
96                 s = server.accept();
97                 System.out.println("accepted");
98                 os = s.getOutputStream();
99                 os.write((reply2+RESPONSE).getBytes());
100                 readAll(s);
101                 s.close();
102 
103             }
104             catch (Exception e) {
105                 System.out.println(e);
106             }
107             finished();
108         }
109 
110         boolean isfinished = false;
111 
finished()112         public synchronized void finished() {
113             isfinished = true;
114             notifyAll();
115         }
116 
waitforfinish()117         public synchronized void waitforfinish() {
118             while (!isfinished) {
119                 try {
120                     wait();
121                 } catch (InterruptedException e) {
122                     e.printStackTrace();
123                 }
124             }
125         }
126     }
127 
128     static class Auth extends Authenticator {
getPasswordAuthentication()129         protected PasswordAuthentication getPasswordAuthentication() {
130             return new PasswordAuthentication("user", new char[] {'a','b','c'});
131         }
132     }
133 
main(String[] args)134     public static void main(String[] args) throws Exception {
135         ServerSocket serversocket = null;
136         BasicServer server = null;
137         Auth authenticator = new Auth();
138 
139         serversocket = new ServerSocket(0, 10, InetAddress.getLoopbackAddress());
140         int port = serversocket.getLocalPort();
141         server = new BasicServer(serversocket);
142 
143         HttpClient client = HttpClient.newBuilder()
144                 .authenticator(authenticator)
145                 .build();
146         server.start();
147         URI uri = URIBuilder.newBuilder()
148             .scheme("http")
149             .loopback()
150             .port(port)
151             .path("/foo")
152             .build();
153         System.out.println("URI: " + uri);
154         HttpRequest request = HttpRequest.newBuilder(uri)
155                 .GET()
156                 .build();
157         HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
158         if (response.statusCode() != 200 || !response.body().equals(server.response())) {
159             System.out.println("Status code = " + response.statusCode());
160             serversocket.close();
161             throw new RuntimeException("Test failed");
162         }
163         serversocket.close();
164         server.waitforfinish();
165         System.out.println("OK");
166     }
167 }
168