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