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