1/* 2 * Copyright (c) 2003, 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 4931274 32 * @summary closeInbound does not signal when a close_notify has not 33 * been received. 34 * @run main/othervm CloseInboundException 35 * @author Brad Wetmore 36 */ 37 38import javax.net.ssl.*; 39import javax.net.ssl.SSLEngineResult.*; 40import java.io.*; 41import java.security.*; 42import java.nio.*; 43 44public class CloseInboundException { 45 46 private SSLEngine ssle1; // client 47 private SSLEngine ssle2; // server 48 49 SSLEngineResult result1; // ssle1's results from last operation 50 SSLEngineResult result2; // ssle2's results from last operation 51 52 private static String pathToStores = "../../../../javax/net/ssl/etc"; 53 private static String keyStoreFile = "keystore"; 54 private static String trustStoreFile = "truststore"; 55 private static String passwd = "passphrase"; 56 57 private static String keyFilename = 58 System.getProperty("test.src", "./") + "/" + pathToStores + 59 "/" + keyStoreFile; 60 private static String trustFilename = 61 System.getProperty("test.src", "./") + "/" + pathToStores + 62 "/" + trustStoreFile; 63 64 private ByteBuffer appOut1; // write side of ssle1 65 private ByteBuffer appIn1; // read side of ssle1 66 private ByteBuffer appOut2; // write side of ssle2 67 private ByteBuffer appIn2; // read side of ssle2 68 69 private ByteBuffer oneToTwo; // "reliable" transport ssle1->ssle2 70 private ByteBuffer twoToOne; // "reliable" transport ssle2->ssle1 71 72 /* 73 * Majority of the test case is here, setup is done below. 74 */ 75 private void runTest(boolean inboundClose) throws Exception { 76 77 boolean done = false; 78 79 while (!isEngineClosed(ssle1) || !isEngineClosed(ssle2)) { 80 81 System.out.println("================"); 82 83 result1 = ssle1.wrap(appOut1, oneToTwo); 84 result2 = ssle2.wrap(appOut2, twoToOne); 85 86 System.out.println("wrap1 = " + result1); 87 System.out.println("oneToTwo = " + oneToTwo); 88 89 System.out.println("wrap2 = " + result2); 90 System.out.println("twoToOne = " + twoToOne); 91 92 runDelegatedTasks(result1, ssle1); 93 runDelegatedTasks(result2, ssle2); 94 95 oneToTwo.flip(); 96 twoToOne.flip(); 97 98 System.out.println("----"); 99 result1 = ssle1.unwrap(twoToOne, appIn1); 100 101 if (done && inboundClose) { 102 try { 103 result2 = ssle2.unwrap(oneToTwo, appIn2); 104 throw new Exception("Didn't throw Exception"); 105 } catch (SSLException e) { 106 System.out.println("Caught proper exception\n" + e); 107 return; 108 } 109 } else { 110 result2 = ssle2.unwrap(oneToTwo, appIn2); 111 } 112 113 System.out.println("unwrap1 = " + result1); 114 System.out.println("twoToOne = " + twoToOne); 115 116 System.out.println("unwrap2 = " + result2); 117 System.out.println("oneToTwo = " + oneToTwo); 118 119 runDelegatedTasks(result1, ssle1); 120 runDelegatedTasks(result2, ssle2); 121 122 oneToTwo.compact(); 123 twoToOne.compact(); 124 125 /* 126 * If we've transfered all the data between app1 and app2, 127 * we try to close and see what that gets us. 128 */ 129 if (!done && (appOut1.limit() == appIn2.position()) && 130 (appOut2.limit() == appIn1.position())) { 131 132 if (inboundClose) { 133 try { 134 System.out.println("Closing ssle1's *INBOUND*..."); 135 ssle1.closeInbound(); 136 throw new Exception("closeInbound didn't throw"); 137 } catch (SSLException e) { 138 System.out.println("Caught closeInbound exc properly"); 139 checkStatus(); 140 /* 141 * Let the message processing continue to 142 * handle the alert. 143 */ 144 } 145 done = true; 146 } else { 147 done = true; 148 System.out.println("Closing ssle1's *OUTBOUND*..."); 149 ssle1.closeOutbound(); 150 } 151 } 152 } 153 } 154 155 /* 156 * Check to see if the close generated a close_notify message, 157 * that the result status is sane, and that close again doesn't 158 * generate a new exception. 159 * 160 * We'll consume the wrapped data when we loop back around. 161 */ 162 private void checkStatus() throws Exception { 163 System.out.println("\nCalling last wrap"); 164 int pos = oneToTwo.position(); 165 166 result1 = ssle1.wrap(appOut1, oneToTwo); 167 System.out.println("result1 = " + result1); 168 169 if ((pos >= oneToTwo.position()) || 170 !result1.getStatus().equals(Status.CLOSED) || 171 !result1.getHandshakeStatus().equals( 172 HandshakeStatus.NOT_HANDSHAKING) || 173 !ssle1.isOutboundDone() || 174 !ssle1.isInboundDone()) { 175 throw new Exception(result1.toString()); 176 } 177 System.out.println("Make sure we don't throw a second SSLException."); 178 ssle1.closeInbound(); 179 } 180 181 public static void main(String args[]) throws Exception { 182 183 CloseInboundException test; 184 185 test = new CloseInboundException(); 186 test.runTest(false); 187 188 test = new CloseInboundException(); 189 test.runTest(true); 190 System.out.println("Test PASSED!!!"); 191 } 192 193 /* 194 * ********************************************************** 195 * Majority of the test case is above, below is just setup stuff 196 * ********************************************************** 197 */ 198 199 public CloseInboundException() throws Exception { 200 201 SSLContext sslc = getSSLContext(keyFilename, trustFilename); 202 203 ssle1 = sslc.createSSLEngine("host1", 1); 204 ssle1.setUseClientMode(true); 205 206 ssle2 = sslc.createSSLEngine("host2", 2); 207 ssle2.setUseClientMode(false); 208 209 createBuffers(); 210 } 211 212 /* 213 * Create an initialized SSLContext to use for this test. 214 */ 215 private SSLContext getSSLContext(String keyFile, String trustFile) 216 throws Exception { 217 218 KeyStore ks = KeyStore.getInstance("JKS"); 219 KeyStore ts = KeyStore.getInstance("JKS"); 220 221 char[] passphrase = "passphrase".toCharArray(); 222 223 ks.load(new FileInputStream(keyFile), passphrase); 224 ts.load(new FileInputStream(trustFile), passphrase); 225 226 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 227 kmf.init(ks, passphrase); 228 229 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 230 tmf.init(ts); 231 232 SSLContext sslCtx = SSLContext.getInstance("TLS"); 233 234 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 235 236 return sslCtx; 237 } 238 239 private void createBuffers() { 240 // Size the buffers as appropriate. 241 SSLSession session = ssle1.getSession(); 242 int appBufferMax = session.getApplicationBufferSize(); 243 int netBufferMax = session.getPacketBufferSize(); 244 245 appIn1 = ByteBuffer.allocateDirect(appBufferMax + 50); 246 appIn2 = ByteBuffer.allocateDirect(appBufferMax + 50); 247 248 oneToTwo = ByteBuffer.allocateDirect(netBufferMax); 249 twoToOne = ByteBuffer.allocateDirect(netBufferMax); 250 251 appOut1 = ByteBuffer.wrap("Hi Engine2, I'm SSLEngine1".getBytes()); 252 appOut2 = ByteBuffer.wrap("Hello Engine1, I'm SSLEngine2".getBytes()); 253 254 System.out.println("AppOut1 = " + appOut1); 255 System.out.println("AppOut2 = " + appOut2); 256 System.out.println(); 257 } 258 259 private static void runDelegatedTasks(SSLEngineResult result, 260 SSLEngine engine) throws Exception { 261 262 if (result.getHandshakeStatus().equals(HandshakeStatus.NEED_TASK)) { 263 Runnable runnable; 264 while ((runnable = engine.getDelegatedTask()) != null) { 265 System.out.println("running delegated task..."); 266 runnable.run(); 267 } 268 } 269 } 270 271 private static boolean isEngineClosed(SSLEngine engine) { 272 return (engine.isOutboundDone() && engine.isInboundDone()); 273 } 274 275} 276