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}