001 /* 002 * Copyright 2008-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2015 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021 package com.unboundid.util.ssl; 022 023 024 025 import java.io.IOException; 026 import java.lang.reflect.Method; 027 import java.net.Socket; 028 import java.security.GeneralSecurityException; 029 import java.util.ArrayList; 030 import java.util.Arrays; 031 import java.util.Collection; 032 import java.util.Collections; 033 import java.util.HashSet; 034 import java.util.Iterator; 035 import java.util.Set; 036 import java.util.StringTokenizer; 037 import java.util.concurrent.atomic.AtomicReference; 038 import javax.net.ssl.KeyManager; 039 import javax.net.ssl.SSLContext; 040 import javax.net.ssl.SSLSocket; 041 import javax.net.ssl.SSLSocketFactory; 042 import javax.net.ssl.SSLServerSocketFactory; 043 import javax.net.ssl.TrustManager; 044 045 import com.unboundid.ldap.sdk.LDAPException; 046 import com.unboundid.ldap.sdk.ResultCode; 047 import com.unboundid.util.Debug; 048 import com.unboundid.util.StaticUtils; 049 050 import static com.unboundid.util.Validator.*; 051 import static com.unboundid.util.ssl.SSLMessages.*; 052 053 054 055 /** 056 * This class provides a simple interface for creating {@code SSLContext} and 057 * {@code SSLSocketFactory} instances, which may be used to create SSL-based 058 * connections, or secure existing connections with StartTLS. 059 * <BR><BR> 060 * <H2>Example 1</H2> 061 * The following example demonstrates the use of the SSL helper to create an 062 * SSL-based LDAP connection that will blindly trust any certificate that the 063 * server presents. Using the {@code TrustAllTrustManager} is only recommended 064 * for testing purposes, since blindly trusting any certificate is not secure. 065 * <PRE> 066 * // Create an SSLUtil instance that is configured to trust any certificate, 067 * // and use it to create a socket factory. 068 * SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); 069 * SSLSocketFactory sslSocketFactory = sslUtil.createSSLSocketFactory(); 070 * 071 * // Establish a secure connection using the socket factory. 072 * LDAPConnection connection = new LDAPConnection(sslSocketFactory); 073 * connection.connect(serverAddress, serverSSLPort); 074 * 075 * // Process operations using the connection.... 076 * RootDSE rootDSE = connection.getRootDSE(); 077 * 078 * connection.close(); 079 * </PRE> 080 * <BR> 081 * <H2>Example 2</H2> 082 * The following example demonstrates the use of the SSL helper to create a 083 * non-secure LDAP connection and then use the StartTLS extended operation to 084 * secure it. It will use a trust store to determine whether to trust the 085 * server certificate. 086 * <PRE> 087 * // Establish a non-secure connection to the server. 088 * LDAPConnection connection = new LDAPConnection(serverAddress, serverPort); 089 * 090 * // Create an SSLUtil instance that is configured to trust certificates in 091 * // a specified trust store file, and use it to create an SSLContext that 092 * // will be used for StartTLS processing. 093 * SSLUtil sslUtil = new SSLUtil(new TrustStoreTrustManager(trustStorePath)); 094 * SSLContext sslContext = sslUtil.createSSLContext(); 095 * 096 * // Use the StartTLS extended operation to secure the connection. 097 * StartTLSExtendedRequest startTLSRequest = 098 * new StartTLSExtendedRequest(sslContext); 099 * ExtendedResult startTLSResult; 100 * try 101 * { 102 * startTLSResult = connection.processExtendedOperation(startTLSRequest); 103 * } 104 * catch (LDAPException le) 105 * { 106 * startTLSResult = new ExtendedResult(le); 107 * } 108 * LDAPTestUtils.assertResultCodeEquals(startTLSResult, ResultCode.SUCCESS); 109 * 110 * // Process operations using the connection.... 111 * RootDSE rootDSE = connection.getRootDSE(); 112 * 113 * connection.close(); 114 * </PRE> 115 */ 116 public final class SSLUtil 117 { 118 /** 119 * The name of the system property that can be used to specify the initial 120 * value for the default SSL protocol that should be used. If this is not 121 * set, then the default SSL protocol will be dynamically determined. This 122 * can be overridden via the {@code setDefaultSSLProtocol(String)} method. 123 */ 124 public static final String PROPERTY_DEFAULT_SSL_PROTOCOL = 125 "com.unboundid.util.SSLUtil.defaultSSLProtocol"; 126 127 128 129 /** 130 * The name of the system property that can be used to provide the initial 131 * set of enabled SSL protocols that should be used, as a comma-delimited 132 * list. If this is not set, then the enabled SSL protocols will be 133 * dynamically determined. This can be overridden via the 134 * {@code setEnabledSSLProtocols(java.util.Collection)} method. 135 */ 136 public static final String PROPERTY_ENABLED_SSL_PROTOCOLS = 137 "com.unboundid.util.SSLUtil.enabledSSLProtocols"; 138 139 140 141 /** 142 * The default protocol string that will be used to create SSL contexts when 143 * no explicit protocol is specified. 144 */ 145 private static final AtomicReference<String> DEFAULT_SSL_PROTOCOL = 146 new AtomicReference<String>("TLSv1"); 147 148 149 150 /** 151 * The default set of SSL protocols that will be enabled for use if available 152 * for SSL sockets created within the LDAP SDK. 153 */ 154 private static final AtomicReference<Set<String>> ENABLED_SSL_PROTOCOLS = 155 new AtomicReference<Set<String>>(); 156 157 158 159 static 160 { 161 configureSSLDefaults(); 162 } 163 164 165 166 // The set of key managers to be used. 167 private final KeyManager[] keyManagers; 168 169 // The set of trust managers to be used. 170 private final TrustManager[] trustManagers; 171 172 173 174 /** 175 * Creates a new SSLUtil instance that will not have a custom key manager or 176 * trust manager. It will not be able to provide a certificate to the server 177 * if one is requested, and it will only trust certificates signed by a 178 * predefined set of authorities. 179 */ 180 public SSLUtil() 181 { 182 keyManagers = null; 183 trustManagers = null; 184 } 185 186 187 188 /** 189 * Creates a new SSLUtil instance that will use the provided trust manager to 190 * determine whether to trust server certificates presented to the client. 191 * It will not be able to provide a certificate to the server if one is 192 * requested. 193 * 194 * @param trustManager The trust manager to use to determine whether to 195 * trust server certificates presented to the client. 196 * It may be {@code null} if the default set of trust 197 * managers should be used. 198 */ 199 public SSLUtil(final TrustManager trustManager) 200 { 201 keyManagers = null; 202 203 if (trustManager == null) 204 { 205 trustManagers = null; 206 } 207 else 208 { 209 trustManagers = new TrustManager[] { trustManager }; 210 } 211 } 212 213 214 215 /** 216 * Creates a new SSLUtil instance that will use the provided trust managers 217 * to determine whether to trust server certificates presented to the client. 218 * It will not be able to provide a certificate to the server if one is 219 * requested. 220 * 221 * @param trustManagers The set of trust managers to use to determine 222 * whether to trust server certificates presented to 223 * the client. It may be {@code null} or empty if the 224 * default set of trust managers should be used. 225 */ 226 public SSLUtil(final TrustManager[] trustManagers) 227 { 228 keyManagers = null; 229 230 if ((trustManagers == null) || (trustManagers.length == 0)) 231 { 232 this.trustManagers = null; 233 } 234 else 235 { 236 this.trustManagers = trustManagers; 237 } 238 } 239 240 241 242 /** 243 * Creates a new SSLUtil instance that will use the provided key manager to 244 * obtain certificates to present to the server, and the provided trust 245 * manager to determine whether to trust server certificates presented to the 246 * client. 247 * 248 * @param keyManager The key manager to use to obtain certificates to 249 * present to the server if requested. It may be 250 * {@code null} if no client certificates will be 251 * required or should be provided. 252 * @param trustManager The trust manager to use to determine whether to 253 * trust server certificates presented to the client. 254 * It may be {@code null} if the default set of trust 255 * managers should be used. 256 */ 257 public SSLUtil(final KeyManager keyManager, final TrustManager trustManager) 258 { 259 if (keyManager == null) 260 { 261 keyManagers = null; 262 } 263 else 264 { 265 keyManagers = new KeyManager[] { keyManager }; 266 } 267 268 if (trustManager == null) 269 { 270 trustManagers = null; 271 } 272 else 273 { 274 trustManagers = new TrustManager[] { trustManager }; 275 } 276 } 277 278 279 280 /** 281 * Creates a new SSLUtil instance that will use the provided key managers to 282 * obtain certificates to present to the server, and the provided trust 283 * managers to determine whether to trust server certificates presented to the 284 * client. 285 * 286 * @param keyManagers The set of key managers to use to obtain 287 * certificates to present to the server if requested. 288 * It may be {@code null} or empty if no client 289 * certificates will be required or should be provided. 290 * @param trustManagers The set of trust managers to use to determine 291 * whether to trust server certificates presented to 292 * the client. It may be {@code null} or empty if the 293 * default set of trust managers should be used. 294 */ 295 public SSLUtil(final KeyManager[] keyManagers, 296 final TrustManager[] trustManagers) 297 { 298 if ((keyManagers == null) || (keyManagers.length == 0)) 299 { 300 this.keyManagers = null; 301 } 302 else 303 { 304 this.keyManagers = keyManagers; 305 } 306 307 if ((trustManagers == null) || (trustManagers.length == 0)) 308 { 309 this.trustManagers = null; 310 } 311 else 312 { 313 this.trustManagers = trustManagers; 314 } 315 } 316 317 318 319 /** 320 * Retrieves the set of key managers configured for use by this class, if any. 321 * 322 * @return The set of key managers configured for use by this class, or 323 * {@code null} if none were provided. 324 */ 325 public KeyManager[] getKeyManagers() 326 { 327 return keyManagers; 328 } 329 330 331 332 /** 333 * Retrieves the set of trust managers configured for use by this class, if 334 * any. 335 * 336 * @return The set of trust managers configured for use by this class, or 337 * {@code null} if none were provided. 338 */ 339 public TrustManager[] getTrustManagers() 340 { 341 return trustManagers; 342 } 343 344 345 346 /** 347 * Creates an initialized SSL context created with the configured key and 348 * trust managers. It will use the protocol returned by the 349 * {@code getDefaultSSLProtocol} method and the JVM-default provider. 350 * 351 * @return The created SSL context. 352 * 353 * @throws GeneralSecurityException If a problem occurs while creating or 354 * initializing the SSL context. 355 */ 356 public SSLContext createSSLContext() 357 throws GeneralSecurityException 358 { 359 return createSSLContext(DEFAULT_SSL_PROTOCOL.get()); 360 } 361 362 363 364 /** 365 * Creates an initialized SSL context created with the configured key and 366 * trust managers. It will use the default provider. 367 * 368 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 369 * Architecture document, the set of supported protocols 370 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 371 * "SSLv2Hello". It must not be {@code null}. 372 * 373 * @return The created SSL context. 374 * 375 * @throws GeneralSecurityException If a problem occurs while creating or 376 * initializing the SSL context. 377 */ 378 public SSLContext createSSLContext(final String protocol) 379 throws GeneralSecurityException 380 { 381 ensureNotNull(protocol); 382 383 final SSLContext sslContext = SSLContext.getInstance(protocol); 384 sslContext.init(keyManagers, trustManagers, null); 385 return sslContext; 386 } 387 388 389 390 /** 391 * Creates an initialized SSL context created with the configured key and 392 * trust managers. 393 * 394 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 395 * Architecture document, the set of supported protocols 396 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 397 * "SSLv2Hello". It must not be {@code null}. 398 * @param provider The name of the provider to use for cryptographic 399 * operations. It must not be {@code null}. 400 * 401 * @return The created SSL context. 402 * 403 * @throws GeneralSecurityException If a problem occurs while creating or 404 * initializing the SSL context. 405 */ 406 public SSLContext createSSLContext(final String protocol, 407 final String provider) 408 throws GeneralSecurityException 409 { 410 ensureNotNull(protocol, provider); 411 412 final SSLContext sslContext = SSLContext.getInstance(protocol, provider); 413 sslContext.init(keyManagers, trustManagers, null); 414 return sslContext; 415 } 416 417 418 419 /** 420 * Creates an SSL socket factory using the configured key and trust manager 421 * providers. It will use the protocol returned by the 422 * {@code getDefaultSSLProtocol} method and the JVM-default provider. 423 * 424 * @return The created SSL socket factory. 425 * 426 * @throws GeneralSecurityException If a problem occurs while creating or 427 * initializing the SSL socket factory. 428 */ 429 public SSLSocketFactory createSSLSocketFactory() 430 throws GeneralSecurityException 431 { 432 return new SetEnabledProtocolsSSLSocketFactory( 433 createSSLContext().getSocketFactory(), 434 ENABLED_SSL_PROTOCOLS.get()); 435 } 436 437 438 439 /** 440 * Creates an SSL socket factory with the configured key and trust managers. 441 * It will use the default provider. 442 * 443 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 444 * Architecture document, the set of supported protocols 445 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 446 * "SSLv2Hello". It must not be {@code null}. 447 * 448 * @return The created SSL socket factory. 449 * 450 * @throws GeneralSecurityException If a problem occurs while creating or 451 * initializing the SSL socket factory. 452 */ 453 public SSLSocketFactory createSSLSocketFactory(final String protocol) 454 throws GeneralSecurityException 455 { 456 return new SetEnabledProtocolsSSLSocketFactory( 457 createSSLContext(protocol).getSocketFactory(), protocol); 458 } 459 460 461 462 /** 463 * Creates an SSL socket factory with the configured key and trust managers. 464 * 465 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 466 * Architecture document, the set of supported protocols 467 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 468 * "SSLv2Hello". It must not be {@code null}. 469 * @param provider The name of the provider to use for cryptographic 470 * operations. It must not be {@code null}. 471 * 472 * @return The created SSL socket factory. 473 * 474 * @throws GeneralSecurityException If a problem occurs while creating or 475 * initializing the SSL socket factory. 476 */ 477 public SSLSocketFactory createSSLSocketFactory(final String protocol, 478 final String provider) 479 throws GeneralSecurityException 480 { 481 return createSSLContext(protocol, provider).getSocketFactory(); 482 } 483 484 485 486 /** 487 * Creates an SSL server socket factory using the configured key and trust 488 * manager providers. It will use the protocol returned by the 489 * {@code getDefaultSSLProtocol} method and the JVM-default provider. 490 * 491 * @return The created SSL server socket factory. 492 * 493 * @throws GeneralSecurityException If a problem occurs while creating or 494 * initializing the SSL server socket 495 * factory. 496 */ 497 public SSLServerSocketFactory createSSLServerSocketFactory() 498 throws GeneralSecurityException 499 { 500 return createSSLContext().getServerSocketFactory(); 501 } 502 503 504 505 /** 506 * Creates an SSL server socket factory using the configured key and trust 507 * manager providers. It will use the JVM-default provider. 508 * 509 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 510 * Architecture document, the set of supported protocols 511 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 512 * "SSLv2Hello". It must not be {@code null}. 513 * 514 * @return The created SSL server socket factory. 515 * 516 * @throws GeneralSecurityException If a problem occurs while creating or 517 * initializing the SSL server socket 518 * factory. 519 */ 520 public SSLServerSocketFactory createSSLServerSocketFactory( 521 final String protocol) 522 throws GeneralSecurityException 523 { 524 return createSSLContext(protocol).getServerSocketFactory(); 525 } 526 527 528 529 /** 530 * Creates an SSL server socket factory using the configured key and trust 531 * manager providers. 532 * 533 * @param protocol The protocol to use. As per the Java SE 6 Cryptography 534 * Architecture document, the set of supported protocols 535 * should include at least "SSLv3", "TLSv1", "TLSv1.1", and 536 * "SSLv2Hello". It must not be {@code null}. 537 * @param provider The name of the provider to use for cryptographic 538 * operations. It must not be {@code null}. 539 * 540 * @return The created SSL server socket factory. 541 * 542 * @throws GeneralSecurityException If a problem occurs while creating or 543 * initializing the SSL server socket 544 * factory. 545 */ 546 public SSLServerSocketFactory createSSLServerSocketFactory( 547 final String protocol, 548 final String provider) 549 throws GeneralSecurityException 550 { 551 return createSSLContext(protocol, provider).getServerSocketFactory(); 552 } 553 554 555 556 /** 557 * Retrieves the SSL protocol string that will be used by calls to 558 * {@code createSSLContext()} that do not explicitly specify which protocol 559 * to use. 560 * 561 * @return The SSL protocol string that will be used by calls to create an 562 * SSL context that do not explicitly specify which protocol to use. 563 */ 564 public static String getDefaultSSLProtocol() 565 { 566 return DEFAULT_SSL_PROTOCOL.get(); 567 } 568 569 570 571 /** 572 * Specifies the SSL protocol string that will be used by calls to 573 * {@code createSSLContext()} that do not explicitly specify which protocol 574 * to use. 575 * 576 * @param defaultSSLProtocol The SSL protocol string that will be used by 577 * calls to create an SSL context that do not 578 * explicitly specify which protocol to use. It 579 * must not be {@code null}. 580 */ 581 public static void setDefaultSSLProtocol(final String defaultSSLProtocol) 582 { 583 ensureNotNull(defaultSSLProtocol); 584 585 DEFAULT_SSL_PROTOCOL.set(defaultSSLProtocol); 586 } 587 588 589 590 /** 591 * Retrieves the set of SSL protocols that will be enabled for use, if 592 * available, for SSL sockets created within the LDAP SDK. 593 * 594 * @return The set of SSL protocols that will be enabled for use, if 595 * available, for SSL sockets created within the LDAP SDK. 596 */ 597 public static Set<String> getEnabledSSLProtocols() 598 { 599 return ENABLED_SSL_PROTOCOLS.get(); 600 } 601 602 603 604 /** 605 * Specifies the set of SSL protocols that will be enabled for use for SSL 606 * sockets created within the LDAP SDK. When creating an SSL socket, the 607 * {@code SSLSocket.getSupportedProtocols} method will be used to determine 608 * which protocols are supported for that socket, and then the 609 * {@code SSLSocket.setEnabledProtocols} method will be used to enable those 610 * protocols which are listed as both supported by the socket and included in 611 * this set. If the provided set is {@code null} or empty, then the default 612 * set of enabled protocols will be used. 613 * 614 * @param enabledSSLProtocols The set of SSL protocols that will be enabled 615 * for use for SSL sockets created within the 616 * LDAP SDK. It may be {@code null} or empty to 617 * indicate that the JDK-default set of enabled 618 * protocols should be used for the socket. 619 */ 620 public static void setEnabledSSLProtocols( 621 final Collection<String> enabledSSLProtocols) 622 { 623 if (enabledSSLProtocols == null) 624 { 625 ENABLED_SSL_PROTOCOLS.set(Collections.<String>emptySet()); 626 } 627 else 628 { 629 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet( 630 new HashSet<String>(enabledSSLProtocols))); 631 } 632 } 633 634 635 636 /** 637 * Updates the provided socket to apply the appropriate set of enabled SSL 638 * protocols. This will only have any effect for sockets that are instances 639 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 640 * {@code java.net.Socket}. This should be called before attempting any 641 * communication over the socket, as 642 * 643 * @param socket The socket on which to apply the configured set of enabled 644 * SSL protocols. 645 * 646 * @throws LDAPException If {@code getEnabledSSLProtocols} returns a 647 * non-empty set but none of the values in that set 648 * are supported by the socket. 649 */ 650 public static void applyEnabledSSLProtocols(final Socket socket) 651 throws LDAPException 652 { 653 try 654 { 655 applyEnabledSSLProtocols(socket, ENABLED_SSL_PROTOCOLS.get()); 656 } 657 catch (final IOException ioe) 658 { 659 Debug.debugException(ioe); 660 throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe); 661 } 662 } 663 664 665 666 /** 667 * Updates the provided socket to apply the appropriate set of enabled SSL 668 * protocols. This will only have any effect for sockets that are instances 669 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 670 * {@code java.net.Socket}. This should be called before attempting any 671 * communication over the socket, as 672 * 673 * @param socket The socket on which to apply the configured set of 674 * enabled SSL protocols. 675 * @param protocols The set of protocols that should be enabled for the 676 * socket, if available. 677 * 678 * @throws IOException If {@code getEnabledSSLProtocols} returns a 679 * non-empty set but none of the values in that set are 680 * supported by the socket. 681 */ 682 static void applyEnabledSSLProtocols(final Socket socket, 683 final Set<String> protocols) 684 throws IOException 685 { 686 if ((socket == null) || (!(socket instanceof SSLSocket)) || 687 protocols.isEmpty()) 688 { 689 return; 690 } 691 692 final Set<String> lowerProtocols = new HashSet<String>(protocols.size()); 693 for (final String s : protocols) 694 { 695 lowerProtocols.add(StaticUtils.toLowerCase(s)); 696 } 697 698 final SSLSocket sslSocket = (SSLSocket) socket; 699 final String[] supportedProtocols = sslSocket.getSupportedProtocols(); 700 701 final ArrayList<String> enabledList = 702 new ArrayList<String>(supportedProtocols.length); 703 for (final String supportedProtocol : supportedProtocols) 704 { 705 if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol))) 706 { 707 enabledList.add(supportedProtocol); 708 } 709 } 710 711 if (enabledList.isEmpty()) 712 { 713 final StringBuilder enabledBuffer = new StringBuilder(); 714 final Iterator<String> enabledIterator = protocols.iterator(); 715 while (enabledIterator.hasNext()) 716 { 717 enabledBuffer.append('\''); 718 enabledBuffer.append(enabledIterator.next()); 719 enabledBuffer.append('\''); 720 721 if (enabledIterator.hasNext()) 722 { 723 enabledBuffer.append(", "); 724 } 725 } 726 727 final StringBuilder supportedBuffer = new StringBuilder(); 728 for (int i=0; i < supportedProtocols.length; i++) 729 { 730 if (i > 0) 731 { 732 supportedBuffer.append(", "); 733 } 734 735 supportedBuffer.append('\''); 736 supportedBuffer.append(supportedProtocols[i]); 737 supportedBuffer.append('\''); 738 } 739 740 throw new IOException( 741 ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get( 742 enabledBuffer.toString(), supportedBuffer.toString(), 743 PROPERTY_ENABLED_SSL_PROTOCOLS, 744 SSLUtil.class.getName() + ".setEnabledSSLProtocols")); 745 } 746 else 747 { 748 final String[] enabledArray = new String[enabledList.size()]; 749 sslSocket.setEnabledProtocols(enabledList.toArray(enabledArray)); 750 } 751 } 752 753 754 755 /** 756 * Configures SSL default settings for the LDAP SDK. This method is 757 * non-private for purposes of easier test coverage. 758 */ 759 static void configureSSLDefaults() 760 { 761 // See if there is a system property that specifies what the default SSL 762 // protocol should be. If not, then try to dynamically determine it. 763 final String defaultPropValue = 764 System.getProperty(PROPERTY_DEFAULT_SSL_PROTOCOL); 765 if ((defaultPropValue != null) && (defaultPropValue.length() > 0)) 766 { 767 DEFAULT_SSL_PROTOCOL.set(defaultPropValue); 768 } 769 else 770 { 771 // Ideally, we should be able to discover the SSL protocol that offers the 772 // best mix of security and compatibility. Unfortunately, Java SE 5 773 // doesn't expose the methods necessary to allow us to do that, but if the 774 // running JVM is Java SE 6 or later, then we can use reflection to invoke 775 // those methods and make the appropriate determination. If we see that 776 // TLSv1.1 and/or TLSv1.2 are available, then we'll add those to the set 777 // of default enabled protocols. 778 try 779 { 780 final Method getDefaultMethod = 781 SSLContext.class.getMethod("getDefault"); 782 final SSLContext defaultContext = 783 (SSLContext) getDefaultMethod.invoke(null); 784 785 final Method getSupportedParamsMethod = 786 SSLContext.class.getMethod("getSupportedSSLParameters"); 787 final Object paramsObj = 788 getSupportedParamsMethod.invoke(defaultContext); 789 790 final Class<?> sslParamsClass = 791 Class.forName("javax.net.ssl.SSLParameters"); 792 final Method getProtocolsMethod = 793 sslParamsClass.getMethod("getProtocols"); 794 final String[] supportedProtocols = 795 (String[]) getProtocolsMethod.invoke(paramsObj); 796 797 final HashSet<String> protocolMap = 798 new HashSet<String>(Arrays.asList(supportedProtocols)); 799 if (protocolMap.contains("TLSv1.2")) 800 { 801 DEFAULT_SSL_PROTOCOL.set("TLSv1.2"); 802 } 803 else if (protocolMap.contains("TLSv1.1")) 804 { 805 DEFAULT_SSL_PROTOCOL.set("TLSv1.1"); 806 } 807 else if (protocolMap.contains("TLSv1")) 808 { 809 DEFAULT_SSL_PROTOCOL.set("TLSv1"); 810 } 811 } 812 catch (final Exception e) 813 { 814 Debug.debugException(e); 815 } 816 } 817 818 // A set to use for the default set of enabled protocols. Unless otherwise 819 // specified via system property, we'll always enable TLSv1. We may enable 820 // other protocols based on the default protocol. The default set of 821 // enabled protocols will not include SSLv3 even if the JVM might otherwise 822 // include it as a default enabled protocol because of known security 823 // problems with SSLv3. 824 final HashSet<String> enabledProtocols = new HashSet<String>(10); 825 enabledProtocols.add("TLSv1"); 826 if (DEFAULT_SSL_PROTOCOL.get().equals("TLSv1.2")) 827 { 828 enabledProtocols.add("TLSv1.1"); 829 enabledProtocols.add("TLSv1.2"); 830 } 831 else if (DEFAULT_SSL_PROTOCOL.get().equals("TLSv1.1")) 832 { 833 enabledProtocols.add("TLSv1.1"); 834 } 835 836 // If there is a system property that specifies which enabled SSL protocols 837 // to use, then it will override the defaults. 838 final String enabledPropValue = 839 System.getProperty(PROPERTY_ENABLED_SSL_PROTOCOLS); 840 if ((enabledPropValue != null) && (enabledPropValue.length() > 0)) 841 { 842 enabledProtocols.clear(); 843 844 final StringTokenizer tokenizer = new StringTokenizer(enabledPropValue, 845 ", ", false); 846 while (tokenizer.hasMoreTokens()) 847 { 848 final String token = tokenizer.nextToken(); 849 if (token.length() > 0) 850 { 851 enabledProtocols.add(token); 852 } 853 } 854 } 855 856 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet(enabledProtocols)); 857 } 858 }