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