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