001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.util.jsse;
018
019 import java.io.IOException;
020 import java.security.GeneralSecurityException;
021 import java.security.SecureRandom;
022 import java.security.Security;
023 import java.util.List;
024
025 import javax.net.ssl.KeyManager;
026 import javax.net.ssl.SSLContext;
027 import javax.net.ssl.SSLEngine;
028 import javax.net.ssl.SSLServerSocketFactory;
029 import javax.net.ssl.SSLSocketFactory;
030 import javax.net.ssl.TrustManager;
031
032 import org.slf4j.Logger;
033 import org.slf4j.LoggerFactory;
034
035 /**
036 * Represents {@link SSLContext} configuration options used in instantiating an
037 * {@code SSLContext} instance.
038 */
039 public class SSLContextParameters extends BaseSSLContextParameters {
040
041 protected static final String DEFAULT_SECURE_SOCKET_PROTOCOL = "TLS";
042
043 private static final Logger LOG = LoggerFactory.getLogger(SSLContextParameters.class);
044
045 /**
046 * The optional key manager configuration for creating the
047 * {@link KeyManager}s used in constructing an {@link SSLContext}.
048 */
049 private KeyManagersParameters keyManagers;
050
051 /**
052 * The optional trust manager configuration for creating the
053 * {@link TrustManager}s used in constructing an {@link SSLContext}.
054 */
055 private TrustManagersParameters trustManagers;
056
057 /**
058 * The optional secure random configuration options to use for constructing
059 * the {@link SecureRandom} used in the creation of an {@link SSLContext].
060 */
061 private SecureRandomParameters secureRandom;
062
063 /**
064 * The optional configuration options to be applied purely to the client side settings
065 * of the {@link SSLContext}. Settings specified here override any duplicate settings
066 * provided at the overall level by this class. These parameters apply to
067 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext}
068 * produced from this class as well as to the {@code SSLContext} itself.
069 */
070 private SSLContextClientParameters clientParameters;
071
072 /**
073 * The optional configuration options to be applied purely to the server side settings
074 * of the {@link SSLContext}. Settings specified here override any duplicate settings
075 * provided at the overall level by this class. These parameters apply to
076 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext}
077 * produced from this class as well as to the {@code SSLContext} itself.
078 */
079 private SSLContextServerParameters serverParameters;
080
081 /**
082 * The optional provider identifier for the JSSE implementation to use when
083 * constructing an {@link SSLContext}.
084 */
085 private String provider;
086
087 /**
088 * The optional protocol for the secure sockets created by the {@link SSLContext}
089 * represented by this instance's configuration. See Appendix A in the <a
090 * href="http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA"
091 * >Java Secure Socket Extension Reference Guide</a> for information about
092 * standard protocol names.
093 */
094 private String secureSocketProtocol;
095
096 public KeyManagersParameters getKeyManagers() {
097 return keyManagers;
098 }
099
100 /**
101 * Sets the optional key manager configuration for creating the
102 * {@link KeyManager}s used in constructing an {@link SSLContext}.
103 *
104 * @param keyManagers the options or {@code null} to provide no
105 * {@code KeyManager}s
106 */
107 public void setKeyManagers(KeyManagersParameters keyManagers) {
108 this.keyManagers = keyManagers;
109 }
110
111 public TrustManagersParameters getTrustManagers() {
112 return trustManagers;
113 }
114
115 /**
116 * Sets the optional trust manager configuration for creating the
117 * {@link TrustManager}s used in constructing an {@link SSLContext}.
118 *
119 * @param trustManagers the options or {@code null} to provide no
120 * {@code TrustManager}s
121 */
122 public void setTrustManagers(TrustManagersParameters trustManagers) {
123 this.trustManagers = trustManagers;
124 }
125
126 public SecureRandomParameters getSecureRandom() {
127 return secureRandom;
128 }
129
130 /**
131 * Sets the optional secure random configuration options to use for
132 * constructing the {@link SecureRandom} used in the creation of an {@link SSLContext}.
133 *
134 * @param secureRandom the options or {@code null} to use the default
135 */
136 public void setSecureRandom(SecureRandomParameters secureRandom) {
137 this.secureRandom = secureRandom;
138 }
139
140 public SSLContextClientParameters getClientParameters() {
141 return clientParameters;
142 }
143
144 /**
145 * The optional configuration options to be applied purely to the client side settings
146 * of the {@link SSLContext}. Settings specified here override any duplicate settings
147 * provided at the overall level by this class. These parameters apply to
148 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext}
149 * produced from this class as well as to the {@code SSLContext} itself.
150 *
151 * @param clientParameters the optional additional client-side parameters
152 */
153 public void setClientParameters(SSLContextClientParameters clientParameters) {
154 this.clientParameters = clientParameters;
155 }
156
157 public SSLContextServerParameters getServerParameters() {
158 return serverParameters;
159 }
160
161 /**
162 * The optional configuration options to be applied purely to the server side settings
163 * of the {@link SSLContext}. Settings specified here override any duplicate settings
164 * provided at the overall level by this class. These parameters apply to
165 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext}
166 * produced from this class as well as to the {@code SSLContext} itself.
167 *
168 * @param serverParameters the optional additional client-side parameters
169 */
170 public void setServerParameters(SSLContextServerParameters serverParameters) {
171 this.serverParameters = serverParameters;
172 }
173
174 public String getProvider() {
175 return provider;
176 }
177
178 /**
179 * Sets the optional provider identifier to use when constructing an
180 * {@link SSLContext}.
181 *
182 * @param provider the identifier (from the list of available providers
183 * returned by {@link Security#getProviders()}) or {@code null}
184 * to use the highest priority provider implementing the secure
185 * socket protocol
186 *
187 * @see Security#getProviders(java.util.Map)
188 * @see #setSecureSocketProtocol(String)
189 */
190 public void setProvider(String provider) {
191 this.provider = provider;
192 }
193
194 public String getSecureSocketProtocol() {
195 if (this.secureSocketProtocol == null) {
196 return DEFAULT_SECURE_SOCKET_PROTOCOL;
197 }
198 return this.secureSocketProtocol;
199 }
200
201 /**
202 * Sets the optional protocol for the secure sockets created by the
203 * {@link SSLContext} represented by this instance's configuration. Defaults
204 * to TLS. See Appendix A in the <a href=
205 * "http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA"
206 * >Java Secure Socket Extension Reference Guide</a> for information about
207 * standard protocol names.
208 *
209 * @param secureSocketProtocol the name of the protocol or {@code null} to
210 * use the default (TLS)
211 */
212 public void setSecureSocketProtocol(String secureSocketProtocol) {
213 this.secureSocketProtocol = secureSocketProtocol;
214 }
215
216 ////////////////////////////////////////////
217
218 /**
219 * Creates an {@link SSLContext} based on the related configuration options
220 * of this instance. Namely, {@link #keyManagers}, {@link #trustManagers}, and
221 * {@link #secureRandom}, but also respecting the chosen provider and secure
222 * socket protocol as well.
223 *
224 * @return a newly configured instance
225 *
226 * @throws GeneralSecurityException if there is a problem in this instances
227 * configuration or that of its nested configuration options
228 * @throws IOException if there is an error reading a key/trust store
229 */
230 public SSLContext createSSLContext() throws GeneralSecurityException, IOException {
231
232 LOG.trace("Creating SSLContext from SSLContextParameters [{}].", this);
233
234 LOG.info("Available providers: {}.", Security.getProviders());
235
236 KeyManager[] keyManagers = this.keyManagers == null ? null : this.keyManagers.createKeyManagers();
237 TrustManager[] trustManagers = this.trustManagers == null ? null : this.trustManagers.createTrustManagers();
238 SecureRandom secureRandom = this.secureRandom == null ? null : this.secureRandom.createSecureRandom();
239
240 SSLContext context;
241 if (this.getProvider() == null) {
242 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol()));
243 } else {
244 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol()),
245 this.parsePropertyValue(this.getProvider()));
246 }
247
248 LOG.debug("SSLContext [{}], initialized from [{}], is using provider [{}], protocol [{}], key managers {}, trust managers {}, and secure random [{}].",
249 new Object[] {context, this, context.getProvider(), context.getProtocol(), keyManagers, trustManagers, secureRandom});
250
251 context.init(keyManagers, trustManagers, secureRandom);
252
253 this.configureSSLContext(context);
254
255 // Decorate the context.
256 context = new SSLContextDecorator(
257 new SSLContextSpiDecorator(
258 context,
259 this.getSSLEngineConfigurers(context),
260 this.getSSLSocketFactoryConfigurers(context),
261 this.getSSLServerSocketFactoryConfigurers(context)));
262
263 return context;
264 }
265
266 @Override
267 protected void configureSSLContext(SSLContext context) throws GeneralSecurityException {
268 LOG.trace("Configuring client and server side SSLContext parameters on SSLContext [{}]...", context);
269 super.configureSSLContext(context);
270
271 if (this.getClientParameters() != null) {
272 LOG.trace("Overriding client-side SSLContext parameters on SSLContext [{}] with configured client parameters.",
273 context);
274 this.getClientParameters().configureSSLContext(context);
275 }
276
277 if (this.getServerParameters() != null) {
278 LOG.trace("Overriding server-side SSLContext parameters on SSLContext [{}] with configured server parameters.",
279 context);
280 this.getServerParameters().configureSSLContext(context);
281 }
282
283 LOG.trace("Configured client and server side SSLContext parameters on SSLContext [{}].", context);
284 }
285
286 @Override
287 protected List<Configurer<SSLEngine>> getSSLEngineConfigurers(SSLContext context) {
288 LOG.trace("Collecting client and server side SSLEngine configurers on SSLContext [{}]...", context);
289 List<Configurer<SSLEngine>> configurers = super.getSSLEngineConfigurers(context);
290
291 if (this.getClientParameters() != null) {
292 LOG.trace("Augmenting SSLEngine configurers with configurers from client parameters on SSLContext [{}].",
293 context);
294 configurers.addAll(this.getClientParameters().getSSLEngineConfigurers(context));
295 }
296
297 if (this.getServerParameters() != null) {
298 LOG.trace("Augmenting SSLEngine configurers with configurers from server parameters on SSLContext [{}].",
299 context);
300 configurers.addAll(this.getServerParameters().getSSLEngineConfigurers(context));
301 }
302
303 LOG.trace("Collected client and server side SSLEngine configurers on SSLContext [{}].", context);
304
305 return configurers;
306 }
307
308 @Override
309 protected List<Configurer<SSLSocketFactory>> getSSLSocketFactoryConfigurers(SSLContext context) {
310 LOG.trace("Collecting SSLSocketFactory configurers on SSLContext [{}]...", context);
311 List<Configurer<SSLSocketFactory>> configurers = super.getSSLSocketFactoryConfigurers(context);
312
313 if (this.getClientParameters() != null) {
314 LOG.trace("Augmenting SSLSocketFactory configurers with configurers from client parameters on SSLContext [{}].",
315 context);
316 configurers.addAll(this.getClientParameters().getSSLSocketFactoryConfigurers(context));
317 }
318
319 LOG.trace("Collected SSLSocketFactory configurers on SSLContext [{}].", context);
320
321 return configurers;
322 }
323
324 @Override
325 protected List<Configurer<SSLServerSocketFactory>> getSSLServerSocketFactoryConfigurers(SSLContext context) {
326 LOG.trace("Collecting SSLServerSocketFactory configurers for SSLContext [{}]...", context);
327 List<Configurer<SSLServerSocketFactory>> configurers = super.getSSLServerSocketFactoryConfigurers(context);
328
329 if (this.getServerParameters() != null) {
330 LOG.trace("Augmenting SSLServerSocketFactory configurers with configurers from server parameters for SSLContext [{}].",
331 context);
332 configurers.addAll(this.getServerParameters().getSSLServerSocketFactoryConfigurers(context));
333 }
334
335 LOG.trace("Collected client and server side SSLServerSocketFactory configurers for SSLContext [{}].", context);
336
337 return configurers;
338 }
339
340 @Override
341 public String toString() {
342 StringBuilder builder = new StringBuilder();
343 builder.append("SSLContextParameters [keyManagers=");
344 builder.append(keyManagers);
345 builder.append(", trustManagers=");
346 builder.append(trustManagers);
347 builder.append(", secureRandom=");
348 builder.append(secureRandom);
349 builder.append(", clientParameters=");
350 builder.append(clientParameters);
351 builder.append(", serverParameters=");
352 builder.append(serverParameters);
353 builder.append(", provider=");
354 builder.append(provider);
355 builder.append(", secureSocketProtocol=");
356 builder.append(secureSocketProtocol);
357 builder.append(", getCipherSuites()=");
358 builder.append(getCipherSuites());
359 builder.append(", getCipherSuitesFilter()=");
360 builder.append(getCipherSuitesFilter());
361 builder.append(", getSecureSocketProtocols()=");
362 builder.append(getSecureSocketProtocols());
363 builder.append(", getSecureSocketProtocolsFilter()=");
364 builder.append(getSecureSocketProtocolsFilter());
365 builder.append(", getSessionTimeout()=");
366 builder.append(getSessionTimeout());
367 builder.append(", getContext()=");
368 builder.append(getCamelContext());
369 builder.append("]");
370 return builder.toString();
371 }
372 }