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: 636238 $, $Date: 2008-03-12 08:36:04 +0100 (mer, 12 mar 2008) $ 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 = true; 66 private KeyStore trustManagerFactoryKeyStore = null; 67 private TrustManagerFactory trustManagerFactory = null; 68 private String trustManagerFactoryAlgorithm = null; 69 private String trustManagerFactoryProvider = null; 70 private boolean trustManagerFactoryAlgorithmUseDefault = true; 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 * The default value of this property is <tt>true<tt/>. 189 * 190 * @param useDefault 191 * <code>true</code> or <code>false</code>. 192 */ 193 public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) { 194 this.keyManagerFactoryAlgorithmUseDefault = useDefault; 195 } 196 197 /** 198 * If this is set to <code>true</code> while no {@link TrustManagerFactory} 199 * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 200 * no algorithm has been set using 201 * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm 202 * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used. 203 * The default value of this property is <tt>true<tt/>. 204 * 205 * @param useDefault <code>true</code> or <code>false</code>. 206 */ 207 public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) { 208 this.trustManagerFactoryAlgorithmUseDefault = useDefault; 209 } 210 211 /** 212 * Sets the {@link KeyManagerFactory} to use. If this is set the properties 213 * which are used by this factory bean to create a {@link KeyManagerFactory} 214 * will all be ignored. 215 * 216 * @param factory the factory. 217 */ 218 public void setKeyManagerFactory(KeyManagerFactory factory) { 219 this.keyManagerFactory = factory; 220 } 221 222 /** 223 * Sets the algorithm to use when creating the {@link KeyManagerFactory} 224 * using {@link KeyManagerFactory#getInstance(java.lang.String)} or 225 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 226 * <p> 227 * This property will be ignored if a {@link KeyManagerFactory} has been 228 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 229 * </p> 230 * <p> 231 * If this property isn't set while no {@link KeyManagerFactory} has been 232 * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 233 * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to 234 * <code>true</code> the value returned 235 * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead. 236 * </p> 237 * 238 * @param algorithm the algorithm to use. 239 */ 240 public void setKeyManagerFactoryAlgorithm(String algorithm) { 241 this.keyManagerFactoryAlgorithm = algorithm; 242 } 243 244 /** 245 * Sets the provider to use when creating the {@link KeyManagerFactory} 246 * using 247 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 248 * <p> 249 * This property will be ignored if a {@link KeyManagerFactory} has been 250 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 251 * </p> 252 * <p> 253 * If this property isn't set and no {@link KeyManagerFactory} has been set 254 * using {@link #setKeyManagerFactory(KeyManagerFactory)} 255 * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used 256 * to create the {@link KeyManagerFactory}. 257 * </p> 258 * 259 * @param provider the name of the provider. 260 */ 261 public void setKeyManagerFactoryProvider(String provider) { 262 this.keyManagerFactoryProvider = provider; 263 } 264 265 /** 266 * Sets the {@link KeyStore} which will be used in the call to 267 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 268 * the {@link SSLContext} is created. 269 * 270 * @param keyStore the key store. 271 */ 272 public void setKeyManagerFactoryKeyStore(KeyStore keyStore) { 273 this.keyManagerFactoryKeyStore = keyStore; 274 } 275 276 /** 277 * Sets the password which will be used in the call to 278 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 279 * the {@link SSLContext} is created. 280 * 281 * @param password the password. Use <code>null</code> to disable password. 282 */ 283 public void setKeyManagerFactoryKeyStorePassword(String password) { 284 if (password != null) { 285 this.keyManagerFactoryKeyStorePassword = password.toCharArray(); 286 } else { 287 this.keyManagerFactoryKeyStorePassword = null; 288 } 289 } 290 291 /** 292 * Sets the {@link TrustManagerFactory} to use. If this is set the 293 * properties which are used by this factory bean to create a 294 * {@link TrustManagerFactory} will all be ignored. 295 * 296 * @param factory 297 * the factory. 298 */ 299 public void setTrustManagerFactory(TrustManagerFactory factory) { 300 this.trustManagerFactory = factory; 301 } 302 303 /** 304 * Sets the algorithm to use when creating the {@link TrustManagerFactory} 305 * using {@link TrustManagerFactory#getInstance(java.lang.String)} or 306 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 307 * <p> 308 * This property will be ignored if a {@link TrustManagerFactory} has been 309 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 310 * </p> 311 * <p> 312 * If this property isn't set while no {@link TrustManagerFactory} has been 313 * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 314 * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to 315 * <code>true</code> the value returned 316 * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead. 317 * </p> 318 * 319 * @param algorithm the algorithm to use. 320 */ 321 public void setTrustManagerFactoryAlgorithm(String algorithm) { 322 this.trustManagerFactoryAlgorithm = algorithm; 323 } 324 325 /** 326 * Sets the {@link KeyStore} which will be used in the call to 327 * {@link TrustManagerFactory#init(java.security.KeyStore)} when 328 * the {@link SSLContext} is created. 329 * <p> 330 * This property will be ignored if {@link ManagerFactoryParameters} has been 331 * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}. 332 * </p> 333 * 334 * @param keyStore the key store. 335 */ 336 public void setTrustManagerFactoryKeyStore(KeyStore keyStore) { 337 this.trustManagerFactoryKeyStore = keyStore; 338 } 339 340 /** 341 * Sets the {@link ManagerFactoryParameters} which will be used in the call to 342 * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when 343 * the {@link SSLContext} is created. 344 * 345 * @param parameters describing provider-specific trust material. 346 */ 347 public void setTrustManagerFactoryParameters( 348 ManagerFactoryParameters parameters) { 349 this.trustManagerFactoryParameters = parameters; 350 } 351 352 /** 353 * Sets the provider to use when creating the {@link TrustManagerFactory} 354 * using 355 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 356 * <p> 357 * This property will be ignored if a {@link TrustManagerFactory} has been 358 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 359 * </p> 360 * <p> 361 * If this property isn't set and no {@link TrustManagerFactory} has been set 362 * using {@link #setTrustManagerFactory(TrustManagerFactory)} 363 * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used 364 * to create the {@link TrustManagerFactory}. 365 * </p> 366 * 367 * @param provider the name of the provider. 368 */ 369 public void setTrustManagerFactoryProvider(String provider) { 370 this.trustManagerFactoryProvider = provider; 371 } 372 373 /** 374 * Sets the {@link SecureRandom} to use when initializing the 375 * {@link SSLContext}. The JVM's default will be used if this isn't set. 376 * 377 * @param secureRandom the {@link SecureRandom} or <code>null</code> if the 378 * JVM's default should be used. 379 * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) 380 */ 381 public void setSecureRandom(SecureRandom secureRandom) { 382 this.secureRandom = secureRandom; 383 } 384 385 /** 386 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode. 387 * 388 * @param size the new session cache size limit; zero means there is no limit. 389 * @see SSLSessionContext#setSessionCacheSize(int size) 390 */ 391 public void setClientSessionCacheSize(int size) { 392 this.clientSessionCacheSize = size; 393 } 394 395 /** 396 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode. 397 * 398 * @param seconds the new session timeout limit in seconds; zero means there is no limit. 399 * @see SSLSessionContext#setSessionTimeout(int seconds) 400 */ 401 public void setClientSessionTimeout(int seconds) { 402 this.clientSessionTimeout = seconds; 403 } 404 405 /** 406 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode. 407 * 408 * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit. 409 * @see SSLSessionContext#setSessionCacheSize(int) 410 */ 411 public void setServerSessionCacheSize(int serverSessionCacheSize) { 412 this.serverSessionCacheSize = serverSessionCacheSize; 413 } 414 415 /** 416 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode. 417 * 418 * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit. 419 * @see SSLSessionContext#setSessionTimeout(int) 420 */ 421 public void setServerSessionTimeout(int serverSessionTimeout) { 422 this.serverSessionTimeout = serverSessionTimeout; 423 } 424 }