KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > keystore > FileKeystoreManager


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.geronimo.security.keystore;
18
19 import java.io.BufferedOutputStream JavaDoc;
20 import java.io.File JavaDoc;
21 import java.io.FileOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.math.BigInteger JavaDoc;
25 import java.net.URI JavaDoc;
26 import java.net.URISyntaxException JavaDoc;
27 import java.security.KeyManagementException JavaDoc;
28 import java.security.KeyStore JavaDoc;
29 import java.security.KeyStoreException JavaDoc;
30 import java.security.NoSuchAlgorithmException JavaDoc;
31 import java.security.NoSuchProviderException JavaDoc;
32 import java.security.PrivateKey JavaDoc;
33 import java.security.PublicKey JavaDoc;
34 import java.security.UnrecoverableKeyException JavaDoc;
35 import java.security.cert.CertificateException JavaDoc;
36 import java.security.cert.X509Certificate JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.Collection JavaDoc;
39 import java.util.Date JavaDoc;
40 import java.util.Hashtable JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Vector JavaDoc;
44 import javax.net.ssl.SSLServerSocketFactory;
45 import javax.net.ssl.SSLSocketFactory;
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.apache.geronimo.gbean.AbstractName;
49 import org.apache.geronimo.gbean.GBeanData;
50 import org.apache.geronimo.gbean.GBeanInfo;
51 import org.apache.geronimo.gbean.GBeanInfoBuilder;
52 import org.apache.geronimo.gbean.GBeanLifecycle;
53 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
54 import org.apache.geronimo.kernel.Kernel;
55 import org.apache.geronimo.kernel.config.ConfigurationUtil;
56 import org.apache.geronimo.kernel.config.EditableConfigurationManager;
57 import org.apache.geronimo.kernel.config.InvalidConfigException;
58 import org.apache.geronimo.management.geronimo.KeyIsLocked;
59 import org.apache.geronimo.management.geronimo.KeystoreException;
60 import org.apache.geronimo.management.geronimo.KeystoreInstance;
61 import org.apache.geronimo.management.geronimo.KeystoreIsLocked;
62 import org.apache.geronimo.management.geronimo.KeystoreManager;
63 import org.apache.geronimo.system.serverinfo.ServerInfo;
64 import org.apache.geronimo.util.jce.X509Principal;
65 import org.apache.geronimo.util.jce.X509V1CertificateGenerator;
66
67 /**
68  * An implementation of KeystoreManager that assumes every file in a specified
69  * directory is a keystore.
70  *
71  * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
72  */

73 public class FileKeystoreManager implements KeystoreManager, GBeanLifecycle {
74     private static final Log log = LogFactory.getLog(FileKeystoreManager.class);
75     private File JavaDoc directory;
76     private ServerInfo serverInfo;
77     private URI JavaDoc configuredDir;
78     private Collection JavaDoc keystores;
79     private Kernel kernel;
80
81     public FileKeystoreManager(URI JavaDoc keystoreDir, ServerInfo serverInfo, Collection JavaDoc keystores, Kernel kernel) {
82         configuredDir = keystoreDir;
83         this.serverInfo = serverInfo;
84         this.keystores = keystores;
85         this.kernel = kernel;
86     }
87
88     public void doStart() throws Exception JavaDoc {
89         URI JavaDoc rootURI;
90         if (serverInfo != null) {
91             rootURI = serverInfo.resolve(configuredDir);
92         } else {
93             rootURI = configuredDir;
94         }
95         if (!rootURI.getScheme().equals("file")) {
96             throw new IllegalStateException JavaDoc("FileKeystoreManager must have a root that's a local directory (not " + rootURI + ")");
97         }
98         directory = new File JavaDoc(rootURI);
99         if (!directory.exists() || !directory.isDirectory() || !directory.canRead()) {
100             throw new IllegalStateException JavaDoc("FileKeystoreManager must have a root that's a valid readable directory (not " + directory.getAbsolutePath() + ")");
101         }
102         log.debug("Keystore directory is " + directory.getAbsolutePath());
103     }
104
105     public void doStop() throws Exception JavaDoc {
106     }
107
108     public void doFail() {
109     }
110
111     public String JavaDoc[] listKeystoreFiles() {
112         File JavaDoc[] files = directory.listFiles();
113         List JavaDoc list = new ArrayList JavaDoc();
114         for (int i = 0; i < files.length; i++) {
115             File JavaDoc file = files[i];
116             if(file.canRead() && !file.isDirectory()) {
117                 list.add(file.getName());
118             }
119         }
120         return (String JavaDoc[]) list.toArray(new String JavaDoc[list.size()]);
121     }
122
123     public KeystoreInstance[] getKeystores() {
124         String JavaDoc[] names = listKeystoreFiles();
125         KeystoreInstance[] result = new KeystoreInstance[names.length];
126         for (int i = 0; i < result.length; i++) {
127             result[i] = getKeystore(names[i]);
128             if(result[i] == null) {
129                 return null;
130             }
131         }
132         return result;
133     }
134
135     public KeystoreInstance getKeystore(String JavaDoc name) {
136         for (Iterator JavaDoc it = keystores.iterator(); it.hasNext();) {
137             KeystoreInstance instance = (KeystoreInstance) it.next();
138             if(instance.getKeystoreName().equals(name)) {
139                 return instance;
140             }
141         }
142         File JavaDoc test = new File JavaDoc(directory, name);
143         if(!test.exists() || !test.canRead()) {
144             throw new IllegalArgumentException JavaDoc("Cannot access keystore "+test.getAbsolutePath()+"!");
145         }
146         AbstractName aName;
147         AbstractName myName = kernel.getAbstractNameFor(this);
148         aName = kernel.getNaming().createSiblingName(myName, name, NameFactory.KEYSTORE_INSTANCE);
149         GBeanData data = new GBeanData(aName, FileKeystoreInstance.getGBeanInfo());
150         try {
151             String JavaDoc path = configuredDir.toString();
152             if(!path.endsWith("/")) {
153                 path += "/";
154             }
155             data.setAttribute("keystorePath", new URI JavaDoc(path +name));
156         } catch (URISyntaxException JavaDoc e) {
157             throw new IllegalStateException JavaDoc("Can't resolve keystore path: "+e.getMessage());
158         }
159         data.setReferencePattern("ServerInfo", kernel.getAbstractNameFor(serverInfo));
160         data.setAttribute("keystoreName", name);
161         EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
162         if(mgr != null) {
163             try {
164                 mgr.addGBeanToConfiguration(myName.getArtifact(), data, true);
165                 return (KeystoreInstance) kernel.getProxyManager().createProxy(aName, KeystoreInstance.class);
166             } catch (InvalidConfigException e) {
167                 log.error("Should never happen", e);
168                 throw new IllegalStateException JavaDoc("Unable to add Keystore GBean ("+e.getMessage()+")");
169             } finally {
170                 ConfigurationUtil.releaseConfigurationManager(kernel, mgr);
171             }
172         } else {
173             log.warn("The ConfigurationManager in the kernel does not allow changes at runtime");
174             return null;
175         }
176     }
177
178     /**
179      * Gets a SocketFactory using one Keystore to access the private key
180      * and another to provide the list of trusted certificate authorities.
181      *
182      * @param provider The SSL provider to use, or null for the default
183      * @param protocol The SSL protocol to use
184      * @param algorithm The SSL algorithm to use
185      * @param trustStore The trust keystore name as provided by listKeystores.
186      * The KeystoreInstance for this keystore must have
187      * unlocked this key.
188      * @param loader The class loader used to resolve factory classes.
189      *
190      * @return A created SSLSocketFactory item created from the KeystoreManager.
191      * @throws KeystoreIsLocked
192      * Occurs when the requested key keystore cannot
193      * be used because it has not been unlocked.
194      * @throws KeyIsLocked
195      * Occurs when the requested private key in the key
196      * keystore cannot be used because it has not been
197      * unlocked.
198      * @throws NoSuchAlgorithmException
199      * @throws UnrecoverableKeyException
200      * @throws KeyStoreException
201      * @throws KeyManagementException
202      * @throws NoSuchProviderException
203      */

204     public SSLSocketFactory createSSLFactory(String JavaDoc provider, String JavaDoc protocol, String JavaDoc algorithm, String JavaDoc trustStore, ClassLoader JavaDoc loader) throws KeystoreException {
205         // typically, the keyStore and the keyAlias are not required if authentication is also not required.
206
return createSSLFactory(provider, protocol, algorithm, null, null, trustStore, loader);
207     }
208
209     /**
210      * Gets a SocketFactory using one Keystore to access the private key
211      * and another to provide the list of trusted certificate authorities.
212      *
213      * @param provider The SSL provider to use, or null for the default
214      * @param protocol The SSL protocol to use
215      * @param algorithm The SSL algorithm to use
216      * @param keyStore The key keystore name as provided by listKeystores. The
217      * KeystoreInstance for this keystore must be unlocked.
218      * @param keyAlias The name of the private key in the keystore. The
219      * KeystoreInstance for this keystore must have unlocked
220      * this key.
221      * @param trustStore The trust keystore name as provided by listKeystores.
222      * The KeystoreInstance for this keystore must have
223      * unlocked this key.
224      * @param loader The class loader used to resolve factory classes.
225      *
226      * @return A created SSLSocketFactory item created from the KeystoreManager.
227      * @throws KeystoreIsLocked
228      * Occurs when the requested key keystore cannot
229      * be used because it has not been unlocked.
230      * @throws KeyIsLocked
231      * Occurs when the requested private key in the key
232      * keystore cannot be used because it has not been
233      * unlocked.
234      * @throws KeystoreException
235      */

236     public SSLSocketFactory createSSLFactory(String JavaDoc provider, String JavaDoc protocol, String JavaDoc algorithm, String JavaDoc keyStore, String JavaDoc keyAlias, String JavaDoc trustStore, ClassLoader JavaDoc loader) throws KeystoreException {
237         // the keyStore is optional.
238
KeystoreInstance keyInstance = null;
239         if (keyStore != null) {
240             keyInstance = getKeystore(keyStore);
241             if(keyInstance.isKeystoreLocked()) {
242                 throw new KeystoreIsLocked("Keystore '"+keyStore+"' is locked; please use the keystore page in the admin console to unlock it");
243             }
244             if(keyInstance.isKeyLocked(keyAlias)) {
245                 throw new KeystoreIsLocked("Key '"+keyAlias+"' in keystore '"+keyStore+"' is locked; please use the keystore page in the admin console to unlock it");
246             }
247         }
248         KeystoreInstance trustInstance = trustStore == null ? null : getKeystore(trustStore);
249         if(trustInstance != null && trustInstance.isKeystoreLocked()) {
250             throw new KeystoreIsLocked("Keystore '"+trustStore+"' is locked; please use the keystore page in the admin console to unlock it");
251         }
252
253         // OMG this hurts, but it causes ClassCastExceptions elsewhere unless done this way!
254
try {
255             Class JavaDoc cls = loader.loadClass("javax.net.ssl.SSLContext");
256             Object JavaDoc ctx = cls.getMethod("getInstance", new Class JavaDoc[] {String JavaDoc.class}).invoke(null, new Object JavaDoc[]{protocol});
257             Class JavaDoc kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
258             Class JavaDoc tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
259             Class JavaDoc src = loader.loadClass("java.security.SecureRandom");
260             cls.getMethod("init", new Class JavaDoc[]{kmc, tmc, src}).invoke(ctx, new Object JavaDoc[]{
261                                                                             keyInstance == null ? null : keyInstance.getKeyManager(algorithm, keyAlias, null),
262                                                                             trustInstance == null ? null : trustInstance.getTrustManager(algorithm, null),
263                                                                             new java.security.SecureRandom JavaDoc()});
264             Object JavaDoc result = cls.getMethod("getSocketFactory", new Class JavaDoc[0]).invoke(ctx, new Object JavaDoc[0]);
265             return (SSLSocketFactory) result;
266         } catch (Exception JavaDoc e) {
267             throw new KeystoreException("Unable to create SSL Factory", e);
268         }
269     }
270
271     /**
272      * Gets a ServerSocketFactory using one Keystore to access the private key
273      * and another to provide the list of trusted certificate authorities.
274      * @param provider The SSL provider to use, or null for the default
275      * @param protocol The SSL protocol to use
276      * @param algorithm The SSL algorithm to use
277      * @param keyStore The key keystore name as provided by listKeystores. The
278      * KeystoreInstance for this keystore must be unlocked.
279      * @param keyAlias The name of the private key in the keystore. The
280      * KeystoreInstance for this keystore must have unlocked
281      * this key.
282      * @param trustStore The trust keystore name as provided by listKeystores.
283      * The KeystoreInstance for this keystore must have
284      * unlocked this key.
285      * @param loader The class loader used to resolve factory classes.
286      *
287      * @throws KeystoreIsLocked Occurs when the requested key keystore cannot
288      * be used because it has not been unlocked.
289      * @throws KeyIsLocked Occurs when the requested private key in the key
290      * keystore cannot be used because it has not been
291      * unlocked.
292      */

293     public SSLServerSocketFactory createSSLServerFactory(String JavaDoc provider, String JavaDoc protocol, String JavaDoc algorithm, String JavaDoc keyStore, String JavaDoc keyAlias, String JavaDoc trustStore, ClassLoader JavaDoc loader) throws KeystoreException {
294         KeystoreInstance keyInstance = getKeystore(keyStore);
295         if(keyInstance.isKeystoreLocked()) {
296             throw new KeystoreIsLocked("Keystore '"+keyStore+"' is locked; please use the keystore page in the admin console to unlock it");
297         }
298         if(keyInstance.isKeyLocked(keyAlias)) {
299             throw new KeystoreIsLocked("Key '"+keyAlias+"' in keystore '"+keyStore+"' is locked; please use the keystore page in the admin console to unlock it");
300         }
301         KeystoreInstance trustInstance = trustStore == null ? null : getKeystore(trustStore);
302         if(trustInstance != null && trustInstance.isKeystoreLocked()) {
303             throw new KeystoreIsLocked("Keystore '"+trustStore+"' is locked; please use the keystore page in the admin console to unlock it");
304         }
305
306         // OMG this hurts, but it causes ClassCastExceptions elsewhere unless done this way!
307
try {
308             Class JavaDoc cls = loader.loadClass("javax.net.ssl.SSLContext");
309             Object JavaDoc ctx = cls.getMethod("getInstance", new Class JavaDoc[] {String JavaDoc.class}).invoke(null, new Object JavaDoc[]{protocol});
310             Class JavaDoc kmc = loader.loadClass("[Ljavax.net.ssl.KeyManager;");
311             Class JavaDoc tmc = loader.loadClass("[Ljavax.net.ssl.TrustManager;");
312             Class JavaDoc src = loader.loadClass("java.security.SecureRandom");
313             cls.getMethod("init", new Class JavaDoc[]{kmc, tmc, src}).invoke(ctx, new Object JavaDoc[]{keyInstance.getKeyManager(algorithm, keyAlias, null),
314                                                                             trustInstance == null ? null : trustInstance.getTrustManager(algorithm, null),
315                                                                             new java.security.SecureRandom JavaDoc()});
316             Object JavaDoc result = cls.getMethod("getServerSocketFactory", new Class JavaDoc[0]).invoke(ctx, new Object JavaDoc[0]);
317             return (SSLServerSocketFactory) result;
318         } catch (Exception JavaDoc e) {
319             throw new KeystoreException("Unable to create SSL Server Factory", e);
320         }
321     }
322
323     public KeystoreInstance createKeystore(String JavaDoc name, char[] password) throws KeystoreException {
324         File JavaDoc test = new File JavaDoc(directory, name);
325         if(test.exists()) {
326             throw new IllegalArgumentException JavaDoc("Keystore already exists "+test.getAbsolutePath()+"!");
327         }
328         try {
329             KeyStore JavaDoc keystore = KeyStore.getInstance(FileKeystoreInstance.JKS);
330             keystore.load(null, password);
331             OutputStream JavaDoc out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(test));
332             keystore.store(out, password);
333             out.flush();
334             out.close();
335             return getKeystore(name);
336         } catch (KeyStoreException JavaDoc e) {
337             throw new KeystoreException("Unable to create keystore", e);
338         } catch (IOException JavaDoc e) {
339             throw new KeystoreException("Unable to create keystore", e);
340         } catch (NoSuchAlgorithmException JavaDoc e) {
341             throw new KeystoreException("Unable to create keystore", e);
342         } catch (CertificateException JavaDoc e) {
343             throw new KeystoreException("Unable to create keystore", e);
344         }
345     }
346
347     public KeystoreInstance[] getUnlockedKeyStores() {
348         List JavaDoc results = new ArrayList JavaDoc();
349         for (Iterator JavaDoc it = keystores.iterator(); it.hasNext();) {
350             KeystoreInstance instance = (KeystoreInstance) it.next();
351             try {
352                 if(!instance.isKeystoreLocked() && instance.getUnlockedKeys(null).length > 0) {
353                     results.add(instance);
354                 }
355             } catch (KeystoreException e) {}
356         }
357         return (KeystoreInstance[]) results.toArray(new KeystoreInstance[results.size()]);
358     }
359
360     public KeystoreInstance[] getUnlockedTrustStores() {
361         List JavaDoc results = new ArrayList JavaDoc();
362         for (Iterator JavaDoc it = keystores.iterator(); it.hasNext();) {
363             KeystoreInstance instance = (KeystoreInstance) it.next();
364             try {
365                 if(!instance.isKeystoreLocked() && instance.isTrustStore(null)) {
366                     results.add(instance);
367                 }
368             } catch (KeystoreException e) {}
369         }
370         return (KeystoreInstance[]) results.toArray(new KeystoreInstance[results.size()]);
371     }
372
373     public static final GBeanInfo GBEAN_INFO;
374
375     static {
376         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(FileKeystoreManager.class);
377         infoFactory.addAttribute("keystoreDir", URI JavaDoc.class, true);
378         infoFactory.addAttribute("kernel", Kernel.class, false);
379         infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
380         infoFactory.addReference("KeystoreInstances", KeystoreInstance.class, NameFactory.KEYSTORE_INSTANCE);
381         infoFactory.addInterface(KeystoreManager.class);
382         infoFactory.setConstructor(new String JavaDoc[]{"keystoreDir", "ServerInfo", "KeystoreInstances", "kernel"});
383
384         GBEAN_INFO = infoFactory.getBeanInfo();
385     }
386
387     public static GBeanInfo getGBeanInfo() {
388         return GBEAN_INFO;
389     }
390
391     // ===================== Move this to a unitiy class or something ====================
392

393     public X509Certificate JavaDoc generateCert(PublicKey JavaDoc publicKey,
394                                         PrivateKey JavaDoc privateKey, String JavaDoc sigalg, int validity, String JavaDoc cn,
395                                         String JavaDoc ou, String JavaDoc o, String JavaDoc l, String JavaDoc st, String JavaDoc c)
396             throws java.security.SignatureException JavaDoc,
397             java.security.InvalidKeyException JavaDoc {
398         X509V1CertificateGenerator certgen = new X509V1CertificateGenerator();
399
400         // issuer dn
401
Vector JavaDoc order = new Vector JavaDoc();
402         Hashtable JavaDoc attrmap = new Hashtable JavaDoc();
403
404         if (cn != null) {
405             attrmap.put(X509Principal.CN, cn);
406             order.add(X509Principal.CN);
407         }
408
409         if (ou != null) {
410             attrmap.put(X509Principal.OU, ou);
411             order.add(X509Principal.OU);
412         }
413
414         if (o != null) {
415             attrmap.put(X509Principal.O, o);
416             order.add(X509Principal.O);
417         }
418
419         if (l != null) {
420             attrmap.put(X509Principal.L, l);
421             order.add(X509Principal.L);
422         }
423
424         if (st != null) {
425             attrmap.put(X509Principal.ST, st);
426             order.add(X509Principal.ST);
427         }
428
429         if (c != null) {
430             attrmap.put(X509Principal.C, c);
431             order.add(X509Principal.C);
432         }
433
434         X509Principal issuerDN = new X509Principal(order, attrmap);
435         certgen.setIssuerDN(issuerDN);
436
437         // validity
438
long curr = System.currentTimeMillis();
439         long untill = curr + (long) validity * 24 * 60 * 60 * 1000;
440
441         certgen.setNotBefore(new Date JavaDoc(curr));
442         certgen.setNotAfter(new Date JavaDoc(untill));
443
444         // subject dn
445
certgen.setSubjectDN(issuerDN);
446
447         // public key
448
certgen.setPublicKey(publicKey);
449
450         // signature alg
451
certgen.setSignatureAlgorithm(sigalg);
452
453         // serial number
454
certgen.setSerialNumber(new BigInteger JavaDoc(String.valueOf(curr)));
455
456         // make certificate
457
return certgen.generateX509Certificate(privateKey);
458     }
459 }
460
Popular Tags