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 }