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 The Apache MINA Project (dev@mina.apache.org)
53   * @version $Rev: 636238 $, $Date: 2008-03-12 08:36:04 +0100 (mer, 12 mar 2008) $
54   */
55  public class SslContextFactory {
56      
57      private String provider = null;
58      private String protocol = "TLS";
59      private SecureRandom secureRandom = null;
60      private KeyStore keyManagerFactoryKeyStore = null;
61      private char[] keyManagerFactoryKeyStorePassword = null;
62      private KeyManagerFactory keyManagerFactory = null;
63      private String keyManagerFactoryAlgorithm = null;
64      private String keyManagerFactoryProvider = null;
65      private boolean keyManagerFactoryAlgorithmUseDefault = true;
66      private KeyStore trustManagerFactoryKeyStore = null;
67      private TrustManagerFactory trustManagerFactory = null;
68      private String trustManagerFactoryAlgorithm = null;
69      private String trustManagerFactoryProvider = null;
70      private boolean trustManagerFactoryAlgorithmUseDefault = true;
71      private ManagerFactoryParameters trustManagerFactoryParameters = null;
72      private int clientSessionCacheSize = -1;
73      private int clientSessionTimeout = -1;
74      private int serverSessionCacheSize = -1;
75      private int serverSessionTimeout = -1;
76  
77      public SSLContext newInstance() throws Exception {
78          KeyManagerFactory kmf = this.keyManagerFactory;
79          TrustManagerFactory tmf = this.trustManagerFactory;
80  
81          if (kmf == null) {
82              String algorithm = keyManagerFactoryAlgorithm;
83              if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
84                  algorithm = KeyManagerFactory.getDefaultAlgorithm();
85              }
86              if (algorithm != null) {
87                  if (keyManagerFactoryProvider == null) {
88                      kmf = KeyManagerFactory.getInstance(algorithm);
89                  } else {
90                      kmf = KeyManagerFactory.getInstance(algorithm,
91                              keyManagerFactoryProvider);
92                  }
93              }
94          }
95  
96          if (tmf == null) {
97              String algorithm = trustManagerFactoryAlgorithm;
98              if (algorithm == null && trustManagerFactoryAlgorithmUseDefault) {
99                  algorithm = TrustManagerFactory.getDefaultAlgorithm();
100             }
101             if (algorithm != null) {
102                 if (trustManagerFactoryProvider == null) {
103                     tmf = TrustManagerFactory.getInstance(algorithm);
104                 } else {
105                     tmf = TrustManagerFactory.getInstance(algorithm,
106                             trustManagerFactoryProvider);
107                 }
108             }
109         }
110 
111         KeyManager[] keyManagers = null;
112         if (kmf != null) {
113             kmf.init(keyManagerFactoryKeyStore,
114                     keyManagerFactoryKeyStorePassword);
115             keyManagers = kmf.getKeyManagers();
116         }
117         TrustManager[] trustManagers = null;
118         if (tmf != null) {
119             if (trustManagerFactoryParameters != null) {
120                 tmf.init(trustManagerFactoryParameters);
121             } else {
122                 tmf.init(trustManagerFactoryKeyStore);
123             }
124             trustManagers = tmf.getTrustManagers();
125         }
126 
127         SSLContext context = null;
128         if (provider == null) {
129             context = SSLContext.getInstance(protocol);
130         } else {
131             context = SSLContext.getInstance(protocol, provider);
132         }
133 
134         context.init(keyManagers, trustManagers, secureRandom);
135 
136         if (clientSessionCacheSize >= 0) {
137             context.getClientSessionContext().setSessionCacheSize(
138                     clientSessionCacheSize);
139         }
140 
141         if (clientSessionTimeout >= 0) {
142             context.getClientSessionContext().setSessionTimeout(
143                     clientSessionTimeout);
144         }
145 
146         if (serverSessionCacheSize >= 0) {
147             context.getServerSessionContext().setSessionCacheSize(
148                     serverSessionCacheSize);
149         }
150 
151         if (serverSessionTimeout >= 0) {
152             context.getServerSessionContext().setSessionTimeout(
153                     serverSessionTimeout);
154         }
155 
156         return context;
157     }
158 
159     /**
160      * Sets the provider of the new {@link SSLContext}. The default value is
161      * <tt>null</tt>, which means the default provider will be used.
162      * 
163      * @param provider the name of the {@link SSLContext} provider
164      */
165     public void setProvider(String provider) {
166         this.provider = provider;
167     }
168 
169     /**
170      * Sets the protocol to use when creating the {@link SSLContext}. The
171      * default is <code>TLS</code>.
172      *
173      * @param protocol the name of the protocol.
174      */
175     public void setProtocol(String protocol) {
176         if (protocol == null) {
177             throw new NullPointerException("protocol");
178         }
179         this.protocol = protocol;
180     }
181 
182     /**
183      * If this is set to <code>true</code> while no {@link KeyManagerFactory}
184      * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
185      * no algorithm has been set using
186      * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm
187      * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used.
188      * The default value of this property is <tt>true<tt/>.
189      *
190      * @param useDefault
191      *            <code>true</code> or <code>false</code>.
192      */
193     public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) {
194         this.keyManagerFactoryAlgorithmUseDefault = useDefault;
195     }
196 
197     /**
198      * If this is set to <code>true</code> while no {@link TrustManagerFactory}
199      * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
200      * no algorithm has been set using
201      * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm
202      * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used.
203      * The default value of this property is <tt>true<tt/>.
204      *
205      * @param useDefault <code>true</code> or <code>false</code>.
206      */
207     public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
208         this.trustManagerFactoryAlgorithmUseDefault = useDefault;
209     }
210 
211     /**
212      * Sets the {@link KeyManagerFactory} to use. If this is set the properties
213      * which are used by this factory bean to create a {@link KeyManagerFactory}
214      * will all be ignored.
215      *
216      * @param factory the factory.
217      */
218     public void setKeyManagerFactory(KeyManagerFactory factory) {
219         this.keyManagerFactory = factory;
220     }
221 
222     /**
223      * Sets the algorithm to use when creating the {@link KeyManagerFactory}
224      * using {@link KeyManagerFactory#getInstance(java.lang.String)} or
225      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
226      * <p>
227      * This property will be ignored if a {@link KeyManagerFactory} has been
228      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
229      * </p>
230      * <p>
231      * If this property isn't set while no {@link KeyManagerFactory} has been
232      * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
233      * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to
234      * <code>true</code> the value returned
235      * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
236      * </p>
237      *
238      * @param algorithm the algorithm to use.
239      */
240     public void setKeyManagerFactoryAlgorithm(String algorithm) {
241         this.keyManagerFactoryAlgorithm = algorithm;
242     }
243 
244     /**
245      * Sets the provider to use when creating the {@link KeyManagerFactory}
246      * using
247      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
248      * <p>
249      * This property will be ignored if a {@link KeyManagerFactory} has been
250      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
251      * </p>
252      * <p>
253      * If this property isn't set and no {@link KeyManagerFactory} has been set
254      * using {@link #setKeyManagerFactory(KeyManagerFactory)}
255      * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
256      * to create the {@link KeyManagerFactory}.
257      * </p>
258      *
259      * @param provider the name of the provider.
260      */
261     public void setKeyManagerFactoryProvider(String provider) {
262         this.keyManagerFactoryProvider = provider;
263     }
264 
265     /**
266      * Sets the {@link KeyStore} which will be used in the call to
267      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
268      * the {@link SSLContext} is created.
269      *
270      * @param keyStore the key store.
271      */
272     public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
273         this.keyManagerFactoryKeyStore = keyStore;
274     }
275 
276     /**
277      * Sets the password which will be used in the call to
278      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
279      * the {@link SSLContext} is created.
280      *
281      * @param password the password. Use <code>null</code> to disable password.
282      */
283     public void setKeyManagerFactoryKeyStorePassword(String password) {
284         if (password != null) {
285             this.keyManagerFactoryKeyStorePassword = password.toCharArray();
286         } else {
287             this.keyManagerFactoryKeyStorePassword = null;
288         }
289     }
290 
291     /**
292      * Sets the {@link TrustManagerFactory} to use. If this is set the
293      * properties which are used by this factory bean to create a
294      * {@link TrustManagerFactory} will all be ignored.
295      *
296      * @param factory
297      *            the factory.
298      */
299     public void setTrustManagerFactory(TrustManagerFactory factory) {
300         this.trustManagerFactory = factory;
301     }
302 
303     /**
304      * Sets the algorithm to use when creating the {@link TrustManagerFactory}
305      * using {@link TrustManagerFactory#getInstance(java.lang.String)} or
306      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
307      * <p>
308      * This property will be ignored if a {@link TrustManagerFactory} has been
309      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
310      * </p>
311      * <p>
312      * If this property isn't set while no {@link TrustManagerFactory} has been
313      * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
314      * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to
315      * <code>true</code> the value returned
316      * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
317      * </p>
318      *
319      * @param algorithm the algorithm to use.
320      */
321     public void setTrustManagerFactoryAlgorithm(String algorithm) {
322         this.trustManagerFactoryAlgorithm = algorithm;
323     }
324 
325     /**
326      * Sets the {@link KeyStore} which will be used in the call to
327      * {@link TrustManagerFactory#init(java.security.KeyStore)} when
328      * the {@link SSLContext} is created.
329      * <p>
330      * This property will be ignored if {@link ManagerFactoryParameters} has been
331      * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
332      * </p>
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(
348             ManagerFactoryParameters parameters) {
349         this.trustManagerFactoryParameters = parameters;
350     }
351 
352     /**
353      * Sets the provider to use when creating the {@link TrustManagerFactory}
354      * using
355      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
356      * <p>
357      * This property will be ignored if a {@link TrustManagerFactory} has been
358      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
359      * </p>
360      * <p>
361      * If this property isn't set and no {@link TrustManagerFactory} has been set
362      * using {@link #setTrustManagerFactory(TrustManagerFactory)}
363      * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used
364      * to create the {@link TrustManagerFactory}.
365      * </p>
366      *
367      * @param provider the name of the provider.
368      */
369     public void setTrustManagerFactoryProvider(String provider) {
370         this.trustManagerFactoryProvider = provider;
371     }
372 
373     /**
374      * Sets the {@link SecureRandom} to use when initializing the
375      * {@link SSLContext}. The JVM's default will be used if this isn't set.
376      *
377      * @param secureRandom the {@link SecureRandom} or <code>null</code> if the
378      *        JVM's default should be used.
379      * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
380      */
381     public void setSecureRandom(SecureRandom secureRandom) {
382         this.secureRandom = secureRandom;
383     }
384 
385     /**
386      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode.
387      *
388      * @param size the new session cache size limit; zero means there is no limit.
389      * @see SSLSessionContext#setSessionCacheSize(int size)
390      */
391     public void setClientSessionCacheSize(int size) {
392         this.clientSessionCacheSize = size;
393     }
394 
395     /**
396      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode.
397      *
398      * @param seconds the new session timeout limit in seconds; zero means there is no limit.
399      * @see SSLSessionContext#setSessionTimeout(int seconds)
400      */
401     public void setClientSessionTimeout(int seconds) {
402         this.clientSessionTimeout = seconds;
403     }
404 
405     /**
406      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode.
407      *
408      * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit.
409      * @see SSLSessionContext#setSessionCacheSize(int)
410      */
411     public void setServerSessionCacheSize(int serverSessionCacheSize) {
412         this.serverSessionCacheSize = serverSessionCacheSize;
413     }
414 
415     /**
416      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode.
417      *
418      * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit.
419      * @see SSLSessionContext#setSessionTimeout(int)
420      */
421     public void setServerSessionTimeout(int serverSessionTimeout) {
422         this.serverSessionTimeout = serverSessionTimeout;
423     }
424 }