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.integration.spring.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.SSLContext;
28  import javax.net.ssl.TrustManager;
29  import javax.net.ssl.TrustManagerFactory;
30  import javax.net.ssl.ManagerFactoryParameters;
31  
32  import org.springframework.beans.factory.config.AbstractFactoryBean;
33  import org.springframework.util.Assert;
34  
35  /**
36   * Spring {@link org.springframework.beans.factory.FactoryBean} implementation 
37   * which makes it possible to configure {@link javax.net.ssl.SSLContext} 
38   * instances using Spring.
39   * <p>
40   * If no properties are set the returned {@link javax.net.ssl.SSLContext} will
41   * be equivalent to what the following creates:
42   * <pre>
43   *      SSLContext c = SSLContext.getInstance( "TLS" );
44   *      c.init( null, null, null );
45   * </pre>
46   * </p>
47   * <p>
48   * Use the properties prefixed with <code>keyManagerFactory</code> to control
49   * the creation of the {@link javax.net.ssl.KeyManager} to be used.
50   * </p>
51   * <p>
52   * Use the properties prefixed with <code>trustManagerFactory</code> to control
53   * the creation of the {@link javax.net.ssl.TrustManagerFactory} to be used.
54   * </p>
55   *
56   * @author The Apache Directory Project (mina-dev@directory.apache.org)
57   * @version $Rev: 555855 $, $Date: 2007-07-13 05:19:00 +0200 (Fri, 13 Jul 2007) $
58   */
59  public class SSLContextFactoryBean extends AbstractFactoryBean {
60      private String protocol = "TLS";
61  
62      private String provider = null;
63  
64      private SecureRandom secureRandom = null;
65  
66      private KeyStore keyManagerFactoryKeyStore = null;
67  
68      private char[] keyManagerFactoryKeyStorePassword = null;
69  
70      private KeyManagerFactory keyManagerFactory = null;
71  
72      private String keyManagerFactoryAlgorithm = null;
73  
74      private String keyManagerFactoryProvider = null;
75  
76      private boolean keyManagerFactoryAlgorithmUseDefault = false;
77  
78      private KeyStore trustManagerFactoryKeyStore = null;
79  
80      private TrustManagerFactory trustManagerFactory = null;
81  
82      private String trustManagerFactoryAlgorithm = null;
83  
84      private String trustManagerFactoryProvider = null;
85  
86      private boolean trustManagerFactoryAlgorithmUseDefault = false;
87  
88      private ManagerFactoryParameters trustManagerFactoryParameters = null;
89  
90      protected Object createInstance() throws Exception {
91          KeyManagerFactory kmf = this.keyManagerFactory;
92          TrustManagerFactory tmf = this.trustManagerFactory;
93  
94          if (kmf == null) {
95              String algorithm = keyManagerFactoryAlgorithm;
96              if (algorithm == null && keyManagerFactoryAlgorithmUseDefault) {
97                  algorithm = KeyManagerFactory.getDefaultAlgorithm();
98              }
99              if (algorithm != null) {
100                 if (keyManagerFactoryProvider == null) {
101                     kmf = KeyManagerFactory.getInstance(algorithm);
102                 } else {
103                     kmf = KeyManagerFactory.getInstance(algorithm,
104                             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,
119                             trustManagerFactoryProvider);
120                 }
121             }
122         }
123 
124         KeyManager[] keyManagers = null;
125         if (kmf != null) {
126             kmf.init(keyManagerFactoryKeyStore,
127                     keyManagerFactoryKeyStorePassword);
128             keyManagers = kmf.getKeyManagers();
129         }
130         TrustManager[] trustManagers = null;
131         if (tmf != null) {
132             if (trustManagerFactoryParameters != null) {
133                 tmf.init(trustManagerFactoryParameters);
134             } else {
135                 tmf.init(trustManagerFactoryKeyStore);
136             }
137             trustManagers = tmf.getTrustManagers();
138         }
139 
140         SSLContext context = null;
141         if (provider == null) {
142             context = SSLContext.getInstance(protocol);
143         } else {
144             context = SSLContext.getInstance(protocol, provider);
145         }
146 
147         context.init(keyManagers, trustManagers, secureRandom);
148 
149         return context;
150     }
151 
152     public Class getObjectType() {
153         return SSLContext.class;
154     }
155 
156     /**
157      * Sets the protocol to use when creating the {@link SSLContext}. The
158      * default is <code>TLS</code>.
159      * 
160      * @param protocol the name of the protocol.
161      * @throws IllegalArgumentException if the specified value is 
162      *         <code>null</code>.
163      */
164     public void setProtocol(String protocol) {
165         Assert.notNull(protocol, "Property 'protocol' may not be null");
166         this.protocol = protocol;
167     }
168 
169     /**
170      * If this is set to <code>true</code> while no {@link KeyManagerFactory}
171      * has been set using {@link #setKeyManagerFactory(KeyManagerFactory)} and
172      * no algorithm has been set using 
173      * {@link #setKeyManagerFactoryAlgorithm(String)} the default algorithm
174      * return by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used.
175      * 
176      * @param useDefault <code>true</code> or <code>false</code>.
177      */
178     public void setKeyManagerFactoryAlgorithmUseDefault(boolean useDefault) {
179         this.keyManagerFactoryAlgorithmUseDefault = useDefault;
180     }
181 
182     /**
183      * If this is set to <code>true</code> while no {@link TrustManagerFactory}
184      * has been set using {@link #setTrustManagerFactory(TrustManagerFactory)} and
185      * no algorithm has been set using 
186      * {@link #setTrustManagerFactoryAlgorithm(String)} the default algorithm
187      * return by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used.
188      * 
189      * @param useDefault <code>true</code> or <code>false</code>.
190      */
191     public void setTrustManagerFactoryAlgorithmUseDefault(boolean useDefault) {
192         this.trustManagerFactoryAlgorithmUseDefault = useDefault;
193     }
194 
195     /**
196      * Sets the {@link KeyManagerFactory} to use. If this is set the properties
197      * which are used by this factory bean to create a {@link KeyManagerFactory}
198      * will all be ignored.
199      * 
200      * @param factory the factory.
201      */
202     public void setKeyManagerFactory(KeyManagerFactory factory) {
203         this.keyManagerFactory = factory;
204     }
205 
206     /**
207      * Sets the algorithm to use when creating the {@link KeyManagerFactory} 
208      * using {@link KeyManagerFactory#getInstance(java.lang.String)} or
209      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
210      * <p>
211      * This property will be ignored if a {@link KeyManagerFactory} has been
212      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
213      * </p>
214      * <p>
215      * If this property isn't set while no {@link KeyManagerFactory} has been 
216      * set using {@link #setKeyManagerFactory(KeyManagerFactory)} and 
217      * {@link #setKeyManagerFactoryAlgorithmUseDefault(boolean)} has been set to 
218      * <code>true</code> the value returned 
219      * by {@link KeyManagerFactory#getDefaultAlgorithm()} will be used instead.
220      * </p> 
221      * 
222      * @param algorithm the algorithm to use.
223      */
224     public void setKeyManagerFactoryAlgorithm(String algorithm) {
225         this.keyManagerFactoryAlgorithm = algorithm;
226     }
227 
228     /**
229      * Sets the provider to use when creating the {@link KeyManagerFactory} 
230      * using 
231      * {@link KeyManagerFactory#getInstance(java.lang.String, java.lang.String)}.
232      * <p>
233      * This property will be ignored if a {@link KeyManagerFactory} has been
234      * set directly using {@link #setKeyManagerFactory(KeyManagerFactory)}.
235      * </p>
236      * <p>
237      * If this property isn't set and no {@link KeyManagerFactory} has been set
238      * using {@link #setKeyManagerFactory(KeyManagerFactory)} 
239      * {@link KeyManagerFactory#getInstance(java.lang.String)} will be used
240      * to create the {@link KeyManagerFactory}.
241      * </p> 
242      * 
243      * @param provider the name of the provider.
244      */
245     public void setKeyManagerFactoryProvider(String provider) {
246         this.keyManagerFactoryProvider = provider;
247     }
248 
249     /**
250      * Sets the {@link KeyStore} which will be used in the call to 
251      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
252      * the {@link SSLContext} is created. 
253      * 
254      * @param keyStore the key store.
255      */
256     public void setKeyManagerFactoryKeyStore(KeyStore keyStore) {
257         this.keyManagerFactoryKeyStore = keyStore;
258     }
259 
260     /**
261      * Sets the password which will be used in the call to 
262      * {@link KeyManagerFactory#init(java.security.KeyStore, char[])} when
263      * the {@link SSLContext} is created. 
264      * 
265      * @param password the password. Use <code>null</code> to disable password.
266      */
267     public void setKeyManagerFactoryKeyStorePassword(String password) {
268         if (password != null) {
269             this.keyManagerFactoryKeyStorePassword = password.toCharArray();
270         } else {
271             this.keyManagerFactoryKeyStorePassword = null;
272         }
273     }
274 
275     /**
276      * Sets the {@link TrustManagerFactory} to use. If this is set the properties
277      * which are used by this factory bean to create a {@link TrustManagerFactory}
278      * will all be ignored.
279      * 
280      * @param factory the factory.
281      */
282     public void setTrustManagerFactory(TrustManagerFactory factory) {
283         this.trustManagerFactory = factory;
284     }
285 
286     /**
287      * Sets the algorithm to use when creating the {@link TrustManagerFactory} 
288      * using {@link TrustManagerFactory#getInstance(java.lang.String)} or
289      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
290      * <p>
291      * This property will be ignored if a {@link TrustManagerFactory} has been
292      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
293      * </p>
294      * <p>
295      * If this property isn't set while no {@link TrustManagerFactory} has been 
296      * set using {@link #setTrustManagerFactory(TrustManagerFactory)} and 
297      * {@link #setTrustManagerFactoryAlgorithmUseDefault(boolean)} has been set to 
298      * <code>true</code> the value returned 
299      * by {@link TrustManagerFactory#getDefaultAlgorithm()} will be used instead.
300      * </p> 
301      * 
302      * @param algorithm the algorithm to use.
303      */
304     public void setTrustManagerFactoryAlgorithm(String algorithm) {
305         this.trustManagerFactoryAlgorithm = algorithm;
306     }
307 
308     /**
309      * Sets the {@link KeyStore} which will be used in the call to 
310      * {@link TrustManagerFactory#init(java.security.KeyStore)} when
311      * the {@link SSLContext} is created. 
312      * <p>
313      * This property will be ignored if {@link ManagerFactoryParameters} has been
314      * set directly using {@link #setTrustManagerFactoryParameters(ManagerFactoryParameters)}.
315      * </p>
316      * 
317      * @param keyStore the key store.
318      */
319     public void setTrustManagerFactoryKeyStore(KeyStore keyStore) {
320         this.trustManagerFactoryKeyStore = keyStore;
321     }
322 
323     /**
324      * Sets the {@link ManagerFactoryParameters} which will be used in the call to
325      * {@link TrustManagerFactory#init(javax.net.ssl.ManagerFactoryParameters)} when
326      * the {@link SSLContext} is created.
327      *  
328      * @param parameters describing provider-specific trust material.
329      */
330     public void setTrustManagerFactoryParameters(
331             ManagerFactoryParameters parameters) {
332         this.trustManagerFactoryParameters = parameters;
333     }
334 
335     /**
336      * Sets the provider to use when creating the {@link TrustManagerFactory} 
337      * using 
338      * {@link TrustManagerFactory#getInstance(java.lang.String, java.lang.String)}.
339      * <p>
340      * This property will be ignored if a {@link TrustManagerFactory} has been
341      * set directly using {@link #setTrustManagerFactory(TrustManagerFactory)}.
342      * </p>
343      * <p>
344      * If this property isn't set and no {@link TrustManagerFactory} has been set
345      * using {@link #setTrustManagerFactory(TrustManagerFactory)} 
346      * {@link TrustManagerFactory#getInstance(java.lang.String)} will be used
347      * to create the {@link TrustManagerFactory}.
348      * </p> 
349      * 
350      * @param provider the name of the provider.
351      */
352     public void setTrustManagerFactoryProvider(String provider) {
353         this.trustManagerFactoryProvider = provider;
354     }
355 
356     /**
357      * Sets the {@link SecureRandom} to use when initializing the 
358      * {@link SSLContext}. The JVM's default will be used if this isn't set.
359      * 
360      * @param secureRandom the {@link SecureRandom} or <code>null</code> if the 
361      *        JVM's default should be used.
362      * @see SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
363      */
364     public void setSecureRandom(SecureRandom secureRandom) {
365         this.secureRandom = secureRandom;
366     }
367 
368 }