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