1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.harmony.xnet.provider.jsse; 19 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.io.OutputStream; 23 import java.util.Arrays; 24 import javax.net.ssl.HandshakeCompletedEvent; 25 import javax.net.ssl.HandshakeCompletedListener; 26 import javax.net.ssl.SSLContext; 27 import javax.net.ssl.SSLServerSocket; 28 import javax.net.ssl.SSLSocket; 29 30 import junit.framework.Test; 31 import junit.framework.TestCase; 32 import junit.framework.TestSuite; 33 34 /** 35 * SSLSocketImplTest 36 */ 37 public class SSLSocketFunctionalTest extends TestCase { 38 39 /** 40 * The cipher suites used for functionality testing. 41 */ 42 private String[] cipher_suites = { 43 "RSA_WITH_RC4_128_MD5", 44 "RSA_WITH_DES_CBC_SHA", 45 "DH_anon_EXPORT_WITH_DES40_CBC_SHA" 46 }; 47 48 // turn on/off the debug logging 49 private boolean doLog = false; 50 51 /** 52 * Sets up the test case. 53 */ 54 @Override 55 public void setUp() throws Exception { 56 if (doLog) { 57 System.out.println("========================"); 58 System.out.println("====== Running the test: " + getName()); 59 System.out.println("========================"); 60 } 61 } 62 63 public void testContextInitialized2() throws Throwable { 64 doTestSelfInteraction(JSSETestData.getContext()); 65 } 66 67 public void doTestInteraction(SSLContext context, SSLContext ctx_other) 68 throws Throwable { 69 SSLContext ctx1, ctx2; 70 71 ctx1 = context; 72 ctx2 = ctx_other; 73 74 int k = 1; 75 76 SSLServerSocket ssocket = (SSLServerSocket) ctx1 77 .getServerSocketFactory().createServerSocket(0); 78 ssocket.setUseClientMode(false); 79 ssocket.setEnabledCipherSuites( 80 ((k & 1) > 0) 81 ? new String[] { "TLS_" + cipher_suites[0] } 82 : new String[] { "SSL_" + cipher_suites[0] }); 83 84 SSLSocket csocket = (SSLSocket) ctx2 85 .getSocketFactory().createSocket("localhost", 86 ssocket.getLocalPort()); 87 csocket.setEnabledProtocols(new String[] { "TLSv1" }); 88 csocket.setUseClientMode(true); 89 csocket.setEnabledCipherSuites( 90 (((k & 2) >> 1) > 0) 91 ? new String[] { "TLS_" + cipher_suites[0] } 92 : new String[] { "SSL_" + cipher_suites[0] }); 93 doTest(ssocket, csocket); 94 } 95 96 public void _doTestInteraction(SSLContext context, SSLContext ctx_other) 97 throws Throwable { 98 for (int i = 0; i < cipher_suites.length; i++) { 99 if (doLog) { 100 System.out.println("======== Checking the work on cipher: " 101 + cipher_suites[i]); 102 } 103 SSLContext ctx1, ctx2; 104 // k: 00, 01, 10, 11; 105 // where 1 means implementation under the test, 106 // 0 - another implementation to interract with 107 for (int k = 0; k < 4; k++) { 108 if (doLog) { 109 System.out.println("======== " + (k & 1) + " " + ((k & 2) >> 1)); 110 } 111 ctx1 = ((k & 1) > 0) ? context : ctx_other; 112 ctx2 = (((k & 2) >> 1) > 0) ? context : ctx_other; 113 114 SSLServerSocket ssocket = (SSLServerSocket) ctx1 115 .getServerSocketFactory().createServerSocket(0); 116 ssocket.setUseClientMode(false); 117 ssocket.setEnabledCipherSuites( 118 ((k & 1) > 0) 119 ? new String[] { "TLS_" + cipher_suites[i] } 120 : new String[] { "SSL_" + cipher_suites[i] }); 121 122 SSLSocket csocket = (SSLSocket) ctx2 123 .getSocketFactory().createSocket("localhost", 124 ssocket.getLocalPort()); 125 csocket.setEnabledProtocols(new String[] { "TLSv1" }); 126 csocket.setUseClientMode(true); 127 csocket.setEnabledCipherSuites( 128 (((k & 2) >> 1) > 0) 129 ? new String[] { "TLS_" + cipher_suites[i] } 130 : new String[] { "SSL_" + cipher_suites[i] }); 131 doTest(ssocket, csocket); 132 } 133 } 134 } 135 136 /** 137 * Tests the interaction with other implementation. 138 */ 139 public void doTestSelfInteraction(SSLContext context) 140 throws Throwable { 141 String[] protocols = { "SSLv3", "TLSv1" }; 142 for (int i = 0; i < cipher_suites.length; i++) { 143 for (int j = 0; j < 2; j++) { 144 if (doLog) { 145 System.out.println("======= " + cipher_suites[i]); 146 } 147 SSLServerSocket ssocket = (SSLServerSocket) context 148 .getServerSocketFactory().createServerSocket(0); 149 ssocket.setUseClientMode(false); 150 ssocket.setEnabledProtocols(new String[] { protocols[j] }); 151 ssocket.setEnabledCipherSuites( 152 new String[] { "TLS_" + cipher_suites[i] }); 153 154 SSLSocket csocket = (SSLSocket) context 155 .getSocketFactory().createSocket("localhost", 156 ssocket.getLocalPort()); 157 csocket.setEnabledProtocols(new String[] { protocols[j] }); 158 csocket.setUseClientMode(true); 159 csocket.setEnabledCipherSuites( 160 new String[] { "TLS_" + cipher_suites[i] }); 161 162 doTest(ssocket, csocket); 163 } 164 } 165 } 166 167 private static class HandshakeListener 168 implements HandshakeCompletedListener { 169 boolean compleated = false; 170 171 public void handshakeCompleted(HandshakeCompletedEvent event) { 172 compleated = true; 173 } 174 } 175 176 /** 177 * Performs SSL connection between the sockets 178 * 179 * @return 180 */ 181 public void doTest(SSLServerSocket ssocket, SSLSocket csocket) 182 throws Throwable { 183 final String server_message = "Hello from SSL Server Socket!"; 184 final String client_message = "Hello from SSL Socket!"; 185 Thread server = null; 186 Thread client = null; 187 final Throwable[] throwed = new Throwable[1]; 188 try { 189 final SSLServerSocket ss = ssocket; 190 final SSLSocket s = csocket; 191 server = new Thread() { 192 @Override 193 public void run() { 194 InputStream is = null; 195 OutputStream os = null; 196 SSLSocket s = null; 197 try { 198 s = (SSLSocket) ss.accept(); 199 if (doLog) { 200 System.out.println("Socket accepted: " + s); 201 } 202 is = s.getInputStream(); 203 os = s.getOutputStream(); 204 // send the message to the client 205 os.write(server_message.getBytes()); 206 // read the response 207 byte[] buff = new byte[client_message.length()]; 208 int len = is.read(buff); 209 if (doLog) { 210 System.out.println("Received message of length " 211 + len + ": '" + new String(buff, 0, len) + "'"); 212 } 213 assertTrue("Read message does not equal to expected", 214 Arrays.equals(client_message.getBytes(), buff)); 215 os.write(-1); 216 assertEquals("Read data differs from expected", 217 255, is.read()); 218 if (doLog) { 219 System.out.println("Server is closed: " 220 + s.isClosed()); 221 } 222 assertEquals("Returned value should be -1", 223 // initiate an exchange of closure alerts 224 -1, is.read()); 225 if (doLog) { 226 System.out.println("Server is closed: " 227 + s.isClosed()); 228 } 229 assertEquals("Returned value should be -1", 230 // initiate an exchange of closure alerts 231 -1, is.read()); 232 } catch (Throwable e) { 233 synchronized (throwed) { 234 if (doLog) { 235 e.printStackTrace(); 236 } 237 if (throwed[0] == null) { 238 throwed[0] = e; 239 } 240 } 241 } finally { 242 try { 243 if (is != null) { 244 is.close(); 245 } 246 } catch (IOException ex) { 247 } 248 try { 249 if (os != null) { 250 os.close(); 251 } 252 } catch (IOException ex) { 253 } 254 try { 255 if (s != null) { 256 s.close(); 257 } 258 } catch (IOException ex) { 259 } 260 } 261 } 262 }; 263 264 client = new Thread() { 265 @Override 266 public void run() { 267 InputStream is = null; 268 OutputStream os = null; 269 try { 270 assertTrue("Client was not connected", s.isConnected()); 271 if (doLog) { 272 System.out.println("Client connected"); 273 } 274 is = s.getInputStream(); 275 os = s.getOutputStream(); 276 s.startHandshake(); 277 if (doLog) { 278 System.out.println("Client: HS was done"); 279 } 280 // read the message from the server 281 byte[] buff = new byte[server_message.length()]; 282 int len = is.read(buff); 283 if (doLog) { 284 System.out.println("Received message of length " 285 + len + ": '" + new String(buff, 0, len) + "'"); 286 } 287 assertTrue("Read message does not equal to expected", 288 Arrays.equals(server_message.getBytes(), buff)); 289 // send the response 290 buff = (" " + client_message + " ").getBytes(); 291 os.write(buff, 1, buff.length - 2); 292 assertEquals("Read data differs from expected", 293 255, is.read()); 294 os.write(-1); 295 if (doLog) { 296 System.out.println("\n======== Closing ========"); 297 } 298 if (doLog) { 299 System.out.println("Client is closed: " 300 + s.isClosed()); 301 } 302 s.close(); 303 if (doLog) { 304 System.out.println("Client is closed: " 305 + s.isClosed()); 306 } 307 } catch (Throwable e) { 308 synchronized (throwed) { 309 if (doLog) { 310 e.printStackTrace(); 311 } 312 if (throwed[0] == null) { 313 throwed[0] = e; 314 } 315 } 316 } finally { 317 try { 318 if (is != null) { 319 is.close(); 320 } 321 } catch (IOException ex) { 322 } 323 try { 324 if (os != null) { 325 os.close(); 326 } 327 } catch (IOException ex) { 328 } 329 try { 330 if (s != null) { 331 s.close(); 332 } 333 } catch (IOException ex) { 334 } 335 } 336 } 337 }; 338 339 server.start(); 340 client.start(); 341 342 while (server.isAlive() || client.isAlive()) { 343 if (throwed[0] != null) { 344 throw throwed[0]; 345 } 346 try { 347 Thread.sleep(500); 348 } catch (Exception e) { 349 } 350 } 351 } finally { 352 if (server != null) { 353 server.stop(); 354 } 355 if (client != null) { 356 client.stop(); 357 } 358 } 359 if (throwed[0] != null) { 360 throw throwed[0]; 361 } 362 } 363 364 public static Test suite() { 365 return new TestSuite(SSLSocketFunctionalTest.class); 366 } 367 368 } 369