KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > protocol > ocsp > OCSPUnidExtension


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.protocol.ocsp;
15
16 import java.io.File JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.security.cert.CertificateException JavaDoc;
19 import java.security.cert.X509Certificate JavaDoc;
20 import java.sql.Connection JavaDoc;
21 import java.sql.PreparedStatement JavaDoc;
22 import java.sql.ResultSet JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 import javax.ejb.EJBException JavaDoc;
27 import javax.servlet.ServletConfig JavaDoc;
28 import javax.servlet.http.HttpServletRequest JavaDoc;
29
30 import org.apache.commons.lang.StringUtils;
31 import org.apache.log4j.Logger;
32 import org.bouncycastle.asn1.DEROctetString;
33 import org.bouncycastle.asn1.x509.X509Extension;
34 import org.bouncycastle.ocsp.CertificateStatus;
35 import org.ejbca.core.ejb.ServiceLocator;
36 import org.ejbca.core.model.InternalResources;
37 import org.ejbca.util.CertTools;
38 import org.ejbca.util.FileTools;
39 import org.ejbca.util.JDBCUtil;
40
41 /** ASN.1 OCSP extension used to map a UNID to a Fnr, OID for this extension is 2.16.578.1.16.3.2
42  *
43  * @author tomas
44  * @version $Id: OCSPUnidExtension.java,v 1.12 2006/12/13 10:35:30 anatom Exp $
45  *
46  */

47 public class OCSPUnidExtension implements IOCSPExtension {
48
49     private static final Logger m_log = Logger.getLogger(OCSPUnidExtension.class);
50     /** Internal localization of logs and errors */
51     private static final InternalResources intres = InternalResources.getInstance();
52
53     /** Constants capturing the possible error returned by the Unid-Fnr OCSP Extension
54      *
55      */

56     public static final int ERROR_NO_ERROR = 0;
57     public static final int ERROR_UNKNOWN = 1;
58     public static final int ERROR_UNAUTHORIZED = 2;
59     public static final int ERROR_NO_FNR_MAPPING = 3;
60     public static final int ERROR_NO_SERIAL_IN_DN = 4;
61     public static final int ERROR_SERVICE_UNAVAILABLE = 5;
62     public static final int ERROR_CERT_REVOKED = 6;
63     
64     private String JavaDoc dataSourceJndi;
65     private Hashtable JavaDoc trustedCerts = new Hashtable JavaDoc();
66     private X509Certificate JavaDoc cacert = null;
67     private int errCode = OCSPUnidExtension.ERROR_NO_ERROR;
68     
69     /** Called after construction
70      *
71      * @param config ServletConfig that can be used to read init-params from web-xml
72      */

73     public void init(ServletConfig JavaDoc config) {
74         // Datasource
75
dataSourceJndi = config.getInitParameter("unidDataSource");
76         if (StringUtils.isEmpty(dataSourceJndi)) {
77             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornoinitparam", "unidDataSource");
78             m_log.error(errMsg);
79             throw new IllegalArgumentException JavaDoc(errMsg);
80         }
81         String JavaDoc trustDir = config.getInitParameter("unidTrustDir");
82         if (StringUtils.isEmpty(trustDir)) {
83             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornoinitparam", "unidTrustDir");
84             m_log.error(errMsg);
85             throw new IllegalArgumentException JavaDoc(errMsg);
86         }
87         // read all files from trustDir, expect that they are PEM formatted certificates
88
CertTools.installBCProvider();
89         File JavaDoc dir = new File JavaDoc(trustDir);
90         try {
91             if (dir == null || dir.isDirectory() == false) {
92                 m_log.error(dir.getCanonicalPath()+ " is not a directory.");
93                 throw new IllegalArgumentException JavaDoc(dir.getCanonicalPath()+ " is not a directory.");
94             }
95             File JavaDoc files[] = dir.listFiles();
96             if (files == null || files.length == 0) {
97                 String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornotrustfiles", dir.getCanonicalPath());
98                 m_log.error(errMsg);
99             }
100             for ( int i=0; i<files.length; i++ ) {
101                 final String JavaDoc fileName = files[i].getCanonicalPath();
102                 // Read the file, don't stop completely if one file has errors in it
103
try {
104                     byte[] bytes = FileTools.getBytesFromPEM(FileTools.readFiletoBuffer(fileName),
105                             "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
106                     X509Certificate JavaDoc cert = CertTools.getCertfromByteArray(bytes);
107                     String JavaDoc key = CertTools.getIssuerDN(cert)+";"+cert.getSerialNumber().toString(16);
108                     trustedCerts.put(key,cert);
109                 } catch (CertificateException JavaDoc e) {
110                     String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorreadingfile", fileName, "trustDir", e.getMessage());
111                     m_log.error(errMsg, e);
112                 } catch (IOException JavaDoc e) {
113                     String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorreadingfile", fileName, "trustDir", e.getMessage());
114                     m_log.error(errMsg, e);
115                 }
116             }
117         } catch (IOException JavaDoc e) {
118             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorreadingtrustfiles", e.getMessage());
119             m_log.error(errMsg, e);
120             throw new IllegalArgumentException JavaDoc(errMsg);
121         }
122         String JavaDoc cacertfile = config.getInitParameter("unidCACert");
123         if (StringUtils.isEmpty(cacertfile)) {
124             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornoinitparam", "unidCACert");
125             m_log.error(errMsg);
126             throw new IllegalArgumentException JavaDoc(errMsg);
127         }
128         try {
129             byte[] bytes = FileTools.getBytesFromPEM(FileTools
130                     .readFiletoBuffer(cacertfile),
131                     "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
132             cacert = CertTools.getCertfromByteArray(bytes);
133         } catch (Exception JavaDoc e) {
134             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorreadingfile", "file", "cacertfile", e.getMessage());
135             m_log.error(errMsg, e);
136             throw new IllegalArgumentException JavaDoc(errMsg);
137         }
138
139     }
140     
141     /** Called by OCSP responder when the configured extension is found in the request.
142      *
143      * @param request HttpServletRequest that can be used to find out information about caller, TLS certificate etc.
144      * @param cert X509Certificate the caller asked for in the OCSP request
145      * @param status CertificateStatus the status the certificate has according to the OCSP responder, null means the cert is good
146      * @return X509Extension that will be added to responseExtensions by OCSP responder, or null if an error occurs
147      */

148     public Hashtable JavaDoc process(HttpServletRequest JavaDoc request, X509Certificate JavaDoc cert, CertificateStatus status) {
149         if (m_log.isDebugEnabled()) {
150             m_log.debug(">process()");
151         }
152         // Check authorization first
153
if (!checkAuthorization(request)) {
154             errCode = OCSPUnidExtension.ERROR_UNAUTHORIZED;
155             return null;
156         }
157         // If the certificate is revoked, we must not return an FNR
158
if (status != null) {
159             errCode = OCSPUnidExtension.ERROR_CERT_REVOKED;
160             return null;
161         }
162         Connection JavaDoc con = null;
163         PreparedStatement JavaDoc ps = null;
164         ResultSet JavaDoc result = null;
165         String JavaDoc fnr = null;
166         String JavaDoc sn = null;
167         try {
168             // The Unis is in the DN component serialNumber
169
sn = CertTools.getPartFromDN(cert.getSubjectDN().getName(), "SN");
170             if (sn != null) {
171                 if (m_log.isDebugEnabled()) {
172                     m_log.debug("Found serialNumber: "+sn);
173                 }
174                 String JavaDoc iMsg = intres.getLocalizedMessage("ocsp.receivedunidreq", request.getRemoteAddr(), request.getRemoteHost(), sn);
175                 m_log.info(iMsg);
176                 try {
177                     con = ServiceLocator.getInstance().getDataSource(dataSourceJndi).getConnection();
178                 } catch (SQLException JavaDoc e) {
179                     String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errordatabaseunid");
180                     m_log.error(errMsg, e);
181                     errCode = OCSPUnidExtension.ERROR_SERVICE_UNAVAILABLE;
182                     return null;
183                 }
184                 ps = con.prepareStatement("select fnr from UnidFnrMapping where unid=?");
185                 ps.setString(1, sn);
186                 result = ps.executeQuery();
187                 if (result.next()) {
188                     fnr = result.getString(1);
189                 }
190             } else {
191                 String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorunidnosnindn", cert.getSubjectDN().getName());
192                 m_log.error(errMsg);
193                 errCode = OCSPUnidExtension.ERROR_NO_SERIAL_IN_DN;
194                 return null;
195             }
196             if (m_log.isDebugEnabled()) {
197                 m_log.debug("<process()");
198             }
199         } catch (Exception JavaDoc e) {
200             throw new EJBException JavaDoc(e);
201         } finally {
202             JDBCUtil.close(con, ps, result);
203         }
204         
205         // Construct the response extentsion if we found a mapping
206
if (fnr == null) {
207             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorunidnosnmapping", sn);
208             m_log.error(errMsg);
209             errCode = OCSPUnidExtension.ERROR_NO_FNR_MAPPING;
210             return null;
211             
212         }
213         String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.returnedunidresponse", request.getRemoteAddr(), request.getRemoteHost(), fnr, sn);
214         m_log.info(errMsg);
215         FnrFromUnidExtension ext = new FnrFromUnidExtension(fnr);
216         Hashtable JavaDoc ret = new Hashtable JavaDoc();
217         ret.put(FnrFromUnidExtension.FnrFromUnidOid, new X509Extension(false, new DEROctetString(ext)));
218         return ret;
219     }
220     
221     /** Returns the last error that occured during process(), when process returns null
222      *
223      * @return error code as defined by implementing class
224      */

225     public int getLastErrorCode() {
226         return errCode;
227     }
228     
229     //
230
// Private methods
231
//
232
boolean checkAuthorization(HttpServletRequest JavaDoc request) {
233         X509Certificate JavaDoc[] certs = (X509Certificate JavaDoc[]) request.getAttribute("javax.servlet.request.X509Certificate");
234         if (certs == null) {
235             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornoclientauth", request.getRemoteAddr(), request.getRemoteHost());
236             m_log.error(errMsg);
237             return false;
238         }
239         // The entitys certificate is nr 0
240
X509Certificate JavaDoc cert = certs[0];
241         if (cert == null) {
242             String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errornoclientauth", request.getRemoteAddr(), request.getRemoteHost());
243             m_log.error(errMsg);
244             return false;
245         }
246         // Check if the certificate is authorized to access the Fnr
247
String JavaDoc key = CertTools.getIssuerDN(cert)+";"+cert.getSerialNumber().toString(16);
248         Object JavaDoc found = trustedCerts.get(key);
249         if (found != null) {
250             // If we found in the hashmap the same key with issuer and serialnumber, we know we got it.
251
// Just verify it as well to be damn sure
252
try {
253                 cert.verify(cacert.getPublicKey());
254             } catch (Exception JavaDoc e) {
255                 String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.errorverifycert");
256                 m_log.error(errMsg, e);
257                 return false;
258             }
259             // If verify was succesful we know if was good!
260
return true;
261         }
262         String JavaDoc errMsg = intres.getLocalizedMessage("ocsp.erroruntrustedclientauth", request.getRemoteAddr(), request.getRemoteHost());
263         m_log.error(errMsg);
264         return false;
265     }
266 }
267
Popular Tags