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.tomcat.util.net.jsse; 19 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.FileNotFoundException; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.net.InetAddress; 26 import java.net.ServerSocket; 27 import java.net.Socket; 28 import java.net.SocketException; 29 import java.security.KeyStore; 30 import java.security.SecureRandom; 31 import java.security.cert.CRL; 32 import java.security.cert.CRLException; 33 import java.security.cert.CertPathParameters; 34 import java.security.cert.CertStore; 35 import java.security.cert.CertStoreParameters; 36 import java.security.cert.CertificateException; 37 import java.security.cert.CertificateFactory; 38 import java.security.cert.CollectionCertStoreParameters; 39 import java.security.cert.PKIXBuilderParameters; 40 import java.security.cert.X509CertSelector; 41 import java.util.Collection; 42 import java.util.Vector; 43 44 import javax.net.ssl.CertPathTrustManagerParameters; 45 import javax.net.ssl.KeyManager; 46 import javax.net.ssl.KeyManagerFactory; 47 import javax.net.ssl.ManagerFactoryParameters; 48 import javax.net.ssl.SSLContext; 49 import javax.net.ssl.SSLException; 50 import javax.net.ssl.SSLServerSocket; 51 import javax.net.ssl.SSLServerSocketFactory; 52 import javax.net.ssl.SSLSessionContext; 53 import javax.net.ssl.SSLSocket; 54 import javax.net.ssl.TrustManager; 55 import javax.net.ssl.TrustManagerFactory; 56 import javax.net.ssl.X509KeyManager; 57 58 import org.apache.tomcat.util.res.StringManager; 59 60 /* 61 1. Make the JSSE's jars available, either as an installed 62 extension (copy them into jre/lib/ext) or by adding 63 them to the Tomcat classpath. 64 2. keytool -genkey -alias tomcat -keyalg RSA 65 Use "changeit" as password ( this is the default we use ) 66 */ 67 68 /** 69 * SSL server socket factory. It _requires_ a valid RSA key and 70 * JSSE. 71 * 72 * @author Harish Prabandham 73 * @author Costin Manolache 74 * @author Stefan Freyr Stefansson 75 * @author EKR -- renamed to JSSESocketFactory 76 * @author Jan Luehe 77 * @author Bill Barker 78 */ 79 public class JSSESocketFactory 80 extends org.apache.tomcat.util.net.ServerSocketFactory { 81 82 private static StringManager sm = 83 StringManager.getManager("org.apache.tomcat.util.net.jsse.res"); 84 85 // defaults 86 static String defaultProtocol = "TLS"; 87 static boolean defaultClientAuth = false; 88 static String defaultKeystoreType = "JKS"; 89 private static final String defaultKeystoreFile 90 = System.getProperty("user.home") + "/.keystore"; 91 private static final String defaultKeyPass = "changeit"; 92 private static final int defaultSessionCacheSize = 0; 93 private static final int defaultSessionTimeout = 86400; 94 95 static org.apache.juli.logging.Log log = 96 org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class); 97 98 protected boolean initialized; 99 protected String clientAuth = "false"; 100 protected SSLServerSocketFactory sslProxy = null; 101 protected String[] enabledCiphers; 102 protected boolean allowUnsafeLegacyRenegotiation = false; 103 104 /** 105 * Flag to state that we require client authentication. 106 */ 107 protected boolean requireClientAuth = false; 108 109 /** 110 * Flag to state that we would like client authentication. 111 */ 112 protected boolean wantClientAuth = false; 113 114 115 public JSSESocketFactory () { 116 } 117 118 public ServerSocket createSocket (int port) 119 throws IOException 120 { 121 if (!initialized) init(); 122 ServerSocket socket = sslProxy.createServerSocket(port); 123 initServerSocket(socket); 124 return socket; 125 } 126 127 public ServerSocket createSocket (int port, int backlog) 128 throws IOException 129 { 130 if (!initialized) init(); 131 ServerSocket socket = sslProxy.createServerSocket(port, backlog); 132 initServerSocket(socket); 133 return socket; 134 } 135 136 public ServerSocket createSocket (int port, int backlog, 137 InetAddress ifAddress) 138 throws IOException 139 { 140 if (!initialized) init(); 141 ServerSocket socket = sslProxy.createServerSocket(port, backlog, 142 ifAddress); 143 initServerSocket(socket); 144 return socket; 145 } 146 147 public Socket acceptSocket(ServerSocket socket) 148 throws IOException 149 { 150 SSLSocket asock = null; 151 try { 152 asock = (SSLSocket)socket.accept(); 153 configureClientAuth(asock); 154 } catch (SSLException e){ 155 throw new SocketException("SSL handshake error" + e.toString()); 156 } 157 return asock; 158 } 159 160 public void handshake(Socket sock) throws IOException { 161 ((SSLSocket)sock).startHandshake(); 162 163 if (!allowUnsafeLegacyRenegotiation) { 164 // Prevent futher handshakes by removing all cipher suites 165 ((SSLSocket) sock).setEnabledCipherSuites(new String[0]); 166 } 167 } 168 169 /* 170 * Determines the SSL cipher suites to be enabled. 171 * 172 * @param requestedCiphers Comma-separated list of requested ciphers 173 * @param supportedCiphers Array of supported ciphers 174 * 175 * @return Array of SSL cipher suites to be enabled, or null if none of the 176 * requested ciphers are supported 177 */ 178 protected String[] getEnabledCiphers(String requestedCiphers, 179 String[] supportedCiphers) { 180 181 String[] enabledCiphers = null; 182 183 if (requestedCiphers != null) { 184 Vector vec = null; 185 String cipher = requestedCiphers; 186 int index = requestedCiphers.indexOf(','); 187 if (index != -1) { 188 int fromIndex = 0; 189 while (index != -1) { 190 cipher = requestedCiphers.substring(fromIndex, index).trim(); 191 if (cipher.length() > 0) { 192 /* 193 * Check to see if the requested cipher is among the 194 * supported ciphers, i.e., may be enabled 195 */ 196 for (int i=0; supportedCiphers != null 197 && i<supportedCiphers.length; i++) { 198 if (supportedCiphers[i].equals(cipher)) { 199 if (vec == null) { 200 vec = new Vector(); 201 } 202 vec.addElement(cipher); 203 break; 204 } 205 } 206 } 207 fromIndex = index+1; 208 index = requestedCiphers.indexOf(',', fromIndex); 209 } // while 210 cipher = requestedCiphers.substring(fromIndex); 211 } 212 213 if (cipher != null) { 214 cipher = cipher.trim(); 215 if (cipher.length() > 0) { 216 /* 217 * Check to see if the requested cipher is among the 218 * supported ciphers, i.e., may be enabled 219 */ 220 for (int i=0; supportedCiphers != null 221 && i<supportedCiphers.length; i++) { 222 if (supportedCiphers[i].equals(cipher)) { 223 if (vec == null) { 224 vec = new Vector(); 225 } 226 vec.addElement(cipher); 227 break; 228 } 229 } 230 } 231 } 232 233 if (vec != null) { 234 enabledCiphers = new String[vec.size()]; 235 vec.copyInto(enabledCiphers); 236 } 237 } else { 238 enabledCiphers = sslProxy.getDefaultCipherSuites(); 239 } 240 241 return enabledCiphers; 242 } 243 244 /* 245 * Gets the SSL server's keystore password. 246 */ 247 protected String getKeystorePassword() { 248 String keyPass = (String)attributes.get("keypass"); 249 if (keyPass == null) { 250 keyPass = defaultKeyPass; 251 } 252 String keystorePass = (String)attributes.get("keystorePass"); 253 if (keystorePass == null) { 254 keystorePass = keyPass; 255 } 256 return keystorePass; 257 } 258 259 /* 260 * Gets the SSL server's keystore. 261 */ 262 protected KeyStore getKeystore(String type, String provider, String pass) 263 throws IOException { 264 265 String keystoreFile = (String)attributes.get("keystore"); 266 if (keystoreFile == null) 267 keystoreFile = defaultKeystoreFile; 268 269 return getStore(type, provider, keystoreFile, pass); 270 } 271 272 /* 273 * Gets the SSL server's truststore. 274 */ 275 protected KeyStore getTrustStore(String keystoreType, 276 String keystoreProvider) throws IOException { 277 KeyStore trustStore = null; 278 279 String truststoreFile = (String)attributes.get("truststoreFile"); 280 if(truststoreFile == null) { 281 truststoreFile = System.getProperty("javax.net.ssl.trustStore"); 282 } 283 if(log.isDebugEnabled()) { 284 log.debug("Truststore = " + truststoreFile); 285 } 286 String truststorePassword = (String)attributes.get("truststorePass"); 287 if( truststorePassword == null) { 288 truststorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); 289 } 290 if( truststorePassword == null ) { 291 truststorePassword = getKeystorePassword(); 292 } 293 if(log.isDebugEnabled()) { 294 log.debug("TrustPass = " + truststorePassword); 295 } 296 String truststoreType = (String)attributes.get("truststoreType"); 297 if( truststoreType == null) { 298 truststoreType = System.getProperty("javax.net.ssl.trustStoreType"); 299 } 300 if(truststoreType == null) { 301 truststoreType = keystoreType; 302 } 303 if(log.isDebugEnabled()) { 304 log.debug("trustType = " + truststoreType); 305 } 306 String truststoreProvider = 307 (String)attributes.get("truststoreProvider"); 308 if( truststoreProvider == null) { 309 truststoreProvider = 310 System.getProperty("javax.net.ssl.trustStoreProvider"); 311 } 312 if (truststoreProvider == null) { 313 truststoreProvider = keystoreProvider; 314 } 315 if(log.isDebugEnabled()) { 316 log.debug("trustProvider = " + truststoreProvider); 317 } 318 319 if (truststoreFile != null && truststorePassword != null){ 320 trustStore = getStore(truststoreType, truststoreProvider, 321 truststoreFile, truststorePassword); 322 } 323 324 return trustStore; 325 } 326 327 /* 328 * Gets the key- or truststore with the specified type, path, and password. 329 */ 330 private KeyStore getStore(String type, String provider, String path, 331 String pass) throws IOException { 332 333 KeyStore ks = null; 334 InputStream istream = null; 335 try { 336 if (provider == null) { 337 ks = KeyStore.getInstance(type); 338 } else { 339 ks = KeyStore.getInstance(type, provider); 340 } 341 if(!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) { 342 File keyStoreFile = new File(path); 343 if (!keyStoreFile.isAbsolute()) { 344 keyStoreFile = new File(System.getProperty("catalina.base"), 345 path); 346 } 347 istream = new FileInputStream(keyStoreFile); 348 } 349 350 ks.load(istream, pass.toCharArray()); 351 } catch (FileNotFoundException fnfe) { 352 log.error(sm.getString("jsse.keystore_load_failed", type, path, 353 fnfe.getMessage()), fnfe); 354 throw fnfe; 355 } catch (IOException ioe) { 356 log.error(sm.getString("jsse.keystore_load_failed", type, path, 357 ioe.getMessage()), ioe); 358 throw ioe; 359 } catch(Exception ex) { 360 String msg = sm.getString("jsse.keystore_load_failed", type, path, 361 ex.getMessage()); 362 log.error(msg, ex); 363 throw new IOException(msg); 364 } finally { 365 if (istream != null) { 366 try { 367 istream.close(); 368 } catch (IOException ioe) { 369 // Do nothing 370 } 371 } 372 } 373 374 return ks; 375 } 376 377 /** 378 * Reads the keystore and initializes the SSL socket factory. 379 */ 380 void init() throws IOException { 381 try { 382 383 String clientAuthStr = (String) attributes.get("clientauth"); 384 if("true".equalsIgnoreCase(clientAuthStr) || 385 "yes".equalsIgnoreCase(clientAuthStr)) { 386 requireClientAuth = true; 387 } else if("want".equalsIgnoreCase(clientAuthStr)) { 388 wantClientAuth = true; 389 } 390 391 // SSL protocol variant (e.g., TLS, SSL v3, etc.) 392 String protocol = (String) attributes.get("protocol"); 393 if (protocol == null) { 394 protocol = defaultProtocol; 395 } 396 397 // Certificate encoding algorithm (e.g., SunX509) 398 String algorithm = (String) attributes.get("algorithm"); 399 if (algorithm == null) { 400 algorithm = KeyManagerFactory.getDefaultAlgorithm();; 401 } 402 403 String keystoreType = (String) attributes.get("keystoreType"); 404 if (keystoreType == null) { 405 keystoreType = defaultKeystoreType; 406 } 407 408 String keystoreProvider = 409 (String) attributes.get("keystoreProvider"); 410 411 String trustAlgorithm = 412 (String)attributes.get("truststoreAlgorithm"); 413 if( trustAlgorithm == null ) { 414 trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 415 } 416 417 // Create and init SSLContext 418 SSLContext context = SSLContext.getInstance(protocol); 419 context.init(getKeyManagers(keystoreType, keystoreProvider, 420 algorithm, 421 (String) attributes.get("keyAlias")), 422 getTrustManagers(keystoreType, keystoreProvider, 423 trustAlgorithm), 424 new SecureRandom()); 425 426 // Configure SSL session cache 427 int sessionCacheSize; 428 if (attributes.get("sessionCacheSize") != null) { 429 sessionCacheSize = Integer.parseInt( 430 (String)attributes.get("sessionCacheSize")); 431 } else { 432 sessionCacheSize = defaultSessionCacheSize; 433 } 434 int sessionCacheTimeout; 435 if (attributes.get("sessionCacheTimeout") != null) { 436 sessionCacheTimeout = Integer.parseInt( 437 (String)attributes.get("sessionCacheTimeout")); 438 } else { 439 sessionCacheTimeout = defaultSessionTimeout; 440 } 441 SSLSessionContext sessionContext = 442 context.getServerSessionContext(); 443 if (sessionContext != null) { 444 sessionContext.setSessionCacheSize(sessionCacheSize); 445 sessionContext.setSessionTimeout(sessionCacheTimeout); 446 } 447 448 // create proxy 449 sslProxy = context.getServerSocketFactory(); 450 451 // Determine which cipher suites to enable 452 String requestedCiphers = (String)attributes.get("ciphers"); 453 enabledCiphers = getEnabledCiphers(requestedCiphers, 454 sslProxy.getSupportedCipherSuites()); 455 456 allowUnsafeLegacyRenegotiation = 457 "true".equals(attributes.get("allowUnsafeLegacyRenegotiation")); 458 459 // Check the SSL config is OK 460 checkConfig(); 461 462 } catch(Exception e) { 463 if( e instanceof IOException ) 464 throw (IOException)e; 465 throw new IOException(e.getMessage()); 466 } 467 } 468 469 /** 470 * Gets the initialized key managers. 471 */ 472 protected KeyManager[] getKeyManagers(String keystoreType, 473 String keystoreProvider, 474 String algorithm, 475 String keyAlias) 476 throws Exception { 477 478 KeyManager[] kms = null; 479 480 String keystorePass = getKeystorePassword(); 481 482 KeyStore ks = getKeystore(keystoreType, keystoreProvider, keystorePass); 483 if (keyAlias != null && !ks.isKeyEntry(keyAlias)) { 484 throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias)); 485 } 486 487 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 488 kmf.init(ks, keystorePass.toCharArray()); 489 490 kms = kmf.getKeyManagers(); 491 if (keyAlias != null) { 492 if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) { 493 keyAlias = keyAlias.toLowerCase(); 494 } 495 for(int i=0; i<kms.length; i++) { 496 kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias); 497 } 498 } 499 500 return kms; 501 } 502 503 /** 504 * Gets the intialized trust managers. 505 */ 506 protected TrustManager[] getTrustManagers(String keystoreType, 507 String keystoreProvider, String algorithm) 508 throws Exception { 509 String crlf = (String) attributes.get("crlFile"); 510 511 TrustManager[] tms = null; 512 513 KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider); 514 if (trustStore != null) { 515 if (crlf == null) { 516 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 517 tmf.init(trustStore); 518 tms = tmf.getTrustManagers(); 519 } else { 520 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 521 CertPathParameters params = getParameters(algorithm, crlf, trustStore); 522 ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params); 523 tmf.init(mfp); 524 tms = tmf.getTrustManagers(); 525 } 526 } 527 528 return tms; 529 } 530 531 /** 532 * Return the initialization parameters for the TrustManager. 533 * Currently, only the default <code>PKIX</code> is supported. 534 * 535 * @param algorithm The algorithm to get parameters for. 536 * @param crlf The path to the CRL file. 537 * @param trustStore The configured TrustStore. 538 * @return The parameters including the CRLs and TrustStore. 539 */ 540 protected CertPathParameters getParameters(String algorithm, 541 String crlf, 542 KeyStore trustStore) 543 throws Exception { 544 CertPathParameters params = null; 545 if("PKIX".equalsIgnoreCase(algorithm)) { 546 PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, 547 new X509CertSelector()); 548 Collection crls = getCRLs(crlf); 549 CertStoreParameters csp = new CollectionCertStoreParameters(crls); 550 CertStore store = CertStore.getInstance("Collection", csp); 551 xparams.addCertStore(store); 552 xparams.setRevocationEnabled(true); 553 String trustLength = (String)attributes.get("trustMaxCertLength"); 554 if(trustLength != null) { 555 try { 556 xparams.setMaxPathLength(Integer.parseInt(trustLength)); 557 } catch(Exception ex) { 558 log.warn("Bad maxCertLength: "+trustLength); 559 } 560 } 561 562 params = xparams; 563 } else { 564 throw new CRLException("CRLs not supported for type: "+algorithm); 565 } 566 return params; 567 } 568 569 570 /** 571 * Load the collection of CRLs. 572 * 573 */ 574 protected Collection<? extends CRL> getCRLs(String crlf) 575 throws IOException, CRLException, CertificateException { 576 577 File crlFile = new File(crlf); 578 if( !crlFile.isAbsolute() ) { 579 crlFile = new File(System.getProperty("catalina.base"), crlf); 580 } 581 Collection<? extends CRL> crls = null; 582 InputStream is = null; 583 try { 584 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 585 is = new FileInputStream(crlFile); 586 crls = cf.generateCRLs(is); 587 } catch(IOException iex) { 588 throw iex; 589 } catch(CRLException crle) { 590 throw crle; 591 } catch(CertificateException ce) { 592 throw ce; 593 } finally { 594 if(is != null) { 595 try{ 596 is.close(); 597 } catch(Exception ex) { 598 } 599 } 600 } 601 return crls; 602 } 603 604 /** 605 * Set the SSL protocol variants to be enabled. 606 * @param socket the SSLServerSocket. 607 * @param protocols the protocols to use. 608 */ 609 protected void setEnabledProtocols(SSLServerSocket socket, String []protocols){ 610 if (protocols != null) { 611 socket.setEnabledProtocols(protocols); 612 } 613 } 614 615 /** 616 * Determines the SSL protocol variants to be enabled. 617 * 618 * @param socket The socket to get supported list from. 619 * @param requestedProtocols Comma-separated list of requested SSL 620 * protocol variants 621 * 622 * @return Array of SSL protocol variants to be enabled, or null if none of 623 * the requested protocol variants are supported 624 */ 625 protected String[] getEnabledProtocols(SSLServerSocket socket, 626 String requestedProtocols){ 627 String[] supportedProtocols = socket.getSupportedProtocols(); 628 629 String[] enabledProtocols = null; 630 631 if (requestedProtocols != null) { 632 Vector vec = null; 633 String protocol = requestedProtocols; 634 int index = requestedProtocols.indexOf(','); 635 if (index != -1) { 636 int fromIndex = 0; 637 while (index != -1) { 638 protocol = requestedProtocols.substring(fromIndex, index).trim(); 639 if (protocol.length() > 0) { 640 /* 641 * Check to see if the requested protocol is among the 642 * supported protocols, i.e., may be enabled 643 */ 644 for (int i=0; supportedProtocols != null 645 && i<supportedProtocols.length; i++) { 646 if (supportedProtocols[i].equals(protocol)) { 647 if (vec == null) { 648 vec = new Vector(); 649 } 650 vec.addElement(protocol); 651 break; 652 } 653 } 654 } 655 fromIndex = index+1; 656 index = requestedProtocols.indexOf(',', fromIndex); 657 } // while 658 protocol = requestedProtocols.substring(fromIndex); 659 } 660 661 if (protocol != null) { 662 protocol = protocol.trim(); 663 if (protocol.length() > 0) { 664 /* 665 * Check to see if the requested protocol is among the 666 * supported protocols, i.e., may be enabled 667 */ 668 for (int i=0; supportedProtocols != null 669 && i<supportedProtocols.length; i++) { 670 if (supportedProtocols[i].equals(protocol)) { 671 if (vec == null) { 672 vec = new Vector(); 673 } 674 vec.addElement(protocol); 675 break; 676 } 677 } 678 } 679 } 680 681 if (vec != null) { 682 enabledProtocols = new String[vec.size()]; 683 vec.copyInto(enabledProtocols); 684 } 685 } 686 687 return enabledProtocols; 688 } 689 690 /** 691 * Configure Client authentication for this version of JSSE. The 692 * JSSE included in Java 1.4 supports the 'want' value. Prior 693 * versions of JSSE will treat 'want' as 'false'. 694 * @param socket the SSLServerSocket 695 */ 696 protected void configureClientAuth(SSLServerSocket socket){ 697 if (wantClientAuth){ 698 socket.setWantClientAuth(wantClientAuth); 699 } else { 700 socket.setNeedClientAuth(requireClientAuth); 701 } 702 } 703 704 /** 705 * Configure Client authentication for this version of JSSE. The 706 * JSSE included in Java 1.4 supports the 'want' value. Prior 707 * versions of JSSE will treat 'want' as 'false'. 708 * @param socket the SSLSocket 709 */ 710 protected void configureClientAuth(SSLSocket socket){ 711 // Per JavaDocs: SSLSockets returned from 712 // SSLServerSocket.accept() inherit this setting. 713 } 714 715 /** 716 * Configures the given SSL server socket with the requested cipher suites, 717 * protocol versions, and need for client authentication 718 */ 719 private void initServerSocket(ServerSocket ssocket) { 720 721 SSLServerSocket socket = (SSLServerSocket) ssocket; 722 723 if (enabledCiphers != null) { 724 socket.setEnabledCipherSuites(enabledCiphers); 725 } 726 727 String requestedProtocols = (String) attributes.get("protocols"); 728 setEnabledProtocols(socket, getEnabledProtocols(socket, 729 requestedProtocols)); 730 731 // we don't know if client auth is needed - 732 // after parsing the request we may re-handshake 733 configureClientAuth(socket); 734 } 735 736 /** 737 * Checks that the certificate is compatible with the enabled cipher suites. 738 * If we don't check now, the JIoEndpoint can enter a nasty logging loop. 739 * See bug 45528. 740 */ 741 private void checkConfig() throws IOException { 742 // Create an unbound server socket 743 ServerSocket socket = sslProxy.createServerSocket(); 744 initServerSocket(socket); 745 746 try { 747 // Set the timeout to 1ms as all we care about is if it throws an 748 // SSLException on accept. 749 socket.setSoTimeout(1); 750 751 socket.accept(); 752 // Will never get here - no client can connect to an unbound port 753 } catch (SSLException ssle) { 754 // SSL configuration is invalid. Possibly cert doesn't match ciphers 755 IOException ioe = new IOException(sm.getString( 756 "jsse.invalid_ssl_conf", ssle.getMessage())); 757 ioe.initCause(ssle); 758 throw ioe; 759 } catch (Exception e) { 760 /* 761 * Possible ways of getting here 762 * socket.accept() throws a SecurityException 763 * socket.setSoTimeout() throws a SocketException 764 * socket.accept() throws some other exception (after a JDK change) 765 * In these cases the test won't work so carry on - essentially 766 * the behaviour before this patch 767 * socket.accept() throws a SocketTimeoutException 768 * In this case all is well so carry on 769 */ 770 } finally { 771 // Should be open here but just in case 772 if (!socket.isClosed()) { 773 socket.close(); 774 } 775 } 776 777 } 778 }