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, String protocol,
096 String algorithm, String keyStore,
097 String keyAlias, String trustStore) throws GeneralSecurityException {
098 // the keyStore is optional.
099 KeystoreInstance keyInstance = null;
100 if (keyStore != null) {
101 keyInstance = getKeystore(keyStore);
102 if (keyInstance.isKeystoreLocked()) {
103 throw new KeystoreIsLocked("Keystore '" + keyStore
104 + "' is locked; please use the keystore page in the admin console to unlock it");
105 }
106 if (keyInstance.isKeyLocked(keyAlias)) {
107 throw new KeystoreIsLocked("Key '" + keyAlias + "' in keystore '" + keyStore
108 + "' is locked; please use the keystore page in the admin console to unlock it");
109 }
110 }
111 KeystoreInstance trustInstance = trustStore == null ? null : getKeystore(trustStore);
112 if (trustInstance != null && trustInstance.isKeystoreLocked()) {
113 throw new KeystoreIsLocked("Keystore '" + trustStore
114 + "' is locked; please use the keystore page in the admin console to unlock it");
115 }
116
117 // OMG this hurts, but it causes ClassCastExceptions elsewhere unless
118 // done this way!
119 try {
120 /*
121 Class cls = loader.loadClass("javax.net.ssl.SSLContext");
122 Object ctx = cls.getMethod("getInstance", new Class[] { String.class }).invoke(null,
123 new Object[] { protocol });
124 Class kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
125 Class tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
126 Class src = loader.loadClass("java.security.SecureRandom");
127 cls.getMethod("init", new Class[] { kmc, tmc, src }).invoke(
128 ctx,
129 new Object[] { keyInstance == null ? null : keyInstance.getKeyManager(algorithm, keyAlias),
130 trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
131 new java.security.SecureRandom() });
132 Object result = cls.getMethod("getSocketFactory", new Class[0]).invoke(ctx, new Object[0]);
133 return (SSLSocketFactory) result;
134 */
135 SSLContext context;
136 if (provider == null) {
137 context = SSLContext.getInstance(protocol);
138 } else {
139 context = SSLContext.getInstance(protocol, provider);
140 }
141 context.init(keyInstance == null ? null : keyInstance.getKeyManager(algorithm, keyAlias),
142 trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
143 new SecureRandom());
144 return context.getSocketFactory();
145 } catch (Exception e) {
146 log.error("Unable to dynamically load", e);
147 return null;
148 }
149 }
150
151 /**
152 * Gets a ServerSocketFactory using one Keystore to access the private key
153 * and another to provide the list of trusted certificate authorities.
154 *
155 * @param provider
156 * The SSL provider to use, or null for the default
157 * @param protocol
158 * The SSL protocol to use
159 * @param algorithm
160 * The SSL algorithm to use
161 * @param keyStore
162 * The key keystore name as provided by listKeystores. The
163 * KeystoreInstance for this keystore must be unlocked.
164 * @param keyAlias
165 * The name of the private key in the keystore. The
166 * KeystoreInstance for this keystore must have unlocked this
167 * key.
168 * @param trustStore
169 * The trust keystore name as provided by listKeystores. The
170 * KeystoreInstance for this keystore must have unlocked this
171 * key.
172 * @param loader
173 * The class loader used to resolve factory classes.
174 *
175 * @throws KeystoreIsLocked
176 * Occurs when the requested key keystore cannot be used because
177 * it has not been unlocked.
178 * @throws KeyIsLocked
179 * Occurs when the requested private key in the key keystore
180 * cannot be used because it has not been unlocked.
181 */
182 public SSLServerSocketFactory createSSLServerFactory(String provider, String protocol,
183 String algorithm, String keyStore,
184 String keyAlias, String trustStore) throws GeneralSecurityException {
185 KeystoreInstance keyInstance = getKeystore(keyStore);
186 if (keyInstance.isKeystoreLocked()) {
187 throw new KeystoreIsLocked("Keystore '" + keyStore
188 + "' is locked; please use the keystore page in the admin console to unlock it");
189 }
190 if (keyInstance.isKeyLocked(keyAlias)) {
191 throw new KeystoreIsLocked("Key '" + keyAlias + "' in keystore '" + keyStore
192 + "' is locked; please use the keystore page in the admin console to unlock it");
193 }
194 KeystoreInstance trustInstance = trustStore == null ? null : getKeystore(trustStore);
195 if (trustInstance != null && trustInstance.isKeystoreLocked()) {
196 throw new KeystoreIsLocked("Keystore '" + trustStore
197 + "' is locked; please use the keystore page in the admin console to unlock it");
198 }
199
200 // OMG this hurts, but it causes ClassCastExceptions elsewhere unless
201 // done this way!
202 try {
203 /*
204 Class cls = loader.loadClass("javax.net.ssl.SSLContext");
205 Object ctx = cls.getMethod("getInstance", new Class[] { String.class }).invoke(null,
206 new Object[] { protocol });
207 Class kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
208 Class tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
209 Class src = loader.loadClass("java.security.SecureRandom");
210 cls.getMethod("init", new Class[] { kmc, tmc, src }).invoke(
211 ctx,
212 new Object[] { keyInstance.getKeyManager(algorithm, keyAlias),
213 trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
214 new java.security.SecureRandom() });
215 Object result = cls.getMethod("getServerSocketFactory", new Class[0]).invoke(ctx, new Object[0]);
216 return (SSLServerSocketFactory) result;
217 */
218 SSLContext context;
219 if (provider == null) {
220 context = SSLContext.getInstance(protocol);
221 } else {
222 context = SSLContext.getInstance(protocol, provider);
223 }
224 context.init(keyInstance == null ? null : keyInstance.getKeyManager(algorithm, keyAlias),
225 trustInstance == null ? null : trustInstance.getTrustManager(algorithm),
226 new SecureRandom());
227 return context.getServerSocketFactory();
228 } catch (Exception e) {
229 log.error("Unable to dynamically load", e);
230 return null;
231 }
232 }
233
234 public KeystoreInstance getKeystore(String name) {
235 if (keystores != null) {
236 for (int i = 0; i < keystores.length; i++) {
237 if (name.equals(keystores[i].getName())) {
238 return keystores[i];
239 }
240 }
241 }
242 return null;
243 }
244
245 }