1 /* 2 * Copyright (c) 2016, 2018, 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.File; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.io.OutputStream; 28 import java.net.URI; 29 import java.net.URISyntaxException; 30 import java.security.Security; 31 import java.net.http.HttpClient; 32 import java.net.http.HttpRequest; 33 import java.net.http.HttpRequest.BodyPublishers; 34 import java.net.http.HttpResponse.BodyHandlers; 35 import javax.net.ssl.SSLParameters; 36 import javax.net.ssl.SSLSession; 37 38 /* 39 * @test 40 * @bug 8150769 8157107 41 * @library server 42 * @summary Checks that SSL parameters can be set for HTTP/2 connection 43 * @modules java.base/sun.net.www.http 44 * java.net.http/jdk.internal.net.http.common 45 * java.net.http/jdk.internal.net.http.frame 46 * java.net.http/jdk.internal.net.http.hpack 47 * @run main/othervm 48 * -Djdk.internal.httpclient.debug=true 49 * -Djdk.httpclient.HttpClient.log=all 50 * TLSConnection 51 */ 52 public class TLSConnection { 53 54 private static final String KEYSTORE = System.getProperty("test.src") 55 + File.separator + "keystore.p12"; 56 private static final String PASSWORD = "password"; 57 58 private static final SSLParameters USE_DEFAULT_SSL_PARAMETERS = new SSLParameters(); 59 60 public static void main(String[] args) throws Exception { 61 // re-enable 3DES 62 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 63 64 // enable all logging 65 System.setProperty("jdk.httpclient.HttpClient.log", "all,frames:all"); 66 67 // initialize JSSE 68 System.setProperty("javax.net.ssl.keyStore", KEYSTORE); 69 System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD); 70 System.setProperty("javax.net.ssl.trustStore", KEYSTORE); 71 System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD); 72 73 Handler handler = new Handler(); 74 75 try (Http2TestServer server = new Http2TestServer("localhost", true, 0)) { 76 server.addHandler(handler, "/"); 77 server.start(); 78 79 int port = server.getAddress().getPort(); 80 String uriString = "https://localhost:" + Integer.toString(port); 81 82 // run test cases 83 boolean success = true; 84 85 SSLParameters parameters = null; 86 success &= expectFailure( 87 "---\nTest #1: SSL parameters is null, expect NPE", 88 () -> connect(uriString, parameters), 89 NullPointerException.class); 90 91 success &= expectSuccess( 92 "---\nTest #2: default SSL parameters, " 93 + "expect successful connection", 94 () -> connect(uriString, USE_DEFAULT_SSL_PARAMETERS)); 95 success &= checkProtocol(handler.getSSLSession(), "TLSv1.2"); 96 97 // set SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite 98 // which has less priority in default cipher suite list 99 success &= expectSuccess( 100 "---\nTest #3: SSL parameters with " 101 + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA cipher suite, " 102 + "expect successful connection", 103 () -> connect(uriString, new SSLParameters( 104 new String[] { "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA" }, 105 new String[] { "TLSv1.2" }))); 106 success &= checkProtocol(handler.getSSLSession(), "TLSv1.2"); 107 success &= checkCipherSuite(handler.getSSLSession(), 108 "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); 109 110 // set TLS_RSA_WITH_AES_128_CBC_SHA cipher suite 111 // which has less priority in default cipher suite list 112 // also set TLSv1.2 protocol 113 success &= expectSuccess( 114 "---\nTest #4: SSL parameters with " 115 + "TLS_RSA_WITH_AES_128_CBC_SHA cipher suite," 116 + " expect successful connection", 117 () -> connect(uriString, new SSLParameters( 118 new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA" }, 119 new String[] { "TLSv1.2" }))); 120 success &= checkProtocol(handler.getSSLSession(), "TLSv1.2"); 121 success &= checkCipherSuite(handler.getSSLSession(), 122 "TLS_RSA_WITH_AES_128_CBC_SHA"); 123 124 if (success) { 125 System.out.println("Test passed"); 126 } else { 127 throw new RuntimeException("At least one test case failed"); 128 } 129 } 130 } 131 132 private static interface Test { 133 134 public void run() throws Exception; 135 } 136 137 private static class Handler implements Http2Handler { 138 139 private static final byte[] BODY = "Test response".getBytes(); 140 141 private volatile SSLSession sslSession; 142 143 @Override 144 public void handle(Http2TestExchange t) throws IOException { 145 System.out.println("Handler: received request to " 146 + t.getRequestURI()); 147 148 try (InputStream is = t.getRequestBody()) { 149 byte[] body = is.readAllBytes(); 150 System.out.println("Handler: read " + body.length 151 + " bytes of body: "); 152 System.out.println(new String(body)); 153 } 154 155 try (OutputStream os = t.getResponseBody()) { 156 t.sendResponseHeaders(200, BODY.length); 157 os.write(BODY); 158 } 159 160 sslSession = t.getSSLSession(); 161 } 162 163 SSLSession getSSLSession() { 164 return sslSession; 165 } 166 } 167 168 private static void connect(String uriString, SSLParameters sslParameters) 169 throws URISyntaxException, IOException, InterruptedException 170 { 171 HttpClient.Builder builder = HttpClient.newBuilder() 172 .version(HttpClient.Version.HTTP_2); 173 if (sslParameters != USE_DEFAULT_SSL_PARAMETERS) 174 builder.sslParameters(sslParameters); 175 HttpClient client = builder.build(); 176 177 HttpRequest request = HttpRequest.newBuilder(new URI(uriString)) 178 .POST(BodyPublishers.ofString("body")) 179 .build(); 180 String body = client.send(request, BodyHandlers.ofString()).body(); 181 182 System.out.println("Response: " + body); 183 } 184 185 private static boolean checkProtocol(SSLSession session, String protocol) { 186 if (session == null) { 187 System.out.println("Check protocol: no session provided"); 188 return false; 189 } 190 191 System.out.println("Check protocol: negotiated protocol: " 192 + session.getProtocol()); 193 System.out.println("Check protocol: expected protocol: " 194 + protocol); 195 if (!protocol.equals(session.getProtocol())) { 196 System.out.println("Check protocol: unexpected negotiated protocol"); 197 return false; 198 } 199 200 return true; 201 } 202 203 private static boolean checkCipherSuite(SSLSession session, String ciphersuite) { 204 if (session == null) { 205 System.out.println("Check protocol: no session provided"); 206 return false; 207 } 208 209 System.out.println("Check protocol: negotiated ciphersuite: " 210 + session.getCipherSuite()); 211 System.out.println("Check protocol: expected ciphersuite: " 212 + ciphersuite); 213 if (!ciphersuite.equals(session.getCipherSuite())) { 214 System.out.println("Check protocol: unexpected negotiated ciphersuite"); 215 return false; 216 } 217 218 return true; 219 } 220 221 private static boolean expectSuccess(String message, Test test) { 222 System.out.println(message); 223 try { 224 test.run(); 225 System.out.println("Passed"); 226 return true; 227 } catch (Exception e) { 228 System.out.println("Failed: unexpected exception:"); 229 e.printStackTrace(System.out); 230 return false; 231 } 232 } 233 234 private static boolean expectFailure(String message, Test test, 235 Class<? extends Throwable> expectedException) { 236 237 System.out.println(message); 238 try { 239 test.run(); 240 System.out.println("Failed: unexpected successful connection"); 241 return false; 242 } catch (Exception e) { 243 System.out.println("Got an exception:"); 244 e.printStackTrace(System.out); 245 if (expectedException != null 246 && !expectedException.isAssignableFrom(e.getClass())) { 247 System.out.printf("Failed: expected %s, but got %s%n", 248 expectedException.getName(), 249 e.getClass().getName()); 250 return false; 251 } 252 System.out.println("Passed: expected exception"); 253 return true; 254 } 255 } 256 }