1 /* 2 * Copyright (c) 2008, 2020, 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 // SunJSSE does not support dynamic system properties, no way to re-use 26 // system properties in samevm/agentvm mode. 27 // 28 29 /* 30 * @test 31 * @bug 6728126 32 * @summary Parsing Extensions in Client Hello message is done in a wrong way 33 * @library /test/lib 34 * @run main/othervm EmptyExtensionData 35 */ 36 37 import javax.net.ssl.*; 38 import javax.net.ssl.SSLEngineResult.*; 39 import java.io.*; 40 import java.security.*; 41 import java.nio.*; 42 43 import jdk.test.lib.security.SecurityUtils; 44 45 public class EmptyExtensionData { 46 47 private static boolean debug = false; 48 49 private static String pathToStores = "../../../../javax/net/ssl/etc"; 50 private static String keyStoreFile = "keystore"; 51 private static String trustStoreFile = "truststore"; 52 private static String passwd = "passphrase"; 53 54 private static String keyFilename = 55 System.getProperty("test.src", "./") + "/" + pathToStores + 56 "/" + keyStoreFile; 57 private static String trustFilename = 58 System.getProperty("test.src", "./") + "/" + pathToStores + 59 "/" + trustStoreFile; 60 checkDone(SSLEngine ssle)61 private static void checkDone(SSLEngine ssle) throws Exception { 62 if (!ssle.isInboundDone()) { 63 throw new Exception("isInboundDone isn't done"); 64 } 65 if (!ssle.isOutboundDone()) { 66 throw new Exception("isOutboundDone isn't done"); 67 } 68 } 69 runTest(SSLEngine ssle)70 private static void runTest(SSLEngine ssle) throws Exception { 71 // a client hello message with an empty extension data 72 byte[] msg_clihello = { 73 (byte)0x16, (byte)0x03, (byte)0x01, (byte)0x00, 74 (byte)0x6f, (byte)0x01, (byte)0x00, (byte)0x00, 75 (byte)0x6b, (byte)0x03, (byte)0x01, (byte)0x48, 76 (byte)0x90, (byte)0x71, (byte)0xfc, (byte)0xf9, 77 (byte)0xa2, (byte)0x3a, (byte)0xd7, (byte)0xa8, 78 (byte)0x0b, (byte)0x25, (byte)0xf1, (byte)0x2b, 79 (byte)0x88, (byte)0x80, (byte)0x66, (byte)0xca, 80 (byte)0x07, (byte)0x78, (byte)0x2a, (byte)0x08, 81 (byte)0x9d, (byte)0x62, (byte)0x1d, (byte)0x89, 82 (byte)0xc9, (byte)0x1e, (byte)0x1f, (byte)0xe5, 83 (byte)0x92, (byte)0xfe, (byte)0x8d, (byte)0x00, 84 (byte)0x00, (byte)0x24, (byte)0x00, (byte)0x88, 85 (byte)0x00, (byte)0x87, (byte)0x00, (byte)0x39, 86 (byte)0x00, (byte)0x38, (byte)0x00, (byte)0x84, 87 (byte)0x00, (byte)0x35, (byte)0x00, (byte)0x45, 88 (byte)0x00, (byte)0x44, (byte)0x00, (byte)0x33, 89 (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x41, 90 (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x05, 91 (byte)0x00, (byte)0x2f, (byte)0x00, (byte)0x16, 92 (byte)0x00, (byte)0x13, (byte)0xfe, (byte)0xff, 93 (byte)0x00, (byte)0x0a, (byte)0x01, (byte)0x00, 94 (byte)0x00, (byte)0x1e, (byte)0x00, (byte)0x00, 95 (byte)0x00, (byte)0x16, (byte)0x00, (byte)0x14, 96 (byte)0x00, (byte)0x00, (byte)0x11, (byte)0x6a, 97 (byte)0x75, (byte)0x73, (byte)0x74, (byte)0x69, 98 (byte)0x6e, (byte)0x2e, (byte)0x75, (byte)0x6b, 99 (byte)0x2e, (byte)0x73, (byte)0x75, (byte)0x6e, 100 (byte)0x2e, (byte)0x63, (byte)0x6f, (byte)0x6d, 101 (byte)0x00, (byte)0x23, (byte)0x00, (byte)0x00 102 }; 103 ByteBuffer bf_clihello = ByteBuffer.wrap(msg_clihello); 104 105 SSLSession session = ssle.getSession(); 106 int appBufferMax = session.getApplicationBufferSize(); 107 int netBufferMax = session.getPacketBufferSize(); 108 109 ByteBuffer serverIn = ByteBuffer.allocate(appBufferMax + 50); 110 ByteBuffer serverOut = ByteBuffer.wrap("I'm Server".getBytes()); 111 ByteBuffer sTOc = ByteBuffer.allocate(netBufferMax); 112 113 ssle.beginHandshake(); 114 115 // unwrap the clientHello message. 116 SSLEngineResult result = ssle.unwrap(bf_clihello, serverIn); 117 System.out.println("server unwrap " + result); 118 runDelegatedTasks(result, ssle); 119 120 // one more step, ensure the clientHello message is parsed. 121 SSLEngineResult.HandshakeStatus status = ssle.getHandshakeStatus(); 122 if ( status == HandshakeStatus.NEED_UNWRAP) { 123 result = ssle.unwrap(bf_clihello, serverIn); 124 System.out.println("server unwrap " + result); 125 runDelegatedTasks(result, ssle); 126 } else if ( status == HandshakeStatus.NEED_WRAP) { 127 result = ssle.wrap(serverOut, sTOc); 128 System.out.println("server wrap " + result); 129 runDelegatedTasks(result, ssle); 130 } else { 131 throw new Exception("unexpected handshake status " + status); 132 } 133 134 // enough, stop 135 } 136 137 /* 138 * If the result indicates that we have outstanding tasks to do, 139 * go ahead and run them in this thread. 140 */ runDelegatedTasks(SSLEngineResult result, SSLEngine engine)141 private static void runDelegatedTasks(SSLEngineResult result, 142 SSLEngine engine) throws Exception { 143 144 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 145 Runnable runnable; 146 while ((runnable = engine.getDelegatedTask()) != null) { 147 log("\trunning delegated task..."); 148 runnable.run(); 149 } 150 HandshakeStatus hsStatus = engine.getHandshakeStatus(); 151 if (hsStatus == HandshakeStatus.NEED_TASK) { 152 throw new Exception( 153 "handshake shouldn't need additional tasks"); 154 } 155 log("\tnew HandshakeStatus: " + hsStatus); 156 } 157 } 158 main(String args[])159 public static void main(String args[]) throws Exception { 160 // Re-enable TLSv1 since test depends on it. 161 SecurityUtils.removeFromDisabledTlsAlgs("TLSv1"); 162 163 SSLEngine ssle = createSSLEngine(keyFilename, trustFilename); 164 runTest(ssle); 165 166 System.out.println("Test Passed."); 167 } 168 169 /* 170 * Create an initialized SSLContext to use for this test. 171 */ createSSLEngine(String keyFile, String trustFile)172 static private SSLEngine createSSLEngine(String keyFile, String trustFile) 173 throws Exception { 174 175 SSLEngine ssle; 176 177 KeyStore ks = KeyStore.getInstance("JKS"); 178 KeyStore ts = KeyStore.getInstance("JKS"); 179 180 char[] passphrase = "passphrase".toCharArray(); 181 182 ks.load(new FileInputStream(keyFile), passphrase); 183 ts.load(new FileInputStream(trustFile), passphrase); 184 185 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 186 kmf.init(ks, passphrase); 187 188 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 189 tmf.init(ts); 190 191 SSLContext sslCtx = SSLContext.getInstance("TLS"); 192 193 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 194 195 ssle = sslCtx.createSSLEngine(); 196 ssle.setUseClientMode(false); 197 198 return ssle; 199 } 200 201 log(String str)202 private static void log(String str) { 203 if (debug) { 204 System.out.println(str); 205 } 206 } 207 } 208