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 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 }