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 */ 017package org.apache.camel.util.jsse; 018 019import java.io.IOException; 020import java.security.GeneralSecurityException; 021import java.security.SecureRandom; 022import java.security.Security; 023import java.util.List; 024 025import javax.net.ssl.KeyManager; 026import javax.net.ssl.SSLContext; 027import javax.net.ssl.SSLEngine; 028import javax.net.ssl.SSLServerSocketFactory; 029import javax.net.ssl.SSLSocketFactory; 030import javax.net.ssl.TrustManager; 031import javax.net.ssl.X509KeyManager; 032 033import org.apache.camel.CamelContext; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Represents {@link SSLContext} configuration options used in instantiating an 039 * {@code SSLContext} instance. 040 */ 041public class SSLContextParameters extends BaseSSLContextParameters { 042 043 protected static final String DEFAULT_SECURE_SOCKET_PROTOCOL = "TLS"; 044 045 private static final Logger LOG = LoggerFactory.getLogger(SSLContextParameters.class); 046 047 /** 048 * The optional key manager configuration for creating the 049 * {@link KeyManager}s used in constructing an {@link SSLContext}. 050 */ 051 private KeyManagersParameters keyManagers; 052 053 /** 054 * The optional trust manager configuration for creating the 055 * {@link TrustManager}s used in constructing an {@link SSLContext}. 056 */ 057 private TrustManagersParameters trustManagers; 058 059 /** 060 * The optional secure random configuration options to use for constructing 061 * the {@link SecureRandom} used in the creation of an {@link SSLContext]. 062 */ 063 private SecureRandomParameters secureRandom; 064 065 /** 066 * The optional configuration options to be applied purely to the client side settings 067 * of the {@link SSLContext}. Settings specified here override any duplicate settings 068 * provided at the overall level by this class. These parameters apply to 069 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext} 070 * produced from this class as well as to the {@code SSLContext} itself. 071 */ 072 private SSLContextClientParameters clientParameters; 073 074 /** 075 * The optional configuration options to be applied purely to the server side settings 076 * of the {@link SSLContext}. Settings specified here override any duplicate settings 077 * provided at the overall level by this class. These parameters apply to 078 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext} 079 * produced from this class as well as to the {@code SSLContext} itself. 080 */ 081 private SSLContextServerParameters serverParameters; 082 083 /** 084 * The optional provider identifier for the JSSE implementation to use when 085 * constructing an {@link SSLContext}. 086 */ 087 private String provider; 088 089 /** 090 * The optional protocol for the secure sockets created by the {@link SSLContext} 091 * represented by this instance's configuration. See Appendix A in the <a 092 * href="http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA" 093 * >Java Secure Socket Extension Reference Guide</a> for information about 094 * standard protocol names. 095 */ 096 private String secureSocketProtocol; 097 098 /** 099 * An optional certificate alias to use. This is useful when the keystore has multiple 100 * certificates. 101 */ 102 private String certAlias; 103 104 public KeyManagersParameters getKeyManagers() { 105 return keyManagers; 106 } 107 108 /** 109 * Sets the optional key manager configuration for creating the 110 * {@link KeyManager}s used in constructing an {@link SSLContext}. 111 * 112 * @param keyManagers the options or {@code null} to provide no 113 * {@code KeyManager}s 114 */ 115 public void setKeyManagers(KeyManagersParameters keyManagers) { 116 this.keyManagers = keyManagers; 117 } 118 119 public TrustManagersParameters getTrustManagers() { 120 return trustManagers; 121 } 122 123 /** 124 * Sets the optional trust manager configuration for creating the 125 * {@link TrustManager}s used in constructing an {@link SSLContext}. 126 * 127 * @param trustManagers the options or {@code null} to provide no 128 * {@code TrustManager}s 129 */ 130 public void setTrustManagers(TrustManagersParameters trustManagers) { 131 this.trustManagers = trustManagers; 132 } 133 134 public SecureRandomParameters getSecureRandom() { 135 return secureRandom; 136 } 137 138 /** 139 * Sets the optional secure random configuration options to use for 140 * constructing the {@link SecureRandom} used in the creation of an {@link SSLContext}. 141 * 142 * @param secureRandom the options or {@code null} to use the default 143 */ 144 public void setSecureRandom(SecureRandomParameters secureRandom) { 145 this.secureRandom = secureRandom; 146 } 147 148 public SSLContextClientParameters getClientParameters() { 149 return clientParameters; 150 } 151 152 /** 153 * The optional configuration options to be applied purely to the client side settings 154 * of the {@link SSLContext}. Settings specified here override any duplicate settings 155 * provided at the overall level by this class. These parameters apply to 156 * {@link SSLSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext} 157 * produced from this class as well as to the {@code SSLContext} itself. 158 * 159 * @param clientParameters the optional additional client-side parameters 160 */ 161 public void setClientParameters(SSLContextClientParameters clientParameters) { 162 this.clientParameters = clientParameters; 163 } 164 165 public SSLContextServerParameters getServerParameters() { 166 return serverParameters; 167 } 168 169 /** 170 * The optional configuration options to be applied purely to the server side settings 171 * of the {@link SSLContext}. Settings specified here override any duplicate settings 172 * provided at the overall level by this class. These parameters apply to 173 * {@link SSLServerSocketFactory}s and {@link SSLEngine}s produced by the the {@code SSLContext} 174 * produced from this class as well as to the {@code SSLContext} itself. 175 * 176 * @param serverParameters the optional additional client-side parameters 177 */ 178 public void setServerParameters(SSLContextServerParameters serverParameters) { 179 this.serverParameters = serverParameters; 180 } 181 182 public String getProvider() { 183 return provider; 184 } 185 186 /** 187 * Sets the optional provider identifier to use when constructing an 188 * {@link SSLContext}. 189 * 190 * @param provider the identifier (from the list of available providers 191 * returned by {@link Security#getProviders()}) or {@code null} 192 * to use the highest priority provider implementing the secure 193 * socket protocol 194 * 195 * @see Security#getProviders(java.util.Map) 196 * @see #setSecureSocketProtocol(String) 197 */ 198 public void setProvider(String provider) { 199 this.provider = provider; 200 } 201 202 public String getSecureSocketProtocol() { 203 if (this.secureSocketProtocol == null) { 204 return DEFAULT_SECURE_SOCKET_PROTOCOL; 205 } 206 return this.secureSocketProtocol; 207 } 208 209 /** 210 * Sets the optional protocol for the secure sockets created by the 211 * {@link SSLContext} represented by this instance's configuration. Defaults 212 * to TLS. See Appendix A in the <a href= 213 * "http://download.oracle.com/javase/6/docs/technotes/guides//security/jsse/JSSERefGuide.html#AppA" 214 * >Java Secure Socket Extension Reference Guide</a> for information about 215 * standard protocol names. 216 * 217 * @param secureSocketProtocol the name of the protocol or {@code null} to 218 * use the default (TLS) 219 */ 220 public void setSecureSocketProtocol(String secureSocketProtocol) { 221 this.secureSocketProtocol = secureSocketProtocol; 222 } 223 224 public String getCertAlias() { 225 return certAlias; 226 } 227 228 /** 229 * An optional certificate alias to use. This is useful when the keystore has multiple 230 * certificates. 231 * @param certAlias an optional certificate alias to use 232 */ 233 public void setCertAlias(String certAlias) { 234 this.certAlias = certAlias; 235 } 236 237 //////////////////////////////////////////// 238 239 /** 240 * Creates an {@link SSLContext} based on the related configuration options 241 * of this instance. Namely, {@link #keyManagers}, {@link #trustManagers}, and 242 * {@link #secureRandom}, but also respecting the chosen provider and secure 243 * socket protocol as well. 244 * 245 * @return a newly configured instance 246 * 247 * @throws GeneralSecurityException if there is a problem in this instances 248 * configuration or that of its nested configuration options 249 * @throws IOException if there is an error reading a key/trust store 250 * @deprecated use {@link #configureSSLContext(SSLContext)} 251 */ 252 @Deprecated 253 public SSLContext createSSLContext() throws GeneralSecurityException, IOException { 254 return createSSLContext(null); 255 } 256 257 /** 258 * Creates an {@link SSLContext} based on the related configuration options 259 * of this instance. Namely, {@link #keyManagers}, {@link #trustManagers}, and 260 * {@link #secureRandom}, but also respecting the chosen provider and secure 261 * socket protocol as well. 262 * 263 * @param camelContext The camel context 264 * 265 * @return a newly configured instance 266 * 267 * @throws GeneralSecurityException if there is a problem in this instances 268 * configuration or that of its nested configuration options 269 * @throws IOException if there is an error reading a key/trust store 270 */ 271 public SSLContext createSSLContext(CamelContext camelContext) throws GeneralSecurityException, IOException { 272 if (camelContext != null) { 273 // setup CamelContext before creating SSLContext 274 setCamelContext(camelContext); 275 if (keyManagers != null) { 276 keyManagers.setCamelContext(camelContext); 277 } 278 if (trustManagers != null) { 279 trustManagers.setCamelContext(camelContext); 280 } 281 if (secureRandom != null) { 282 secureRandom.setCamelContext(camelContext); 283 } 284 if (clientParameters != null) { 285 clientParameters.setCamelContext(camelContext); 286 } 287 if (serverParameters != null) { 288 serverParameters.setCamelContext(camelContext); 289 } 290 } 291 292 LOG.trace("Creating SSLContext from SSLContextParameters [{}].", this); 293 294 LOG.info("Available providers: {}.", Security.getProviders()); 295 296 KeyManager[] keyManagers = this.keyManagers == null ? null : this.keyManagers.createKeyManagers(); 297 TrustManager[] trustManagers = this.trustManagers == null ? null : this.trustManagers.createTrustManagers(); 298 SecureRandom secureRandom = this.secureRandom == null ? null : this.secureRandom.createSecureRandom(); 299 300 SSLContext context; 301 if (this.getProvider() == null) { 302 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol())); 303 } else { 304 context = SSLContext.getInstance(this.parsePropertyValue(this.getSecureSocketProtocol()), 305 this.parsePropertyValue(this.getProvider())); 306 } 307 308 if (this.getCertAlias() != null && keyManagers != null) { 309 for (int idx = 0; idx < keyManagers.length; idx++) { 310 if (keyManagers[idx] instanceof X509KeyManager) { 311 try { 312 keyManagers[idx] = new AliasedX509ExtendedKeyManager(this.getCertAlias(), 313 (X509KeyManager)keyManagers[idx]); 314 } catch (Exception e) { 315 throw new GeneralSecurityException(e); 316 } 317 } 318 } 319 } 320 321 LOG.debug("SSLContext [{}], initialized from [{}], is using provider [{}], protocol [{}], key managers {}, trust managers {}, and secure random [{}].", 322 new Object[] {context, this, context.getProvider(), context.getProtocol(), keyManagers, trustManagers, secureRandom}); 323 324 context.init(keyManagers, trustManagers, secureRandom); 325 326 this.configureSSLContext(context); 327 328 // Decorate the context. 329 context = new SSLContextDecorator( 330 new SSLContextSpiDecorator( 331 context, 332 this.getSSLEngineConfigurers(context), 333 this.getSSLSocketFactoryConfigurers(context), 334 this.getSSLServerSocketFactoryConfigurers(context))); 335 336 return context; 337 } 338 339 @Override 340 protected void configureSSLContext(SSLContext context) throws GeneralSecurityException { 341 LOG.trace("Configuring client and server side SSLContext parameters on SSLContext [{}]...", context); 342 super.configureSSLContext(context); 343 344 if (this.getClientParameters() != null) { 345 LOG.trace("Overriding client-side SSLContext parameters on SSLContext [{}] with configured client parameters.", 346 context); 347 this.getClientParameters().configureSSLContext(context); 348 } 349 350 if (this.getServerParameters() != null) { 351 LOG.trace("Overriding server-side SSLContext parameters on SSLContext [{}] with configured server parameters.", 352 context); 353 this.getServerParameters().configureSSLContext(context); 354 } 355 356 LOG.trace("Configured client and server side SSLContext parameters on SSLContext [{}].", context); 357 } 358 359 @Override 360 protected List<Configurer<SSLEngine>> getSSLEngineConfigurers(SSLContext context) { 361 LOG.trace("Collecting client and server side SSLEngine configurers on SSLContext [{}]...", context); 362 List<Configurer<SSLEngine>> configurers = super.getSSLEngineConfigurers(context); 363 364 if (this.getClientParameters() != null) { 365 LOG.trace("Augmenting SSLEngine configurers with configurers from client parameters on SSLContext [{}].", 366 context); 367 configurers.addAll(this.getClientParameters().getSSLEngineConfigurers(context)); 368 } 369 370 if (this.getServerParameters() != null) { 371 LOG.trace("Augmenting SSLEngine configurers with configurers from server parameters on SSLContext [{}].", 372 context); 373 configurers.addAll(this.getServerParameters().getSSLEngineConfigurers(context)); 374 } 375 376 LOG.trace("Collected client and server side SSLEngine configurers on SSLContext [{}].", context); 377 378 return configurers; 379 } 380 381 @Override 382 protected List<Configurer<SSLSocketFactory>> getSSLSocketFactoryConfigurers(SSLContext context) { 383 LOG.trace("Collecting SSLSocketFactory configurers on SSLContext [{}]...", context); 384 List<Configurer<SSLSocketFactory>> configurers = super.getSSLSocketFactoryConfigurers(context); 385 386 if (this.getClientParameters() != null) { 387 LOG.trace("Augmenting SSLSocketFactory configurers with configurers from client parameters on SSLContext [{}].", 388 context); 389 configurers.addAll(this.getClientParameters().getSSLSocketFactoryConfigurers(context)); 390 } 391 392 LOG.trace("Collected SSLSocketFactory configurers on SSLContext [{}].", context); 393 394 return configurers; 395 } 396 397 @Override 398 protected List<Configurer<SSLServerSocketFactory>> getSSLServerSocketFactoryConfigurers(SSLContext context) { 399 LOG.trace("Collecting SSLServerSocketFactory configurers for SSLContext [{}]...", context); 400 List<Configurer<SSLServerSocketFactory>> configurers = super.getSSLServerSocketFactoryConfigurers(context); 401 402 if (this.getServerParameters() != null) { 403 LOG.trace("Augmenting SSLServerSocketFactory configurers with configurers from server parameters for SSLContext [{}].", 404 context); 405 configurers.addAll(this.getServerParameters().getSSLServerSocketFactoryConfigurers(context)); 406 } 407 408 LOG.trace("Collected client and server side SSLServerSocketFactory configurers for SSLContext [{}].", context); 409 410 return configurers; 411 } 412 413 @Override 414 public String toString() { 415 StringBuilder builder = new StringBuilder(); 416 builder.append("SSLContextParameters[keyManagers="); 417 builder.append(keyManagers); 418 builder.append(", trustManagers="); 419 builder.append(trustManagers); 420 builder.append(", secureRandom="); 421 builder.append(secureRandom); 422 builder.append(", clientParameters="); 423 builder.append(clientParameters); 424 builder.append(", serverParameters="); 425 builder.append(serverParameters); 426 builder.append(", provider="); 427 builder.append(provider); 428 builder.append(", secureSocketProtocol="); 429 builder.append(secureSocketProtocol); 430 builder.append(", certAlias="); 431 builder.append(certAlias); 432 builder.append(", getCipherSuites()="); 433 builder.append(getCipherSuites()); 434 builder.append(", getCipherSuitesFilter()="); 435 builder.append(getCipherSuitesFilter()); 436 builder.append(", getSecureSocketProtocols()="); 437 builder.append(getSecureSocketProtocols()); 438 builder.append(", getSecureSocketProtocolsFilter()="); 439 builder.append(getSecureSocketProtocolsFilter()); 440 builder.append(", getSessionTimeout()="); 441 builder.append(getSessionTimeout()); 442 builder.append("]"); 443 return builder.toString(); 444 } 445 446}