Path: blob/master/test/jdk/java/net/Authenticator/B6870935.java
41149 views
/*1* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 687093526* @modules java.base/sun.net.www27* @run main/othervm -Dhttp.nonProxyHosts="" -Dhttp.auth.digest.validateProxy=true B687093528* @run main/othervm -Djava.net.preferIPv6Addresses=true29* -Dhttp.nonProxyHosts="" -Dhttp.auth.digest.validateProxy=true B687093530*/3132import java.io.*;33import java.util.*;34import java.net.*;35import java.security.*;36import sun.net.www.*;3738/* This is one simple test of the RFC2617 digest authentication behavior39* It specifically tests that the client correctly checks the returned40* Authentication-Info header field from the server and throws an exception41* if the password is wrong42*/4344public class B6870935 {4546static char[] passwd = "password".toCharArray();47static String username = "user";48static String nonce = "abcdefghijklmnopqrstuvwxyz";49static String realm = "wallyworld";50static String uri = "http://www.ibm.com";51static volatile boolean error = false;5253static class DigestServer extends Thread {5455ServerSocket s;56InputStream is;57OutputStream os;58int port;5960String reply1 = "HTTP/1.1 407 Proxy Authentication Required\r\n"+61"Proxy-Authenticate: Digest realm=\""+realm+"\" domain=/ "+62"nonce=\""+nonce+"\" qop=\"auth\"\r\n\r\n";6364String reply2 = "HTTP/1.1 200 OK\r\n" +65"Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +66"Server: Apache/1.3.14 (Unix)\r\n" +67"Content-Type: text/html; charset=iso-8859-1\r\n" +68"Transfer-encoding: chunked\r\n\r\n"+69"B\r\nHelloWorld1\r\n"+70"B\r\nHelloWorld2\r\n"+71"B\r\nHelloWorld3\r\n"+72"B\r\nHelloWorld4\r\n"+73"B\r\nHelloWorld5\r\n"+74"0\r\n"+75"Proxy-Authentication-Info: ";7677DigestServer (ServerSocket y) {78s = y;79port = s.getLocalPort();80}8182public void run () {83try {84System.out.println("Server started");85Socket s1 = s.accept ();86is = s1.getInputStream ();87os = s1.getOutputStream ();88is.read ();89os.write (reply1.getBytes());90System.out.println("First response sent");91Thread.sleep (2000);92s1.close ();93System.out.println("First connection closed");9495s1 = s.accept ();96is = s1.getInputStream ();97os = s1.getOutputStream ();98// is.read ();99// need to get the cnonce out of the response100MessageHeader header = new MessageHeader (is);101String raw = header.findValue ("Proxy-Authorization");102HeaderParser parser = new HeaderParser (raw);103String cnonce = parser.findValue ("cnonce");104String cnstring = parser.findValue ("nc");105String clientrsp = parser.findValue ("response");106String expected = computeDigest(107true, username,passwd,realm,108"GET", uri, nonce, cnonce, cnstring109);110if (!expected.equals(clientrsp)) {111s1.close ();112s.close ();113error = true;114return;115}116117String reply = reply2 + getAuthorization (118realm, false, uri, "GET", cnonce,119cnstring, passwd, username120) +"\r\n";121os.write (reply.getBytes());122System.out.println("Second response sent");123Thread.sleep (2000);124s1.close ();125System.out.println("Second connection closed");126}127catch (Exception e) {128System.out.println (e);129e.printStackTrace();130} finally {131System.out.println("Server finished");132}133}134135private String getAuthorization (String realm, boolean isRequest, String uri, String method, String cnonce, String cnstring, char[] password, String username) {136String response;137138try {139response = computeDigest(isRequest, username,passwd,realm,140method, uri, nonce, cnonce, cnstring);141} catch (NoSuchAlgorithmException ex) {142return null;143}144145String value = "Digest"146+ " qop=\"auth"147+ "\", cnonce=\"" + cnonce148+ "\", rspauth=\"" + response149+ "\", nc=\"" + cnstring + "\"";150return (value+ "\r\n");151}152153private String computeDigest(154boolean isRequest, String userName, char[] password,155String realm, String connMethod,156String requestURI, String nonceString,157String cnonce, String ncValue158) throws NoSuchAlgorithmException159{160161String A1, HashA1;162163MessageDigest md = MessageDigest.getInstance("MD5");164165{166A1 = userName + ":" + realm + ":";167HashA1 = encode(A1, password, md);168}169170String A2;171if (isRequest) {172A2 = connMethod + ":" + requestURI;173} else {174A2 = ":" + requestURI;175}176String HashA2 = encode(A2, null, md);177String combo, finalHash;178179{ /* RRC2617 when qop=auth */180combo = HashA1+ ":" + nonceString + ":" + ncValue + ":" +181cnonce + ":auth:" +HashA2;182183}184finalHash = encode(combo, null, md);185return finalHash;186}187188private String encode(String src, char[] passwd, MessageDigest md) {189md.update(src.getBytes());190if (passwd != null) {191byte[] passwdBytes = new byte[passwd.length];192for (int i=0; i<passwd.length; i++)193passwdBytes[i] = (byte)passwd[i];194md.update(passwdBytes);195Arrays.fill(passwdBytes, (byte)0x00);196}197byte[] digest = md.digest();198return HexFormat.of().formatHex(digest);199}200}201202203static class MyAuthenticator extends Authenticator {204public MyAuthenticator () {205super ();206}207208public PasswordAuthentication getPasswordAuthentication ()209{210return (new PasswordAuthentication (username, passwd));211}212}213214215public static void main(String[] args) throws Exception {216int nLoops = 1;217int nSize = 10;218int port, n =0;219byte b[] = new byte[nSize];220DigestServer server;221ServerSocket sock;222223InetAddress address = InetAddress.getLoopbackAddress();224InetAddress resolved = InetAddress.getByName(address.getHostName());225System.out.println("Lookup: "226+ address + " -> \"" + address.getHostName() + "\" -> "227+ resolved);228String proxyHost = address.equals(resolved)229? address.getHostName()230: address.getHostAddress();231try {232sock = new ServerSocket();233sock.bind(new InetSocketAddress(address, 0));234port = sock.getLocalPort ();235}236catch (Exception e) {237System.out.println ("Exception: " + e);238return;239}240241server = new DigestServer(sock);242server.start ();243244try {245Authenticator.setDefault (new MyAuthenticator ());246SocketAddress addr = InetSocketAddress.createUnresolved(proxyHost, port);247Proxy proxy = new Proxy (Proxy.Type.HTTP, addr);248String s = "http://www.ibm.com";249URL url = new URL(s);250System.out.println("opening connection through proxy: " + addr);251java.net.URLConnection conURL = url.openConnection(proxy);252253InputStream in = conURL.getInputStream();254int c;255while ((c = in.read ()) != -1) {256}257in.close ();258}259catch(IOException e) {260e.printStackTrace();261error = true;262sock.close();263} finally {264server.join();265}266if (error) {267throw new RuntimeException ("Error in test");268}269}270}271272273