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