Skip to content

Commit b87a7e9

Browse files
nizarbenallajaikiran
authored andcommitted
8144100: Incorrect case-sensitive equality in com.sun.net.httpserver.BasicAuthenticator
Reviewed-by: jpai, dfuchs
1 parent 1dac34f commit b87a7e9

File tree

2 files changed

+120
-2
lines changed

2 files changed

+120
-2
lines changed

src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -118,7 +118,7 @@ public Result authenticate (HttpExchange t)
118118
return new Authenticator.Retry (401);
119119
}
120120
int sp = auth.indexOf (' ');
121-
if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) {
121+
if (sp == -1 || !auth.substring(0, sp).equalsIgnoreCase("Basic")) {
122122
return new Authenticator.Failure (401);
123123
}
124124
byte[] b = Base64.getDecoder().decode(auth.substring(sp+1));
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (c) 2024, 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 8144100
27+
* @summary checking token sent by client should be done in case-insensitive manner
28+
* @run main BasicAuthToken
29+
*/
30+
31+
import java.io.BufferedReader;
32+
import java.io.BufferedWriter;
33+
import java.io.InputStreamReader;
34+
import java.io.OutputStreamWriter;
35+
import java.net.InetAddress;
36+
import java.net.InetSocketAddress;
37+
import java.net.Socket;
38+
import java.util.Base64;
39+
import com.sun.net.httpserver.Authenticator;
40+
import com.sun.net.httpserver.BasicAuthenticator;
41+
import com.sun.net.httpserver.HttpServer;
42+
43+
public class BasicAuthToken {
44+
private static final String CRLF = "\r\n";
45+
private static final String someContext = "/test";
46+
47+
public static void main(String[] args) throws Exception {
48+
HttpServer server = server();
49+
try {
50+
client(server.getAddress().getPort());
51+
} finally {
52+
server.stop(0);
53+
}
54+
}
55+
56+
static HttpServer server() throws Exception {
57+
String realm = "someRealm";
58+
ServerAuthenticator authenticator = new ServerAuthenticator(realm);
59+
HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
60+
server.createContext(someContext, exchange -> {
61+
if (authenticator.authenticate(exchange) instanceof Authenticator.Failure) {
62+
exchange.sendResponseHeaders(401, -1);
63+
exchange.close();
64+
return;
65+
}
66+
exchange.sendResponseHeaders(200, -1);
67+
exchange.close();
68+
}).setAuthenticator(authenticator);
69+
server.start();
70+
return server;
71+
}
72+
73+
static void client(int port) throws Exception {
74+
try (Socket socket = new Socket(InetAddress.getLoopbackAddress(), port)) {
75+
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
76+
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
77+
String credentials = "username:password";
78+
String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes());
79+
writer.write("GET " + someContext + " HTTP/1.1" + CRLF);
80+
writer.write("Host: localhost:" + port + CRLF);
81+
writer.write("User-Agent: Java/" + System.getProperty("java.version") + CRLF);
82+
writer.write("Authorization: BAsIc " + encodedCredentials + CRLF);
83+
writer.write(CRLF);
84+
writer.flush();
85+
86+
System.err.println("Server response");
87+
String statusLine = reader.readLine();
88+
System.err.println(statusLine);
89+
90+
if (!statusLine.startsWith("HTTP/1.1 200")) {
91+
throw new RuntimeException("unexpected status line: " + statusLine);
92+
}
93+
if (!ServerAuthenticator.wasChecked()) {
94+
throw new RuntimeException("Authenticator wasn't invoked");
95+
}
96+
}
97+
}
98+
99+
100+
static class ServerAuthenticator extends BasicAuthenticator {
101+
private static volatile boolean invoked = false;
102+
103+
ServerAuthenticator(String realm) {
104+
super(realm);
105+
}
106+
107+
public static boolean wasChecked() {
108+
return invoked;
109+
}
110+
111+
@Override
112+
public boolean checkCredentials(String username, String password) {
113+
String validUsername = "username", validPassword = "password";
114+
invoked = true;
115+
return username.equals(validUsername) && password.equals(validPassword);
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)