1 /* 2 * Copyright (c) 2001, 2016, 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 import java.io.*; 25 import java.net.*; 26 import java.security.KeyStore; 27 import javax.net.*; 28 import javax.net.ssl.*; 29 30 import jdk.test.lib.process.OutputAnalyzer; 31 import jdk.test.lib.process.ProcessTools; 32 33 /* 34 * @test 35 * @bug 4423074 36 * @modules java.base/sun.net.www 37 * @summary This test case is written to test the https POST through a proxy. 38 * There is no proxy authentication done. It includes a simple server 39 * that serves http POST method requests in secure channel, and a client 40 * that makes https POST request through a proxy. 41 * @library /test/lib 42 * @build jdk.test.lib.Utils 43 * jdk.test.lib.Asserts 44 * jdk.test.lib.JDKToolFinder 45 * jdk.test.lib.JDKToolLauncher 46 * jdk.test.lib.Platform 47 * jdk.test.lib.process.* 48 * @compile OriginServer.java ProxyTunnelServer.java 49 * @run main/othervm PostThruProxy 50 */ 51 public class PostThruProxy { 52 53 private static final String TEST_SRC = System.getProperty("test.src", "."); 54 private static final int TIMEOUT = 30000; 55 56 /* 57 * Where do we find the keystores? 58 */ 59 static String pathToStores = "../../../../../../javax/net/ssl/etc"; 60 static String keyStoreFile = "keystore"; 61 static String trustStoreFile = "truststore"; 62 static String passwd = "passphrase"; 63 64 private static int serverPort = 0; 65 66 /* 67 * The TestServer implements a OriginServer that 68 * processes HTTP requests and responses. 69 */ 70 static class TestServer extends OriginServer { 71 public TestServer(ServerSocket ss) throws Exception { 72 super(ss); 73 } 74 75 /* 76 * Returns an array of bytes containing the bytes for 77 * the data sent in the response. 78 * 79 * @return bytes for the data in the response 80 */ 81 public byte[] getBytes() { 82 return "Https POST thru proxy is successful". 83 getBytes(); 84 } 85 } 86 87 /* 88 * Main method to create the server and client 89 */ 90 public static void main(String args[]) throws Exception { 91 String keyFilename = TEST_SRC + "/" + pathToStores + "/" + keyStoreFile; 92 String trustFilename = TEST_SRC + "/" + pathToStores + "/" 93 + trustStoreFile; 94 95 System.setProperty("javax.net.ssl.keyStore", keyFilename); 96 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 97 System.setProperty("javax.net.ssl.trustStore", trustFilename); 98 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 99 100 boolean useSSL = true; 101 /* 102 * setup the server 103 */ 104 try { 105 ServerSocketFactory ssf = getServerSocketFactory(useSSL); 106 ServerSocket ss = ssf.createServerSocket(serverPort); 107 ss.setSoTimeout(TIMEOUT); // 30 seconds 108 serverPort = ss.getLocalPort(); 109 new TestServer(ss); 110 } catch (Exception e) { 111 System.out.println("Server side failed:" + 112 e.getMessage()); 113 throw e; 114 } 115 // trigger the client 116 try { 117 doClientSide(); 118 } catch (Exception e) { 119 System.out.println("Client side failed: " + 120 e.getMessage()); 121 throw e; 122 } 123 } 124 125 private static ServerSocketFactory getServerSocketFactory 126 (boolean useSSL) throws Exception { 127 if (useSSL) { 128 // set up key manager to do server authentication 129 SSLContext ctx = SSLContext.getInstance("TLS"); 130 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 131 KeyStore ks = KeyStore.getInstance("JKS"); 132 char[] passphrase = passwd.toCharArray(); 133 134 ks.load(new FileInputStream(System.getProperty( 135 "javax.net.ssl.keyStore")), passphrase); 136 kmf.init(ks, passphrase); 137 ctx.init(kmf.getKeyManagers(), null, null); 138 139 return ctx.getServerSocketFactory(); 140 } else { 141 return ServerSocketFactory.getDefault(); 142 } 143 } 144 145 /* 146 * Message to be posted 147 */ 148 static String postMsg = "Testing HTTP post on a https server"; 149 150 static void doClientSide() throws Exception { 151 HostnameVerifier reservedHV = 152 HttpsURLConnection.getDefaultHostnameVerifier(); 153 try { 154 /* 155 * setup up a proxy 156 */ 157 SocketAddress pAddr = setupProxy(); 158 159 /* 160 * we want to avoid URLspoofCheck failures in cases where the cert 161 * DN name does not match the hostname in the URL. 162 */ 163 HttpsURLConnection.setDefaultHostnameVerifier( 164 new NameVerifier()); 165 URL url = new URL("https://" + getHostname() +":" + serverPort); 166 167 Proxy p = new Proxy(Proxy.Type.HTTP, pAddr); 168 HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p); 169 https.setConnectTimeout(TIMEOUT); 170 https.setReadTimeout(TIMEOUT); 171 https.setDoOutput(true); 172 https.setRequestMethod("POST"); 173 PrintStream ps = null; 174 try { 175 ps = new PrintStream(https.getOutputStream()); 176 ps.println(postMsg); 177 ps.flush(); 178 if (https.getResponseCode() != 200) { 179 throw new RuntimeException("test Failed"); 180 } 181 ps.close(); 182 183 // clear the pipe 184 BufferedReader in = new BufferedReader( 185 new InputStreamReader( 186 https.getInputStream())); 187 String inputLine; 188 while ((inputLine = in.readLine()) != null) 189 System.out.println("Client received: " + inputLine); 190 in.close(); 191 } catch (SSLException e) { 192 if (ps != null) 193 ps.close(); 194 throw e; 195 } catch (SocketTimeoutException e) { 196 System.out.println("Client can not get response in time: " 197 + e.getMessage()); 198 } 199 } finally { 200 HttpsURLConnection.setDefaultHostnameVerifier(reservedHV); 201 } 202 } 203 204 static class NameVerifier implements HostnameVerifier { 205 public boolean verify(String hostname, SSLSession session) { 206 return true; 207 } 208 } 209 210 static SocketAddress setupProxy() throws IOException { 211 ProxyTunnelServer pserver = new ProxyTunnelServer(); 212 213 // disable proxy authentication 214 pserver.needUserAuth(false); 215 pserver.start(); 216 return new InetSocketAddress("localhost", pserver.getPort()); 217 } 218 219 private static String getHostname() { 220 try { 221 OutputAnalyzer oa = ProcessTools.executeCommand("hostname"); 222 return oa.getOutput().trim(); 223 } catch (Throwable e) { 224 throw new RuntimeException("Get hostname failed.", e); 225 } 226 } 227 }