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 }