KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > model > ca > caadmin > extendedcaservices > CmsCAService


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13
14 package org.ejbca.core.model.ca.caadmin.extendedcaservices;
15
16 import java.io.IOException JavaDoc;
17 import java.io.UnsupportedEncodingException JavaDoc;
18 import java.security.InvalidAlgorithmParameterException JavaDoc;
19 import java.security.KeyPair JavaDoc;
20 import java.security.KeyStore JavaDoc;
21 import java.security.NoSuchAlgorithmException JavaDoc;
22 import java.security.NoSuchProviderException JavaDoc;
23 import java.security.PrivateKey JavaDoc;
24 import java.security.cert.CertStore JavaDoc;
25 import java.security.cert.CertStoreException JavaDoc;
26 import java.security.cert.Certificate JavaDoc;
27 import java.security.cert.CollectionCertStoreParameters JavaDoc;
28 import java.security.cert.X509Certificate JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.List JavaDoc;
32
33 import org.apache.log4j.Logger;
34 import org.bouncycastle.cms.CMSException;
35 import org.bouncycastle.cms.CMSProcessable;
36 import org.bouncycastle.cms.CMSProcessableByteArray;
37 import org.bouncycastle.cms.CMSSignedData;
38 import org.bouncycastle.cms.CMSSignedDataGenerator;
39 import org.bouncycastle.cms.CMSSignedGenerator;
40 import org.ejbca.core.ejb.ServiceLocator;
41 import org.ejbca.core.model.InternalResources;
42 import org.ejbca.core.model.ca.caadmin.CA;
43 import org.ejbca.core.model.ca.caadmin.IllegalKeyStoreException;
44 import org.ejbca.core.model.ca.certificateprofiles.XKMSCertificateProfile;
45 import org.ejbca.core.model.ra.UserDataVO;
46 import org.ejbca.util.Base64;
47 import org.ejbca.util.CertTools;
48 import org.ejbca.util.KeyTools;
49
50
51
52 /** Handles and maintains the CA-part of the CMS message functionality.
53  * The service have it's own certificate used for signing and encryption
54  *
55  * @version $Id: CmsCAService.java,v 1.2.2.1 2007/02/23 10:35:14 anatom Exp $
56  */

57 public class CmsCAService extends ExtendedCAService implements java.io.Serializable JavaDoc{
58
59     /** Determines if a de-serialized file is compatible with this class.
60     *
61     * Maintainers must change this value if and only if the new version
62     * of this class is not compatible with old versions. See Sun docs
63     * for <a HREF=http://java.sun.com/products/jdk/1.1/docs/guide
64     * /serialization/spec/version.doc.html> details. </a>
65     */

66     private static final long serialVersionUID = 5273836489592921586L;
67     
68     private static Logger m_log = Logger.getLogger(CmsCAService.class);
69     /** Internal localization of logs and errors */
70     private static final InternalResources intres = InternalResources.getInstance();
71
72     public static final float LATEST_VERSION = 1;
73
74     public static final String JavaDoc SERVICENAME = "CMSCASERVICE";
75
76     private PrivateKey JavaDoc privKey = null;
77     private List JavaDoc certificatechain = null;
78
79     private CmsCAServiceInfo info = null;
80
81     private static final String JavaDoc KEYSTORE = "keystore";
82     private static final String JavaDoc KEYSPEC = "keyspec";
83     private static final String JavaDoc KEYALGORITHM = "keyalgorithm";
84     private static final String JavaDoc SUBJECTDN = "subjectdn";
85     private static final String JavaDoc SUBJECTALTNAME = "subjectaltname";
86
87     private static final String JavaDoc PRIVATESIGNKEYALIAS = "privatesignkeyalias";
88
89
90
91     public CmsCAService(ExtendedCAServiceInfo serviceinfo) {
92         m_log.debug("CmsCAService : constructor " + serviceinfo.getStatus());
93         CertTools.installBCProvider();
94         // Currently only RSA keys are supported
95
CmsCAServiceInfo info = (CmsCAServiceInfo) serviceinfo;
96         data = new HashMap JavaDoc();
97         data.put(EXTENDEDCASERVICETYPE, new Integer JavaDoc(ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE));
98
99         data.put(KEYSPEC, info.getKeySpec());
100         data.put(KEYALGORITHM, info.getKeyAlgorithm());
101         setSubjectDN(info.getSubjectDN());
102         setSubjectAltName(info.getSubjectAltName());
103         setStatus(serviceinfo.getStatus());
104
105         data.put(VERSION, new Float JavaDoc(LATEST_VERSION));
106     }
107
108     public CmsCAService(HashMap JavaDoc data) throws IllegalArgumentException JavaDoc, IllegalKeyStoreException {
109         CertTools.installBCProvider();
110         loadData(data);
111         if(data.get(KEYSTORE) != null){
112             // lookup keystore passwords
113
String JavaDoc keystorepass = ServiceLocator.getInstance().getString("java:comp/env/CMSKeyStorePass");
114             if (keystorepass == null)
115                 throw new IllegalArgumentException JavaDoc("Missing CMSKeyStorePass property.");
116
117             try {
118                 m_log.debug("Loading CMS keystore");
119                 KeyStore JavaDoc keystore=KeyStore.getInstance("PKCS12", "BC");
120                 keystore.load(new java.io.ByteArrayInputStream JavaDoc(Base64.decode(((String JavaDoc) data.get(KEYSTORE)).getBytes())),keystorepass.toCharArray());
121                 m_log.debug("Finished loading CMS keystore");
122
123                 this.privKey = (PrivateKey JavaDoc) keystore.getKey(PRIVATESIGNKEYALIAS, null);
124                 // Due to a bug in Glassfish, we need to make sure all certificates in this
125
// Array i of SUNs own provider
126
//this.certificatechain = Arrays.asList(keystore.getCertificateChain(PRIVATESIGNKEYALIAS));
127
this.certificatechain = CertTools.getCertCollectionFromArray(keystore.getCertificateChain(PRIVATESIGNKEYALIAS), "SUN");
128                 this.info = new CmsCAServiceInfo(getStatus(),
129                         getSubjectDN(),
130                         getSubjectAltName(),
131                         (String JavaDoc)data.get(KEYSPEC),
132                         (String JavaDoc) data.get(KEYALGORITHM),
133                         this.certificatechain);
134
135             } catch (Exception JavaDoc e) {
136                 throw new IllegalKeyStoreException(e);
137             }
138
139             data.put(EXTENDEDCASERVICETYPE, new Integer JavaDoc(ExtendedCAServiceInfo.TYPE_CMSEXTENDEDSERVICE));
140         }
141     }
142
143
144
145     /*
146      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
147      */

148     public void init(CA ca) throws Exception JavaDoc {
149         m_log.debug("CmsCAService : init");
150         // lookup keystore passwords
151
String JavaDoc keystorepass = ServiceLocator.getInstance().getString("java:comp/env/CMSKeyStorePass");
152         if (keystorepass == null)
153             throw new IllegalArgumentException JavaDoc("Missing CMSKeyStorePass property.");
154
155         // Currently only RSA keys are supported
156
CmsCAServiceInfo info = (CmsCAServiceInfo) getExtendedCAServiceInfo();
157
158         // Create KeyStore
159
KeyStore JavaDoc keystore = KeyStore.getInstance("PKCS12", "BC");
160         keystore.load(null, null);
161
162         KeyPair JavaDoc cmskeys = KeyTools.genKeys(info.getKeySpec(), info.getKeyAlgorithm());
163
164         Certificate JavaDoc certificate =
165             ca.generateCertificate(new UserDataVO("NOUSERNAME",
166                     info.getSubjectDN(),
167                     0,
168                     info.getSubjectAltName(),
169                     "NOEMAIL",
170                     0,0,0,0, null,null,0,0,null)
171             , cmskeys.getPublic(),
172             -1, // KeyUsage
173
ca.getValidity(),
174             new XKMSCertificateProfile()); // We can use the (simple) XKMS profile, since it uses the same values as we want for CMS
175

176         certificatechain = new ArrayList JavaDoc();
177         certificatechain.add(certificate);
178         certificatechain.addAll(ca.getCertificateChain());
179         this.privKey = cmskeys.getPrivate();
180
181         keystore.setKeyEntry(PRIVATESIGNKEYALIAS,cmskeys.getPrivate(),null,(Certificate JavaDoc[]) certificatechain.toArray(new Certificate JavaDoc[certificatechain.size()]));
182         java.io.ByteArrayOutputStream JavaDoc baos = new java.io.ByteArrayOutputStream JavaDoc();
183         keystore.store(baos, keystorepass.toCharArray());
184         data.put(KEYSTORE, new String JavaDoc(Base64.encode(baos.toByteArray())));
185         // Store KeyStore
186

187         setStatus(info.getStatus());
188         this.info = new CmsCAServiceInfo(info.getStatus(),
189                 getSubjectDN(),
190                 getSubjectAltName(),
191                 (String JavaDoc)data.get(KEYSPEC),
192                 (String JavaDoc) data.get(KEYALGORITHM),
193                 certificatechain);
194     }
195
196     /*
197      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
198      */

199     public void update(ExtendedCAServiceInfo serviceinfo, CA ca) throws Exception JavaDoc{
200         CmsCAServiceInfo info = (CmsCAServiceInfo) serviceinfo;
201         m_log.debug("CmsCAService : update " + serviceinfo.getStatus());
202         setStatus(serviceinfo.getStatus());
203         if(info.getRenewFlag()){
204             // Renew The Signers certificate.
205
this.init(ca);
206         }
207
208         // Only status is updated
209
this.info = new CmsCAServiceInfo(serviceinfo.getStatus(),
210                 getSubjectDN(),
211                 getSubjectAltName(),
212                 (String JavaDoc) data.get(KEYSPEC),
213                 (String JavaDoc) data.get(KEYALGORITHM),
214                 certificatechain);
215     }
216
217
218
219     /*
220      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
221      */

222     public ExtendedCAServiceResponse extendedService(ExtendedCAServiceRequest request) throws ExtendedCAServiceRequestException, IllegalExtendedCAServiceRequestException,ExtendedCAServiceNotActiveException {
223         m_log.debug(">extendedService");
224         if (!(request instanceof CmsCAServiceRequest)) {
225             throw new IllegalExtendedCAServiceRequestException();
226         }
227         if (this.getStatus() != ExtendedCAServiceInfo.STATUS_ACTIVE) {
228             String JavaDoc msg = intres.getLocalizedMessage("caservice.notactive");
229             m_log.error(msg);
230             throw new ExtendedCAServiceNotActiveException(msg);
231         }
232         ExtendedCAServiceResponse returnval = null;
233         X509Certificate JavaDoc signerCert = (X509Certificate JavaDoc) certificatechain.get(0);
234         CmsCAServiceRequest serviceReq = (CmsCAServiceRequest)request;
235
236         // Create the signed data
237
CMSSignedDataGenerator gen1 = new CMSSignedDataGenerator();
238         try {
239             // Add our signer info and sign the message
240
CertStore JavaDoc certs;
241             certs = CertStore.getInstance("Collection",
242                     new CollectionCertStoreParameters JavaDoc(certificatechain), "BC");
243             gen1.addCertificatesAndCRLs(certs);
244             gen1.addSigner(privKey, signerCert, CMSSignedGenerator.DIGEST_SHA1);
245             CMSProcessable msg = new CMSProcessableByteArray(serviceReq.getDoc());
246             CMSSignedData s = gen1.generate(msg, true, "BC");
247             byte[] resp = s.getEncoded();
248             returnval = new CmsCAServiceResponse(resp);
249         } catch (InvalidAlgorithmParameterException JavaDoc e) {
250             m_log.error("Error in CmsCAService", e);
251             throw new ExtendedCAServiceRequestException(e);
252         } catch (NoSuchAlgorithmException JavaDoc e) {
253             m_log.error("Error in CmsCAService", e);
254             throw new ExtendedCAServiceRequestException(e);
255         } catch (NoSuchProviderException JavaDoc e) {
256             m_log.error("Error in CmsCAService", e);
257             throw new ExtendedCAServiceRequestException(e);
258         } catch (CertStoreException JavaDoc e) {
259             m_log.error("Error in CmsCAService", e);
260             throw new ExtendedCAServiceRequestException(e);
261         } catch (CMSException e) {
262             m_log.error("Error in CmsCAService", e);
263             throw new ExtendedCAServiceRequestException(e);
264         } catch (IOException JavaDoc e) {
265             m_log.error("Error in CmsCAService", e);
266             throw new ExtendedCAServiceRequestException(e);
267         }
268
269         m_log.debug("<extendedService");
270         return returnval;
271     }
272
273
274     public float getLatestVersion() {
275         return LATEST_VERSION;
276     }
277
278     public void upgrade() {
279         if(Float.compare(LATEST_VERSION, getVersion()) != 0) {
280             // New version of the class, upgrade
281

282             data.put(VERSION, new Float JavaDoc(LATEST_VERSION));
283         }
284     }
285
286     /*
287      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#getExtendedCAServiceInfo()
288      */

289     public ExtendedCAServiceInfo getExtendedCAServiceInfo() {
290         if(info == null){
291             info = new CmsCAServiceInfo(getStatus(),
292                     getSubjectDN(),
293                     getSubjectAltName(),
294                     (String JavaDoc) data.get(KEYSPEC),
295                     (String JavaDoc) data.get(KEYALGORITHM),
296                     certificatechain);
297         }
298
299         return this.info;
300     }
301
302
303     public String JavaDoc getSubjectDN(){
304         String JavaDoc retval = null;
305         String JavaDoc str = (String JavaDoc)data.get(SUBJECTDN);
306         try {
307             retval = new String JavaDoc(Base64.decode((str).getBytes("UTF-8")));
308         } catch (UnsupportedEncodingException JavaDoc e) {
309             m_log.error("Could not decode data from Base64",e);
310         } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
311             // This is an old CA, where it's not Base64encoded
312
m_log.debug("Old non base64 encoded DN: "+str);
313             retval = str;
314         }
315
316         return retval;
317     }
318
319     public void setSubjectDN(String JavaDoc dn){
320
321         try {
322             data.put(SUBJECTDN,new String JavaDoc(Base64.encode(dn.getBytes("UTF-8"),false)));
323         } catch (UnsupportedEncodingException JavaDoc e) {
324             m_log.error("Could not encode data from Base64",e);
325         }
326     }
327
328     public String JavaDoc getSubjectAltName(){
329         String JavaDoc retval = null;
330         String JavaDoc str= (String JavaDoc) data.get(SUBJECTALTNAME);
331         try {
332             retval = new String JavaDoc(Base64.decode((str).getBytes("UTF-8")));
333         } catch (UnsupportedEncodingException JavaDoc e) {
334             m_log.error("Could not decode data from Base64",e);
335         } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
336             // This is an old CA, where it's not Base64encoded
337
m_log.debug("Old non base64 encoded altname: "+str);
338             retval = str;
339         }
340
341         return retval;
342     }
343
344     public void setSubjectAltName(String JavaDoc dn){
345
346         try {
347             data.put(SUBJECTALTNAME,new String JavaDoc(Base64.encode(dn.getBytes("UTF-8"), false)));
348         } catch (UnsupportedEncodingException JavaDoc e) {
349             m_log.error("Could not encode data from Base64",e);
350         }
351     }
352 }
353
354
Popular Tags