diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java index a240fa725d4..440d80d3b1a 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,7 +118,7 @@ public abstract class BasicAuthenticator extends Authenticator { return new Authenticator.Retry (401); } int sp = auth.indexOf (' '); - if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) { + if (sp == -1 || !auth.substring(0, sp).equalsIgnoreCase("Basic")) { return new Authenticator.Failure (401); } byte[] b = Base64.getDecoder().decode(auth.substring(sp+1)); diff --git a/test/jdk/com/sun/net/httpserver/BasicAuthToken.java b/test/jdk/com/sun/net/httpserver/BasicAuthToken.java new file mode 100644 index 00000000000..a393ac4c5dd --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/BasicAuthToken.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8144100 + * @summary checking token sent by client should be done in case-insensitive manner + * @run main BasicAuthToken + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Base64; +import com.sun.net.httpserver.Authenticator; +import com.sun.net.httpserver.BasicAuthenticator; +import com.sun.net.httpserver.HttpServer; + +public class BasicAuthToken { + private static final String CRLF = "\r\n"; + private static final String someContext = "/test"; + + public static void main(String[] args) throws Exception { + HttpServer server = server(); + try { + client(server.getAddress().getPort()); + } finally { + server.stop(0); + } + } + + static HttpServer server() throws Exception { + String realm = "someRealm"; + ServerAuthenticator authenticator = new ServerAuthenticator(realm); + HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + server.createContext(someContext, exchange -> { + if (authenticator.authenticate(exchange) instanceof Authenticator.Failure) { + exchange.sendResponseHeaders(401, -1); + exchange.close(); + return; + } + exchange.sendResponseHeaders(200, -1); + exchange.close(); + }).setAuthenticator(authenticator); + server.start(); + return server; + } + + static void client(int port) throws Exception { + try (Socket socket = new Socket(InetAddress.getLoopbackAddress(), port)) { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String credentials = "username:password"; + String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes()); + writer.write("GET " + someContext + " HTTP/1.1" + CRLF); + writer.write("Host: localhost:" + port + CRLF); + writer.write("User-Agent: Java/" + System.getProperty("java.version") + CRLF); + writer.write("Authorization: BAsIc " + encodedCredentials + CRLF); + writer.write(CRLF); + writer.flush(); + + System.err.println("Server response"); + String statusLine = reader.readLine(); + System.err.println(statusLine); + + if (!statusLine.startsWith("HTTP/1.1 200")) { + throw new RuntimeException("unexpected status line: " + statusLine); + } + if (!ServerAuthenticator.wasChecked()) { + throw new RuntimeException("Authenticator wasn't invoked"); + } + } + } + + + static class ServerAuthenticator extends BasicAuthenticator { + private static volatile boolean invoked = false; + + ServerAuthenticator(String realm) { + super(realm); + } + + public static boolean wasChecked() { + return invoked; + } + + @Override + public boolean checkCredentials(String username, String password) { + String validUsername = "username", validPassword = "password"; + invoked = true; + return username.equals(validUsername) && password.equals(validPassword); + } + } +}