summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java')
-rw-r--r--pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java386
1 files changed, 386 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
new file mode 100644
index 000000000..67a829f9d
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
@@ -0,0 +1,386 @@
+// --- 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.cert;
+
+
+import com.netscape.cms.servlet.common.*;
+import com.netscape.cms.servlet.base.*;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Random;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateEncodingException;
+
+import netscape.security.x509.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.authorization.*;
+import com.netscape.certsrv.authentication.*;
+
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.ra.*;
+import com.netscape.certsrv.apps.*;
+
+
+/**
+ * Perform the first step in revoking a certificate
+ *
+ * @version $Revision$, $Date$
+ */
+public class RevocationServlet extends CMSServlet {
+ private final static String PROP_REVOKEBYDN = "revokeByDN";
+ // revocation templates.
+ private final static String TPL_FILE = "reasonToRevoke.template";
+
+ // http params
+ public static final String SERIAL_NO = "serialNo";
+ // XXX can't do pkcs10 cause it's got no serial no.
+ // (unless put serial no in pki attributes)
+ // public static final String PKCS10 = "pkcs10";
+ public static final String REASON_CODE = "reasonCode";
+
+ private String mFormPath = null;
+ private boolean mRevokeByDN = true;
+
+ private Random mRandom = null;
+ private Nonces mNonces = null;
+
+
+ public RevocationServlet() {
+ super();
+ }
+
+ /**
+ * initialize the servlet. This servlet uses
+ * the template file "reasonToRevoke.template" to render the
+ * result.
+ * @param sc servlet configuration, read from the web.xml file
+ */
+ public void init(ServletConfig sc) throws ServletException {
+ super.init(sc);
+ // override success template. has same info as enrollment.
+ mTemplates.remove(CMSRequest.SUCCESS);
+
+ mFormPath = "/" + TPL_FILE;
+ try {
+ mFormPath = sc.getInitParameter(
+ PROP_SUCCESS_TEMPLATE);
+ if (mFormPath == null)
+ mFormPath = "/" + TPL_FILE;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ if (((ICertificateAuthority) mAuthority).noncesEnabled()) {
+ mNonces = ((ICertificateAuthority) mAuthority).getNonces();
+ mRandom = new Random();
+ }
+ }
+
+ // set to false by revokeByDN=false in web.xml
+ mRevokeByDN = false;
+ String tmp = sc.getInitParameter(PROP_REVOKEBYDN);
+
+ if (tmp == null || tmp.trim().equalsIgnoreCase("false"))
+ mRevokeByDN = false;
+ else if (tmp.trim().equalsIgnoreCase("true"))
+ mRevokeByDN = true;
+ } catch (Exception e) {
+ }
+ }
+
+
+ /**
+ * Process the HTTP request. Note that this servlet does not
+ * actually perform the certificate revocation. This is the first
+ * step in the multi-step revocation process. (the next step is
+ * in the ReasonToRevoke servlet.
+ *
+ * @param cmsReq the object holding the request and response information
+ */
+ protected void process(CMSRequest cmsReq)
+ throws EBaseException {
+ IArgBlock httpParams = cmsReq.getHttpParams();
+ HttpServletRequest httpReq = cmsReq.getHttpReq();
+ HttpServletResponse httpResp = cmsReq.getHttpResp();
+
+ // revocation requires either:
+ // - coming from ee:
+ // - old cert from ssl client auth
+ // - old certs from auth manager
+ // - coming from agent or trusted RA:
+ // - serial no of cert to be revoked.
+
+ BigInteger old_serial_no = null;
+ X509CertImpl old_cert = null;
+ String revokeAll = null;
+
+ 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()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ IArgBlock header = CMS.createArgBlock();
+ IArgBlock ctx = CMS.createArgBlock();
+ CMSTemplateParams argSet = new CMSTemplateParams(header, ctx);
+
+ IAuthToken authToken = authenticate(cmsReq);
+
+ AuthzToken authzToken = null;
+
+ try {
+ authzToken = authorize(mAclMethod, authToken,
+ mAuthzResourceName, "submit");
+ } 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;
+ }
+
+ // coming from agent
+ if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) {
+ X509Certificate[] cert = new X509Certificate[1];
+
+ old_serial_no = getCertFromAgent(httpParams, cert);
+ old_cert = (X509CertImpl) cert[0];
+ } // coming from client
+ else {
+ // from auth manager
+ X509CertImpl[] cert = new X509CertImpl[1];
+
+ old_serial_no = getCertFromAuthMgr(authToken, cert);
+ old_cert = cert[0];
+ }
+
+ header.addStringValue("serialNumber", old_cert.getSerialNumber().toString(16));
+ header.addStringValue("serialNumberDecimal", old_cert.getSerialNumber().toString());
+ // header.addStringValue("subject", old_cert.getSubjectDN().toString());
+ // header.addLongValue("validNotBefore", old_cert.getNotBefore().getTime()/1000);
+ // header.addLongValue("validNotAfter", old_cert.getNotAfter().getTime()/1000);
+
+ if (mNonces != null) {
+ long n = mRandom.nextLong();
+ long m = mNonces.addNonce(n, (X509Certificate)old_cert);
+ if ((n + m) != 0) {
+ header.addStringValue("nonce", Long.toString(m));
+ }
+ }
+
+ boolean noInfo = false;
+ X509CertImpl[] certsToRevoke = null;
+
+ if (mAuthority instanceof ICertificateAuthority) {
+ certsToRevoke = ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificates(
+ old_cert.getSubjectDN().toString(),
+ ICertificateRepository.ALL_UNREVOKED_CERTS);
+
+ } else if (mAuthority instanceof IRegistrationAuthority) {
+ IRequest req = mRequestQueue.newRequest(IRequest.GETCERTS_REQUEST);
+ String filter = "(&(" + ICertRecord.ATTR_X509CERT + "." +
+ X509CertInfo.SUBJECT + "=" +
+ old_cert.getSubjectDN().toString() + ")(|(" +
+ ICertRecord.ATTR_CERT_STATUS + "=" +
+ ICertRecord.STATUS_VALID + ")(" +
+ ICertRecord.ATTR_CERT_STATUS + "=" +
+ ICertRecord.STATUS_EXPIRED + ")))";
+
+ req.setExtData(IRequest.CERT_FILTER, filter);
+ mRequestQueue.processRequest(req);
+ RequestStatus status = req.getRequestStatus();
+
+ if (status == RequestStatus.COMPLETE) {
+ header.addStringValue("request", req.getRequestId().toString());
+ Enumeration enum1 = req.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = (String) enum1.nextElement();
+
+ if (name.equals(IRequest.OLD_CERTS)) {
+ X509CertImpl[] certs = req.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ certsToRevoke = certs;
+ }
+ }
+ } else {
+ noInfo = true;
+ }
+ }
+
+ boolean authorized = false;
+
+ if (certsToRevoke != null && certsToRevoke.length > 0) {
+ for (int i = 0; i < certsToRevoke.length; i++) {
+ if (old_cert.getSerialNumber().equals(certsToRevoke[i].getSerialNumber())) {
+ authorized = true;
+ break;
+ }
+ }
+ }
+
+ if (!noInfo && (certsToRevoke == null || certsToRevoke.length == 0 ||
+ (!authorized))) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CA_CERT_ALREADY_REVOKED_1", old_serial_no.toString(16)));
+ throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CERT_ALREADY_REVOKED"));
+ }
+
+ if (!mRevokeByDN || noInfo) {
+ certsToRevoke = new X509CertImpl[1];
+ certsToRevoke[0] = old_cert;
+ try {
+ byte[] ba = old_cert.getEncoded();
+ // Do base 64 encoding
+
+ header.addStringValue("b64eCertificate", com.netscape.osutil.OSUtil.BtoA(ba));
+ } catch (CertificateEncodingException e) {
+ }
+ }
+
+ if (certsToRevoke != null && certsToRevoke.length > 0) {
+ header.addIntegerValue("totalRecordCount", certsToRevoke.length);
+ header.addIntegerValue("verifiedRecordCount", certsToRevoke.length);
+
+ for (int i = 0; i < certsToRevoke.length; i++) {
+ IArgBlock rarg = CMS.createArgBlock();
+
+ rarg.addStringValue("serialNumber",
+ certsToRevoke[i].getSerialNumber().toString(16));
+ rarg.addStringValue("serialNumberDecimal",
+ certsToRevoke[i].getSerialNumber().toString());
+ rarg.addStringValue("subject",
+ certsToRevoke[i].getSubjectDN().toString());
+ rarg.addLongValue("validNotBefore",
+ certsToRevoke[i].getNotBefore().getTime() / 1000);
+ rarg.addLongValue("validNotAfter",
+ certsToRevoke[i].getNotAfter().getTime() / 1000);
+ argSet.addRepeatRecord(rarg);
+ }
+ } else {
+ header.addIntegerValue("totalRecordCount", 0);
+ header.addIntegerValue("verifiedRecordCount", 0);
+ }
+
+ // set revocation reason, default to unspecified if not set.
+ int reasonCode = httpParams.getValueAsInt(REASON_CODE, 0);
+
+ header.addIntegerValue("reason", reasonCode);
+
+ 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_OUT_STREAM_TEMPLATE", e.toString()));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"));
+ }
+
+ return;
+ }
+
+ /**
+ * get cert to revoke from agent.
+ */
+ private BigInteger getCertFromAgent(
+ IArgBlock httpParams, X509Certificate[] certContainer)
+ throws EBaseException {
+ BigInteger serialno = null;
+ X509Certificate cert = null;
+
+ // get serial no
+ serialno = httpParams.getValueAsBigInteger(SERIAL_NO, null);
+ if (serialno == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_REVOKE"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_SERIALNO_FOR_REVOKE"));
+ }
+
+ // get cert from db if we're cert authority.
+ if (mAuthority instanceof ICertificateAuthority) {
+ cert = getX509Certificate(serialno);
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION"));
+ }
+ }
+ certContainer[0] = cert;
+ return serialno;
+ }
+
+ /**
+ * get cert to revoke from auth manager
+ */
+ private BigInteger getCertFromAuthMgr(
+ IAuthToken authToken, X509Certificate[] certContainer)
+ throws EBaseException {
+ X509CertImpl cert =
+ authToken.getInCert(AuthToken.TOKEN_CERT);
+
+ if (cert == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSGW_MISSING_CERTS_REVOKE_FROM_AUTHMGR"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_MISSING_CERTS_REVOKE_FROM_AUTHMGR"));
+ }
+ if (mAuthority instanceof ICertificateAuthority &&
+ !isCertFromCA(cert)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION"));
+ throw new ECMSGWException(
+ CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION"));
+ }
+ certContainer[0] = cert;
+ BigInteger serialno = ((X509Certificate) cert).getSerialNumber();
+
+ return serialno;
+ }
+
+}
+