From 621d9e5c413e561293d7484b93882d985b3fe15f Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Sat, 24 Mar 2012 02:27:47 -0500 Subject: 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 --- .../cms/servlet/cert/RevocationServlet.java | 392 +++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java (limited to 'base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java') diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java new file mode 100644 index 000000000..22aa29eda --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java @@ -0,0 +1,392 @@ +// --- 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 java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Random; + +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.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +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.base.Nonces; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +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.Utils; + +/** + * Perform the first step in revoking a certificate + * + * @version $Revision$, $Date$ + */ +public class RevocationServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -9086730404084717413L; + 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; + + 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 = 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", Utils.base64encode(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; + } + +} -- cgit