diff options
author | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-24 02:27:47 -0500 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-26 11:43:54 -0500 |
commit | 621d9e5c413e561293d7484b93882d985b3fe15f (patch) | |
tree | 638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/common/src/com/netscape/cms/servlet/ocsp | |
parent | 40d3643b8d91886bf210aa27f711731c81a11e49 (diff) | |
download | pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip |
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder.
This folder was created during svn migration and is no longer
needed. This folder has now been removed and the contents have
been moved up one level.
Ticket #131
Diffstat (limited to 'base/common/src/com/netscape/cms/servlet/ocsp')
7 files changed, 1969 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java new file mode 100644 index 000000000..1ef680853 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java @@ -0,0 +1,310 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Configure the CA to respond to OCSP requests for a CA + * + * @version $Revision$ $Date$ + */ +public class AddCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1065151608542115340L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + public static final BigInteger BIG_ZERO = new BigInteger("0"); + public static final Long MINUS_ONE = Long.valueOf(-1); + + private final static String TPL_FILE = "addCA.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST = + "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_3"; + private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED_3"; + + public AddCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCA.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param cert ca certificate. The format is base-64, DER encoded, wrapped with -----BEGIN CERTIFICATE-----, + * -----END CERTIFICATE----- strings + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST used when a CA is attempted to be added to the OCSP + * responder + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED used when an add CA request to the OCSP + * Responder is processed + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditCA = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditCASubjectDN = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("AddCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + String b64 = cmsReq.getHttpReq().getParameter("cert"); + + if (b64 == null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST, + auditSubjectID, + ILogger.FAILURE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_CERT")); + } + + auditCA = Cert.normalizeCertStr(Cert.stripCertBrackets(b64.trim())); + // record the fact that a request to add CA is made + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditCA); + + audit(auditMessage); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER")); + } + if (b64.indexOf(END_HEADER) == -1) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER")); + } + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + X509Certificate leafCert = null; + X509Certificate certs[] = null; + + try { + X509Certificate cert = Cert.mapCert(b64); + + if (cert == null) { + CMS.debug("AddCAServlet::process() - cert is null!"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new EBaseException("cert is null"); + } else { + certs = new X509Certificate[1]; + } + + certs[0] = cert; + leafCert = cert; + auditCASubjectDN = leafCert.getSubjectDN().getName(); + } catch (Exception e) { + } + if (certs == null) { + try { + // this could be a chain + certs = Cert.mapCertFromPKCS7(b64); + if (certs[0].getSubjectDN().getName().equals(certs[0].getIssuerDN().getName())) { + leafCert = certs[certs.length - 1]; + } else { + leafCert = certs[0]; + } + auditCASubjectDN = leafCert.getSubjectDN().getName(); + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR")); + } + } + if (certs != null && certs.length > 0) { + // (1) need to normalize (sort) the chain + + // (2) store certificate (and certificate chain) into + // database + ICRLIssuingPointRecord rec = defStore.createCRLIssuingPointRecord( + leafCert.getSubjectDN().getName(), + BIG_ZERO, + MINUS_ONE, null, null); + + try { + rec.set(ICRLIssuingPointRecord.ATTR_CA_CERT, leafCert.getEncoded()); + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + // error + } + defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec); + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CA certificate " + leafCert.getSubjectDN().getName()); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditCASubjectDN); + + audit(auditMessage); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java new file mode 100644 index 000000000..2dec0e1f5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java @@ -0,0 +1,591 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRLException; +import java.security.cert.X509CRL; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509ExtensionException; + +import org.mozilla.jss.CryptoManager; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.repository.IRepositoryRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Update the OCSP responder with a new CRL + * + * @version $Revision$ $Date$ + */ +public class AddCRLServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1476080474638590902L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE REVOCATION LIST-----"; + public static final String END_HEADER = + "-----END CERTIFICATE REVOCATION LIST-----"; + + private final static String TPL_FILE = "addCRL.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL = + "LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL_3"; + private final static String LOGGING_SIGNED_AUDIT_CRL_VALIDATION = + "LOGGING_SIGNED_AUDIT_CRL_VALIDATION_2"; + + public AddCRLServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCRL.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <P> + * + * <ul> + * <li>http.param crl certificate revocation list, base-64, DER encoded wrapped in -----BEGIN CERTIFICATE REVOCATION + * LIST-----, -----END CERTIFICATE REVOCATION LIST----- strings + * <li>http.param noui if true, use minimal hardcoded text response + * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL used when CRLs are retrieved by the OCSP Responder ("agent" + * or "EE") + * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_VALIDATION used when CRL is retrieved and validation process occurs + * ("agent" or "EE") + * </ul> + * + * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + protected synchronized void process(CMSRequest cmsReq) + throws EBaseException { + boolean CRLFetched = false; + boolean CRLValidated = false; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditCRLNum = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("add_crl", true /* main action */); + } + + try { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + return; + } + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + if (authToken != null) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("AddCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + } + log(ILogger.LL_INFO, "AddCRLServlet"); + String b64 = cmsReq.getHttpReq().getParameter("crl"); + if (CMS.debugOn()) + CMS.debug("AddCRLServlet: b64=" + b64); + + if (b64 == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CRL")); + } + + String nouiParm = cmsReq.getHttpReq().getParameter("noui"); + boolean noUI = false; + + if (nouiParm != null && nouiParm.equals("true")) { + noUI = true; + CMS.debug("AddCRLServlet: noUI=true"); + } else { + CMS.debug("AddCRLServlet: noUI=false"); + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + if (!noUI) { + form = getTemplate(mFormPath, req, locale); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, + e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CRL_HEADER")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), + "CMS_GW_MISSING_CRL_HEADER")); + } + if (b64.indexOf(END_HEADER) == -1) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CRL_FOOTER")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), + "CMS_GW_MISSING_CRL_FOOTER")); + } + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + X509CRLImpl crl = null; + + try { + long startTime = CMS.getCurrentDate().getTime(); + CMS.debug("AddCRLServlet: mapCRL start startTime=" + startTime); + if (statsSub != null) { + statsSub.startTiming("decode_crl"); + } + crl = mapCRL1(b64); + if (statsSub != null) { + statsSub.endTiming("decode_crl"); + } + long endTime = CMS.getCurrentDate().getTime(); + CMS.debug("AddCRLServlet: mapCRL done endTime=" + endTime + + " diff=" + (endTime - startTime)); + + // Retrieve the actual CRL number + BigInteger crlNum = crl.getCRLNumber(); + if (crlNum != null) { + auditCRLNum = crlNum.toString(); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.SUCCESS, + auditCRLNum); + + audit(auditMessage); + + // acknowledge that the CRL has been retrieved + CRLFetched = true; + } catch (Exception e) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + log(ILogger.LL_INFO, "AddCRLServlet: CRL Issuer DN " + + crl.getIssuerDN().getName()); + + ICRLIssuingPointRecord pt = null; + + try { + pt = defStore.readCRLIssuingPoint( + crl.getIssuerDN().getName()); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", + crl.getIssuerDN().getName())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + log(ILogger.LL_INFO, "AddCRLServlet: IssuingPoint " + + pt.getThisUpdate()); + + // verify CRL + byte caCertData[] = pt.getCACert(); + if (caCertData != null) { + try { + X509CertImpl caCert = new X509CertImpl(caCertData); + CMS.debug("AddCRLServlet: start verify"); + + CryptoManager cmanager = CryptoManager.getInstance(); + org.mozilla.jss.crypto.X509Certificate jssCert = null; + try { + jssCert = cmanager.importCACertPackage( + caCert.getEncoded()); + } catch (Exception e2) { + CMS.debug("AddCRLServlet: importCACertPackage " + + e2.toString()); + throw new EBaseException(e2.toString()); + } + + if (statsSub != null) { + statsSub.startTiming("verify_crl"); + } + crl.verify(jssCert.getPublicKey(), "Mozilla-JSS"); + if (statsSub != null) { + statsSub.endTiming("verify_crl"); + } + CMS.debug("AddCRLServlet: done verify"); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.SUCCESS); + + audit(auditMessage); + + // acknowledge that the CRL has been validated + CRLValidated = true; + } catch (Exception e) { + CMS.debug("AddCRLServlet: failed to verify CRL " + e.toString()); + CMS.debug(e); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", + crl.getIssuerDN().getName())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + } + + if ((pt.getThisUpdate() != null) && + (pt.getThisUpdate().getTime() >= + crl.getThisUpdate().getTime())) { + // error, the uploaded CRL is older than the current + CMS.debug("AddCRLServlet: no update, CRL is older"); + log(ILogger.LL_INFO, + "AddCRLServlet: no update, received CRL is older " + + "than current CRL"); + if (noUI) { + try { + resp.setContentType("application/text"); + resp.getOutputStream().write("status=1\n".getBytes()); + resp.getOutputStream().write( + "error=Sent CRL is older than the current CRL\n".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + return; + } catch (Exception e) { + } + } else { + CMS.debug("AddCRLServlet: CRL is older"); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + throw new ECMSGWException(CMS.getUserMessage( + "CMS_GW_OLD_CRL_ERROR")); + } + } + + if (crl.isDeltaCRL()) { + CMS.debug("AddCRLServlet: no update, Delta CRLs are not supported."); + log(ILogger.LL_INFO, "AddCRLServlet: no update, " + + CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED")); + if (noUI) { + try { + resp.setContentType("application/text"); + resp.getOutputStream().write("status=1\n".getBytes()); + resp.getOutputStream().write( + "error=Delta CRLs are not supported.\n".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + + return; + } catch (Exception e) { + } + } else { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED")); + } + } + + CMS.debug("AddCRLServlet: strt committing CRL"); + log(ILogger.LL_INFO, "AddCRLServlet: Start Committing CRL"); + + // ***************************************************** + // The commit transaction may take long time and + // there may have a system crash during the transaction + // ***************************************************** + + IRepositoryRecord repRec = defStore.createRepositoryRecord(); + + repRec.set(IRepositoryRecord.ATTR_SERIALNO, + new BigInteger(Long.toString(crl.getThisUpdate().getTime()))); + try { + defStore.addRepository( + crl.getIssuerDN().getName(), + Long.toString(crl.getThisUpdate().getTime()), + repRec); + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CRL Updated " + + Long.toString(crl.getThisUpdate().getTime())); + } catch (Exception e) { + CMS.debug("AddCRLServlet: add repository e=" + e.toString()); + } + log(ILogger.LL_INFO, "AddCRLServlet: Created CRL Repository " + + Long.toString(crl.getThisUpdate().getTime())); + + if (defStore.waitOnCRLUpdate()) { + defStore.updateCRL(crl); + } else { + // when the CRL large, the thread is terminiated by the + // servlet framework before it can finish its work + UpdateCRLThread uct = new UpdateCRLThread(defStore, crl); + + uct.start(); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (noUI) { + CMS.debug("AddCRLServlet: return result noUI=true"); + resp.setContentType("application/text"); + resp.getOutputStream().write("status=0".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + } else { + CMS.debug("AddCRLServlet: return result noUI=false"); + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } + } catch (IOException e) { + CMS.debug("AddCRLServlet: return result error=" + e.toString()); + mOCSPAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", + e.toString())); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } catch (EBaseException eAudit1) { + if (!CRLFetched) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + } else { + if (!CRLValidated) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + } + } + throw eAudit1; + } + if (statsSub != null) { + statsSub.endTiming("add_crl"); + } + } + + public X509CRLImpl mapCRL1(String mime64) + throws IOException { + mime64 = Cert.stripCRLBrackets(mime64.trim()); + + byte rawPub[] = CMS.AtoB(mime64); + X509CRLImpl crl = null; + + try { + crl = new X509CRLImpl(rawPub, false); + } catch (Exception e) { + throw new IOException(e.toString()); + } + return crl; + } +} + +class UpdateCRLThread extends Thread { + private IDefStore mDefStore = null; + private X509CRL mCRL = null; + + public UpdateCRLThread( + IDefStore defStore, X509CRL crl) { + mDefStore = defStore; + mCRL = crl; + } + + public void run() { + try { + if (!((X509CRLImpl) mCRL).areEntriesIncluded()) + mCRL = new X509CRLImpl(((X509CRLImpl) mCRL).getEncoded()); + mDefStore.updateCRL(mCRL); + } catch (CRLException e) { + } catch (X509ExtensionException e) { + } catch (EBaseException e) { + // ignore + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java new file mode 100644 index 000000000..dfe796366 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java @@ -0,0 +1,216 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.security.cert.X509CRLEntry; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Check the status of a specific certificate + * + * @version $Revision$ $Date$ + */ +public class CheckCertServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 7782198059640825050L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + public static final String ATTR_STATUS = "status"; + public static final String ATTR_ISSUERDN = "issuerDN"; + public static final String ATTR_SUBJECTDN = "subjectDN"; + public static final String ATTR_SERIALNO = "serialno"; + + public static final String STATUS_GOOD = "good"; + public static final String STATUS_REVOKED = "revoked"; + public static final String STATUS_UNKNOWN = "unknown"; + + private final static String TPL_FILE = "checkCert.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + public CheckCertServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "checkCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param cert certificate to check. Base64, DER encoded, wrapped in -----BEGIN CERTIFICATE-----, -----END + * CERTIFICATE----- strings + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "validate"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + String b64 = cmsReq.getHttpReq().getParameter("cert"); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + // error + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER")); + + } + if (b64.indexOf(END_HEADER) == -1) { + // error + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER")); + } + + X509Certificate cert = null; + + try { + cert = Cert.mapCert(b64); + } catch (Exception e) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR")); + } + if (cert == null) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR")); + } + + ICRLIssuingPointRecord pt = defStore.readCRLIssuingPoint( + cert.getIssuerDN().getName()); + + header.addStringValue(ATTR_ISSUERDN, cert.getIssuerDN().getName()); + header.addStringValue(ATTR_SUBJECTDN, cert.getSubjectDN().getName()); + header.addStringValue(ATTR_SERIALNO, "0x" + cert.getSerialNumber().toString(16)); + try { + X509CRLImpl crl = null; + + crl = new X509CRLImpl(pt.getCRL()); + X509CRLEntry crlentry = crl.getRevokedCertificate(cert.getSerialNumber()); + + if (crlentry == null) { + if (defStore.isNotFoundGood()) { + header.addStringValue(ATTR_STATUS, STATUS_GOOD); + } else { + header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN); + } + } else { + header.addStringValue(ATTR_STATUS, STATUS_REVOKED); + } + } catch (Exception e) { + header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN); + } + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Checked Certificate Status " + + cert.getIssuerDN().getName() + " " + cert.getSerialNumber().toString()); + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java b/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java new file mode 100644 index 000000000..3dfc1d5f3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java @@ -0,0 +1,164 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IOCSPService; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve information about the number of OCSP requests the OCSP + * has serviced + * + * @version $Revision$, $Date$ + */ +public class GetOCSPInfo extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -3633557968127876119L; + private final static String TPL_FILE = "getOCSPInfo.template"; + private String mFormPath = null; + + public GetOCSPInfo() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template + * file "getOCSPInfo.template" to render the result page. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + if (!(mAuthority instanceof IOCSPService)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IOCSPService ca = (IOCSPService) mAuthority; + + header.addLongValue("numReq", ca.getNumOCSPRequest()); + header.addLongValue("totalSec", ca.getOCSPRequestTotalTime()); + header.addLongValue("totalSignSec", ca.getOCSPTotalSignTime()); + header.addLongValue("totalLookupSec", ca.getOCSPTotalLookupTime()); + header.addLongValue("totalData", ca.getOCSPTotalData()); + long secs = 0; + if (ca.getOCSPRequestTotalTime() != 0) { + secs = (ca.getNumOCSPRequest() * 1000) / ca.getOCSPRequestTotalTime(); + } + header.addLongValue("ReqSec", secs); + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java new file mode 100644 index 000000000..a93512ccd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java @@ -0,0 +1,198 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Show the list of CA's that the OCSP responder can service + * + * @version $Revision$ $Date$ + */ +public class ListCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 3764395161795483452L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + private final static String TPL_FILE = "listCAs.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + public ListCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "listCAs.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + Enumeration<ICRLIssuingPointRecord> recs = defStore.searchAllCRLIssuingPointRecord(100); + + // show the current CRL number if present + header.addStringValue("stateCount", + Integer.toString(defStore.getStateCount())); + + while (recs.hasMoreElements()) { + ICRLIssuingPointRecord rec = recs.nextElement(); + IArgBlock rarg = CMS.createArgBlock(); + String thisId = rec.getId(); + + rarg.addStringValue("Id", thisId); + Date thisUpdate = rec.getThisUpdate(); + + if (thisUpdate == null) { + rarg.addStringValue("ThisUpdate", "UNKNOWN"); + } else { + rarg.addStringValue("ThisUpdate", thisUpdate.toString()); + } + Date nextUpdate = rec.getNextUpdate(); + + if (nextUpdate == null) { + rarg.addStringValue("NextUpdate", "UNKNOWN"); + } else { + rarg.addStringValue("NextUpdate", nextUpdate.toString()); + } + Long rc = rec.getCRLSize(); + + if (rc == null) { + rarg.addLongValue("NumRevoked", 0); + } else { + if (rc.longValue() == -1) { + rarg.addStringValue("NumRevoked", "UNKNOWN"); + } else { + rarg.addLongValue("NumRevoked", rc.longValue()); + } + } + + BigInteger crlNumber = rec.getCRLNumber(); + if (crlNumber == null || crlNumber.equals(new BigInteger("-1"))) { + rarg.addStringValue("CRLNumber", "UNKNOWN"); + } else { + rarg.addStringValue("CRLNumber", crlNumber.toString()); + } + + rarg.addLongValue("ReqCount", defStore.getReqCount(thisId)); + argSet.addRepeatRecord(rarg); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java new file mode 100644 index 000000000..3ab20141c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java @@ -0,0 +1,276 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mozilla.jss.asn1.ASN1Util; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.ocsp.IOCSPService; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.ocsp.BasicOCSPResponse; +import com.netscape.cmsutil.ocsp.OCSPRequest; +import com.netscape.cmsutil.ocsp.OCSPResponse; +import com.netscape.cmsutil.ocsp.ResponseBytes; +import com.netscape.cmsutil.ocsp.ResponseData; +import com.netscape.cmsutil.ocsp.SingleResponse; +import com.netscape.cmsutil.ocsp.TBSRequest; +import com.netscape.cmsutil.util.Utils; + +/** + * Process OCSP messages, According to RFC 2560 + * See http://www.ietf.org/rfc/rfc2560.txt + * + * @version $Revision$ $Date$ + */ +public class OCSPServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 120903601883352030L; + public final static String PROP_AUTHORITY = "authority"; + public final static String PROP_CLIENTAUTH = "GetClientCert"; + public final static String PROP_MAX_REQUEST_SIZE = "MaxRequestSize"; + public final static String PROP_ID = "ID"; + + private int m_maxRequestSize = 5000; + + public OCSPServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + String s = sc.getInitParameter(PROP_MAX_REQUEST_SIZE); + if (s != null) { + try { + m_maxRequestSize = Integer.parseInt(s); + } catch (Exception e) { + } + } + + } + + /** + * Process the HTTP request. + * This method is invoked when the OCSP service receives a OCSP + * request. Based on RFC 2560, the request should have the OCSP + * request in the HTTP body as binary blob. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("ocsp", true /* main action */); + } + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMS.debug("Servlet Path=" + httpReq.getServletPath()); + CMS.debug("RequestURI=" + httpReq.getRequestURI()); + String pathInfo = httpReq.getPathInfo(); + if (pathInfo != null && pathInfo.indexOf('%') != -1) { + try { + pathInfo = URLDecoder.decode(pathInfo, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + throw new EBaseException("OCSPServlet: Unsupported encoding" + e); + } + } + CMS.debug("PathInfo=" + pathInfo); + + OCSPRequest ocspReq = null; + + try { + InputStream is = httpReq.getInputStream(); + byte reqbuf[] = null; + String method = httpReq.getMethod(); + CMS.debug("Method=" + method); + if (method != null && method.equals("POST")) { + int reqlen = httpReq.getContentLength(); + + if (reqlen == -1) { + throw new Exception("OCSPServlet: Content-Length not supplied"); + } + if (reqlen == 0) { + throw new Exception("OCSPServlet: Invalid Content-Length"); + } + if (reqlen > m_maxRequestSize) { + throw new Exception("OCSPServlet: Client sending too much OCSP request data (" + reqlen + ")"); + } + + // for debugging + reqbuf = new byte[reqlen]; + int bytesread = 0; + boolean partial = false; + + while (bytesread < reqlen) { + int r = is.read(reqbuf, bytesread, reqlen - bytesread); + if (r == -1) { + throw new Exception("OCSPServlet: Client did not supply enough OCSP data"); + } + bytesread += r; + if (partial == false) { + if (bytesread < reqlen) { + partial = true; + } + } + } + is = new ByteArrayInputStream(reqbuf); + } else { + // GET method + if ((pathInfo == null) || + (pathInfo.equals("")) || + (pathInfo.substring(1) == null) || + (pathInfo.substring(1).equals(""))) { + throw new Exception("OCSPServlet: OCSP request not provided in GET method"); + } + is = new ByteArrayInputStream( + Utils.base64decode(pathInfo.substring(1))); + } + + // (1) retrieve OCSP request + // (2) decode request + OCSPResponse response = null; + + try { + OCSPRequest.Template reqTemplate = + new OCSPRequest.Template(); + + if ((is == null) || + (is.toString().equals(""))) { + throw new Exception("OCSPServlet: OCSP request is " + + "empty or malformed"); + } + ocspReq = (OCSPRequest) reqTemplate.decode(is); + if ((ocspReq == null) || + (ocspReq.toString().equals(""))) { + throw new Exception("OCSPServlet: Decoded OCSP request " + + "is empty or malformed"); + } + response = ((IOCSPService) mAuthority).validate(ocspReq); + } catch (Exception e) { + ; + CMS.debug("OCSPServlet: " + e.toString()); + } + + if (response != null) { + ByteArrayOutputStream fos1 = new ByteArrayOutputStream(); + + response.encode(fos1); + fos1.close(); + + byte[] respbytes; + + respbytes = fos1.toByteArray(); + + // print out OCSP response in debug mode so that + // we can validate the response + if (CMS.debugOn()) { + CMS.debug("OCSPServlet: OCSP Request:"); + CMS.debug("OCSPServlet: " + CMS.BtoA(ASN1Util.encode(ocspReq))); + TBSRequest tbsReq = ocspReq.getTBSRequest(); + for (int i = 0; i < tbsReq.getRequestCount(); i++) { + com.netscape.cmsutil.ocsp.Request req = tbsReq.getRequestAt(i); + CMS.debug("Serial Number: " + req.getCertID().getSerialNumber()); + } + CMS.debug("OCSPServlet: OCSP Response Size:"); + CMS.debug("OCSPServlet: " + Integer.toString(respbytes.length)); + CMS.debug("OCSPServlet: OCSP Response Data:"); + CMS.debug("OCSPServlet: " + CMS.BtoA(respbytes)); + ResponseBytes rbytes = response.getResponseBytes(); + if (rbytes == null) { + CMS.debug("Response bytes is null"); + } else if (rbytes.getObjectIdentifier().equals( + ResponseBytes.OCSP_BASIC)) { + BasicOCSPResponse basicRes = (BasicOCSPResponse) + BasicOCSPResponse.getTemplate().decode( + new ByteArrayInputStream(rbytes.getResponse().toByteArray())); + if (basicRes == null) { + CMS.debug("Basic Res is null"); + } else { + ResponseData data = basicRes.getResponseData(); + for (int i = 0; i < data.getResponseCount(); i++) { + SingleResponse res = data.getResponseAt(i); + CMS.debug("Serial Number: " + + res.getCertID().getSerialNumber() + + " Status: " + + res.getCertStatus().getClass().getName()); + } + } + } + } + + httpResp.setContentType("application/ocsp-response"); + + httpResp.setContentLength(respbytes.length); + OutputStream ooss = httpResp.getOutputStream(); + + ooss.write(respbytes); + ooss.flush(); + if (statsSub != null) { + statsSub.endTiming("ocsp"); + } + + mRenderResult = false; + } + } catch (Exception e) { + CMS.debug("OCSPServlet: " + e.toString()); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java new file mode 100644 index 000000000..4262940d0 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java @@ -0,0 +1,214 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.ocsp; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Configure the CA to no longer respond to OCSP requests for a CA + * + * @version $Revision: 1274 $ $Date: 2010-09-07 22:14:41 -0700 (Tue, 07 Sep 2010) $ + */ +public class RemoveCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -4519898238552366358L; + private final static String TPL_FILE = "removeCA.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_3"; + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS_3"; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE_3"; + + public RemoveCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCA.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param ca id. The format is string. + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST used when a CA is attempted to be removed from the + * OCSP responder + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS and + * LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE are used when a remove CA request to the OCSP + * Responder is processed successfully or not. + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("RemoveCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + + String caID = cmsReq.getHttpReq().getParameter("caID"); + + if (caID == null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE, + auditSubjectID, + ILogger.FAILURE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_ID")); + } + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + caID); + + audit(auditMessage); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + try { + defStore.deleteCRLIssuingPointRecord(caID); + + } catch (EBaseException e) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE, + auditSubjectID, + ILogger.FAILURE, + caID); + audit(auditMessage); + + CMS.debug("RemoveCAServlet::process: Error deleting CRL IssuingPoint: " + caID); + throw new EBaseException(e.toString()); + } + + CMS.debug("RemoveCAServlet::process: CRL IssuingPoint for CA successfully removed: " + caID); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + caID); + audit(auditMessage); + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} |