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: 599286 $, $Date: 2007-11-28 22:56:19 -0700 (Wed, 28 Nov 2007) $
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 = false;
66      private KeyStore trustManagerFactoryKeyStore = null;
67      private TrustManagerFactory trustManagerFactory = null;
68      private String trustManagerFactoryAlgorithm = null;
69      private String trustManagerFactoryProvider = null;
70      private boolean trustManagerFactoryAlgorithmUseDefault = false;
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      *
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      *
203      * @param useDefault <code>true</code> or <code>false</code>.
204      */
205     public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
206         this.trustManagerFactoryAlgorithmUseDefault = useDefault;
207     }
208 
209     /**
210      * Sets the {@link KeyManagerFactory} to use. If this is set the properties
211      * which are used by this factory bean to create a {@link KeyManagerFactory}
212      * will all be ignored.
213      *
214      * @param factory the factory.
215      */
216     public void setKeyManagerFactory(KeyManagerFactory factory) {
217         this.keyManagerFactory = factory;
218     }
219 
220     /**
221      * Sets the algorithm to use when creating the {@link KeyManagerFactory}
222      * using {@link KeyManagerFactory#getInstance(java.lang.String)} or
223      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
224      * <p>
225      * This property will be ignored if a {@link KeyManagerFactory} has been
226      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
227      * </p>
228      * <p>
229      * If this property isn't set while no {@link KeyManagerFactory} has been
230      * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
231      * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to
232      * <code>true</code> the value returned
233      * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
234      * </p>
235      *
236      * @param algorithm the algorithm to use.
237      */
238     public void setKeyManagerFactoryAlgorithm(String algorithm) {
239         this.keyManagerFactoryAlgorithm = algorithm;
240     }
241 
242     /**
243      * Sets the provider to use when creating the {@link KeyManagerFactory}
244      * using
245      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
246      * <p>
247      * This property will be ignored if a {@link KeyManagerFactory} has been
248      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
249      * </p>
250      * <p>
251      * If this property isn't set and no {@link KeyManagerFactory} has been set
252      * using {@link #setKeyManagerFactory(KeyManagerFactory)}
253      * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
254      * to create the {@link KeyManagerFactory}.
255      * </p>
256      *
257      * @param provider the name of the provider.
258      */
259     public void setKeyManagerFactoryProvider(String provider) {
260         this.keyManagerFactoryProvider = provider;
261     }
262 
263     /**
264      * Sets the {@link KeyStore} which will be used in the call to
265      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
266      * the {@link SSLContext} is created.
267      *
268      * @param keyStore the key store.
269      */
270     public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
271         this.keyManagerFactoryKeyStore = keyStore;
272     }
273 
274     /**
275      * Sets the password which will be used in the call to
276      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
277      * the {@link SSLContext} is created.
278      *
279      * @param password the password. Use <code>null</code> to disable password.
280      */
281     public void setKeyManagerFactoryKeyStorePassword(String password) {
282         if (password != null) {
283             this.keyManagerFactoryKeyStorePassword = password.toCharArray();
284         } else {
285             this.keyManagerFactoryKeyStorePassword = null;
286         }
287     }
288 
289     /**
290      * Sets the {@link TrustManagerFactory} to use. If this is set the
291      * properties which are used by this factory bean to create a
292      * {@link TrustManagerFactory} will all be ignored.
293      *
294      * @param factory
295      *            the factory.
296      */
297     public void setTrustManagerFactory(TrustManagerFactory factory) {
298         this.trustManagerFactory = factory;
299     }
300 
301     /**
302      * Sets the algorithm to use when creating the {@link TrustManagerFactory}
303      * using {@link TrustManagerFactory#getInstance(java.lang.String)} or
304      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
305      * <p>
306      * This property will be ignored if a {@link TrustManagerFactory} has been
307      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
308      * </p>
309      * <p>
310      * If this property isn't set while no {@link TrustManagerFactory} has been
311      * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
312      * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to
313      * <code>true</code> the value returned
314      * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
315      * </p>
316      *
317      * @param algorithm the algorithm to use.
318      */
319     public void setTrustManagerFactoryAlgorithm(String algorithm) {
320         this.trustManagerFactoryAlgorithm = algorithm;
321     }
322 
323     /**
324      * Sets the {@link KeyStore} which will be used in the call to
325      * {@link TrustManagerFactory#init(java.security.KeyStore)} when
326      * the {@link SSLContext} is created.
327      * <p>
328      * This property will be ignored if {@link ManagerFactoryParameters} has been
329      * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
330      * </p>
331      *
332      * @param keyStore the key store.
333      */
334     public void setTrustManagerFactoryKeyStore(KeyStore keyStore) {
335         this.trustManagerFactoryKeyStore = keyStore;
336     }
337 
338     /**
339      * Sets the {@link ManagerFactoryParameters} which will be used in the call to
340      * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when
341      * the {@link SSLContext} is created.
342      *
343      * @param parameters describing provider-specific trust material.
344      */
345     public void setTrustManagerFactoryParameters(
346             ManagerFactoryParameters parameters) {
347         this.trustManagerFactoryParameters = parameters;
348     }
349 
350     /**
351      * Sets the provider to use when creating the {@link TrustManagerFactory}
352      * using
353      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
354      * <p>
355      * This property will be ignored if a {@link TrustManagerFactory} has been
356      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
357      * </p>
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      * </p>
364      *
365      * @param provider the name of the provider.
366      */
367     public void setTrustManagerFactoryProvider(String provider) {
368         this.trustManagerFactoryProvider = provider;
369     }
370 
371     /**
372      * Sets the {@link SecureRandom} to use when initializing the
373      * {@link SSLContext}. The JVM's default will be used if this isn't set.
374      *
375      * @param secureRandom the {@link SecureRandom} or <code>null</code> if the
376      *        JVM's default should be used.
377      * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
378      */
379     public void setSecureRandom(SecureRandom secureRandom) {
380         this.secureRandom = secureRandom;
381     }
382 
383     /**
384      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in client mode.
385      *
386      * @param size the new session cache size limit; zero means there is no limit.
387      * @see SSLSessionContext#setSessionCacheSize(int size)
388      */
389     public void setClientSessionCacheSize(int size) {
390         this.clientSessionCacheSize = size;
391     }
392 
393     /**
394      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in client mode.
395      *
396      * @param seconds the new session timeout limit in seconds; zero means there is no limit.
397      * @see SSLSessionContext#setSessionTimeout(int seconds)
398      */
399     public void setClientSessionTimeout(int seconds) {
400         this.clientSessionTimeout = seconds;
401     }
402 
403     /**
404      * Sets the SSLSession cache size for the {@link SSLSessionContext} for use in server mode.
405      *
406      * @param serverSessionCacheSize the new session cache size limit; zero means there is no limit.
407      * @see SSLSessionContext#setSessionCacheSize(int)
408      */
409     public void setServerSessionCacheSize(int serverSessionCacheSize) {
410         this.serverSessionCacheSize = serverSessionCacheSize;
411     }
412 
413     /**
414      * Set the SSLSession timeout limit for the {@link SSLSessionContext} for use in server mode.
415      *
416      * @param serverSessionTimeout the new session timeout limit in seconds; zero means there is no limit.
417      * @see SSLSessionContext#setSessionTimeout(int)
418      */
419     public void setServerSessionTimeout(int serverSessionTimeout) {
420         this.serverSessionTimeout = serverSessionTimeout;
421     }
422 }