Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/sun/net/www/http/HttpURLConnection/DigestAuth.java
41154 views
1
/*
2
* Copyright (c) 2016, 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
import com.sun.net.httpserver.HttpExchange;
25
import com.sun.net.httpserver.HttpHandler;
26
import com.sun.net.httpserver.HttpServer;
27
import java.io.BufferedReader;
28
import java.io.InputStreamReader;
29
import java.io.IOException;
30
import java.io.InputStream;
31
import java.net.Authenticator;
32
import java.net.InetAddress;
33
import java.net.InetSocketAddress;
34
import java.net.PasswordAuthentication;
35
import java.net.URL;
36
import java.net.URLConnection;
37
import java.util.List;
38
39
/*
40
* @test
41
* @bug 8138990
42
* @summary Tests for HTTP Digest auth
43
* The impl maintains a cache for auth info,
44
* the testcases run in a separate JVM to avoid cache hits
45
* @modules jdk.httpserver
46
* @run main/othervm DigestAuth good
47
* @run main/othervm DigestAuth only_nonce
48
* @run main/othervm DigestAuth sha1
49
* @run main/othervm DigestAuth no_header
50
* @run main/othervm DigestAuth no_nonce
51
* @run main/othervm DigestAuth no_qop
52
* @run main/othervm DigestAuth invalid_alg
53
* @run main/othervm DigestAuth validate_server
54
* @run main/othervm DigestAuth validate_server_no_qop
55
*/
56
public class DigestAuth {
57
58
static final String EXPECT_FAILURE = null;
59
static final String EXPECT_DIGEST = "Digest";
60
static final String REALM = "[email protected]";
61
static final String NEXT_NONCE = "40f2e879449675f288476d772627370a";
62
63
static final String GOOD_WWW_AUTH_HEADER = "Digest "
64
+ "realm=\"[email protected]\", "
65
+ "qop=\"auth,auth-int\", "
66
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
67
+ "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
68
69
static final String GOOD_WWW_AUTH_HEADER_NO_QOP = "Digest "
70
+ "realm=\"[email protected]\", "
71
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
72
+ "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
73
74
static final String WWW_AUTH_HEADER_NO_NONCE = "Digest "
75
+ "realm=\"[email protected]\", "
76
+ "qop=\"auth,auth-int\", "
77
+ "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
78
79
static final String WWW_AUTH_HEADER_NO_QOP = "Digest "
80
+ "realm=\"[email protected]\", "
81
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
82
+ "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
83
84
static final String WWW_AUTH_HEADER_ONLY_NONCE = "Digest "
85
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"";
86
87
static final String WWW_AUTH_HEADER_SHA1 = "Digest "
88
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
89
+ "algorithm=\"SHA1\"";
90
91
static final String WWW_AUTH_HEADER_INVALID_ALGORITHM = "Digest "
92
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
93
+ "algorithm=\"SHA123\"";
94
95
static final String AUTH_INFO_HEADER_NO_QOP_FIRST =
96
"nextnonce=\"" + NEXT_NONCE + "\", "
97
+ "rspauth=\"ee85bc4315d8b18757809f1a8b9382d8\"";
98
99
static final String AUTH_INFO_HEADER_NO_QOP_SECOND =
100
"rspauth=\"12f2fa12841b3775b6054576722446b2\"";
101
102
static final String AUTH_INFO_HEADER_WRONG_DIGEST =
103
"nextnonce=\"" + NEXT_NONCE + "\", "
104
+ "rspauth=\"7327570c586207eca2afae94fc20903d\", "
105
+ "cnonce=\"0a4f113b\", "
106
+ "nc=00000001, "
107
+ "qop=auth";
108
109
public static void main(String[] args) throws Exception {
110
if (args.length == 0) {
111
throw new RuntimeException("No testcase specified");
112
}
113
String testcase = args[0];
114
115
// start a local HTTP server
116
try (LocalHttpServer server = LocalHttpServer.startServer()) {
117
118
// set authenticator
119
AuthenticatorImpl auth = new AuthenticatorImpl();
120
Authenticator.setDefault(auth);
121
122
String url = String.format("http://%s/test/", server.getAuthority());
123
124
boolean success = true;
125
switch (testcase) {
126
case "good":
127
// server returns a good WWW-Authenticate header
128
server.setWWWAuthHeader(GOOD_WWW_AUTH_HEADER);
129
success = testAuth(url, auth, EXPECT_DIGEST);
130
if (auth.lastRequestedPrompt == null ||
131
!auth.lastRequestedPrompt.equals(REALM)) {
132
System.out.println("Unexpected realm: "
133
+ auth.lastRequestedPrompt);
134
success = false;
135
}
136
break;
137
case "validate_server":
138
// enable processing Authentication-Info headers
139
System.setProperty("http.auth.digest.validateServer",
140
"true");
141
142
/* Server returns good WWW-Authenticate
143
* and Authentication-Info headers with wrong digest
144
*/
145
server.setWWWAuthHeader(GOOD_WWW_AUTH_HEADER);
146
server.setAuthInfoHeader(AUTH_INFO_HEADER_WRONG_DIGEST);
147
success = testAuth(url, auth, EXPECT_FAILURE);
148
if (auth.lastRequestedPrompt == null ||
149
!auth.lastRequestedPrompt.equals(REALM)) {
150
System.out.println("Unexpected realm: "
151
+ auth.lastRequestedPrompt);
152
success = false;
153
}
154
break;
155
case "validate_server_no_qop":
156
// enable processing Authentication-Info headers
157
System.setProperty("http.auth.digest.validateServer",
158
"true");
159
160
/* Server returns good both WWW-Authenticate
161
* and Authentication-Info headers without any qop field,
162
* so that client-nonce should not be taked into account,
163
* and connection should succeed.
164
*/
165
server.setWWWAuthHeader(GOOD_WWW_AUTH_HEADER_NO_QOP);
166
server.setAuthInfoHeader(AUTH_INFO_HEADER_NO_QOP_FIRST);
167
success = testAuth(url, auth, EXPECT_DIGEST);
168
if (auth.lastRequestedPrompt == null ||
169
!auth.lastRequestedPrompt.equals(REALM)) {
170
System.out.println("Unexpected realm: "
171
+ auth.lastRequestedPrompt);
172
success = false;
173
}
174
175
// connect again and check if nextnonce was used
176
server.setAuthInfoHeader(AUTH_INFO_HEADER_NO_QOP_SECOND);
177
success &= testAuth(url, auth, EXPECT_DIGEST);
178
if (!NEXT_NONCE.equals(server.lastRequestedNonce)) {
179
System.out.println("Unexpected next nonce: "
180
+ server.lastRequestedNonce);
181
success = false;
182
}
183
break;
184
case "only_nonce":
185
/* Server returns a good WWW-Authenticate header
186
* which contains only nonce (no realm set).
187
*
188
* Realm from WWW-Authenticate header is passed to
189
* authenticator which can use it as a prompt
190
* when it asks a user for credentials.
191
*
192
* It's fine if an HTTP client doesn't fail if no realm set,
193
* and delegates making a decision to authenticator/user.
194
*/
195
server.setWWWAuthHeader(WWW_AUTH_HEADER_ONLY_NONCE);
196
success = testAuth(url, auth, EXPECT_DIGEST);
197
if (auth.lastRequestedPrompt != null &&
198
!auth.lastRequestedPrompt.trim().isEmpty()) {
199
System.out.println("Unexpected realm: "
200
+ auth.lastRequestedPrompt);
201
success = false;
202
}
203
break;
204
case "sha1":
205
// server returns a good WWW-Authenticate header with SHA-1
206
server.setWWWAuthHeader(WWW_AUTH_HEADER_SHA1);
207
success = testAuth(url, auth, EXPECT_DIGEST);
208
break;
209
case "no_header":
210
// server returns no WWW-Authenticate header
211
success = testAuth(url, auth, EXPECT_FAILURE);
212
if (auth.lastRequestedScheme != null) {
213
System.out.println("Unexpected scheme: "
214
+ auth.lastRequestedScheme);
215
success = false;
216
}
217
break;
218
case "no_nonce":
219
// server returns a wrong WWW-Authenticate header (no nonce)
220
server.setWWWAuthHeader(WWW_AUTH_HEADER_NO_NONCE);
221
success = testAuth(url, auth, EXPECT_FAILURE);
222
break;
223
case "invalid_alg":
224
// server returns a wrong WWW-Authenticate header
225
// (invalid hash algorithm)
226
server.setWWWAuthHeader(WWW_AUTH_HEADER_INVALID_ALGORITHM);
227
success = testAuth(url, auth, EXPECT_FAILURE);
228
break;
229
case "no_qop":
230
// server returns a good WWW-Authenticate header
231
// without QOPs
232
server.setWWWAuthHeader(WWW_AUTH_HEADER_NO_QOP);
233
success = testAuth(url, auth, EXPECT_DIGEST);
234
break;
235
default:
236
throw new RuntimeException("Unexpected testcase: "
237
+ testcase);
238
}
239
240
if (!success) {
241
throw new RuntimeException("Test failed");
242
}
243
}
244
245
System.out.println("Test passed");
246
}
247
248
static boolean testAuth(String url, AuthenticatorImpl auth,
249
String expectedScheme) {
250
251
try {
252
System.out.printf("Connect to %s, expected auth scheme is '%s'%n",
253
url, expectedScheme);
254
load(url);
255
256
if (expectedScheme == null) {
257
System.out.println("Unexpected successful connection");
258
return false;
259
}
260
261
System.out.printf("Actual auth scheme is '%s'%n",
262
auth.lastRequestedScheme);
263
if (!expectedScheme.equalsIgnoreCase(auth.lastRequestedScheme)) {
264
System.out.println("Unexpected auth scheme");
265
return false;
266
}
267
} catch (IOException e) {
268
if (expectedScheme != null) {
269
System.out.println("Unexpected exception: " + e);
270
e.printStackTrace(System.out);
271
return false;
272
}
273
System.out.println("Expected exception: " + e);
274
}
275
276
return true;
277
}
278
279
static void load(String url) throws IOException {
280
URLConnection conn = new URL(url).openConnection();
281
conn.setUseCaches(false);
282
try (BufferedReader reader = new BufferedReader(
283
new InputStreamReader(conn.getInputStream()))) {
284
285
String line = reader.readLine();
286
if (line == null) {
287
throw new IOException("Couldn't read response");
288
}
289
do {
290
System.out.println(line);
291
} while ((line = reader.readLine()) != null);
292
}
293
}
294
295
private static class AuthenticatorImpl extends Authenticator {
296
297
private String lastRequestedScheme;
298
private String lastRequestedPrompt;
299
300
@Override
301
public PasswordAuthentication getPasswordAuthentication() {
302
lastRequestedScheme = getRequestingScheme();
303
lastRequestedPrompt = getRequestingPrompt();
304
System.out.println("AuthenticatorImpl: requested "
305
+ lastRequestedScheme);
306
307
return new PasswordAuthentication("Mufasa",
308
"Circle Of Life".toCharArray());
309
}
310
}
311
312
// local HTTP server which pretends to support HTTP Digest auth
313
static class LocalHttpServer implements HttpHandler, AutoCloseable {
314
315
private final HttpServer server;
316
private volatile String wwwAuthHeader = null;
317
private volatile String authInfoHeader = null;
318
private volatile String lastRequestedNonce;
319
320
private LocalHttpServer(HttpServer server) {
321
this.server = server;
322
}
323
324
public String getAuthority() {
325
InetAddress address = server.getAddress().getAddress();
326
String hostaddr = address.isAnyLocalAddress()
327
? "localhost" : address.getHostAddress();
328
if (hostaddr.indexOf(':') > -1) {
329
hostaddr = "[" + hostaddr + "]";
330
}
331
return hostaddr + ":" + getPort();
332
}
333
334
void setWWWAuthHeader(String wwwAuthHeader) {
335
this.wwwAuthHeader = wwwAuthHeader;
336
}
337
338
void setAuthInfoHeader(String authInfoHeader) {
339
this.authInfoHeader = authInfoHeader;
340
}
341
342
static LocalHttpServer startServer() throws IOException {
343
InetAddress loopback = InetAddress.getLoopbackAddress();
344
HttpServer httpServer = HttpServer.create(
345
new InetSocketAddress(loopback, 0), 0);
346
LocalHttpServer localHttpServer = new LocalHttpServer(httpServer);
347
localHttpServer.start();
348
349
return localHttpServer;
350
}
351
352
void start() {
353
server.createContext("/test", this);
354
server.start();
355
System.out.println("HttpServer: started on port " + getAuthority());
356
}
357
358
void stop() {
359
server.stop(0);
360
System.out.println("HttpServer: stopped");
361
}
362
363
int getPort() {
364
return server.getAddress().getPort();
365
}
366
367
@Override
368
public void handle(HttpExchange t) throws IOException {
369
System.out.println("HttpServer: handle connection");
370
371
// read a request
372
try (InputStream is = t.getRequestBody()) {
373
while (is.read() > 0);
374
}
375
376
try {
377
List<String> headers = t.getRequestHeaders()
378
.get("Authorization");
379
String header = "";
380
if (headers != null && !headers.isEmpty()) {
381
header = headers.get(0).trim().toLowerCase();
382
}
383
if (header.startsWith("digest")) {
384
if (authInfoHeader != null) {
385
t.getResponseHeaders().add("Authentication-Info",
386
authInfoHeader);
387
}
388
lastRequestedNonce = findParameter(header, "nonce");
389
byte[] output = "hello".getBytes();
390
t.sendResponseHeaders(200, output.length);
391
t.getResponseBody().write(output);
392
System.out.println("HttpServer: return 200");
393
} else {
394
if (wwwAuthHeader != null) {
395
t.getResponseHeaders().add(
396
"WWW-Authenticate", wwwAuthHeader);
397
}
398
byte[] output = "forbidden".getBytes();
399
t.sendResponseHeaders(401, output.length);
400
t.getResponseBody().write(output);
401
System.out.println("HttpServer: return 401");
402
}
403
} catch (IOException e) {
404
System.out.println("HttpServer: exception: " + e);
405
System.out.println("HttpServer: return 500");
406
t.sendResponseHeaders(500, 0);
407
} finally {
408
t.close();
409
}
410
}
411
412
private static String findParameter(String header, String name) {
413
name = name.toLowerCase();
414
if (header != null) {
415
String[] params = header.split("\\s");
416
for (String param : params) {
417
param = param.trim().toLowerCase();
418
if (param.startsWith(name)) {
419
String[] parts = param.split("=");
420
if (parts.length > 1) {
421
return parts[1]
422
.replaceAll("\"", "").replaceAll(",", "");
423
}
424
}
425
}
426
}
427
return null;
428
}
429
430
@Override
431
public void close() {
432
stop();
433
}
434
}
435
}
436
437