KickJava   Java API By Example, From Geeks To Geeks.

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


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.UnsupportedEncodingException JavaDoc;
17 import java.security.KeyPair JavaDoc;
18 import java.security.KeyStore JavaDoc;
19 import java.security.NoSuchProviderException JavaDoc;
20 import java.security.PrivateKey JavaDoc;
21 import java.security.PublicKey JavaDoc;
22 import java.security.cert.Certificate JavaDoc;
23 import java.security.cert.X509Certificate JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.apache.log4j.Logger;
30 import org.bouncycastle.ocsp.BasicOCSPResp;
31 import org.bouncycastle.ocsp.OCSPException;
32 import org.ejbca.core.ejb.ServiceLocator;
33 import org.ejbca.core.model.InternalResources;
34 import org.ejbca.core.model.ca.NotSupportedException;
35 import org.ejbca.core.model.ca.caadmin.CA;
36 import org.ejbca.core.model.ca.caadmin.IllegalKeyStoreException;
37 import org.ejbca.core.model.ca.certificateprofiles.OCSPSignerCertificateProfile;
38 import org.ejbca.core.model.ra.UserDataVO;
39 import org.ejbca.core.protocol.ocsp.OCSPUtil;
40 import org.ejbca.util.Base64;
41 import org.ejbca.util.CertTools;
42 import org.ejbca.util.KeyTools;
43
44
45
46 /** Handles and maintains the CA-part of the OCSP functionality
47  *
48  * @version $Id: OCSPCAService.java,v 1.15.2.1 2007/02/23 10:35:14 anatom Exp $
49  */

50 public class OCSPCAService extends ExtendedCAService implements java.io.Serializable JavaDoc{
51
52     private static Logger m_log = Logger.getLogger(OCSPCAService.class);
53     /** Internal localization of logs and errors */
54     private static final InternalResources intres = InternalResources.getInstance();
55
56     public static final float LATEST_VERSION = 2;
57     
58     public static final String JavaDoc SERVICENAME = "OCSPCASERVICE";
59       
60
61     private PrivateKey JavaDoc ocspsigningkey = null;
62     private List JavaDoc ocspcertificatechain = null;
63     
64     private OCSPCAServiceInfo info = null;
65     
66     private static final String JavaDoc OCSPKEYSTORE = "ocspkeystore";
67     private static final String JavaDoc KEYSPEC = "keyspec";
68     private static final String JavaDoc KEYALGORITHM = "keyalgorithm";
69     private static final String JavaDoc SUBJECTDN = "subjectdn";
70     private static final String JavaDoc SUBJECTALTNAME = "subjectaltname";
71     
72     private static final String JavaDoc PRIVATESIGNKEYALIAS = "privatesignkeyalias";
73
74     /** kept for upgrade purposes 3.3 -> 3.4 */
75     private static final String JavaDoc KEYSIZE = "keysize";
76             
77     public OCSPCAService(ExtendedCAServiceInfo serviceinfo) {
78       m_log.debug("OCSPCAService : constructor " + serviceinfo.getStatus());
79       CertTools.installBCProvider();
80       // Currently only RSA keys are supported
81
OCSPCAServiceInfo info = (OCSPCAServiceInfo) serviceinfo;
82       data = new HashMap JavaDoc();
83       data.put(EXTENDEDCASERVICETYPE, new Integer JavaDoc(ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE));
84
85       data.put(KEYSPEC, info.getKeySpec());
86       data.put(KEYALGORITHM, info.getKeyAlgorithm());
87       setSubjectDN(info.getSubjectDN());
88       setSubjectAltName(info.getSubjectAltName());
89       setStatus(serviceinfo.getStatus());
90         
91       data.put(VERSION, new Float JavaDoc(LATEST_VERSION));
92     }
93     
94     public OCSPCAService(HashMap JavaDoc data) throws IllegalArgumentException JavaDoc, IllegalKeyStoreException {
95       CertTools.installBCProvider();
96       loadData(data);
97       if(data.get(OCSPKEYSTORE) != null){
98          // lookup keystore passwords
99
String JavaDoc keystorepass = ServiceLocator.getInstance().getString("java:comp/env/OCSPKeyStorePass");
100          if (keystorepass == null)
101              throw new IllegalArgumentException JavaDoc("Missing OCSPKeyStorePass property.");
102                
103         try {
104             m_log.debug("Loading OCSP keystore");
105             KeyStore JavaDoc keystore=KeyStore.getInstance("PKCS12", "BC");
106             keystore.load(new java.io.ByteArrayInputStream JavaDoc(Base64.decode(((String JavaDoc) data.get(OCSPKEYSTORE)).getBytes())),keystorepass.toCharArray());
107             m_log.debug("Finished loading OCSP keystore");
108       
109             this.ocspsigningkey = (PrivateKey JavaDoc) keystore.getKey(PRIVATESIGNKEYALIAS, null);
110             // Due to a bug in Glassfish, we need to make sure all certificates in this
111
// Array i of SUNs own provider
112
//this.ocspcertificatechain = Arrays.asList(keystore.getCertificateChain(PRIVATESIGNKEYALIAS));
113
this.ocspcertificatechain = CertTools.getCertCollectionFromArray(keystore.getCertificateChain(PRIVATESIGNKEYALIAS), "SUN");
114             this.info = new OCSPCAServiceInfo(getStatus(),
115                                               getSubjectDN(),
116                                               getSubjectAltName(),
117                                               (String JavaDoc)data.get(KEYSPEC),
118                                               (String JavaDoc) data.get(KEYALGORITHM),
119                                               this.ocspcertificatechain);
120       
121         } catch (Exception JavaDoc e) {
122             throw new IllegalKeyStoreException(e);
123         }
124         
125         data.put(EXTENDEDCASERVICETYPE, new Integer JavaDoc(ExtendedCAServiceInfo.TYPE_OCSPEXTENDEDSERVICE));
126      }
127    }
128     
129     
130
131    /*
132     * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
133     */

134    public void init(CA ca) throws Exception JavaDoc {
135      m_log.debug("OCSPCAService : init ");
136      // lookup keystore passwords
137
String JavaDoc keystorepass = ServiceLocator.getInstance().getString("java:comp/env/OCSPKeyStorePass");
138      if (keystorepass == null)
139        throw new IllegalArgumentException JavaDoc("Missing OCSPKeyPass property.");
140         
141       // Currently only RSA keys are supported
142
OCSPCAServiceInfo info = (OCSPCAServiceInfo) getExtendedCAServiceInfo();
143                   
144      // Create OSCP KeyStore
145
KeyStore JavaDoc keystore = KeyStore.getInstance("PKCS12", "BC");
146      keystore.load(null, null);
147       
148      KeyPair JavaDoc ocspkeys = KeyTools.genKeys(info.getKeySpec(), info.getKeyAlgorithm());
149           
150      Certificate JavaDoc ocspcertificate =
151       ca.generateCertificate(new UserDataVO("NOUSERNAME",
152                                             info.getSubjectDN(),
153                                             0,
154                                             info.getSubjectAltName(),
155                                             "NOEMAIL",
156                                             0,0,0,0, null,null,0,0,null)
157                            , ocspkeys.getPublic(),
158                            -1, // KeyUsage
159
ca.getValidity(),
160                            new OCSPSignerCertificateProfile());
161       
162      ocspcertificatechain = new ArrayList JavaDoc();
163      ocspcertificatechain.add(ocspcertificate);
164      ocspcertificatechain.addAll(ca.getCertificateChain());
165      this.ocspsigningkey = ocspkeys.getPrivate();
166               
167      keystore.setKeyEntry(PRIVATESIGNKEYALIAS,ocspkeys.getPrivate(),null,(Certificate JavaDoc[]) ocspcertificatechain.toArray(new Certificate JavaDoc[ocspcertificatechain.size()]));
168      java.io.ByteArrayOutputStream JavaDoc baos = new java.io.ByteArrayOutputStream JavaDoc();
169      keystore.store(baos, keystorepass.toCharArray());
170      data.put(OCSPKEYSTORE, new String JavaDoc(Base64.encode(baos.toByteArray())));
171      // Store OCSP KeyStore
172

173      setStatus(info.getStatus());
174      this.info = new OCSPCAServiceInfo(info.getStatus(),
175                                       getSubjectDN(),
176                                       getSubjectAltName(),
177                                       (String JavaDoc)data.get(KEYSPEC),
178                                       (String JavaDoc) data.get(KEYALGORITHM),
179                                        ocspcertificatechain);
180       
181    }
182
183    /*
184     * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
185     */

186    public void update(ExtendedCAServiceInfo serviceinfo, CA ca) throws Exception JavaDoc{
187        OCSPCAServiceInfo info = (OCSPCAServiceInfo) serviceinfo;
188        m_log.debug("OCSPCAService : update " + serviceinfo.getStatus());
189        setStatus(serviceinfo.getStatus());
190        if(info.getRenewFlag()){
191          // Renew The OCSP Signers certificate.
192
this.init(ca);
193        }
194              
195        // Only status is updated
196
this.info = new OCSPCAServiceInfo(serviceinfo.getStatus(),
197                                           getSubjectDN(),
198                                           getSubjectAltName(),
199                                           (String JavaDoc) data.get(KEYSPEC),
200                                           (String JavaDoc) data.get(KEYALGORITHM),
201                                           this.ocspcertificatechain);
202                                                                                                                                   
203    }
204
205
206
207     /*
208      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#extendedService(org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAServiceRequest)
209      */

210     public ExtendedCAServiceResponse extendedService(ExtendedCAServiceRequest request) throws ExtendedCAServiceRequestException, IllegalExtendedCAServiceRequestException,ExtendedCAServiceNotActiveException {
211         m_log.debug(">extendedService");
212         if (!(request instanceof OCSPCAServiceRequest)) {
213             throw new IllegalExtendedCAServiceRequestException();
214         }
215         if (this.getStatus() != ExtendedCAServiceInfo.STATUS_ACTIVE) {
216             String JavaDoc msg = intres.getLocalizedMessage("caservice.notactive");
217             m_log.error(msg);
218             throw new ExtendedCAServiceNotActiveException(msg);
219         }
220         ExtendedCAServiceResponse returnval = null;
221         OCSPCAServiceRequest ocspServiceReq = (OCSPCAServiceRequest)request;
222         List JavaDoc certChain = ocspcertificatechain;
223         if (ocspServiceReq.getCertificateChain() != null) {
224             m_log.debug("Using cert chain from CA");
225             certChain = ocspServiceReq.getCertificateChain();
226         }
227         X509Certificate JavaDoc signerCert = (X509Certificate JavaDoc)certChain.get(0);
228
229         String JavaDoc sigAlgs = ocspServiceReq.getSigAlg();
230         PublicKey JavaDoc pk = signerCert.getPublicKey();
231         String JavaDoc sigAlg = OCSPUtil.getSigningAlgFromAlgSelection(sigAlgs, pk);
232         m_log.debug("Signing algorithm: "+sigAlg);
233         boolean includeChain = ocspServiceReq.includeChain();
234         X509Certificate JavaDoc[] chain = null;
235         if (includeChain) {
236             chain = (X509Certificate JavaDoc[])certChain.toArray(new X509Certificate JavaDoc[0]);
237         }
238         try {
239             PrivateKey JavaDoc privKey = this.ocspsigningkey;
240             if (ocspServiceReq.getPrivKey() != null) {
241                 m_log.debug("Using private key from CA");
242                 privKey = ocspServiceReq.getPrivKey();
243             }
244             BasicOCSPResp ocspresp = OCSPUtil.generateBasicOCSPResp(ocspServiceReq, sigAlg, signerCert, privKey, ocspServiceReq.getPrivKeyProvider(), chain);
245             returnval = new OCSPCAServiceResponse(ocspresp, chain == null ? null : Arrays.asList(chain));
246         } catch (OCSPException ocspe) {
247             throw new ExtendedCAServiceRequestException(ocspe);
248         } catch (NoSuchProviderException JavaDoc nspe) {
249             throw new ExtendedCAServiceRequestException(nspe);
250         } catch (NotSupportedException e) {
251             m_log.error("Request type not supported: ", e);
252             throw new IllegalExtendedCAServiceRequestException(e);
253         } catch (IllegalArgumentException JavaDoc e) {
254             m_log.error("IllegalArgumentException: ", e);
255             throw new IllegalExtendedCAServiceRequestException(e);
256         }
257         m_log.debug("<extendedService");
258         return returnval;
259     }
260
261     
262     public float getLatestVersion() {
263         return LATEST_VERSION;
264     }
265
266     public void upgrade() {
267         if(Float.compare(LATEST_VERSION, getVersion()) != 0) {
268           // New version of the class, upgrade
269
String JavaDoc msg = intres.getLocalizedMessage("ocspcaservice.upgrade", new Float JavaDoc(getVersion()));
270             m_log.info(msg);
271             if(data.get(KEYSPEC) == null) {
272                 // Upgrade old rsa keysize to new general keyspec
273
Integer JavaDoc oldKeySize = (Integer JavaDoc)data.get(KEYSIZE);
274                 data.put(KEYSPEC, oldKeySize.toString());
275             }
276
277           data.put(VERSION, new Float JavaDoc(LATEST_VERSION));
278         }
279     }
280
281     /*
282      * @see org.ejbca.core.model.ca.caadmin.extendedcaservices.ExtendedCAService#getExtendedCAServiceInfo()
283      */

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