001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2018 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.HashSet;
035import java.util.Iterator;
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, and TLSv1.2 protocols will be enabled by default (if the JVM
065 * supports them), with TLSv1.2 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 default protocol string that will be used to create SSL contexts when
151   * no explicit protocol is specified.
152   */
153  private static final AtomicReference<String> DEFAULT_SSL_PROTOCOL =
154       new AtomicReference<>("TLSv1");
155
156
157
158  /**
159   * The default set of SSL protocols that will be enabled for use if available
160   * for SSL sockets created within the LDAP SDK.
161   */
162  private static final AtomicReference<Set<String>> ENABLED_SSL_PROTOCOLS =
163       new AtomicReference<>();
164
165
166
167  static
168  {
169    configureSSLDefaults();
170  }
171
172
173
174  // The set of key managers to be used.
175  private final KeyManager[] keyManagers;
176
177  // The set of trust managers to be used.
178  private final TrustManager[] trustManagers;
179
180
181
182  /**
183   * Creates a new SSLUtil instance that will not have a custom key manager or
184   * trust manager.  It will not be able to provide a certificate to the server
185   * if one is requested, and it will only trust certificates signed by a
186   * predefined set of authorities.
187   */
188  public SSLUtil()
189  {
190    keyManagers   = null;
191    trustManagers = null;
192  }
193
194
195
196  /**
197   * Creates a new SSLUtil instance that will use the provided trust manager to
198   * determine whether to trust server certificates presented to the client.
199   * It will not be able to provide a certificate to the server if one is
200   * requested.
201   *
202   * @param  trustManager  The trust manager to use to determine whether to
203   *                       trust server certificates presented to the client.
204   *                       It may be {@code null} if the default set of trust
205   *                       managers should be used.
206   */
207  public SSLUtil(final TrustManager trustManager)
208  {
209    keyManagers = null;
210
211    if (trustManager == null)
212    {
213      trustManagers = null;
214    }
215    else
216    {
217      trustManagers = new TrustManager[] { trustManager };
218    }
219  }
220
221
222
223  /**
224   * Creates a new SSLUtil instance that will use the provided trust managers
225   * to determine whether to trust server certificates presented to the client.
226   * It will not be able to provide a certificate to the server if one is
227   * requested.
228   *
229   * @param  trustManagers  The set of trust managers to use to determine
230   *                        whether to trust server certificates presented to
231   *                        the client.  It may be {@code null} or empty if the
232   *                        default set of trust managers should be used.
233   */
234  public SSLUtil(final TrustManager[] trustManagers)
235  {
236    keyManagers = null;
237
238    if ((trustManagers == null) || (trustManagers.length == 0))
239    {
240      this.trustManagers = null;
241    }
242    else
243    {
244      this.trustManagers = trustManagers;
245    }
246  }
247
248
249
250  /**
251   * Creates a new SSLUtil instance that will use the provided key manager to
252   * obtain certificates to present to the server, and the provided trust
253   * manager to determine whether to trust server certificates presented to the
254   * client.
255   *
256   * @param  keyManager    The key manager to use to obtain certificates to
257   *                       present to the server if requested.  It may be
258   *                       {@code null} if no client certificates will be
259   *                       required or should be provided.
260   * @param  trustManager  The trust manager to use to determine whether to
261   *                       trust server certificates presented to the client.
262   *                       It may be {@code null} if the default set of trust
263   *                       managers should be used.
264   */
265  public SSLUtil(final KeyManager keyManager, final TrustManager trustManager)
266  {
267    if (keyManager == null)
268    {
269      keyManagers = null;
270    }
271    else
272    {
273      keyManagers = new KeyManager[] { keyManager };
274    }
275
276    if (trustManager == null)
277    {
278      trustManagers = null;
279    }
280    else
281    {
282      trustManagers = new TrustManager[] { trustManager };
283    }
284  }
285
286
287
288  /**
289   * Creates a new SSLUtil instance that will use the provided key managers to
290   * obtain certificates to present to the server, and the provided trust
291   * managers to determine whether to trust server certificates presented to the
292   * client.
293   *
294   * @param  keyManagers    The set of key managers to use to obtain
295   *                        certificates to present to the server if requested.
296   *                        It may be {@code null} or empty if no client
297   *                        certificates will be required or should be provided.
298   * @param  trustManagers  The set of trust managers to use to determine
299   *                        whether to trust server certificates presented to
300   *                        the client.  It may be {@code null} or empty if the
301   *                        default set of trust managers should be used.
302   */
303  public SSLUtil(final KeyManager[] keyManagers,
304                 final TrustManager[] trustManagers)
305  {
306    if ((keyManagers == null) || (keyManagers.length == 0))
307    {
308      this.keyManagers = null;
309    }
310    else
311    {
312      this.keyManagers = keyManagers;
313    }
314
315    if ((trustManagers == null) || (trustManagers.length == 0))
316    {
317      this.trustManagers = null;
318    }
319    else
320    {
321      this.trustManagers = trustManagers;
322    }
323  }
324
325
326
327  /**
328   * Retrieves the set of key managers configured for use by this class, if any.
329   *
330   * @return  The set of key managers configured for use by this class, or
331   *          {@code null} if none were provided.
332   */
333  public KeyManager[] getKeyManagers()
334  {
335    return keyManagers;
336  }
337
338
339
340  /**
341   * Retrieves the set of trust managers configured for use by this class, if
342   * any.
343   *
344   * @return  The set of trust managers configured for use by this class, or
345   *          {@code null} if none were provided.
346   */
347  public TrustManager[] getTrustManagers()
348  {
349    return trustManagers;
350  }
351
352
353
354  /**
355   * Creates an initialized SSL context created with the configured key and
356   * trust managers.  It will use the protocol returned by the
357   * {@link #getDefaultSSLProtocol} method and the JVM-default provider.
358   *
359   * @return  The created SSL context.
360   *
361   * @throws  GeneralSecurityException  If a problem occurs while creating or
362   *                                    initializing the SSL context.
363   */
364  public SSLContext createSSLContext()
365         throws GeneralSecurityException
366  {
367    return createSSLContext(DEFAULT_SSL_PROTOCOL.get());
368  }
369
370
371
372  /**
373   * Creates an initialized SSL context created with the configured key and
374   * trust managers.  It will use the default provider.
375   *
376   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
377   *                   Extension (JSSE) Reference Guide provides a list of the
378   *                   supported protocols, but commonly used values are
379   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
380   *                   {@code null}.
381   *
382   *
383   * @return  The created SSL context.
384   *
385   * @throws  GeneralSecurityException  If a problem occurs while creating or
386   *                                    initializing the SSL context.
387   */
388  public SSLContext createSSLContext(final String protocol)
389         throws GeneralSecurityException
390  {
391    Validator.ensureNotNull(protocol);
392
393    final SSLContext sslContext = SSLContext.getInstance(protocol);
394    sslContext.init(keyManagers, trustManagers, null);
395    return sslContext;
396  }
397
398
399
400  /**
401   * Creates an initialized SSL context created with the configured key and
402   * trust managers.
403   *
404   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
405   *                   Extension (JSSE) Reference Guide provides a list of the
406   *                   supported protocols, but commonly used values are
407   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
408   *                   {@code null}.
409   * @param  provider  The name of the provider to use for cryptographic
410   *                   operations.  It must not be {@code null}.
411   *
412   * @return  The created SSL context.
413   *
414   * @throws  GeneralSecurityException  If a problem occurs while creating or
415   *                                    initializing the SSL context.
416   */
417  public SSLContext createSSLContext(final String protocol,
418                                     final String provider)
419         throws GeneralSecurityException
420  {
421    Validator.ensureNotNull(protocol, provider);
422
423    final SSLContext sslContext = SSLContext.getInstance(protocol, provider);
424    sslContext.init(keyManagers, trustManagers, null);
425    return sslContext;
426  }
427
428
429
430  /**
431   * Creates an SSL socket factory using the configured key and trust manager
432   * providers.  It will use the protocol returned by the
433   * {@link #getDefaultSSLProtocol} method and the JVM-default provider.
434   *
435   * @return  The created SSL socket factory.
436   *
437   * @throws  GeneralSecurityException  If a problem occurs while creating or
438   *                                    initializing the SSL socket factory.
439   */
440  public SSLSocketFactory createSSLSocketFactory()
441         throws GeneralSecurityException
442  {
443    return new SetEnabledProtocolsSSLSocketFactory(
444         createSSLContext().getSocketFactory(),
445         ENABLED_SSL_PROTOCOLS.get());
446  }
447
448
449
450  /**
451   * Creates an SSL socket factory with the configured key and trust managers.
452   * It will use the default provider.
453   *
454   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
455   *                   Extension (JSSE) Reference Guide provides a list of the
456   *                   supported protocols, but commonly used values are
457   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
458   *                   {@code null}.
459   *
460   * @return  The created SSL socket factory.
461   *
462   * @throws  GeneralSecurityException  If a problem occurs while creating or
463   *                                    initializing the SSL socket factory.
464   */
465  public SSLSocketFactory createSSLSocketFactory(final String protocol)
466         throws GeneralSecurityException
467  {
468    return new SetEnabledProtocolsSSLSocketFactory(
469         createSSLContext(protocol).getSocketFactory(), protocol);
470  }
471
472
473
474  /**
475   * Creates an SSL socket factory with the configured key and trust managers.
476   *
477   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
478   *                   Extension (JSSE) Reference Guide provides a list of the
479   *                   supported protocols, but commonly used values are
480   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
481   *                   {@code null}.
482   * @param  provider  The name of the provider to use for cryptographic
483   *                   operations.  It must not be {@code null}.
484   *
485   * @return  The created SSL socket factory.
486   *
487   * @throws  GeneralSecurityException  If a problem occurs while creating or
488   *                                    initializing the SSL socket factory.
489   */
490  public SSLSocketFactory createSSLSocketFactory(final String protocol,
491                                                 final String provider)
492         throws GeneralSecurityException
493  {
494    return createSSLContext(protocol, provider).getSocketFactory();
495  }
496
497
498
499  /**
500   * Creates an SSL server socket factory using the configured key and trust
501   * manager providers.  It will use the protocol returned by the
502   * {@link #getDefaultSSLProtocol} method and the JVM-default provider.
503   *
504   * @return  The created SSL server socket factory.
505   *
506   * @throws  GeneralSecurityException  If a problem occurs while creating or
507   *                                    initializing the SSL server socket
508   *                                    factory.
509   */
510  public SSLServerSocketFactory createSSLServerSocketFactory()
511         throws GeneralSecurityException
512  {
513    return new SetEnabledProtocolsSSLServerSocketFactory(
514         createSSLContext().getServerSocketFactory(),
515         ENABLED_SSL_PROTOCOLS.get());
516  }
517
518
519
520  /**
521   * Creates an SSL server socket factory using the configured key and trust
522   * manager providers.  It will use the JVM-default provider.
523   *
524   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
525   *                   Extension (JSSE) Reference Guide provides a list of the
526   *                   supported protocols, but commonly used values are
527   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
528   *                   {@code null}.
529   *
530   * @return  The created SSL server socket factory.
531   *
532   * @throws  GeneralSecurityException  If a problem occurs while creating or
533   *                                    initializing the SSL server socket
534   *                                    factory.
535   */
536  public SSLServerSocketFactory createSSLServerSocketFactory(
537                                     final String protocol)
538         throws GeneralSecurityException
539  {
540    return new SetEnabledProtocolsSSLServerSocketFactory(
541         createSSLContext(protocol).getServerSocketFactory(), protocol);
542  }
543
544
545
546  /**
547   * Creates an SSL server socket factory using the configured key and trust
548   * manager providers.
549   *
550   * @param  protocol  The SSL protocol to use.  The Java Secure Socket
551   *                   Extension (JSSE) Reference Guide provides a list of the
552   *                   supported protocols, but commonly used values are
553   *                   "TLSv1.2", "TLSv1.1", and "TLSv1".  This must not be
554   *                   {@code null}.
555   * @param  provider  The name of the provider to use for cryptographic
556   *                   operations.  It must not be {@code null}.
557   *
558   * @return  The created SSL server socket factory.
559   *
560   * @throws  GeneralSecurityException  If a problem occurs while creating or
561   *                                    initializing the SSL server socket
562   *                                    factory.
563   */
564  public SSLServerSocketFactory createSSLServerSocketFactory(
565                                     final String protocol,
566                                     final String provider)
567         throws GeneralSecurityException
568  {
569    return createSSLContext(protocol, provider).getServerSocketFactory();
570  }
571
572
573
574  /**
575   * Retrieves the SSL protocol string that will be used by calls to
576   * {@link #createSSLContext()} that do not explicitly specify which protocol
577   * to use.
578   *
579   * @return  The SSL protocol string that will be used by calls to create an
580   *          SSL context that do not explicitly specify which protocol to use.
581   */
582  public static String getDefaultSSLProtocol()
583  {
584    return DEFAULT_SSL_PROTOCOL.get();
585  }
586
587
588
589  /**
590   * Specifies the SSL protocol string that will be used by calls to
591   * {@link #createSSLContext()} that do not explicitly specify which protocol
592   * to use.
593   *
594   * @param  defaultSSLProtocol  The SSL protocol string that will be used by
595   *                             calls to create an SSL context that do not
596   *                             explicitly specify which protocol to use.  It
597   *                             must not be {@code null}.
598   */
599  public static void setDefaultSSLProtocol(final String defaultSSLProtocol)
600  {
601    Validator.ensureNotNull(defaultSSLProtocol);
602
603    DEFAULT_SSL_PROTOCOL.set(defaultSSLProtocol);
604  }
605
606
607
608  /**
609   * Retrieves the set of SSL protocols that will be enabled for use, if
610   * available, for SSL sockets created within the LDAP SDK.
611   *
612   * @return  The set of SSL protocols that will be enabled for use, if
613   *          available, for SSL sockets created within the LDAP SDK.
614   */
615  public static Set<String> getEnabledSSLProtocols()
616  {
617    return ENABLED_SSL_PROTOCOLS.get();
618  }
619
620
621
622  /**
623   * Specifies the set of SSL protocols that will be enabled for use for SSL
624   * sockets created within the LDAP SDK.  When creating an SSL socket, the
625   * {@code SSLSocket.getSupportedProtocols} method will be used to determine
626   * which protocols are supported for that socket, and then the
627   * {@code SSLSocket.setEnabledProtocols} method will be used to enable those
628   * protocols which are listed as both supported by the socket and included in
629   * this set.  If the provided set is {@code null} or empty, then the default
630   * set of enabled protocols will be used.
631   *
632   * @param  enabledSSLProtocols  The set of SSL protocols that will be enabled
633   *                              for use for SSL sockets created within the
634   *                              LDAP SDK.  It may be {@code null} or empty to
635   *                              indicate that the JDK-default set of enabled
636   *                              protocols should be used for the socket.
637   */
638  public static void setEnabledSSLProtocols(
639                          final Collection<String> enabledSSLProtocols)
640  {
641    if (enabledSSLProtocols == null)
642    {
643      ENABLED_SSL_PROTOCOLS.set(Collections.<String>emptySet());
644    }
645    else
646    {
647      ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet(
648           new HashSet<>(enabledSSLProtocols)));
649    }
650  }
651
652
653
654  /**
655   * Updates the provided socket to apply the appropriate set of enabled SSL
656   * protocols.  This will only have any effect for sockets that are instances
657   * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of
658   * {@code java.net.Socket}.  This should be called before attempting any
659   * communication over the socket, as
660   *
661   * @param  socket  The socket on which to apply the configured set of enabled
662   *                 SSL protocols.
663   *
664   * @throws  LDAPException  If {@link #getEnabledSSLProtocols} returns a
665   *                         non-empty set but none of the values in that set
666   *                         are supported by the socket.
667   */
668  public static void applyEnabledSSLProtocols(final Socket socket)
669         throws LDAPException
670  {
671    try
672    {
673      applyEnabledSSLProtocols(socket, ENABLED_SSL_PROTOCOLS.get());
674    }
675    catch (final IOException ioe)
676    {
677      Debug.debugException(ioe);
678      throw new LDAPException(ResultCode.CONNECT_ERROR, ioe.getMessage(), ioe);
679    }
680  }
681
682
683
684  /**
685   * Updates the provided socket to apply the appropriate set of enabled SSL
686   * protocols.  This will only have any effect for sockets that are instances
687   * of {@code javax.net.ssl.SSLSocket}, but it is safe to call for any kind of
688   * {@code java.net.Socket}.  This should be called before attempting any
689   * communication over the socket.
690   *
691   * @param  socket     The socket on which to apply the configured set of
692   *                    enabled SSL protocols.
693   * @param  protocols  The set of protocols that should be enabled for the
694   *                    socket, if available.
695   *
696   * @throws  IOException  If a problem is encountered while applying the
697   *                       desired set of enabled protocols to the given socket.
698   */
699  static void applyEnabledSSLProtocols(final Socket socket,
700                                       final Set<String> protocols)
701         throws IOException
702  {
703    if ((socket == null) || (!(socket instanceof SSLSocket)) ||
704        protocols.isEmpty())
705    {
706      return;
707    }
708
709    final SSLSocket sslSocket = (SSLSocket) socket;
710    final String[] protocolsToEnable =
711         getSSLProtocolsToEnable(protocols, sslSocket.getSupportedProtocols());
712
713    try
714    {
715      sslSocket.setEnabledProtocols(protocolsToEnable);
716    }
717    catch (final Exception e)
718    {
719      Debug.debugException(e);
720    }
721  }
722
723
724
725  /**
726   * Updates the provided server socket to apply the appropriate set of enabled
727   * SSL protocols.  This will only have any effect for server sockets that are
728   * instances of {@code javax.net.ssl.SSLServerSocket}, but it is safe to call
729   * for any kind of {@code java.net.ServerSocket}.  This should be called
730   * before attempting any communication over the socket.
731   *
732   * @param  serverSocket  The server socket on which to apply the configured
733   *                       set of enabled SSL protocols.
734   * @param  protocols     The set of protocols that should be enabled for the
735   *                       server socket, if available.
736   *
737   * @throws  IOException  If a problem is encountered while applying the
738   *                       desired set of enabled protocols to the given server
739   *                       socket.
740   */
741  static void applyEnabledSSLProtocols(final ServerSocket serverSocket,
742                                       final Set<String> protocols)
743         throws IOException
744  {
745    if ((serverSocket == null) ||
746        (!(serverSocket instanceof SSLServerSocket)) ||
747        protocols.isEmpty())
748    {
749      return;
750    }
751
752    final SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocket;
753    final String[] protocolsToEnable = getSSLProtocolsToEnable(protocols,
754         sslServerSocket.getSupportedProtocols());
755
756    try
757    {
758      sslServerSocket.setEnabledProtocols(protocolsToEnable);
759    }
760    catch (final Exception e)
761    {
762      Debug.debugException(e);
763    }
764  }
765
766
767
768  /**
769   * Retrieves the names of the SSL protocols that should be enabled given the
770   * provided information.
771   *
772   * @param  desiredProtocols    The set of protocols that are desired to be
773   *                             enabled.
774   * @param  supportedProtocols  The set of all protocols that are supported.
775   *
776   * @return  The names of the SSL protocols that should be enabled.
777   *
778   * @throws  IOException  If none of the desired values are included in the
779   *                       supported set.
780   */
781  private static String[] getSSLProtocolsToEnable(
782                               final Set<String> desiredProtocols,
783                               final String[] supportedProtocols)
784         throws IOException
785  {
786    final Set<String> lowerProtocols = new HashSet<>(desiredProtocols.size());
787    for (final String s : desiredProtocols)
788    {
789      lowerProtocols.add(StaticUtils.toLowerCase(s));
790    }
791
792    final ArrayList<String> enabledList =
793         new ArrayList<>(supportedProtocols.length);
794    for (final String supportedProtocol : supportedProtocols)
795    {
796      if (lowerProtocols.contains(StaticUtils.toLowerCase(supportedProtocol)))
797      {
798        enabledList.add(supportedProtocol);
799      }
800    }
801
802    if (enabledList.isEmpty())
803    {
804      final StringBuilder enabledBuffer = new StringBuilder();
805      final Iterator<String> enabledIterator = desiredProtocols.iterator();
806      while (enabledIterator.hasNext())
807      {
808        enabledBuffer.append('\'');
809        enabledBuffer.append(enabledIterator.next());
810        enabledBuffer.append('\'');
811
812        if (enabledIterator.hasNext())
813        {
814          enabledBuffer.append(", ");
815        }
816      }
817
818      final StringBuilder supportedBuffer = new StringBuilder();
819      for (int i=0; i < supportedProtocols.length; i++)
820      {
821        if (i > 0)
822        {
823          supportedBuffer.append(", ");
824        }
825
826        supportedBuffer.append('\'');
827        supportedBuffer.append(supportedProtocols[i]);
828        supportedBuffer.append('\'');
829      }
830
831      throw new IOException(
832           ERR_NO_ENABLED_SSL_PROTOCOLS_AVAILABLE_FOR_SOCKET.get(
833                enabledBuffer.toString(), supportedBuffer.toString(),
834                PROPERTY_ENABLED_SSL_PROTOCOLS,
835                SSLUtil.class.getName() + ".setEnabledSSLProtocols"));
836    }
837    else
838    {
839      return enabledList.toArray(StaticUtils.NO_STRINGS);
840    }
841  }
842
843
844
845  /**
846   * Configures SSL default settings for the LDAP SDK.  This method is
847   * non-private for purposes of easier test coverage.
848   */
849  static void configureSSLDefaults()
850  {
851    // See if there is a system property that specifies what the default SSL
852    // protocol should be.  If not, then try to dynamically determine it.
853    final String defaultPropValue =
854         System.getProperty(PROPERTY_DEFAULT_SSL_PROTOCOL);
855    if ((defaultPropValue != null) && (! defaultPropValue.isEmpty()))
856    {
857      DEFAULT_SSL_PROTOCOL.set(defaultPropValue);
858    }
859    else
860    {
861      // We should be able to discover the SSL protocol that offers the best mix
862      // of security and compatibility.  If we see that TLSv1.1 and/or TLSv1.2
863      // are available, then we'll add those to the set of default enabled
864      // protocols.
865      try
866      {
867        final SSLContext defaultContext = SSLContext.getDefault();
868        final String[] supportedProtocols =
869             defaultContext.getSupportedSSLParameters().getProtocols();
870
871        final HashSet<String> protocolMap =
872             new HashSet<>(Arrays.asList(supportedProtocols));
873        if (protocolMap.contains("TLSv1.2"))
874        {
875          DEFAULT_SSL_PROTOCOL.set("TLSv1.2");
876        }
877        else if (protocolMap.contains("TLSv1.1"))
878        {
879          DEFAULT_SSL_PROTOCOL.set("TLSv1.1");
880        }
881        else if (protocolMap.contains("TLSv1"))
882        {
883          DEFAULT_SSL_PROTOCOL.set("TLSv1");
884        }
885      }
886      catch (final Exception e)
887      {
888        Debug.debugException(e);
889      }
890    }
891
892    // A set to use for the default set of enabled protocols.  Unless otherwise
893    // specified via system property, we'll always enable TLSv1.  We may enable
894    // other protocols based on the default protocol.  The default set of
895    // enabled protocols will not include SSLv3 even if the JVM might otherwise
896    // include it as a default enabled protocol because of known security
897    // problems with SSLv3.
898    final HashSet<String> enabledProtocols = new HashSet<>(10);
899    enabledProtocols.add("TLSv1");
900    if (DEFAULT_SSL_PROTOCOL.get().equals("TLSv1.2"))
901    {
902      enabledProtocols.add("TLSv1.1");
903      enabledProtocols.add("TLSv1.2");
904    }
905    else if (DEFAULT_SSL_PROTOCOL.get().equals("TLSv1.1"))
906    {
907      enabledProtocols.add("TLSv1.1");
908    }
909
910    // If there is a system property that specifies which enabled SSL protocols
911    // to use, then it will override the defaults.
912    final String enabledPropValue =
913         System.getProperty(PROPERTY_ENABLED_SSL_PROTOCOLS);
914    if ((enabledPropValue != null) && (! enabledPropValue.isEmpty()))
915    {
916      enabledProtocols.clear();
917
918      final StringTokenizer tokenizer = new StringTokenizer(enabledPropValue,
919           ", ", false);
920      while (tokenizer.hasMoreTokens())
921      {
922        final String token = tokenizer.nextToken();
923        if (! token.isEmpty())
924        {
925          enabledProtocols.add(token);
926        }
927      }
928    }
929
930    ENABLED_SSL_PROTOCOLS.set(Collections.unmodifiableSet(enabledProtocols));
931  }
932
933
934
935  /**
936   * Creates a string representation of the provided certificate.
937   *
938   * @param  certificate  The certificate for which to generate the string
939   *                      representation.  It must not be {@code null}.
940   *
941   * @return  A string representation of the provided certificate.
942   */
943  public static String certificateToString(final X509Certificate certificate)
944  {
945    final StringBuilder buffer = new StringBuilder();
946    certificateToString(certificate, buffer);
947    return buffer.toString();
948  }
949
950
951
952  /**
953   * Appends a string representation of the provided certificate to the given
954   * buffer.
955   *
956   * @param  certificate  The certificate for which to generate the string
957   *                      representation.  It must not be {@code null}.
958   * @param  buffer       The buffer to which to append the string
959   *                      representation.
960   */
961  public static void certificateToString(final X509Certificate certificate,
962                                         final StringBuilder buffer)
963  {
964    buffer.append("Certificate(subject='");
965    buffer.append(
966         certificate.getSubjectX500Principal().getName(X500Principal.RFC2253));
967    buffer.append("', serialNumber=");
968    buffer.append(certificate.getSerialNumber());
969    buffer.append(", notBefore=");
970    StaticUtils.encodeGeneralizedTime(certificate.getNotBefore());
971    buffer.append(", notAfter=");
972    StaticUtils.encodeGeneralizedTime(certificate.getNotAfter());
973    buffer.append(", signatureAlgorithm='");
974    buffer.append(certificate.getSigAlgName());
975    buffer.append("', signatureBytes='");
976    StaticUtils.toHex(certificate.getSignature(), buffer);
977    buffer.append("', issuerSubject='");
978    buffer.append(
979         certificate.getIssuerX500Principal().getName(X500Principal.RFC2253));
980    buffer.append("')");
981  }
982}