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 12:19:00 +0900 (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 }