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.filter.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.ManagerFactoryParameters; 28 import javax.net.ssl.SSLContext; 29 import javax.net.ssl.SSLSessionContext; 30 import javax.net.ssl.TrustManager; 31 import javax.net.ssl.TrustManagerFactory; 32 33 /** 34 * A factory that creates and configures a new {@link SSLContext}. 35 * <p> 36 * If no properties are set the returned {@link SSLContext} will 37 * be equivalent to what the following creates: 38 * <pre> 39 * SSLContext c = SSLContext.getInstance( "TLS" ); 40 * c.init(null, null, null); 41 * </pre> 42 * </p> 43 * <p> 44 * Use the properties prefixed with <code>keyManagerFactory</code> to control 45 * the creation of the {@link KeyManager} to be used. 46 * </p> 47 * <p> 48 * Use the properties prefixed with <code>trustManagerFactory</code> to control 49 * the creation of the {@link TrustManagerFactory} to be used. 50 * </p> 51 * 52 * @author The Apache MINA Project (dev@mina.apache.org) 53 * @version $Rev: 599286 $, $Date: 2007-11-28 22:56:19 -0700 (Wed, 28 Nov 2007) $ 54 */ 55 public class SslContextFactory { 56 57 private String provider = null; 58 private String protocol = "TLS"; 59 private SecureRandom secureRandom = null; 60 private KeyStore keyManagerFactoryKeyStore = null; 61 private char[] keyManagerFactoryKeyStorePassword = null; 62 private KeyManagerFactory keyManagerFactory = null; 63 private String keyManagerFactoryAlgorithm = null; 64 private String keyManagerFactoryProvider = null; 65 private boolean keyManagerFactoryAlgorithmUseDefault = false; 66 private KeyStore trustManagerFactoryKeyStore = null; 67 private TrustManagerFactory trustManagerFactory = null; 68 private String trustManagerFactoryAlgorithm = null; 69 private String trustManagerFactoryProvider = null; 70 private boolean trustManagerFactoryAlgorithmUseDefault = false; 71 private ManagerFactoryParameters trustManagerFactoryParameters = null; 72 private int clientSessionCacheSize = -1; 73 private int clientSessionTimeout = -1; 74 private int serverSessionCacheSize = -1; 75 private int serverSessionTimeout = -1; 76 77 public SSLContext newInstance() throws Exception { 78 KeyManagerFactory kmf = this.keyManagerFactory; 79 TrustManagerFactory tmf = this.trustManagerFactory; 80 81 if (kmf == null) { 82 String algorithm = keyManagerFactoryAlgorithm; 83 if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) { 84 algorithm = KeyManagerFactory.getDefaultAlgorithm(); 85 } 86 if (algorithm != null) { 87 if (keyManagerFactoryProvider == null) { 88 kmf = KeyManagerFactory.getInstance(algorithm); 89 } else { 90 kmf = KeyManagerFactory.getInstance(algorithm, 91 keyManagerFactoryProvider); 92 } 93 } 94 } 95 96 if (tmf == null) { 97 String algorithm = trustManagerFactoryAlgorithm; 98 if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) { 99 algorithm = TrustManagerFactory.getDefaultAlgorithm(); 100 } 101 if (algorithm != null) { 102 if (trustManagerFactoryProvider == null) { 103 tmf = TrustManagerFactory.getInstance(algorithm); 104 } else { 105 tmf = TrustManagerFactory.getInstance(algorithm, 106 trustManagerFactoryProvider); 107 } 108 } 109 } 110 111 KeyManager[] keyManagers = null; 112 if (kmf != null) { 113 kmf.init(keyManagerFactoryKeyStore, 114 keyManagerFactoryKeyStorePassword); 115 keyManagers = kmf.getKeyManagers(); 116 } 117 TrustManager[] trustManagers = null; 118 if (tmf != null) { 119 if (trustManagerFactoryParameters != null) { 120 tmf.init(trustManagerFactoryParameters); 121 } else { 122 tmf.init(trustManagerFactoryKeyStore); 123 } 124 trustManagers = tmf.getTrustManagers(); 125 } 126 127 SSLContext context = null; 128 if (provider == null) { 129 context = SSLContext.getInstance(protocol); 130 } else { 131 context = SSLContext.getInstance(protocol, provider); 132 } 133 134 context.init(keyManagers, trustManagers, secureRandom); 135 136 if (clientSessionCacheSize >= 0) { 137 context.getClientSessionContext().setSessionCacheSize( 138 clientSessionCacheSize); 139 } 140 141 if (clientSessionTimeout >= 0) { 142 context.getClientSessionContext().setSessionTimeout( 143 clientSessionTimeout); 144 } 145 146 if (serverSessionCacheSize >= 0) { 147 context.getServerSessionContext().setSessionCacheSize( 148 serverSessionCacheSize); 149 } 150 151 if (serverSessionTimeout >= 0) { 152 context.getServerSessionContext().setSessionTimeout( 153 serverSessionTimeout); 154 } 155 156 return context; 157 } 158 159 /** 160 * Sets the provider of the new {@link SSLContext}. The default value is 161 * <tt>null</tt>, which means the default provider will be used. 162 * 163 * @param provider the name of the {@link SSLContext} provider 164 */ 165 public void setProvider(String provider) { 166 this.provider = provider; 167 } 168 169 /** 170 * Sets the protocol to use when creating the {@link SSLContext}. The 171 * default is <code>TLS</code>. 172 * 173 * @param protocol the name of the protocol. 174 */ 175 public void setProtocol(String protocol) { 176 if (protocol == null) { 177 throw new NullPointerException("protocol"); 178 } 179 this.protocol = protocol; 180 } 181 182 /** 183 * If this is set to <code>true</code> while no {@link KeyManagerFactory} 184 * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 185 * no algorithm has been set using 186 * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm 187 * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used. 188 * 189 * @param useDefault 190 * <code>true</code> or <code>false</code>. 191 */ 192 public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) { 193 this.keyManagerFactoryAlgorithmUseDefault = useDefault; 194 } 195 196 /** 197 * If this is set to <code>true</code> while no {@link TrustManagerFactory} 198 * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 199 * no algorithm has been set using 200 * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm 201 * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used. 202 * 203 * @param useDefault <code>true</code> or <code>false</code>. 204 */ 205 public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) { 206 this.trustManagerFactoryAlgorithmUseDefault = useDefault; 207 } 208 209 /** 210 * Sets the {@link KeyManagerFactory} to use. If this is set the properties 211 * which are used by this factory bean to create a {@link KeyManagerFactory} 212 * will all be ignored. 213 * 214 * @param factory the factory. 215 */ 216 public void setKeyManagerFactory(KeyManagerFactory factory) { 217 this.keyManagerFactory = factory; 218 } 219 220 /** 221 * Sets the algorithm to use when creating the {@link KeyManagerFactory} 222 * using {@link KeyManagerFactory#getInstance(java.lang.String)} or 223 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 224 * <p> 225 * This property will be ignored if a {@link KeyManagerFactory} has been 226 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 227 * </p> 228 * <p> 229 * If this property isn't set while no {@link KeyManagerFactory} has been 230 * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 231 * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to 232 * <code>true</code> the value returned 233 * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead. 234 * </p> 235 * 236 * @param algorithm the algorithm to use. 237 */ 238 public void setKeyManagerFactoryAlgorithm(String algorithm) { 239 this.keyManagerFactoryAlgorithm = algorithm; 240 } 241 242 /** 243 * Sets the provider to use when creating the {@link KeyManagerFactory} 244 * using 245 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 246 * <p> 247 * This property will be ignored if a {@link KeyManagerFactory} has been 248 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 249 * </p> 250 * <p> 251 * If this property isn't set and no {@link KeyManagerFactory} has been set 252 * using {@link #setKeyManagerFactory(KeyManagerFactory)} 253 * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used 254 * to create the {@link KeyManagerFactory}. 255 * </p> 256 * 257 * @param provider the name of the provider. 258 */ 259 public void setKeyManagerFactoryProvider(String provider) { 260 this.keyManagerFactoryProvider = provider; 261 } 262 263 /** 264 * Sets the {@link KeyStore} which will be used in the call to 265 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 266 * the {@link SSLContext} is created. 267 * 268 * @param keyStore the key store. 269 */ 270 public void setKeyManagerFactoryKeyStore(KeyStore keyStore) { 271 this.keyManagerFactoryKeyStore = keyStore; 272 } 273 274 /** 275 * Sets the password which will be used in the call to 276 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 277 * the {@link SSLContext} is created. 278 * 279 * @param password the password. Use <code>null</code> to disable password. 280 */ 281 public void setKeyManagerFactoryKeyStorePassword(String password) { 282 if (password != null) { 283 this.keyManagerFactoryKeyStorePassword = password.toCharArray(); 284 } else { 285 this.keyManagerFactoryKeyStorePassword = null; 286 } 287 } 288 289 /** 290 * Sets the {@link TrustManagerFactory} to use. If this is set the 291 * properties which are used by this factory bean to create a 292 * {@link TrustManagerFactory} will all be ignored. 293 * 294 * @param factory 295 * the factory. 296 */ 297 public void setTrustManagerFactory(TrustManagerFactory factory) { 298 this.trustManagerFactory = factory; 299 } 300 301 /** 302 * Sets the algorithm to use when creating the {@link TrustManagerFactory} 303 * using {@link TrustManagerFactory#getInstance(java.lang.String)} or 304 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 305 * <p> 306 * This property will be ignored if a {@link TrustManagerFactory} has been 307 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 308 * </p> 309 * <p> 310 * If this property isn't set while no {@link TrustManagerFactory} has been 311 * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 312 * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to 313 * <code>true</code> the value returned 314 * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead. 315 * </p> 316 * 317 * @param algorithm the algorithm to use. 318 */ 319 public void setTrustManagerFactoryAlgorithm(String algorithm) { 320 this.trustManagerFactoryAlgorithm = algorithm; 321 } 322 323 /** 324 * Sets the {@link KeyStore} which will be used in the call to 325 * {@link TrustManagerFactory#init(java.security.KeyStore)} when 326 * the {@link SSLContext} is created. 327 * <p> 328 * This property will be ignored if {@link ManagerFactoryParameters} has been 329 * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}. 330 * </p> 331 * 332 * @param keyStore the key store. 333 */ 334 public void setTrustManagerFactoryKeyStore(KeyStore keyStore) { 335 this.trustManagerFactoryKeyStore = keyStore; 336 } 337 338 /** 339 * Sets the {@link ManagerFactoryParameters} which will be used in the call to 340 * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when 341 * the {@link SSLContext} is created. 342 * 343 * @param parameters describing provider-specific trust material. 344 */ 345 public void setTrustManagerFactoryParameters( 346 ManagerFactoryParameters parameters) { 347 this.trustManagerFactoryParameters = parameters; 348 } 349 350 /** 351 * Sets the provider to use when creating the {@link TrustManagerFactory} 352 * using 353 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 354 * <p> 355 * This property will be ignored if a {@link TrustManagerFactory} has been 356 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 357 * </p> 358 * <p> 359 * If this property isn't set and no {@link TrustManagerFactory} has been set 360 * using {@link #setTrustManagerFactory(TrustManagerFactory)} 361 * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used 362 * to create the {@link TrustManagerFactory}. 363 * </p> 364 * 365 * @param provider the name of the provider. 366 */ 367 public void setTrustManagerFactoryProvider(String provider) { 368 this.trustManagerFactoryProvider = provider; 369 } 370 371 /** 372 * Sets the {@link SecureRandom} to use when initializing the 373 * {@link SSLContext}. The JVM's default will be used if this isn't set. 374 * 375 * @param secureRandom the {@link SecureRandom} or <code>null</code> if the 376 * JVM's default should be used. 377 * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) 378 */ 379 public void setSecureRandom(SecureRandom secureRandom) { 380 this.secureRandom = secureRandom; 381 } 382 383 /** 384 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode. 385 * 386 * @param size the new session cache size limit; zero means there is no limit. 387 * @see SSLSessionContext#setSessionCacheSize(int size) 388 */ 389 public void setClientSessionCacheSize(int size) { 390 this.clientSessionCacheSize = size; 391 } 392 393 /** 394 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode. 395 * 396 * @param seconds the new session timeout limit in seconds; zero means there is no limit. 397 * @see SSLSessionContext#setSessionTimeout(int seconds) 398 */ 399 public void setClientSessionTimeout(int seconds) { 400 this.clientSessionTimeout = seconds; 401 } 402 403 /** 404 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode. 405 * 406 * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit. 407 * @see SSLSessionContext#setSessionCacheSize(int) 408 */ 409 public void setServerSessionCacheSize(int serverSessionCacheSize) { 410 this.serverSessionCacheSize = serverSessionCacheSize; 411 } 412 413 /** 414 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode. 415 * 416 * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit. 417 * @see SSLSessionContext#setSessionTimeout(int) 418 */ 419 public void setServerSessionTimeout(int serverSessionTimeout) { 420 this.serverSessionTimeout = serverSessionTimeout; 421 } 422 }