001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.filter.ssl; 021 022import java.security.KeyStore; 023import java.security.SecureRandom; 024 025import javax.net.ssl.KeyManager; 026import javax.net.ssl.KeyManagerFactory; 027import javax.net.ssl.ManagerFactoryParameters; 028import javax.net.ssl.SSLContext; 029import javax.net.ssl.SSLSessionContext; 030import javax.net.ssl.TrustManager; 031import javax.net.ssl.TrustManagerFactory; 032 033/** 034 * A factory that creates and configures a new {@link SSLContext}. 035 * <p> 036 * If no properties are set the returned {@link SSLContext} will 037 * be equivalent to what the following creates: 038 * <pre> 039 * SSLContext c = SSLContext.getInstance( "TLS" ); 040 * c.init(null, null, null); 041 * </pre> 042 * <p> 043 * Use the properties prefixed with <code>keyManagerFactory</code> to control 044 * the creation of the {@link KeyManager} to be used. 045 * <p> 046 * Use the properties prefixed with <code>trustManagerFactory</code> to control 047 * the creation of the {@link TrustManagerFactory} to be used. 048 * 049 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 050 */ 051public class SslContextFactory { 052 053 private String provider = null; 054 055 private String protocol = "TLS"; 056 057 private SecureRandom secureRandom = null; 058 059 private KeyStore keyManagerFactoryKeyStore = null; 060 061 private char[] keyManagerFactoryKeyStorePassword = null; 062 063 private KeyManagerFactory keyManagerFactory = null; 064 065 private String keyManagerFactoryAlgorithm = null; 066 067 private String keyManagerFactoryProvider = null; 068 069 private boolean keyManagerFactoryAlgorithmUseDefault = true; 070 071 private KeyStore trustManagerFactoryKeyStore = null; 072 073 private TrustManagerFactory trustManagerFactory = null; 074 075 private String trustManagerFactoryAlgorithm = null; 076 077 private String trustManagerFactoryProvider = null; 078 079 private boolean trustManagerFactoryAlgorithmUseDefault = true; 080 081 private ManagerFactoryParameters trustManagerFactoryParameters = null; 082 083 private int clientSessionCacheSize = -1; 084 085 private int clientSessionTimeout = -1; 086 087 private int serverSessionCacheSize = -1; 088 089 private int serverSessionTimeout = -1; 090 091 public SSLContext newInstance() throws Exception { 092 KeyManagerFactory kmf = this.keyManagerFactory; 093 TrustManagerFactory tmf = this.trustManagerFactory; 094 095 if (kmf == null) { 096 String algorithm = keyManagerFactoryAlgorithm; 097 if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) { 098 algorithm = KeyManagerFactory.getDefaultAlgorithm(); 099 } 100 if (algorithm != null) { 101 if (keyManagerFactoryProvider == null) { 102 kmf = KeyManagerFactory.getInstance(algorithm); 103 } else { 104 kmf = KeyManagerFactory.getInstance(algorithm, keyManagerFactoryProvider); 105 } 106 } 107 } 108 109 if (tmf == null) { 110 String algorithm = trustManagerFactoryAlgorithm; 111 if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) { 112 algorithm = TrustManagerFactory.getDefaultAlgorithm(); 113 } 114 if (algorithm != null) { 115 if (trustManagerFactoryProvider == null) { 116 tmf = TrustManagerFactory.getInstance(algorithm); 117 } else { 118 tmf = TrustManagerFactory.getInstance(algorithm, trustManagerFactoryProvider); 119 } 120 } 121 } 122 123 KeyManager[] keyManagers = null; 124 if (kmf != null) { 125 kmf.init(keyManagerFactoryKeyStore, keyManagerFactoryKeyStorePassword); 126 keyManagers = kmf.getKeyManagers(); 127 } 128 TrustManager[] trustManagers = null; 129 if (tmf != null) { 130 if (trustManagerFactoryParameters != null) { 131 tmf.init(trustManagerFactoryParameters); 132 } else { 133 tmf.init(trustManagerFactoryKeyStore); 134 } 135 trustManagers = tmf.getTrustManagers(); 136 } 137 138 SSLContext context = null; 139 if (provider == null) { 140 context = SSLContext.getInstance(protocol); 141 } else { 142 context = SSLContext.getInstance(protocol, provider); 143 } 144 145 context.init(keyManagers, trustManagers, secureRandom); 146 147 if (clientSessionCacheSize >= 0) { 148 context.getClientSessionContext().setSessionCacheSize(clientSessionCacheSize); 149 } 150 151 if (clientSessionTimeout >= 0) { 152 context.getClientSessionContext().setSessionTimeout(clientSessionTimeout); 153 } 154 155 if (serverSessionCacheSize >= 0) { 156 context.getServerSessionContext().setSessionCacheSize(serverSessionCacheSize); 157 } 158 159 if (serverSessionTimeout >= 0) { 160 context.getServerSessionContext().setSessionTimeout(serverSessionTimeout); 161 } 162 163 return context; 164 } 165 166 /** 167 * Sets the provider of the new {@link SSLContext}. The default value is 168 * <tt>null</tt>, which means the default provider will be used. 169 * 170 * @param provider the name of the {@link SSLContext} provider 171 */ 172 public void setProvider(String provider) { 173 this.provider = provider; 174 } 175 176 /** 177 * Sets the protocol to use when creating the {@link SSLContext}. The 178 * default is <code>TLS</code>. 179 * 180 * @param protocol the name of the protocol. 181 */ 182 public void setProtocol(String protocol) { 183 if (protocol == null) { 184 throw new IllegalArgumentException("protocol"); 185 } 186 this.protocol = protocol; 187 } 188 189 /** 190 * If this is set to <tt>true</tt> while no {@link KeyManagerFactory} 191 * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 192 * no algorithm has been set using 193 * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm 194 * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used. 195 * The default value of this property is <tt>true</tt>. 196 * 197 * @param useDefault 198 * <tt>true</tt> or <tt>false</tt>. 199 */ 200 public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) { 201 this.keyManagerFactoryAlgorithmUseDefault = useDefault; 202 } 203 204 /** 205 * If this is set to <tt>true</tt> while no {@link TrustManagerFactory} 206 * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 207 * no algorithm has been set using 208 * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm 209 * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used. 210 * The default value of this property is <tt>true</tt>. 211 * 212 * @param useDefault <tt>true</tt> or <tt>false</tt>. 213 */ 214 public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) { 215 this.trustManagerFactoryAlgorithmUseDefault = useDefault; 216 } 217 218 /** 219 * Sets the {@link KeyManagerFactory} to use. If this is set the properties 220 * which are used by this factory bean to create a {@link KeyManagerFactory} 221 * will all be ignored. 222 * 223 * @param factory the factory. 224 */ 225 public void setKeyManagerFactory(KeyManagerFactory factory) { 226 this.keyManagerFactory = factory; 227 } 228 229 /** 230 * Sets the algorithm to use when creating the {@link KeyManagerFactory} 231 * using {@link KeyManagerFactory#getInstance(java.lang.String)} or 232 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 233 * <p> 234 * This property will be ignored if a {@link KeyManagerFactory} has been 235 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 236 * <p> 237 * If this property isn't set while no {@link KeyManagerFactory} has been 238 * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 239 * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to 240 * <tt>true</tt> the value returned 241 * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead. 242 * 243 * @param algorithm the algorithm to use. 244 */ 245 public void setKeyManagerFactoryAlgorithm(String algorithm) { 246 this.keyManagerFactoryAlgorithm = algorithm; 247 } 248 249 /** 250 * Sets the provider to use when creating the {@link KeyManagerFactory} 251 * using 252 * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}. 253 * <p> 254 * This property will be ignored if a {@link KeyManagerFactory} has been 255 * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}. 256 * <p> 257 * If this property isn't set and no {@link KeyManagerFactory} has been set 258 * using {@link #setKeyManagerFactory(KeyManagerFactory)} 259 * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used 260 * to create the {@link KeyManagerFactory}. 261 * 262 * @param provider the name of the provider. 263 */ 264 public void setKeyManagerFactoryProvider(String provider) { 265 this.keyManagerFactoryProvider = provider; 266 } 267 268 /** 269 * Sets the {@link KeyStore} which will be used in the call to 270 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 271 * the {@link SSLContext} is created. 272 * 273 * @param keyStore the key store. 274 */ 275 public void setKeyManagerFactoryKeyStore(KeyStore keyStore) { 276 this.keyManagerFactoryKeyStore = keyStore; 277 } 278 279 /** 280 * Sets the password which will be used in the call to 281 * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when 282 * the {@link SSLContext} is created. 283 * 284 * @param password the password. Use <code>null</code> to disable password. 285 */ 286 public void setKeyManagerFactoryKeyStorePassword(String password) { 287 if (password != null) { 288 this.keyManagerFactoryKeyStorePassword = password.toCharArray(); 289 } else { 290 this.keyManagerFactoryKeyStorePassword = null; 291 } 292 } 293 294 /** 295 * Sets the {@link TrustManagerFactory} to use. If this is set the 296 * properties which are used by this factory bean to create a 297 * {@link TrustManagerFactory} will all be ignored. 298 * 299 * @param factory 300 * the factory. 301 */ 302 public void setTrustManagerFactory(TrustManagerFactory factory) { 303 this.trustManagerFactory = factory; 304 } 305 306 /** 307 * Sets the algorithm to use when creating the {@link TrustManagerFactory} 308 * using {@link TrustManagerFactory#getInstance(java.lang.String)} or 309 * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}. 310 * <p> 311 * This property will be ignored if a {@link TrustManagerFactory} has been 312 * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}. 313 * <p> 314 * If this property isn't set while no {@link TrustManagerFactory} has been 315 * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 316 * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to 317 * <tt>true</tt> the value returned 318 * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead. 319 * 320 * @param algorithm the algorithm to use. 321 */ 322 public void setTrustManagerFactoryAlgorithm(String algorithm) { 323 this.trustManagerFactoryAlgorithm = algorithm; 324 } 325 326 /** 327 * Sets the {@link KeyStore} which will be used in the call to 328 * {@link TrustManagerFactory#init(java.security.KeyStore)} when 329 * the {@link SSLContext} is created. 330 * <p> 331 * This property will be ignored if {@link ManagerFactoryParameters} has been 332 * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}. 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(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 * 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 * 364 * @param provider the name of the provider. 365 */ 366 public void setTrustManagerFactoryProvider(String provider) { 367 this.trustManagerFactoryProvider = provider; 368 } 369 370 /** 371 * Sets the {@link SecureRandom} to use when initializing the 372 * {@link SSLContext}. The JVM's default will be used if this isn't set. 373 * 374 * @param secureRandom the {@link SecureRandom} or <code>null</code> if the 375 * JVM's default should be used. 376 * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom) 377 */ 378 public void setSecureRandom(SecureRandom secureRandom) { 379 this.secureRandom = secureRandom; 380 } 381 382 /** 383 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode. 384 * 385 * @param size the new session cache size limit; zero means there is no limit. 386 * @see SSLSessionContext#setSessionCacheSize(int size) 387 */ 388 public void setClientSessionCacheSize(int size) { 389 this.clientSessionCacheSize = size; 390 } 391 392 /** 393 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode. 394 * 395 * @param seconds the new session timeout limit in seconds; zero means there is no limit. 396 * @see SSLSessionContext#setSessionTimeout(int seconds) 397 */ 398 public void setClientSessionTimeout(int seconds) { 399 this.clientSessionTimeout = seconds; 400 } 401 402 /** 403 * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode. 404 * 405 * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit. 406 * @see SSLSessionContext#setSessionCacheSize(int) 407 */ 408 public void setServerSessionCacheSize(int serverSessionCacheSize) { 409 this.serverSessionCacheSize = serverSessionCacheSize; 410 } 411 412 /** 413 * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode. 414 * 415 * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit. 416 * @see SSLSessionContext#setSessionTimeout(int) 417 */ 418 public void setServerSessionTimeout(int serverSessionTimeout) { 419 this.serverSessionTimeout = serverSessionTimeout; 420 } 421}