1710N/A/*
2362N/A * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
1710N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1710N/A *
1710N/A * This code is free software; you can redistribute it and/or modify it
1710N/A * under the terms of the GNU General Public License version 2 only, as
1710N/A * published by the Free Software Foundation.
1710N/A *
1710N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1710N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1710N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1710N/A * version 2 for more details (a copy is included in the LICENSE file that
1710N/A * accompanied this code).
1710N/A *
1710N/A * You should have received a copy of the GNU General Public License version
1710N/A * 2 along with this work; if not, write to the Free Software Foundation,
1710N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1710N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
1710N/A */
1710N/A
1710N/A/**
1710N/A * @test
1710N/A * @bug 6870935
1710N/A * @run main/othervm -Dhttp.nonProxyHosts="" -Dhttp.auth.digest.validateProxy=true B6870935
1710N/A */
1710N/A
1710N/Aimport java.io.*;
1710N/Aimport java.util.*;
1710N/Aimport java.net.*;
1710N/Aimport java.security.*;
1710N/Aimport sun.net.www.*;
1710N/A
1710N/A/* This is one simple test of the RFC2617 digest authentication behavior
1710N/A * It specifically tests that the client correctly checks the returned
1710N/A * Authentication-Info header field from the server and throws an exception
1710N/A * if the password is wrong
1710N/A */
1710N/A
1710N/Apublic class B6870935 {
1710N/A
1710N/A static char[] passwd = "password".toCharArray();
1710N/A static String username = "user";
1710N/A static String nonce = "abcdefghijklmnopqrstuvwxyz";
1710N/A static String realm = "wallyworld";
1710N/A static String uri = "http://www.ibm.com";
1710N/A static volatile boolean error = false;
1710N/A
1710N/A static class DigestServer extends Thread {
1710N/A
1710N/A ServerSocket s;
1710N/A InputStream is;
1710N/A OutputStream os;
1710N/A int port;
1710N/A
1710N/A String reply1 = "HTTP/1.1 407 Proxy Authentication Required\r\n"+
1710N/A "Proxy-Authenticate: Digest realm=\""+realm+"\" domain=/ "+
1710N/A "nonce=\""+nonce+"\" qop=\"auth\"\r\n\r\n";
1710N/A
1710N/A String reply2 = "HTTP/1.1 200 OK\r\n" +
1710N/A "Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" +
1710N/A "Server: Apache/1.3.14 (Unix)\r\n" +
1710N/A "Content-Type: text/html; charset=iso-8859-1\r\n" +
1710N/A "Transfer-encoding: chunked\r\n\r\n"+
1710N/A "B\r\nHelloWorld1\r\n"+
1710N/A "B\r\nHelloWorld2\r\n"+
1710N/A "B\r\nHelloWorld3\r\n"+
1710N/A "B\r\nHelloWorld4\r\n"+
1710N/A "B\r\nHelloWorld5\r\n"+
1710N/A "0\r\n"+
1710N/A "Proxy-Authentication-Info: ";
1710N/A
1710N/A DigestServer (ServerSocket y) {
1710N/A s = y;
1710N/A port = s.getLocalPort();
1710N/A }
1710N/A
1710N/A public void run () {
1710N/A try {
1710N/A Socket s1 = s.accept ();
1710N/A is = s1.getInputStream ();
1710N/A os = s1.getOutputStream ();
1710N/A is.read ();
1710N/A os.write (reply1.getBytes());
1710N/A Thread.sleep (2000);
1710N/A s1.close ();
1710N/A
1710N/A s1 = s.accept ();
1710N/A is = s1.getInputStream ();
1710N/A os = s1.getOutputStream ();
1710N/A is.read ();
1710N/A // need to get the cnonce out of the response
1710N/A MessageHeader header = new MessageHeader (is);
1710N/A String raw = header.findValue ("Proxy-Authorization");
1710N/A HeaderParser parser = new HeaderParser (raw);
1710N/A String cnonce = parser.findValue ("cnonce");
1710N/A String cnstring = parser.findValue ("nc");
1710N/A String clientrsp = parser.findValue ("response");
1710N/A String expected = computeDigest(
1710N/A true, username,passwd,realm,
1710N/A "GET", uri, nonce, cnonce, cnstring
1710N/A );
1710N/A if (!expected.equals(clientrsp)) {
1710N/A s1.close ();
1710N/A s.close ();
1710N/A error = true;
1710N/A return;
1710N/A }
1710N/A
1710N/A String reply = reply2 + getAuthorization (
1710N/A realm, false, uri, "GET", cnonce,
1710N/A cnstring, passwd, username
1710N/A ) +"\r\n";
1710N/A os.write (reply.getBytes());
1710N/A Thread.sleep (2000);
1710N/A s1.close ();
1710N/A }
1710N/A catch (Exception e) {
1710N/A System.out.println (e);
1710N/A e.printStackTrace();
1710N/A }
1710N/A }
1710N/A
1710N/A private String getAuthorization (String realm, boolean isRequest, String uri, String method, String cnonce, String cnstring, char[] password, String username) {
1710N/A String response;
1710N/A
1710N/A try {
1710N/A response = computeDigest(isRequest, username,passwd,realm,
1710N/A method, uri, nonce, cnonce, cnstring);
1710N/A } catch (NoSuchAlgorithmException ex) {
1710N/A return null;
1710N/A }
1710N/A
1710N/A String value = "Digest"
1710N/A + " qop=\"auth"
1710N/A + "\", cnonce=\"" + cnonce
1710N/A + "\", rspauth=\"" + response
1710N/A + "\", nc=\"" + cnstring + "\"";
1710N/A return (value+ "\r\n");
1710N/A }
1710N/A
1710N/A private String computeDigest(
1710N/A boolean isRequest, String userName, char[] password,
1710N/A String realm, String connMethod,
1710N/A String requestURI, String nonceString,
1710N/A String cnonce, String ncValue
1710N/A ) throws NoSuchAlgorithmException
1710N/A {
1710N/A
1710N/A String A1, HashA1;
1710N/A
1710N/A MessageDigest md = MessageDigest.getInstance("MD5");
1710N/A
1710N/A {
1710N/A A1 = userName + ":" + realm + ":";
1710N/A HashA1 = encode(A1, password, md);
1710N/A }
1710N/A
1710N/A String A2;
1710N/A if (isRequest) {
1710N/A A2 = connMethod + ":" + requestURI;
1710N/A } else {
1710N/A A2 = ":" + requestURI;
1710N/A }
1710N/A String HashA2 = encode(A2, null, md);
1710N/A String combo, finalHash;
1710N/A
1710N/A { /* RRC2617 when qop=auth */
1710N/A combo = HashA1+ ":" + nonceString + ":" + ncValue + ":" +
1710N/A cnonce + ":auth:" +HashA2;
1710N/A
1710N/A }
1710N/A finalHash = encode(combo, null, md);
1710N/A return finalHash;
1710N/A }
1710N/A
1710N/A private final static char charArray[] = {
1710N/A '0', '1', '2', '3', '4', '5', '6', '7',
1710N/A '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1710N/A };
1710N/A
1710N/A private String encode(String src, char[] passwd, MessageDigest md) {
1710N/A md.update(src.getBytes());
1710N/A if (passwd != null) {
1710N/A byte[] passwdBytes = new byte[passwd.length];
1710N/A for (int i=0; i<passwd.length; i++)
1710N/A passwdBytes[i] = (byte)passwd[i];
1710N/A md.update(passwdBytes);
1710N/A Arrays.fill(passwdBytes, (byte)0x00);
1710N/A }
1710N/A byte[] digest = md.digest();
1710N/A
1710N/A StringBuffer res = new StringBuffer(digest.length * 2);
1710N/A for (int i = 0; i < digest.length; i++) {
1710N/A int hashchar = ((digest[i] >>> 4) & 0xf);
1710N/A res.append(charArray[hashchar]);
1710N/A hashchar = (digest[i] & 0xf);
1710N/A res.append(charArray[hashchar]);
1710N/A }
1710N/A return res.toString();
1710N/A }
1710N/A }
1710N/A
1710N/A
1710N/A static class MyAuthenticator extends Authenticator {
1710N/A public MyAuthenticator () {
1710N/A super ();
1710N/A }
1710N/A
1710N/A public PasswordAuthentication getPasswordAuthentication ()
1710N/A {
1710N/A return (new PasswordAuthentication (username, passwd));
1710N/A }
1710N/A }
1710N/A
1710N/A
1710N/A public static void main(String[] args) throws Exception {
1710N/A int nLoops = 1;
1710N/A int nSize = 10;
1710N/A int port, n =0;
1710N/A byte b[] = new byte[nSize];
1710N/A DigestServer server;
1710N/A ServerSocket sock;
1710N/A
1710N/A try {
1710N/A sock = new ServerSocket (0);
1710N/A port = sock.getLocalPort ();
1710N/A }
1710N/A catch (Exception e) {
1710N/A System.out.println ("Exception: " + e);
1710N/A return;
1710N/A }
1710N/A
1710N/A server = new DigestServer(sock);
1710N/A server.start ();
1710N/A
1710N/A try {
1710N/A
1710N/A Authenticator.setDefault (new MyAuthenticator ());
1710N/A SocketAddress addr = new InetSocketAddress ("127.0.0.1", port);
1710N/A Proxy proxy = new Proxy (Proxy.Type.HTTP, addr);
1710N/A String s = "http://www.ibm.com";
1710N/A URL url = new URL(s);
1710N/A java.net.URLConnection conURL = url.openConnection(proxy);
1710N/A
1710N/A InputStream in = conURL.getInputStream();
1710N/A int c;
1710N/A while ((c = in.read ()) != -1) {
1710N/A }
1710N/A in.close ();
1710N/A }
1710N/A catch(IOException e) {
1710N/A e.printStackTrace();
1710N/A error = true;
1710N/A }
1710N/A if (error) {
1710N/A throw new RuntimeException ("Error in test");
1710N/A }
1710N/A }
1710N/A}