1 /*
   2  * Copyright (c) 2001, 2011, 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 4323990 4413069
  27  * @summary HttpsURLConnection doesn't send Proxy-Authorization on CONNECT
  28  *     Incorrect checking of proxy server response
  29  * @modules java.base/sun.net.www
  30  * @run main/othervm ProxyAuthTest
  31  *
  32  *     No way to reserve and restore java.lang.Authenticator, need to run this
  33  *     test in othervm mode.
  34  */
  35 
  36 import java.io.*;
  37 import java.net.*;
  38 import java.security.KeyStore;
  39 import javax.net.*;
  40 import javax.net.ssl.*;
  41 import java.security.cert.*;
  42 
  43 /*
  44  * ProxyAuthTest.java -- includes a simple server that can serve
  45  * Http get request in both clear and secure channel, and a client
  46  * that makes https requests behind the firewall through an
  47  * authentication proxy
  48  */
  49 
  50 public class ProxyAuthTest {
  51     /*
  52      * Where do we find the keystores?
  53      */
  54     static String pathToStores = "../../../../../../javax/net/ssl/etc";
  55     static String keyStoreFile = "keystore";
  56     static String trustStoreFile = "truststore";
  57     static String passwd = "passphrase";
  58 
  59     volatile private static int serverPort = 0;
  60 
  61     /*
  62      * The TestServer implements a OriginServer that
  63      * processes HTTP requests and responses.
  64      */
  65     static class TestServer extends OriginServer {
  66         public TestServer(ServerSocket ss) throws Exception {
  67             super(ss);
  68         }
  69 
  70         /*
  71          * Returns an array of bytes containing the bytes for
  72          * the data sent in the response.
  73          *
  74          * @return bytes for the data in the response
  75          */
  76         public byte[] getBytes() {
  77             return "Proxy authentication for tunneling succeeded ..".
  78                         getBytes();
  79         }
  80     }
  81 
  82     /*
  83      * Main method to create the server and the client
  84      */
  85     public static void main(String args[]) throws Exception {
  86         String keyFilename =
  87             System.getProperty("test.src", "./") + "/" + pathToStores +
  88                 "/" + keyStoreFile;
  89         String trustFilename =
  90             System.getProperty("test.src", "./") + "/" + pathToStores +
  91                 "/" + trustStoreFile;
  92 
  93         System.setProperty("javax.net.ssl.keyStore", keyFilename);
  94         System.setProperty("javax.net.ssl.keyStorePassword", passwd);
  95         System.setProperty("javax.net.ssl.trustStore", trustFilename);
  96         System.setProperty("javax.net.ssl.trustStorePassword", passwd);
  97 
  98         boolean useSSL = true;
  99         /*
 100          * setup the server
 101          */
 102         try {
 103             ServerSocketFactory ssf =
 104                 ProxyAuthTest.getServerSocketFactory(useSSL);
 105             ServerSocket ss = ssf.createServerSocket(serverPort);
 106             serverPort = ss.getLocalPort();
 107             new TestServer(ss);
 108         } catch (Exception e) {
 109             System.out.println("Server side failed:" +
 110                                 e.getMessage());
 111             throw e;
 112         }
 113         // trigger the client
 114         try {
 115             doClientSide();
 116         } catch (Exception e) {
 117             System.out.println("Client side failed: " + e.getMessage());
 118             throw e;
 119         }
 120     }
 121 
 122     private static ServerSocketFactory getServerSocketFactory
 123                    (boolean useSSL) throws Exception {
 124         if (useSSL) {
 125             SSLServerSocketFactory ssf = null;
 126             // set up key manager to do server authentication
 127             SSLContext ctx;
 128             KeyManagerFactory kmf;
 129             KeyStore ks;
 130             char[] passphrase = passwd.toCharArray();
 131 
 132             ctx = SSLContext.getInstance("TLS");
 133             kmf = KeyManagerFactory.getInstance("SunX509");
 134             ks = KeyStore.getInstance("JKS");
 135 
 136             ks.load(new FileInputStream(System.getProperty(
 137                         "javax.net.ssl.keyStore")), passphrase);
 138             kmf.init(ks, passphrase);
 139             ctx.init(kmf.getKeyManagers(), null, null);
 140 
 141             ssf = ctx.getServerSocketFactory();
 142             return ssf;
 143         } else {
 144             return ServerSocketFactory.getDefault();
 145         }
 146     }
 147 
 148     static void doClientSide() throws Exception {
 149         /*
 150          * setup up a proxy with authentication information
 151          */
 152         setupProxy();
 153 
 154         /*
 155          * we want to avoid URLspoofCheck failures in cases where the cert
 156          * DN name does not match the hostname in the URL.
 157          */
 158         HttpsURLConnection.setDefaultHostnameVerifier(
 159                                       new NameVerifier());
 160         URL url = new URL("https://" + "localhost:" + serverPort
 161                                 + "/index.html");
 162         BufferedReader in = null;
 163         try {
 164             in = new BufferedReader(new InputStreamReader(
 165                                url.openStream()));
 166             String inputLine;
 167             System.out.print("Client recieved from the server: ");
 168             while ((inputLine = in.readLine()) != null)
 169                 System.out.println(inputLine);
 170             in.close();
 171         } catch (SSLException e) {
 172             if (in != null)
 173                 in.close();
 174             throw e;
 175         }
 176     }
 177 
 178     static class NameVerifier implements HostnameVerifier {
 179         public boolean verify(String hostname, SSLSession session) {
 180             return true;
 181         }
 182     }
 183 
 184     static void setupProxy() throws IOException {
 185         ProxyTunnelServer pserver = new ProxyTunnelServer();
 186         /*
 187          * register a system wide authenticator and setup the proxy for
 188          * authentication
 189          */
 190         Authenticator.setDefault(new TestAuthenticator());
 191 
 192         // register with the username and password
 193         pserver.needUserAuth(true);
 194         pserver.setUserAuth("Test", "test123");
 195 
 196         pserver.start();
 197         System.setProperty("https.proxyHost", "localhost");
 198         System.setProperty("https.proxyPort", String.valueOf(
 199                                         pserver.getPort()));
 200     }
 201 
 202     public static class TestAuthenticator extends Authenticator {
 203 
 204         public PasswordAuthentication getPasswordAuthentication() {
 205             return new PasswordAuthentication("Test",
 206                                          "test123".toCharArray());
 207         }
 208     }
 209 }