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