001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.servicemix.jbi.security.keystore.impl;
018:
019: import java.security.GeneralSecurityException;
020: import java.security.SecureRandom;
021:
022: import javax.net.ssl.SSLContext;
023: import javax.net.ssl.SSLServerSocketFactory;
024: import javax.net.ssl.SSLSocketFactory;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.servicemix.jbi.security.keystore.KeystoreInstance;
029: import org.apache.servicemix.jbi.security.keystore.KeystoreIsLocked;
030: import org.apache.servicemix.jbi.security.keystore.KeystoreManager;
031:
032: /**
033: *
034: * @org.apache.xbean.XBean element="keystoreManager"
035: *
036: */
037: public class BaseKeystoreManager implements KeystoreManager {
038:
039: protected final Log log = LogFactory.getLog(getClass());
040:
041: protected KeystoreInstance[] keystores;
042:
043: /**
044: * @return the keystores
045: */
046: public KeystoreInstance[] getKeystores() {
047: return keystores;
048: }
049:
050: /**
051: * @param keystores the keystores to set
052: */
053: public void setKeystores(KeystoreInstance[] keystores) {
054: this .keystores = keystores;
055: }
056:
057: /**
058: * Gets a SocketFactory using one Keystore to access the private key and
059: * another to provide the list of trusted certificate authorities.
060: *
061: * @param provider
062: * The SSL provider to use, or null for the default
063: * @param protocol
064: * The SSL protocol to use
065: * @param algorithm
066: * The SSL algorithm to use
067: * @param keyStore
068: * The key keystore name as provided by listKeystores. The
069: * KeystoreInstance for this keystore must be unlocked.
070: * @param keyAlias
071: * The name of the private key in the keystore. The
072: * KeystoreInstance for this keystore must have unlocked this
073: * key.
074: * @param trustStore
075: * The trust keystore name as provided by listKeystores. The
076: * KeystoreInstance for this keystore must have unlocked this
077: * key.
078: * @param loader
079: * The class loader used to resolve factory classes.
080: *
081: * @return A created SSLSocketFactory item created from the KeystoreManager.
082: * @throws GeneralSecurityException
083: * @throws KeystoreIsLocked
084: * Occurs when the requested key keystore cannot be used because
085: * it has not been unlocked.
086: * @throws KeyIsLocked
087: * Occurs when the requested private key in the key keystore
088: * cannot be used because it has not been unlocked.
089: * @throws NoSuchAlgorithmException
090: * @throws UnrecoverableKeyException
091: * @throws KeyStoreException
092: * @throws KeyManagementException
093: * @throws NoSuchProviderException
094: */
095: public SSLSocketFactory createSSLFactory(String provider,
096: String protocol, String algorithm, String keyStore,
097: String keyAlias, String trustStore)
098: throws GeneralSecurityException {
099: // the keyStore is optional.
100: KeystoreInstance keyInstance = null;
101: if (keyStore != null) {
102: keyInstance = getKeystore(keyStore);
103: if (keyInstance.isKeystoreLocked()) {
104: throw new KeystoreIsLocked(
105: "Keystore '"
106: + keyStore
107: + "' is locked; please use the keystore page in the admin console to unlock it");
108: }
109: if (keyInstance.isKeyLocked(keyAlias)) {
110: throw new KeystoreIsLocked(
111: "Key '"
112: + keyAlias
113: + "' in keystore '"
114: + keyStore
115: + "' is locked; please use the keystore page in the admin console to unlock it");
116: }
117: }
118: KeystoreInstance trustInstance = trustStore == null ? null
119: : getKeystore(trustStore);
120: if (trustInstance != null && trustInstance.isKeystoreLocked()) {
121: throw new KeystoreIsLocked(
122: "Keystore '"
123: + trustStore
124: + "' is locked; please use the keystore page in the admin console to unlock it");
125: }
126:
127: // OMG this hurts, but it causes ClassCastExceptions elsewhere unless
128: // done this way!
129: try {
130: /*
131: Class cls = loader.loadClass("javax.net.ssl.SSLContext");
132: Object ctx = cls.getMethod("getInstance", new Class[] { String.class }).invoke(null,
133: new Object[] { protocol });
134: Class kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
135: Class tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
136: Class src = loader.loadClass("java.security.SecureRandom");
137: cls.getMethod("init", new Class[] { kmc, tmc, src }).invoke(
138: ctx,
139: new Object[] { keyInstance == null ? null : keyInstance.getKeyManager(algorithm, keyAlias),
140: trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
141: new java.security.SecureRandom() });
142: Object result = cls.getMethod("getSocketFactory", new Class[0]).invoke(ctx, new Object[0]);
143: return (SSLSocketFactory) result;
144: */
145: SSLContext context;
146: if (provider == null) {
147: context = SSLContext.getInstance(protocol);
148: } else {
149: context = SSLContext.getInstance(protocol, provider);
150: }
151: context.init(keyInstance == null ? null : keyInstance
152: .getKeyManager(algorithm, keyAlias),
153: trustInstance == null ? null : trustInstance
154: .getTrustManager(algorithm),
155: new SecureRandom());
156: return context.getSocketFactory();
157: } catch (Exception e) {
158: log.error("Unable to dynamically load", e);
159: return null;
160: }
161: }
162:
163: /**
164: * Gets a ServerSocketFactory using one Keystore to access the private key
165: * and another to provide the list of trusted certificate authorities.
166: *
167: * @param provider
168: * The SSL provider to use, or null for the default
169: * @param protocol
170: * The SSL protocol to use
171: * @param algorithm
172: * The SSL algorithm to use
173: * @param keyStore
174: * The key keystore name as provided by listKeystores. The
175: * KeystoreInstance for this keystore must be unlocked.
176: * @param keyAlias
177: * The name of the private key in the keystore. The
178: * KeystoreInstance for this keystore must have unlocked this
179: * key.
180: * @param trustStore
181: * The trust keystore name as provided by listKeystores. The
182: * KeystoreInstance for this keystore must have unlocked this
183: * key.
184: * @param loader
185: * The class loader used to resolve factory classes.
186: *
187: * @throws KeystoreIsLocked
188: * Occurs when the requested key keystore cannot be used because
189: * it has not been unlocked.
190: * @throws KeyIsLocked
191: * Occurs when the requested private key in the key keystore
192: * cannot be used because it has not been unlocked.
193: */
194: public SSLServerSocketFactory createSSLServerFactory(
195: String provider, String protocol, String algorithm,
196: String keyStore, String keyAlias, String trustStore)
197: throws GeneralSecurityException {
198: KeystoreInstance keyInstance = getKeystore(keyStore);
199: if (keyInstance.isKeystoreLocked()) {
200: throw new KeystoreIsLocked(
201: "Keystore '"
202: + keyStore
203: + "' is locked; please use the keystore page in the admin console to unlock it");
204: }
205: if (keyInstance.isKeyLocked(keyAlias)) {
206: throw new KeystoreIsLocked(
207: "Key '"
208: + keyAlias
209: + "' in keystore '"
210: + keyStore
211: + "' is locked; please use the keystore page in the admin console to unlock it");
212: }
213: KeystoreInstance trustInstance = trustStore == null ? null
214: : getKeystore(trustStore);
215: if (trustInstance != null && trustInstance.isKeystoreLocked()) {
216: throw new KeystoreIsLocked(
217: "Keystore '"
218: + trustStore
219: + "' is locked; please use the keystore page in the admin console to unlock it");
220: }
221:
222: // OMG this hurts, but it causes ClassCastExceptions elsewhere unless
223: // done this way!
224: try {
225: /*
226: Class cls = loader.loadClass("javax.net.ssl.SSLContext");
227: Object ctx = cls.getMethod("getInstance", new Class[] { String.class }).invoke(null,
228: new Object[] { protocol });
229: Class kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
230: Class tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
231: Class src = loader.loadClass("java.security.SecureRandom");
232: cls.getMethod("init", new Class[] { kmc, tmc, src }).invoke(
233: ctx,
234: new Object[] { keyInstance.getKeyManager(algorithm, keyAlias),
235: trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
236: new java.security.SecureRandom() });
237: Object result = cls.getMethod("getServerSocketFactory", new Class[0]).invoke(ctx, new Object[0]);
238: return (SSLServerSocketFactory) result;
239: */
240: SSLContext context;
241: if (provider == null) {
242: context = SSLContext.getInstance(protocol);
243: } else {
244: context = SSLContext.getInstance(protocol, provider);
245: }
246: context.init(keyInstance == null ? null : keyInstance
247: .getKeyManager(algorithm, keyAlias),
248: trustInstance == null ? null : trustInstance
249: .getTrustManager(algorithm),
250: new SecureRandom());
251: return context.getServerSocketFactory();
252: } catch (Exception e) {
253: log.error("Unable to dynamically load", e);
254: return null;
255: }
256: }
257:
258: public KeystoreInstance getKeystore(String name) {
259: if (keystores != null) {
260: for (int i = 0; i < keystores.length; i++) {
261: if (name.equals(keystores[i].getName())) {
262: return keystores[i];
263: }
264: }
265: }
266: return null;
267: }
268:
269: }
|