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