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