001/* 002 * Copyright 2008-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2008-2024 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-2024 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.Provider; 045import java.security.cert.X509Certificate; 046import java.util.ArrayList; 047import java.util.Arrays; 048import java.util.Collection; 049import java.util.Collections; 050import java.util.Iterator; 051import java.util.LinkedHashSet; 052import java.util.Set; 053import java.util.StringTokenizer; 054import java.util.concurrent.atomic.AtomicReference; 055import javax.net.ssl.KeyManager; 056import javax.net.ssl.SSLContext; 057import javax.net.ssl.SSLServerSocket; 058import javax.net.ssl.SSLSocket; 059import javax.net.ssl.SSLSocketFactory; 060import javax.net.ssl.SSLServerSocketFactory; 061import javax.net.ssl.TrustManager; 062import javax.security.auth.x500.X500Principal; 063 064import com.unboundid.ldap.sdk.LDAPException; 065import com.unboundid.ldap.sdk.ResultCode; 066import com.unboundid.util.CryptoHelper; 067import com.unboundid.util.Debug; 068import com.unboundid.util.NotNull; 069import com.unboundid.util.Nullable; 070import com.unboundid.util.StaticUtils; 071import com.unboundid.util.ThreadLocalSecureRandom; 072import com.unboundid.util.ThreadSafety; 073import com.unboundid.util.ThreadSafetyLevel; 074import com.unboundid.util.Validator; 075 076import static com.unboundid.util.ssl.SSLMessages.*; 077 078 079 080/** 081 * This class provides a relatively simple interface for helping to configure 082 * secure communication using TLS (formerly known as SSL) and StartTLS (which 083 * uses an LDAP extended operation to convert an already-established non-secure 084 * connection to one that uses TLS security). When establishing secure 085 * connections, there are five main concepts to be aware of: 086 * <UL> 087 * <LI>The allowed set of TLS protocol versions</LI> 088 * <LI>The allowed set of TLS cipher suites</LI> 089 * <LI>The key manager (if any) to use for obtaining local certificates</LI> 090 * <LI>The trust manager to use for determining whether to trust peer 091 * certificates</LI> 092 * <LI>The logic used to validate certificate hostnames</LI> 093 * </UL> 094 * Each of these is covered in more detail below. 095 * <BR><BR> 096 * <H2>TLS Protocol Versions</H2> 097 * The TLS protocol has evolved over time to improve both security and 098 * efficiency, and each update to the protocol has been assigned a version 099 * number. At present, only TLSv1.3 and TLSv1.2 are considered secure, and only 100 * those versions will be enabled by default, with TLSv1.3 preferred over 101 * TLSv1.2. Note that some older JVMs do not support TLSv1.3, and only TLSv1.2 102 * will be enabled by default in that case. In the very unlikely event that the 103 * JVM does not support either TLSv1.3 or TLSv1.2, the LDAP SDK may fall back to 104 * enabling support for TLSv1.1 or TLSv1. 105 * <BR><BR> 106 * If you want or need to explicitly specify the TLS protocol versions to use 107 * for secure communication, then you may use the 108 * {@link #setEnabledSSLProtocols} method to indicate which protocol versions 109 * are allowed, and the {@link #setDefaultSSLProtocol} method to indicate which 110 * is the preferred protocol version. You can use any TLS protocol version that 111 * the underlying JVM supports. 112 * <BR><BR> 113 * It is also possible to specify the set of enabled and default TLS protocol 114 * versions using Java system properties. The 115 * {@code com.unboundid.util.SSLUtil.enabledSSLProtocols} property may be set 116 * with a comma-delimited list of the TLS protocol versions that should be 117 * enabled by default, and the 118 * {@code com.unboundid.util.SSLUtil.defaultSSLProtocol} property may be set 119 * with the protocol version that should be preferred. If set, these properties 120 * will override the logic that the LDAP SDK automatically uses to select 121 * default values, but those defaults may be explicitly overridden by calls to 122 * the {@code setEnabledSSLProtocols} and {@code setDefaultSSLProtocol} methods. 123 * <BR><BR> 124 * <H2>TLS Cipher Suites</H2> 125 * A cipher suite encapsulates a number of settings that will be used to 126 * actually secure TLS communication between two systems, including which 127 * algorithm to use for key exchange, which algorithm to use for bulk 128 * encryption, and which algorithm to use for integrity protection. The JVM 129 * supports a fixed set of TLS cipher suites, although it may only enable 130 * support for a subset of those by default, and the LDAP SDK may further 131 * disable support for some of those suites by default for security reasons. 132 * The logic that the LDAP SDK uses to select a good default set of TLS cipher 133 * suites is encapsulated in the {@link TLSCipherSuiteSelector} class, and the 134 * class-level documentation for that class describes the criteria that it uses 135 * to make its selection. 136 * <BR><BR> 137 * If you wish to override the LDAP SDK's default selection, you may use the 138 * {@link #setEnabledSSLCipherSuites} method to explicitly specify the set of 139 * cipher suites that should be enabled. Alternatively, the 140 * {@code com.unboundid.util.SSLUtil.enabledSSLCipherSuites} system property may 141 * be set with a comma-delimited list of the cipher suites that should be 142 * enabled. 143 * <BR><BR> 144 * <H2>Key Managers</H2> 145 * A key manager is used to obtain access to a certificate chain and private key 146 * that should be presented to the peer during TLS negotiation. In the most 147 * common use cases, in which the LDAP SDK is used only to establish outbound 148 * connections and does not need to use a certificate to authenticate itself to 149 * the LDAP server, there won't be any need to present a certificate chain, and 150 * there won't be any need to configure a key manager. However, if you are 151 * using the LDAP SDK to accept TLS-secured connections from LDAP clients (for 152 * example, using the 153 * {@link com.unboundid.ldap.listener.InMemoryDirectoryServer} or 154 * another type of {@link com.unboundid.ldap.listener.LDAPListener}), if the 155 * server requires clients to present their own certificate for mutual TLS 156 * authentication, or if you want to use the SASL EXTERNAL mechanism to use a 157 * client certificate to authenticate to the server at the LDAP layer, then you 158 * will need to specify a key manager to provide access to that certificate 159 * chain. The key manager to use for that purpose should be provided in the 160 * {@code SSLUtil} constructor. 161 * <BR><BR> 162 * While any {@code javax.net.ssl.KeyManager} instance can be used, the LDAP SDK 163 * provides three options that will be sufficient for most use cases: 164 * <UL> 165 * <LI>{@link KeyStoreKeyManager} -- Allows the certificate chain and private 166 * key to be obtained from a key store file, which will typically be in 167 * the JKS or PKCS #12 format (or in the Bouncy Castle BCFKS format when 168 * using the LDAP SDK in FIPS 140-2-compliant mode).</LI> 169 * <LI>{@link PEMFileKeyManager} -- Allows the certificate chain and private 170 * key to be obtained from text files that contain the PEM-encoded 171 * representation of X.509 certificates and a PKCS #8 private key.</LI> 172 * <LI>{@link PKCS11KeyManager} -- Allows the certificate chain and private 173 * key to be accessed from a PKCS #11 token, like a hardware security 174 * module (HSM).</LI> 175 * </UL> 176 * <BR><BR> 177 * <H2>Trust Managers</H2> 178 * A trust manager is used to determine whether to trust a certificate chain 179 * presented by a peer during TLS negotiation. Trust is a very important aspect 180 * of TLS because it's important to make sure that the peer you're communicating 181 * with is actually who you intend it to be and not someone else who has managed 182 * to hijack the negotiation process. 183 * <BR><BR> 184 * You will generally always want to provide a trust manager, regardless of 185 * whether you're using the LDAP SDK to act as a client or a server, and this 186 * trust manager should be provided in the {@code SSLUtil} constructor. The 187 * LDAP SDK offers several trust manager implementations, including: 188 * <UL> 189 * <LI>{@link JVMDefaultTrustManager} -- Uses the JVM's default 190 * {@code cacerts} trust store to obtain access to a set of trusted, 191 * well-known issuer certificates, including those from commercial 192 * certification authorities like Verisign or DigiCert, and from trusted 193 * free providers like Let's Encrypt. This trust manager will only accept 194 * valid certificates that have been signed by one of those trusted 195 * authorities.</LI> 196 * <LI>{@link TrustStoreTrustManager} -- Uses the information in a trust store 197 * file (typically in a format like JKS, PKCS #12 or BCFKS) as a set of 198 * trusted certificates and issuers.</LI> 199 * <LI>{@link PEMFileTrustManager} -- Uses the information one or more files 200 * containing the PEM representations of X.509 certificates as a set of 201 * trusted certificates and issuers.</LI> 202 * <LI>{@link com.unboundid.ldap.sdk.unboundidds.TopologyRegistryTrustManager} 203 * -- Uses the topology registry information in the configuration of a 204 * Ping Identity Directory Server (or related server product) to obtain a 205 * set of trusted certificates and issuers.</LI> 206 * <LI>{@link PromptTrustManager} -- Interactively prompts the user (via the 207 * terminal) to determine whether the presented certificate chain should 208 * be trusted.</LI> 209 * <LI>{@link TrustAllTrustManager} -- Blindly trusts all certificate chains 210 * that are presented to it. This may be convenient in some cases for 211 * testing purposes, but it is strongly discouraged for production use 212 * because it does not actually perform any real trust processing and will 213 * allow connecting to unintended or malicious peers.</LI> 214 * <LI>{@link AggregateTrustManager} -- Allows you to combine multiple other 215 * trust managers in the course of determining whether to trust a 216 * presented certificate chain. For example, you may use this to 217 * automatically trust certificates signed by an issuer in the JVM's 218 * {@code cacerts} file or in an explicitly specified alternative trust 219 * store file, but to fall back to interactively prompting the user for 220 * certificates not trusted by one of the previous two methods.</LI> 221 * </UL> 222 * <BR><BR> 223 * <H2>Certificate Hostname Validation</H2> 224 * Trust managers can be used to ensure that a certificate chain presented by a 225 * peer originally came from a trusted source, but that doesn't necessarily mean 226 * that the peer system is the one you intend it to be. It's not at all 227 * difficult for malicious users and applications to obtain a certificate that 228 * is signed by a CA in the JVM's default set of trusted issuers. However, any 229 * certificate signed by one of those trusted issuers will include information 230 * in a subject alternative name extension that specifies the hostnames (or at 231 * least domain names) and IP addresses for systems with which that certificate 232 * is allowed to be used, and those issues are careful to verify that they only 233 * issue certificates to systems that are legitimately associated with those 234 * systems. So while a malicious user may be able to easily get a certificate 235 * from a trusted issuer, it should not be possible for them to get a 236 * certificate with a subject alternative name extension containing addresses 237 * they don't legitimately have the right to use. 238 * <BR><BR> 239 * Because of this, it's very important that clients not only verify that the 240 * server's certificate comes from a trusted source, but also that it's allowed 241 * to be used by that server system. This additional level of validation can 242 * help thwart attacks that rely on DNS hijacking or other methods of diverting 243 * communication away from the intended recipient to one that an attacker 244 * controls instead. The LDAP SDK does not perform this validation by default 245 * because there are unfortunately too many cases in which clients (especially 246 * those used in testing and development environments) might need to interact 247 * with a server whose certificate may not have an appropriate subject 248 * alternative name extension. However, in production environments with a 249 * properly configured TLS certificate, hostname verification can be enabled by 250 * calling the 251 * {@link com.unboundid.ldap.sdk.LDAPConnectionOptions#setSSLSocketVerifier} 252 * method with an instance of the {@link HostNameSSLSocketVerifier}. 253 * Alternatively, you can set the {@code com.unboundid.ldap.sdk. 254 * LDAPConnectionOptions.defaultVerifyCertificateHostnames} system property with 255 * a value of "{@code true}" to enable this validation by default. 256 * <BR><BR> 257 * <H2>Examples</H2> 258 * The following example demonstrates the process for establish a secure client 259 * connection. It relies on the LDAP SDK's default configuration for selecting 260 * TLS protocols and cipher suites, and does not use a key manager. It uses an 261 * aggregate trust manager to automatically trust any certificates signed by one 262 * of the JVM's default trusted issuers or an issuer in an explicitly specified 263 * key store file, and it enables host name validation. 264 * <BR><BR> 265 * <PRE> 266 * AggregateTrustManager trustManager = new AggregateTrustManager(false, 267 * JVMDefaultTrustManager.getInstance(), 268 * new TrustStoreTrustManager(trustStorePath, trustStorePIN, 269 * "PKCS12", true)); 270 * SSLUtil sslUtil = new SSLUtil(trustManager); 271 * 272 * LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); 273 * connectionOptions.setSSLSocketVerifier( 274 * new HostNameSSLSocketVerifier(true)); 275 * 276 * try (LDAPConnection connection = new LDAPConnection( 277 * sslUtil.createSSLSocketFactory(), connectionOptions, 278 * serverAddress, serverLDAPSPort)) 279 * { 280 * // Use the connection here. 281 * RootDSE rootDSE = connection.getRootDSE(); 282 * } 283 * </PRE> 284 * <BR><BR> 285 * The above example establishes an LDAPS connection that is secured by TLS as 286 * soon as it is created. The following example shows the process needed to use 287 * the StartTLS extended operation to secure an already-established non-secure 288 * connection: 289 * <BR><BR> 290 * <PRE> 291 * AggregateTrustManager trustManager = new AggregateTrustManager(false, 292 * JVMDefaultTrustManager.getInstance(), 293 * new TrustStoreTrustManager(trustStorePath, trustStorePIN, 294 * "PKCS12", true)); 295 * SSLUtil sslUtil = new SSLUtil(trustManager); 296 * 297 * LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); 298 * connectionOptions.setSSLSocketVerifier( 299 * new HostNameSSLSocketVerifier(true)); 300 * 301 * try (LDAPConnection connection = new LDAPConnection( 302 * connectionOptions, serverAddress, serverLDAPPort)) 303 * { 304 * // Use the StartTLS extended operation to secure the connection. 305 * ExtendedResult startTLSResult; 306 * try 307 * { 308 * startTLSResult = connection.processExtendedOperation( 309 * new StartTLSExtendedRequest( 310 * sslUtil.createSSLSocketFactory())); 311 * } 312 * catch (LDAPException e) 313 * { 314 * Debug.debugException(e); 315 * startTLSResult = new ExtendedResult(e); 316 * } 317 * LDAPTestUtils.assertResultCodeEquals(startTLSResult, 318 * ResultCode.SUCCESS); 319 * 320 * // Use the connection here. 321 * RootDSE rootDSE = connection.getRootDSE(); 322 * } 323 * </PRE> 324 */ 325@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 326public final class SSLUtil 327{ 328 /** 329 * The name of a system property 330 * (com.unboundid.util.SSLUtil.defaultSSLProtocol) that can be used to specify 331 * the initial value for the default SSL protocol that should be used. If 332 * this is not set, then the default SSL protocol will be dynamically 333 * determined. This can be overridden via the 334 * {@link #setDefaultSSLProtocol(String)} method. 335 */ 336 @NotNull public static final String PROPERTY_DEFAULT_SSL_PROTOCOL = 337 "com.unboundid.util.SSLUtil.defaultSSLProtocol"; 338 339 340 341 /** 342 * The name of a system property 343 * (com.unboundid.util.SSLUtil.enabledSSLProtocols) that can be used to 344 * provide the initial set of enabled SSL protocols that should be used, as a 345 * comma-delimited list. If this is not set, then the enabled SSL protocols 346 * will be dynamically determined. This can be overridden via the 347 * {@link #setEnabledSSLProtocols(Collection)} method. 348 */ 349 @NotNull public static final String PROPERTY_ENABLED_SSL_PROTOCOLS = 350 "com.unboundid.util.SSLUtil.enabledSSLProtocols"; 351 352 353 354 /** 355 * The name of a system property 356 * (com.unboundid.util.SSLUtil.enabledSSLCipherSuites) that can be used to 357 * provide the initial set of enabled SSL cipher suites that should be used, 358 * as a comma-delimited list. If this is not set, then the enabled SSL cipher 359 * suites will be dynamically determined using the 360 * {@link TLSCipherSuiteSelector}. This can be overridden via the 361 * {@link #setEnabledSSLCipherSuites(Collection)} method. 362 */ 363 @NotNull public static final String PROPERTY_ENABLED_SSL_CIPHER_SUITES = 364 "com.unboundid.util.SSLUtil.enabledSSLCipherSuites"; 365 366 367 368 /** 369 * The name of the SSL protocol that can be used to request TLSv1.3. 370 */ 371 @NotNull public static final String SSL_PROTOCOL_TLS_1_3 = "TLSv1.3"; 372 373 374 375 /** 376 * The name of the SSL protocol that can be used to request TLSv1.2. 377 */ 378 @NotNull public static final String SSL_PROTOCOL_TLS_1_2 = "TLSv1.2"; 379 380 381 382 /** 383 * The name of the SSL protocol that can be used to request TLSv1.1. 384 */ 385 @NotNull public static final String SSL_PROTOCOL_TLS_1_1 = "TLSv1.1"; 386 387 388 389 /** 390 * The name of the SSL protocol that can be used to request TLSv1. 391 */ 392 @NotNull public static final String SSL_PROTOCOL_TLS_1 = "TLSv1"; 393 394 395 396 /** 397 * The name of the SSL protocol that can be used to request SSLv3. 398 */ 399 @NotNull public static final String SSL_PROTOCOL_SSL_3 = "SSLv3"; 400 401 402 403 /** 404 * The name of the SSL protocol that can be used to request SSLv2Hello. 405 */ 406 @NotNull public static final String SSL_PROTOCOL_SSL_2_HELLO = "SSLv2Hello"; 407 408 409 410 /** 411 * The default protocol string that will be used to create SSL contexts when 412 * no explicit protocol is specified. 413 */ 414 @NotNull private static final AtomicReference<String> DEFAULT_SSL_PROTOCOL = 415 new AtomicReference<>(SSL_PROTOCOL_TLS_1_2); 416 417 418 419 /** 420 * The default set of SSL cipher suites that will be enabled for use if 421 * available for SSL sockets created within the LDAP SDK. 422 */ 423 @NotNull private static final AtomicReference<Set<String>> 424 ENABLED_SSL_CIPHER_SUITES = new AtomicReference<>( 425 (Set<String>) new LinkedHashSet<>( 426 TLSCipherSuiteSelector.getRecommendedCipherSuites())); 427 428 429 430 /** 431 * The default set of SSL protocols that will be enabled for use if available 432 * for SSL sockets created within the LDAP SDK. 433 */ 434 @NotNull private static final AtomicReference<Set<String>> 435 ENABLED_SSL_PROTOCOLS = new AtomicReference<>( 436 StaticUtils.setOf(SSL_PROTOCOL_TLS_1_2)); 437 438 439 440 /** 441 * The name of the service type that providers use to indicate the 442 * {@code SSLContext} algorithms that they support. 443 */ 444 @NotNull static final String PROVIDER_SERVICE_TYPE_SSL_CONTEXT = 445 "SSLContext"; 446 447 448 449 /** 450 * Indicates whether SSL/TLS debugging is expected to be enabled, based on 451 * the javax.net.debug system property. 452 */ 453 private static final boolean JVM_SSL_DEBUGGING_ENABLED = 454 TLSCipherSuiteSelector.jvmSSLDebuggingEnabled(); 455 456 457 458 static 459 { 460 configureSSLDefaults(); 461 } 462 463 464 465 // Indicates whether any of the provided key managers is a PKCS #11 key 466 // manager. 467 private final boolean usingPKCS11KeyManager; 468 469 // The set of key managers to be used. 470 @Nullable private final KeyManager[] keyManagers; 471 472 // The set of trust managers to be used. 473 @Nullable private final TrustManager[] trustManagers; 474 475 476 477 /** 478 * Creates a new SSLUtil instance that will not have a custom key manager or 479 * trust manager. It will not be able to provide a certificate to the server 480 * if one is requested, and it will only trust certificates signed by a 481 * predefined set of authorities. 482 */ 483 public SSLUtil() 484 { 485 keyManagers = null; 486 trustManagers = null; 487 usingPKCS11KeyManager = false; 488 } 489 490 491 492 /** 493 * Creates a new SSLUtil instance that will use the provided trust manager to 494 * determine whether to trust server certificates presented to the client. 495 * It will not be able to provide a certificate to the server if one is 496 * requested. 497 * 498 * @param trustManager The trust manager to use to determine whether to 499 * trust server certificates presented to the client. 500 * It may be {@code null} if the default set of trust 501 * managers should be used. 502 */ 503 public SSLUtil(@Nullable final TrustManager trustManager) 504 { 505 keyManagers = null; 506 usingPKCS11KeyManager = false; 507 508 if (trustManager == null) 509 { 510 trustManagers = null; 511 } 512 else 513 { 514 trustManagers = new TrustManager[] { trustManager }; 515 } 516 } 517 518 519 520 /** 521 * Creates a new SSLUtil instance that will use the provided trust managers 522 * to determine whether to trust server certificates presented to the client. 523 * It will not be able to provide a certificate to the server if one is 524 * requested. 525 * 526 * @param trustManagers The set of trust managers to use to determine 527 * whether to trust server certificates presented to 528 * the client. It may be {@code null} or empty if the 529 * default set of trust managers should be used. 530 */ 531 public SSLUtil(@Nullable final TrustManager[] trustManagers) 532 { 533 keyManagers = null; 534 usingPKCS11KeyManager = false; 535 536 if ((trustManagers == null) || (trustManagers.length == 0)) 537 { 538 this.trustManagers = null; 539 } 540 else 541 { 542 this.trustManagers = trustManagers; 543 } 544 } 545 546 547 548 /** 549 * Creates a new SSLUtil instance that will use the provided key manager to 550 * obtain certificates to present to the server, and the provided trust 551 * manager to determine whether to trust server certificates presented to the 552 * client. 553 * 554 * @param keyManager The key manager to use to obtain certificates to 555 * present to the server if requested. It may be 556 * {@code null} if no client certificates will be 557 * required or should be provided. 558 * @param trustManager The trust manager to use to determine whether to 559 * trust server certificates presented to the client. 560 * It may be {@code null} if the default set of trust 561 * managers should be used. 562 */ 563 public SSLUtil(@Nullable final KeyManager keyManager, 564 @Nullable final TrustManager trustManager) 565 { 566 if (keyManager == null) 567 { 568 keyManagers = null; 569 usingPKCS11KeyManager = false; 570 } 571 else 572 { 573 keyManagers = new KeyManager[] { keyManager }; 574 usingPKCS11KeyManager = (keyManager instanceof PKCS11KeyManager); 575 } 576 577 if (trustManager == null) 578 { 579 trustManagers = null; 580 } 581 else 582 { 583 trustManagers = new TrustManager[] { trustManager }; 584 } 585 } 586 587 588 589 /** 590 * Creates a new SSLUtil instance that will use the provided key managers to 591 * obtain certificates to present to the server, and the provided trust 592 * managers to determine whether to trust server certificates presented to the 593 * client. 594 * 595 * @param keyManagers The set of key managers to use to obtain 596 * certificates to present to the server if requested. 597 * It may be {@code null} or empty if no client 598 * certificates will be required or should be provided. 599 * @param trustManagers The set of trust managers to use to determine 600 * whether to trust server certificates presented to 601 * the client. It may be {@code null} or empty if the 602 * default set of trust managers should be used. 603 */ 604 public SSLUtil(@Nullable final KeyManager[] keyManagers, 605 @Nullable final TrustManager[] trustManagers) 606 { 607 if ((keyManagers == null) || (keyManagers.length == 0)) 608 { 609 this.keyManagers = null; 610 usingPKCS11KeyManager = false; 611 } 612 else 613 { 614 this.keyManagers = keyManagers; 615 616 boolean usingPKCS11 = false; 617 for (final KeyManager km : keyManagers) 618 { 619 if (km instanceof PKCS11KeyManager) 620 { 621 usingPKCS11 = true; 622 break; 623 } 624 } 625 626 usingPKCS11KeyManager = usingPKCS11; 627 } 628 629 if ((trustManagers == null) || (trustManagers.length == 0)) 630 { 631 this.trustManagers = null; 632 } 633 else 634 { 635 this.trustManagers = trustManagers; 636 } 637 } 638 639 640 641 /** 642 * Retrieves the set of key managers configured for use by this class, if any. 643 * 644 * @return The set of key managers configured for use by this class, or 645 * {@code null} if none were provided. 646 */ 647 @Nullable() 648 public KeyManager[] getKeyManagers() 649 { 650 return keyManagers; 651 } 652 653 654 655 /** 656 * Retrieves the set of trust managers configured for use by this class, if 657 * any. 658 * 659 * @return The set of trust managers configured for use by this class, or 660 * {@code null} if none were provided. 661 */ 662 @Nullable() 663 public TrustManager[] getTrustManagers() 664 { 665 return trustManagers; 666 } 667 668 669 670 /** 671 * Creates an initialized SSL context created with the configured key and 672 * trust managers. It will use the protocol returned by the 673 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 674 * 675 * @return The created SSL context. 676 * 677 * @throws GeneralSecurityException If a problem occurs while creating or 678 * initializing the SSL context. 679 */ 680 @NotNull() 681 public SSLContext createSSLContext() 682 throws GeneralSecurityException 683 { 684 return createSSLContext(DEFAULT_SSL_PROTOCOL.get()); 685 } 686 687 688 689 /** 690 * Creates an initialized SSL context created with the configured key and 691 * trust managers. It will use a default provider. 692 * 693 * @param protocol The SSL protocol to use. The Java Secure Socket 694 * Extension (JSSE) Reference Guide provides a list of the 695 * supported protocols, but commonly used values are 696 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 697 * not be {@code null}. 698 * 699 * 700 * @return The created SSL context. 701 * 702 * @throws GeneralSecurityException If a problem occurs while creating or 703 * initializing the SSL context. 704 */ 705 @NotNull() 706 public SSLContext createSSLContext(@NotNull final String protocol) 707 throws GeneralSecurityException 708 { 709 Validator.ensureNotNull(protocol); 710 711 SSLContext sslContext = null; 712 if (usingPKCS11KeyManager) 713 { 714 final Provider pkcs11JSSEProvider = 715 PKCS11KeyManager.getPKCS11JSSESProvider(); 716 if ((pkcs11JSSEProvider != null) && (pkcs11JSSEProvider.getService( 717 PROVIDER_SERVICE_TYPE_SSL_CONTEXT, protocol) != null)) 718 { 719 if (JVM_SSL_DEBUGGING_ENABLED) 720 { 721 System.err.println("SSLUtil.createSSLContext creating a PKCS #11 " + 722 "SSLContext for protocol " + protocol); 723 } 724 725 sslContext = CryptoHelper.getSSLContext(protocol, pkcs11JSSEProvider); 726 } 727 } 728 729 if (sslContext == null) 730 { 731 if (JVM_SSL_DEBUGGING_ENABLED) 732 { 733 System.err.println("SSLUtil.createSSLContext creating an SSLContext " + 734 "for protocol " + protocol); 735 } 736 737 sslContext = CryptoHelper.getSSLContext(protocol); 738 } 739 740 sslContext.init(keyManagers, trustManagers, ThreadLocalSecureRandom.get()); 741 return sslContext; 742 } 743 744 745 746 /** 747 * Creates an initialized SSL context created with the configured key and 748 * trust managers. 749 * 750 * @param protocol The SSL protocol to use. The Java Secure Socket 751 * Extension (JSSE) Reference Guide provides a list of the 752 * supported protocols, but commonly used values are 753 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 754 * not be {@code null}. 755 * @param provider The name of the provider to use for cryptographic 756 * operations. It must not be {@code null}. 757 * 758 * @return The created SSL context. 759 * 760 * @throws GeneralSecurityException If a problem occurs while creating or 761 * initializing the SSL context. 762 */ 763 @NotNull() 764 public SSLContext createSSLContext(@NotNull final String protocol, 765 @NotNull final String provider) 766 throws GeneralSecurityException 767 { 768 Validator.ensureNotNull(protocol, provider); 769 770 if (JVM_SSL_DEBUGGING_ENABLED) 771 { 772 System.err.println("SSLUtil.createSSLContext creating an SSLContext " + 773 "for protocol " + protocol + " and provider " + provider); 774 } 775 776 final SSLContext sslContext = 777 CryptoHelper.getSSLContext(protocol, provider); 778 sslContext.init(keyManagers, trustManagers, null); 779 return sslContext; 780 } 781 782 783 784 /** 785 * Creates an SSL socket factory using the configured key and trust manager 786 * providers. It will use the protocol returned by the 787 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 788 * 789 * @return The created SSL socket factory. 790 * 791 * @throws GeneralSecurityException If a problem occurs while creating or 792 * initializing the SSL socket factory. 793 */ 794 @NotNull() 795 public SSLSocketFactory createSSLSocketFactory() 796 throws GeneralSecurityException 797 { 798 if (JVM_SSL_DEBUGGING_ENABLED) 799 { 800 System.err.println("SSLUtil.createSSLSocketFactory creating a " + 801 "SetEnabledProtocolsAndCipherSuitesSSLSocketFactory with enabled " + 802 "protocols " + ENABLED_SSL_PROTOCOLS.get() + 803 " and enabled cipher suites " + ENABLED_SSL_CIPHER_SUITES.get()); 804 } 805 806 return new SetEnabledProtocolsAndCipherSuitesSSLSocketFactory( 807 createSSLContext().getSocketFactory(), 808 ENABLED_SSL_PROTOCOLS.get(), ENABLED_SSL_CIPHER_SUITES.get()); 809 } 810 811 812 813 /** 814 * Creates an SSL socket factory with the configured key and trust managers. 815 * It will use the default provider. 816 * 817 * @param protocol The SSL protocol to use. The Java Secure Socket 818 * Extension (JSSE) Reference Guide provides a list of the 819 * supported protocols, but commonly used values are 820 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 821 * not be {@code null}. 822 * 823 * @return The created SSL socket factory. 824 * 825 * @throws GeneralSecurityException If a problem occurs while creating or 826 * initializing the SSL socket factory. 827 */ 828 @NotNull() 829 public SSLSocketFactory createSSLSocketFactory( 830 @NotNull final String protocol) 831 throws GeneralSecurityException 832 { 833 if (JVM_SSL_DEBUGGING_ENABLED) 834 { 835 System.err.println("SSLUtil.createSSLSocketFactory creating a " + 836 "SetEnabledProtocolsAndCipherSuitesSSLSocketFactory with protocol " + 837 protocol + " and enabled cipher suites " + 838 ENABLED_SSL_CIPHER_SUITES.get()); 839 } 840 841 return new SetEnabledProtocolsAndCipherSuitesSSLSocketFactory( 842 createSSLContext(protocol).getSocketFactory(), protocol, 843 ENABLED_SSL_CIPHER_SUITES.get()); 844 } 845 846 847 848 /** 849 * Creates an SSL socket factory with the configured key and trust managers. 850 * 851 * @param protocol The SSL protocol to use. The Java Secure Socket 852 * Extension (JSSE) Reference Guide provides a list of the 853 * supported protocols, but commonly used values are 854 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 855 * not be {@code null}. 856 * @param provider The name of the provider to use for cryptographic 857 * operations. It must not be {@code null}. 858 * 859 * @return The created SSL socket factory. 860 * 861 * @throws GeneralSecurityException If a problem occurs while creating or 862 * initializing the SSL socket factory. 863 */ 864 @NotNull() 865 public SSLSocketFactory createSSLSocketFactory(@NotNull final String protocol, 866 @NotNull final String provider) 867 throws GeneralSecurityException 868 { 869 if (JVM_SSL_DEBUGGING_ENABLED) 870 { 871 System.err.println("SSLUtil.createSSLSocketFactory creating an " + 872 873 "SetEnabledProtocolsAndCipherSuitesSSLSocketFactory with protocol " + 874 protocol + ", provider " + provider + 875 ", and enabled cipher suites " + ENABLED_SSL_CIPHER_SUITES.get()); 876 } 877 878 return new SetEnabledProtocolsAndCipherSuitesSSLSocketFactory( 879 createSSLContext(protocol, provider).getSocketFactory(), protocol, 880 ENABLED_SSL_CIPHER_SUITES.get()); 881 } 882 883 884 885 /** 886 * Creates an SSL server socket factory using the configured key and trust 887 * manager providers. It will use the protocol returned by the 888 * {@link #getDefaultSSLProtocol} method and the JVM-default provider. 889 * 890 * @return The created SSL server socket factory. 891 * 892 * @throws GeneralSecurityException If a problem occurs while creating or 893 * initializing the SSL server socket 894 * factory. 895 */ 896 @NotNull() 897 public SSLServerSocketFactory createSSLServerSocketFactory() 898 throws GeneralSecurityException 899 { 900 if (JVM_SSL_DEBUGGING_ENABLED) 901 { 902 System.err.println("SSLUtil.createSSLServerSocketFactory creating a " + 903 "SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory with " + 904 "enabled protocols " + ENABLED_SSL_PROTOCOLS.get() + 905 " and enabled cipher suites " + ENABLED_SSL_CIPHER_SUITES.get()); 906 } 907 908 return new SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory( 909 createSSLContext().getServerSocketFactory(), 910 ENABLED_SSL_PROTOCOLS.get(), ENABLED_SSL_CIPHER_SUITES.get()); 911 } 912 913 914 915 /** 916 * Creates an SSL server socket factory using the configured key and trust 917 * manager providers. It will use the JVM-default provider. 918 * 919 * @param protocol The SSL protocol to use. The Java Secure Socket 920 * Extension (JSSE) Reference Guide provides a list of the 921 * supported protocols, but commonly used values are 922 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 923 * not be {@code null}. 924 * 925 * @return The created SSL server socket factory. 926 * 927 * @throws GeneralSecurityException If a problem occurs while creating or 928 * initializing the SSL server socket 929 * factory. 930 */ 931 @NotNull() 932 public SSLServerSocketFactory createSSLServerSocketFactory( 933 @NotNull final String protocol) 934 throws GeneralSecurityException 935 { 936 if (JVM_SSL_DEBUGGING_ENABLED) 937 { 938 System.err.println("SSLUtil.createSSLServerSocketFactory creating a " + 939 "SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory with " + 940 "protocol " + protocol + " and enabled cipher suites " + 941 ENABLED_SSL_CIPHER_SUITES.get()); 942 } 943 944 return new SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory( 945 createSSLContext(protocol).getServerSocketFactory(), protocol, 946 ENABLED_SSL_CIPHER_SUITES.get()); 947 } 948 949 950 951 /** 952 * Creates an SSL server socket factory using the configured key and trust 953 * manager providers. 954 * 955 * @param protocol The SSL protocol to use. The Java Secure Socket 956 * Extension (JSSE) Reference Guide provides a list of the 957 * supported protocols, but commonly used values are 958 * "TLSv1.3", "TLSv1.2", "TLSv1.1", and "TLSv1". This must 959 * not be {@code null}. 960 * @param provider The name of the provider to use for cryptographic 961 * operations. It must not be {@code null}. 962 * 963 * @return The created SSL server socket factory. 964 * 965 * @throws GeneralSecurityException If a problem occurs while creating or 966 * initializing the SSL server socket 967 * factory. 968 */ 969 @NotNull() 970 public SSLServerSocketFactory createSSLServerSocketFactory( 971 @NotNull final String protocol, 972 @NotNull final String provider) 973 throws GeneralSecurityException 974 { 975 if (JVM_SSL_DEBUGGING_ENABLED) 976 { 977 System.err.println("SSLUtil.createSSLServerSocketFactory creating a " + 978 "SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory with " + 979 "protocol " + protocol + ", provider " + provider + 980 ", and enabled cipher suites " + ENABLED_SSL_CIPHER_SUITES.get()); 981 } 982 983 return new SetEnabledProtocolsAndCipherSuitesSSLServerSocketFactory( 984 createSSLContext(protocol, provider).getServerSocketFactory(), 985 protocol, ENABLED_SSL_CIPHER_SUITES.get()); 986 } 987 988 989 990 /** 991 * Retrieves the SSL protocol string that will be used by calls to 992 * {@link #createSSLContext()} that do not explicitly specify which protocol 993 * to use. 994 * 995 * @return The SSL protocol string that will be used by calls to create an 996 * SSL context that do not explicitly specify which protocol to use. 997 */ 998 @NotNull() 999 public static String getDefaultSSLProtocol() 1000 { 1001 return DEFAULT_SSL_PROTOCOL.get(); 1002 } 1003 1004 1005 1006 /** 1007 * Specifies the SSL protocol string that will be used by calls to 1008 * {@link #createSSLContext()} that do not explicitly specify which protocol 1009 * to use. 1010 * 1011 * @param defaultSSLProtocol The SSL protocol string that will be used by 1012 * calls to create an SSL context that do not 1013 * explicitly specify which protocol to use. It 1014 * must not be {@code null}. 1015 */ 1016 public static void setDefaultSSLProtocol( 1017 @NotNull final String defaultSSLProtocol) 1018 { 1019 Validator.ensureNotNull(defaultSSLProtocol); 1020 1021 if (JVM_SSL_DEBUGGING_ENABLED) 1022 { 1023 System.err.println("SSLUtil.setDefaultSSLProtocol setting the " + 1024 "default SSL protocol to " + defaultSSLProtocol); 1025 } 1026 1027 DEFAULT_SSL_PROTOCOL.set(defaultSSLProtocol); 1028 } 1029 1030 1031 1032 /** 1033 * Retrieves the set of SSL protocols that will be enabled for use, if 1034 * available, for SSL sockets created within the LDAP SDK. 1035 * 1036 * @return The set of SSL protocols that will be enabled for use, if 1037 * available, for SSL sockets created within the LDAP SDK. 1038 */ 1039 @NotNull() 1040 public static Set<String> getEnabledSSLProtocols() 1041 { 1042 return ENABLED_SSL_PROTOCOLS.get(); 1043 } 1044 1045 1046 1047 /** 1048 * Specifies the set of SSL protocols that will be enabled for use for SSL 1049 * sockets created within the LDAP SDK. When creating an SSL socket, the 1050 * {@code SSLSocket.getSupportedProtocols} method will be used to determine 1051 * which protocols are supported for that socket, and then the 1052 * {@code SSLSocket.setEnabledProtocols} method will be used to enable those 1053 * protocols which are listed as both supported by the socket and included in 1054 * this set. If the provided set is {@code null} or empty, then the default 1055 * set of enabled protocols will be used. 1056 * 1057 * @param enabledSSLProtocols The set of SSL protocols that will be enabled 1058 * for use for SSL sockets created within the 1059 * LDAP SDK. It may be {@code null} or empty to 1060 * indicate that the JDK-default set of enabled 1061 * protocols should be used for the socket. 1062 */ 1063 public static void setEnabledSSLProtocols( 1064 @Nullable final Collection<String> enabledSSLProtocols) 1065 { 1066 if (enabledSSLProtocols == null) 1067 { 1068 if (JVM_SSL_DEBUGGING_ENABLED) 1069 { 1070 System.err.println("SSLUtil.setEnabledSSLProtocols setting the " + 1071 "enabled SSL protocols to an empty set"); 1072 } 1073 1074 ENABLED_SSL_PROTOCOLS.set(Collections.<String>emptySet()); 1075 } 1076 else 1077 { 1078 if (JVM_SSL_DEBUGGING_ENABLED) 1079 { 1080 System.err.println("SSLUtil.setEnabledSSLProtocols setting the " + 1081 "enabled SSL protocols to " + enabledSSLProtocols); 1082 } 1083 1084 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet( 1085 new LinkedHashSet<>(enabledSSLProtocols))); 1086 } 1087 } 1088 1089 1090 1091 /** 1092 * Updates the provided socket to apply the appropriate set of enabled SSL 1093 * protocols. This will only have any effect for sockets that are instances 1094 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 1095 * {@code java.net.Socket}. This should be called before attempting any 1096 * communication over the socket. 1097 * 1098 * @param socket The socket on which to apply the configured set of enabled 1099 * SSL protocols. 1100 * 1101 * @throws LDAPException If {@link #getEnabledSSLProtocols} returns a 1102 * non-empty set but none of the values in that set 1103 * are supported by the socket. 1104 */ 1105 public static void applyEnabledSSLProtocols(@NotNull final Socket socket) 1106 throws LDAPException 1107 { 1108 try 1109 { 1110 applyEnabledSSLProtocols(socket, ENABLED_SSL_PROTOCOLS.get()); 1111 } 1112 catch (final IOException ioe) 1113 { 1114 Debug.debugException(ioe); 1115 throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe); 1116 } 1117 } 1118 1119 1120 1121 /** 1122 * Updates the provided socket to apply the appropriate set of enabled SSL 1123 * protocols. This will only have any effect for sockets that are instances 1124 * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of 1125 * {@code java.net.Socket}. This should be called before attempting any 1126 * communication over the socket. 1127 * 1128 * @param socket The socket on which to apply the configured set of 1129 * enabled SSL protocols. 1130 * @param protocols The set of protocols that should be enabled for the 1131 * socket, if available. 1132 * 1133 * @throws IOException If a problem is encountered while applying the 1134 * desired set of enabled protocols to the given socket. 1135 */ 1136 static void applyEnabledSSLProtocols(@Nullable final Socket socket, 1137 @NotNull final Set<String> protocols) 1138 throws IOException 1139 { 1140 if ((socket == null) || (!(socket instanceof SSLSocket)) || 1141 protocols.isEmpty()) 1142 { 1143 return; 1144 } 1145 1146 final SSLSocket sslSocket = (SSLSocket) socket; 1147 final String[] protocolsToEnable = 1148 getSSLProtocolsToEnable(protocols, sslSocket.getSupportedProtocols()); 1149 1150 try 1151 { 1152 if (JVM_SSL_DEBUGGING_ENABLED) 1153 { 1154 System.err.println("SSLUtil.applyEnabledSSLProtocols applying " + 1155 "protocolsToEnable " + Arrays.toString(protocolsToEnable) + 1156 " to SSLSocket " + sslSocket); 1157 } 1158 1159 sslSocket.setEnabledProtocols(protocolsToEnable); 1160 } 1161 catch (final Exception e) 1162 { 1163 Debug.debugException(e); 1164 } 1165 } 1166 1167 1168 1169 /** 1170 * Updates the provided server socket to apply the appropriate set of enabled 1171 * SSL protocols. This will only have any effect for server sockets that are 1172 * instances of {@code javax.net.ssl.SSLServerSocket}, but it is safe to call 1173 * for any kind of {@code java.net.ServerSocket}. This should be called 1174 * before attempting any communication over the socket. 1175 * 1176 * @param serverSocket The server socket on which to apply the configured 1177 * set of enabled SSL protocols. 1178 * @param protocols The set of protocols that should be enabled for the 1179 * server socket, if available. 1180 * 1181 * @throws IOException If a problem is encountered while applying the 1182 * desired set of enabled protocols to the given server 1183 * socket. 1184 */ 1185 static void applyEnabledSSLProtocols( 1186 @Nullable final ServerSocket serverSocket, 1187 @NotNull final Set<String> protocols) 1188 throws IOException 1189 { 1190 if ((serverSocket == null) || 1191 (!(serverSocket instanceof SSLServerSocket)) || 1192 protocols.isEmpty()) 1193 { 1194 return; 1195 } 1196 1197 final SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket; 1198 final String[] protocolsToEnable = getSSLProtocolsToEnable(protocols, 1199 sslServerSocket.getSupportedProtocols()); 1200 1201 try 1202 { 1203 if (JVM_SSL_DEBUGGING_ENABLED) 1204 { 1205 System.err.println("SSLUtil.applyEnabledSSLProtocols applying " + 1206 "protocolsToEnable " + Arrays.toString(protocolsToEnable) + 1207 " to SSLServerSocket " + sslServerSocket); 1208 } 1209 1210 sslServerSocket.setEnabledProtocols(protocolsToEnable); 1211 } 1212 catch (final Exception e) 1213 { 1214 Debug.debugException(e); 1215 } 1216 } 1217 1218 1219 1220 /** 1221 * Retrieves the names of the SSL protocols that should be enabled given the 1222 * provided information. 1223 * 1224 * @param desiredProtocols The set of protocols that are desired to be 1225 * enabled. 1226 * @param supportedProtocols The set of all protocols that are supported. 1227 * 1228 * @return The names of the SSL protocols that should be enabled. 1229 * 1230 * @throws IOException If none of the desired values are included in the 1231 * supported set. 1232 */ 1233 @NotNull() 1234 private static String[] getSSLProtocolsToEnable( 1235 @NotNull final Set<String> desiredProtocols, 1236 @NotNull final String[] supportedProtocols) 1237 throws IOException 1238 { 1239 final Set<String> lowerProtocols = new LinkedHashSet<>( 1240 StaticUtils.computeMapCapacity(desiredProtocols.size())); 1241 for (final String s : desiredProtocols) 1242 { 1243 lowerProtocols.add(StaticUtils.toLowerCase(s)); 1244 } 1245 1246 final ArrayList<String> enabledList = 1247 new ArrayList<>(supportedProtocols.length); 1248 for (final String supportedProtocol : supportedProtocols) 1249 { 1250 if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol))) 1251 { 1252 enabledList.add(supportedProtocol); 1253 } 1254 } 1255 1256 if (enabledList.isEmpty()) 1257 { 1258 final StringBuilder enabledBuffer = new StringBuilder(); 1259 final Iterator<String> enabledIterator = desiredProtocols.iterator(); 1260 while (enabledIterator.hasNext()) 1261 { 1262 enabledBuffer.append('\''); 1263 enabledBuffer.append(enabledIterator.next()); 1264 enabledBuffer.append('\''); 1265 1266 if (enabledIterator.hasNext()) 1267 { 1268 enabledBuffer.append(", "); 1269 } 1270 } 1271 1272 final StringBuilder supportedBuffer = new StringBuilder(); 1273 for (int i=0; i < supportedProtocols.length; i++) 1274 { 1275 if (i > 0) 1276 { 1277 supportedBuffer.append(", "); 1278 } 1279 1280 supportedBuffer.append('\''); 1281 supportedBuffer.append(supportedProtocols[i]); 1282 supportedBuffer.append('\''); 1283 } 1284 1285 throw new IOException( 1286 ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get( 1287 enabledBuffer.toString(), supportedBuffer.toString(), 1288 PROPERTY_ENABLED_SSL_PROTOCOLS, 1289 SSLUtil.class.getName() + ".setEnabledSSLProtocols")); 1290 } 1291 else 1292 { 1293 return enabledList.toArray(StaticUtils.NO_STRINGS); 1294 } 1295 } 1296 1297 1298 1299 /** 1300 * Retrieves the set of SSL cipher suites that will be enabled for use, if 1301 * available, for SSL sockets created within the LDAP SDK. 1302 * 1303 * @return The set of SSL cipher suites that will be enabled for use, if 1304 * available, for SSL sockets created within the LDAP SDK. 1305 */ 1306 @NotNull() 1307 public static Set<String> getEnabledSSLCipherSuites() 1308 { 1309 return ENABLED_SSL_CIPHER_SUITES.get(); 1310 } 1311 1312 1313 1314 /** 1315 * Specifies the set of SSL cipher suites that will be enabled for SSL sockets 1316 * created within the LDAP SDK. When creating an SSL socket, the 1317 * {@code SSLSocket.getSupportedCipherSuites} method will be used to determine 1318 * which cipher suites are supported for that socket, and then the 1319 * {@code SSLSocket.setEnabledCipherSuites} method will be used to enable 1320 * those suites which are listed as both supported by the socket and included 1321 * in this set. If the provided set is {@code null} or empty, then the 1322 * default set of enabled cipher suites will be used. 1323 * 1324 * @param enabledSSLCipherSuites The set of SSL cipher suites that will be 1325 * enabled for use for SSL sockets created 1326 * within the LDAP SDK. It may be 1327 * {@code null} or empty to indicate that the 1328 * JDK-default set of enabled cipher suites 1329 * should be used for the socket. 1330 */ 1331 public static void setEnabledSSLCipherSuites( 1332 @Nullable final Collection<String> enabledSSLCipherSuites) 1333 { 1334 if (enabledSSLCipherSuites == null) 1335 { 1336 if (JVM_SSL_DEBUGGING_ENABLED) 1337 { 1338 System.err.println("SSLUtil.setEnabledSSLCipherSuites setting the " + 1339 "enabled SSL cipher suites to an empty set"); 1340 } 1341 1342 ENABLED_SSL_CIPHER_SUITES.set(Collections.<String>emptySet()); 1343 } 1344 else 1345 { 1346 if (JVM_SSL_DEBUGGING_ENABLED) 1347 { 1348 System.err.println("SSLUtil.setEnabledSSLCipherSuites setting the " + 1349 "enabled SSL cipher suites to " + enabledSSLCipherSuites); 1350 } 1351 1352 ENABLED_SSL_CIPHER_SUITES.set(Collections.unmodifiableSet( 1353 new LinkedHashSet<>(enabledSSLCipherSuites))); 1354 } 1355 } 1356 1357 1358 1359 /** 1360 * Updates the provided socket to apply the appropriate set of enabled SSL 1361 * cipher suites. This will only have any effect for sockets that are 1362 * instances of {@code javax.net.ssl.SSLSocket}, but it is safe to call for 1363 * any kind of {@code java.net.Socket}. This should be called before 1364 * attempting any communication over the socket. 1365 * 1366 * @param socket The socket on which to apply the configured set of enabled 1367 * SSL cipher suites. 1368 * 1369 * @throws LDAPException If {@link #getEnabledSSLCipherSuites} returns a 1370 * non-empty set but none of the values in that set 1371 * are supported by the socket. 1372 */ 1373 public static void applyEnabledSSLCipherSuites(@NotNull final Socket socket) 1374 throws LDAPException 1375 { 1376 try 1377 { 1378 applyEnabledSSLCipherSuites(socket, ENABLED_SSL_CIPHER_SUITES.get()); 1379 } 1380 catch (final IOException ioe) 1381 { 1382 Debug.debugException(ioe); 1383 throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe); 1384 } 1385 } 1386 1387 1388 1389 /** 1390 * Updates the provided socket to apply the appropriate set of enabled SSL 1391 * cipher suites. This will only have any effect for sockets that are 1392 * instances of {@code javax.net.ssl.SSLSocket}, but it is safe to call for 1393 * any kind of {@code java.net.Socket}. This should be called before 1394 * attempting any communication over the socket. 1395 * 1396 * @param socket The socket on which to apply the configured set of 1397 * enabled SSL cipher suites. 1398 * @param cipherSuites The set of cipher suites that should be enabled for 1399 * the socket, if available. 1400 * 1401 * @throws IOException If a problem is encountered while applying the 1402 * desired set of enabled cipher suites to the given 1403 * socket. 1404 */ 1405 static void applyEnabledSSLCipherSuites(@Nullable final Socket socket, 1406 @NotNull final Set<String> cipherSuites) 1407 throws IOException 1408 { 1409 if ((socket == null) || (!(socket instanceof SSLSocket)) || 1410 cipherSuites.isEmpty()) 1411 { 1412 return; 1413 } 1414 1415 final SSLSocket sslSocket = (SSLSocket) socket; 1416 final String[] cipherSuitesToEnable = 1417 getSSLCipherSuitesToEnable(cipherSuites, 1418 sslSocket.getSupportedCipherSuites()); 1419 try 1420 { 1421 if (JVM_SSL_DEBUGGING_ENABLED) 1422 { 1423 System.err.println("SSLUtil.applyEnabledSSLCipherSuites applying " + 1424 "cinpherSuitesToEnable " + Arrays.toString(cipherSuitesToEnable) + 1425 " to SSLSocket " + sslSocket); 1426 } 1427 1428 sslSocket.setEnabledCipherSuites(cipherSuitesToEnable); 1429 } 1430 catch (final Exception e) 1431 { 1432 Debug.debugException(e); 1433 } 1434 } 1435 1436 1437 1438 /** 1439 * Updates the provided server socket to apply the appropriate set of enabled 1440 * SSL cipher suites. This will only have any effect for server sockets that 1441 * are instances of {@code javax.net.ssl.SSLServerSocket}, but it is safe to 1442 * call for any kind of {@code java.net.ServerSocket}. This should be called 1443 * before attempting any communication over the socket. 1444 * 1445 * @param serverSocket The server socket on which to apply the configured 1446 * set of enabled SSL cipher suites. 1447 * @param cipherSuites The set of cipher suites that should be enabled 1448 * for the server socket, if available. 1449 * 1450 * @throws IOException If a problem is encountered while applying the 1451 * desired set of enabled cipher suites to the given 1452 * server socket. 1453 */ 1454 static void applyEnabledSSLCipherSuites( 1455 @Nullable final ServerSocket serverSocket, 1456 @NotNull final Set<String> cipherSuites) 1457 throws IOException 1458 { 1459 if ((serverSocket == null) || 1460 (! (serverSocket instanceof SSLServerSocket)) || 1461 cipherSuites.isEmpty()) 1462 { 1463 return; 1464 } 1465 1466 final SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket; 1467 final String[] cipherSuitesToEnable = 1468 getSSLCipherSuitesToEnable(cipherSuites, 1469 sslServerSocket.getSupportedCipherSuites()); 1470 1471 try 1472 { 1473 if (JVM_SSL_DEBUGGING_ENABLED) 1474 { 1475 System.err.println("SSLUtil.applyEnabledSSLCipherSuites applying " + 1476 "cinpherSuitesToEnable " + Arrays.toString(cipherSuitesToEnable) + 1477 " to SSLServerSocket " + sslServerSocket); 1478 } 1479 1480 sslServerSocket.setEnabledCipherSuites(cipherSuitesToEnable); 1481 } 1482 catch (final Exception e) 1483 { 1484 Debug.debugException(e); 1485 } 1486 } 1487 1488 1489 1490 /** 1491 * Retrieves the names of the SSL cipher suites that should be enabled given 1492 * the provided information. 1493 * 1494 * @param desiredCipherSuites The set of cipher suites that are desired to 1495 * be enabled. 1496 * @param supportedCipherSuites The set of all cipher suites that are 1497 * supported. 1498 * 1499 * @return The names of the SSL cipher suites that should be enabled. 1500 * 1501 * @throws IOException If none of the desired values are included in the 1502 * supported set. 1503 */ 1504 @NotNull() 1505 private static String[] getSSLCipherSuitesToEnable( 1506 @NotNull final Set<String> desiredCipherSuites, 1507 @NotNull final String[] supportedCipherSuites) 1508 throws IOException 1509 { 1510 final Set<String> upperCipherSuites = new LinkedHashSet<>( 1511 StaticUtils.computeMapCapacity(desiredCipherSuites.size())); 1512 for (final String s : desiredCipherSuites) 1513 { 1514 upperCipherSuites.add(StaticUtils.toUpperCase(s)); 1515 } 1516 1517 final ArrayList<String> enabledList = 1518 new ArrayList<>(supportedCipherSuites.length); 1519 for (final String supportedCipherSuite : supportedCipherSuites) 1520 { 1521 if (upperCipherSuites.contains(StaticUtils.toUpperCase( 1522 supportedCipherSuite))) 1523 { 1524 enabledList.add(supportedCipherSuite); 1525 } 1526 } 1527 1528 if (enabledList.isEmpty()) 1529 { 1530 final StringBuilder enabledBuffer = new StringBuilder(); 1531 final Iterator<String> enabledIterator = desiredCipherSuites.iterator(); 1532 while (enabledIterator.hasNext()) 1533 { 1534 enabledBuffer.append('\''); 1535 enabledBuffer.append(enabledIterator.next()); 1536 enabledBuffer.append('\''); 1537 1538 if (enabledIterator.hasNext()) 1539 { 1540 enabledBuffer.append(", "); 1541 } 1542 } 1543 1544 final StringBuilder supportedBuffer = new StringBuilder(); 1545 for (int i=0; i < supportedCipherSuites.length; i++) 1546 { 1547 if (i > 0) 1548 { 1549 supportedBuffer.append(", "); 1550 } 1551 1552 supportedBuffer.append('\''); 1553 supportedBuffer.append(supportedCipherSuites[i]); 1554 supportedBuffer.append('\''); 1555 } 1556 1557 throw new IOException( 1558 ERR_NO_ENABLED_SSL_CIPHER_SUITES_AVAILABLE_FOR_SOCKET.get( 1559 enabledBuffer.toString(), supportedBuffer.toString(), 1560 PROPERTY_ENABLED_SSL_CIPHER_SUITES, 1561 SSLUtil.class.getName() + ".setEnabledSSLCipherSuites")); 1562 } 1563 else 1564 { 1565 return enabledList.toArray(StaticUtils.NO_STRINGS); 1566 } 1567 } 1568 1569 1570 1571 /** 1572 * Configures SSL default settings for the LDAP SDK. This method is 1573 * non-private for purposes of easier test coverage. 1574 */ 1575 static void configureSSLDefaults() 1576 { 1577 // Determine the set of TLS protocols that the JVM supports. 1578 String tls13Protocol = null; 1579 String tls12Protocol = null; 1580 String tls11Protocol = null; 1581 String tls1Protocol = null; 1582 try 1583 { 1584 final SSLContext defaultContext = CryptoHelper.getDefaultSSLContext(); 1585 for (final String supportedProtocol : 1586 defaultContext.getSupportedSSLParameters().getProtocols()) 1587 { 1588 if (supportedProtocol.equalsIgnoreCase(SSL_PROTOCOL_TLS_1_3)) 1589 { 1590 tls13Protocol = supportedProtocol; 1591 } 1592 else if (supportedProtocol.equalsIgnoreCase(SSL_PROTOCOL_TLS_1_2)) 1593 { 1594 tls12Protocol = supportedProtocol; 1595 } 1596 else if (supportedProtocol.equalsIgnoreCase(SSL_PROTOCOL_TLS_1_1)) 1597 { 1598 tls11Protocol = supportedProtocol; 1599 } 1600 else if (supportedProtocol.equalsIgnoreCase(SSL_PROTOCOL_TLS_1)) 1601 { 1602 tls1Protocol = supportedProtocol; 1603 } 1604 } 1605 } 1606 catch (final Exception e) 1607 { 1608 Debug.debugException(e); 1609 } 1610 1611 1612 // Determine the set of TLS protocols that should be enabled. 1613 final String enabledProtocolsPropertyValue = 1614 StaticUtils.getSystemProperty(PROPERTY_ENABLED_SSL_PROTOCOLS); 1615 final Set<String> enabledProtocols = new LinkedHashSet<>(); 1616 if (enabledProtocolsPropertyValue != null) 1617 { 1618 final StringTokenizer tokenizer = 1619 new StringTokenizer(enabledProtocolsPropertyValue, ", ", false); 1620 while (tokenizer.hasMoreTokens()) 1621 { 1622 final String enabledProtocol = tokenizer.nextToken().trim(); 1623 if (! enabledProtocol.isEmpty()) 1624 { 1625 enabledProtocols.add(enabledProtocol); 1626 } 1627 } 1628 } 1629 else 1630 { 1631 if (tls13Protocol != null) 1632 { 1633 enabledProtocols.add(tls13Protocol); 1634 if (tls12Protocol != null) 1635 { 1636 enabledProtocols.add(tls12Protocol); 1637 } 1638 } 1639 else if (tls12Protocol != null) 1640 { 1641 enabledProtocols.add(tls12Protocol); 1642 } 1643 else if (tls11Protocol != null) 1644 { 1645 enabledProtocols.add(tls11Protocol); 1646 } 1647 else if (tls1Protocol != null) 1648 { 1649 enabledProtocols.add(tls1Protocol); 1650 } 1651 } 1652 1653 ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet(enabledProtocols)); 1654 1655 1656 // Determine the default TLS protocol. 1657 final String defaultProtocol; 1658 final String defaultProtocolPropertyValue = 1659 StaticUtils.getSystemProperty(PROPERTY_DEFAULT_SSL_PROTOCOL); 1660 if (defaultProtocolPropertyValue != null) 1661 { 1662 defaultProtocol = defaultProtocolPropertyValue; 1663 } 1664 else 1665 { 1666 defaultProtocol = enabledProtocols.iterator().next(); 1667 } 1668 1669 DEFAULT_SSL_PROTOCOL.set(defaultProtocol); 1670 1671 1672 // Determine the set of TLS cipher suites to enable by default. 1673 TLSCipherSuiteSelector.recompute(); 1674 final String enabledSuitesPropertyValue = 1675 StaticUtils.getSystemProperty(PROPERTY_ENABLED_SSL_CIPHER_SUITES); 1676 final LinkedHashSet<String> enabledCipherSuites = new LinkedHashSet<>(); 1677 if ((enabledSuitesPropertyValue != null) && 1678 (! enabledSuitesPropertyValue.isEmpty())) 1679 { 1680 final StringTokenizer tokenizer = 1681 new StringTokenizer(enabledSuitesPropertyValue, ", ", false); 1682 while (tokenizer.hasMoreTokens()) 1683 { 1684 final String token = tokenizer.nextToken().trim(); 1685 if (! token.isEmpty()) 1686 { 1687 enabledCipherSuites.add(token); 1688 } 1689 } 1690 } 1691 else 1692 { 1693 enabledCipherSuites.addAll( 1694 TLSCipherSuiteSelector.getRecommendedCipherSuites()); 1695 } 1696 1697 ENABLED_SSL_CIPHER_SUITES.set(enabledCipherSuites); 1698 } 1699 1700 1701 1702 /** 1703 * Creates a string representation of the provided certificate. 1704 * 1705 * @param certificate The certificate for which to generate the string 1706 * representation. It must not be {@code null}. 1707 * 1708 * @return A string representation of the provided certificate. 1709 */ 1710 @NotNull() 1711 public static String certificateToString( 1712 @NotNull final X509Certificate certificate) 1713 { 1714 final StringBuilder buffer = new StringBuilder(); 1715 certificateToString(certificate, buffer); 1716 return buffer.toString(); 1717 } 1718 1719 1720 1721 /** 1722 * Appends a string representation of the provided certificate to the given 1723 * buffer. 1724 * 1725 * @param certificate The certificate for which to generate the string 1726 * representation. It must not be {@code null}. 1727 * @param buffer The buffer to which to append the string 1728 * representation. 1729 */ 1730 public static void certificateToString( 1731 @NotNull final X509Certificate certificate, 1732 @NotNull final StringBuilder buffer) 1733 { 1734 buffer.append("Certificate(subject='"); 1735 buffer.append( 1736 certificate.getSubjectX500Principal().getName(X500Principal.RFC2253)); 1737 buffer.append("', serialNumber="); 1738 buffer.append(certificate.getSerialNumber()); 1739 buffer.append(", notBefore="); 1740 StaticUtils.encodeGeneralizedTime(certificate.getNotBefore()); 1741 buffer.append(", notAfter="); 1742 StaticUtils.encodeGeneralizedTime(certificate.getNotAfter()); 1743 buffer.append(", signatureAlgorithm='"); 1744 buffer.append(certificate.getSigAlgName()); 1745 buffer.append("', signatureBytes='"); 1746 StaticUtils.toHex(certificate.getSignature(), buffer); 1747 buffer.append("', issuerSubject='"); 1748 buffer.append( 1749 certificate.getIssuerX500Principal().getName(X500Principal.RFC2253)); 1750 buffer.append("')"); 1751 } 1752}