1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * 19 */ 20 package org.apache.mina.integration.spring.ssl; 21 22 import java.security.KeyStore; 23 import java.security.SecureRandom; 24 25 import javax.net.ssl.KeyManager; 26 import javax.net.ssl.KeyManagerFactory; 27 import javax.net.ssl.SSLContext; 28 import javax.net.ssl.TrustManager; 29 import javax.net.ssl.TrustManagerFactory; 30 import javax.net.ssl.ManagerFactoryParameters; 31 32 import org.springframework.beans.factory.config.AbstractFactoryBean; 33 import org.springframework.util.Assert; 34 35 /** 36 * Spring {@link org.springframework.beans.factory.FactoryBean} implementation 37 * which makes it possible to configure {@link javax.net.ssl.SSLContext} 38 * instances using Spring. 39 * <p> 40 * If no properties are set the returned {@link javax.net.ssl.SSLContext} will 41 * be equivalent to what the following creates: 42 * <pre> 43 * SSLContext c = SSLContext.getInstance( "TLS" ); 44 * c.init( null, null, null ); 45 * </pre> 46 * </p> 47 * <p> 48 * Use the properties prefixed with <code>keyManagerFactory</code> to control 49 * the creation of the {@link javax.net.ssl.KeyManager} to be used. 50 * </p> 51 * <p> 52 * Use the properties prefixed with <code>trustManagerFactory</code> to control 53 * the creation of the {@link javax.net.ssl.TrustManagerFactory} to be used. 54 * </p> 55 * 56 * @author The Apache Directory Project (mina-dev@directory.apache.org) 57 * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007) $ 58 */ 59 public class SSLContextFactoryBean extends AbstractFactoryBean { 60 private String protocol = "TLS"; 61 62 private String provider = null; 63 64 private SecureRandom secureRandom = null; 65 66 private KeyStore keyManagerFactoryKeyStore = null; 67 68 private char[] keyManagerFactoryKeyStorePassword = null; 69 70 private KeyManagerFactory keyManagerFactory = null; 71 72 private String keyManagerFactoryAlgorithm = null; 73 74 private String keyManagerFactoryProvider = null; 75 76 private boolean keyManagerFactoryAlgorithmUseDefault = false; 77 78 private KeyStore trustManagerFactoryKeyStore = null; 79 80 private TrustManagerFactory trustManagerFactory = null; 81 82 private String trustManagerFactoryAlgorithm = null; 83 84 private String trustManagerFactoryProvider = null; 85 86 private boolean trustManagerFactoryAlgorithmUseDefault = false; 87 88 private ManagerFactoryParameters trustManagerFactoryParameters = null; 89 90 protected Object createInstance() throws Exception { 91 KeyManagerFactory kmf = this.keyManagerFactory; 92 TrustManagerFactory tmf = this.trustManagerFactory; 93 94 if (kmf == null) { 95 String algorithm = keyManagerFactoryAlgorithm; 96 if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) { 97 algorithm = KeyManagerFactory.getDefaultAlgorithm(); 98 } 99 if (algorithm != null) { 100 if (keyManagerFactoryProvider == null) { 101 kmf = KeyManagerFactory.getInstance(algorithm); 102 } else { 103 kmf = KeyManagerFactory.getInstance(algorithm, 104 keyManagerFactoryProvider); 105 } 106 } 107 } 108 109 if (tmf == null) { 110 String algorithm = trustManagerFactoryAlgorithm; 111 if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) { 112 algorithm = TrustManagerFactory.getDefaultAlgorithm(); 113 } 114 if (algorithm != null) { 115 if (trustManagerFactoryProvider == null) { 116 tmf = TrustManagerFactory.getInstance(algorithm); 117 } else { 118 tmf = TrustManagerFactory.getInstance(algorithm, 119 trustManagerFactoryProvider); 120 } 121 } 122 } 123 124 KeyManager[] keyManagers = null; 125 if (kmf != null) { 126 kmf.init(keyManagerFactoryKeyStore, 127 keyManagerFactoryKeyStorePassword); 128 keyManagers = kmf.getKeyManagers(); 129 } 130 TrustManager[] trustManagers = null; 131 if (tmf != null) { 132 if (trustManagerFactoryParameters != null) { 133 tmf.init(trustManagerFactoryParameters); 134 } else { 135 tmf.init(trustManagerFactoryKeyStore); 136 } 137 trustManagers = tmf.getTrustManagers(); 138 } 139 140 SSLContext context = null; 141 if (provider == null) { 142 context = SSLContext.getInstance(protocol); 143 } else { 144 context = SSLContext.getInstance(protocol, provider); 145 } 146 147 context.init(keyManagers, trustManagers, secureRandom); 148 149 return context; 150 } 151 152 public Class getObjectType() { 153 return SSLContext.class; 154 } 155 156 /** 157 * Sets the protocol to use when creating the {@link SSLContext}. The 158 * default is <code>TLS</code>. 159 * 160 * @param protocol the name of the protocol. 161 * @throws IllegalArgumentException if the specified value is 162 * <code>null</code>. 163 */ 164 public void setProtocol(String protocol) { 165 Assert.notNull(protocol, "Property 'protocol' may not be null"); 166 this.protocol = protocol; 167 } 168 169 /** 170 * If this is set to <code>true</code> while no {@link KeyManagerFactory} 171 * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 172 * no algorithm has been set using 173 * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm 174 * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used. 175 * 176 * @param useDefault <code>true</code> or <code>false</code>. 177 */ 178 public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) { 179 this.keyManagerFactoryAlgorithmUseDefault = useDefault; 180 } 181 182 /** 183 * If this is set to <code>true</code> while no {@link TrustManagerFactory} 184 * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 185 * no algorithm has been set using 186 * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm 187 * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used. 188 * 189 * @param useDefault <code>true</code> or <code>false</code>. 190 */ 191 public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) { 192 this.trustManagerFactoryAlgorithmUseDefault = useDefault; 193 } 194 195 /** 196 * Sets the {@link KeyManagerFactory} to use. If this is set the properties 197 * which are used by this factory bean to create a {@link KeyManagerFactory} 198 * will all be ignored. 199 * 200 * @param factory the factory. 201 */ 202 public void setKeyManagerFactory(KeyManagerFactory factory) { 203 this.keyManagerFactory = factory; 204 } 205 206 /** 207 * Sets the algorithm to use when creating the {@link KeyManagerFactory} 208 * using {@link KeyManagerFactory#getInstance(java.lang.String)} or 209 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 210 * <p> 211 * This property will be ignored if a {@link KeyManagerFactory} has been 212 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 213 * </p> 214 * <p> 215 * If this property isn't set while no {@link KeyManagerFactory} has been 216 * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 217 * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to 218 * <code>true</code> the value returned 219 * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead. 220 * </p> 221 * 222 * @param algorithm the algorithm to use. 223 */ 224 public void setKeyManagerFactoryAlgorithm(String algorithm) { 225 this.keyManagerFactoryAlgorithm = algorithm; 226 } 227 228 /** 229 * Sets the provider to use when creating the {@link KeyManagerFactory} 230 * using 231 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 232 * <p> 233 * This property will be ignored if a {@link KeyManagerFactory} has been 234 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 235 * </p> 236 * <p> 237 * If this property isn't set and no {@link KeyManagerFactory} has been set 238 * using {@link #setKeyManagerFactory(KeyManagerFactory)} 239 * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used 240 * to create the {@link KeyManagerFactory}. 241 * </p> 242 * 243 * @param provider the name of the provider. 244 */ 245 public void setKeyManagerFactoryProvider(String provider) { 246 this.keyManagerFactoryProvider = provider; 247 } 248 249 /** 250 * Sets the {@link KeyStore} which will be used in the call to 251 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 252 * the {@link SSLContext} is created. 253 * 254 * @param keyStore the key store. 255 */ 256 public void setKeyManagerFactoryKeyStore(KeyStore keyStore) { 257 this.keyManagerFactoryKeyStore = keyStore; 258 } 259 260 /** 261 * Sets the password which will be used in the call to 262 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 263 * the {@link SSLContext} is created. 264 * 265 * @param password the password. Use <code>null</code> to disable password. 266 */ 267 public void setKeyManagerFactoryKeyStorePassword(String password) { 268 if (password != null) { 269 this.keyManagerFactoryKeyStorePassword = password.toCharArray(); 270 } else { 271 this.keyManagerFactoryKeyStorePassword = null; 272 } 273 } 274 275 /** 276 * Sets the {@link TrustManagerFactory} to use. If this is set the properties 277 * which are used by this factory bean to create a {@link TrustManagerFactory} 278 * will all be ignored. 279 * 280 * @param factory the factory. 281 */ 282 public void setTrustManagerFactory(TrustManagerFactory factory) { 283 this.trustManagerFactory = factory; 284 } 285 286 /** 287 * Sets the algorithm to use when creating the {@link TrustManagerFactory} 288 * using {@link TrustManagerFactory#getInstance(java.lang.String)} or 289 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 290 * <p> 291 * This property will be ignored if a {@link TrustManagerFactory} has been 292 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 293 * </p> 294 * <p> 295 * If this property isn't set while no {@link TrustManagerFactory} has been 296 * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 297 * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to 298 * <code>true</code> the value returned 299 * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead. 300 * </p> 301 * 302 * @param algorithm the algorithm to use. 303 */ 304 public void setTrustManagerFactoryAlgorithm(String algorithm) { 305 this.trustManagerFactoryAlgorithm = algorithm; 306 } 307 308 /** 309 * Sets the {@link KeyStore} which will be used in the call to 310 * {@link TrustManagerFactory#init(java.security.KeyStore)} when 311 * the {@link SSLContext} is created. 312 * <p> 313 * This property will be ignored if {@link ManagerFactoryParameters} has been 314 * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}. 315 * </p> 316 * 317 * @param keyStore the key store. 318 */ 319 public void setTrustManagerFactoryKeyStore(KeyStore keyStore) { 320 this.trustManagerFactoryKeyStore = keyStore; 321 } 322 323 /** 324 * Sets the {@link ManagerFactoryParameters} which will be used in the call to 325 * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when 326 * the {@link SSLContext} is created. 327 * 328 * @param parameters describing provider-specific trust material. 329 */ 330 public void setTrustManagerFactoryParameters( 331 ManagerFactoryParameters parameters) { 332 this.trustManagerFactoryParameters = parameters; 333 } 334 335 /** 336 * Sets the provider to use when creating the {@link TrustManagerFactory} 337 * using 338 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 339 * <p> 340 * This property will be ignored if a {@link TrustManagerFactory} has been 341 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 342 * </p> 343 * <p> 344 * If this property isn't set and no {@link TrustManagerFactory} has been set 345 * using {@link #setTrustManagerFactory(TrustManagerFactory)} 346 * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used 347 * to create the {@link TrustManagerFactory}. 348 * </p> 349 * 350 * @param provider the name of the provider. 351 */ 352 public void setTrustManagerFactoryProvider(String provider) { 353 this.trustManagerFactoryProvider = provider; 354 } 355 356 /** 357 * Sets the {@link SecureRandom} to use when initializing the 358 * {@link SSLContext}. The JVM's default will be used if this isn't set. 359 * 360 * @param secureRandom the {@link SecureRandom} or <code>null</code> if the 361 * JVM's default should be used. 362 * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) 363 */ 364 public void setSecureRandom(SecureRandom secureRandom) { 365 this.secureRandom = secureRandom; 366 } 367 368 }