001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2010 Sun Microsystems, Inc. 015 * Portions Copyright 2016 ForgeRock AS. 016 * Portions Copyright 2021 Wren Security. 017 */ 018package org.forgerock.opendj.ldap; 019 020import java.io.IOException; 021import java.security.GeneralSecurityException; 022import java.security.Provider; 023import java.security.SecureRandom; 024 025import javax.net.ssl.KeyManager; 026import javax.net.ssl.SSLContext; 027import javax.net.ssl.TrustManager; 028 029/** 030 * An SSL context builder provides an interface for incrementally constructing 031 * {@link SSLContext} instances for use when securing connections with SSL or 032 * the StartTLS extended operation. The {@link #getSSLContext()} should be 033 * called in order to obtain the {@code SSLContext}. 034 * <p> 035 * For example, use the SSL context builder when setting up LDAP options needed 036 * to use StartTLS. {@link org.forgerock.opendj.ldap.TrustManagers 037 * TrustManagers} has methods you can use to set the trust manager for the SSL 038 * context builder. 039 * 040 * <pre> 041 * LDAPOptions options = new LDAPOptions(); 042 * SSLContext sslContext = 043 * new SSLContextBuilder().setTrustManager(...).getSSLContext(); 044 * options.setSSLContext(sslContext); 045 * options.setUseStartTLS(true); 046 * 047 * String host = ...; 048 * int port = ...; 049 * LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port, options); 050 * Connection connection = factory.getConnection(); 051 * // Connection uses StartTLS... 052 * </pre> 053 */ 054public final class SSLContextBuilder { 055 /** SSL protocol: supports some version of SSL; may support other versions. */ 056 public static final String PROTOCOL_SSL = "SSL"; 057 /** SSL protocol: supports SSL version 2 or higher; may support other versions. */ 058 public static final String PROTOCOL_SSL2 = "SSLv2"; 059 /** SSL protocol: supports SSL version 3; may support other versions. */ 060 public static final String PROTOCOL_SSL3 = "SSLv3"; 061 /** SSL protocol: supports some version of TLS; may support other versions. */ 062 public static final String PROTOCOL_TLS = "TLS"; 063 /** SSL protocol: supports RFC 2246: TLS version 1.0 ; may support other versions. */ 064 public static final String PROTOCOL_TLS1 = "TLSv1"; 065 /** SSL protocol: supports RFC 4346: TLS version 1.1 ; may support other versions. */ 066 public static final String PROTOCOL_TLS1_1 = "TLSv1.1"; 067 /** SSL protocol: supports RFC 5246: TLS version 1.2 ; may support other versions. */ 068 public static final String PROTOCOL_TLS1_2 = "TLSv1.2"; 069 070 private TrustManager trustManager; 071 private KeyManager keyManager; 072 private String protocol = PROTOCOL_TLS1_2; 073 private SecureRandom random; 074 075 /** These are mutually exclusive. */ 076 private Provider provider; 077 private String providerName; 078 079 /** Creates a new SSL context builder using default parameters. */ 080 public SSLContextBuilder() { 081 try { 082 keyManager = KeyManagers.useJvmDefaultKeyStore(); 083 } catch (GeneralSecurityException | IOException ex) { 084 keyManager = null; 085 } 086 } 087 088 /** 089 * Creates a {@code SSLContext} using the parameters of this SSL context 090 * builder. 091 * 092 * @return A {@code SSLContext} using the parameters of this SSL context 093 * builder. 094 * @throws GeneralSecurityException 095 * If the SSL context could not be created, perhaps due to 096 * missing algorithms. 097 */ 098 public SSLContext getSSLContext() throws GeneralSecurityException { 099 SSLContext sslContext = getInstance(); 100 sslContext.init(getKeyManagers(), getTrustManagers(), random); 101 return sslContext; 102 } 103 104 private SSLContext getInstance() throws GeneralSecurityException { 105 if (provider != null) { 106 return SSLContext.getInstance(protocol, provider); 107 } else if (providerName != null) { 108 return SSLContext.getInstance(protocol, providerName); 109 } else { 110 return SSLContext.getInstance(protocol); 111 } 112 } 113 114 private KeyManager[] getKeyManagers() { 115 return keyManager != null ? new KeyManager[] { keyManager } : null; 116 } 117 118 private TrustManager[] getTrustManagers() { 119 return trustManager != null ? new TrustManager[] { trustManager } : null; 120 } 121 122 /** 123 * Sets the key manager which the SSL context should use. By default, the JVM's key manager is used. 124 * 125 * @param keyManager 126 * The key manager which the SSL context should use, which may be {@code null} indicating that no 127 * certificates will be used. 128 * @return This SSL context builder. 129 */ 130 public SSLContextBuilder setKeyManager(final KeyManager keyManager) { 131 this.keyManager = keyManager; 132 return this; 133 } 134 135 /** 136 * Sets the protocol which the SSL context should use. By default, TLSv1.2 137 * will be used. 138 * 139 * @param protocol 140 * The protocol which the SSL context should use, which may be 141 * {@code null} indicating that TLSv1.2 will be used. 142 * @return This SSL context builder. 143 */ 144 public SSLContextBuilder setProtocol(final String protocol) { 145 this.protocol = protocol != null ? protocol : PROTOCOL_TLS1_2; 146 return this; 147 } 148 149 /** 150 * Sets the provider which the SSL context should use. By default, the 151 * default provider associated with this JVM will be used. 152 * 153 * @param provider 154 * The provider which the SSL context should use, which may be 155 * {@code null} indicating that the default provider associated 156 * with this JVM will be used. 157 * @return This SSL context builder. 158 */ 159 public SSLContextBuilder setProvider(final Provider provider) { 160 this.provider = provider; 161 this.providerName = null; 162 return this; 163 } 164 165 /** 166 * Sets the provider which the SSL context should use. By default, the 167 * default provider associated with this JVM will be used. 168 * 169 * @param providerName 170 * The name of the provider which the SSL context should use, 171 * which may be {@code null} indicating that the default provider 172 * associated with this JVM will be used. 173 * @return This SSL context builder. 174 */ 175 public SSLContextBuilder setProvider(final String providerName) { 176 this.provider = null; 177 this.providerName = providerName; 178 return this; 179 } 180 181 /** 182 * Sets the secure random number generator which the SSL context should use. 183 * By default, the default secure random number generator associated with 184 * this JVM will be used. 185 * 186 * @param random 187 * The secure random number generator which the SSL context 188 * should use, which may be {@code null} indicating that the 189 * default secure random number generator associated with this 190 * JVM will be used. 191 * @return This SSL context builder. 192 */ 193 public SSLContextBuilder setSecureRandom(final SecureRandom random) { 194 this.random = random; 195 return this; 196 } 197 198 /** 199 * Sets the trust manager which the SSL context should use. By default, no 200 * trust manager is specified indicating that only certificates signed by 201 * the authorities associated with this JVM will be accepted. 202 * 203 * @param trustManager 204 * The trust manager which the SSL context should use, which may 205 * be {@code null} indicating that only certificates signed by 206 * the authorities associated with this JVM will be accepted. 207 * @return This SSL context builder. 208 */ 209 public SSLContextBuilder setTrustManager(final TrustManager trustManager) { 210 this.trustManager = trustManager; 211 return this; 212 } 213}