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