KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > ca > FileCertificateStore


1 /**
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one or more
4  * contributor license agreements. See the NOTICE file distributed with
5  * this work for additional information regarding copyright ownership.
6  * The ASF licenses this file to You under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.apache.geronimo.security.ca;
19
20 import java.io.File JavaDoc;
21 import java.io.FileInputStream JavaDoc;
22 import java.io.FileOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.math.BigInteger JavaDoc;
25 import java.net.URI JavaDoc;
26 import java.security.cert.Certificate JavaDoc;
27 import java.security.cert.CertificateFactory JavaDoc;
28 import java.security.cert.X509Certificate JavaDoc;
29 import java.util.Properties JavaDoc;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.geronimo.gbean.AbstractName;
34 import org.apache.geronimo.gbean.GBeanInfo;
35 import org.apache.geronimo.gbean.GBeanInfoBuilder;
36 import org.apache.geronimo.gbean.GBeanLifecycle;
37 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
38 import org.apache.geronimo.kernel.Kernel;
39 import org.apache.geronimo.management.geronimo.CertificateStore;
40 import org.apache.geronimo.management.geronimo.CertificateStoreException;
41 import org.apache.geronimo.system.serverinfo.ServerInfo;
42 import org.apache.geronimo.util.CaUtils;
43
44 /**
45  * A certificate store implementation using disk files.
46  *
47  * @version $Rev: 476291 $ $Date: 2006-11-17 15:05:24 -0500 (Fri, 17 Nov 2006) $
48  */

49
50 public class FileCertificateStore implements CertificateStore, GBeanLifecycle {
51     private static final Log log = LogFactory.getLog(FileCertificateStore.class);
52
53     private ServerInfo serverInfo;
54     private Kernel kernel;
55     private AbstractName abstractName;
56     private URI JavaDoc directoryPath;
57     
58     // File name for storing the highest serial number in the store
59
private static final String JavaDoc SERIAL_NUMBER_FILE = "highest-serial-number.txt";
60     // Extension for certificate files. Filename would be <serial-number>+CERT_FILE_SUFFIX
61
private static final String JavaDoc CERT_FILE_SUFFIX = ".txt";
62     // File name for storing CA's certificate
63
private static final String JavaDoc CA_CERT_FILE = "ca-cert.txt";
64     // File name for storing Certificate Challenges
65
private static final String JavaDoc CHALLENGE_FILENAME = "challenge.properties";
66     private static final String JavaDoc CHALLENGE_FILE_HEADER = "Challenge File";
67     
68     // directory for the certificate store
69
private File JavaDoc storeDir = null;
70     
71     // File object of SERIAL_NUMBER_FILE cached
72
private File JavaDoc highestSerialFile = null;
73     // highest serial number cached
74
private BigInteger JavaDoc highestSerialNumber = null;
75     // Cerificate Challenges
76
private Properties JavaDoc challenges = null;
77     
78     /**
79      * Constructor
80      * @param storeDir directory for the certificate store
81      */

82     public FileCertificateStore(ServerInfo serverInfo, URI JavaDoc directoryPath, Kernel kernel, AbstractName abstractName) {
83         this.serverInfo = serverInfo;
84         this.kernel = kernel;
85         this.abstractName = abstractName;
86         this.directoryPath = directoryPath;
87     }
88     /**
89      * This method stores a given certificate.
90      *
91      * @param cert Certificate to be stored
92      */

93     public void storeCertificate(Certificate JavaDoc cert) throws CertificateStoreException {
94         BigInteger JavaDoc sNo = ((X509Certificate JavaDoc)cert).getSerialNumber();
95         File JavaDoc certFile = new File JavaDoc(storeDir, sNo+CERT_FILE_SUFFIX);
96         try {
97             // Check if the highest serial number is less than the serial number of certificate to be stored.
98
if(sNo.compareTo(getHighestSerialNumber()) == 1) {
99                 // store the current serial number so that getNextSerialNumber() will not result in duplicate
100
// serial number
101
setHighestSerialNumber(sNo);
102             }
103             
104             // Store the certificate to disk in base64 format
105
FileOutputStream JavaDoc fout = new FileOutputStream JavaDoc(certFile);
106             CaUtils.storeInBase64(fout, cert.getEncoded(), CaUtils.CERT_HEADER, CaUtils.CERT_FOOTER, CaUtils.B64_LINE_SIZE);
107             fout.close();
108         } catch (Exception JavaDoc e) {
109             throw new CertificateStoreException("Error while storing certificate.", e);
110         }
111     }
112
113     /**
114      * This method returns a Certificate with a given serial number (if it exists in the store)
115      *
116      * @param sNo Serial Number of the certificate to be retrieved.
117      */

118     public Certificate JavaDoc getCertificate(BigInteger JavaDoc sNo) throws CertificateStoreException {
119         File JavaDoc certFile = new File JavaDoc(storeDir, sNo+CERT_FILE_SUFFIX);
120         if(!certFile.exists()) {
121             // No such certificate in the store.
122
throw new CertificateStoreException("No certificate with serial number "+sNo+" found.");
123         }
124         
125         // Read the certificate from disk and generate a java.security.cert.Certificate
126
try {
127             FileInputStream JavaDoc fin = new FileInputStream JavaDoc(certFile);
128             CertificateFactory JavaDoc certFac = CertificateFactory.getInstance("X.509");
129             Certificate JavaDoc cert = certFac.generateCertificate(fin);
130             fin.close();
131             return cert;
132         } catch (Exception JavaDoc e) {
133             throw new CertificateStoreException("Error while retrieving certificate.", e);
134         }
135     }
136
137     /**
138      * This method returns base64 encoded certificate with a given serial number (if it exists in the store)
139      *
140      * @param sNo Serial Number of the certificate to be retrieved.
141      */

142     public String JavaDoc getCertificateBase64Text(BigInteger JavaDoc sNo) throws CertificateStoreException {
143         File JavaDoc certFile = new File JavaDoc(storeDir, sNo+CERT_FILE_SUFFIX);
144         if(!certFile.exists()) {
145             throw new CertificateStoreException("No certificate with serial number "+sNo+" found.");
146         }
147         FileInputStream JavaDoc fin;
148         try {
149             fin = new FileInputStream JavaDoc(certFile);
150             byte[] data = new byte[fin.available()];
151             fin.read(data);
152             fin.close();
153             return new String JavaDoc(data);
154         } catch (Exception JavaDoc e) {
155             throw new CertificateStoreException("Error while retrieving certificate.", e);
156         }
157     }
158     
159     /**
160      * This method returns the highest certificate serial number in the store.
161      */

162     public BigInteger JavaDoc getHighestSerialNumber() throws CertificateStoreException{
163         if(highestSerialNumber == null) {
164             // Value has not been cached. Read from the disk.
165
try {
166                 FileInputStream JavaDoc finp = new FileInputStream JavaDoc(highestSerialFile);
167                 byte[] data = new byte[finp.available()];
168                 finp.read(data);
169                 finp.close();
170                 highestSerialNumber = new BigInteger JavaDoc(new String JavaDoc(data).trim());
171             } catch (Exception JavaDoc e) {
172                 throw new CertificateStoreException("Error while getting serial number.", e);
173             }
174         }
175         return highestSerialNumber;
176     }
177
178     /**
179      * This method returns the 'highest certificate serial number plus ONE' and increments the highest
180      * serial number in the store.
181      */

182     public BigInteger JavaDoc getNextSerialNumber() throws CertificateStoreException{
183         setHighestSerialNumber(getHighestSerialNumber().add(BigInteger.ONE));
184         return highestSerialNumber;
185     }
186
187     /**
188      * This method checks if a certificate with a given serial number exists in the store.
189      *
190      * @param sNo Serial number of the certificate to be checked
191      */

192     public boolean containsCertificate(BigInteger JavaDoc sNo) {
193         File JavaDoc certFile = new File JavaDoc(storeDir, sNo+CERT_FILE_SUFFIX);
194         return certFile.exists();
195     }
196     
197     /**
198      * This method sets the highest serial number to a given value and updates the same to disk.
199      * @param sNo The serial number to be set
200      */

201     private void setHighestSerialNumber(BigInteger JavaDoc sNo) throws CertificateStoreException{
202         try {
203             highestSerialNumber = sNo;
204             FileOutputStream JavaDoc fout = new FileOutputStream JavaDoc(highestSerialFile);
205             fout.write(highestSerialNumber.toString().getBytes());
206             fout.close();
207         } catch (Exception JavaDoc e) {
208             throw new CertificateStoreException("Error while setting highest serial number.", e);
209         }
210     }
211     
212     /**
213      * This method stores the CA's certificate in the store.
214      * @param cert CA's certificate
215      */

216     public boolean storeCACertificate(Certificate JavaDoc cert) throws CertificateStoreException{
217         FileOutputStream JavaDoc fout = null;
218         try {
219             fout = new FileOutputStream JavaDoc(new File JavaDoc(storeDir, CA_CERT_FILE));
220             CaUtils.storeInBase64(fout, cert.getEncoded(), CaUtils.CERT_HEADER, CaUtils.CERT_FOOTER, CaUtils.B64_LINE_SIZE);
221             fout.close();
222             return true;
223         } catch (Exception JavaDoc e) {
224             throw new CertificateStoreException("Exception in storing CA certificate", e);
225         }
226     }
227
228     /**
229      * This method returns the CA's certificate stored in the store.
230      */

231     public Certificate JavaDoc getCACertificate() throws CertificateStoreException {
232         FileInputStream JavaDoc fin = null;
233         try {
234             fin = new FileInputStream JavaDoc(new File JavaDoc(storeDir, CA_CERT_FILE));
235             CertificateFactory JavaDoc certFac = CertificateFactory.getInstance("X.509");
236             Certificate JavaDoc cert = certFac.generateCertificate(fin);
237             fin.close();
238             return cert;
239         } catch (Exception JavaDoc e) {
240             throw new CertificateStoreException("Exception in getting CA certificate", e);
241         }
242     }
243     
244     /**
245      * This method stores the challenge phrase against the specified certificate serial number
246      * @param sNo Serial number of the certificate
247      * @param challenge Challenge phrase
248      */

249     public boolean setCertificateChallenge(BigInteger JavaDoc sNo, String JavaDoc challenge) {
250         if(challenges == null) {
251             loadChallenges();
252         }
253         if(!challenges.containsKey(sNo.toString())) {
254             challenges.setProperty(sNo.toString(), challenge);
255             storeChallenges();
256             return true;
257         }
258         return false;
259     }
260
261     /**
262      * This methods stores the challenges map to disk
263      */

264     private void storeChallenges() {
265         if(challenges == null) loadChallenges();
266         File JavaDoc chFile = new File JavaDoc(storeDir, CHALLENGE_FILENAME);
267         FileOutputStream JavaDoc fout = null;
268         try {
269             fout = new FileOutputStream JavaDoc(chFile);
270             challenges.store(fout, CHALLENGE_FILE_HEADER);
271             fout.close();
272         } catch (Exception JavaDoc e) {
273             log.error("Exceptions while storing challenges file. File = "+chFile.getAbsolutePath(), e);
274         }
275         
276     }
277     
278     /**
279      * This method loads the challenges map from disk.
280      */

281     private void loadChallenges() {
282         File JavaDoc chFile = new File JavaDoc(storeDir, CHALLENGE_FILENAME);
283         FileInputStream JavaDoc fin = null;
284         try {
285             if(!chFile.exists())
286                 chFile.createNewFile();
287             fin = new FileInputStream JavaDoc(chFile);
288             challenges = new Properties JavaDoc();
289             challenges.load(fin);
290             fin.close();
291         } catch (IOException JavaDoc e) {
292             log.error("Exceptions while loading challenges file. File = "+chFile.getAbsolutePath(), e);
293         }
294     }
295     
296     public void doFail() {
297     }
298
299     public void doStart() throws Exception JavaDoc {
300         serverInfo.resolveServer(directoryPath);
301         URI JavaDoc dirURI;
302         if (serverInfo != null) {
303             dirURI = serverInfo.resolve(directoryPath);
304         } else {
305             dirURI = directoryPath;
306         }
307         if (!dirURI.getScheme().equals("file")) {
308             throw new IllegalStateException JavaDoc("FileCertificateStore must have a root that's a local directory (not " + dirURI + ")");
309         }
310         storeDir = new File JavaDoc(dirURI);
311         if(!storeDir.exists()) {
312             storeDir.mkdirs();
313             log.debug("Created directory "+storeDir.getAbsolutePath());
314         } else if(!storeDir.isDirectory() || !storeDir.canRead()) {
315             throw new IllegalStateException JavaDoc("FileCertificateStore must have a root that's a valid readable directory (not " + storeDir.getAbsolutePath() + ")");
316         }
317         log.debug("CertificateStore directory is " + storeDir.getAbsolutePath());
318         highestSerialFile = new File JavaDoc(storeDir, SERIAL_NUMBER_FILE);
319         if(!highestSerialFile.exists()) {
320             // If the file does not exist, it means the certificate store is a new one.
321
// Start with ZERO
322
try {
323                 setHighestSerialNumber(BigInteger.ZERO);
324             } catch(CertificateStoreException e) {
325                 log.error("Error initializing certificate store. storeDir="+storeDir, e);
326             }
327         }
328         loadChallenges();
329     }
330
331     public void doStop() throws Exception JavaDoc {
332     }
333
334     public static final GBeanInfo GBEAN_INFO;
335
336     static {
337         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(FileCertificateStore.class, "CertificateStore");
338         infoFactory.addAttribute("directoryPath", URI JavaDoc.class, true, false);
339         infoFactory.addAttribute("kernel", Kernel.class, false);
340         infoFactory.addAttribute("abstractName", AbstractName.class, false);
341         infoFactory.addReference("ServerInfo", ServerInfo.class, NameFactory.GERONIMO_SERVICE);
342         infoFactory.addInterface(CertificateStore.class);
343         infoFactory.setConstructor(new String JavaDoc[]{"ServerInfo", "directoryPath", "kernel", "abstractName"});
344
345         GBEAN_INFO = infoFactory.getBeanInfo();
346     }
347     
348     public static GBeanInfo getGBeanInfo() {
349         return GBEAN_INFO;
350     }
351 }
352
Popular Tags