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.Iterator; 035import java.util.LinkedHashSet; 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 system property that can be used to provide the initial 151 * set of enabled SSL cipher suites that should be used, as a comma-delimited 152 * list. If this is not set, then the enabled SSL cipher suites will be 153 * dynamically determined. This can be overridden via the 154 * {@link #setEnabledSSLCipherSuites(Collection)} method. 155 */ 156 public static final String PROPERTY_ENABLED_SSL_CIPHER_SUITES = 157 "com.unboundid.util.SSLUtil.enabledSSLCipherSuites"; 158 159 160 161 /** 162 * The name of the SSL protocol that can be used to request TLSv1.3. 163 */ 164 public static final String SSL_PROTOCOL_TLS_1_3 = "TLSv1.3"; 165 166 167 168 /** 169 * The name of the SSL protocol that can be used to request TLSv1.2. 170 */ 171 public static final String SSL_PROTOCOL_TLS_1_2 = "TLSv1.2"; 172 173 174 175 /** 176 * The name of the SSL protocol that can be used to request TLSv1.1. 177 */ 178 public static final String SSL_PROTOCOL_TLS_1_1 = "TLSv1.1"; 179 180 181 182 /** 183 * The name of the SSL protocol that can be used to request TLSv1. 184 */ 185 public static final String SSL_PROTOCOL_TLS_1 = "TLSv1"; 186 187 188 189 /** 190 * The name of the SSL protocol that can be used to request SSLv3. 191 */ 192 public static final String SSL_PROTOCOL_SSL_3 = "SSLv3"; 193 194 195 196 /** 197 * The name of the SSL protocol that can be used to request SSLv2Hello. 198 */ 199 public static final String SSL_PROTOCOL_SSL_2_HELLO = "SSLv2Hello"; 200 201 202 203 /** 204 * The default protocol string that will be used to create SSL contexts when 205 * no explicit protocol is specified. 206 */ 207 private static final AtomicReference<String> DEFAULT_SSL_PROTOCOL = 208 new AtomicReference<>(SSL_PROTOCOL_TLS_1); 209 210 211 212 /** 213 * The default set of SSL cipher suites that will be enabled for use if 214 * available for SSL sockets created within the LDAP SDK. 215 */ 216 private static final AtomicReference<Set<String>> ENABLED_SSL_CIPHER_SUITES = 217 new AtomicReference<>(); 218 219 220 221 /** 222 * The default set of SSL protocols that will be enabled for use if available 223 * for SSL sockets created within the LDAP SDK. 224 */ 225 private static final AtomicReference<Set<String>> ENABLED_SSL_PROTOCOLS = 226 new AtomicReference<>(); 227 228 229 230 static 231 { 232 configureSSLDefaults(); 233 } 234 235 236 237 // The set of key managers to be used. 238 private final KeyManager[] keyManagers; 239 240 // The set of trust managers to be used. 241 private final TrustManager[] trustManagers; 242 243 244 245 /** 246 * Creates a new SSLUtil instance that will not have a custom key manager or 247 * trust manager. It will not be able to provide a certificate to the server 248 * if one is requested, and it will only trust certificates signed by a 249 * predefined set of authorities. 250 */ 251 public SSLUtil() 252 { 253 keyManagers = null; 254 trustManagers = null; 255 } 256 257 258 259 /** 260 * Creates a new SSLUtil instance that will use the provided trust manager to 261 * determine whether to trust server certificates presented to the client. 262 * It will not be able to provide a certificate to the server if one is 263 * requested. 264 * 265 * @param trustManager The trust manager to use to determine whether to 266 * trust server certificates presented to the client. 267 * It may be {@code null} if the default set of trust 268 * managers should be used. 269 */ 270 public SSLUtil(final TrustManager trustManager) 271 { 272 keyManagers = null; 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 trust managers 288 * to determine whether to trust server certificates presented to the client. 289 * It will not be able to provide a certificate to the server if one is 290 * requested. 291 * 292 * @param trustManagers The set of trust managers to use to determine 293 * whether to trust server certificates presented to 294 * the client. It may be {@code null} or empty if the 295 * default set of trust managers should be used. 296 */ 297 public SSLUtil(final TrustManager[] trustManagers) 298 { 299 keyManagers = null; 300 301 if ((trustManagers == null) || (trustManagers.length == 0)) 302 { 303 this.trustManagers = null; 304 } 305 else 306 { 307 this.trustManagers = trustManagers; 308 } 309 } 310 311 312 313 /** 314 * Creates a new SSLUtil instance that will use the provided key manager to 315 * obtain certificates to present to the server, and the provided trust 316 * manager to determine whether to trust server certificates presented to the 317 * client. 318 * 319 * @param keyManager The key manager to use to obtain certificates to 320 * present to the server if requested. It may be 321 * {@code null} if no client certificates will be 322 * required or should be provided. 323 * @param trustManager The trust manager to use to determine whether to 324 * trust server certificates presented to the client. 325 * It may be {@code null} if the default set of trust 326 * managers should be used. 327 */ 328 public SSLUtil(final KeyManager keyManager, final TrustManager trustManager) 329 { 330 if (keyManager == null) 331 { 332 keyManagers = null; 333 } 334 else 335 { 336 keyManagers = new KeyManager[] { keyManager }; 337 } 338 339 if (trustManager == null) 340 { 341 trustManagers = null; 342 } 343 else 344 { 345 trustManagers = new TrustManager[] { trustManager }; 346 } 347 } 348 349 350 351 /** 352 * Creates a new SSLUtil instance that will use the provided key managers to 353 * obtain certificates to present to the server, and the provided trust 354 * managers to determine whether to trust server certificates presented to the 355 * client. 356 * 357 * @param keyManagers The set of key managers to use to obtain 358 * certificates to present to the server if requested. 359 * It may be {@code null} or empty if no client 360 * certificates will be required or should be provided. 361 * @param trustManagers The set of trust managers to use to determine 362 * whether to trust server certificates presented to 363 * the client. It may be {@code null} or empty if the 364 * default set of trust managers should be used. 365 */ 366 public SSLUtil(final KeyManager[] keyManagers, 367 final TrustManager[] trustManagers) 368 { 369 if ((keyManagers == null) || (keyManagers.length == 0)) 370 { 371 this.keyManagers = null; 372 } 373 else 374 { 375 this.keyManagers = keyManagers; 376 } 377 378 if ((trustManagers == null) || (trustManagers.length == 0)) 379 { 380 this.trustManagers = null; 381 } 382 else 383 { 384 this.trustManagers = trustManagers; 385 } 386 } 387 388 389 390 /** 391 * Retrieves the set of key managers configured for use by this class, if any. 392 * 393 * @return The set of key managers configured for use by this class, or 394 * {@code null} if none were provided. 395 */ 396 public KeyManager[] getKeyManagers() 397 { 398 return keyManagers; 399 } 400 401 402 403 /** 404 * Retrieves the set of trust managers configured for use by this class, if 405 * any. 406 * 407 * @return The set of trust managers configured for use by this class, or 408 * {@code null} if none were provided. 409 */ 410 public TrustManager[] getTrustManagers() 411 { 412 return trustManagers; 413 } 414 415 416 417 /** 418 * Creates an initialized SSL context created with the configured key and 419 * trust managers. It will use the protocol returned by the 420 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 421 * 422 * @return The created SSL context. 423 * 424 * @throws GeneralSecurityException If a problem occurs while creating or 425 * initializing the SSL context. 426 */ 427 public SSLContext createSSLContext() 428 throws GeneralSecurityException 429 { 430 return createSSLContext(DEFAULT_SSL_PROTOCOL.get()); 431 } 432 433 434 435 /** 436 * Creates an initialized SSL context created with the configured key and 437 * trust managers. It will use the default provider. 438 * 439 * @param protocol The SSL protocol to use. The Java Secure Socket 440 * Extension (JSSE) Reference Guide provides a list of the 441 * supported protocols, but commonly used values are 442 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 443 * not be {@code null}. 444 * 445 * 446 * @return The created SSL context. 447 * 448 * @throws GeneralSecurityException If a problem occurs while creating or 449 * initializing the SSL context. 450 */ 451 public SSLContext createSSLContext(final String protocol) 452 throws GeneralSecurityException 453 { 454 Validator.ensureNotNull(protocol); 455 456 final SSLContext sslContext = SSLContext.getInstance(protocol); 457 sslContext.init(keyManagers, trustManagers, null); 458 return sslContext; 459 } 460 461 462 463 /** 464 * Creates an initialized SSL context created with the configured key and 465 * trust managers. 466 * 467 * @param protocol The SSL protocol to use. The Java Secure Socket 468 * Extension (JSSE) Reference Guide provides a list of the 469 * supported protocols, but commonly used values are 470 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 471 * not be {@code null}. 472 * @param provider The name of the provider to use for cryptographic 473 * operations. It must not be {@code null}. 474 * 475 * @return The created SSL context. 476 * 477 * @throws GeneralSecurityException If a problem occurs while creating or 478 * initializing the SSL context. 479 */ 480 public SSLContext createSSLContext(final String protocol, 481 final String provider) 482 throws GeneralSecurityException 483 { 484 Validator.ensureNotNull(protocol, provider); 485 486 final SSLContext sslContext = SSLContext.getInstance(protocol, provider); 487 sslContext.init(keyManagers, trustManagers, null); 488 return sslContext; 489 } 490 491 492 493 /** 494 * Creates an SSL socket factory using the configured key and trust manager 495 * providers. It will use the protocol returned by the 496 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 497 * 498 * @return The created SSL socket factory. 499 * 500 * @throws GeneralSecurityException If a problem occurs while creating or 501 * initializing the SSL socket factory. 502 */ 503 public SSLSocketFactory createSSLSocketFactory() 504 throws GeneralSecurityException 505 { 506 return new SetEnabledProtocolsAndCipherSuitesSSLSocketFactory( 507 createSSLContext().getSocketFactory(), 508 ENABLED_SSL_PROTOCOLS.get(), ENABLED_SSL_CIPHER_SUITES.get()); 509 } 510 511 512 513 /** 514 * Creates an SSL socket factory with the configured key and trust managers. 515 * It will use the default provider. 516 * 517 * @param protocol The SSL protocol to use. The Java Secure Socket 518 * Extension (JSSE) Reference Guide provides a list of the 519 * supported protocols, but commonly used values are 520 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 521 * not be {@code null}. 522 * 523 * @return The created SSL socket factory. 524 * 525 * @throws GeneralSecurityException If a problem occurs while creating or 526 * initializing the SSL socket factory. 527 */ 528 public SSLSocketFactory createSSLSocketFactory(final String protocol) 529 throws GeneralSecurityException 530 { 531 return new SetEnabledProtocolsAndCipherSuitesSSLSocketFactory( 532 createSSLContext(protocol).getSocketFactory(), protocol, 533 ENABLED_SSL_CIPHER_SUITES.get()); 534 } 535 536 537 538 /** 539 * Creates an SSL socket factory with the configured key and trust managers. 540 * 541 * @param protocol The SSL protocol to use. The Java Secure Socket 542 * Extension (JSSE) Reference Guide provides a list of the 543 * supported protocols, but commonly used values are 544 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 545 * 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 socket factory. 550 * 551 * @throws GeneralSecurityException If a problem occurs while creating or 552 * initializing the SSL socket factory. 553 */ 554 public SSLSocketFactory createSSLSocketFactory(final String protocol, 555 final String provider) 556 throws GeneralSecurityException 557 { 558 return createSSLContext(protocol, provider).getSocketFactory(); 559 } 560 561 562 563 /** 564 * Creates an SSL server socket factory using the configured key and trust 565 * manager providers. It will use the protocol returned by the 566 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 567 * 568 * @return The created SSL server socket factory. 569 * 570 * @throws GeneralSecurityException If a problem occurs while creating or 571 * initializing the SSL server socket 572 * factory. 573 */ 574 public SSLServerSocketFactory createSSLServerSocketFactory() 575 throws GeneralSecurityException 576 { 577 return new SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory( 578 createSSLContext().getServerSocketFactory(), 579 ENABLED_SSL_PROTOCOLS.get(), ENABLED_SSL_CIPHER_SUITES.get()); 580 } 581 582 583 584 /** 585 * Creates an SSL server socket factory using the configured key and trust 586 * manager providers. It will use the JVM-default provider. 587 * 588 * @param protocol The SSL protocol to use. The Java Secure Socket 589 * Extension (JSSE) Reference Guide provides a list of the 590 * supported protocols, but commonly used values are 591 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 592 * not be {@code null}. 593 * 594 * @return The created SSL server socket factory. 595 * 596 * @throws GeneralSecurityException If a problem occurs while creating or 597 * initializing the SSL server socket 598 * factory. 599 */ 600 public SSLServerSocketFactory createSSLServerSocketFactory( 601 final String protocol) 602 throws GeneralSecurityException 603 { 604 return new SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory( 605 createSSLContext(protocol).getServerSocketFactory(), protocol, 606 ENABLED_SSL_CIPHER_SUITES.get()); 607 } 608 609 610 611 /** 612 * Creates an SSL server socket factory using the configured key and trust 613 * manager providers. 614 * 615 * @param protocol The SSL protocol to use. The Java Secure Socket 616 * Extension (JSSE) Reference Guide provides a list of the 617 * supported protocols, but commonly used values are 618 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 619 * not be {@code null}. 620 * @param provider The name of the provider to use for cryptographic 621 * operations. It must not be {@code null}. 622 * 623 * @return The created SSL server socket factory. 624 * 625 * @throws GeneralSecurityException If a problem occurs while creating or 626 * initializing the SSL server socket 627 * factory. 628 */ 629 public SSLServerSocketFactory createSSLServerSocketFactory( 630 final String protocol, 631 final String provider) 632 throws GeneralSecurityException 633 { 634 return createSSLContext(protocol, provider).getServerSocketFactory(); 635 } 636 637 638 639 /** 640 * Retrieves the SSL protocol string that will be used by calls to 641 * {@link #createSSLContext()} that do not explicitly specify which protocol 642 * to use. 643 * 644 * @return The SSL protocol string that will be used by calls to create an 645 * SSL context that do not explicitly specify which protocol to use. 646 */ 647 public static String getDefaultSSLProtocol() 648 { 649 return DEFAULT_SSL_PROTOCOL.get(); 650 } 651 652 653 654 /** 655 * Specifies the SSL protocol string that will be used by calls to 656 * {@link #createSSLContext()} that do not explicitly specify which protocol 657 * to use. 658 * 659 * @param defaultSSLProtocol The SSL protocol string that will be used by 660 * calls to create an SSL context that do not 661 * explicitly specify which protocol to use. It 662 * must not be {@code null}. 663 */ 664 public static void setDefaultSSLProtocol(final String defaultSSLProtocol) 665 { 666 Validator.ensureNotNull(defaultSSLProtocol); 667 668 DEFAULT_SSL_PROTOCOL.set(defaultSSLProtocol); 669 } 670 671 672 673 /** 674 * Retrieves the set of SSL protocols that will be enabled for use, if 675 * available, for SSL sockets created within the LDAP SDK. 676 * 677 * @return The set of SSL protocols that will be enabled for use, if 678 * available, for SSL sockets created within the LDAP SDK. 679 */ 680 public static Set<String> getEnabledSSLProtocols() 681 { 682 return ENABLED_SSL_PROTOCOLS.get(); 683 } 684 685 686 687 /** 688 * Specifies the set of SSL protocols that will be enabled for use for SSL 689 * sockets created within the LDAP SDK. When creating an SSL socket, the 690 * {@code SSLSocket.getSupportedProtocols} method will be used to determine 691 * which protocols are supported for that socket, and then the 692 * {@code SSLSocket.setEnabledProtocols} method will be used to enable those 693 * protocols which are listed as both supported by the socket and included in 694 * this set. If the provided set is {@code null} or empty, then the default 695 * set of enabled protocols will be used. 696 * 697 * @param enabledSSLProtocols The set of SSL protocols that will be enabled 698 * for use for SSL sockets created within the 699 * LDAP SDK. It may be {@code null} or empty to 700 * indicate that the JDK-default set of enabled 701 * protocols should be used for the socket. 702 */ 703 public static void setEnabledSSLProtocols( 704 final Collection<String> enabledSSLProtocols) 705 { 706 if (enabledSSLProtocols == null) 707 { 708 ENABLED_SSL_PROTOCOLS.set(Collections.<String>emptySet()); 709 } 710 else 711 { 712 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet( 713 new LinkedHashSet<>(enabledSSLProtocols))); 714 } 715 } 716 717 718 719 /** 720 * Updates the provided socket to apply the appropriate set of enabled SSL 721 * protocols. This will only have any effect for sockets that are instances 722 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 723 * {@code java.net.Socket}. This should be called before attempting any 724 * communication over the socket. 725 * 726 * @param socket The socket on which to apply the configured set of enabled 727 * SSL protocols. 728 * 729 * @throws LDAPException If {@link #getEnabledSSLProtocols} returns a 730 * non-empty set but none of the values in that set 731 * are supported by the socket. 732 */ 733 public static void applyEnabledSSLProtocols(final Socket socket) 734 throws LDAPException 735 { 736 try 737 { 738 applyEnabledSSLProtocols(socket, ENABLED_SSL_PROTOCOLS.get()); 739 } 740 catch (final IOException ioe) 741 { 742 Debug.debugException(ioe); 743 throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe); 744 } 745 } 746 747 748 749 /** 750 * Updates the provided socket to apply the appropriate set of enabled SSL 751 * protocols. This will only have any effect for sockets that are instances 752 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 753 * {@code java.net.Socket}. This should be called before attempting any 754 * communication over the socket. 755 * 756 * @param socket The socket on which to apply the configured set of 757 * enabled SSL protocols. 758 * @param protocols The set of protocols that should be enabled for the 759 * socket, if available. 760 * 761 * @throws IOException If a problem is encountered while applying the 762 * desired set of enabled protocols to the given socket. 763 */ 764 static void applyEnabledSSLProtocols(final Socket socket, 765 final Set<String> protocols) 766 throws IOException 767 { 768 if ((socket == null) || (!(socket instanceof SSLSocket)) || 769 protocols.isEmpty()) 770 { 771 return; 772 } 773 774 final SSLSocket sslSocket = (SSLSocket) socket; 775 final String[] protocolsToEnable = 776 getSSLProtocolsToEnable(protocols, sslSocket.getSupportedProtocols()); 777 778 try 779 { 780 sslSocket.setEnabledProtocols(protocolsToEnable); 781 } 782 catch (final Exception e) 783 { 784 Debug.debugException(e); 785 } 786 } 787 788 789 790 /** 791 * Updates the provided server socket to apply the appropriate set of enabled 792 * SSL protocols. This will only have any effect for server sockets that are 793 * instances of {@code javax.net.ssl.SSLServerSocket}, but it is safe to call 794 * for any kind of {@code java.net.ServerSocket}. This should be called 795 * before attempting any communication over the socket. 796 * 797 * @param serverSocket The server socket on which to apply the configured 798 * set of enabled SSL protocols. 799 * @param protocols The set of protocols that should be enabled for the 800 * server socket, if available. 801 * 802 * @throws IOException If a problem is encountered while applying the 803 * desired set of enabled protocols to the given server 804 * socket. 805 */ 806 static void applyEnabledSSLProtocols(final ServerSocket serverSocket, 807 final Set<String> protocols) 808 throws IOException 809 { 810 if ((serverSocket == null) || 811 (!(serverSocket instanceof SSLServerSocket)) || 812 protocols.isEmpty()) 813 { 814 return; 815 } 816 817 final SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket; 818 final String[] protocolsToEnable = getSSLProtocolsToEnable(protocols, 819 sslServerSocket.getSupportedProtocols()); 820 821 try 822 { 823 sslServerSocket.setEnabledProtocols(protocolsToEnable); 824 } 825 catch (final Exception e) 826 { 827 Debug.debugException(e); 828 } 829 } 830 831 832 833 /** 834 * Retrieves the names of the SSL protocols that should be enabled given the 835 * provided information. 836 * 837 * @param desiredProtocols The set of protocols that are desired to be 838 * enabled. 839 * @param supportedProtocols The set of all protocols that are supported. 840 * 841 * @return The names of the SSL protocols that should be enabled. 842 * 843 * @throws IOException If none of the desired values are included in the 844 * supported set. 845 */ 846 private static String[] getSSLProtocolsToEnable( 847 final Set<String> desiredProtocols, 848 final String[] supportedProtocols) 849 throws IOException 850 { 851 final Set<String> lowerProtocols = new LinkedHashSet<>( 852 StaticUtils.computeMapCapacity(desiredProtocols.size())); 853 for (final String s : desiredProtocols) 854 { 855 lowerProtocols.add(StaticUtils.toLowerCase(s)); 856 } 857 858 final ArrayList<String> enabledList = 859 new ArrayList<>(supportedProtocols.length); 860 for (final String supportedProtocol : supportedProtocols) 861 { 862 if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol))) 863 { 864 enabledList.add(supportedProtocol); 865 } 866 } 867 868 if (enabledList.isEmpty()) 869 { 870 final StringBuilder enabledBuffer = new StringBuilder(); 871 final Iterator<String> enabledIterator = desiredProtocols.iterator(); 872 while (enabledIterator.hasNext()) 873 { 874 enabledBuffer.append('\''); 875 enabledBuffer.append(enabledIterator.next()); 876 enabledBuffer.append('\''); 877 878 if (enabledIterator.hasNext()) 879 { 880 enabledBuffer.append(", "); 881 } 882 } 883 884 final StringBuilder supportedBuffer = new StringBuilder(); 885 for (int i=0; i < supportedProtocols.length; i++) 886 { 887 if (i > 0) 888 { 889 supportedBuffer.append(", "); 890 } 891 892 supportedBuffer.append('\''); 893 supportedBuffer.append(supportedProtocols[i]); 894 supportedBuffer.append('\''); 895 } 896 897 throw new IOException( 898 ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get( 899 enabledBuffer.toString(), supportedBuffer.toString(), 900 PROPERTY_ENABLED_SSL_PROTOCOLS, 901 SSLUtil.class.getName() + ".setEnabledSSLProtocols")); 902 } 903 else 904 { 905 return enabledList.toArray(StaticUtils.NO_STRINGS); 906 } 907 } 908 909 910 911 /** 912 * Retrieves the set of SSL cipher suites that will be enabled for use, if 913 * available, for SSL sockets created within the LDAP SDK. 914 * 915 * @return The set of SSL cipher suites that will be enabled for use, if 916 * available, for SSL sockets created within the LDAP SDK. 917 */ 918 public static Set<String> getEnabledSSLCipherSuites() 919 { 920 return ENABLED_SSL_CIPHER_SUITES.get(); 921 } 922 923 924 925 /** 926 * Specifies the set of SSL cipher suites that will be enabled for SSL sockets 927 * created within the LDAP SDK. When creating an SSL socket, the 928 * {@code SSLSocket.getSupportedCipherSuites} method will be used to determine 929 * which cipher suites are supported for that socket, and then the 930 * {@code SSLSocket.setEnabledCipherSuites} method will be used to enable 931 * those suites which are listed as both supported by the socket and included 932 * in this set. If the provided set is {@code null} or empty, then the 933 * default set of enabled cipher suites will be used. 934 * 935 * @param enabledSSLCipherSuites The set of SSL cipher suites that will be 936 * enabled for use for SSL sockets created 937 * within the LDAP SDK. It may be 938 * {@code null} or empty to indicate that the 939 * JDK-default set of enabled cipher suites 940 * should be used for the socket. 941 */ 942 public static void setEnabledSSLCipherSuites( 943 final Collection<String> enabledSSLCipherSuites) 944 { 945 if (enabledSSLCipherSuites == null) 946 { 947 ENABLED_SSL_CIPHER_SUITES.set(Collections.<String>emptySet()); 948 } 949 else 950 { 951 ENABLED_SSL_CIPHER_SUITES.set(Collections.unmodifiableSet( 952 new LinkedHashSet<>(enabledSSLCipherSuites))); 953 } 954 } 955 956 957 958 /** 959 * Updates the provided socket to apply the appropriate set of enabled SSL 960 * cipher suites. This will only have any effect for sockets that are 961 * instances of {@code javax.net.ssl.SSLSocket}, but it is safe to call for 962 * any kind of {@code java.net.Socket}. This should be called before 963 * attempting any communication over the socket. 964 * 965 * @param socket The socket on which to apply the configured set of enabled 966 * SSL cipher suties. 967 * 968 * @throws LDAPException If {@link #getEnabledSSLCipherSuites} returns a 969 * non-empty set but none of the values in that set 970 * are supported by the socket. 971 */ 972 public static void applyEnabledSSLCipherSuites(final Socket socket) 973 throws LDAPException 974 { 975 try 976 { 977 applyEnabledSSLCipherSuites(socket, ENABLED_SSL_CIPHER_SUITES.get()); 978 } 979 catch (final IOException ioe) 980 { 981 Debug.debugException(ioe); 982 throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe); 983 } 984 } 985 986 987 988 /** 989 * Updates the provided socket to apply the appropriate set of enabled SSL 990 * cipher suites. This will only have any effect for sockets that are 991 * instances of {@code javax.net.ssl.SSLSocket}, but it is safe to call for 992 * any kind of {@code java.net.Socket}. This should be called before 993 * attempting any communication over the socket. 994 * 995 * @param socket The socket on which to apply the configured set of 996 * enabled SSL cipher suites. 997 * @param cipherSuites The set of cipher suites that should be enabled for 998 * the socket, if available. 999 * 1000 * @throws IOException If a problem is encountered while applying the 1001 * desired set of enabled cipher suites to the given 1002 * socket. 1003 */ 1004 static void applyEnabledSSLCipherSuites(final Socket socket, 1005 final Set<String> cipherSuites) 1006 throws IOException 1007 { 1008 if ((socket == null) || (!(socket instanceof SSLSocket)) || 1009 cipherSuites.isEmpty()) 1010 { 1011 return; 1012 } 1013 1014 final SSLSocket sslSocket = (SSLSocket) socket; 1015 final String[] cipherSuitesToEnable = 1016 getSSLCipherSuitesToEnable(cipherSuites, 1017 sslSocket.getSupportedCipherSuites()); 1018 1019 try 1020 { 1021 sslSocket.setEnabledCipherSuites(cipherSuitesToEnable); 1022 } 1023 catch (final Exception e) 1024 { 1025 Debug.debugException(e); 1026 } 1027 } 1028 1029 1030 1031 /** 1032 * Updates the provided server socket to apply the appropriate set of enabled 1033 * SSL cipher suites. This will only have any effect for server sockets that 1034 * are instances of {@code javax.net.ssl.SSLServerSocket}, but it is safe to 1035 * call for any kind of {@code java.net.ServerSocket}. This should be called 1036 * before attempting any communication over the socket. 1037 * 1038 * @param serverSocket The server socket on which to apply the configured 1039 * set of enabled SSL cipher suites. 1040 * @param cipherSuites The set of cipher suites that should be enabled 1041 * for the server socket, if available. 1042 * 1043 * @throws IOException If a problem is encountered while applying the 1044 * desired set of enabled cipher suites to the given 1045 * server socket. 1046 */ 1047 static void applyEnabledSSLCipherSuites(final ServerSocket serverSocket, 1048 final Set<String> cipherSuites) 1049 throws IOException 1050 { 1051 if ((serverSocket == null) || 1052 (!(serverSocket instanceof SSLServerSocket)) || 1053 cipherSuites.isEmpty()) 1054 { 1055 return; 1056 } 1057 1058 final SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket; 1059 final String[] cipherSuitesToEnable = 1060 getSSLCipherSuitesToEnable(cipherSuites, 1061 sslServerSocket.getSupportedCipherSuites()); 1062 1063 try 1064 { 1065 sslServerSocket.setEnabledCipherSuites(cipherSuitesToEnable); 1066 } 1067 catch (final Exception e) 1068 { 1069 Debug.debugException(e); 1070 } 1071 } 1072 1073 1074 1075 /** 1076 * Retrieves the names of the SSL cipher suites that should be enabled given 1077 * the provided information. 1078 * 1079 * @param desiredCipherSuites The set of cipher suites that are desired to 1080 * be enabled. 1081 * @param supportedCipherSuites The set of all cipher suites that are 1082 * supported. 1083 * 1084 * @return The names of the SSL cipher suites that should be enabled. 1085 * 1086 * @throws IOException If none of the desired values are included in the 1087 * supported set. 1088 */ 1089 private static String[] getSSLCipherSuitesToEnable( 1090 final Set<String> desiredCipherSuites, 1091 final String[] supportedCipherSuites) 1092 throws IOException 1093 { 1094 final Set<String> upperCipherSuites = new LinkedHashSet<>( 1095 StaticUtils.computeMapCapacity(desiredCipherSuites.size())); 1096 for (final String s : desiredCipherSuites) 1097 { 1098 upperCipherSuites.add(StaticUtils.toUpperCase(s)); 1099 } 1100 1101 final ArrayList<String> enabledList = 1102 new ArrayList<>(supportedCipherSuites.length); 1103 for (final String supportedCipherSuite : supportedCipherSuites) 1104 { 1105 if (upperCipherSuites.contains(StaticUtils.toUpperCase( 1106 supportedCipherSuite))) 1107 { 1108 enabledList.add(supportedCipherSuite); 1109 } 1110 } 1111 1112 if (enabledList.isEmpty()) 1113 { 1114 final StringBuilder enabledBuffer = new StringBuilder(); 1115 final Iterator<String> enabledIterator = desiredCipherSuites.iterator(); 1116 while (enabledIterator.hasNext()) 1117 { 1118 enabledBuffer.append('\''); 1119 enabledBuffer.append(enabledIterator.next()); 1120 enabledBuffer.append('\''); 1121 1122 if (enabledIterator.hasNext()) 1123 { 1124 enabledBuffer.append(", "); 1125 } 1126 } 1127 1128 final StringBuilder supportedBuffer = new StringBuilder(); 1129 for (int i=0; i < supportedCipherSuites.length; i++) 1130 { 1131 if (i > 0) 1132 { 1133 supportedBuffer.append(", "); 1134 } 1135 1136 supportedBuffer.append('\''); 1137 supportedBuffer.append(supportedCipherSuites[i]); 1138 supportedBuffer.append('\''); 1139 } 1140 1141 throw new IOException( 1142 ERR_NO_ENABLED_SSL_CIPHER_SUITES_AVAILABLE_FOR_SOCKET.get( 1143 enabledBuffer.toString(), supportedBuffer.toString(), 1144 PROPERTY_ENABLED_SSL_CIPHER_SUITES, 1145 SSLUtil.class.getName() + ".setEnabledSSLCipherSuites")); 1146 } 1147 else 1148 { 1149 return enabledList.toArray(StaticUtils.NO_STRINGS); 1150 } 1151 } 1152 1153 1154 1155 /** 1156 * Configures SSL default settings for the LDAP SDK. This method is 1157 * non-private for purposes of easier test coverage. 1158 */ 1159 static void configureSSLDefaults() 1160 { 1161 // See if there is a system property that specifies what the default SSL 1162 // protocol should be. If not, then try to dynamically determine it. 1163 final String defaultPropValue = 1164 StaticUtils.getSystemProperty(PROPERTY_DEFAULT_SSL_PROTOCOL); 1165 if ((defaultPropValue != null) && (! defaultPropValue.isEmpty())) 1166 { 1167 DEFAULT_SSL_PROTOCOL.set(defaultPropValue); 1168 } 1169 else 1170 { 1171 // We should be able to discover the SSL protocol that offers the best mix 1172 // of security and compatibility. If we see that TLSv1.1, TLSv1.2, and/or 1173 // TLSv1.3 are available, then we'll add those to the set of default 1174 // enabled protocols. 1175 try 1176 { 1177 final SSLContext defaultContext = SSLContext.getDefault(); 1178 final String[] supportedProtocols = 1179 defaultContext.getSupportedSSLParameters().getProtocols(); 1180 1181 final LinkedHashSet<String> protocolMap = 1182 new LinkedHashSet<>(Arrays.asList(supportedProtocols)); 1183 if (protocolMap.contains(SSL_PROTOCOL_TLS_1_3)) 1184 { 1185 DEFAULT_SSL_PROTOCOL.set(SSL_PROTOCOL_TLS_1_3); 1186 } 1187 else if (protocolMap.contains(SSL_PROTOCOL_TLS_1_2)) 1188 { 1189 DEFAULT_SSL_PROTOCOL.set(SSL_PROTOCOL_TLS_1_2); 1190 } 1191 else if (protocolMap.contains(SSL_PROTOCOL_TLS_1_1)) 1192 { 1193 DEFAULT_SSL_PROTOCOL.set(SSL_PROTOCOL_TLS_1_1); 1194 } 1195 else if (protocolMap.contains(SSL_PROTOCOL_TLS_1)) 1196 { 1197 DEFAULT_SSL_PROTOCOL.set(SSL_PROTOCOL_TLS_1); 1198 } 1199 } 1200 catch (final Exception e) 1201 { 1202 Debug.debugException(e); 1203 } 1204 } 1205 1206 // A set to use for the default set of enabled protocols. Unless otherwise 1207 // specified via system property, we'll always enable TLSv1. We may enable 1208 // other protocols based on the default protocol. The default set of 1209 // enabled protocols will not include SSLv3 even if the JVM might otherwise 1210 // include it as a default enabled protocol because of known security 1211 // problems with SSLv3. 1212 final LinkedHashSet<String> enabledProtocols = 1213 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 1214 if (DEFAULT_SSL_PROTOCOL.get().equals(SSL_PROTOCOL_TLS_1_3)) 1215 { 1216 enabledProtocols.add(SSL_PROTOCOL_TLS_1_3); 1217 enabledProtocols.add(SSL_PROTOCOL_TLS_1_2); 1218 enabledProtocols.add(SSL_PROTOCOL_TLS_1_1); 1219 } 1220 else if (DEFAULT_SSL_PROTOCOL.get().equals(SSL_PROTOCOL_TLS_1_2)) 1221 { 1222 enabledProtocols.add(SSL_PROTOCOL_TLS_1_2); 1223 enabledProtocols.add(SSL_PROTOCOL_TLS_1_1); 1224 } 1225 else if (DEFAULT_SSL_PROTOCOL.get().equals(SSL_PROTOCOL_TLS_1_1)) 1226 { 1227 enabledProtocols.add(SSL_PROTOCOL_TLS_1_1); 1228 } 1229 enabledProtocols.add(SSL_PROTOCOL_TLS_1); 1230 1231 // If there is a system property that specifies which enabled SSL protocols 1232 // to use, then it will override the defaults. 1233 String enabledPropValue = 1234 StaticUtils.getSystemProperty(PROPERTY_ENABLED_SSL_PROTOCOLS); 1235 if ((enabledPropValue != null) && (! enabledPropValue.isEmpty())) 1236 { 1237 enabledProtocols.clear(); 1238 1239 final StringTokenizer tokenizer = new StringTokenizer(enabledPropValue, 1240 ", ", false); 1241 while (tokenizer.hasMoreTokens()) 1242 { 1243 final String token = tokenizer.nextToken(); 1244 if (! token.isEmpty()) 1245 { 1246 enabledProtocols.add(token); 1247 } 1248 } 1249 } 1250 1251 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet(enabledProtocols)); 1252 1253 1254 // Use the TLS cipher suite selector to set the default set of enabled 1255 // cipher suites for any SSL sockets that are created. 1256 ENABLED_SSL_CIPHER_SUITES.set( 1257 TLSCipherSuiteSelector.getRecommendedCipherSuites()); 1258 1259 1260 // If there is a system property that specifies which SSL cipher suites to 1261 // use, then it wil override the defaults. 1262 enabledPropValue = 1263 StaticUtils.getSystemProperty(PROPERTY_ENABLED_SSL_CIPHER_SUITES); 1264 if ((enabledPropValue != null) && (! enabledPropValue.isEmpty())) 1265 { 1266 final LinkedHashSet<String> enabledCipherSuites = 1267 new LinkedHashSet<>(StaticUtils.computeMapCapacity(50)); 1268 1269 final StringTokenizer tokenizer = new StringTokenizer(enabledPropValue, 1270 ", ", false); 1271 while (tokenizer.hasMoreTokens()) 1272 { 1273 final String token = tokenizer.nextToken(); 1274 if (! token.isEmpty()) 1275 { 1276 enabledCipherSuites.add(token); 1277 } 1278 } 1279 1280 if (! enabledCipherSuites.isEmpty()) 1281 { 1282 ENABLED_SSL_CIPHER_SUITES.set( 1283 Collections.unmodifiableSet(enabledCipherSuites)); 1284 } 1285 } 1286 } 1287 1288 1289 1290 /** 1291 * Creates a string representation of the provided certificate. 1292 * 1293 * @param certificate The certificate for which to generate the string 1294 * representation. It must not be {@code null}. 1295 * 1296 * @return A string representation of the provided certificate. 1297 */ 1298 public static String certificateToString(final X509Certificate certificate) 1299 { 1300 final StringBuilder buffer = new StringBuilder(); 1301 certificateToString(certificate, buffer); 1302 return buffer.toString(); 1303 } 1304 1305 1306 1307 /** 1308 * Appends a string representation of the provided certificate to the given 1309 * buffer. 1310 * 1311 * @param certificate The certificate for which to generate the string 1312 * representation. It must not be {@code null}. 1313 * @param buffer The buffer to which to append the string 1314 * representation. 1315 */ 1316 public static void certificateToString(final X509Certificate certificate, 1317 final StringBuilder buffer) 1318 { 1319 buffer.append("Certificate(subject='"); 1320 buffer.append( 1321 certificate.getSubjectX500Principal().getName(X500Principal.RFC2253)); 1322 buffer.append("', serialNumber="); 1323 buffer.append(certificate.getSerialNumber()); 1324 buffer.append(", notBefore="); 1325 StaticUtils.encodeGeneralizedTime(certificate.getNotBefore()); 1326 buffer.append(", notAfter="); 1327 StaticUtils.encodeGeneralizedTime(certificate.getNotAfter()); 1328 buffer.append(", signatureAlgorithm='"); 1329 buffer.append(certificate.getSigAlgName()); 1330 buffer.append("', signatureBytes='"); 1331 StaticUtils.toHex(certificate.getSignature(), buffer); 1332 buffer.append("', issuerSubject='"); 1333 buffer.append( 1334 certificate.getIssuerX500Principal().getName(X500Principal.RFC2253)); 1335 buffer.append("')"); 1336 } 1337}