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