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