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