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