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