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