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