View Javadoc
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   * 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 = "TLS";
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      public SSLContext newInstance() throws Exception {
92          KeyManagerFactory kmf = this.keyManagerFactory;
93          TrustManagerFactory tmf = this.trustManagerFactory;
94  
95          if (kmf == null) {
96              String algorithm = keyManagerFactoryAlgorithm;
97              if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
98                  algorithm = KeyManagerFactory.getDefaultAlgorithm();
99              }
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 }