summaryrefslogtreecommitdiffstats
path: root/pki/base/ca/src
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/ca/src')
-rw-r--r--pki/base/ca/src/CMakeLists.txt57
-rw-r--r--pki/base/ca/src/com/netscape/ca/CAPolicy.java136
-rw-r--r--pki/base/ca/src/com/netscape/ca/CAService.java2077
-rw-r--r--pki/base/ca/src/com/netscape/ca/CMSCRLExtensions.java686
-rw-r--r--pki/base/ca/src/com/netscape/ca/CRLIssuingPoint.java3086
-rw-r--r--pki/base/ca/src/com/netscape/ca/CRLWithExpiredCerts.java74
-rw-r--r--pki/base/ca/src/com/netscape/ca/CertificateAuthority.java1968
-rw-r--r--pki/base/ca/src/com/netscape/ca/SigningUnit.java381
8 files changed, 8465 insertions, 0 deletions
diff --git a/pki/base/ca/src/CMakeLists.txt b/pki/base/ca/src/CMakeLists.txt
new file mode 100644
index 000000000..54dde47a8
--- /dev/null
+++ b/pki/base/ca/src/CMakeLists.txt
@@ -0,0 +1,57 @@
+project(pki-ca_java Java)
+
+# '/usr/share/java' jars
+find_file(LDAPJDK_JAR
+ NAMES
+ ldapjdk.jar
+ PATHS
+ /usr/share/java
+)
+
+
+# '/usr/lib/java' jars
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ /usr/lib/java
+)
+
+find_file(OSUTIL_JAR
+ NAMES
+ osutil.jar
+ PATHS
+ /usr/lib/java
+)
+
+
+# identify java sources
+set(pki-ca_java_SRCS
+ com/netscape/ca/CMSCRLExtensions.java
+ com/netscape/ca/CAService.java
+ com/netscape/ca/SigningUnit.java
+ com/netscape/ca/CRLWithExpiredCerts.java
+ com/netscape/ca/CRLIssuingPoint.java
+ com/netscape/ca/CAPolicy.java
+ com/netscape/ca/CertificateAuthority.java
+)
+
+
+# set classpath
+set(CMAKE_JAVA_INCLUDE_PATH
+ ${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_CMSCORE_JAR}
+ ${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR}
+ ${LDAPJDK_JAR}
+ ${JSS_JAR} ${OSUTIL_JAR} ${SYMKEY_JAR})
+
+
+# set version
+set(CMAKE_JAVA_TARGET_VERSION ${APPLICATION_VERSION})
+
+
+# build pki-ca.jar
+add_jar(pki-ca ${pki-ca_java_SRCS})
+add_dependencies(pki-ca osutil symkey pki-nsutil pki-cmsutil pki-certsrv pki-cms pki-cmscore)
+install_jar(pki-ca ${JAVA_JAR_INSTALL_DIR}/pki)
+set(PKI_CA_JAR ${pki-ca_JAR_FILE} CACHE INTERNAL "pki-ca jar file")
+
diff --git a/pki/base/ca/src/com/netscape/ca/CAPolicy.java b/pki/base/ca/src/com/netscape/ca/CAPolicy.java
new file mode 100644
index 000000000..8b2a48a3d
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CAPolicy.java
@@ -0,0 +1,136 @@
+// --- 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.ca;
+
+
+import com.netscape.certsrv.policy.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.profile.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+
+import com.netscape.cmscore.policy.*;
+import com.netscape.cmscore.util.Debug;
+
+
+/**
+ * XXX Just inherit 'GenericPolicyProcessor' (from RA) for now.
+ * This really bad. need to make a special case just for connector.
+ * would like a much better way of doing this to handle both EE and
+ * connectors.
+ * XXX2 moved to just implement IPolicy since GenericPolicyProcessor is
+ * unuseable for CA.
+ *
+ * @version $Revision$, $Date$
+ */
+public class CAPolicy implements IPolicy {
+ IConfigStore mConfig = null;
+ ICertificateAuthority mCA = null;
+
+ public static String PROP_PROCESSOR =
+ "processor";
+ // These are the different types of policy that are
+ // allowed for the "processor" property
+ public static String PR_TYPE_CLASSIC = "classic";
+
+ // XXX this way for now since generic just works for EE.
+ public GenericPolicyProcessor mPolicies = null;
+
+ public CAPolicy() {
+ }
+
+ public IPolicyProcessor getPolicyProcessor() {
+ return mPolicies;
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mCA = (ICertificateAuthority) owner;
+ mConfig = config;
+
+ String processorType = // XXX - need to upgrade 4.2
+ config.getString(PROP_PROCESSOR, PR_TYPE_CLASSIC);
+
+ Debug.trace("selected policy processor = " + processorType);
+ if (processorType.equals(PR_TYPE_CLASSIC)) {
+ mPolicies = new GenericPolicyProcessor();
+ } else {
+ throw new EBaseException("Unknown policy processor type (" +
+ processorType + ")");
+ }
+
+ mPolicies.init(mCA, mConfig);
+ }
+
+ public boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ */
+ public PolicyResult apply(IRequest r) {
+ if (r == null) {
+ Debug.trace("in CAPolicy.apply(request=null)");
+ return PolicyResult.REJECTED;
+ }
+
+ Debug.trace("in CAPolicy.apply(requestType=" +
+ r.getRequestType() + ",requestId=" +
+ r.getRequestId().toString() + ",requestStatus=" +
+ r.getRequestStatus().toString() + ")");
+
+ if (isProfileRequest(r)) {
+ Debug.trace("CAPolicy: Profile-base Request " +
+ r.getRequestId().toString());
+
+ CMS.debug("CAPolicy: requestId=" +
+ r.getRequestId().toString());
+
+ String profileId = r.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals("")) {
+ return PolicyResult.REJECTED;
+ }
+
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem("profile");
+
+ try {
+ IProfile profile = ps.getProfile(profileId);
+
+ r.setExtData("dbStatus", "NOT_UPDATED");
+ profile.populate(r);
+ profile.validate(r);
+ return PolicyResult.ACCEPTED;
+ } catch (EBaseException e) {
+ CMS.debug("CAPolicy: " + e.toString());
+ return PolicyResult.REJECTED;
+ }
+ }
+ Debug.trace("mPolicies = " + mPolicies.getClass());
+ return mPolicies.apply(r);
+ }
+
+}
+
diff --git a/pki/base/ca/src/com/netscape/ca/CAService.java b/pki/base/ca/src/com/netscape/ca/CAService.java
new file mode 100644
index 000000000..a63391d2e
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CAService.java
@@ -0,0 +1,2077 @@
+// --- 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.ca;
+
+
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.profile.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.connector.*;
+import com.netscape.cmscore.connector.*;
+import netscape.security.extensions.CertInfo;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.crmf.*;
+import com.netscape.cmscore.util.Debug;
+
+import netscape.security.x509.*;
+import netscape.security.util.BigInt;
+import netscape.security.util.*;
+import java.security.cert.*;
+import java.security.NoSuchAlgorithmException;
+import java.io.*;
+import java.util.*;
+import java.math.*;
+import java.security.*;
+
+
+/**
+ * Request Service for CertificateAuthority.
+ */
+public class CAService implements ICAService, IService {
+
+ public static final String CRMF_REQUEST = "CRMFRequest";
+ public static final String CHALLENGE_PHRASE = "challengePhrase";
+ public static final String SERIALNO_ARRAY = "serialNoArray";
+
+ // CCA->CLA connector
+ protected static IConnector mCLAConnector = null;
+
+ private ICertificateAuthority mCA = null;
+ private Hashtable mServants = new Hashtable();
+ private IConnector mKRAConnector = null;
+ private IConfigStore mConfig = null;
+ private boolean mArchivalRequired = true;
+ private Hashtable mCRLIssuingPoints = new Hashtable();
+
+ private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+ private final static String
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST =
+ "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST_4";
+
+ public CAService(ICertificateAuthority ca) {
+ mCA = ca;
+
+ // init services.
+ mServants.put(
+ IRequest.ENROLLMENT_REQUEST,
+ new serviceIssue(this));
+ mServants.put(
+ IRequest.RENEWAL_REQUEST,
+ new serviceRenewal(this));
+ mServants.put(
+ IRequest.REVOCATION_REQUEST,
+ new serviceRevoke(this));
+ mServants.put(
+ IRequest.CMCREVOKE_REQUEST,
+ new serviceRevoke(this));
+ mServants.put(
+ IRequest.REVOCATION_CHECK_CHALLENGE_REQUEST,
+ new serviceCheckChallenge(this));
+ mServants.put(
+ IRequest.GETCERTS_FOR_CHALLENGE_REQUEST,
+ new getCertsForChallenge(this));
+ mServants.put(
+ IRequest.UNREVOCATION_REQUEST,
+ new serviceUnrevoke(this));
+ mServants.put(
+ IRequest.GETCACHAIN_REQUEST,
+ new serviceGetCAChain(this));
+ mServants.put(
+ IRequest.GETCRL_REQUEST,
+ new serviceGetCRL(this));
+ mServants.put(
+ IRequest.GETREVOCATIONINFO_REQUEST,
+ new serviceGetRevocationInfo(this));
+ mServants.put(
+ IRequest.GETCERTS_REQUEST,
+ new serviceGetCertificates(this));
+ mServants.put(
+ IRequest.CLA_CERT4CRL_REQUEST,
+ new serviceCert4Crl(this));
+ mServants.put(
+ IRequest.CLA_UNCERT4CRL_REQUEST,
+ new serviceUnCert4Crl(this));
+ mServants.put(
+ IRequest.GETCERT_STATUS_REQUEST,
+ new getCertStatus(this));
+ }
+
+ public void init(IConfigStore config) throws EBaseException {
+ mConfig = config;
+
+ try {
+ // MOVED TO com.netscape.certsrv.apps.CMS
+ // java.security.Security.addProvider(new netscape.security.provider.CMS());
+ // java.security.Provider pr = java.security.Security.getProvider("CMS");
+ // if (pr != null) {
+ // ;
+ // }
+ // else
+ // Debug.trace("Something is wrong in CMS install !");
+ java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
+
+ Debug.trace("CertificateFactory Type : " + cf.getType());
+ Debug.trace("CertificateFactory Provider : " + cf.getProvider().getInfo());
+ } catch (java.security.cert.CertificateException e) {
+ Debug.trace("Something is happen in install CMS provider !" + e.toString());
+ }
+ }
+
+ public void startup() throws EBaseException {
+ IConfigStore kraConfig = mConfig.getSubStore("KRA");
+
+ if (kraConfig != null) {
+ mArchivalRequired = kraConfig.getBoolean(
+ "archivalRequired", true);
+ mKRAConnector = getConnector(kraConfig);
+ if (mKRAConnector != null) {
+ if (Debug.ON) {
+ Debug.trace("Started KRA Connector");
+ }
+ mKRAConnector.start();
+ }
+ }
+
+ // clone ca to CLA (clone master) connector
+ IConfigStore claConfig = mConfig.getSubStore("CLA");
+
+ if (claConfig != null) {
+ mCLAConnector = getConnector(claConfig);
+ if (mCLAConnector != null) {
+ CMS.debug(CMS.getLogMessage("CMSCORE_CA_START_CONNECTOR"));
+ if (Debug.ON) {
+ Debug.trace("Started CLA Connector in CCA");
+ }
+ mCLAConnector.start();
+ }
+ }
+ }
+
+ protected ICertificateAuthority getCA() {
+ return mCA;
+ }
+
+ public IConnector getKRAConnector() {
+ return mKRAConnector;
+ }
+
+ public void setKRAConnector(IConnector c) {
+ mKRAConnector = c;
+ }
+
+ public IConnector getConnector(IConfigStore config)
+ throws EBaseException {
+ IConnector connector = null;
+
+ if (config == null || config.size() <= 0) {
+ return null;
+ }
+ boolean enable = config.getBoolean("enable", true);
+ // provide a way to register a 3rd connector into RA
+ String extConnector = config.getString("class", null);
+
+ if (extConnector != null) {
+ try {
+ connector = (IConnector)
+ Class.forName(extConnector).newInstance();
+ // connector.start() will be called later on
+ return connector;
+ } catch (Exception e) {
+ // ignore external class if error
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_LOAD_CONNECTOR", extConnector, e.toString()));
+ }
+ }
+
+ if (!enable)
+ return null;
+ boolean local = config.getBoolean("local");
+ IAuthority authority = null;
+
+ if (local) {
+ String id = config.getString("id");
+
+ authority = (IAuthority) SubsystemRegistry.getInstance().get(id);
+ if (authority == null) {
+ String msg = "local authority " + id + " not found.";
+
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_AUTHORITY_NOT_FOUND", id));
+ throw new EBaseException(msg);
+ }
+ connector = new LocalConnector((ICertAuthority) mCA, authority);
+ // log(ILogger.LL_INFO, "local Connector to "+id+" inited");
+ } else {
+ String host = config.getString("host");
+ int port = config.getInteger("port");
+ String uri = config.getString("uri");
+ String nickname = config.getString("nickName", null);
+ int resendInterval = config.getInteger("resendInterval", -1);
+ // Inserted by beomsuk
+ int timeout = config.getInteger("timeout", 0);
+ // Insert end
+ // Changed by beomsuk
+ //RemoteAuthority remauthority =
+ // new RemoteAuthority(host, port, uri);
+ RemoteAuthority remauthority =
+ new RemoteAuthority(host, port, uri, timeout);
+
+ // Change end
+ if (nickname == null)
+ nickname = mCA.getNickname();
+ // Changed by beomsuk
+ //connector =
+ // new HttpConnector(mCA, nickname, remauthority, resendInterval);
+ if (timeout == 0)
+ connector = new HttpConnector((IAuthority) mCA, nickname, remauthority, resendInterval, config);
+ else
+ connector = new HttpConnector((IAuthority) mCA, nickname, remauthority, resendInterval, config, timeout);
+ // Change end
+
+ // log(ILogger.LL_INFO, "remote authority "+
+ // host+":"+port+" "+uri+" inited");
+ }
+ return connector;
+ }
+
+ public boolean isProfileRequest(IRequest request) {
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals(""))
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ * After population of defaults, and constraint validation,
+ * the profile request is processed here.
+ */
+ public void serviceProfileRequest(IRequest request)
+ throws EBaseException {
+ CMS.debug("CAService: serviceProfileRequest requestId=" +
+ request.getRequestId().toString());
+
+ String profileId = request.getExtDataInString("profileId");
+
+ if (profileId == null || profileId.equals("")) {
+ throw new EBaseException("profileId not found");
+ }
+
+ IProfileSubsystem ps = (IProfileSubsystem)
+ CMS.getSubsystem("profile");
+ IProfile profile = null;
+
+ try {
+ profile = ps.getProfile(profileId);
+ } catch (EProfileException e) {
+ }
+ if (profile == null) {
+ throw new EProfileException("Profile not found " + profileId);
+ }
+
+ // assumed rejected
+ request.setExtData("dbStatus", "NOT_UPDATED");
+
+ // profile.populate(request);
+ profile.validate(request);
+ profile.execute(request);
+
+ // This function is called only from ConnectorServlet
+
+ // serialize to request queue
+ }
+
+ /**
+ * method interface for IService
+ * <P>
+ *
+ * <ul>
+ * <li>signed.audit LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST used
+ * whenever a user private key archive request is made. This is an option
+ * in a cert enrollment request detected by an RA or a CA, so, if selected,
+ * it should be logged immediately following the certificate request.
+ * </ul>
+ * @param request a certificate enrollment request from an RA or CA
+ * @return true or false
+ */
+ public boolean serviceRequest(IRequest request) {
+ String auditMessage = null;
+ String auditSubjectID = auditSubjectID();
+ String auditRequesterID = auditRequesterID();
+ String auditArchiveID = ILogger.SIGNED_AUDIT_NON_APPLICABLE;
+
+ boolean completed = false;
+
+ // short cut profile-based request
+ if (isProfileRequest(request)) {
+ try {
+ CMS.debug("CAServic: x0 requestStatus=" + request.getRequestStatus().toString() + " instance=" + request);
+ serviceProfileRequest(request);
+ request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
+ CMS.debug("CAServic: x1 requestStatus=" + request.getRequestStatus().toString());
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return true;
+ } catch (EBaseException e) {
+ CMS.debug("CAServic: x2 requestStatus=" + request.getRequestStatus().toString());
+ // need to put error into the request
+ CMS.debug("CAService: serviceRequest " + e.toString());
+ request.setExtData(IRequest.RESULT, IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR, e.toString());
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return false;
+ }
+ }
+
+ String type = request.getRequestType();
+ IServant servant = (IServant) mServants.get(type);
+
+ if (servant == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_INVALID_REQUEST_TYPE", type));
+ request.setExtData(IRequest.RESULT, IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR,
+ new ECAException(CMS.getUserMessage("CMS_CA_UNRECOGNIZED_REQUEST_TYPE", type)));
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return true;
+ }
+
+ try {
+ // send request to KRA first
+ if (type.equals(IRequest.ENROLLMENT_REQUEST) &&
+ isPKIArchiveOptionPresent(request) && mKRAConnector != null) {
+ if (Debug.ON) {
+ Debug.trace("*** Sending enrollment request to KRA");
+ }
+ boolean sendStatus = mKRAConnector.send(request);
+
+ if (mArchivalRequired == true) {
+ if (sendStatus == false) {
+ request.setExtData(IRequest.RESULT,
+ IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR,
+ new ECAException(CMS.getUserMessage("CMS_CA_SEND_KRA_REQUEST")));
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return true;
+ } else {
+ if (request.getExtDataInString(IRequest.ERROR) != null) {
+ request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
+ request.deleteExtData(IRequest.ERROR);
+ }
+ }
+ if (request.getExtDataInString(IRequest.ERROR) != null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return true;
+ }
+ }
+ } else {
+ if (Debug.ON) {
+ Debug.trace("*** NOT Send to KRA type=" + type + " ENROLLMENT=" + IRequest.ENROLLMENT_REQUEST);
+ }
+ }
+
+ completed = servant.service(request);
+ request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
+ } catch (EBaseException e) {
+ request.setExtData(IRequest.RESULT, IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR, e);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return true;
+ }
+
+ // XXX in case of key archival this may not always be the case.
+ if (Debug.ON)
+ Debug.trace("serviceRequest completed = " + completed);
+
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_PRIVATE_KEY_ARCHIVE_REQUEST,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditArchiveID);
+
+ audit(auditMessage);
+
+ return completed;
+ }
+
+ /**
+ * register CRL Issuing Point
+ */
+ public void addCRLIssuingPoint(String id, ICRLIssuingPoint crlIssuingPoint) {
+ mCRLIssuingPoints.put(id, crlIssuingPoint);
+ }
+
+ /**
+ * get CRL Issuing Point
+ */
+ public Hashtable getCRLIssuingPoints() {
+ return mCRLIssuingPoints;
+ }
+
+ /**
+ * Checks if PKIArchiveOption present in the request.
+ */
+ private boolean isPKIArchiveOptionPresent(IRequest request) {
+ String crmfBlob = request.getExtDataInString(
+ IRequest.HTTP_PARAMS, CRMF_REQUEST);
+
+ if (crmfBlob == null) {
+ if (Debug.ON) {
+ Debug.trace("CRMF not found");
+ }
+ } else {
+ try {
+ PKIArchiveOptionsContainer opts[] = CRMFParser.getPKIArchiveOptions(crmfBlob);
+
+ if (opts != null) {
+ return true;
+ }
+ } catch (IOException e) {
+ }
+ return false;
+ }
+ return false;
+ }
+
+ ///
+ /// CA related routines.
+ ///
+
+ public X509CertImpl issueX509Cert(X509CertInfo certi)
+ throws EBaseException {
+ return issueX509Cert(certi, null, null);
+ }
+
+ /**
+ * issue cert for enrollment.
+ */
+ public X509CertImpl issueX509Cert(X509CertInfo certi, String profileId, String rid)
+ throws EBaseException {
+ CMS.debug("issueX509Cert");
+ X509CertImpl certImpl = issueX509Cert("", certi, false, null);
+
+ CMS.debug("storeX509Cert " + certImpl.getSerialNumber());
+ storeX509Cert(profileId, rid, certImpl);
+ CMS.debug("done storeX509Cert");
+ return certImpl;
+ }
+
+ X509CertImpl issueX509Cert(String rid, X509CertInfo certi)
+ throws EBaseException {
+ return issueX509Cert(rid, certi, false, null);
+ }
+
+ /**
+ * issue cert for enrollment.
+ */
+ void storeX509Cert(String profileId, String rid, X509CertImpl cert)
+ throws EBaseException {
+ storeX509Cert(rid, cert, false, null, null, null, profileId);
+ }
+
+ /**
+ * issue cert for enrollment.
+ */
+ void storeX509Cert(String rid, X509CertImpl cert, String crmfReqId)
+ throws EBaseException {
+ storeX509Cert(rid, cert, false, null, crmfReqId, null, null);
+ }
+
+ void storeX509Cert(String rid, X509CertImpl cert, String crmfReqId,
+ String challengePassword) throws EBaseException {
+ storeX509Cert(rid, cert, false, null, crmfReqId, challengePassword, null);
+ }
+
+ /**
+ * issue cert for enrollment and renewal.
+ * renewal is expected to have original cert serial no. in cert info
+ * field.
+ */
+ X509CertImpl issueX509Cert(String rid, X509CertInfo certi,
+ boolean renewal, BigInteger oldSerialNo)
+ throws EBaseException {
+ String algname = null;
+ X509CertImpl cert = null;
+
+ // NOTE: In this implementation, the "oldSerialNo"
+ // parameter is NOT used!
+
+ boolean doUTF8 = mConfig.getBoolean("dnUTF8Encoding", false);
+
+ CMS.debug("dnUTF8Encoding " + doUTF8);
+
+ try {
+ // check required fields in certinfo.
+ if (certi.get(X509CertInfo.SUBJECT) == null ||
+ certi.get(X509CertInfo.KEY) == null) {
+
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_MISSING_ATTR"));
+ // XXX how do you reject a request in the service object ?
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_REQD_FIELDS_IN_CERTISSUE"));
+ }
+
+ // set default cert version. If policies added a extensions
+ // the version would already be set to version 3.
+ if (certi.get(X509CertInfo.VERSION) == null) {
+ certi.set(X509CertInfo.VERSION, mCA.getDefaultCertVersion());
+ }
+
+ // set default validity if not set.
+ // validity would normally be set by policies or by
+ // agent or by authentication module.
+ CertificateValidity validity = (CertificateValidity)
+ certi.get(X509CertInfo.VALIDITY);
+ Date begin = null, end = null;
+
+ if (validity != null) {
+ begin = (Date)
+ validity.get(CertificateValidity.NOT_BEFORE);
+ end = (Date)
+ validity.get(CertificateValidity.NOT_AFTER);
+ }
+ if (validity == null ||
+ (begin.getTime() == 0 && end.getTime() == 0)) {
+ if (Debug.ON) {
+ Debug.trace("setting default validity");
+ }
+
+ begin = CMS.getCurrentDate();
+ end = new Date(begin.getTime() + mCA.getDefaultValidity());
+ certi.set(CertificateValidity.NAME,
+ new CertificateValidity(begin, end));
+ }
+
+ /*
+ * For non-CA certs, check if validity exceeds CA time.
+ * If so, set to CA's not after if default validity
+ * exceeds ca's not after.
+ */
+
+ // First find out if it is a CA cert
+ boolean is_ca = false;
+ CertificateExtensions exts = null;
+ BasicConstraintsExtension bc_ext = null;
+
+ try {
+ exts = (CertificateExtensions)
+ certi.get(X509CertInfo.EXTENSIONS);
+ if (exts != null) {
+ Enumeration e = exts.getElements();
+
+ while (e.hasMoreElements()) {
+ Extension ext = (Extension) e.nextElement();
+
+ if (ext.getExtensionId().toString().equals(PKIXExtensions.BasicConstraints_Id.toString())) {
+ bc_ext = (BasicConstraintsExtension) ext;
+ }
+ }
+
+ if(bc_ext != null) {
+ Boolean isCA = (Boolean) bc_ext.get(BasicConstraintsExtension.IS_CA);
+ is_ca = isCA.booleanValue();
+ }
+ } // exts != null
+ } catch (Exception e) {
+ CMS.debug("EnrollDefault: getExtension " + e.toString());
+ }
+
+ Date caNotAfter =
+ mCA.getSigningUnit().getCertImpl().getNotAfter();
+
+ if (begin.after(caNotAfter)) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_PAST_VALIDITY"));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CERT_BEGIN_AFTER_CA_VALIDITY"));
+ }
+
+ if (end.after(caNotAfter)) {
+ if(!is_ca) {
+ if (!mCA.isEnablePastCATime()) {
+ end = caNotAfter;
+ certi.set(CertificateValidity.NAME,
+ new CertificateValidity(begin, caNotAfter));
+ CMS.debug("CAService: issueX509Cert: cert past CA's NOT_AFTER...ca.enablePastCATime != true...resetting");
+ } else {
+ CMS.debug("CAService: issueX509Cert: cert past CA's NOT_AFTER...ca.enablePastCATime = true...not resetting");
+ }
+ } else {
+ CMS.debug("CAService: issueX509Cert: CA cert issuance past CA's NOT_AFTER.");
+ } //!is_ca
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_PAST_NOT_AFTER"));
+ }
+
+ // check algorithm in certinfo.
+ AlgorithmId algid = null;
+ CertificateAlgorithmId algor = (CertificateAlgorithmId)
+ certi.get(X509CertInfo.ALGORITHM_ID);
+
+ if (algor == null || algor.toString().equals(CertInfo.SERIALIZE_ALGOR.toString())) {
+ algname = mCA.getSigningUnit().getDefaultAlgorithm();
+ algid = AlgorithmId.get(algname);
+ certi.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(algid));
+ } else {
+ algid = (AlgorithmId)
+ algor.get(CertificateAlgorithmId.ALGORITHM);
+ algname = algid.getName();
+ }
+ } catch (CertificateException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_BAD_FIELD", e.toString()));
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_ERROR_GETTING_FIELDS_IN_ISSUE"));
+ } catch (IOException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_BAD_FIELD", e.toString()));
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_ERROR_GETTING_FIELDS_IN_ISSUE"));
+ } catch (NoSuchAlgorithmException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname));
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ }
+
+ // get old cert serial number if renewal
+ if (renewal) {
+ try {
+ CertificateSerialNumber serialno = (CertificateSerialNumber)
+ certi.get(X509CertInfo.SERIAL_NUMBER);
+
+ if (serialno == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NULL_SERIAL_NUMBER"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ SerialNumber serialnum = (SerialNumber)
+ serialno.get(CertificateSerialNumber.NUMBER);
+
+ if (serialnum == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NULL_SERIAL_NUMBER"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ } catch (CertificateException e) {
+ // not possible
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_ORG_SERIAL", e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ } catch (IOException e) {
+ // not possible.
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_ORG_SERIAL", e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ }
+
+ // set issuer, serial number
+ try {
+ BigInteger serialNo =
+ mCA.getCertificateRepository().getNextSerialNumber();
+
+ certi.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber(serialNo));
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_SIGN_SERIAL", serialNo.toString(16)));
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_NEXT_SERIAL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_NOSERIALNO", rid));
+ } catch (CertificateException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_SERIAL", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SET_SERIALNO_FAILED", rid));
+ } catch (IOException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_SERIAL", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SET_SERIALNO_FAILED", rid));
+ }
+
+ try {
+ certi.set(X509CertInfo.ISSUER,
+ new CertificateIssuerName(mCA.getX500Name()));
+ } catch (CertificateException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_ISSUER", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_SET_ISSUER_FAILED", rid));
+ } catch (IOException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_ISSUER", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_SET_ISSUER_FAILED", rid));
+ }
+
+ byte[] utf8_encodingOrder = { DerValue.tag_UTF8String };
+
+ if (doUTF8 == true) {
+ try {
+
+ CMS.debug("doUTF8 true, updating subject.");
+ CertificateSubjectName sName = (CertificateSubjectName) certi.get(X509CertInfo.SUBJECT);
+
+ String subject = certi.get(X509CertInfo.SUBJECT).toString();
+
+ certi.set(X509CertInfo.SUBJECT, new CertificateSubjectName(
+ new X500Name(subject,
+ new LdapV3DNStrConverter(X500NameAttrMap.getDirDefault(), true), utf8_encodingOrder)));
+
+ } catch (CertificateException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_SUBJECT", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_SET_ISSUER_FAILED", rid));
+ } catch (IOException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SET_SUBJECT", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_SET_ISSUER_FAILED", rid));
+ }
+ }
+
+ CMS.debug("About to mCA.sign cert.");
+ cert = mCA.sign(certi, algname);
+ return cert;
+ }
+
+ void storeX509Cert(String rid, X509CertImpl cert,
+ boolean renewal, BigInteger oldSerialNo)
+ throws EBaseException {
+ storeX509Cert(rid, cert, renewal, oldSerialNo, null, null, null);
+ }
+
+ void storeX509Cert(String rid, X509CertImpl cert,
+ boolean renewal, BigInteger oldSerialNo, String crmfReqId,
+ String challengePassword, String profileId) throws EBaseException {
+ // now store in repository.
+ // if renewal, set the old serial number in the new cert,
+ // set the new serial number in the old cert.
+
+ CMS.debug("In storeX509Cert");
+ try {
+ BigInteger newSerialNo = cert.getSerialNumber();
+ MetaInfo metaInfo = new MetaInfo();
+
+ if (profileId != null)
+ metaInfo.set("profileId", profileId);
+ if (rid != null)
+ metaInfo.set(CertRecord.META_REQUEST_ID, rid);
+ if (challengePassword != null && !challengePassword.equals(""))
+ metaInfo.set("challengePhrase", challengePassword);
+ if (crmfReqId != null) {
+ //System.out.println("Adding crmf reqid "+crmfReqId);
+ metaInfo.set(CertRecord.META_CRMF_REQID, crmfReqId);
+ }
+ if (renewal)
+ metaInfo.set(CertRecord.META_OLD_CERT, oldSerialNo.toString());
+ mCA.getCertificateRepository().addCertificateRecord(
+ new CertRecord(newSerialNo, cert, metaInfo));
+
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_STORE_SERIAL", cert.getSerialNumber().toString(16)));
+ if (renewal) {
+
+ /*
+ mCA.getCertificateRepository().markCertificateAsRenewed(
+ BigIntegerMapper.BigIntegerToDB(oldSerialNo));
+ mCA.mCertRepot.markCertificateAsRenewed(oldSerialNo);
+ */
+ MetaInfo oldMeta = null;
+ CertRecord oldCertRec = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(oldSerialNo);
+
+ if (oldCertRec == null) {
+ Exception e =
+ new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR",
+ "Cannot read cert record for " + oldSerialNo));
+
+ e.printStackTrace();
+ }
+ if (oldCertRec != null)
+ oldMeta = oldCertRec.getMetaInfo();
+ if (oldMeta == null) {
+ if (Debug.ON) {
+ Debug.trace("No meta info! for " + oldSerialNo);
+ }
+ oldMeta = new MetaInfo();
+ } else {
+ if (Debug.ON) {
+ System.out.println("Old meta info");
+ Enumeration n = oldMeta.getElements();
+
+ while (n.hasMoreElements()) {
+ String name = (String) n.nextElement();
+
+ System.out.println("name " + name + " value " +
+ oldMeta.get(name));
+ }
+ }
+ }
+ oldMeta.set(CertRecord.META_RENEWED_CERT,
+ newSerialNo.toString());
+ ModificationSet modSet = new ModificationSet();
+
+ modSet.add(CertRecord.ATTR_AUTO_RENEW,
+ Modification.MOD_REPLACE,
+ CertRecord.AUTO_RENEWAL_DONE);
+ modSet.add(ICertRecord.ATTR_META_INFO,
+ Modification.MOD_REPLACE, oldMeta);
+ mCA.getCertificateRepository().modifyCertificateRecord(oldSerialNo, modSet);
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_MARK_SERIAL", oldSerialNo.toString(16), newSerialNo.toString(16)));
+ if (Debug.ON) {
+ CertRecord check = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(oldSerialNo);
+ MetaInfo meta = check.getMetaInfo();
+
+ Enumeration n = oldMeta.getElements();
+
+ while (n.hasMoreElements()) {
+ String name = (String) n.nextElement();
+
+ }
+ }
+ }
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_STORE_SERIAL", cert.getSerialNumber().toString(16)));
+ if (Debug.ON)
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ /**
+ * revoke cert, check fields in crlentry, etc.
+ */
+ public void revokeCert(RevokedCertImpl crlentry)
+ throws EBaseException {
+ revokeCert(crlentry, null);
+ }
+
+ public void revokeCert(RevokedCertImpl crlentry, String requestId)
+ throws EBaseException {
+ BigInteger serialno = crlentry.getSerialNumber();
+ Date revdate = crlentry.getRevocationDate();
+ CRLExtensions crlentryexts = crlentry.getExtensions();
+
+ CertRecord certRec = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(serialno);
+
+ if (certRec == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_NOT_FOUND", serialno.toString(16)));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL",
+ "0x" + serialno.toString(16)));
+ }
+ RevocationInfo revInfo = (RevocationInfo) certRec.getRevocationInfo();
+ CRLExtensions exts = null;
+ CRLReasonExtension reasonext = null;
+
+ if (revInfo != null)
+ exts = revInfo.getCRLEntryExtensions();
+ if (exts != null) {
+ try {
+ reasonext = (CRLReasonExtension)
+ exts.get(CRLReasonExtension.NAME);
+ } catch (X509ExtensionException e) {
+ // this means no crl reason extension set.
+ }
+ }
+ // allow revoking certs that are on hold.
+ String certStatus = certRec.getStatus();
+
+ if (certStatus.equals(ICertRecord.STATUS_REVOKED) ||
+ certStatus.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CERT_ALREADY_REVOKED",
+ "0x" + Long.toHexString(serialno.longValue())));
+ }
+ try {
+ mCA.getCertificateRepository().markAsRevoked(serialno,
+ new RevocationInfo(revdate, crlentryexts));
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_CERT_REVOKED",
+ serialno.toString(16)));
+ // inform all CRLIssuingPoints about revoked certificate
+ Enumeration eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement();
+
+ if (ip != null) {
+ boolean b = true;
+
+ if (ip.isCACertsOnly()) {
+ X509CertImpl cert = certRec.getCertificate();
+
+ if (cert != null) b = cert.getBasicConstraintsIsCA();
+ }
+ if (ip.isProfileCertsOnly()) {
+ MetaInfo metaInfo = certRec.getMetaInfo();
+ if (metaInfo != null) {
+ String profileId = (String)metaInfo.get("profileId");
+ if (profileId != null) {
+ b = ip.checkCurrentProfile(profileId);
+ }
+ }
+ }
+ if (b) ip.addRevokedCert(serialno, crlentry, requestId);
+ }
+ }
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_REVOCATION", serialno.toString(), e.toString()));
+ //e.printStackTrace();
+ throw e;
+ }
+ return;
+ }
+
+ /**
+ * unrevoke cert, check serial number, etc.
+ */
+ void unrevokeCert(BigInteger serialNo)
+ throws EBaseException {
+ unrevokeCert(serialNo, null);
+ }
+
+ void unrevokeCert(BigInteger serialNo, String requestId)
+ throws EBaseException {
+ CertRecord certRec = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(serialNo);
+
+ if (certRec == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_NOT_FOUND", serialNo.toString(16)));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL",
+ "0x" + serialNo.toString(16)));
+ }
+ RevocationInfo revInfo = (RevocationInfo) certRec.getRevocationInfo();
+ CRLExtensions exts = null;
+ CRLReasonExtension reasonext = null;
+
+ if (revInfo == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_ON_HOLD", serialNo.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_IS_NOT_ON_HOLD",
+ serialNo.toString()));
+ }
+ exts = revInfo.getCRLEntryExtensions();
+ if (exts != null) {
+ try {
+ reasonext = (CRLReasonExtension)
+ exts.get(CRLReasonExtension.NAME);
+ } catch (X509ExtensionException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_ON_HOLD", serialNo.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_IS_NOT_ON_HOLD",
+ serialNo.toString()));
+ }
+ } else {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_ON_HOLD", serialNo.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_IS_NOT_ON_HOLD",
+ serialNo.toString()));
+ }
+ // allow unrevoking certs that are on hold.
+ if ((certRec.getStatus().equals(ICertRecord.STATUS_REVOKED) ||
+ certRec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED)) &&
+ reasonext != null &&
+ reasonext.getReason() == RevocationReason.CERTIFICATE_HOLD) {
+ try {
+ mCA.getCertificateRepository().unmarkRevoked(serialNo, revInfo,
+ certRec.getRevokedOn(), certRec.getRevokedBy());
+ mCA.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_CERT_UNREVOKED", serialNo.toString(16)));
+ // inform all CRLIssuingPoints about unrevoked certificate
+ Enumeration eIPs = mCRLIssuingPoints.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement();
+
+ if (ip != null) {
+ boolean b = true;
+
+ if (ip.isCACertsOnly()) {
+ X509CertImpl cert = certRec.getCertificate();
+
+ if (cert != null) b = cert.getBasicConstraintsIsCA();
+ }
+ if (ip.isProfileCertsOnly()) {
+ MetaInfo metaInfo = certRec.getMetaInfo();
+ if (metaInfo != null) {
+ String profileId = (String)metaInfo.get("profileId");
+ if (profileId != null) {
+ b = ip.checkCurrentProfile(profileId);
+ }
+ }
+ }
+ if (b) ip.addUnrevokedCert(serialNo, requestId);
+ }
+ }
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_ERROR_UNREVOKE", serialNo.toString(16)));
+ throw e;
+ }
+ } else {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_ON_HOLD", serialNo.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_IS_NOT_ON_HOLD",
+ "0x" + serialNo.toString(16)));
+ }
+
+ return;
+ }
+
+ /**
+ * Signed Audit Log
+ *
+ * This method is called to store messages to the signed audit log.
+ * <P>
+ *
+ * @param msg signed audit log message
+ */
+ private void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
+ /**
+ * Signed Audit Log Subject ID
+ *
+ * This method is called to obtain the "SubjectID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message SubjectID
+ */
+ private String auditSubjectID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String subjectID = null;
+
+ // Initialize subjectID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ subjectID = (String)
+ auditContext.get(SessionContext.USER_ID);
+
+ if (subjectID != null) {
+ subjectID = subjectID.trim();
+ } else {
+ subjectID = ILogger.NONROLEUSER;
+ }
+ } else {
+ subjectID = ILogger.UNIDENTIFIED;
+ }
+
+ return subjectID;
+ }
+
+ /**
+ * Signed Audit Log Requester ID
+ *
+ * This method is called to obtain the "RequesterID" for
+ * a signed audit log message.
+ * <P>
+ *
+ * @return id string containing the signed audit log message RequesterID
+ */
+ private String auditRequesterID() {
+ // if no signed audit object exists, bail
+ if (mSignedAuditLogger == null) {
+ return null;
+ }
+
+ String requesterID = null;
+
+ // Initialize requesterID
+ SessionContext auditContext = SessionContext.getExistingContext();
+
+ if (auditContext != null) {
+ requesterID = (String)
+ auditContext.get(SessionContext.REQUESTER_ID);
+
+ if (requesterID != null) {
+ requesterID = requesterID.trim();
+ } else {
+ requesterID = ILogger.UNIDENTIFIED;
+ }
+ } else {
+ requesterID = ILogger.UNIDENTIFIED;
+ }
+
+ return requesterID;
+ }
+}
+
+
+///
+/// servant classes
+///
+
+interface IServant {
+ public boolean service(IRequest request) throws EBaseException;
+}
+
+
+class serviceIssue implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceIssue(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ // XXX This is ugly. should associate attributes with
+ // request types, not policy.
+ // XXX how do we know what to look for in request ?
+
+ if (request.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null)
+ return serviceX509(request);
+ else
+ return false; // Don't know what it is ?????
+ }
+
+ public boolean serviceX509(IRequest request)
+ throws EBaseException {
+ // XXX This is ugly. should associate attributes with
+ // request types, not policy.
+ // XXX how do we know what to look for in request ?
+ X509CertInfo certinfos[] =
+ request.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (certinfos == null || certinfos[0] == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_REQUEST_NOT_FOUND", request.getRequestId().toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_ISSUEREQ"));
+ }
+ String challengePassword =
+ request.getExtDataInString(CAService.CHALLENGE_PHRASE);
+
+ X509CertImpl[] certs = new X509CertImpl[certinfos.length];
+ String rid = request.getRequestId().toString();
+ int i;
+
+ for (i = 0; i < certinfos.length; i++) {
+ try {
+ certs[i] = mService.issueX509Cert(rid, certinfos[i]);
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUE_ERROR", Integer.toString(i), rid, e.toString()));
+ throw e;
+ }
+ }
+ String crmfReqId = request.getExtDataInString(IRequest.CRMF_REQID);
+ EBaseException ex = null;
+
+ for (i = 0; i < certs.length; i++) {
+ try {
+ mService.storeX509Cert(rid, certs[i], crmfReqId, challengePassword);
+ } catch (EBaseException e) {
+ e.printStackTrace();
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_STORE_ERROR", Integer.toString(i), rid, e.toString()));
+ ex = e; // save to throw later.
+ break;
+ }
+ }
+ if (ex != null) {
+ for (int j = 0; j < i; j++) {
+ // delete the stored cert records from the database.
+ // we issue all or nothing.
+ BigInteger serialNo =
+ ((X509Certificate) certs[i]).getSerialNumber();
+
+ try {
+ mCA.getCertificateRepository().deleteCertificateRecord(serialNo);
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_DELETE_CERT_ERROR", serialNo.toString(), e.toString()));
+ }
+ }
+ throw ex;
+ }
+
+ request.setExtData(IRequest.ISSUED_CERTS, certs);
+
+ return true;
+ }
+}
+
+
+class serviceRenewal implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceRenewal(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ // XXX if one fails should all fail ? - can't backtrack.
+ X509CertInfo certinfos[] =
+ request.getExtDataInCertInfoArray(IRequest.CERT_INFO);
+
+ if (certinfos == null || certinfos[0] == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT_REQUEST_NOT_FOUND", request.getRequestId().toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ X509CertImpl issuedCerts[] = new X509CertImpl[certinfos.length];
+
+ for (int j = 0; j < issuedCerts.length; j++)
+ issuedCerts[j] = null;
+ String svcerrors[] = new String[certinfos.length];
+
+ for (int k = 0; k < svcerrors.length; k++)
+ svcerrors[k] = null;
+ String rid = request.getRequestId().toString();
+
+ for (int i = 0; i < certinfos.length; i++) {
+ try {
+ // get old serial number.
+ SerialNumber serialnum = null;
+
+ try {
+ CertificateSerialNumber serialno = (CertificateSerialNumber)
+ certinfos[i].get(X509CertInfo.SERIAL_NUMBER);
+
+ if (serialno == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NULL_SERIAL_NUMBER"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ serialnum = (SerialNumber)
+ serialno.get(CertificateSerialNumber.NUMBER);
+ } catch (IOException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ } catch (CertificateException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ if (serialnum == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ERROR_GET_CERT", ""));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_RENEWREQ"));
+ }
+ BigInt serialnumBigInt = serialnum.getNumber();
+ BigInteger oldSerialNo = serialnumBigInt.toBigInteger();
+
+ // get cert record
+ CertRecord certRecord = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(oldSerialNo);
+
+ if (certRecord == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NOT_FROM_CA", oldSerialNo.toString()));
+ svcerrors[i] = new ECAException(
+ CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL",
+ oldSerialNo.toString())).toString();
+ continue;
+ }
+
+ // check if cert has been revoked.
+ String certStatus = certRecord.getStatus();
+
+ if (certStatus.equals(ICertRecord.STATUS_REVOKED) ||
+ certStatus.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_RENEW_REVOKED", oldSerialNo.toString()));
+ svcerrors[i] = new ECAException(
+ CMS.getUserMessage("CMS_CA_CANNOT_RENEW_REVOKED_CERT",
+ "0x" + oldSerialNo.toString(16))).toString();
+ continue;
+ }
+
+ // check if cert has already been renewed.
+ MetaInfo metaInfo = certRecord.getMetaInfo();
+
+ if (metaInfo != null) {
+ String renewed = (String)
+ metaInfo.get(certRecord.META_RENEWED_CERT);
+
+ if (renewed != null) {
+ BigInteger serial = new BigInteger(renewed);
+ X509CertImpl cert = (X509CertImpl)
+ mCA.getCertificateRepository().getX509Certificate(serial);
+
+ if (cert == null) {
+ // something wrong
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_MISSING_RENEWED", serial.toString()));
+ svcerrors[i] = new ECAException(
+ CMS.getUserMessage("CMS_CA_ERROR_GETTING_RENEWED_CERT",
+ oldSerialNo.toString(), serial.toString())).toString();
+ continue;
+ }
+ // get cert record
+ CertRecord cRecord = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(serial);
+
+ if (cRecord == null) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NOT_FROM_CA", serial.toString()));
+ svcerrors[i] = new ECAException(
+ CMS.getUserMessage("CMS_CA_CANT_FIND_CERT_SERIAL",
+ serial.toString())).toString();
+ continue;
+ }
+ // Check renewed certificate already REVOKED or EXPIRED
+ String status = cRecord.getStatus();
+
+ if (status.equals(ICertRecord.STATUS_REVOKED) ||
+ status.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
+ Debug.trace("It is already revoked or Expired !!!");
+ } // it is still new ... So just return this certificate to user
+ else {
+ Debug.trace("It is still new !!!");
+ issuedCerts[i] = cert;
+ continue;
+ }
+ }
+ }
+
+ // issue the cert.
+ issuedCerts[i] =
+ mService.issueX509Cert(rid, certinfos[i], true, oldSerialNo);
+ mService.storeX509Cert(rid, issuedCerts[i], true, oldSerialNo);
+ } catch (ECAException e) {
+ svcerrors[i] = e.toString();
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CANNOT_RENEW", Integer.toString(i), request.getRequestId().toString()));
+ }
+ }
+
+ // always set issued certs regardless of error.
+ request.setExtData(IRequest.ISSUED_CERTS, issuedCerts);
+
+ // set and throw error if any.
+ int l;
+
+ for (l = svcerrors.length - 1; l >= 0 && svcerrors[l] == null; l--);
+ if (l >= 0) {
+ request.setExtData(IRequest.SVCERRORS, svcerrors);
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_NO_RENEW", request.getRequestId().toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_RENEW_FAILED"));
+ }
+ return true;
+ }
+}
+
+
+class getCertsForChallenge implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public getCertsForChallenge(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ BigInteger[] serialNoArray =
+ request.getExtDataInBigIntegerArray(CAService.SERIALNO_ARRAY);
+ X509CertImpl[] certs = new X509CertImpl[serialNoArray.length];
+
+ for (int i = 0; i < serialNoArray.length; i++) {
+ certs[i] = mCA.getCertificateRepository().getX509Certificate(serialNoArray[i]);
+ }
+ request.setExtData(IRequest.OLD_CERTS, certs);
+ return true;
+ }
+}
+
+
+class getCertStatus implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public getCertStatus(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request) throws EBaseException {
+ BigInteger serialno = request.getExtDataInBigInteger("serialNumber");
+ String issuerDN = request.getExtDataInString("issuerDN");
+ CertificateRepository certDB = (CertificateRepository)
+ mCA.getCertificateRepository();
+
+ String status = null;
+
+ if (serialno != null) {
+ CertRecord record = null;
+
+ try {
+ record = (CertRecord) certDB.readCertificateRecord(serialno);
+ } catch (EBaseException ee) {
+ Debug.trace(ee.toString());
+ }
+
+ if (record != null) {
+ status = record.getStatus();
+ if (status.equals("VALID")) {
+ X509CertImpl cacert = mCA.getCACert();
+ Principal p = cacert.getSubjectDN();
+
+ if (!p.toString().equals(issuerDN)) {
+ status = "INVALIDCERTROOT";
+ }
+ }
+ }
+ }
+
+ request.setExtData(IRequest.CERT_STATUS, status);
+ return true;
+ }
+}
+
+
+class serviceCheckChallenge implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+ private MessageDigest mSHADigest = null;
+
+ public serviceCheckChallenge(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ try {
+ mSHADigest = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ }
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ // note: some request attributes used below are set in
+ // authentication/ChallengePhraseAuthentication.java :(
+ BigInteger serialno = request.getExtDataInBigInteger("serialNumber");
+ String pwd = request.getExtDataInString(
+ CAService.CHALLENGE_PHRASE);
+ CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository();
+ BigInteger[] bigIntArray = null;
+
+ if (serialno != null) {
+ CertRecord record = null;
+
+ try {
+ record = (CertRecord) certDB.readCertificateRecord(serialno);
+ } catch (EBaseException ee) {
+ Debug.trace(ee.toString());
+ }
+ if (record != null) {
+ String status = record.getStatus();
+
+ if (status.equals("VALID")) {
+ boolean samepwd = compareChallengePassword(record, pwd);
+
+ if (samepwd) {
+ bigIntArray = new BigInteger[1];
+ bigIntArray[0] = record.getSerialNumber();
+ }
+ } else {
+ bigIntArray = new BigInteger[0];
+ }
+ } else
+ bigIntArray = new BigInteger[0];
+ } else {
+ String subjectName = request.getExtDataInString("subjectName");
+
+ if (subjectName != null) {
+ String filter = "(&(x509cert.subject=" + subjectName + ")(certStatus=VALID))";
+ ICertRecordList list = certDB.findCertRecordsInList(filter, null, 10);
+ int size = list.getSize();
+ Enumeration en = list.getCertRecords(0, size - 1);
+
+ if (!en.hasMoreElements()) {
+ bigIntArray = new BigInteger[0];
+ } else {
+ Vector idv = new Vector();
+
+ while (en.hasMoreElements()) {
+ CertRecord record = (CertRecord) en.nextElement();
+ boolean samepwd = compareChallengePassword(record, pwd);
+
+ if (samepwd) {
+ BigInteger id = record.getSerialNumber();
+
+ idv.addElement(id);
+ }
+ }
+ bigIntArray = new BigInteger[idv.size()];
+ idv.copyInto(bigIntArray);
+ }
+ }
+ }
+
+ if (bigIntArray == null)
+ bigIntArray = new BigInteger[0];
+
+ request.setExtData(CAService.SERIALNO_ARRAY, bigIntArray);
+ return true;
+ }
+
+ private boolean compareChallengePassword(CertRecord record, String pwd)
+ throws EBaseException {
+ MetaInfo metaInfo = (MetaInfo) record.get(CertRecord.ATTR_META_INFO);
+
+ if (metaInfo == null) {
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", "metaInfo"));
+ }
+
+ String hashpwd = hashPassword(pwd);
+
+ // got metaInfo
+ String challengeString =
+ (String) metaInfo.get(CertRecord.META_CHALLENGE_PHRASE);
+
+ if (!challengeString.equals(hashpwd)) {
+ return false;
+ } else
+ return true;
+ }
+
+ private String hashPassword(String pwd) {
+ String salt = "lala123";
+ byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes());
+ String b64E = com.netscape.osutil.OSUtil.BtoA(pwdDigest);
+
+ return "{SHA}" + b64E;
+ }
+}
+
+
+class serviceRevoke implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceRevoke(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ boolean sendStatus = true;
+ // XXX Need to think passing as array.
+ // XXX every implemented according to servlet.
+ RevokedCertImpl crlentries[] =
+ request.getExtDataInRevokedCertArray(IRequest.CERT_INFO);
+
+ if (crlentries == null ||
+ crlentries.length == 0 ||
+ crlentries[0] == null) {
+ // XXX should this be an error ?
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRL_NOT_FOUND", request.getRequestId().toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_REVREQ"));
+ }
+
+ RevokedCertImpl revokedCerts[] =
+ new RevokedCertImpl[crlentries.length];
+ String svcerrors[] = null;
+
+ for (int i = 0; i < crlentries.length; i++) {
+ try {
+ mService.revokeCert(crlentries[i], request.getRequestId().toString());
+ revokedCerts[i] = crlentries[i];
+ } catch (ECAException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CANNOT_REVOKE", Integer.toString(i), request.getRequestId().toString(), e.toString()));
+ revokedCerts[i] = null;
+ if (svcerrors == null) {
+ svcerrors = new String[revokedCerts.length];
+ }
+ svcerrors[i] = e.toString();
+ }
+ }
+
+ // #605941 - request.get(IRequest.CERT_INFO) store exact same thing
+ // request.set(IRequest.REVOKED_CERTS, revokedCerts);
+
+ // if clone ca, send revoked cert records to CLA
+ if (CAService.mCLAConnector != null) {
+ CMS.debug(CMS.getLogMessage("CMSCORE_CA_CLONE_READ_REVOKED"));
+ BigInteger revokedCertIds[] =
+ new BigInteger[revokedCerts.length];
+
+ for (int i = 0; i < revokedCerts.length; i++) {
+ revokedCertIds[i] = revokedCerts[i].getSerialNumber();
+ }
+ request.deleteExtData(IRequest.CERT_INFO);
+ request.deleteExtData(IRequest.OLD_CERTS);
+ request.setExtData(IRequest.REVOKED_CERT_RECORDS, revokedCertIds);
+
+ CMS.debug(CMS.getLogMessage("CMSCORE_CA_CLONE_READ_REVOKED_CONNECTOR"));
+
+ request.setRequestType(IRequest.CLA_CERT4CRL_REQUEST);
+ sendStatus = CAService.mCLAConnector.send(request);
+ if (sendStatus == false) {
+ request.setExtData(IRequest.RESULT,
+ IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR,
+ new ECAException(CMS.getUserMessage("CMS_CA_SEND_CLA_REQUEST")));
+ return sendStatus;
+ } else {
+ if (request.getExtDataInString(IRequest.ERROR) != null) {
+ request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
+ request.deleteExtData(IRequest.ERROR);
+ }
+ }
+ if (request.getExtDataInString(IRequest.ERROR) != null) {
+ return sendStatus;
+ }
+ }
+
+ if (svcerrors != null) {
+ request.setExtData(IRequest.SVCERRORS, svcerrors);
+ throw new ECAException(CMS.getUserMessage("CMS_CA_REVOKE_FAILED"));
+ }
+
+ if (Debug.ON) {
+ Debug.trace("serviceRevoke sendStatus=" + sendStatus);
+ }
+
+ return sendStatus;
+ }
+}
+
+
+class serviceUnrevoke implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceUnrevoke(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ boolean sendStatus = true;
+ BigInteger oldSerialNo[] =
+ request.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+
+ if (oldSerialNo == null || oldSerialNo.length < 1) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER"));
+ }
+
+ String svcerrors[] = null;
+ boolean needOldCerts = false;
+ X509CertImpl oldCerts[] = request.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCerts == null || oldCerts.length < 1) {
+ needOldCerts = true;
+ oldCerts = new X509CertImpl[oldSerialNo.length];
+ }
+
+ for (int i = 0; i < oldSerialNo.length; i++) {
+ try {
+ if (oldSerialNo[i].compareTo(new BigInteger("0")) < 0) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER"));
+ }
+ if (needOldCerts) {
+ CertRecord certRec = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(oldSerialNo[i]);
+
+ oldCerts[i] = certRec.getCertificate();
+ }
+ mService.unrevokeCert(oldSerialNo[i], request.getRequestId().toString());
+ } catch (ECAException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_FAILED", oldSerialNo[i].toString(), request.getRequestId().toString()));
+ if (svcerrors == null) {
+ svcerrors = new String[oldSerialNo.length];
+ }
+ svcerrors[i] = e.toString();
+ }
+ }
+
+ // if clone ca, send unrevoked cert serials to CLA
+ if (CAService.mCLAConnector != null) {
+ request.setRequestType(IRequest.CLA_UNCERT4CRL_REQUEST);
+ sendStatus = CAService.mCLAConnector.send(request);
+ if (sendStatus == false) {
+ request.setExtData(IRequest.RESULT,
+ IRequest.RES_ERROR);
+ request.setExtData(IRequest.ERROR,
+ new ECAException(CMS.getUserMessage("CMS_CA_SEND_CLA_REQUEST")));
+ return sendStatus;
+ } else {
+ if (request.getExtDataInString(IRequest.ERROR) != null) {
+ request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS);
+ request.deleteExtData(IRequest.ERROR);
+ }
+ }
+
+ }
+
+ if (needOldCerts) {
+ request.setExtData(IRequest.OLD_CERTS, oldCerts);
+ }
+
+ if (svcerrors != null) {
+ request.setExtData(IRequest.SVCERRORS, svcerrors);
+ throw new ECAException(CMS.getUserMessage("CMS_CA_UNREVOKE_FAILED"));
+ }
+
+ return sendStatus;
+ }
+}
+
+
+class serviceGetCAChain implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceGetCAChain(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request) throws EBaseException {
+ CertificateChain certChain = mCA.getCACertChain();
+ ByteArrayOutputStream certChainOut = new ByteArrayOutputStream();
+ try {
+ certChain.encode(certChainOut);
+ } catch (IOException e) {
+ mCA.log(ILogger.LL_FAILURE, e.toString());
+ throw new EBaseException(e.toString());
+ }
+ request.setExtData(IRequest.CACERTCHAIN, certChainOut.toByteArray());
+ return true;
+ }
+}
+
+
+class serviceGetCRL implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceGetCRL(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ try {
+ ICRLIssuingPointRecord crlRec =
+ (ICRLIssuingPointRecord) mCA.getCRLRepository().readCRLIssuingPointRecord(mCA.PROP_MASTER_CRL);
+ X509CRLImpl crl = new X509CRLImpl(crlRec.getCRL());
+
+ request.setExtData(IRequest.CRL, crl.getEncoded());
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_FIND_CRL"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_NOT_FOUND", e.toString()));
+ } catch (CRLException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_INST_CRL", mCA.PROP_MASTER_CRL));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_NOGOOD", mCA.PROP_MASTER_CRL));
+ } catch (X509ExtensionException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_GETCRL_NO_ISSUING_REC"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUEPT_EXT_NOGOOD",
+ mCA.PROP_MASTER_CRL));
+ }
+ return true;
+ }
+}
+
+
+class serviceGetRevocationInfo implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceGetRevocationInfo(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ Enumeration enum1 = request.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = (String) enum1.nextElement();
+
+ if (name.equals(IRequest.ISSUED_CERTS)) {
+ X509CertImpl certsToCheck[] =
+ request.getExtDataInCertArray(IRequest.ISSUED_CERTS);
+
+ CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository();
+ RevocationInfo info =
+ certDB.isCertificateRevoked(certsToCheck[0]);
+
+ if (info != null) {
+ RevokedCertImpl revokedCerts[] = new RevokedCertImpl[1];
+ RevokedCertImpl revokedCert = new RevokedCertImpl(
+ certsToCheck[0].getSerialNumber(),
+ info.getRevocationDate(),
+ info.getCRLEntryExtensions());
+
+ revokedCerts[0] = revokedCert;
+ request.setExtData(IRequest.REVOKED_CERTS, revokedCerts);
+ }
+ }
+ }
+ return true;
+ }
+}
+
+
+class serviceGetCertificates implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceGetCertificates(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ Enumeration enum1 = request.getExtDataKeys();
+
+ while (enum1.hasMoreElements()) {
+ String name = (String) enum1.nextElement();
+
+ if (name.equals(IRequest.CERT_FILTER)) {
+ String filter = request.getExtDataInString(IRequest.CERT_FILTER);
+
+ CertificateRepository certDB = (CertificateRepository) mCA.getCertificateRepository();
+ X509CertImpl[] certs = certDB.getX509Certificates(filter);
+
+ if (certs != null) {
+ request.setExtData(IRequest.OLD_CERTS, certs);
+ }
+ }
+ }
+ return true;
+ }
+}
+
+
+class serviceCert4Crl implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceCert4Crl(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ // XXX Need to think passing as array.
+ // XXX every implemented according to servlet.
+ BigInteger revokedCertIds[] = request.getExtDataInBigIntegerArray(
+ IRequest.REVOKED_CERT_RECORDS);
+ if (revokedCertIds == null ||
+ revokedCertIds.length == 0) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_ENTRY", request.getRequestId().toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_CLAREQ"));
+ }
+
+ CertRecord revokedCertRecs[] = new CertRecord[revokedCertIds.length];
+ for (int i = 0; i < revokedCertIds.length; i++) {
+ revokedCertRecs[i] = (CertRecord)
+ mCA.getCertificateRepository().readCertificateRecord(
+ revokedCertIds[i]);
+ }
+
+ if (revokedCertRecs == null ||
+ revokedCertRecs.length == 0 ||
+ revokedCertRecs[0] == null) {
+ // XXX should this be an error ?
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_ENTRY", request.getRequestId().toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_MISSING_INFO_IN_CLAREQ"));
+ }
+
+ CertRecord recordedCerts[] =
+ new CertRecord[revokedCertRecs.length];
+ String svcerrors[] = null;
+
+ for (int i = 0; i < revokedCertRecs.length; i++) {
+ try {
+ // for CLA, record it into cert repost
+ ((CertificateRepository) mCA.getCertificateRepository()).addRevokedCertRecord(revokedCertRecs[i]);
+ // mService.revokeCert(crlentries[i]);
+ recordedCerts[i] = revokedCertRecs[i];
+ // inform all CRLIssuingPoints about revoked certificate
+ Hashtable hips = mService.getCRLIssuingPoints();
+ Enumeration eIPs = hips.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement();
+ // form RevokedCertImpl
+ RevokedCertImpl rci =
+ new RevokedCertImpl(revokedCertRecs[i].getSerialNumber(),
+ revokedCertRecs[i].getRevokedOn());
+
+ if (ip != null) {
+ ip.addRevokedCert(revokedCertRecs[i].getSerialNumber(), rci);
+ }
+ }
+
+ } catch (ECAException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CERT4CRL_NO_REC", Integer.toString(i), request.getRequestId().toString(), e.toString()));
+ recordedCerts[i] = null;
+ if (svcerrors == null) {
+ svcerrors = new String[recordedCerts.length];
+ }
+ svcerrors[i] = e.toString();
+ }
+ }
+ //need to record which gets recorded and which failed...cfu
+ // request.set(IRequest.REVOKED_CERTS, revokedCerts);
+ if (svcerrors != null) {
+ request.setExtData(IRequest.SVCERRORS, svcerrors);
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CERT4CRL_FAILED"));
+ }
+
+ return true;
+ }
+}
+
+
+class serviceUnCert4Crl implements IServant {
+ private ICertificateAuthority mCA;
+ private CAService mService;
+
+ public serviceUnCert4Crl(CAService service) {
+ mService = service;
+ mCA = mService.getCA();
+ }
+
+ public boolean service(IRequest request)
+ throws EBaseException {
+ BigInteger oldSerialNo[] =
+ request.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+
+ if (oldSerialNo == null || oldSerialNo.length < 1) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_UNREVOKE_MISSING_SERIAL"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_MISSING_SERIAL_NUMBER"));
+ }
+
+ String svcerrors[] = null;
+
+ for (int i = 0; i < oldSerialNo.length; i++) {
+ try {
+ mCA.getCertificateRepository().deleteCertificateRecord(oldSerialNo[i]);
+ // inform all CRLIssuingPoints about unrevoked certificate
+ Hashtable hips = mService.getCRLIssuingPoints();
+ Enumeration eIPs = hips.elements();
+
+ while (eIPs.hasMoreElements()) {
+ ICRLIssuingPoint ip = (ICRLIssuingPoint) eIPs.nextElement();
+
+ if (ip != null) {
+ ip.addUnrevokedCert(oldSerialNo[i]);
+ }
+ }
+ } catch (EBaseException e) {
+ mCA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_DELETE_CERT_ERROR", oldSerialNo[i].toString(), e.toString()));
+ if (svcerrors == null) {
+ svcerrors = new String[oldSerialNo.length];
+ }
+ svcerrors[i] = e.toString();
+ }
+
+ }
+
+ if (svcerrors != null) {
+ request.setExtData(IRequest.SVCERRORS, svcerrors);
+ throw new ECAException(CMS.getUserMessage("CMS_CA_UNCERT4CRL_FAILED"));
+ }
+
+ return true;
+ }
+}
+
diff --git a/pki/base/ca/src/com/netscape/ca/CMSCRLExtensions.java b/pki/base/ca/src/com/netscape/ca/CMSCRLExtensions.java
new file mode 100644
index 000000000..abbfbfc9f
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CMSCRLExtensions.java
@@ -0,0 +1,686 @@
+// --- 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.ca;
+
+
+import java.io.IOException;
+import java.util.*;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.Extension;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.IssuerAlternativeNameExtension;
+import netscape.security.x509.CRLNumberExtension;
+import netscape.security.x509.DeltaCRLIndicatorExtension;
+import netscape.security.x509.IssuingDistributionPointExtension;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.HoldInstructionExtension;
+import netscape.security.x509.InvalidityDateExtension;
+import netscape.security.x509.CertificateIssuerExtension;
+import netscape.security.x509.FreshestCRLExtension;
+import netscape.security.x509.OIDMap;
+import netscape.security.extensions.AuthInfoAccessExtension;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.base.SubsystemRegistry;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotDefined;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.common.Constants;
+import com.netscape.certsrv.common.NameValuePair;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.*;
+import java.security.cert.CertificateException;
+import com.netscape.cms.crl.CMSIssuingDistributionPointExtension;
+
+
+public class CMSCRLExtensions implements ICMSCRLExtensions {
+ public static final String PROP_ENABLE = "enable";
+ public static final String PROP_EXTENSION = "extension";
+ public static final String PROP_CLASS = "class";
+ public static final String PROP_TYPE = "type";
+ public static final String PROP_CRITICAL = "critical";
+ public static final String PROP_CRL_EXT = "CRLExtension";
+ public static final String PROP_CRL_ENTRY_EXT = "CRLEntryExtension";
+
+ private ICRLIssuingPoint mCRLIssuingPoint = null;
+
+ private IConfigStore mConfig = null;
+ private IConfigStore mCRLExtConfig = null;
+
+ private Vector mCRLExtensionNames = new Vector();
+ private Vector mCRLEntryExtensionNames = new Vector();
+ private Vector mEnabledCRLExtensions = new Vector();
+ private Vector mCriticalCRLExtensions = new Vector();
+ private Hashtable mCRLExtensionClassNames = new Hashtable();
+ private Hashtable mCRLExtensionIDs = new Hashtable();
+
+ private static final Vector mDefaultCRLExtensionNames = new Vector();
+ private static final Vector mDefaultCRLEntryExtensionNames = new Vector();
+ private static final Vector mDefaultEnabledCRLExtensions = new Vector();
+ private static final Vector mDefaultCriticalCRLExtensions = new Vector();
+ private static final Hashtable mDefaultCRLExtensionClassNames = new Hashtable();
+ private static final Hashtable mDefaultCRLExtensionIDs = new Hashtable();
+
+ private ILogger mLogger = CMS.getLogger();
+
+ static {
+
+ /* Default CRL Extensions */
+ mDefaultCRLExtensionNames.addElement(AuthorityKeyIdentifierExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(IssuerAlternativeNameExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(CRLNumberExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(DeltaCRLIndicatorExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(IssuingDistributionPointExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(FreshestCRLExtension.NAME);
+ mDefaultCRLExtensionNames.addElement(AuthInfoAccessExtension.NAME2);
+
+ /* Default CRL Entry Extensions */
+ mDefaultCRLEntryExtensionNames.addElement(CRLReasonExtension.NAME);
+ //mDefaultCRLEntryExtensionNames.addElement(HoldInstructionExtension.NAME);
+ mDefaultCRLEntryExtensionNames.addElement(InvalidityDateExtension.NAME);
+ //mDefaultCRLEntryExtensionNames.addElement(CertificateIssuerExtension.NAME);
+
+ /* Default Enabled CRL Extensions */
+ mDefaultEnabledCRLExtensions.addElement(CRLNumberExtension.NAME);
+ //mDefaultEnabledCRLExtensions.addElement(DeltaCRLIndicatorExtension.NAME);
+ mDefaultEnabledCRLExtensions.addElement(CRLReasonExtension.NAME);
+ mDefaultEnabledCRLExtensions.addElement(InvalidityDateExtension.NAME);
+
+ /* Default Critical CRL Extensions */
+ mDefaultCriticalCRLExtensions.addElement(DeltaCRLIndicatorExtension.NAME);
+ mDefaultCriticalCRLExtensions.addElement(IssuingDistributionPointExtension.NAME);
+ //mDefaultCriticalCRLExtensions.addElement(CertificateIssuerExtension.NAME);
+
+ /* CRL extension IDs */
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.AuthorityKey_Id.toString(),
+ AuthorityKeyIdentifierExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.IssuerAlternativeName_Id.toString(),
+ IssuerAlternativeNameExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.CRLNumber_Id.toString(),
+ CRLNumberExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.DeltaCRLIndicator_Id.toString(),
+ DeltaCRLIndicatorExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.IssuingDistributionPoint_Id.toString(),
+ IssuingDistributionPointExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.ReasonCode_Id.toString(),
+ CRLReasonExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.HoldInstructionCode_Id.toString(),
+ HoldInstructionExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.InvalidityDate_Id.toString(),
+ InvalidityDateExtension.NAME);
+ //mDefaultCRLExtensionIDs.put(PKIXExtensions.CertificateIssuer_Id.toString(),
+ // CertificateIssuerExtension.NAME);
+ mDefaultCRLExtensionIDs.put(PKIXExtensions.FreshestCRL_Id.toString(),
+ FreshestCRLExtension.NAME);
+ mDefaultCRLExtensionIDs.put(AuthInfoAccessExtension.ID.toString(),
+ AuthInfoAccessExtension.NAME2);
+
+ /* Class names */
+ mDefaultCRLExtensionClassNames.put(AuthorityKeyIdentifierExtension.NAME,
+ "com.netscape.cms.crl.CMSAuthorityKeyIdentifierExtension");
+ mDefaultCRLExtensionClassNames.put(IssuerAlternativeNameExtension.NAME,
+ "com.netscape.cms.crl.CMSIssuerAlternativeNameExtension");
+ mDefaultCRLExtensionClassNames.put(CRLNumberExtension.NAME,
+ "com.netscape.cms.crl.CMSCRLNumberExtension");
+ mDefaultCRLExtensionClassNames.put(DeltaCRLIndicatorExtension.NAME,
+ "com.netscape.cms.crl.CMSDeltaCRLIndicatorExtension");
+ mDefaultCRLExtensionClassNames.put(IssuingDistributionPointExtension.NAME,
+ "com.netscape.cms.crl.CMSIssuingDistributionPointExtension");
+ mDefaultCRLExtensionClassNames.put(CRLReasonExtension.NAME,
+ "com.netscape.cms.crl.CMSCRLReasonExtension");
+ mDefaultCRLExtensionClassNames.put(HoldInstructionExtension.NAME,
+ "com.netscape.cms.crl.CMSHoldInstructionExtension");
+ mDefaultCRLExtensionClassNames.put(InvalidityDateExtension.NAME,
+ "com.netscape.cms.crl.CMSInvalidityDateExtension");
+ //mDefaultCRLExtensionClassNames.put(CertificateIssuerExtension.NAME,
+ // "com.netscape.cms.crl.CMSCertificateIssuerExtension");
+ mDefaultCRLExtensionClassNames.put(FreshestCRLExtension.NAME,
+ "com.netscape.cms.crl.CMSFreshestCRLExtension");
+ mDefaultCRLExtensionClassNames.put(AuthInfoAccessExtension.NAME2,
+ "com.netscape.cms.crl.CMSAuthInfoAccessExtension");
+
+ try {
+ OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(),
+ DeltaCRLIndicatorExtension.OID,
+ DeltaCRLIndicatorExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(HoldInstructionExtension.class.getName(),
+ HoldInstructionExtension.OID,
+ HoldInstructionExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(InvalidityDateExtension.class.getName(),
+ InvalidityDateExtension.OID,
+ InvalidityDateExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ try {
+ OIDMap.addAttribute(FreshestCRLExtension.class.getName(),
+ FreshestCRLExtension.OID,
+ FreshestCRLExtension.NAME);
+ } catch (CertificateException e) {
+ }
+ }
+
+ /**
+ * Constructs a CRL extensions for CRL issuing point.
+ */
+ public CMSCRLExtensions(ICRLIssuingPoint crlIssuingPoint, IConfigStore config) {
+ boolean modifiedConfig = false;
+
+ mConfig = config;
+ mCRLExtConfig = config.getSubStore(PROP_EXTENSION);
+ mCRLIssuingPoint = crlIssuingPoint;
+
+ IConfigStore mFileConfig =
+ SubsystemRegistry.getInstance().get("MAIN").getConfigStore();
+
+ IConfigStore crlExtConfig = (IConfigStore) mFileConfig;
+ StringTokenizer st = new StringTokenizer(mCRLExtConfig.getName(), ".");
+
+ while (st.hasMoreTokens()) {
+ String subStoreName = st.nextToken();
+ IConfigStore newConfig = crlExtConfig.getSubStore(subStoreName);
+
+ if (newConfig != null) {
+ crlExtConfig = newConfig;
+ }
+ }
+
+ if (crlExtConfig != null) {
+ Enumeration enumExts = crlExtConfig.getSubStoreNames();
+
+ while (enumExts.hasMoreElements()) {
+ String extName = (String) enumExts.nextElement();
+ IConfigStore extConfig = crlExtConfig.getSubStore(extName);
+
+ if (extConfig != null) {
+ modifiedConfig |= getEnableProperty(extName, extConfig);
+ modifiedConfig |= getCriticalProperty(extName, extConfig);
+ modifiedConfig |= getTypeProperty(extName, extConfig);
+ modifiedConfig |= getClassProperty(extName, extConfig);
+ }
+ }
+
+ if (modifiedConfig) {
+ try {
+ mFileConfig.commit(true);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_SAVE_CONF", e.toString()));
+ }
+ }
+ }
+ }
+
+ private boolean getEnableProperty(String extName, IConfigStore extConfig) {
+ boolean modifiedConfig = false;
+
+ try {
+ if (extConfig.getBoolean(PROP_ENABLE)) {
+ mEnabledCRLExtensions.addElement(extName);
+ }
+ } catch (EPropertyNotFound e) {
+ extConfig.putBoolean(PROP_ENABLE, mDefaultEnabledCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultEnabledCRLExtensions.contains(extName)) {
+ mEnabledCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_NO_ENABLE", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ } catch (EPropertyNotDefined e) {
+ extConfig.putBoolean(PROP_ENABLE, mDefaultEnabledCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultEnabledCRLExtensions.contains(extName)) {
+ mEnabledCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_UNDEFINE_ENABLE", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ } catch (EBaseException e) {
+ extConfig.putBoolean(PROP_ENABLE, mDefaultEnabledCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultEnabledCRLExtensions.contains(extName)) {
+ mEnabledCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_ENABLE", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ }
+ return modifiedConfig;
+ }
+
+ private boolean getCriticalProperty(String extName, IConfigStore extConfig) {
+ boolean modifiedConfig = false;
+
+ try {
+ if (extConfig.getBoolean(PROP_CRITICAL)) {
+ mCriticalCRLExtensions.addElement(extName);
+ }
+ } catch (EPropertyNotFound e) {
+ extConfig.putBoolean(PROP_CRITICAL, mDefaultCriticalCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultCriticalCRLExtensions.contains(extName)) {
+ mCriticalCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_NO_CRITICAL", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ } catch (EPropertyNotDefined e) {
+ extConfig.putBoolean(PROP_CRITICAL, mDefaultCriticalCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultCriticalCRLExtensions.contains(extName)) {
+ mCriticalCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_UNDEFINE_CRITICAL", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ } catch (EBaseException e) {
+ extConfig.putBoolean(PROP_CRITICAL, mDefaultCriticalCRLExtensions.contains(extName));
+ modifiedConfig = true;
+ if (mDefaultCriticalCRLExtensions.contains(extName)) {
+ mCriticalCRLExtensions.addElement(extName);
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_CRITICAL", extName, mDefaultEnabledCRLExtensions.contains(extName) ? "true" : "false"));
+ }
+ return modifiedConfig;
+ }
+
+ private boolean getTypeProperty(String extName, IConfigStore extConfig) {
+ boolean modifiedConfig = false;
+ String extType = null;
+
+ try {
+ extType = extConfig.getString(PROP_TYPE);
+ if (extType.length() > 0) {
+ if (extType.equals(PROP_CRL_ENTRY_EXT)) {
+ mCRLEntryExtensionNames.addElement(extName);
+ } else if (extType.equals(PROP_CRL_EXT)) {
+ mCRLExtensionNames.addElement(extName);
+ } else {
+ if (mDefaultCRLEntryExtensionNames.contains(extName)) {
+ extConfig.putString(PROP_TYPE, PROP_CRL_ENTRY_EXT);
+ modifiedConfig = true;
+ mCRLEntryExtensionNames.addElement(extName);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_EXT", extName, PROP_CRL_ENTRY_EXT));
+ } else if (mDefaultCRLExtensionNames.contains(extName)) {
+ extConfig.putString(PROP_TYPE, PROP_CRL_EXT);
+ modifiedConfig = true;
+ mCRLExtensionNames.addElement(extName);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_EXT", extName, PROP_CRL_EXT));
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_EXT", extName, ""));
+ }
+ }
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_UNDEFINE_EXT", extName));
+ }
+ } catch (EPropertyNotFound e) {
+ if (mDefaultCRLEntryExtensionNames.contains(extName)) {
+ extConfig.putString(PROP_TYPE, PROP_CRL_ENTRY_EXT);
+ modifiedConfig = true;
+ } else if (mDefaultCRLExtensionNames.contains(extName)) {
+ extConfig.putString(PROP_TYPE, PROP_CRL_EXT);
+ modifiedConfig = true;
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_MISSING_EXT", extName));
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_INVALID_EXT", extName, ""));
+ }
+ return modifiedConfig;
+ }
+
+ private boolean getClassProperty(String extName, IConfigStore extConfig) {
+ boolean modifiedConfig = false;
+ String extClass = null;
+
+ try {
+ extClass = extConfig.getString(PROP_CLASS);
+ if (extClass.length() > 0) {
+ mCRLExtensionClassNames.put(extName, extClass);
+
+ try {
+ Class crlExtClass = Class.forName(extClass);
+
+ if (crlExtClass != null) {
+ ICMSCRLExtension cmsCRLExt = (ICMSCRLExtension) crlExtClass.newInstance();
+
+ if (cmsCRLExt != null) {
+ String id = (String) cmsCRLExt.getCRLExtOID();
+
+ if (id != null) {
+ mCRLExtensionIDs.put(id, extName);
+ }
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_FOUND", extClass, e.toString()));
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_INST", extClass, e.toString()));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_ACCESS", extClass, e.toString()));
+ }
+
+ } else {
+ if (mDefaultCRLExtensionClassNames.containsKey(extName)) {
+ extClass = (String) mCRLExtensionClassNames.get(extName);
+ extConfig.putString(PROP_CLASS, extClass);
+ modifiedConfig = true;
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_DEFINED", extName));
+ }
+ } catch (EPropertyNotFound e) {
+ if (mDefaultCRLExtensionClassNames.containsKey(extName)) {
+ extClass = (String) mDefaultCRLExtensionClassNames.get(extName);
+ extConfig.putString(PROP_CLASS, extClass);
+ modifiedConfig = true;
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_MISSING", extName));
+ } catch (EBaseException e) {
+ if (mDefaultCRLExtensionClassNames.containsKey(extName)) {
+ extClass = (String) mDefaultCRLExtensionClassNames.get(extName);
+ extConfig.putString(PROP_CLASS, extClass);
+ modifiedConfig = true;
+ }
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_INVALID", extName));
+ }
+ return modifiedConfig;
+ }
+
+ public boolean isCRLExtension(String extName) {
+ return mCRLExtensionNames.contains(extName);
+ }
+
+ public boolean isCRLEntryExtension(String extName) {
+ return mCRLEntryExtensionNames.contains(extName);
+ }
+
+ public boolean isCRLExtensionEnabled(String extName) {
+ return ((mCRLExtensionNames.contains(extName) ||
+ mCRLEntryExtensionNames.contains(extName)) &&
+ mEnabledCRLExtensions.contains(extName));
+ }
+
+ public boolean isCRLExtensionCritical(String extName) {
+ return mCriticalCRLExtensions.contains(extName);
+ }
+
+ public String getCRLExtensionName(String id) {
+ String name = null;
+
+ if (mCRLExtensionIDs.containsKey(id)) {
+ name = (String) mCRLExtensionIDs.get(id);
+ }
+ return name;
+ }
+
+ public Vector getCRLExtensionNames() {
+ return (Vector) mCRLExtensionNames.clone();
+ }
+
+ public Vector getCRLEntryExtensionNames() {
+ return (Vector) mCRLEntryExtensionNames.clone();
+ }
+
+ public void addToCRLExtensions(CRLExtensions crlExts, String extName, Extension ext) {
+ if (mCRLExtensionClassNames.containsKey(extName)) {
+ String name = (String) mCRLExtensionClassNames.get(extName);
+
+ try {
+ Class extClass = Class.forName(name);
+
+ if (extClass != null) {
+ ICMSCRLExtension cmsCRLExt = (ICMSCRLExtension) extClass.newInstance();
+
+ if (cmsCRLExt != null) {
+ if (ext != null) {
+ if (isCRLExtensionCritical(extName) ^ ext.isCritical()) {
+ ext = (Extension) cmsCRLExt.setCRLExtensionCriticality(
+ ext, isCRLExtensionCritical(extName));
+ }
+ } else {
+ ext = (Extension) cmsCRLExt.getCRLExtension(mCRLExtConfig.getSubStore(extName),
+ mCRLIssuingPoint,
+ isCRLExtensionCritical(extName));
+ }
+
+ if (crlExts != null && ext != null) {
+ crlExts.set(extName, ext);
+ }
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_FOUND", name, e.toString()));
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_INST", name, e.toString()));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_ACCESS", name, e.toString()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_ADD", name, e.toString()));
+ }
+ }
+ }
+
+ public NameValuePairs getConfigParams(String id) {
+ NameValuePairs nvp = null;
+
+ if (mCRLEntryExtensionNames.contains(id) ||
+ mCRLExtensionNames.contains(id)) {
+ nvp = new NameValuePairs();
+
+ /*
+ if (mCRLEntryExtensionNames.contains(id)) {
+ nvp.add(Constants.PR_CRLEXT_IMPL_NAME, "CRLEntryExtension");
+ } else {
+ nvp.add(Constants.PR_CRLEXT_IMPL_NAME, "CRLExtension");
+ }
+
+ if (mCRLEntryExtensionNames.contains(id)) {
+ nvp.add(PROP_TYPE, "CRLEntryExtension");
+ } else {
+ nvp.add(PROP_TYPE, "CRLExtension");
+ }
+ */
+
+ if (mEnabledCRLExtensions.contains(id)) {
+ nvp.add(PROP_ENABLE, Constants.TRUE);
+ } else {
+ nvp.add(PROP_ENABLE, Constants.FALSE);
+ }
+ if (mCriticalCRLExtensions.contains(id)) {
+ nvp.add(PROP_CRITICAL, Constants.TRUE);
+ } else {
+ nvp.add(PROP_CRITICAL, Constants.FALSE);
+ }
+
+ if (mCRLExtensionClassNames.containsKey(id)) {
+ String name = (String) mCRLExtensionClassNames.get(id);
+
+ if (name != null) {
+
+ try {
+ Class extClass = Class.forName(name);
+
+ if (extClass != null) {
+ ICMSCRLExtension cmsCRLExt = (ICMSCRLExtension) extClass.newInstance();
+
+ if (cmsCRLExt != null) {
+ cmsCRLExt.getConfigParams(mCRLExtConfig.getSubStore(id), nvp);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_FOUND", name, e.toString()));
+ } catch (InstantiationException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_INST", name, e.toString()));
+ } catch (IllegalAccessException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_CLASS_NOT_ACCESS", name, e.toString()));
+ }
+
+ int i = name.lastIndexOf('.');
+
+ if ((i > -1) && (i + 1 < name.length())) {
+ String idName = name.substring(i + 1);
+
+ if (idName != null) {
+ nvp.add(Constants.PR_CRLEXT_IMPL_NAME, idName);
+ }
+ }
+ }
+ }
+ }
+ return nvp;
+ }
+
+ public void setConfigParams(String id, NameValuePairs nvp, IConfigStore config) {
+ ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ String ipId = nvp.getValue("id");
+
+ ICRLIssuingPoint ip = null;
+ if(ipId != null && ca != null) {
+ ip = ca.getCRLIssuingPoint(ipId);
+ }
+
+ for (int i = 0; i < nvp.size(); i++) {
+ NameValuePair p = nvp.elementAt(i);
+ String name = p.getName();
+ String value = p.getValue();
+
+ if (name.equals(PROP_ENABLE)) {
+ if (!(value.equals(Constants.TRUE) ||
+ value.equals(Constants.FALSE))) {
+ continue;
+ }
+ if (value.equals(Constants.TRUE)) {
+ if (!(mEnabledCRLExtensions.contains(id))) {
+ mEnabledCRLExtensions.addElement(id);
+ }
+ }
+ if (value.equals(Constants.FALSE)) {
+ mEnabledCRLExtensions.remove(id);
+ }
+ }
+
+ if (name.equals(PROP_CRITICAL)) {
+ if (!(value.equals(Constants.TRUE) ||
+ value.equals(Constants.FALSE))) {
+ continue;
+ }
+ if (value.equals(Constants.TRUE)) {
+ if (!(mCriticalCRLExtensions.contains(id))) {
+ mCriticalCRLExtensions.addElement(id);
+ }
+ }
+ if (value.equals(Constants.FALSE)) {
+ mCriticalCRLExtensions.remove(id);
+ }
+ }
+ //Sync the onlyContainsCACerts with similar property in CRLIssuingPoint
+ //called caCertsOnly.
+ if(name.equals(CMSIssuingDistributionPointExtension.PROP_CACERTS)) {
+ NameValuePairs crlIssuingPointPairs = null;
+ boolean crlCACertsOnly = false;
+
+ boolean issuingDistPointExtEnabled = false;
+
+ CMSCRLExtensions cmsCRLExtensions = (CMSCRLExtensions) ip.getCRLExtensions();
+ if(cmsCRLExtensions != null) {
+ issuingDistPointExtEnabled = cmsCRLExtensions.isCRLExtensionEnabled(IssuingDistributionPointExtension.NAME);
+ }
+
+ CMS.debug("issuingDistPointExtEnabled = " + issuingDistPointExtEnabled);
+
+ if (!(value.equals(Constants.TRUE) ||
+ value.equals(Constants.FALSE))) {
+ continue;
+ }
+
+ //Get value of caCertsOnly from CRLIssuingPoint
+ if((ip != null) && (issuingDistPointExtEnabled == true)) {
+ crlCACertsOnly = ip.isCACertsOnly();
+ CMS.debug("CRLCACertsOnly is: " + crlCACertsOnly);
+ crlIssuingPointPairs = new NameValuePairs();
+
+ }
+
+ String newValue = "";
+ boolean modifiedCRLConfig = false;
+ //If the CRLCACertsOnly prop is false change it to true to sync.
+ if(value.equals(Constants.TRUE) && (issuingDistPointExtEnabled == true)) {
+ if(crlCACertsOnly == false) {
+ CMS.debug(" value = true and CRLCACertsOnly is already false.");
+ crlIssuingPointPairs.add(Constants.PR_CA_CERTS_ONLY, Constants.TRUE);
+ newValue = Constants.TRUE;
+ ip.updateConfig(crlIssuingPointPairs);
+ modifiedCRLConfig = true;
+ }
+ }
+
+ //If the CRLCACertsOnly prop is true change it to false to sync.
+ if(value.equals(Constants.FALSE) && (issuingDistPointExtEnabled == true)) {
+ crlIssuingPointPairs.add(Constants.PR_CA_CERTS_ONLY, Constants.FALSE);
+ if(ip != null) {
+ ip.updateConfig(crlIssuingPointPairs);
+ newValue = Constants.FALSE;
+ modifiedCRLConfig = true;
+ }
+ }
+
+ if(modifiedCRLConfig == true) {
+ //Commit to this CRL IssuingPoint's config store
+ ICertificateAuthority CA = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+ IConfigStore crlsSubStore = CA.getConfigStore();
+ crlsSubStore = crlsSubStore.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE);
+ crlsSubStore = crlsSubStore.getSubStore(ipId);
+ try {
+ crlsSubStore.putString(Constants.PR_CA_CERTS_ONLY,newValue);
+ crlsSubStore.commit(true);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CRLEXTS_SAVE_CONF", e.toString()));
+ }
+ }
+ }
+
+ config.putString(name, value);
+ }
+ }
+
+ public String getClassPath(String name) {
+ Enumeration enum1 = mCRLExtensionClassNames.elements();
+
+ while (enum1.hasMoreElements()) {
+ String extClassName = (String) enum1.nextElement();
+
+ if (extClassName != null) {
+ int i = extClassName.lastIndexOf('.');
+
+ if ((i > -1) && (i + 1 < extClassName.length())) {
+ String idName = extClassName.substring(i + 1);
+
+ if (idName != null) {
+ if (name.equals(idName)) {
+ return extClassName;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CMSCRLExtension - " + msg);
+ }
+}
+
diff --git a/pki/base/ca/src/com/netscape/ca/CRLIssuingPoint.java b/pki/base/ca/src/com/netscape/ca/CRLIssuingPoint.java
new file mode 100644
index 000000000..aba2db149
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CRLIssuingPoint.java
@@ -0,0 +1,3086 @@
+// --- 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.ca;
+
+
+import java.util.*;
+import java.math.*;
+import java.io.*;
+import java.security.cert.CRLException;
+import java.security.NoSuchAlgorithmException;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import netscape.security.pkcs.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.util.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.ca.ICMSCRLExtension;
+import com.netscape.cmscore.request.CertRequestConstants;
+import com.netscape.cmscore.ldap.*;
+import com.netscape.cmscore.util.Debug;
+
+/**
+ * This class encapsulates CRL issuing mechanism. CertificateAuthority
+ * contains a map of CRLIssuingPoint indexed by string ids. Each issuing
+ * point contains information about CRL issuing and publishing parameters
+ * as well as state information which includes last issued CRL, next CRL
+ * serial number, time of the next update etc.
+ * If autoUpdateInterval is set to non-zero value then worker thread
+ * is created that will perform CRL update at scheduled intervals. Update
+ * can also be triggered by invoking updateCRL method directly. Another
+ * parameter minUpdateInterval can be used to prevent CRL
+ * from being updated too often
+ * <P>
+ *
+ * @author awnuk
+ * @author lhsiao
+ * @author galperin
+ * @version $Revision$, $Date$
+ */
+
+public class CRLIssuingPoint implements ICRLIssuingPoint, Runnable {
+
+ /* Foreign config param for IssuingDistributionPointExtension. */
+ public static final String PROP_CACERTS = "onlyContainsCACerts";
+
+ public static final long SECOND = 1000L;
+ public static final long MINUTE = (SECOND * 60L);
+
+ private static final int CRL_PAGE_SIZE = 10000;
+
+ /* configuration file property names */
+
+ public IPublisherProcessor mPublisherProcessor = null;
+
+ private ILogger mLogger = CMS.getLogger();
+
+ private IConfigStore mConfigStore;
+
+ private ICRLPublisher mCRLPublisher = null;
+ private int mCountMod = 0;
+ private int mCount = 0;
+ private int mPageSize = CRL_PAGE_SIZE;
+
+ private CMSCRLExtensions mCMSCRLExtensions = null;
+
+ /**
+ * Internal unique id of this CRL issuing point.
+ */
+ protected String mId = null;
+
+ /**
+ * Reference to the CertificateAuthority instance which owns this
+ * issuing point.
+ */
+ protected ICertificateAuthority mCA = null;
+
+ /**
+ * Reference to the CRL repository maintained in CA.
+ */
+ protected ICRLRepository mCRLRepository = null;
+
+ /**
+ * Reference to the cert repository maintained in CA.
+ */
+ private ICertificateRepository mCertRepository = null;
+
+ /**
+ * Enable CRL issuing point.
+ */
+ private boolean mEnable = true;
+
+ /**
+ * Description of the issuing point
+ */
+ private String mDescription = null;
+
+ /**
+ * CRL cache
+ */
+ private Hashtable mCRLCerts = new Hashtable();
+ private Hashtable mRevokedCerts = new Hashtable();
+ private Hashtable mUnrevokedCerts = new Hashtable();
+ private Hashtable mExpiredCerts = new Hashtable();
+ private boolean mIncludeExpiredCerts = false;
+ private boolean mIncludeExpiredCertsOneExtraTime = false;
+ private boolean mCACertsOnly = false;
+
+ private boolean mProfileCertsOnly = false;
+ private Vector mProfileList = null;
+
+ /**
+ * Enable CRL cache.
+ */
+ private boolean mEnableCRLCache = true;
+ private boolean mCRLCacheIsCleared = true;
+ private boolean mEnableCacheRecovery = false;
+ private String mFirstUnsaved = null;
+ private boolean mEnableCacheTesting = false;
+
+ /**
+ * Last CRL cache update
+ */
+ private long mLastCacheUpdate = 0;
+
+ /**
+ * Time interval in milliseconds between consequential CRL cache
+ * updates performed automatically.
+ */
+ private long mCacheUpdateInterval;
+
+ /**
+ * Enable CRL updates.
+ */
+ private boolean mEnableCRLUpdates = true;
+
+ /**
+ * CRL update schema.
+ */
+ private int mUpdateSchema = 1;
+ private int mSchemaCounter = 0;
+
+ /**
+ * Enable CRL daily updates at listed times.
+ */
+ private boolean mEnableDailyUpdates = false;
+ private Vector mDailyUpdates = null;
+ private int mCurrentDay = 0;
+ private int mLastDay = 0;
+ private int mTimeListSize = 0;
+ private boolean mExtendedTimeList = false;
+
+ /**
+ * Enable CRL auto update with interval
+ */
+ private boolean mEnableUpdateFreq = false;
+
+ /**
+ * Time interval in milliseconds between consequential CRL Enable CRL daily update at updates
+ * performed automatically.
+ */
+ private long mAutoUpdateInterval;
+
+ /**
+ * Minimum time interval in milliseconds between consequential
+ * CRL updates (manual or automatic).
+ */
+ private long mMinUpdateInterval;
+
+ /**
+ * Update CRL even if auto interval > 0
+ */
+ private boolean mAlwaysUpdate = false;
+
+ /**
+ * next update grace period
+ */
+ private long mNextUpdateGracePeriod;
+
+ /**
+ * Boolean flag controlling whether CRLv2 extensions are to be
+ * used in CRL.
+ */
+ private boolean mAllowExtensions = false;
+
+ /**
+ * DN of the directory entry where CRLs from this issuing point
+ * are published.
+ */
+ private String mPublishDN = null;
+
+ /**
+ * signing algorithm
+ */
+ private String mSigningAlgorithm = null;
+ private String mLastSigningAlgorithm = null;
+
+ /**
+ * Cached value of the CRL extensions to be placed in CRL
+ */
+ //protected CRLExtensions mCrlExtensions;
+
+ /**
+ * CRL number
+ */
+ private BigInteger mCRLNumber;
+ private BigInteger mNextCRLNumber;
+ private BigInteger mLastCRLNumber;
+
+ /**
+ * Delta CRL number
+ */
+ private BigInteger mDeltaCRLNumber;
+ private BigInteger mNextDeltaCRLNumber;
+
+ /**
+ * Last CRL update date
+ */
+ private Date mLastUpdate;
+ private Date mLastFullUpdate;
+ private long mLastScheduledUpdate = 0;
+
+ /**
+ * Next scheduled CRL update date
+ */
+ private Date mNextUpdate;
+ private Date mNextDeltaUpdate;
+ private boolean mExtendedNextUpdate;
+
+ /**
+ * Worker thread doing auto-update
+ */
+ private Thread mUpdateThread = null;
+
+ /**
+ * for going one more round when auto-interval is set to 0 (turned off)
+ */
+ private boolean mDoLastAutoUpdate = false;
+
+ /**
+ * whether issuing point has been initialized.
+ */
+ private int mInitialized = CRL_IP_NOT_INITIALIZED;
+
+ /**
+ * number of entries in the CRL
+ */
+ private long mCRLSize = -1;
+ private long mDeltaCRLSize = -1;
+
+ /**
+ * update status, publishing status Strings to store in requests to
+ * display result.
+ */
+ private String mCrlUpdateStatus;
+ private String mCrlUpdateError;
+ private String mCrlPublishStatus;
+ private String mCrlPublishError;
+
+ /**
+ * begin, end serial number range of revoked certs if any.
+ */
+ protected BigInteger mBeginSerial = null;
+ protected BigInteger mEndSerial = null;
+
+ private int mUpdatingCRL = CRL_UPDATE_DONE;
+
+ private boolean mDoManualUpdate = false;
+ private String mSignatureAlgorithmForManualUpdate = null;
+
+ private boolean mPublishOnStart = false;
+ private long[] mSplits = new long[10];
+
+ private boolean mSaveMemory = false;
+
+ /**
+ * Constructs a CRL issuing point from instantiating from class name.
+ * CRL Issuing point must be followed by method call init(CA, id, config);
+ */
+ public CRLIssuingPoint() {
+ }
+
+ public boolean isCRLIssuingPointEnabled() {
+ return mEnable;
+ }
+
+ public void enableCRLIssuingPoint(boolean enable) {
+ if ((!enable) && (mEnable ^ enable)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ }
+ mEnable = enable;
+ setAutoUpdates();
+ }
+
+ public boolean isCRLGenerationEnabled() {
+ return mEnableCRLUpdates;
+ }
+
+ public String getCrlUpdateStatusStr() {
+ return mCrlUpdateStatus;
+ }
+
+ public String getCrlUpdateErrorStr() {
+ return mCrlUpdateError;
+ }
+
+ public String getCrlPublishStatusStr() {
+ return mCrlPublishStatus;
+ }
+
+ public String getCrlPublishErrorStr() {
+ return mCrlPublishError;
+ }
+
+ public ICMSCRLExtensions getCRLExtensions() {
+ return mCMSCRLExtensions;
+ }
+
+ public int isCRLIssuingPointInitialized() {
+ return mInitialized;
+ }
+
+ public boolean isManualUpdateSet() {
+ return mDoManualUpdate;
+ }
+
+ public boolean areExpiredCertsIncluded() {
+ return mIncludeExpiredCerts;
+ }
+
+ public boolean isCACertsOnly() {
+ return mCACertsOnly;
+ }
+
+ public boolean isProfileCertsOnly() {
+ return (mProfileCertsOnly && mProfileList != null && mProfileList.size() > 0);
+ }
+
+ public boolean checkCurrentProfile(String id) {
+ boolean b = false;
+
+ if (mProfileCertsOnly && mProfileList != null && mProfileList.size() > 0) {
+ for (int k = 0; k < mProfileList.size(); k++) {
+ String profileId = (String) mProfileList.elementAt(k);
+ if (id != null && profileId != null && profileId.equalsIgnoreCase(id)) {
+ b = true;
+ break;
+ }
+ }
+ }
+
+ return b;
+ }
+
+
+ /**
+ * Initializes a CRL issuing point config.
+ * <P>
+ *
+ * @param ca reference to CertificateAuthority instance which
+ * owns this issuing point.
+ * @param id string id of this CRL issuing point.
+ * @param config configuration of this CRL issuing point.
+ * @exception EBaseException if initialization failed
+ * @exception IOException
+ */
+ public void init(ISubsystem ca, String id, IConfigStore config)
+ throws EBaseException {
+ mCA = (ICertificateAuthority) ca;
+ mId = id;
+
+ if (mId.equals(ICertificateAuthority.PROP_MASTER_CRL)) {
+ mCrlUpdateStatus = IRequest.CRL_UPDATE_STATUS;
+ mCrlUpdateError = IRequest.CRL_UPDATE_ERROR;
+ mCrlPublishStatus = IRequest.CRL_PUBLISH_STATUS;
+ mCrlPublishError = IRequest.CRL_PUBLISH_ERROR;
+ } else {
+ mCrlUpdateStatus = IRequest.CRL_UPDATE_STATUS + "_" + mId;
+ mCrlUpdateError = IRequest.CRL_UPDATE_ERROR + "_" + mId;
+ mCrlPublishStatus = IRequest.CRL_PUBLISH_STATUS + "_" + mId;
+ mCrlPublishError = IRequest.CRL_PUBLISH_ERROR + "_" + mId;
+ }
+
+ mConfigStore = config;
+
+ IConfigStore crlSubStore = mCA.getConfigStore().getSubStore(mCA.PROP_CRL_SUBSTORE);
+ mPageSize = crlSubStore.getInteger(mCA.PROP_CRL_PAGE_SIZE, CRL_PAGE_SIZE);
+ CMS.debug("CRL Page Size: "+ mPageSize);
+
+ mCountMod = config.getInteger("countMod",0);
+ mCRLRepository = mCA.getCRLRepository();
+ mCertRepository = mCA.getCertificateRepository();
+ ((CertificateRepository) mCertRepository).addCRLIssuingPoint(mId, this);
+ mPublisherProcessor = mCA.getPublisherProcessor();
+
+ //mCRLPublisher = mCA.getCRLPublisher();
+ ((CAService) mCA.getCAService()).addCRLIssuingPoint(mId, this);
+
+ // read in config parameters.
+ initConfig(config);
+
+ // create request listener.
+ String lname = RevocationRequestListener.class.getName();
+ String crlListName = lname + "_" + mId;
+
+ if (mCA.getRequestListener(crlListName) == null) {
+ mCA.registerRequestListener(
+ crlListName, new RevocationRequestListener());
+ }
+
+ for (int i = 0; i < mSplits.length; i++) {
+ mSplits[i] = 0;
+ }
+
+ // this will start a thread if necessary for automatic updates.
+ setAutoUpdates();
+ }
+
+
+ private int checkTime(String time) {
+ String digits = "0123456789";
+
+ int len = time.length();
+ if (len < 3 || len > 5) return -1;
+
+ int s = time.indexOf(':');
+ if (s < 0 || s > 2 || (len - s) != 3) return -1;
+
+ int h = 0;
+ for (int i = 0; i < s; i++) {
+ h *= 10;
+ int k = digits.indexOf(time.charAt(i));
+ if (k < 0) return -1;
+ h += k;
+ }
+ if (h > 23) return -1;
+
+ int m = 0;
+ for (int i = s+1; i < len; i++) {
+ m *= 10;
+ int k = digits.indexOf(time.charAt(i));
+ if (k < 0) return -1;
+ m += k;
+ }
+ if (m > 59) return -1;
+
+ return ((h * 60) + m);
+ }
+
+ private boolean areTimeListsIdentical(Vector list1, Vector list2) {
+ boolean identical = true;
+ if (list1 == null || list2 == null) identical = false;
+ if (identical && list1.size() != list2.size()) identical = false;
+ for (int i = 0; identical && i < list1.size(); i++) {
+ Vector times1 = (Vector)list1.elementAt(i);
+ Vector times2 = (Vector)list2.elementAt(i);
+ if (times1.size() != times2.size()) identical = false;
+ for (int j = 0; identical && j < times1.size(); j++) {
+ if ((((Integer)(times1.elementAt(j))).intValue()) != (((Integer)(times2.elementAt(j))).intValue())) {
+ identical = false;
+ }
+ }
+ }
+ CMS.debug("areTimeListsIdentical: identical: "+identical);
+ return identical;
+ }
+
+ private int getTimeListDays(Vector listedDays) {
+ int days = (listedDays != null)? listedDays.size(): 0;
+ CMS.debug("getTimeListDays: "+days);
+ return days;
+ }
+
+ private int getTimeListSize(Vector listedDays) {
+ int listSize = 0;
+ for (int i = 0; listedDays != null && i < listedDays.size(); i++) {
+ Vector listedTimes = (Vector)listedDays.elementAt(i);
+ listSize += ((listedTimes != null)? listedTimes.size(): 0);
+ }
+ CMS.debug("getTimeListSize: ListSize="+listSize);
+ return listSize;
+ }
+
+ private boolean isTimeListExtended(String list) {
+ boolean extendedTimeList = true;
+ if (list == null || list.indexOf('*') == -1)
+ extendedTimeList = false;
+ return extendedTimeList;
+ }
+
+ private Vector getTimeList(String list) {
+ boolean timeListPresent = false;
+ if (list == null || list.length() == 0) return null;
+ if (list.charAt(0) == ',' || list.charAt(list.length()-1) == ',') return null;
+
+ Vector listedDays = new Vector();
+
+ StringTokenizer days = new StringTokenizer(list, ";", true);
+ int n = 0;
+ Vector listedTimes = null;
+ while (days.hasMoreTokens()) {
+ String dayList = days.nextToken().trim();
+ if (dayList == null) continue;
+
+ if (dayList.equals(";")) {
+ if (timeListPresent) {
+ timeListPresent = false;
+ } else {
+ listedTimes = new Vector();
+ listedDays.addElement(listedTimes);
+ n++;
+ }
+ continue;
+ } else {
+ listedTimes = new Vector();
+ listedDays.addElement(listedTimes);
+ timeListPresent = true;
+ n++;
+ }
+ int t0 = -1;
+ StringTokenizer times = new StringTokenizer(dayList, ",");
+ while (times.hasMoreTokens()) {
+ String time = times.nextToken();
+ int k = 1;
+ if (time.charAt(0) == '*') {
+ time = time.substring(1);
+ k = -1;
+ }
+ int t = checkTime(time);
+ if (t < 0) {
+ return null;
+ } else {
+ if (t > t0) {
+ listedTimes.addElement(new Integer(k*t));
+ t0 = t;
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+ if (!timeListPresent) {
+ listedTimes = new Vector();
+ listedDays.addElement(listedTimes);
+ n++;
+ }
+
+ return listedDays;
+ }
+
+ private String checkProfile(String id, Enumeration e) {
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String profileId = (String) e.nextElement();
+ if (profileId != null && profileId.equalsIgnoreCase(id))
+ return id;
+ }
+ }
+ return null;
+ }
+
+ private Vector getProfileList(String list) {
+ Enumeration e = null;
+ IConfigStore pc = CMS.getConfigStore().getSubStore("profile");
+ if (pc != null) e = pc.getSubStoreNames();
+ if (list == null) return null;
+ if (list.length() > 0 && list.charAt(list.length()-1) == ',') return null;
+
+ Vector listedProfiles = new Vector();
+
+ StringTokenizer elements = new StringTokenizer(list, ",", true);
+ int t0 = -1;
+ int n = 0;
+ while (elements.hasMoreTokens()) {
+ String element = elements.nextToken().trim();
+ if (element == null || element.length() == 0) return null;
+ if (element.equals(",") && n % 2 == 0) return null;
+ if (n % 2 == 0) {
+ String id = checkProfile(element, e);
+ if (id != null) {
+ listedProfiles.addElement(id);
+ }
+ }
+ n++;
+ }
+ if (n % 2 == 0) return null;
+
+ return listedProfiles;
+ }
+
+
+ /**
+ * get CRL config store info
+ */
+ protected void initConfig(IConfigStore config)
+ throws EBaseException {
+
+ mEnable = config.getBoolean(Constants.PR_ENABLE, true);
+ mDescription = config.getString(Constants.PR_DESCRIPTION);
+
+ // Get CRL cache config.
+ mEnableCRLCache = config.getBoolean(Constants.PR_ENABLE_CACHE, true);
+ mCacheUpdateInterval = MINUTE * config.getInteger(Constants.PR_CACHE_FREQ, 0);
+ mEnableCacheRecovery = config.getBoolean(Constants.PR_CACHE_RECOVERY, false);
+ mEnableCacheTesting = config.getBoolean(Constants.PR_CACHE_TESTING, false);
+
+ // check if CRL generation is enabled
+ mEnableCRLUpdates = config.getBoolean(Constants.PR_ENABLE_CRL, true);
+
+ // get update schema
+ mUpdateSchema = config.getInteger(Constants.PR_UPDATE_SCHEMA, 1);
+ mSchemaCounter = 0;
+
+ // Get always update even if updated perdically.
+ mAlwaysUpdate = config.getBoolean(Constants.PR_UPDATE_ALWAYS, false);
+
+ // Get list of daily updates.
+ mEnableDailyUpdates = config.getBoolean(Constants.PR_ENABLE_DAILY, false);
+ String daily = config.getString(Constants.PR_DAILY_UPDATES, null);
+ mDailyUpdates = getTimeList(daily);
+ mExtendedTimeList = isTimeListExtended(daily);
+ mTimeListSize = getTimeListSize(mDailyUpdates);
+ if (mDailyUpdates == null || mDailyUpdates.isEmpty() || mTimeListSize == 0) {
+ mEnableDailyUpdates = false;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_INVALID_TIME_LIST"));
+ }
+
+ // Get auto update interval in minutes.
+ mEnableUpdateFreq = config.getBoolean(Constants.PR_ENABLE_FREQ, true);
+ mAutoUpdateInterval = MINUTE * config.getInteger(Constants.PR_UPDATE_FREQ, 0);
+ mMinUpdateInterval = MINUTE * config.getInteger(PROP_MIN_UPDATE_INTERVAL, 0);
+ if (mEnableUpdateFreq && mAutoUpdateInterval > 0 &&
+ mAutoUpdateInterval < mMinUpdateInterval)
+ mAutoUpdateInterval = mMinUpdateInterval;
+
+ // get next update grace period
+ mNextUpdateGracePeriod = MINUTE * config.getInteger(Constants.PR_GRACE_PERIOD, 0);
+
+ // Get V2 or V1 CRL
+ mAllowExtensions = config.getBoolean(Constants.PR_EXTENSIONS, false);
+
+ mIncludeExpiredCerts = config.getBoolean(Constants.PR_INCLUDE_EXPIREDCERTS, false);
+ mIncludeExpiredCertsOneExtraTime = config.getBoolean(Constants.PR_INCLUDE_EXPIREDCERTS_ONEEXTRATIME, false);
+ mCACertsOnly = config.getBoolean(Constants.PR_CA_CERTS_ONLY, false);
+ mProfileCertsOnly = config.getBoolean(Constants.PR_PROFILE_CERTS_ONLY, false);
+ if (mProfileCertsOnly) {
+ String profiles = config.getString(Constants.PR_PROFILE_LIST, null);
+ mProfileList = getProfileList(profiles);
+ }
+
+ // Get default signing algorithm.
+ // check if algorithm is supported.
+ mSigningAlgorithm = mCA.getCRLSigningUnit().getDefaultAlgorithm();
+ String algorithm = config.getString(Constants.PR_SIGNING_ALGORITHM, null);
+
+ if (algorithm != null) {
+ // make sure this algorithm is acceptable to CA.
+ mCA.getCRLSigningUnit().checkSigningAlgorithmFromName(algorithm);
+ mSigningAlgorithm = algorithm;
+ }
+
+ mPublishOnStart = config.getBoolean(PROP_PUBLISH_ON_START, false);
+ // if publish dn is null then certificate will be published to
+ // CA's entry in the directory.
+ mPublishDN = config.getString(PROP_PUBLISH_DN, null);
+
+ mSaveMemory = config.getBoolean("saveMemory", false);
+
+ mCMSCRLExtensions = new CMSCRLExtensions(this, config);
+
+ mExtendedNextUpdate = ((mUpdateSchema > 1 || (mEnableDailyUpdates && mExtendedTimeList)) && isDeltaCRLEnabled())?
+ config.getBoolean(Constants.PR_EXTENDED_NEXT_UPDATE, true):
+ false;
+
+ // Get serial number ranges if any.
+ mBeginSerial = config.getBigInteger(PROP_BEGIN_SERIAL, null);
+ if (mBeginSerial != null && mBeginSerial.compareTo(BigInteger.ZERO) < 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1",
+ PROP_BEGIN_SERIAL, "BigInteger", "positive number"));
+ }
+ mEndSerial = config.getBigInteger(PROP_END_SERIAL, null);
+ if (mEndSerial != null && mEndSerial.compareTo(BigInteger.ZERO) < 0) {
+ throw new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INVALID_PROPERTY_1",
+ PROP_END_SERIAL, "BigInteger", "positive number"));
+ }
+ }
+
+ /**
+ * Reads CRL issuing point, if missing, it creates one.
+ * Initializes CRL cache and republishes CRL if requested
+ * Called from auto update thread (run()).
+ * Do not call it from init(), because it will block CMS on start.
+ */
+ private void initCRL() {
+ ICRLIssuingPointRecord crlRecord = null;
+
+ mLastCacheUpdate = System.currentTimeMillis() + mCacheUpdateInterval;
+
+ try {
+ crlRecord = mCRLRepository.readCRLIssuingPointRecord(mId);
+ } catch (EDBNotAvailException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_INST_CRL", e.toString()));
+ mInitialized = CRL_IP_INITIALIZATION_FAILED;
+ return;
+ } catch (EBaseException e) {
+ // CRL was never set.
+ // fall to the following..
+ }
+
+ if (crlRecord != null) {
+ mCRLNumber = crlRecord.getCRLNumber();
+ if (crlRecord.getCRLSize() != null) {
+ mCRLSize = crlRecord.getCRLSize().longValue();
+ }
+ mNextCRLNumber = mCRLNumber.add(BigInteger.ONE);
+
+ if (crlRecord.getDeltaCRLSize() != null) {
+ mDeltaCRLSize = crlRecord.getDeltaCRLSize().longValue();
+ }
+
+ mDeltaCRLNumber = crlRecord.getDeltaCRLNumber();
+ if (mDeltaCRLNumber == null) {
+ mDeltaCRLNumber = mCRLNumber; // better recovery later
+ } else {
+ if (mDeltaCRLNumber.compareTo(mCRLNumber) < 0) {
+ mDeltaCRLNumber = mCRLNumber;
+ clearCRLCache();
+ mDeltaCRLSize = -1L;
+ }
+ }
+ mNextDeltaCRLNumber = mDeltaCRLNumber.add(BigInteger.ONE);
+
+ if (mNextDeltaCRLNumber.compareTo(mNextCRLNumber) > 0) {
+ mNextCRLNumber = mNextDeltaCRLNumber;
+ }
+
+ mLastCRLNumber = BigInteger.ZERO;
+
+ mLastUpdate = crlRecord.getThisUpdate();
+ if (mLastUpdate == null) {
+ mLastUpdate = new Date(0L);
+ }
+ mLastFullUpdate = null;
+
+ mNextUpdate = crlRecord.getNextUpdate();
+ if (isDeltaCRLEnabled()) {
+ mNextDeltaUpdate = (mNextUpdate != null)? new Date(mNextUpdate.getTime()): null;
+ }
+
+ mFirstUnsaved = crlRecord.getFirstUnsaved();
+ if (Debug.on()) {
+ Debug.trace("initCRL CRLNumber="+mCRLNumber.toString()+" CRLSize="+mCRLSize+
+ " FirstUnsaved="+mFirstUnsaved);
+ }
+ if (mFirstUnsaved == null ||
+ (mFirstUnsaved != null && mFirstUnsaved.equals(ICRLIssuingPointRecord.NEW_CACHE))) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ } else {
+ byte[] crl = crlRecord.getCRL();
+
+ if (crl != null) {
+ X509CRLImpl x509crl = null;
+
+ if (mEnableCRLCache || mPublishOnStart) {
+ try {
+ x509crl = new X509CRLImpl(crl);
+ } catch (Exception e) {
+ clearCRLCache();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_DECODE_CRL", e.toString()));
+ } catch (OutOfMemoryError e) {
+ clearCRLCache();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_DECODE_CRL", e.toString()));
+ mInitialized = CRL_IP_INITIALIZATION_FAILED;
+ return;
+ }
+ }
+ if (x509crl != null) {
+ mLastFullUpdate = x509crl.getThisUpdate();
+ if (mEnableCRLCache) {
+ if (mCRLCacheIsCleared && mUpdatingCRL == CRL_UPDATE_DONE) {
+ mRevokedCerts = crlRecord.getRevokedCerts();
+ if (mRevokedCerts == null) {
+ mRevokedCerts = new Hashtable();
+ }
+ mUnrevokedCerts = crlRecord.getUnrevokedCerts();
+ if (mUnrevokedCerts == null) {
+ mUnrevokedCerts = new Hashtable();
+ }
+ mExpiredCerts = crlRecord.getExpiredCerts();
+ if (mExpiredCerts == null) {
+ mExpiredCerts = new Hashtable();
+ }
+ if (isDeltaCRLEnabled()) {
+ mNextUpdate = x509crl.getNextUpdate();
+ }
+ mCRLCerts = x509crl.getListOfRevokedCertificates();
+ }
+ if (mFirstUnsaved != null && !mFirstUnsaved.equals(ICRLIssuingPointRecord.CLEAN_CACHE)) {
+ recoverCRLCache();
+ } else {
+ mCRLCacheIsCleared = false;
+ }
+ mInitialized = CRL_IP_INITIALIZED;
+ }
+ if (mPublishOnStart) {
+ try {
+ publishCRL(x509crl);
+ x509crl = null;
+ } catch (EBaseException e) {
+ x509crl = null;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_CRL", mCRLNumber.toString(), e.toString()));
+ } catch (OutOfMemoryError e) {
+ x509crl = null;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_CRL", mCRLNumber.toString(), e.toString()));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (crlRecord == null) {
+ // no crl was ever created, or crl in db is corrupted.
+ // create new one.
+ try {
+ crlRecord = new CRLIssuingPointRecord(mId, BigInteger.ZERO, Long.valueOf(-1),
+ null, null, BigInteger.ZERO, Long.valueOf(-1),
+ mRevokedCerts, mUnrevokedCerts, mExpiredCerts);
+ mCRLRepository.addCRLIssuingPointRecord(crlRecord);
+ mCRLNumber = BigInteger.ZERO; //BIG_ZERO;
+ mNextCRLNumber = BigInteger.ONE; //BIG_ONE;
+ mLastCRLNumber = mCRLNumber;
+ mDeltaCRLNumber = mCRLNumber;
+ mNextDeltaCRLNumber = mNextCRLNumber;
+ mLastUpdate = new Date(0L);
+ if (crlRecord != null) {
+ // This will trigger updateCRLNow, which will also publish CRL.
+ if ((mDoManualUpdate == false) &&
+ (mEnableCRLCache || mAlwaysUpdate ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0))) {
+ mInitialized = CRL_IP_INITIALIZED;
+ setManualUpdate(null);
+ }
+ }
+ } catch (EBaseException ex) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_CREATE_CRL", ex.toString()));
+ mInitialized = CRL_IP_INITIALIZATION_FAILED;
+ return;
+ }
+ }
+ mInitialized = CRL_IP_INITIALIZED;
+ }
+
+ private Object configMonitor = new Object();
+
+ public boolean updateConfig(NameValuePairs params) {
+ synchronized (configMonitor) {
+ boolean noRestart = true;
+ boolean modifiedSchedule = false;
+
+ for (int i = 0; i < params.size(); i++) {
+ NameValuePair p = params.elementAt(i);
+ String name = p.getName();
+ String value = p.getValue();
+
+ // -- Update Schema --
+ if (name.equals(Constants.PR_ENABLE_CRL)) {
+ if (value.equals(Constants.FALSE) && mEnableCRLUpdates) {
+ mEnableCRLUpdates = false;
+ modifiedSchedule = true;
+ } else if (value.equals(Constants.TRUE) && (!mEnableCRLUpdates)) {
+ mEnableCRLUpdates = true;
+ modifiedSchedule = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_UPDATE_SCHEMA)) {
+ try {
+ if (value != null && value.length() > 0) {
+ int schema = Integer.parseInt(value.trim());
+ if (mUpdateSchema != schema) {
+ mUpdateSchema = schema;
+ mSchemaCounter = 0;
+ modifiedSchedule = true;
+ }
+ }
+ } catch (NumberFormatException e) {
+ noRestart = false;
+ }
+ }
+
+ if (name.equals(Constants.PR_EXTENDED_NEXT_UPDATE)) {
+ if (value.equals(Constants.FALSE) && mExtendedNextUpdate) {
+ mExtendedNextUpdate = false;
+ } else if (value.equals(Constants.TRUE) && (!mExtendedNextUpdate)) {
+ mExtendedNextUpdate = true;
+ }
+ }
+
+ // -- Update Frequency --
+ if (name.equals(Constants.PR_UPDATE_ALWAYS)) {
+ if (value.equals(Constants.FALSE) && mAlwaysUpdate) {
+ mAlwaysUpdate = false;
+ } else if (value.equals(Constants.TRUE) && (!mAlwaysUpdate)) {
+ mAlwaysUpdate = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_ENABLE_DAILY)) {
+ if (value.equals(Constants.FALSE) && mEnableDailyUpdates) {
+ mEnableDailyUpdates = false;
+ modifiedSchedule = true;
+ } else if (value.equals(Constants.TRUE) && (!mEnableDailyUpdates)) {
+ mEnableDailyUpdates = true;
+ modifiedSchedule = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_DAILY_UPDATES)) {
+ boolean extendedTimeList = isTimeListExtended(value);
+ Vector dailyUpdates = getTimeList(value);
+ if (mExtendedTimeList != extendedTimeList) {
+ mExtendedTimeList = extendedTimeList;
+ modifiedSchedule = true;
+ }
+ if (!areTimeListsIdentical(mDailyUpdates, dailyUpdates)) {
+ mCurrentDay = 0;
+ mLastDay = 0;
+ mDailyUpdates = dailyUpdates;
+ mTimeListSize = getTimeListSize(mDailyUpdates);
+ modifiedSchedule = true;
+ }
+ if (mDailyUpdates == null || mDailyUpdates.isEmpty() || mTimeListSize == 0) {
+ mEnableDailyUpdates = false;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_INVALID_TIME_LIST"));
+ }
+ }
+
+ if (name.equals(Constants.PR_ENABLE_FREQ)) {
+ if (value.equals(Constants.FALSE) && mEnableUpdateFreq) {
+ mEnableUpdateFreq = false;
+ modifiedSchedule = true;
+ } else if (value.equals(Constants.TRUE) && (!mEnableUpdateFreq)) {
+ mEnableUpdateFreq = true;
+ modifiedSchedule = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_UPDATE_FREQ)) {
+ try {
+ if (value != null && value.length() > 0) {
+ long t = MINUTE * Long.parseLong(value.trim());
+ if (mAutoUpdateInterval != t) {
+ mAutoUpdateInterval = t;
+ modifiedSchedule = true;
+ }
+ } else {
+ if (mAutoUpdateInterval != 0) {
+ mAutoUpdateInterval = 0;
+ modifiedSchedule = true;
+ }
+ }
+ } catch (NumberFormatException e) {
+ noRestart = false;
+ }
+ }
+
+ if (name.equals(Constants.PR_GRACE_PERIOD)) {
+ try {
+ if (value != null && value.length() > 0) {
+ mNextUpdateGracePeriod = MINUTE * Long.parseLong(value.trim());
+ }
+ } catch (NumberFormatException e) {
+ noRestart = false;
+ }
+ }
+
+ // -- CRL Cache --
+ if (name.equals(Constants.PR_ENABLE_CACHE)) {
+ if (value.equals(Constants.FALSE) && mEnableCRLCache) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mEnableCRLCache = false;
+ modifiedSchedule = true;
+ } else if (value.equals(Constants.TRUE) && (!mEnableCRLCache)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mEnableCRLCache = true;
+ modifiedSchedule = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_CACHE_FREQ)) {
+ try {
+ if (value != null && value.length() > 0) {
+ long t = MINUTE * Long.parseLong(value.trim());
+ if (mCacheUpdateInterval != t) {
+ mCacheUpdateInterval = t;
+ modifiedSchedule = true;
+ }
+ }
+ } catch (NumberFormatException e) {
+ noRestart = false;
+ }
+ }
+
+ if (name.equals(Constants.PR_CACHE_RECOVERY)) {
+ if (value.equals(Constants.FALSE) && mEnableCacheRecovery) {
+ mEnableCacheRecovery = false;
+ } else if (value.equals(Constants.TRUE) && (!mEnableCacheRecovery)) {
+ mEnableCacheRecovery = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_CACHE_TESTING)) {
+ if (value.equals(Constants.FALSE) && mEnableCacheTesting) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mEnableCacheTesting = false;
+ setManualUpdate(null);
+ } else if (value.equals(Constants.TRUE) && (!mEnableCacheTesting)) {
+ mEnableCacheTesting = true;
+ }
+ }
+
+ // -- CRL Format --
+ if (name.equals(Constants.PR_SIGNING_ALGORITHM)) {
+ if (value != null) value = value.trim();
+ if (!mSigningAlgorithm.equals(value)) {
+ mSigningAlgorithm = value;
+ }
+ }
+
+ if (name.equals(Constants.PR_EXTENSIONS)) {
+ if (value.equals(Constants.FALSE) && mAllowExtensions) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mAllowExtensions = false;
+ } else if (value.equals(Constants.TRUE) && (!mAllowExtensions)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mAllowExtensions = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_INCLUDE_EXPIREDCERTS)) {
+ if (value.equals(Constants.FALSE) && mIncludeExpiredCerts) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mIncludeExpiredCerts = false;
+ } else if (value.equals(Constants.TRUE) && (!mIncludeExpiredCerts)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mIncludeExpiredCerts = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_INCLUDE_EXPIREDCERTS_ONEEXTRATIME)) {
+ if (value.equals(Constants.FALSE) && mIncludeExpiredCertsOneExtraTime) {
+ mIncludeExpiredCertsOneExtraTime = false;
+ } else if (value.equals(Constants.TRUE) && (!mIncludeExpiredCertsOneExtraTime)) {
+ mIncludeExpiredCertsOneExtraTime = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_CA_CERTS_ONLY)) {
+ Extension distExt = getCRLExtension(IssuingDistributionPointExtension.NAME);
+ IssuingDistributionPointExtension iExt = (IssuingDistributionPointExtension) distExt;
+ IssuingDistributionPoint issuingDistributionPoint = null;
+ if(iExt != null)
+ issuingDistributionPoint = iExt.getIssuingDistributionPoint();
+ if (value.equals(Constants.FALSE) && mCACertsOnly) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mCACertsOnly = false;
+ } else if (value.equals(Constants.TRUE) && (!mCACertsOnly)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mCACertsOnly = true;
+ }
+ //attempt to sync the IssuingDistributionPoint Extension value of
+ //onlyContainsCACerts
+ if(issuingDistributionPoint != null && params.size() > 1) {
+ boolean onlyContainsCACerts = issuingDistributionPoint.getOnlyContainsCACerts();
+ if(onlyContainsCACerts != mCACertsOnly) {
+ IConfigStore config = mCA.getConfigStore();
+ IConfigStore crlsSubStore =
+ config.getSubStore(mCA.PROP_CRL_SUBSTORE);
+ IConfigStore crlSubStore = crlsSubStore.getSubStore(mId);
+ IConfigStore crlExtsSubStore =
+ crlSubStore.getSubStore(mCA.PROP_CRLEXT_SUBSTORE);
+ crlExtsSubStore = crlExtsSubStore.getSubStore(IssuingDistributionPointExtension.NAME);
+
+ if(crlExtsSubStore != null) {
+ String val = "";
+ if(mCACertsOnly == true) {
+ val = Constants.TRUE;
+ } else {
+ val = Constants.FALSE;
+ }
+ crlExtsSubStore.putString(PROP_CACERTS,val);
+ try {
+ crlExtsSubStore.commit(true);
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+ }
+
+ if (name.equals(Constants.PR_PROFILE_CERTS_ONLY)) {
+ if (value.equals(Constants.FALSE) && mProfileCertsOnly) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mProfileCertsOnly = false;
+ } else if (value.equals(Constants.TRUE) && (!mProfileCertsOnly)) {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ mProfileCertsOnly = true;
+ }
+ }
+
+ if (name.equals(Constants.PR_PROFILE_LIST)) {
+ Vector profileList = getProfileList(value);
+ if (((profileList != null) ^ (mProfileList != null)) ||
+ (profileList != null && mProfileList != null &&
+ (!mProfileList.equals(profileList)))) {
+ if (profileList != null) {
+ mProfileList = (Vector) profileList.clone();
+ } else {
+ mProfileList = null;
+ }
+ clearCRLCache();
+ updateCRLCacheRepository();
+ }
+ if (mProfileList == null || mProfileList.isEmpty()) {
+ mProfileCertsOnly = false;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_INVALID_PROFILE_LIST"));
+ }
+ }
+ }
+
+ if (modifiedSchedule) setAutoUpdates();
+
+ return noRestart;
+ }
+ }
+
+ /**
+ * This method is called during shutdown.
+ * <P>
+ */
+ public synchronized void shutdown() {
+ // this should stop a thread if necessary
+ if (mEnableCRLCache && mCacheUpdateInterval > 0) {
+ updateCRLCacheRepository();
+ }
+ mEnable = false;
+
+ setAutoUpdates();
+ /*
+ if (mUpdateThread != null) {
+ try {
+ mUpdateThread.interrupt();
+ }
+ catch (Exception e) {
+ }
+ }
+ */
+ }
+
+ /**
+ * Returns internal id of this CRL issuing point.
+ * <P>
+ *
+ * @return internal id of this CRL issuing point
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Returns internal description of this CRL issuing point.
+ * <P>
+ *
+ * @return internal description of this CRL issuing point
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ /**
+ * Sets internal description of this CRL issuing point.
+ *
+ * @param description description for this CRL issuing point.
+ */
+ public void setDescription(String description) {
+ mDescription = description;
+ }
+
+ /**
+ * Returns DN of the directory entry where CRLs.from this issuing point
+ * are published.
+ * <P>
+ *
+ * @return DN of the directory entry where CRLs are published.
+ */
+ public String getPublishDN() {
+ return mPublishDN;
+ }
+
+ /**
+ * Returns signing algorithm.
+ * <P>
+ *
+ * @return SigningAlgorithm.
+ */
+ public String getSigningAlgorithm() {
+ return mSigningAlgorithm;
+ }
+
+ public String getLastSigningAlgorithm() {
+ return mLastSigningAlgorithm;
+ }
+
+ /**
+ * Returns current CRL generation schema for this CRL issuing point.
+ * <P>
+ *
+ * @return current CRL generation schema for this CRL issuing point
+ */
+ public int getCRLSchema() {
+ return mUpdateSchema;
+ }
+
+ /**
+ * Returns current CRL number of this CRL issuing point.
+ * <P>
+ *
+ * @return current CRL number of this CRL issuing point
+ */
+ public BigInteger getCRLNumber() {
+ return mCRLNumber;
+ }
+
+ /**
+ * Returns current delta CRL number of this CRL issuing point.
+ * <P>
+ *
+ * @return current delta CRL number of this CRL issuing point
+ */
+ public BigInteger getDeltaCRLNumber() {
+ return (isDeltaCRLEnabled() && mDeltaCRLSize > -1)? mDeltaCRLNumber: BigInteger.ZERO;
+ }
+
+ /**
+ * Returns next CRL number of this CRL issuing point.
+ * <P>
+ *
+ * @return next CRL number of this CRL issuing point
+ */
+ public BigInteger getNextCRLNumber() {
+ return mNextDeltaCRLNumber;
+ }
+
+ /**
+ * Returns number of entries in the CRL
+ * <P>
+ *
+ * @return number of entries in the CRL
+ */
+ public long getCRLSize() {
+ return (mCRLCerts.size() > 0 && mCRLSize == 0)? mCRLCerts.size(): mCRLSize;
+ }
+
+ /**
+ * Returns number of entries in delta CRL
+ * <P>
+ *
+ * @return number of entries in delta CRL
+ */
+ public long getDeltaCRLSize() {
+ return mDeltaCRLSize;
+ }
+
+ /**
+ * Returns last update time
+ * <P>
+ *
+ * @return last CRL update time
+ */
+ public Date getLastUpdate() {
+ return mLastUpdate;
+ }
+
+ /**
+ * Returns next update time
+ * <P>
+ *
+ * @return next CRL update time
+ */
+ public Date getNextUpdate() {
+ return mNextUpdate;
+ }
+
+ /**
+ * Returns next update time
+ * <P>
+ *
+ * @return next CRL update time
+ */
+ public Date getNextDeltaUpdate() {
+ return mNextDeltaUpdate;
+ }
+
+ /**
+ * Returns all the revoked certificates from the CRL cache.
+ * <P>
+ *
+ * @return set of all the revoked certificates or null if there are none.
+ */
+ public Set getRevokedCertificates(int start, int end) {
+ if (mCRLCacheIsCleared || mCRLCerts == null || mCRLCerts.isEmpty()) {
+ return null;
+ } else {
+ ArraySet certSet = new ArraySet();
+ Collection badCerts = mCRLCerts.values();
+ Object[] objs = badCerts.toArray();
+ for (int i = start; i < end && i < objs.length; i++)
+ certSet.add(objs[i]);
+ return certSet;
+ }
+ }
+
+ /**
+ * Returns certificate authority.
+ * <P>
+ *
+ * @return certificate authority
+ */
+ public ISubsystem getCertificateAuthority() {
+ return mCA;
+ }
+
+ /**
+ * Sets CRL auto updates
+ */
+
+ private synchronized void setAutoUpdates() {
+ if ((mEnable && mUpdateThread == null) &&
+ ((mEnableCRLCache && mCacheUpdateInterval > 0) ||
+ (mEnableCRLUpdates &&
+ ((mEnableDailyUpdates && mDailyUpdates != null &&
+ mTimeListSize > 0) ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0) ||
+ (mInitialized == CRL_IP_NOT_INITIALIZED) ||
+ mDoLastAutoUpdate || mDoManualUpdate)))) {
+ mUpdateThread = new Thread(this, "CRLIssuingPoint-" + mId);
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_ISSUING_START_CRL", mId));
+ mUpdateThread.setDaemon(true);
+ mUpdateThread.start();
+ }
+
+ if ((mInitialized == CRL_IP_INITIALIZED) && (((mNextUpdate != null) ^
+ ((mEnableDailyUpdates && mDailyUpdates != null && mTimeListSize > 0) ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0))) ||
+ (!mEnableCRLUpdates && mNextUpdate != null))) {
+ mDoLastAutoUpdate = true;
+ }
+
+ if (mEnableUpdateFreq && mAutoUpdateInterval > 0 &&
+ mAutoUpdateInterval < mMinUpdateInterval) {
+ mAutoUpdateInterval = mMinUpdateInterval;
+ }
+
+ notifyAll();
+ }
+
+ /**
+ * Sets CRL manual-update
+ * Starts or stops worker thread as necessary.
+ */
+ public synchronized void setManualUpdate(String signatureAlgorithm) {
+ if (!mDoManualUpdate) {
+ mDoManualUpdate = true;
+ mSignatureAlgorithmForManualUpdate = signatureAlgorithm;
+ if (mEnableUpdateFreq && mAutoUpdateInterval > 0 && mUpdateThread != null) {
+ notifyAll();
+ } else {
+ setAutoUpdates();
+ }
+ }
+ }
+
+ /**
+ * @return auto update interval in milliseconds.
+ */
+ public long getAutoUpdateInterval() {
+ return (mEnableUpdateFreq)? mAutoUpdateInterval: 0;
+ }
+
+ /**
+ * @return always update the CRL
+ */
+ public boolean getAlwaysUpdate() {
+ return mAlwaysUpdate;
+ }
+
+ /**
+ * @return next update grace period in minutes.
+ */
+
+ public long getNextUpdateGracePeriod() {
+ return mNextUpdateGracePeriod;
+ }
+
+ /**
+ * Finds next update time expressed as delay or time of the next update.
+ *
+ * @param fromLastUpdate if true, function returns delay to the next update time
+ * otherwise returns the next update time.
+ * @param delta if true, function returns the next update time for delta CRL,
+ * otherwise returns the next update time for CRL.
+ * @return delay to the next update time or the next update time itself
+ */
+ private long findNextUpdate(boolean fromLastUpdate, boolean delta) {
+ long now = System.currentTimeMillis();
+ TimeZone tz = TimeZone.getDefault();
+ int offset = tz.getOffset(now);
+ long oneDay = 1440L * MINUTE;
+ long nowToday = (now + (long)offset) % oneDay;
+ long startOfToday = now - nowToday;
+
+ long lastUpdated = (mLastUpdate != null)? mLastUpdate.getTime(): now;
+ long lastUpdateDay = lastUpdated - ((lastUpdated + (long)offset) % oneDay);
+
+ long lastUpdate = (mLastUpdate != null && fromLastUpdate)? mLastUpdate.getTime(): now;
+ long last = (lastUpdate + (long)offset) % oneDay;
+ long lastDay = lastUpdate - last;
+
+ boolean isDeltaEnabled = isDeltaCRLEnabled();
+ long next = 0L;
+ long nextUpdate = 0L;
+
+ CMS.debug("findNextUpdate: fromLastUpdate: "+fromLastUpdate+" delta: "+delta);
+
+ int numberOfDays = (int)((startOfToday - lastUpdateDay) / oneDay);
+ if (numberOfDays > 0 && mDailyUpdates.size() > 1 &&
+ ((mCurrentDay == mLastDay) ||
+ (mCurrentDay != ((mLastDay + numberOfDays) % mDailyUpdates.size())))) {
+ mCurrentDay = (mLastDay + numberOfDays) % mDailyUpdates.size();
+ }
+
+ if ((delta || fromLastUpdate) && isDeltaEnabled &&
+ (mUpdateSchema > 1 || (mEnableDailyUpdates && mExtendedTimeList)) &&
+ mNextDeltaUpdate != null) {
+ nextUpdate = mNextDeltaUpdate.getTime();
+ } else if (mNextUpdate != null) {
+ nextUpdate = mNextUpdate.getTime();
+ }
+
+ if (mEnableDailyUpdates &&
+ mDailyUpdates != null && mDailyUpdates.size() > 0) {
+ int n = 0;
+ if (mDailyUpdates.size() == 1 && ((Vector)mDailyUpdates.elementAt(0)).size() == 1 &&
+ mEnableUpdateFreq && mAutoUpdateInterval > 0) {
+ // Interval updates with starting time
+ long firstTime = MINUTE * ((Integer)((Vector)mDailyUpdates.elementAt(0)).elementAt(0)).longValue();
+ long t = firstTime;
+ long interval = mAutoUpdateInterval;
+ if (mExtendedNextUpdate && (!fromLastUpdate) && (!delta) &&
+ isDeltaEnabled && mUpdateSchema > 1) {
+ interval *= mUpdateSchema;
+ }
+ while (t < oneDay) {
+ if (t - mMinUpdateInterval > last) break;
+ t += interval;
+ n++;
+ }
+
+ if (t <= oneDay) {
+ next = lastDay + t;
+ if (fromLastUpdate) {
+ n = n % mUpdateSchema;
+ if (t == firstTime) {
+ mSchemaCounter = 0;
+ } else if (n != mSchemaCounter) {
+ if (mSchemaCounter != 0 && (mSchemaCounter < n || n == 0)) {
+ mSchemaCounter = n;
+ }
+ }
+ }
+ } else {
+ next = lastDay + oneDay + firstTime;
+ if (fromLastUpdate) {
+ mSchemaCounter = 0;
+ }
+ }
+ } else {
+ // Daily updates following the list
+ if (last > nowToday) {
+ last = nowToday - 100; // 100ms - precision
+ }
+ int i, m;
+ for (i = 0, m = 0; i < mCurrentDay; i++) {
+ m += ((Vector)mDailyUpdates.elementAt(i)).size();
+ }
+ // search the current day
+ for (i = 0; i < ((Vector)mDailyUpdates.elementAt(mCurrentDay)).size(); i++) {
+ long t = MINUTE * ((Integer)((Vector)mDailyUpdates.elementAt(mCurrentDay)).elementAt(i)).longValue();
+ if (mEnableDailyUpdates && mExtendedTimeList) {
+ if (mExtendedNextUpdate && (!fromLastUpdate) && (!delta) && isDeltaEnabled) {
+ if (t < 0) {
+ t *= -1;
+ } else {
+ t = 0;
+ }
+ } else {
+ if (t < 0) {
+ t *= -1;
+ }
+ }
+ }
+ if (t - mMinUpdateInterval > last) {
+ if (mExtendedNextUpdate && (!fromLastUpdate) && (!(mEnableDailyUpdates && mExtendedTimeList)) && (!delta) &&
+ isDeltaEnabled && mUpdateSchema > 1) {
+ i += mUpdateSchema - ((i + m) % mUpdateSchema);
+ }
+ break;
+ }
+ n++;
+ }
+
+ if (i < ((Vector)mDailyUpdates.elementAt(mCurrentDay)).size()) {
+ // found inside the current day
+ next = (MINUTE * ((Integer)((Vector)mDailyUpdates.elementAt(mCurrentDay)).elementAt(i)).longValue());
+ if (mEnableDailyUpdates && mExtendedTimeList && next < 0) {
+ next *= -1;
+ if (fromLastUpdate) {
+ mSchemaCounter = 0;
+ }
+ }
+ next += ((lastDay < lastUpdateDay)? lastDay: lastUpdateDay) + (oneDay * (mCurrentDay - mLastDay));
+
+ if (fromLastUpdate && (!(mEnableDailyUpdates && mExtendedTimeList))) {
+ n = n % mUpdateSchema;
+ if (i == 0 && mCurrentDay == 0) {
+ mSchemaCounter = 0;
+ } else if (n != mSchemaCounter) {
+ if (mSchemaCounter != 0 && ((n == 0 && mCurrentDay == 0) || mSchemaCounter < n)) {
+ mSchemaCounter = n;
+ }
+ }
+ }
+ } else {
+ // done with today
+ int j = i - ((Vector)mDailyUpdates.elementAt(mCurrentDay)).size();
+ int nDays = 1;
+ long t = 0;
+ if (mDailyUpdates.size() > 1) {
+ while (nDays <= mDailyUpdates.size()) {
+ int nextDay = (mCurrentDay + nDays) % mDailyUpdates.size();
+ if (j < ((Vector)mDailyUpdates.elementAt(nextDay)).size()) {
+ if (nextDay == 0 && (!(mEnableDailyUpdates && mExtendedTimeList))) j = 0;
+ t = MINUTE * ((Integer)((Vector)mDailyUpdates.elementAt(nextDay)).elementAt(j)).longValue();
+ if (mEnableDailyUpdates && mExtendedTimeList) {
+ if (mExtendedNextUpdate && (!fromLastUpdate) && (!delta) && isDeltaEnabled) {
+ if (t < 0) {
+ t *= -1;
+ } else {
+ j++;
+ continue;
+ }
+ } else {
+ if (t < 0) {
+ t *= -1;
+ if (fromLastUpdate) {
+ mSchemaCounter = 0;
+ }
+ }
+ }
+ }
+ break;
+ } else {
+ j -= ((Vector)mDailyUpdates.elementAt(nextDay)).size();
+ }
+ nDays++;
+ }
+ }
+ next = ((lastDay < lastUpdateDay)? lastDay: lastUpdateDay) + (oneDay * nDays) + t;
+
+ if (fromLastUpdate && mDailyUpdates.size() < 2) {
+ mSchemaCounter = 0;
+ }
+ }
+ }
+ } else if (mEnableUpdateFreq && mAutoUpdateInterval > 0) {
+ // Interval updates without starting time
+ if (mExtendedNextUpdate && (!fromLastUpdate) && (!delta) && isDeltaEnabled && mUpdateSchema > 1) {
+ next = lastUpdate + (mUpdateSchema * mAutoUpdateInterval);
+ } else {
+ next = lastUpdate + mAutoUpdateInterval;
+ }
+ }
+
+ if (fromLastUpdate && nextUpdate > 0 && (nextUpdate < next || nextUpdate >= now)) {
+ next = nextUpdate;
+ }
+
+ CMS.debug("findNextUpdate: "+((new Date(next)).toString())+((fromLastUpdate)? " delay: "+(next-now): ""));
+
+ return (fromLastUpdate)? next-now: next;
+ }
+
+
+ /**
+ * Implements Runnable interface. Defines auto-update
+ * logic used by worker thread.
+ * <P>
+ */
+ public void run() {
+ while (mEnable && ((mEnableCRLCache && mCacheUpdateInterval > 0) ||
+ (mInitialized == CRL_IP_NOT_INITIALIZED) ||
+ mDoLastAutoUpdate || (mEnableCRLUpdates &&
+ ((mEnableDailyUpdates && mDailyUpdates != null &&
+ mTimeListSize > 0) ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0) ||
+ mDoManualUpdate)))) {
+
+ synchronized (this) {
+ long delay = 0;
+ long delay2 = 0;
+ boolean doCacheUpdate = false;
+ boolean scheduledUpdates = mEnableCRLUpdates &&
+ ((mEnableDailyUpdates && mDailyUpdates != null &&
+ mTimeListSize > 0) ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0));
+
+ if (mInitialized == CRL_IP_NOT_INITIALIZED)
+ initCRL();
+ if (mInitialized == CRL_IP_INITIALIZED && (!mEnable)) break;
+
+ if ((mEnableCRLUpdates && mDoManualUpdate) || mDoLastAutoUpdate) {
+ delay = 0;
+ } else if (scheduledUpdates) {
+ delay = findNextUpdate(true, false);
+ }
+
+ if (mEnableCRLCache && mCacheUpdateInterval > 0) {
+ delay2 = mLastCacheUpdate + mCacheUpdateInterval -
+ System.currentTimeMillis();
+ if (delay2 < delay ||
+ (!(scheduledUpdates || mDoLastAutoUpdate ||
+ (mEnableCRLUpdates && mDoManualUpdate)))) {
+ delay = delay2;
+ if (delay <= 0) {
+ doCacheUpdate = true;
+ mLastCacheUpdate = System.currentTimeMillis();
+ }
+ }
+ }
+
+ if (delay > 0) {
+ try {
+ wait(delay);
+ } catch (InterruptedException e) {
+ }
+ } else {
+ try {
+ if (doCacheUpdate) {
+ updateCRLCacheRepository();
+ } else if (mAutoUpdateInterval > 0 || mDoLastAutoUpdate || mDoManualUpdate) {
+ updateCRL();
+ }
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_CRL",
+ (doCacheUpdate)?"update CRL cache":"update CRL", e.toString()));
+ if (Debug.on()) {
+ Debug.trace((doCacheUpdate)?"update CRL cache":"update CRL" + " error " + e);
+ Debug.printStackTrace(e);
+ }
+ }
+ // put this here to prevent continuous loop if internal
+ // db is down.
+ if (mDoLastAutoUpdate)
+ mDoLastAutoUpdate = false;
+ if (mDoManualUpdate) {
+ mDoManualUpdate = false;
+ mSignatureAlgorithmForManualUpdate = null;
+ }
+ }
+ }
+ }
+ mUpdateThread = null;
+ }
+
+
+ /**
+ * Updates CRL and publishes it.
+ * If time elapsed since last CRL update is less than
+ * minUpdateInterval silently returns.
+ * Otherwise determines nextUpdate by adding autoUpdateInterval or
+ * minUpdateInterval to the current time. If neither of the
+ * intervals are defined nextUpdate will be null.
+ * Then using specified configuration parameters it formulates new
+ * CRL, signs it, updates CRLIssuingPointRecord in the database
+ * and publishes CRL in the directory.
+ * <P>
+ */
+ private void updateCRL() throws EBaseException {
+ /*
+ if (mEnableUpdateFreq && mAutoUpdateInterval > 0 &&
+ (System.currentTimeMillis() - mLastUpdate.getTime() <
+ mMinUpdateInterval)) {
+ // log or alternatively throw an Exception
+ return;
+ }
+ */
+ if (mDoManualUpdate && mSignatureAlgorithmForManualUpdate != null) {
+ updateCRLNow(mSignatureAlgorithmForManualUpdate);
+ } else {
+ updateCRLNow();
+ }
+ }
+
+ /**
+ * This method may be overrided by CRLWithExpiredCerts.java
+ */
+ public String getFilter() {
+ // PLEASE DONT CHANGE THE FILTER. It is indexed.
+ // Changing it will degrade performance. See
+ // also com.netscape.certsetup.LDAPUtil.java
+ String filter = "";
+
+ if (mIncludeExpiredCerts)
+ filter += "(|";
+ filter += "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")";
+ if (mIncludeExpiredCerts)
+ filter += "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))";
+
+ if (mCACertsOnly) {
+ filter += "(x509cert.BasicConstraints.isCA=on)";
+ }
+
+ if (mProfileCertsOnly && mProfileList != null && mProfileList.size() > 0) {
+ if (mProfileList.size() > 1) {
+ filter += "(|";
+ }
+ for (int k = 0; k < mProfileList.size(); k++) {
+ String id = (String) mProfileList.elementAt(k);
+ filter += "(" + CertRecord.ATTR_META_INFO + "=profileId:" + id + ")";
+ }
+ if (mProfileList.size() > 1) {
+ filter += ")";
+ }
+ }
+
+ // check if any ranges specified.
+ if (mBeginSerial != null) {
+ filter += "(" + CertRecord.ATTR_ID + ">=" + mBeginSerial.toString() + ")";
+ }
+ if (mEndSerial != null) {
+ filter += "(" + CertRecord.ATTR_ID + "<=" + mEndSerial.toString() + ")";
+ }
+
+ // get all revoked non-expired certs.
+ if (mEndSerial != null || mBeginSerial != null || mCACertsOnly ||
+ (mProfileCertsOnly && mProfileList != null && mProfileList.size() > 0)) {
+ filter = "(&" + filter + ")";
+ }
+
+ return filter;
+ }
+
+ /**
+ * Gets a enumeration of revoked certs to put into CRL.
+ * This does not include expired certs.
+ * <i>Override this method to make a CRL other than the
+ * full/complete CRL.</i>
+ * @return Enumeration of CertRecords to put into CRL.
+ * @exception EBaseException if an error occured in the database.
+ */
+ public void processRevokedCerts(IElementProcessor p)
+ throws EBaseException {
+ CertRecProcessor cp = (CertRecProcessor) p;
+ String filter = getFilter();
+
+ // NOTE: dangerous cast.
+ // correct way would be to modify interface and add
+ // accessor but we don't want to touch the interface
+ CertificateRepository cr = (CertificateRepository)mCertRepository;
+
+ synchronized (cr.mCertStatusUpdateThread) {
+ CMS.debug("Starting processRevokedCerts (entered lock)");
+ ICertRecordList list = mCertRepository.findCertRecordsInList(filter,
+ new String[] {ICertRecord.ATTR_ID, ICertRecord.ATTR_REVO_INFO, "objectclass" },
+ "serialno",
+ mPageSize);
+
+ int totalSize = list.getSize();
+
+ list.processCertRecords(0, totalSize - 1, cp);
+ CMS.debug("processRevokedCerts done");
+ }
+ }
+
+ /**
+ * clears CRL cache
+ */
+ public void clearCRLCache() {
+ mCRLCacheIsCleared = true;
+ mCRLCerts.clear();
+ mRevokedCerts.clear();
+ mUnrevokedCerts.clear();
+ mExpiredCerts.clear();
+ mSchemaCounter = 0;
+ }
+
+ /**
+ * clears Delta-CRL cache
+ */
+ public void clearDeltaCRLCache() {
+ mRevokedCerts.clear();
+ mUnrevokedCerts.clear();
+ mExpiredCerts.clear();
+ mSchemaCounter = 0;
+ }
+
+ /**
+ * recovers CRL cache
+ */
+ private void recoverCRLCache() {
+ if (mEnableCacheRecovery) {
+ // 553815 - original filter was not aligned with any VLV index
+ // String filter = "(&(requeststate=complete)"+
+ // "(|(requestType=" + IRequest.REVOCATION_REQUEST + ")"+
+ // "(requestType=" + IRequest.UNREVOCATION_REQUEST + ")))";
+ String filter = "(requeststate=complete)";
+ if (Debug.on()) {
+ Debug.trace("recoverCRLCache mFirstUnsaved="+mFirstUnsaved+" filter="+filter);
+ }
+ IRequestQueue mQueue = mCA.getRequestQueue();
+
+ IRequestVirtualList list = mQueue.getPagedRequestsByFilter(
+ new RequestId(mFirstUnsaved), filter, 500, "requestId");
+ if (Debug.on()) {
+ Debug.trace("recoverCRLCache size="+list.getSize()+" index="+list.getCurrentIndex());
+ }
+
+ CertRecProcessor cp = new CertRecProcessor(mCRLCerts, this, mLogger, mAllowExtensions);
+ boolean includeCert = true;
+
+ int s = list.getSize() - list.getCurrentIndex();
+ for (int i = 0; i < s; i++) {
+ IRequest request = null;
+ try {
+ request = list.getElementAt(i);
+ } catch (Exception e) {
+ // handled below
+ }
+ if (request == null) {
+ continue;
+ }
+ if (Debug.on()) {
+ Debug.trace("recoverCRLCache request="+request.getRequestId().toString()+
+ " type="+request.getRequestType());
+ }
+ if (IRequest.REVOCATION_REQUEST.equals(request.getRequestType())) {
+ RevokedCertImpl revokedCert[] =
+ request.getExtDataInRevokedCertArray(IRequest.CERT_INFO);
+ for (int j = 0; j < revokedCert.length; j++) {
+ if (Debug.on()) {
+ Debug.trace("recoverCRLCache R j="+j+" length="+revokedCert.length+
+ " SerialNumber=0x"+revokedCert[j].getSerialNumber().toString(16));
+ }
+ if(cp != null)
+ includeCert = cp.checkRevokedCertExtensions(revokedCert[j].getExtensions());
+ if(includeCert) {
+ updateRevokedCert(REVOKED_CERT, revokedCert[j].getSerialNumber(), revokedCert[j]);
+ }
+ }
+ } else if (IRequest.UNREVOCATION_REQUEST.equals(request.getRequestType())) {
+ BigInteger serialNo[] = request.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+ for (int j = 0; j < serialNo.length; j++) {
+ if (Debug.on()) {
+ Debug.trace("recoverCRLCache U j="+j+" length="+serialNo.length+
+ " SerialNumber=0x"+serialNo[j].toString(16));
+ }
+ updateRevokedCert(UNREVOKED_CERT, serialNo[j], null);
+ }
+ }
+ }
+
+ try {
+ mCRLRepository.updateRevokedCerts(mId, mRevokedCerts, mUnrevokedCerts);
+ mFirstUnsaved = ICRLIssuingPointRecord.CLEAN_CACHE;
+ mCRLCacheIsCleared = false;
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_CRL_CACHE", e.toString()));
+ }
+ } else {
+ clearCRLCache();
+ updateCRLCacheRepository();
+ }
+ }
+
+ public int getNumberOfRecentlyRevokedCerts() {
+ return mRevokedCerts.size();
+ }
+
+ public int getNumberOfRecentlyUnrevokedCerts() {
+ return mUnrevokedCerts.size();
+ }
+
+ public int getNumberOfRecentlyExpiredCerts() {
+ return mExpiredCerts.size();
+ }
+
+ private Extension getCRLExtension(String extName) {
+ if(mAllowExtensions == false) {
+ return null;
+ }
+ if(mCMSCRLExtensions.isCRLExtensionEnabled(extName) == false) {
+ return null;
+ }
+
+ CMSCRLExtensions exts = (CMSCRLExtensions) this.getCRLExtensions();
+ CRLExtensions ext = new CRLExtensions();
+
+ Vector extNames = exts.getCRLExtensionNames();
+ for (int i = 0; i < extNames.size(); i++) {
+ String curName = (String) extNames.elementAt(i);
+ if (curName.equals(extName)) {
+ exts.addToCRLExtensions(ext, extName, null);
+ }
+ }
+ Extension theExt = null;
+ try {
+ theExt = ext.get(extName);
+ } catch (Exception e) {
+ }
+
+ CMS.debug("CRLIssuingPoint.getCRLExtension extension: " + theExt);
+ return theExt;
+ }
+ /**
+ * get required crl entry extensions
+ */
+ public CRLExtensions getRequiredEntryExtensions(CRLExtensions exts) {
+ CRLExtensions entryExt = null;
+
+ if (mAllowExtensions && exts != null && exts.size() > 0) {
+ entryExt = new CRLExtensions();
+ Vector extNames = mCMSCRLExtensions.getCRLEntryExtensionNames();
+
+ for (int i = 0; i < extNames.size(); i++) {
+ String extName = (String) extNames.elementAt(i);
+
+ if (mCMSCRLExtensions.isCRLExtensionEnabled(extName)) {
+ int k;
+
+ for (k = 0; k < exts.size(); k++) {
+ Extension ext = (Extension) exts.elementAt(k);
+ String name = mCMSCRLExtensions.getCRLExtensionName(
+ ext.getExtensionId().toString());
+
+ if (extName.equals(name)) {
+ if (!(ext instanceof CRLReasonExtension) ||
+ (((CRLReasonExtension) ext).getReason().toInt() >
+ RevocationReason.UNSPECIFIED.toInt())) {
+ mCMSCRLExtensions.addToCRLExtensions(entryExt, extName, ext);
+ }
+ break;
+ }
+ }
+ if (k == exts.size()) {
+ mCMSCRLExtensions.addToCRLExtensions(entryExt, extName, null);
+ }
+ }
+ }
+ }
+
+ return entryExt;
+ }
+
+ private static final int REVOKED_CERT = 1;
+ private static final int UNREVOKED_CERT = 2;
+ private Object cacheMonitor = new Object();
+
+ /**
+ * update CRL cache with new revoked-unrevoked certificate info
+ */
+ private void updateRevokedCert(int certType,
+ BigInteger serialNumber,
+ RevokedCertImpl revokedCert) {
+ updateRevokedCert(certType, serialNumber, revokedCert, null);
+ }
+
+ private void updateRevokedCert(int certType,
+ BigInteger serialNumber,
+ RevokedCertImpl revokedCert,
+ String requestId) {
+ synchronized (cacheMonitor) {
+ if (requestId != null && mFirstUnsaved != null &&
+ mFirstUnsaved.equals(ICRLIssuingPointRecord.CLEAN_CACHE)) {
+ mFirstUnsaved = requestId;
+ try {
+ mCRLRepository.updateFirstUnsaved(mId, mFirstUnsaved);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_CRL_CACHE", e.toString()));
+ }
+ }
+ if (certType == REVOKED_CERT) {
+ if (mUnrevokedCerts.containsKey(serialNumber)) {
+ mUnrevokedCerts.remove(serialNumber);
+ if (mCRLCerts.containsKey(serialNumber)) {
+ Date revocationDate = revokedCert.getRevocationDate();
+ CRLExtensions entryExt = getRequiredEntryExtensions(revokedCert.getExtensions());
+ RevokedCertImpl newRevokedCert =
+ new RevokedCertImpl(serialNumber, revocationDate, entryExt);
+
+ mCRLCerts.put(serialNumber, (RevokedCertificate) newRevokedCert);
+ }
+ } else {
+ Date revocationDate = revokedCert.getRevocationDate();
+ CRLExtensions entryExt = getRequiredEntryExtensions(revokedCert.getExtensions());
+ RevokedCertImpl newRevokedCert =
+ new RevokedCertImpl(serialNumber, revocationDate, entryExt);
+
+ mRevokedCerts.put(serialNumber, (RevokedCertificate) newRevokedCert);
+ }
+ } else if (certType == UNREVOKED_CERT) {
+ if (mRevokedCerts.containsKey(serialNumber)) {
+ mRevokedCerts.remove(serialNumber);
+ } else {
+ CRLExtensions entryExt = new CRLExtensions();
+
+ try {
+ entryExt.set(CRLReasonExtension.REMOVE_FROM_CRL.getName(),
+ CRLReasonExtension.REMOVE_FROM_CRL);
+ } catch (IOException e) {
+ }
+ RevokedCertImpl newRevokedCert = new RevokedCertImpl(serialNumber,
+ CMS.getCurrentDate(), entryExt);
+
+ mUnrevokedCerts.put(serialNumber, (RevokedCertificate) newRevokedCert);
+ }
+ }
+ }
+ }
+
+ /**
+ * registers revoked certificates
+ */
+ public void addRevokedCert(BigInteger serialNumber, RevokedCertImpl revokedCert) {
+ addRevokedCert(serialNumber, revokedCert, null);
+ }
+
+ public void addRevokedCert(BigInteger serialNumber, RevokedCertImpl revokedCert,
+ String requestId) {
+
+ CertRecProcessor cp = new CertRecProcessor(mCRLCerts, this, mLogger, mAllowExtensions);
+ boolean includeCert = true;
+ if(cp != null)
+ includeCert = cp.checkRevokedCertExtensions(revokedCert.getExtensions());
+
+ if (mEnable && mEnableCRLCache && includeCert == true) {
+ updateRevokedCert(REVOKED_CERT, serialNumber, revokedCert, requestId);
+
+ if (mCacheUpdateInterval == 0) {
+ try {
+ mCRLRepository.updateRevokedCerts(mId, mRevokedCerts, mUnrevokedCerts);
+ mFirstUnsaved = ICRLIssuingPointRecord.CLEAN_CACHE;
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_REVOKED_CERT", mId, e.toString()));
+ }
+ }
+ }
+ }
+
+ /**
+ * registers unrevoked certificates
+ */
+ public void addUnrevokedCert(BigInteger serialNumber) {
+ addUnrevokedCert(serialNumber, null);
+ }
+
+ public void addUnrevokedCert(BigInteger serialNumber, String requestId) {
+ if (mEnable && mEnableCRLCache) {
+ updateRevokedCert(UNREVOKED_CERT, serialNumber, null, requestId);
+
+ if (mCacheUpdateInterval == 0) {
+ try {
+ mCRLRepository.updateRevokedCerts(mId, mRevokedCerts, mUnrevokedCerts);
+ mFirstUnsaved = ICRLIssuingPointRecord.CLEAN_CACHE;
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_UNREVOKED_CERT", mId, e.toString()));
+ }
+ }
+ }
+ }
+
+ /**
+ * registers expired certificates
+ */
+ public void addExpiredCert(BigInteger serialNumber) {
+
+ if (mEnable && mEnableCRLCache && (!mIncludeExpiredCerts)) {
+ if (!(mExpiredCerts.containsKey(serialNumber))) {
+ CRLExtensions entryExt = new CRLExtensions();
+
+ try {
+ entryExt.set(CRLReasonExtension.REMOVE_FROM_CRL.getName(),
+ CRLReasonExtension.REMOVE_FROM_CRL);
+ } catch (IOException e) {
+ }
+ RevokedCertImpl newRevokedCert = new RevokedCertImpl(serialNumber,
+ CMS.getCurrentDate(), entryExt);
+
+ mExpiredCerts.put(serialNumber, (RevokedCertificate) newRevokedCert);
+ }
+
+ if (mCacheUpdateInterval == 0) {
+ try {
+ mCRLRepository.updateExpiredCerts(mId, mExpiredCerts);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_EXPIRED_CERT", mId, e.toString()));
+ }
+ }
+ }
+ }
+
+ private Object repositoryMonitor = new Object();
+
+ public void updateCRLCacheRepository() {
+ synchronized (repositoryMonitor) {
+ try {
+ mCRLRepository.updateCRLCache(mId, Long.valueOf(mCRLSize),
+ mRevokedCerts, mUnrevokedCerts, mExpiredCerts);
+ mFirstUnsaved = ICRLIssuingPointRecord.CLEAN_CACHE;
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_STORE_CRL_CACHE", e.toString()));
+ }
+ }
+ }
+
+ public boolean isDeltaCRLEnabled() {
+ return (mAllowExtensions && mEnableCRLCache &&
+ mCMSCRLExtensions.isCRLExtensionEnabled(DeltaCRLIndicatorExtension.NAME) &&
+ mCMSCRLExtensions.isCRLExtensionEnabled(CRLNumberExtension.NAME) &&
+ mCMSCRLExtensions.isCRLExtensionEnabled(CRLReasonExtension.NAME));
+ }
+
+ public boolean isThisCurrentDeltaCRL(X509CRLImpl deltaCRL) {
+ boolean result = false;
+
+ if (isDeltaCRLEnabled() && mDeltaCRLSize > -1) {
+ if (deltaCRL != null) {
+ CRLExtensions crlExtensions = deltaCRL.getExtensions();
+
+ if (crlExtensions != null) {
+ for (int k = 0; k < crlExtensions.size(); k++) {
+ Extension ext = (Extension) crlExtensions.elementAt(k);
+
+ if (DeltaCRLIndicatorExtension.OID.equals(ext.getExtensionId().toString())) {
+ DeltaCRLIndicatorExtension dExt = (DeltaCRLIndicatorExtension) ext;
+ BigInteger crlNumber = null;
+
+ try {
+ crlNumber = (BigInteger) dExt.get(DeltaCRLIndicatorExtension.NUMBER);
+ } catch (IOException e) {
+ }
+ if (crlNumber != null && (crlNumber.equals(mLastCRLNumber) ||
+ mLastCRLNumber.equals(BigInteger.ZERO))) {
+ result = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return (result);
+ }
+
+ public boolean isCRLCacheEnabled() {
+ return mEnableCRLCache;
+ }
+
+ public boolean isCRLCacheEmpty() {
+ return ((mCRLCerts != null)? mCRLCerts.isEmpty(): true);
+ }
+
+ public boolean isCRLCacheTestingEnabled() {
+ return mEnableCacheTesting;
+ }
+
+ public Date getRevocationDateFromCache(BigInteger serialNumber,
+ boolean checkDeltaCache,
+ boolean includeExpiredCerts) {
+ Date revocationDate = null;
+
+ if (mCRLCerts.containsKey(serialNumber)) {
+ revocationDate = ((RevokedCertificate) mCRLCerts.get(serialNumber)).getRevocationDate();
+ }
+
+ if (checkDeltaCache && isDeltaCRLEnabled()) {
+ if (mUnrevokedCerts.containsKey(serialNumber)) {
+ revocationDate = null;
+ }
+ if (mRevokedCerts.containsKey(serialNumber)) {
+ revocationDate = ((RevokedCertificate) mRevokedCerts.get(serialNumber)).getRevocationDate();
+ }
+ if (!includeExpiredCerts && mExpiredCerts.containsKey(serialNumber)) {
+ revocationDate = null;
+ }
+ }
+
+ return revocationDate;
+ }
+
+ public Vector getSplitTimes() {
+ Vector splits = new Vector();
+
+ for (int i = 0; i < mSplits.length; i++) {
+ splits.addElement(Long.valueOf(mSplits[i]));
+ }
+ return splits;
+ }
+
+ public int isCRLUpdateInProgress() {
+ return mUpdatingCRL;
+ }
+
+ /**
+ * updates CRL and publishes it now
+ */
+ public void updateCRLNow()
+ throws EBaseException {
+
+ updateCRLNow(null);
+ }
+
+ public synchronized void updateCRLNow(String signingAlgorithm)
+ throws EBaseException {
+
+ if ((!mEnable) || (!mEnableCRLUpdates && !mDoLastAutoUpdate)) return;
+ CMS.debug("Updating CRL");
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, AuditFormat.LEVEL,
+ CMS.getLogMessage("CMSCORE_CA_CA_CRL_UPDATE_STARTED"),
+ new Object[] {
+ getId(),
+ getNextCRLNumber(),
+ Boolean.toString(isDeltaCRLEnabled()),
+ Boolean.toString(isCRLCacheEnabled()),
+ Boolean.toString(mEnableCacheRecovery),
+ Boolean.toString(mCRLCacheIsCleared),
+ ""+mCRLCerts.size()+","+mRevokedCerts.size()+","+mUnrevokedCerts.size()+","+mExpiredCerts.size()+""
+ }
+ );
+ mUpdatingCRL = CRL_UPDATE_STARTED;
+ if (signingAlgorithm == null || signingAlgorithm.length() == 0)
+ signingAlgorithm = mSigningAlgorithm;
+ mLastSigningAlgorithm = signingAlgorithm;
+ Date thisUpdate = CMS.getCurrentDate();
+ Date nextUpdate = null;
+ Date nextDeltaUpdate = null;
+
+ if (mEnableCRLUpdates && ((mEnableDailyUpdates &&
+ mDailyUpdates != null && mTimeListSize > 0) ||
+ (mEnableUpdateFreq && mAutoUpdateInterval > 0))) {
+
+ if ((!isDeltaCRLEnabled()) || mSchemaCounter == 0 || mUpdateSchema == 1) {
+ nextUpdate = new Date(findNextUpdate(false, false));
+ mNextUpdate = new Date(nextUpdate.getTime());
+ }
+ if (isDeltaCRLEnabled()) {
+ if (mUpdateSchema > 1 || (mEnableDailyUpdates && mExtendedTimeList && mTimeListSize > 1)) {
+ nextDeltaUpdate = new Date(findNextUpdate(false, true));
+ if (mExtendedNextUpdate && mSchemaCounter > 0 &&
+ mNextUpdate != null && mNextUpdate.equals(nextDeltaUpdate)) {
+ if (mEnableDailyUpdates && mExtendedTimeList && mTimeListSize > 1) {
+ mSchemaCounter = mTimeListSize - 1;
+ } else {
+ mSchemaCounter = mUpdateSchema - 1;
+ }
+ }
+ } else {
+ nextDeltaUpdate = new Date(nextUpdate.getTime());
+ if (mUpdateSchema == 1) {
+ mSchemaCounter = 0;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < mSplits.length; i++) {
+ mSplits[i] = 0;
+ }
+
+ mLastUpdate = thisUpdate;
+ // mNextUpdate = nextUpdate;
+ mNextDeltaUpdate = (nextDeltaUpdate != null)? new Date(nextDeltaUpdate.getTime()): null;
+ if (nextUpdate != null) {
+ nextUpdate.setTime((nextUpdate.getTime())+mNextUpdateGracePeriod);
+ }
+ if (nextDeltaUpdate != null) {
+ nextDeltaUpdate.setTime((nextDeltaUpdate.getTime())+mNextUpdateGracePeriod);
+ }
+
+ mSplits[0] -= System.currentTimeMillis();
+ Hashtable clonedRevokedCerts = (Hashtable) mRevokedCerts.clone();
+ Hashtable clonedUnrevokedCerts = (Hashtable) mUnrevokedCerts.clone();
+ Hashtable clonedExpiredCerts = (Hashtable) mExpiredCerts.clone();
+
+ mSplits[0] += System.currentTimeMillis();
+
+ // starting from the beginning
+
+ if ((!mEnableCRLCache) ||
+ ((mCRLCacheIsCleared && mCRLCerts.isEmpty() && clonedRevokedCerts.isEmpty() &&
+ clonedUnrevokedCerts.isEmpty() && clonedExpiredCerts.isEmpty()) ||
+ (mCRLCerts.isEmpty() && (!clonedUnrevokedCerts.isEmpty())) ||
+ (mCRLCerts.size() < clonedUnrevokedCerts.size()) ||
+ (mCRLCerts.isEmpty() && (mCRLSize > 0)) ||
+ (mCRLCerts.size() > 0 && mCRLSize == 0))) {
+
+ mSplits[5] -= System.currentTimeMillis();
+ mDeltaCRLSize = -1;
+ clearCRLCache();
+ clonedRevokedCerts.clear();
+ clonedUnrevokedCerts.clear();
+ clonedExpiredCerts.clear();
+ mSchemaCounter = 0;
+
+ IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("generation");
+ }
+ CertRecProcessor cp = new CertRecProcessor(mCRLCerts, this, mLogger, mAllowExtensions);
+ processRevokedCerts(cp);
+
+ if (statsSub != null) {
+ statsSub.endTiming("generation");
+ }
+
+ mCRLCacheIsCleared = false;
+ mSplits[5] += System.currentTimeMillis();
+ } else {
+ if (isDeltaCRLEnabled()) {
+ mSplits[1] -= System.currentTimeMillis();
+ Hashtable deltaCRLCerts = (Hashtable) clonedRevokedCerts.clone();
+
+ deltaCRLCerts.putAll(clonedUnrevokedCerts);
+ if (mIncludeExpiredCertsOneExtraTime) {
+ if (!clonedExpiredCerts.isEmpty()) {
+ for (Enumeration e = clonedExpiredCerts.keys(); e.hasMoreElements();) {
+ BigInteger serialNumber = (BigInteger) e.nextElement();
+ if ((mLastFullUpdate != null &&
+ mLastFullUpdate.after(((RevokedCertificate)(mExpiredCerts.get(serialNumber))).getRevocationDate())) ||
+ mLastFullUpdate == null) {
+ deltaCRLCerts.put(serialNumber, clonedExpiredCerts.get(serialNumber));
+ }
+ }
+ }
+ } else {
+ deltaCRLCerts.putAll(clonedExpiredCerts);
+ }
+
+ mLastCRLNumber = mCRLNumber;
+
+ CRLExtensions ext = new CRLExtensions();
+ Vector extNames = mCMSCRLExtensions.getCRLExtensionNames();
+
+ for (int i = 0; i < extNames.size(); i++) {
+ String extName = (String) extNames.elementAt(i);
+
+ if (mCMSCRLExtensions.isCRLExtensionEnabled(extName) &&
+ (!extName.equals(FreshestCRLExtension.NAME))) {
+ mCMSCRLExtensions.addToCRLExtensions(ext, extName, null);
+ }
+ }
+ mSplits[1] += System.currentTimeMillis();
+
+ X509CRLImpl newX509DeltaCRL = null;
+
+ try {
+ mSplits[2] -= System.currentTimeMillis();
+ byte[] newDeltaCRL;
+
+ // #56123 - dont generate CRL if no revoked certificates
+ if (mConfigStore.getBoolean("noCRLIfNoRevokedCert", false)) {
+ if (deltaCRLCerts.size() == 0) {
+ CMS.debug("CRLIssuingPoint: No Revoked Certificates Found And noCRLIfNoRevokedCert is set to true - No Delta CRL Generated");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", "No Revoked Certificates"));
+ }
+ }
+ X509CRLImpl crl = new X509CRLImpl(mCA.getCRLX500Name(),
+ AlgorithmId.get(signingAlgorithm),
+ thisUpdate, nextDeltaUpdate, deltaCRLCerts, ext);
+
+ newX509DeltaCRL = mCA.sign(crl, signingAlgorithm);
+ newDeltaCRL = newX509DeltaCRL.getEncoded();
+ mSplits[2] += System.currentTimeMillis();
+
+ mSplits[3] -= System.currentTimeMillis();
+ mCRLRepository.updateDeltaCRL(mId, mNextDeltaCRLNumber,
+ Long.valueOf(deltaCRLCerts.size()), mNextDeltaUpdate, newDeltaCRL);
+ mSplits[3] += System.currentTimeMillis();
+
+ mDeltaCRLSize = deltaCRLCerts.size();
+
+
+ long totalTime = 0;
+ String splitTimes = " (";
+ for (int i = 1; i < mSplits.length && i < 5; i++) {
+ totalTime += mSplits[i];
+ if (i > 1) splitTimes += ",";
+ splitTimes += Long.toString(mSplits[i]);
+ }
+ splitTimes += ")";
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ CMS.getLogMessage("CMSCORE_CA_CA_DELTA_CRL_UPDATED"),
+ new Object[] {
+ getId(),
+ getNextCRLNumber(),
+ getCRLNumber(),
+ getLastUpdate(),
+ getNextDeltaUpdate(),
+ Long.toString(mDeltaCRLSize),
+ Long.toString(totalTime)+splitTimes
+ }
+ );
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_OR_STORE_DELTA", e.toString()));
+ mDeltaCRLSize = -1;
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_DELTA", e.toString()));
+ mDeltaCRLSize = -1;
+ } catch (CRLException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_DELTA", e.toString()));
+ mDeltaCRLSize = -1;
+ } catch (X509ExtensionException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_DELTA", e.toString()));
+ mDeltaCRLSize = -1;
+ } catch (OutOfMemoryError e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_DELTA", e.toString()));
+ mDeltaCRLSize = -1;
+ }
+
+ try {
+ mSplits[4] -= System.currentTimeMillis();
+ publishCRL(newX509DeltaCRL, true);
+ mSplits[4] += System.currentTimeMillis();
+ } catch (EBaseException e) {
+ newX509DeltaCRL = null;
+ if (Debug.on())
+ Debug.printStackTrace(e);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_DELTA", mCRLNumber.toString(), e.toString()));
+ } catch (OutOfMemoryError e) {
+ newX509DeltaCRL = null;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_DELTA", mCRLNumber.toString(), e.toString()));
+ }
+ } else {
+ mDeltaCRLSize = -1;
+ }
+
+ mSplits[5] -= System.currentTimeMillis();
+
+ if (mSchemaCounter == 0) {
+ if (((!mCRLCerts.isEmpty()) && ((!clonedRevokedCerts.isEmpty()) ||
+ (!clonedUnrevokedCerts.isEmpty()) || (!clonedExpiredCerts.isEmpty()))) ||
+ (mCRLCerts.isEmpty() && (mCRLSize == 0) && (!clonedRevokedCerts.isEmpty()))) {
+
+ if (!clonedUnrevokedCerts.isEmpty()) {
+ for (Enumeration e = clonedUnrevokedCerts.keys(); e.hasMoreElements();) {
+ BigInteger serialNumber = (BigInteger) e.nextElement();
+
+ if (mCRLCerts.containsKey(serialNumber)) {
+ mCRLCerts.remove(serialNumber);
+ }
+ mUnrevokedCerts.remove(serialNumber);
+ }
+ }
+
+ if (!clonedRevokedCerts.isEmpty()) {
+ for (Enumeration e = clonedRevokedCerts.keys(); e.hasMoreElements();) {
+ BigInteger serialNumber = (BigInteger) e.nextElement();
+
+ mCRLCerts.put(serialNumber, mRevokedCerts.get(serialNumber));
+ mRevokedCerts.remove(serialNumber);
+ }
+ }
+
+ if (!clonedExpiredCerts.isEmpty()) {
+ for (Enumeration e = clonedExpiredCerts.keys(); e.hasMoreElements();) {
+ BigInteger serialNumber = (BigInteger) e.nextElement();
+
+ if ((!mIncludeExpiredCertsOneExtraTime) ||
+ (mLastFullUpdate != null &&
+ mLastFullUpdate.after(((RevokedCertificate)(mExpiredCerts.get(serialNumber))).getRevocationDate())) ||
+ mLastFullUpdate == null) {
+ if (mCRLCerts.containsKey(serialNumber)) {
+ mCRLCerts.remove(serialNumber);
+ }
+ mExpiredCerts.remove(serialNumber);
+ }
+ }
+ }
+ }
+ mLastFullUpdate = mLastUpdate;
+ }
+ mSplits[5] += System.currentTimeMillis();
+ }
+
+ clonedRevokedCerts.clear();
+ clonedUnrevokedCerts.clear();
+ clonedExpiredCerts.clear();
+ clonedRevokedCerts = null;
+ clonedUnrevokedCerts = null;
+ clonedExpiredCerts = null;
+
+ if ((!isDeltaCRLEnabled()) || mSchemaCounter == 0) {
+ mSplits[6] -= System.currentTimeMillis();
+ if (mNextDeltaCRLNumber.compareTo(mNextCRLNumber) > 0) {
+ mNextCRLNumber = mNextDeltaCRLNumber;
+ }
+
+ CRLExtensions ext = null;
+
+ if (mAllowExtensions) {
+ ext = new CRLExtensions();
+ Vector extNames = mCMSCRLExtensions.getCRLExtensionNames();
+
+ for (int i = 0; i < extNames.size(); i++) {
+ String extName = (String) extNames.elementAt(i);
+
+ if (mCMSCRLExtensions.isCRLExtensionEnabled(extName) &&
+ (!extName.equals(DeltaCRLIndicatorExtension.NAME))) {
+ mCMSCRLExtensions.addToCRLExtensions(ext, extName, null);
+ }
+ }
+ }
+ mSplits[6] += System.currentTimeMillis();
+ // for audit log
+
+ X509CRLImpl newX509CRL;
+
+ try {
+ byte[] newCRL;
+
+ CMS.debug("Making CRL with algorithm " +
+ signingAlgorithm + " " + AlgorithmId.get(signingAlgorithm));
+
+ mSplits[7] -= System.currentTimeMillis();
+
+ // #56123 - dont generate CRL if no revoked certificates
+ if (mConfigStore.getBoolean("noCRLIfNoRevokedCert", false)) {
+ if (mCRLCerts.size() == 0) {
+ CMS.debug("CRLIssuingPoint: No Revoked Certificates Found And noCRLIfNoRevokedCert is set to true - No CRL Generated");
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", "No Revoked Certificates"));
+ }
+ }
+ CMS.debug("before new X509CRLImpl");
+ X509CRLImpl crl = new X509CRLImpl(mCA.getCRLX500Name(),
+ AlgorithmId.get(signingAlgorithm),
+ thisUpdate, nextUpdate, mCRLCerts, ext);
+
+ CMS.debug("before sign");
+ newX509CRL = mCA.sign(crl, signingAlgorithm);
+
+ CMS.debug("before getEncoded()");
+ newCRL = newX509CRL.getEncoded();
+ CMS.debug("after getEncoded()");
+ mSplits[7] += System.currentTimeMillis();
+
+ mSplits[8] -= System.currentTimeMillis();
+
+ Date nextUpdateDate = mNextUpdate;
+ if (isDeltaCRLEnabled() && (mUpdateSchema > 1 ||
+ (mEnableDailyUpdates && mExtendedTimeList)) && mNextDeltaUpdate != null) {
+ nextUpdateDate = mNextDeltaUpdate;
+ }
+ if (mSaveMemory) {
+ mCRLRepository.updateCRLIssuingPointRecord(
+ mId, newCRL, thisUpdate, nextUpdateDate,
+ mNextCRLNumber, Long.valueOf(mCRLCerts.size()));
+ updateCRLCacheRepository();
+ } else {
+ mCRLRepository.updateCRLIssuingPointRecord(
+ mId, newCRL, thisUpdate, nextUpdateDate,
+ mNextCRLNumber, Long.valueOf(mCRLCerts.size()),
+ mRevokedCerts, mUnrevokedCerts, mExpiredCerts);
+ mFirstUnsaved = ICRLIssuingPointRecord.CLEAN_CACHE;
+ }
+
+ mSplits[8] += System.currentTimeMillis();
+
+ mCRLSize = mCRLCerts.size();
+ mCRLNumber = mNextCRLNumber;
+ mDeltaCRLNumber = mCRLNumber;
+ mNextCRLNumber = mCRLNumber.add(BigInteger.ONE);
+ mNextDeltaCRLNumber = mNextCRLNumber;
+
+
+ CMS.debug("Logging CRL Update to transaction log");
+ long totalTime = 0;
+ long crlTime = 0;
+ long deltaTime = 0;
+ String splitTimes = " (";
+ for (int i = 0; i < mSplits.length; i++) {
+ totalTime += mSplits[i];
+ if (i > 0 && i < 5) {
+ deltaTime += mSplits[i];
+ } else {
+ crlTime += mSplits[i];
+ }
+ if (i > 0) splitTimes += ",";
+ splitTimes += Long.toString(mSplits[i]);
+ }
+ splitTimes += "," + Long.toString(deltaTime) + "," + Long.toString(crlTime) + "," + Long.toString(totalTime) + ")";
+ mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER,
+ AuditFormat.LEVEL,
+ CMS.getLogMessage("CMSCORE_CA_CA_CRL_UPDATED"),
+ new Object[] {
+ getId(),
+ getCRLNumber(),
+ getLastUpdate(),
+ getNextUpdate(),
+ Long.toString(mCRLSize),
+ Long.toString(totalTime),
+ Long.toString(crlTime),
+ Long.toString(deltaTime)+splitTimes
+ }
+ );
+ CMS.debug("Finished Logging CRL Update to transaction log");
+
+ } catch (EBaseException e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ if (Debug.on())
+ Debug.printStackTrace(e);
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_OR_STORE_CRL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ } catch (NoSuchAlgorithmException e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_CRL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ } catch (CRLException e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_CRL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ } catch (X509ExtensionException e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_CRL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ } catch (OutOfMemoryError e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_SIGN_CRL", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ }
+
+ try {
+ mSplits[9] -= System.currentTimeMillis();
+ mUpdatingCRL = CRL_PUBLISHING_STARTED;
+ publishCRL(newX509CRL);
+ newX509CRL = null;
+ mSplits[9] += System.currentTimeMillis();
+ } catch (EBaseException e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_CRL", mCRLNumber.toString(), e.toString()));
+ } catch (OutOfMemoryError e) {
+ newX509CRL = null;
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_PUBLISH_CRL", mCRLNumber.toString(), e.toString()));
+ }
+ }
+
+ if (isDeltaCRLEnabled() && mDeltaCRLSize > -1 && mSchemaCounter > 0) {
+ mDeltaCRLNumber = mNextDeltaCRLNumber;
+ mNextDeltaCRLNumber = mDeltaCRLNumber.add(BigInteger.ONE);
+ }
+
+ if ((!(mEnableDailyUpdates && mExtendedTimeList)) || mSchemaCounter == 0) mSchemaCounter++;
+ if ((mEnableDailyUpdates && mExtendedTimeList && mSchemaCounter >= mTimeListSize) ||
+ (mUpdateSchema > 1 && mSchemaCounter >= mUpdateSchema)) mSchemaCounter = 0;
+ mLastDay = mCurrentDay;
+
+ mUpdatingCRL = CRL_UPDATE_DONE;
+ notifyAll();
+ }
+
+ /**
+ * publish CRL. called from updateCRLNow() and init().
+ */
+
+ public void publishCRL()
+ throws EBaseException {
+ publishCRL(null);
+ }
+
+ protected void publishCRL(X509CRLImpl x509crl)
+ throws EBaseException {
+ publishCRL(x509crl, false);
+ }
+
+ protected void publishCRL(X509CRLImpl x509crl, boolean isDeltaCRL)
+ throws EBaseException {
+ SessionContext sc = SessionContext.getContext();
+
+ IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("crl_publishing");
+ }
+
+ if (mCountMod == 0) {
+ sc.put(SC_CRL_COUNT, Integer.toString(mCount));
+ } else {
+ sc.put(SC_CRL_COUNT, Integer.toString(mCount%mCountMod));
+ }
+ mCount++;
+ sc.put(SC_ISSUING_POINT_ID, mId);
+ if (isDeltaCRL) {
+ sc.put(SC_IS_DELTA_CRL, "true");
+ } else {
+ sc.put(SC_IS_DELTA_CRL, "false");
+ }
+
+ ICRLIssuingPointRecord crlRecord = null;
+
+ CMS.debug("Publish CRL");
+ try {
+ if (x509crl == null) {
+ crlRecord = mCRLRepository.readCRLIssuingPointRecord(mId);
+ if (crlRecord != null) {
+ byte[] crl = (isDeltaCRL) ? crlRecord.getDeltaCRL() : crlRecord.getCRL();
+
+ if (crl != null) {
+ x509crl = new X509CRLImpl(crl);
+ }
+ }
+ }
+ if (x509crl != null &&
+ mPublisherProcessor != null && mPublisherProcessor.enabled()) {
+ Enumeration rules = mPublisherProcessor.getRules(IPublisherProcessor.PROP_LOCAL_CRL);
+ if (rules == null || !rules.hasMoreElements()) {
+ CMS.debug("CRL publishing is not enabled.");
+ } else {
+ if (mPublishDN != null) {
+ mPublisherProcessor.publishCRL(mPublishDN, x509crl);
+ CMS.debug("CRL published to " + mPublishDN);
+ } else {
+ mPublisherProcessor.publishCRL(x509crl,getId());
+ CMS.debug("CRL published.");
+ }
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("Could not publish CRL. Error " + e);
+ CMS.debug("Could not publish CRL. ID " + mId);
+ throw new EErrorPublishCRL(
+ CMS.getUserMessage("CMS_CA_ERROR_PUBLISH_CRL", mId, e.toString()));
+ } finally {
+ if (statsSub != null) {
+ statsSub.endTiming("crl_publishing");
+ }
+ }
+ }
+
+ protected void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA, level,
+ "CRLIssuingPoint " + mId + " - " + msg);
+ }
+
+ void setConfigParam(String name, String value) {
+ mConfigStore.putString(name, value);
+ }
+
+ class RevocationRequestListener implements IRequestListener {
+
+ public void init(ISubsystem sys, IConfigStore config)
+ throws EBaseException {
+ }
+
+ public void set(String name, String val) {
+ }
+
+ public void accept(IRequest r) {
+ String requestType = r.getRequestType();
+
+ if (requestType.equals(IRequest.REVOCATION_REQUEST) ||
+ requestType.equals(IRequest.UNREVOCATION_REQUEST) ||
+ requestType.equals(IRequest.CLA_CERT4CRL_REQUEST) ||
+ requestType.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) {
+ CMS.debug("Revocation listener called.");
+ // check if serial number is in begin/end range if set.
+ if (mBeginSerial != null || mEndSerial != null) {
+ CMS.debug(
+ "Checking if serial number is between " +
+ mBeginSerial + " and " + mEndSerial);
+ BigInteger[] serialNos =
+ r.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS);
+
+ if (serialNos == null || serialNos.length == 0) {
+ X509CertImpl oldCerts[] =
+ r.getExtDataInCertArray(IRequest.OLD_CERTS);
+
+ if (oldCerts == null || oldCerts.length == 0)
+ return;
+ serialNos = new BigInteger[oldCerts.length];
+ for (int i = 0; i < oldCerts.length; i++) {
+ serialNos[i] = oldCerts[i].getSerialNumber();
+ }
+ }
+
+ boolean inRange = false;
+
+ for (int i = 0; i < serialNos.length; i++) {
+ if ((mBeginSerial == null ||
+ serialNos[i].compareTo(mBeginSerial) >= 0) &&
+ (mEndSerial == null ||
+ serialNos[i].compareTo(mEndSerial) <= 0)) {
+ inRange = true;
+ }
+ }
+ if (!inRange) {
+ return;
+ }
+ }
+
+ if (mAlwaysUpdate) {
+ try {
+ updateCRLNow();
+ r.setExtData(mCrlUpdateStatus, IRequest.RES_SUCCESS);
+ if (mPublisherProcessor != null) {
+ r.setExtData(mCrlPublishStatus, IRequest.RES_SUCCESS);
+ }
+ } catch (EErrorPublishCRL e) {
+ // error already logged in updateCRLNow();
+ r.setExtData(mCrlUpdateStatus, IRequest.RES_SUCCESS);
+ if (mPublisherProcessor != null) {
+ r.setExtData(mCrlPublishStatus, IRequest.RES_ERROR);
+ r.setExtData(mCrlPublishError, e);
+ }
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_UPDATE_CRL", e.toString()));
+ r.setExtData(mCrlUpdateStatus, IRequest.RES_ERROR);
+ r.setExtData(mCrlUpdateError, e);
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_ISSUING_UPDATE_CRL", e.toString()));
+ if (Debug.on())
+ Debug.printStackTrace(e);
+ r.setExtData(mCrlUpdateStatus, IRequest.RES_ERROR);
+ r.setExtData(mCrlUpdateError,
+ new EBaseException(
+ CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString())));
+ }
+ }
+ }
+ }
+ }
+}
+
+
+class CertRecProcessor implements IElementProcessor {
+ private Hashtable mCRLCerts = null;
+ private boolean mAllowExtensions = false;
+ private ILogger mLogger;
+ private CRLIssuingPoint mIP = null;
+
+ private boolean mIssuingDistPointAttempted = false;
+ private boolean mIssuingDistPointEnabled = false;
+ private BitArray mOnlySomeReasons = null;
+
+ public CertRecProcessor(Hashtable crlCerts, CRLIssuingPoint ip, ILogger logger, boolean allowExtensions) {
+ mCRLCerts = crlCerts;
+ mLogger = logger;
+ mIP = ip;
+ mAllowExtensions = allowExtensions;
+ mIssuingDistPointAttempted = false;
+ mIssuingDistPointEnabled = false;
+ mOnlySomeReasons = null;
+ }
+
+ private boolean initCRLIssuingDistPointExtension() {
+ boolean result = false;
+ CMSCRLExtensions exts = null;
+
+ if(mIssuingDistPointAttempted == true) {
+ if((mIssuingDistPointEnabled == true) && (mOnlySomeReasons != null )) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ mIssuingDistPointAttempted = true;
+ exts = (CMSCRLExtensions) mIP.getCRLExtensions();
+ if(exts == null) {
+ return result;
+ }
+ boolean isIssuingDistPointExtEnabled = false;
+ isIssuingDistPointExtEnabled = exts.isCRLExtensionEnabled(IssuingDistributionPointExtension.NAME);
+ if(isIssuingDistPointExtEnabled == false) {
+ mIssuingDistPointEnabled = false;
+ return false;
+ }
+
+ mIssuingDistPointEnabled = true;
+
+ //Get info out of the IssuingDistPointExtension
+ CRLExtensions ext = new CRLExtensions();
+ Vector extNames = exts.getCRLExtensionNames();
+ for (int i = 0; i < extNames.size(); i++) {
+ String extName = (String) extNames.elementAt(i);
+ if (extName.equals(IssuingDistributionPointExtension.NAME)) {
+ exts.addToCRLExtensions(ext, extName, null);
+ }
+ }
+ Extension issuingDistExt = null;
+ try {
+ issuingDistExt = ext.get(IssuingDistributionPointExtension.NAME);
+ } catch (Exception e) {
+ }
+
+ IssuingDistributionPointExtension iExt = null;
+ if(issuingDistExt != null)
+ iExt = (IssuingDistributionPointExtension) issuingDistExt;
+ IssuingDistributionPoint issuingDistributionPoint = null;
+ if(iExt != null)
+ issuingDistributionPoint = iExt.getIssuingDistributionPoint();
+
+ BitArray onlySomeReasons = null;
+
+ if(issuingDistributionPoint != null)
+ onlySomeReasons = issuingDistributionPoint.getOnlySomeReasons();
+
+ boolean applyReasonMatch = false;
+ boolean reasonMatch = true;
+
+ if(onlySomeReasons != null) {
+ applyReasonMatch = !onlySomeReasons.toString().equals("0000000");
+ CMS.debug("applyReasonMatch " + applyReasonMatch);
+ if(applyReasonMatch == true) {
+ mOnlySomeReasons = onlySomeReasons;
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ private boolean checkOnlySomeReasonsExtension(CRLExtensions entryExts)
+ {
+ boolean includeCert = true;
+ //This is exactly how the Pretty Print code obtains the reason code
+ //through the extensions
+ if(entryExts == null) {
+ return includeCert;
+ }
+
+ Extension crlReasonExt = null;
+ try {
+ crlReasonExt = entryExts.get(CRLReasonExtension.NAME);
+ } catch (Exception e) {
+ return includeCert;
+ }
+
+ RevocationReason reason = null;
+ int reasonIndex = 0;
+ if(crlReasonExt != null) {
+ try {
+ CRLReasonExtension theReason = (CRLReasonExtension) crlReasonExt;
+ reason = (RevocationReason) theReason.get("value");
+ reasonIndex = reason.toInt();
+ CMS.debug("revoked reason " + reason);
+ } catch (Exception e) {
+ return includeCert;
+ }
+ } else {
+ return includeCert;
+ }
+ boolean reasonMatch = false;
+ if(reason != null) {
+ if(mOnlySomeReasons != null) {
+ reasonMatch = mOnlySomeReasons.get(reasonIndex);
+ if(reasonMatch != true) {
+ includeCert = false;
+ } else {
+ CMS.debug("onlySomeReasons match! reason: " + reason);
+ }
+ }
+ }
+
+ return includeCert;
+ }
+
+ public boolean checkRevokedCertExtensions(CRLExtensions crlExtensions)
+ {
+ //For now just check the onlySomeReason CRL IssuingDistributionPoint extension
+
+ boolean includeCert = true;
+ if((crlExtensions == null) || (mAllowExtensions == false)) {
+ return includeCert;
+ }
+ boolean inited = initCRLIssuingDistPointExtension();
+
+ //If the CRLIssuingDistPointExtension is not available or
+ // if onlySomeReasons does not apply, bail.
+ if(inited == false) {
+ return includeCert;
+ }
+
+ //Check the onlySomeReasonsExtension
+ includeCert = checkOnlySomeReasonsExtension(crlExtensions);
+
+ return includeCert;
+ }
+
+ public void process(Object o) throws EBaseException {
+ try {
+ CertRecord certRecord = (CertRecord) o;
+
+ CRLExtensions entryExt = null, crlExts = null;
+ BigInteger serialNumber = certRecord.getSerialNumber();
+ Date revocationDate = certRecord.getRevocationDate();
+ IRevocationInfo revInfo = certRecord.getRevocationInfo();
+
+ if (revInfo != null) {
+ crlExts = revInfo.getCRLEntryExtensions();
+ entryExt = mIP.getRequiredEntryExtensions(crlExts);
+ }
+ RevokedCertificate newRevokedCert =
+ new RevokedCertImpl(serialNumber, revocationDate, entryExt);
+
+ boolean includeCert = checkRevokedCertExtensions(crlExts);
+
+ if (includeCert == true) {
+ mCRLCerts.put(serialNumber, (RevokedCertificate) newRevokedCert);
+ if (serialNumber != null) {
+ CMS.debug("Putting certificate serial: 0x"+serialNumber.toString(16)+" into CRL hashtable");
+ }
+ }
+ } catch (EBaseException e) {
+ CMS.debug(
+ "CA failed constructing CRL entry: " +
+ (mCRLCerts.size() + 1) + " " + e);
+ throw new ECAException(CMS.getUserMessage("CMS_CA_FAILED_CONSTRUCTING_CRL", e.toString()));
+ }
+ }
+}
+
diff --git a/pki/base/ca/src/com/netscape/ca/CRLWithExpiredCerts.java b/pki/base/ca/src/com/netscape/ca/CRLWithExpiredCerts.java
new file mode 100644
index 000000000..94de0d90b
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CRLWithExpiredCerts.java
@@ -0,0 +1,74 @@
+// --- 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.ca;
+
+
+import java.util.Enumeration;
+import java.util.Date;
+import java.math.*;
+
+import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.util.Debug;
+import com.netscape.cmscore.dbs.*;
+
+
+/**
+ * A CRL Issuing point that contains revoked certs, include onces that
+ * have expired.
+ */
+public class CRLWithExpiredCerts extends CRLIssuingPoint {
+
+ /**
+ * overrides getRevokedCerts in CRLIssuingPoint to include
+ * all revoked certs, including once that have expired.
+ *
+ * @param thisUpdate parameter is ignored.
+ *
+ * @exception EBaseException if an exception occured getting revoked
+ * certificates from the database.
+ */
+ public String getFilter() {
+ // PLEASE DONT CHANGE THE FILTER. It is indexed.
+ // Changing it will degrade performance. See
+ // also com.netscape.certsetup.LDAPUtil.java
+ String filter =
+ "(|(" + CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_REVOKED + ")" +
+ "(" + CertRecord.ATTR_CERT_STATUS + "=" +
+ CertRecord.STATUS_REVOKED_EXPIRED + "))";
+
+ // check if any ranges specified.
+ if (mBeginSerial != null)
+ filter += "(" + CertRecord.ATTR_ID + ">=" + mBeginSerial.toString() + ")";
+ if (mEndSerial != null)
+ filter += "(" + CertRecord.ATTR_ID + "<=" + mEndSerial.toString() + ")";
+ // get all revoked non-expired certs.
+ if (mEndSerial != null || mBeginSerial != null) {
+ filter = "(&" + filter + ")";
+ }
+ return filter;
+ }
+
+ /**
+ * registers expired certificates
+ */
+ public void addExpiredCert(BigInteger serialNumber) {
+ // don't do anything
+ }
+}
diff --git a/pki/base/ca/src/com/netscape/ca/CertificateAuthority.java b/pki/base/ca/src/com/netscape/ca/CertificateAuthority.java
new file mode 100644
index 000000000..49e88a5bb
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -0,0 +1,1968 @@
+// --- 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.ca;
+
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.math.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.CRLException;
+import java.security.cert.X509Certificate;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import org.mozilla.jss.asn1.*;
+import org.mozilla.jss.pkix.primitive.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.util.*;
+import com.netscape.certsrv.listeners.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.dbs.*;
+import com.netscape.certsrv.dbs.repository.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.certsrv.dbs.certdb.*;
+import com.netscape.certsrv.dbs.replicadb.*;
+import com.netscape.certsrv.dbs.crldb.*;
+import com.netscape.certsrv.dbs.crldb.ICRLRepository;
+import com.netscape.certsrv.apps.*;
+
+import org.mozilla.jss.pkix.cert.Extension;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import com.netscape.certsrv.ldap.*;
+import com.netscape.certsrv.publish.*;
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.policy.*;
+
+import com.netscape.certsrv.ocsp.*;
+import com.netscape.cmscore.policy.*;
+import com.netscape.cmscore.request.*;
+import com.netscape.cmscore.dbs.*;
+import com.netscape.cmscore.ldap.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.security.*;
+import com.netscape.cmsutil.ocsp.*;
+
+import com.netscape.certsrv.listeners.*;
+import com.netscape.cmscore.listeners.*;
+
+
+/**
+ * A class represents a Certificate Authority that is
+ * responsible for certificate specific operations.
+ * <P>
+ *
+ * @author lhsiao
+ * @version $Revision$, $Date$
+ */
+public class CertificateAuthority implements ICertificateAuthority, ICertAuthority, IOCSPService {
+ public static final String OFFICIAL_NAME = "Certificate Manager";
+
+ public final static OBJECT_IDENTIFIER OCSP_NONCE = new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.48.1.2");
+
+ protected ISubsystem mOwner = null;
+ protected IConfigStore mConfig = null;
+ protected ILogger mLogger = CMS.getLogger();
+ protected Hashtable mCRLIssuePoints = new Hashtable();
+ protected CRLIssuingPoint mMasterCRLIssuePoint = null; // the complete crl.
+ protected SigningUnit mSigningUnit;
+ protected SigningUnit mOCSPSigningUnit;
+ protected SigningUnit mCRLSigningUnit;
+
+ protected X500Name mName = null;
+ protected X500Name mCRLName = null;
+ protected X500Name mOCSPName = null;
+ protected String mNickname = null; // nickname of CA signing cert.
+ protected String mOCSPNickname = null; // nickname of OCSP signing cert.
+ protected long mCertSerialNumberCounter = System.currentTimeMillis();
+ protected long mRequestID = System.currentTimeMillis();
+
+ protected String[] mAllowedSignAlgors = null;
+
+ protected CertificateRepository mCertRepot = null;
+ protected CRLRepository mCRLRepot = null;
+ protected ReplicaIDRepository mReplicaRepot = null;
+
+ protected CertificateChain mCACertChain = null;
+ protected CertificateChain mOCSPCertChain = null;
+ protected X509CertImpl mCRLCert = null;
+ protected org.mozilla.jss.crypto.X509Certificate mCRLX509Cert = null;
+ protected X509CertImpl mCaCert = null;
+ protected org.mozilla.jss.crypto.X509Certificate mCaX509Cert = null;
+ protected X509CertImpl mOCSPCert = null;
+ protected org.mozilla.jss.crypto.X509Certificate mOCSPX509Cert = null;
+ protected String[] mCASigningAlgorithms = null;
+
+ protected PublisherProcessor mPublisherProcessor = null;
+ protected IRequestQueue mRequestQueue = null;
+ protected CAPolicy mPolicy = null;
+ protected CAService mService = null;
+ protected IRequestNotifier mNotify = null;
+ protected IRequestNotifier mPNotify = null;
+ protected long mNumOCSPRequest = 0;
+ protected long mTotalTime = 0;
+ protected long mTotalData = 0;
+ protected long mSignTime = 0;
+ protected long mLookupTime = 0;
+
+ protected static final int FASTSIGNING_DISABLED = 0;
+ protected static final int FASTSIGNING_ENABLED = 1;
+
+ protected CertificateVersion mDefaultCertVersion;
+ protected long mDefaultValidity;
+ protected boolean mEnablePastCATime;
+ protected boolean mEnableOCSP;
+ protected int mFastSigning = FASTSIGNING_DISABLED;
+
+ protected static final long SECOND = 1000; // 1000 milliseconds
+ protected static final long MINUTE = 60 * SECOND;
+ protected static final long HOUR = 60 * MINUTE;
+ protected static final long DAY = 24 * HOUR;
+ protected static final long YEAR = DAY * 365;
+
+ protected static final String PROP_CERT_REPOS_DN = "CertificateRepositoryDN";
+ protected static final String PROP_REPOS_DN = "RepositoryDN";
+ protected static final String PROP_REPLICAID_DN = "dbs.replicadn";
+
+ // for the notification listeners
+
+ /**
+ * Package constants
+ */
+
+ public IRequestListener mCertIssuedListener = null;
+ public IRequestListener mCertRevokedListener = null;
+ public IRequestListener mReqInQListener = null;
+
+ /* cache responder ID for performance */
+ private ResponderID mResponderIDByName = null;
+ private ResponderID mResponderIDByHash = null;
+
+ protected Hashtable mListenerPlugins = null;
+
+ /**
+ * Internal constants
+ */
+
+ protected ICRLPublisher mCRLPublisher = null;
+ private String mId = null;
+
+ private boolean mByName = true;
+
+ private boolean mUseNonces = true;
+ private int mMaxNonces = 100;
+ private Nonces mNonces = null;
+
+ /**
+ * Constructs a CA subsystem.
+ */
+ public CertificateAuthority() {
+ }
+
+ /**
+ * Retrieves subsystem identifier.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ public CertificateVersion getDefaultCertVersion() {
+ return mDefaultCertVersion;
+ }
+
+ public boolean isEnablePastCATime() {
+ return mEnablePastCATime;
+ }
+
+ /**
+ * Sets subsystem identifier.
+ */
+ public void setId(String id) throws EBaseException {
+ mId = id;
+ }
+
+ /**
+ * updates the Master CRL now
+ */
+ public void updateCRLNow() throws EBaseException {
+ if (mMasterCRLIssuePoint != null) {
+ mMasterCRLIssuePoint.updateCRLNow();
+ }
+ }
+
+
+ public void publishCRLNow() throws EBaseException {
+ if (mMasterCRLIssuePoint != null) {
+ mMasterCRLIssuePoint.publishCRL();
+ }
+ }
+ public ICRLPublisher getCRLPublisher() {
+ return mCRLPublisher;
+ }
+
+ public IPolicyProcessor getPolicyProcessor() {
+ return mPolicy.getPolicyProcessor();
+ }
+
+ public boolean noncesEnabled() {
+ return mUseNonces;
+ }
+
+ public Nonces getNonces() {
+ return mNonces;
+ }
+
+ /**
+ * Initializes this CA subsystem.
+ * <P>
+ *
+ * @param owner owner of this subsystem
+ * @param config configuration of this subsystem
+ * @exception EBaseException failed to initialize this CA
+ */
+ public void init(ISubsystem owner, IConfigStore config) throws
+ EBaseException {
+
+ try {
+ CMS.debug("CertificateAuthority init ");
+ mOwner = owner;
+ mConfig = config;
+
+ // init cert & crl database.
+ initCaDatabases();
+
+ // init signing unit & CA cert.
+ try {
+ initSigUnit();
+ // init default CA attributes like cert version, validity.
+ initDefCaAttrs();
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ ;
+ else
+ throw e;
+ }
+
+ // init web gateway.
+ initWebGateway();
+
+ mUseNonces = mConfig.getBoolean("enableNonces", true);
+ mMaxNonces = mConfig.getInteger("maxNumberOfNonces", 100);
+ if (mUseNonces) {
+ mNonces = new Nonces(mMaxNonces);
+ CMS.debug("CertificateAuthority init: Nonces enabled. ("+mNonces.size()+")");
+ }
+
+ // init request queue and related modules.
+ CMS.debug("CertificateAuthority init: initRequestQueue");
+ initRequestQueue();
+ if (CMS.isPreOpMode())
+ return;
+
+ // set certificate status to 10 minutes
+ mCertRepot.setCertStatusUpdateInterval(
+ mRequestQueue.getRequestRepository(),
+ mConfig.getInteger("certStatusUpdateInterval", 10 * 60),
+ mConfig.getBoolean("listenToCloneModifications", false));
+ mCertRepot.setConsistencyCheck(
+ mConfig.getBoolean("ConsistencyCheck", false));
+ mCertRepot.setSkipIfInConsistent(
+ mConfig.getBoolean("SkipIfInConsistent", false));
+
+ mService.init(config.getSubStore("connector"));
+
+ initMiscellaneousListeners();
+
+ // instantiate CRL publisher
+ IConfigStore cpStore = null;
+
+ mByName = config.getBoolean("byName", true);
+
+ cpStore = config.getSubStore("crlPublisher");
+ if (cpStore != null && cpStore.size() > 0) {
+ String publisherClass = cpStore.getString("class");
+
+ if (publisherClass != null) {
+ try {
+ Class pc = Class.forName(publisherClass);
+
+ mCRLPublisher = (ICRLPublisher)
+ pc.newInstance();
+ mCRLPublisher.init(this, cpStore);
+ } catch (ClassNotFoundException ee) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_PUBLISHER", ee.toString()));
+ } catch (IllegalAccessException ee) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_PUBLISHER", ee.toString()));
+ } catch (InstantiationException ee) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_PUBLISHER", ee.toString()));
+ }
+ }
+ }
+
+ // initialize publisher processor (publish remote admin
+ // rely on this subsystem, so it has to be initialized)
+ initPublish();
+
+ // Initialize CRL issuing points.
+ // note CRL framework depends on DBS, CRYPTO and PUBLISHING
+ // being functional.
+ initCRL();
+
+ } catch (EBaseException e) {
+ if (CMS.isPreOpMode())
+ return;
+ else
+ throw e;
+ }
+ }
+
+ /**
+ * return CA's request queue processor
+ */
+ public IRequestQueue getRequestQueue() {
+ return mRequestQueue;
+ }
+
+ /**
+ * registers listener
+ */
+ public void registerRequestListener(IRequestListener listener) {
+ mNotify.registerListener(listener);
+ }
+
+ /**
+ * registers listener with a name.
+ */
+ public void registerRequestListener(String name, IRequestListener listener) {
+ mNotify.registerListener(name, listener);
+ }
+
+ /**
+ * removes listener
+ */
+ public void removeRequestListener(IRequestListener listener) {
+ mNotify.removeListener(listener);
+ }
+
+ /**
+ * removes listener with a name.
+ */
+ public void removeRequestListener(String name) {
+ mNotify.removeListener(name);
+ }
+
+ /**
+ * register listener for pending requests
+ */
+ public void registerPendingListener(IRequestListener listener) {
+ mPNotify.registerListener(listener);
+ }
+
+ /**
+ * register listener for pending requests with a name.
+ */
+ public void registerPendingListener(String name, IRequestListener listener) {
+ mPNotify.registerListener(name, listener);
+ }
+
+ /**
+ * get listener from listener list
+ */
+ public IRequestListener getRequestListener(String name) {
+ return mNotify.getListener(name);
+ }
+
+ /**
+ * get notifiers registered by CA
+ */
+ public IRequestNotifier getRequestNotifier() {
+ return mNotify;
+ }
+
+ /**
+ * get listener from listener list
+ */
+ public IRequestListener getPendingListener(String name) {
+ return mPNotify.getListener(name);
+ }
+
+ public Enumeration getRequestListenerNames() {
+ return mNotify.getListenerNames();
+ }
+
+ public IRequestListener getRequestInQListener() {
+ return mReqInQListener;
+ }
+
+ public IRequestListener getCertIssuedListener() {
+ return mCertIssuedListener;
+ }
+
+ public IRequestListener getCertRevokedListener() {
+ return mCertRevokedListener;
+ }
+
+ /**
+ * return CA's policy processor.
+ */
+ public IPolicy getCAPolicy() {
+ return mPolicy;
+ }
+
+ /**
+ * return CA's request queue service object.
+ */
+ public IService getCAService() {
+ return mService;
+ }
+
+ /**
+ * check if the ca is a clone.
+ */
+ public boolean isClone() {
+ if (mService.mCLAConnector != null)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Starts up this subsystem.
+ */
+ public void startup() throws EBaseException {
+ if (CMS.isPreOpMode()) {
+ return;
+ }
+ mService.startup();
+ mRequestQueue.recover();
+
+ // Note that this could be null.
+
+ // setup Admin operations
+
+ initNotificationListeners();
+
+ startPublish();
+ // startCRL();
+ }
+
+ /**
+ * Shutdowns this subsystem.
+ * <P>
+ */
+ public void shutdown() {
+ Enumeration enums = mCRLIssuePoints.elements();
+ while (enums.hasMoreElements()) {
+ CRLIssuingPoint point = (CRLIssuingPoint)enums.nextElement();
+ point.shutdown();
+ }
+
+ if (mMasterCRLIssuePoint != null) {
+ mMasterCRLIssuePoint.shutdown();
+ }
+
+ mSigningUnit = null;
+ mOCSPSigningUnit = null;
+ mCRLSigningUnit = null;
+ if (mCertRepot != null) {
+ mCertRepot.shutdown();
+ mCertRepot = null;
+ }
+ mCRLRepot = null;
+ mPublisherProcessor.shutdown();
+ }
+
+ /**
+ * Retrieves the configuration store of this subsystem.
+ * <P>
+ */
+ public IConfigStore getConfigStore() {
+ return mConfig;
+ }
+
+ /**
+ * Retrieves logger.
+ */
+ public ILogger getLogger() {
+ return CMS.getLogger();
+ }
+
+ /**
+ * Retrieves database services.
+ */
+ public IDBSubsystem getDBSubsystem() {
+ return DBSubsystem.getInstance();
+ }
+
+ public void setValidity(String enableCAPast) throws EBaseException {
+ if (enableCAPast.equals("true"))
+ mEnablePastCATime = true;
+ else
+ mEnablePastCATime = false;
+ mConfig.putString(PROP_ENABLE_PAST_CATIME, enableCAPast);
+ }
+
+ public long getDefaultValidity() {
+ return mDefaultValidity;
+ }
+
+ public SignatureAlgorithm getDefaultSignatureAlgorithm() {
+ return mSigningUnit.getDefaultSignatureAlgorithm();
+ }
+
+ public String getDefaultAlgorithm() {
+ return mSigningUnit.getDefaultAlgorithm();
+ }
+
+ public void setDefaultAlgorithm(String algorithm) throws EBaseException {
+ mSigningUnit.setDefaultAlgorithm(algorithm);
+ }
+
+ public String getStartSerial() {
+ try {
+ BigInteger serial =
+ ((Repository) mCertRepot).getTheSerialNumber();
+
+ if (serial == null)
+ return "";
+ else
+ return serial.toString(16);
+ } catch (EBaseException e) {
+ // shouldn't get here.
+ return "";
+ }
+ }
+
+ public void setStartSerial(String serial) throws EBaseException {
+ ((Repository) mCertRepot).setTheSerialNumber(new BigInteger(serial));
+ }
+
+ public String getMaxSerial() {
+ String serial = ((Repository) mCertRepot).getMaxSerial();
+
+ if (serial != null)
+ return serial;
+ else
+ return "";
+ }
+
+ public void setMaxSerial(String serial) throws EBaseException {
+ ((Repository) mCertRepot).setMaxSerial(serial);
+ }
+
+ /**
+ * Retrieves certificate repository.
+ * <P>
+ *
+ * @return certificate repository
+ */
+ public ICertificateRepository getCertificateRepository() {
+ return mCertRepot;
+ }
+
+ /**
+ * Retrieves replica repository.
+ * <P>
+ *
+ * @return replica repository
+ */
+ public IReplicaIDRepository getReplicaRepository() {
+ return mReplicaRepot;
+ }
+
+
+ /**
+ * Retrieves CRL repository.
+ */
+ public ICRLRepository getCRLRepository() {
+ return mCRLRepot;
+ }
+
+ public IPublisherProcessor getPublisherProcessor() {
+ return mPublisherProcessor;
+ }
+
+ /**
+ * Retrieves the CRL issuing point by id.
+ * <P>
+ * @param id string id of the CRL issuing point
+ * @return CRL issuing point
+ */
+ public ICRLIssuingPoint getCRLIssuingPoint(String id) {
+ return (CRLIssuingPoint) mCRLIssuePoints.get(id);
+ }
+
+ /**
+ * Enumerates CRL issuing points
+ * <P>
+ * @return security service
+ */
+ public Enumeration getCRLIssuingPoints() {
+ return mCRLIssuePoints.elements();
+ }
+
+ public int getCRLIssuingPointsSize() {
+ return mCRLIssuePoints.size();
+ }
+
+ /**
+ * Adds CRL issuing point with the given identifier and description.
+ */
+ public boolean addCRLIssuingPoint(IConfigStore crlSubStore, String id,
+ boolean enable, String description) {
+ crlSubStore.makeSubStore(id);
+ IConfigStore c = crlSubStore.getSubStore(id);
+
+ if (c != null) {
+ c.putString("allowExtensions", "true");
+ c.putString("alwaysUpdate", "false");
+ c.putString("autoUpdateInterval", "240");
+ c.putString("caCertsOnly", "false");
+ c.putString("cacheUpdateInterval", "15");
+ c.putString("class", "com.netscape.ca.CRLIssuingPoint");
+ c.putString("dailyUpdates", "3:45");
+ c.putString("description", description);
+ c.putBoolean("enable", enable);
+ c.putString("enableCRLCache", "true");
+ c.putString("enableCRLUpdates", "true");
+ c.putString("enableCacheTesting", "false");
+ c.putString("enableCacheRecovery", "true");
+ c.putString("enableDailyUpdates", "false");
+ c.putString("enableUpdateInterval", "true");
+ c.putString("extendedNextUpdate", "true");
+ c.putString("includeExpiredCerts", "false");
+ c.putString("minUpdateInterval", "0");
+ c.putString("nextUpdateGracePeriod", "0");
+ c.putString("publishOnStart", "false");
+ c.putString("saveMemory", "false");
+ c.putString("signingAlgorithm", "SHA256withRSA");
+ c.putString("updateSchema", "1");
+
+ // crl extensions
+ // AuthorityInformationAccess
+ c.putString("extension.AuthorityInformationAccess.enable", "false");
+ c.putString("extension.AuthorityInformationAccess.critical", "false");
+ c.putString("extension.AuthorityInformationAccess.type", "CRLExtension");
+ c.putString("extension.AuthorityInformationAccess.class",
+ "com.netscape.cms.crl.CMSAuthInfoAccessExtension");
+ c.putString("extension.AuthorityInformationAccess.numberOfAccessDescriptions", "1");
+ c.putString("extension.AuthorityInformationAccess.accessMethod0", "caIssuers");
+ c.putString("extension.AuthorityInformationAccess.accessLocationType0", "URI");
+ c.putString("extension.AuthorityInformationAccess.accessLocation0", "");
+ // AuthorityKeyIdentifier
+ c.putString("extension.AuthorityKeyIdentifier.enable", "false");
+ c.putString("extension.AuthorityKeyIdentifier.critical", "false");
+ c.putString("extension.AuthorityKeyIdentifier.type", "CRLExtension");
+ c.putString("extension.AuthorityKeyIdentifier.class",
+ "com.netscape.cms.crl.CMSAuthorityKeyIdentifierExtension");
+ // IssuerAlternativeName
+ c.putString("extension.IssuerAlternativeName.enable", "false");
+ c.putString("extension.IssuerAlternativeName.critical", "false");
+ c.putString("extension.IssuerAlternativeName.type", "CRLExtension");
+ c.putString("extension.IssuerAlternativeName.class",
+ "com.netscape.cms.crl.CMSIssuerAlternativeNameExtension");
+ c.putString("extension.IssuerAlternativeName.numNames", "0");
+ c.putString("extension.IssuerAlternativeName.nameType0", "");
+ c.putString("extension.IssuerAlternativeName.name0", "");
+ // CRLNumber
+ c.putString("extension.CRLNumber.enable", "true");
+ c.putString("extension.CRLNumber.critical", "false");
+ c.putString("extension.CRLNumber.type", "CRLExtension");
+ c.putString("extension.CRLNumber.class",
+ "com.netscape.cms.crl.CMSCRLNumberExtension");
+ // DeltaCRLIndicator
+ c.putString("extension.DeltaCRLIndicator.enable", "false");
+ c.putString("extension.DeltaCRLIndicator.critical", "true");
+ c.putString("extension.DeltaCRLIndicator.type", "CRLExtension");
+ c.putString("extension.DeltaCRLIndicator.class",
+ "com.netscape.cms.crl.CMSDeltaCRLIndicatorExtension");
+ // IssuingDistributionPoint
+ c.putString("extension.IssuingDistributionPoint.enable", "false");
+ c.putString("extension.IssuingDistributionPoint.critical", "true");
+ c.putString("extension.IssuingDistributionPoint.type", "CRLExtension");
+ c.putString("extension.IssuingDistributionPoint.class",
+ "com.netscape.cms.crl.CMSIssuingDistributionPointExtension");
+ c.putString("extension.IssuingDistributionPoint.pointType", "");
+ c.putString("extension.IssuingDistributionPoint.pointName", "");
+ c.putString("extension.IssuingDistributionPoint.onlyContainsUserCerts", "false");
+ c.putString("extension.IssuingDistributionPoint.onlyContainsCACerts", "false");
+ c.putString("extension.IssuingDistributionPoint.onlySomeReasons", "");
+ //"keyCompromise,cACompromise,affiliationChanged,superseded,cessationOfOperation,certificateHold");
+ c.putString("extension.IssuingDistributionPoint.indirectCRL", "false");
+ // CRLReason
+ c.putString("extension.CRLReason.enable", "true");
+ c.putString("extension.CRLReason.critical", "false");
+ c.putString("extension.CRLReason.type", "CRLEntryExtension");
+ c.putString("extension.CRLReason.class",
+ "com.netscape.cms.crl.CMSCRLReasonExtension");
+ // HoldInstruction - removed by RFC 5280
+ // c.putString("extension.HoldInstruction.enable", "false");
+ // c.putString("extension.HoldInstruction.critical", "false");
+ // c.putString("extension.HoldInstruction.type", "CRLEntryExtension");
+ // c.putString("extension.HoldInstruction.class",
+ // "com.netscape.cms.crl.CMSHoldInstructionExtension");
+ // c.putString("extension.HoldInstruction.instruction", "none");
+ // InvalidityDate
+ c.putString("extension.InvalidityDate.enable", "true");
+ c.putString("extension.InvalidityDate.critical", "false");
+ c.putString("extension.InvalidityDate.type", "CRLEntryExtension");
+ c.putString("extension.InvalidityDate.class",
+ "com.netscape.cms.crl.CMSInvalidityDateExtension");
+ // CertificateIssuer
+ /*
+ c.putString("extension.CertificateIssuer.enable", "false");
+ c.putString("extension.CertificateIssuer.critical", "true");
+ c.putString("extension.CertificateIssuer.type", "CRLEntryExtension");
+ c.putString("extension.CertificateIssuer.class",
+ "com.netscape.cms.crl.CMSCertificateIssuerExtension");
+ c.putString("extension.CertificateIssuer.numNames", "0");
+ c.putString("extension.CertificateIssuer.nameType0", "");
+ c.putString("extension.CertificateIssuer.name0", "");
+ */
+ // FreshestCRL
+ c.putString("extension.FreshestCRL.enable", "false");
+ c.putString("extension.FreshestCRL.critical", "false");
+ c.putString("extension.FreshestCRL.type", "CRLExtension");
+ c.putString("extension.FreshestCRL.class",
+ "com.netscape.cms.crl.CMSFreshestCRLExtension");
+ c.putString("extension.FreshestCRL.numPoints", "0");
+ c.putString("extension.FreshestCRL.pointType0", "");
+ c.putString("extension.FreshestCRL.pointName0", "");
+
+ String issuingPointClassName = null;
+ Class issuingPointClass = null;
+ CRLIssuingPoint issuingPoint = null;
+
+ try {
+ issuingPointClassName = c.getString(PROP_CLASS);
+ issuingPointClass = Class.forName(issuingPointClassName);
+ issuingPoint = (CRLIssuingPoint) issuingPointClass.newInstance();
+ issuingPoint.init(this, id, c);
+ mCRLIssuePoints.put(id, issuingPoint);
+ } catch (EPropertyNotFound e) {
+ crlSubStore.removeSubStore(id);
+ return false;
+ } catch (EBaseException e) {
+ crlSubStore.removeSubStore(id);
+ return false;
+ } catch (ClassNotFoundException e) {
+ crlSubStore.removeSubStore(id);
+ return false;
+ } catch (InstantiationException e) {
+ crlSubStore.removeSubStore(id);
+ return false;
+ } catch (IllegalAccessException e) {
+ crlSubStore.removeSubStore(id);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Deletes CRL issuing point with the given identifier.
+ */
+ public void deleteCRLIssuingPoint(IConfigStore crlSubStore, String id) {
+ CRLIssuingPoint ip = (CRLIssuingPoint) mCRLIssuePoints.get(id);
+
+ if (ip != null) {
+ ip.shutdown();
+ mCRLIssuePoints.remove(id);
+ ip = null;
+ crlSubStore.removeSubStore(id);
+ try {
+ mCRLRepot.deleteCRLIssuingPointRecord(id);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("FAILED_REMOVING_CRL_IP_2", id, e.toString()));
+ }
+ }
+ }
+
+ /**
+ * Returns X500 name of the Certificate Authority
+ * <P>
+ *
+ * @return CA name
+ */
+ public X500Name getX500Name() {
+ return mName;
+ }
+
+ public X500Name getCRLX500Name() {
+ return mCRLName;
+ }
+
+ public X500Name getOCSPX500Name() {
+ return mOCSPName;
+ }
+
+ /**
+ * Returns nickname of CA's signing cert.
+ * <p>
+ * @return CA signing cert nickname.
+ */
+ public String getNickname() {
+ return mNickname;
+ }
+
+ /**
+ * Returns nickname of OCSP's signing cert.
+ * <p>
+ * @return OCSP signing cert nickname.
+ */
+ public String getOCSPNickname() {
+ return mOCSPNickname;
+ }
+
+ /**
+ * Returns default signing unit used by this CA
+ * <P>
+ *
+ * @return request identifier
+ */
+ public ISigningUnit getSigningUnit() {
+ return mSigningUnit;
+ }
+
+ public ISigningUnit getCRLSigningUnit() {
+ return mCRLSigningUnit;
+ }
+
+ public ISigningUnit getOCSPSigningUnit() {
+ return mOCSPSigningUnit;
+ }
+
+ public void setBasicConstraintMaxLen(int num) {
+ mConfig.putString("Policy.rule.BasicConstraintsExt.maxPathLen", "" + num);
+ }
+
+ /**
+ * Signs CRL using the specified signature algorithm.
+ * If no algorithm is specified the CA's default signing algorithm
+ * is used.
+ * <P>
+ * @param crl the CRL to be signed.
+ * @param algname the algorithm name to use. This is a JCA name such
+ * as MD5withRSA, etc. If set to null the default signing algorithm
+ * is used.
+ *
+ * @return the signed CRL
+ */
+ public X509CRLImpl sign(X509CRLImpl crl, String algname)
+ throws EBaseException {
+ X509CRLImpl signedcrl = null;
+
+ IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("signing");
+ }
+
+ long startTime = CMS.getCurrentDate().getTime();
+ try {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream tmp = new DerOutputStream();
+
+ if (algname == null) {
+ algname = mSigningUnit.getDefaultAlgorithm();
+ }
+
+ crl.encodeInfo(tmp);
+ AlgorithmId.get(algname).encode(tmp);
+
+ byte[] tbsCertList = crl.getTBSCertList();
+
+ byte[] signature = mCRLSigningUnit.sign(tbsCertList, algname);
+
+ if (crl.setSignature(signature)) {
+ tmp.putBitString(signature);
+ out.write(DerValue.tag_Sequence, tmp);
+
+ if (crl.setSignedCRL(out.toByteArray())) {
+ signedcrl = crl;
+ // signedcrl = new X509CRLImpl(out.toByteArray());
+ } else {
+ CMS.debug("Failed to add signed-CRL to CRL object.");
+ }
+ } else {
+ CMS.debug("Failed to add signature to CRL object.");
+ }
+ } catch (CRLException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CRL", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CRL_FAILED", e.getMessage()));
+ } catch (X509ExtensionException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CRL", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CRL_FAILED", e.getMessage()));
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CRL", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CRL_FAILED", e.getMessage()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CRL", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CRL_FAILED", e.getMessage()));
+ } finally {
+ if (statsSub != null) {
+ statsSub.endTiming("signing");
+ }
+ }
+
+ return signedcrl;
+ }
+
+ /**
+ * Signs the given certificate info using specified signing algorithm
+ * If no algorithm is specified the CA's default algorithm is used.
+ * <P>
+ * @param certInfo the certificate info to be signed.
+ * @param algname the signing algorithm to use. These are names defined
+ * in JCA, such as MD5withRSA, etc. If null the CA's default
+ * signing algorithm will be used.
+ * @return signed certificate
+ */
+ public X509CertImpl sign(X509CertInfo certInfo, String algname)
+ throws EBaseException {
+
+ X509CertImpl signedcert = null;
+
+ IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats");
+ if (statsSub != null) {
+ statsSub.startTiming("signing");
+ }
+
+ long startTime = CMS.getCurrentDate().getTime();
+ try {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream tmp = new DerOutputStream();
+
+ if (certInfo == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_CERTINFO"));
+ return null;
+ }
+
+ if (algname == null) {
+ algname = mSigningUnit.getDefaultAlgorithm();
+ }
+
+ CMS.debug("sign cert get algorithm");
+ AlgorithmId alg = AlgorithmId.get(algname);
+
+ // encode certificate info
+ CMS.debug("sign cert encoding cert");
+ certInfo.encode(tmp);
+ byte[] rawCert = tmp.toByteArray();
+
+ // encode algorithm identifier
+ CMS.debug("sign cert encoding algorithm");
+ alg.encode(tmp);
+
+ CMS.debug("CA cert signing: signing cert");
+ byte[] signature = mSigningUnit.sign(rawCert, algname);
+
+ tmp.putBitString(signature);
+
+ // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
+ out.write(DerValue.tag_Sequence, tmp);
+ //log(ILogger.LL_INFO, "CertificateAuthority: done signing");
+
+ switch (mFastSigning) {
+ case FASTSIGNING_DISABLED:
+ signedcert = new X509CertImpl(out.toByteArray());
+ break;
+
+ case FASTSIGNING_ENABLED:
+ signedcert = new X509CertImpl(out.toByteArray(), certInfo);
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CERT", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CERT_FAILED", e.getMessage()));
+ } catch (IOException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CERT", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CERT_FAILED", e.getMessage()));
+ } catch (CertificateException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_SIGN_CERT", e.toString(), e.getMessage()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_CERT_FAILED", e.getMessage()));
+ } finally {
+ if (statsSub != null) {
+ statsSub.endTiming("signing");
+ }
+ }
+ return signedcert;
+ }
+
+ /**
+ * Sign a byte array using the specified algorithm.
+ * If algorithm is null the CA's default algorithm is used.
+ * <p>
+ * @param data the data to be signed in a byte array.
+ * @param algname the algorithm to use.
+ * @return the signature in a byte array.
+ */
+ public byte[] sign(byte[] data, String algname)
+ throws EBaseException {
+ return mSigningUnit.sign(data, algname);
+ }
+
+ /**
+ * logs a message in the CA area.
+ * @param level the debug level.
+ * @param msg the message to debug.
+ */
+ public void log(int level, String msg) {
+ mLogger.log(ILogger.EV_SYSTEM, ILogger.S_CA,
+ level, msg);
+ }
+
+ /**
+ * Retrieves certificate chains of this CA.
+ * @return this CA's cert chain.
+ */
+ public CertificateChain getCACertChain() {
+ return mCACertChain;
+ }
+
+ public X509CertImpl getCACert() {
+ if (mCaCert != null) {
+ return mCaCert;
+ }
+ // during configuration
+ try {
+ String cert = mConfig.getString("signing.cert", null);
+ if (cert != null) {
+ return new X509CertImpl(CMS.AtoB(cert));
+ }
+ } catch (EBaseException e) {
+ CMS.debug(e);
+ } catch (CertificateException e) {
+ CMS.debug(e);
+ }
+ return null;
+ }
+
+ public org.mozilla.jss.crypto.X509Certificate getCaX509Cert() {
+ return mCaX509Cert;
+ }
+
+ public String[] getCASigningAlgorithms() {
+ if (mCASigningAlgorithms != null)
+ return mCASigningAlgorithms;
+
+ if (mCaCert == null)
+ return null; // CA not inited yet.
+ X509Key caPubKey = null;
+
+ try {
+ caPubKey = (X509Key) mCaCert.get(X509CertImpl.PUBLIC_KEY);
+ } catch (CertificateParsingException e) {
+ }
+ if (caPubKey == null)
+ return null; // something seriously wrong.
+ AlgorithmId alg = caPubKey.getAlgorithmId();
+
+ if (alg == null)
+ return null; // something seriously wrong.
+ mCASigningAlgorithms = AlgorithmId.getSigningAlgorithms(alg);
+ if (mCASigningAlgorithms == null) {
+ CMS.debug(
+ "CA - no signing algorithms for " + alg.getName());
+ } else {
+ CMS.debug(
+ "CA First signing algorithm is " + mCASigningAlgorithms[0]);
+ }
+
+ return mCASigningAlgorithms;
+ }
+
+ //////////
+ // Initialization routines.
+ //
+
+
+ /**
+ * init CA signing unit & cert chain.
+ */
+ private void initSigUnit()
+ throws EBaseException {
+ try {
+ // init signing unit
+ mSigningUnit = new SigningUnit();
+ IConfigStore caSigningCfg =
+ mConfig.getSubStore(PROP_SIGNING_SUBSTORE);
+
+ mSigningUnit.init(this, caSigningCfg);
+ CMS.debug("CA signing unit inited");
+
+ // for identrus
+ IConfigStore CrlStore = mConfig.getSubStore(PROP_CRL_SIGNING_SUBSTORE);
+
+ if (CrlStore != null && CrlStore.size() > 0) {
+ mCRLSigningUnit = new SigningUnit();
+ mCRLSigningUnit.init(this, mConfig.getSubStore(PROP_CRL_SIGNING_SUBSTORE));
+ } else {
+ mCRLSigningUnit = mSigningUnit;
+ }
+
+ // init cert chain
+ CryptoManager manager = CryptoManager.getInstance();
+
+ int caChainNum =
+ caSigningCfg.getInteger(PROP_CA_CHAIN_NUM, 0);
+
+ CMS.debug("cachainNum= " + caChainNum);
+ if (caChainNum > 0) {
+ // custom build chain (for cross cert chain)
+ // audit here ***
+ IConfigStore chainStore =
+ caSigningCfg.getSubStore(PROP_CA_CHAIN);
+
+ if (chainStore == null) {
+ log(ILogger.LL_FAILURE,
+ CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN",
+ "ca cert chain config error"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED",
+ "ca cert chain config error"));
+ }
+
+ java.security.cert.X509Certificate[] implchain =
+ new java.security.cert.X509Certificate[caChainNum];
+
+ for (int i = 0; i < caChainNum; i++) {
+ String subtreeName = PROP_CA_CERT + i;
+ // cert file name must be full path
+ String certFileName =
+ chainStore.getString(subtreeName, null);
+
+ if ((certFileName == null) || certFileName.equals("")) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN", "cert file config error"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED",
+ "cert file config error"));
+ }
+ byte[] b64Bytes = getCertFromFile(certFileName);
+ String b64String = new String(b64Bytes);
+ byte[] certBytes = KeyCertUtil.convertB64EToByteArray(b64String);
+
+ implchain[i] = new X509CertImpl(certBytes);
+ } // for
+
+ mCACertChain = new CertificateChain(implchain);
+ CMS.debug("in init - custom built CA cert chain.");
+ } else {
+ // build ca chain the traditional way
+ org.mozilla.jss.crypto.X509Certificate[] chain =
+ manager.buildCertificateChain(mSigningUnit.getCert());
+ // do this in case other subsyss expect a X509CertImpl
+ java.security.cert.X509Certificate[] implchain =
+ new java.security.cert.X509Certificate[chain.length];
+
+ for (int i = 0; i < chain.length; i++) {
+ implchain[i] = new X509CertImpl(chain[i].getEncoded());
+ }
+ mCACertChain = new CertificateChain(implchain);
+ CMS.debug("in init - got CA chain from JSS.");
+ }
+
+ IConfigStore OCSPStore = mConfig.getSubStore(PROP_OCSP_SIGNING_SUBSTORE);
+
+ if (OCSPStore != null && OCSPStore.size() > 0) {
+ mOCSPSigningUnit = new SigningUnit();
+ mOCSPSigningUnit.init(this, mConfig.getSubStore(PROP_OCSP_SIGNING_SUBSTORE));
+ CMS.debug("Separate OCSP signing unit inited");
+ } else {
+ mOCSPSigningUnit = mSigningUnit;
+ CMS.debug("Shared OCSP signing unit inited");
+ }
+
+ org.mozilla.jss.crypto.X509Certificate[] ocspChain =
+ manager.buildCertificateChain(mOCSPSigningUnit.getCert());
+ // do this in case other subsyss expect a X509CertImpl
+ java.security.cert.X509Certificate[] ocspImplchain =
+ new java.security.cert.X509Certificate[ocspChain.length];
+
+ for (int i = 0; i < ocspChain.length; i++) {
+ ocspImplchain[i] = new X509CertImpl(ocspChain[i].getEncoded());
+ }
+ mOCSPCertChain = new CertificateChain(ocspImplchain);
+ CMS.debug("in init - got OCSP chain from JSS.");
+ // init issuer name - take name from the cert.
+
+ mCaX509Cert = mSigningUnit.getCert();
+ mCaCert = new X509CertImpl(mCaX509Cert.getEncoded());
+ getCASigningAlgorithms();
+ mName = (X500Name) mCaCert.getSubjectDN();
+
+ mCRLX509Cert = mCRLSigningUnit.getCert();
+ mCRLCert = new X509CertImpl(mCRLX509Cert.getEncoded());
+ mCRLName = (X500Name) mCRLCert.getSubjectDN();
+
+ mOCSPX509Cert = mOCSPSigningUnit.getCert();
+ mOCSPNickname = mOCSPSigningUnit.getNickname();
+ mOCSPCert = new X509CertImpl(mOCSPX509Cert.getEncoded());
+ mOCSPName = (X500Name) mOCSPCert.getSubjectDN();
+ mNickname = mSigningUnit.getNickname();
+ CMS.debug("in init - got CA name " + mName);
+
+ } catch (CryptoManager.NotInitializedException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_SIGNING", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CRYPTO_NOT_INITIALIZED"));
+ } catch (CertificateException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED", e.toString()));
+ } catch (FileNotFoundException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED", e.toString()));
+ } catch (IOException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED", e.toString()));
+ } catch (TokenException e) {
+ if (Debug.ON)
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_CHAIN", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_BUILD_CA_CHAIN_FAILED", e.toString()));
+ }
+ }
+
+ /**
+ * read ca cert from path, converts and bytes
+ */
+ byte[] getCertFromFile(String path)
+ throws FileNotFoundException, IOException {
+
+ File file = new File(path);
+ Long l = Long.valueOf(file.length());
+ byte[] b = new byte[l.intValue()];
+ FileInputStream in = new FileInputStream(path);
+ int num = in.read(b);
+ in.close();
+
+ return b;
+ }
+
+ /**
+ * init default cert attributes.
+ */
+ private void initDefCaAttrs()
+ throws EBaseException {
+ int version = mConfig.getInteger(PROP_X509CERT_VERSION,
+ CertificateVersion.V3);
+
+ if (version != CertificateVersion.V1 &&
+ version != CertificateVersion.V3) {
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_X509CERT_VERSION_NOT_SUPPORTED"));
+ }
+ try {
+ mDefaultCertVersion = new CertificateVersion(version - 1);
+ } catch (IOException e) {
+ // should never occur.
+ }
+
+ int validity_in_days = mConfig.getInteger(PROP_DEF_VALIDITY, 2 * 365);
+
+ mDefaultValidity = validity_in_days * DAY; // days in config file.
+
+ mEnablePastCATime =
+ mConfig.getBoolean(PROP_ENABLE_PAST_CATIME, false);
+ mEnableOCSP =
+ mConfig.getBoolean(PROP_ENABLE_OCSP, true);
+
+ String fs = mConfig.getString(PROP_FAST_SIGNING, "");
+
+ if (fs.equals("enabled") || fs.equals("enable")) {
+ mFastSigning = FASTSIGNING_ENABLED;
+ } else {
+ mFastSigning = FASTSIGNING_DISABLED;
+ }
+
+ }
+
+ /**
+ * init cert & crl database
+ */
+ private void initCaDatabases()
+ throws EBaseException {
+ int certdb_inc = mConfig.getInteger(PROP_CERTDB_INC, 5);
+
+ String certReposDN = mConfig.getString(PROP_CERT_REPOS_DN, null);
+
+ if (certReposDN == null) {
+ certReposDN = "ou=certificateRepository, ou=" + getId() +
+ ", " + getDBSubsystem().getBaseDN();
+ }
+ String reposDN = mConfig.getString(PROP_REPOS_DN, null);
+
+ if (reposDN == null) {
+ reposDN = "ou=certificateRepository, ou=" + getId() +
+ ", " + getDBSubsystem().getBaseDN();
+ }
+
+ int transitMaxRecords = mConfig.getInteger(PROP_CERTDB_TRANS_MAXRECORDS, 1000000);
+ int transitRecordPageSize = mConfig.getInteger(PROP_CERTDB_TRANS_PAGESIZE, 200);
+
+ mCertRepot = new CertificateRepository(
+ DBSubsystem.getInstance(),
+ certReposDN, certdb_inc, reposDN);
+
+ mCertRepot.setTransitMaxRecords(transitMaxRecords);
+ mCertRepot.setTransitRecordPageSize(transitRecordPageSize);
+
+ CMS.debug("Cert Repot inited");
+
+ // init crl repot.
+
+ int crldb_inc = mConfig.getInteger(PROP_CRLDB_INC, 5);
+
+ mCRLRepot = new CRLRepository(
+ DBSubsystem.getInstance(),
+ crldb_inc,
+ "ou=crlIssuingPoints, ou=" + getId() + ", " +
+ getDBSubsystem().getBaseDN());
+ CMS.debug("CRL Repot inited");
+
+ String replicaReposDN = mConfig.getString(PROP_REPLICAID_DN, null);
+ if (replicaReposDN == null) {
+ replicaReposDN = "ou=Replica," + getDBSubsystem().getBaseDN();
+ }
+ mReplicaRepot = new ReplicaIDRepository(
+ DBSubsystem.getInstance(), 1, replicaReposDN);
+ CMS.debug("Replica Repot inited");
+
+ }
+
+ /**
+ * init web gateway - just gets the ee gateway for this CA.
+ */
+ private void initWebGateway()
+ throws EBaseException {
+ }
+
+ private void startPublish()
+ throws EBaseException {
+ //xxx Note that CMS411 only support ca cert publishing to ldap
+ // if ldap publishing is not enabled while publishing isenabled
+ // there will be a lot of problem.
+ try {
+ if (mPublisherProcessor.enabled()) {
+ mPublisherProcessor.publishCACert(mCaCert);
+ CMS.debug("published ca cert");
+ }
+ } catch (ELdapException e) {
+ // exception not thrown - not seen as a fatal error.
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_PUBLISH", e.toString()));
+ }
+ }
+
+ /**
+ * init publishing
+ */
+ private void initPublish()
+ throws EBaseException {
+ IConfigStore c = null;
+
+ try {
+ c = mConfig.getSubStore(PROP_PUBLISH_SUBSTORE);
+ if (c != null && c.size() > 0) {
+ mPublisherProcessor = new PublisherProcessor(
+ getId() + "pp");
+ mPublisherProcessor.init(this, c);
+ CMS.debug("Publishing inited");
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_PUBLISH"));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_INIT_PUBLISH_MODULE_FAILED"));
+ }
+
+ } catch (ELdapException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_ERROR_PUBLISH_MODULE", e.toString()));
+ //throw new ECAException(
+ // CAResources.INIT_PUBLISH_MODULE_FAILED, e);
+ }
+ }
+
+ private void initMiscellaneousListeners() {
+ IConfigStore lc = null;
+ IConfigStore implc = null;
+ IConfigStore instc = null;
+
+ mListenerPlugins = new Hashtable();
+ try {
+ // Get list of listener implementations
+ lc = mConfig.getSubStore(PROP_LISTENER_SUBSTORE);
+ if (lc != null) {
+
+ implc = lc.getSubStore(PROP_IMPL);
+ Enumeration names = implc.getSubStoreNames();
+
+ while (names.hasMoreElements()) {
+ String id = (String) names.nextElement();
+
+ if (Debug.ON)
+ Debug.trace("registering listener impl: " + id);
+ String cl = implc.getString(id + "." + PROP_CLASS);
+
+ ListenerPlugin plugin = new ListenerPlugin(id, cl);
+
+ mListenerPlugins.put(id, plugin);
+ }
+
+ instc = lc.getSubStore(PROP_INSTANCE);
+ Enumeration instances = instc.getSubStoreNames();
+
+ while (instances.hasMoreElements()) {
+ String id = (String) instances.nextElement();
+
+ if (Debug.ON)
+ Debug.trace("registering listener instance: " + id);
+ IConfigStore iConfig = instc.getSubStore(id);
+ String implName = instc.getString(id + "." + PROP_PLUGIN);
+ ListenerPlugin plugin = (ListenerPlugin) mListenerPlugins.get(implName);
+
+ if (plugin == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_ERROR_LISTENER", implName));
+ throw new Exception("Cannot initialize");
+ }
+ String className = plugin.getClassPath();
+
+ try {
+ IRequestListener listener = null;
+
+ listener = (IRequestListener)
+ Class.forName(className).newInstance();
+
+ //listener.init(id, implName, iConfig);
+ listener.init(this, iConfig);
+ // registerRequestListener(id, (IRequestListener) listener);
+ //log(ILogger.LL_INFO,
+ // "Listener instance " + id + " added");
+
+ } catch (Exception e) {
+ if (Debug.ON) {
+ e.printStackTrace();
+ }
+ Debug.trace("failed to add listener instance");
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_INIT_LISTENER", id, e.toString()));
+ throw e;
+ }
+ }
+
+ }
+
+ } catch (Exception e) {
+ log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CA_CA_FAILED_LISTENER", e.toString()));
+ }
+
+ }
+
+ /**
+ * init notification related listeners
+ */
+ private void initNotificationListeners() {
+ IConfigStore nc = null;
+
+ try {
+ nc = mConfig.getSubStore(PROP_NOTIFY_SUBSTORE);
+ if (nc != null && nc.size() > 0) {
+ // Initialize Certificate Issued notification listener
+
+ String certificateIssuedListenerClassName = nc.getString("certificateIssuedListenerClassName", "com.netscape.cms.listeners.CertificateIssuedListener");
+
+ try {
+ mCertIssuedListener = (IRequestListener) Class.forName(certificateIssuedListenerClassName).newInstance();
+ mCertIssuedListener.init(this, nc);
+ } catch (Exception e1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_REGISTER_LISTENER", certificateIssuedListenerClassName));
+ }
+
+ // Initialize Revoke Request notification listener
+
+ String certificateRevokedListenerClassName = nc.getString("certificateIssuedListenerClassName", "com.netscape.cms.listeners.CertificateRevokedListener");
+
+ try {
+ mCertRevokedListener = (IRequestListener) Class.forName(certificateRevokedListenerClassName).newInstance();
+ mCertRevokedListener.init(this, nc);
+ } catch (Exception e1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_REGISTER_LISTENER", certificateRevokedListenerClassName));
+ }
+
+ // Initialize Request In Queue notification listener
+ IConfigStore rq = nc.getSubStore(PROP_REQ_IN_Q_SUBSTORE);
+
+ String requestInQListenerClassName = nc.getString("certificateIssuedListenerClassName", "com.netscape.cms.listeners.RequestInQListener");
+
+ try {
+ mReqInQListener = (IRequestListener) Class.forName(requestInQListenerClassName).newInstance();
+ mReqInQListener.init(this, nc);
+ } catch (Exception e1) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_REGISTER_REQ_LISTENER", requestInQListenerClassName));
+ }
+
+ // Initialize extra listeners
+ IConfigStore mListenerConfig = null;
+
+ } else {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NOTIFY_NONE"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NOTIFY_FAILED"));
+ // throw e;
+ }
+ }
+
+ /**
+ * initialize request queue components
+ */
+ private void initRequestQueue()
+ throws EBaseException {
+ mPolicy = new CAPolicy();
+ ((CAPolicy) mPolicy).init(this, mConfig.getSubStore(PROP_POLICY));
+ CMS.debug("CA policy inited");
+ mService = new CAService(this);
+ CMS.debug("CA service inited");
+
+ mNotify = new ARequestNotifier (this);
+ CMS.debug("CA notifier inited");
+ mPNotify = new ARequestNotifier();
+ CMS.debug("CA pending notifier inited");
+
+ // instantiate CA request queue.
+ try {
+ int reqdb_inc = mConfig.getInteger("reqdbInc", 5);
+
+ mRequestQueue =
+ RequestSubsystem.getInstance().getRequestQueue(
+ getId(), reqdb_inc, mPolicy, mService, mNotify, mPNotify);
+ } catch (EBaseException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_QUEUE_FAILED", e.toString()));
+ throw e;
+ }
+
+ // init request scheduler if configured
+ String schedulerClass =
+ mConfig.getString("requestSchedulerClass", null);
+
+ if (schedulerClass != null) {
+ try {
+ IRequestScheduler scheduler = (IRequestScheduler)
+ Class.forName(schedulerClass).newInstance();
+
+ mRequestQueue.setRequestScheduler(scheduler);
+ } catch (Exception e) {
+ // do nothing here
+ }
+ }
+ }
+
+ /*
+ private void startCRL()
+ throws EBaseException
+ {
+ Enumeration e = mCRLIssuePoints.keys();
+ while (e.hasMoreElements()) {
+ CRLIssuingPoint cp = (CRLIssuingPoint)
+ mCRLIssuePoints.get(e.nextElement());
+ cp.startup();
+ }
+ }
+ */
+
+ /**
+ * initialize CRL
+ */
+ private void initCRL()
+ throws EBaseException {
+ IConfigStore crlConfig = mConfig.getSubStore(PROP_CRL_SUBSTORE);
+
+ if ((crlConfig == null) || (crlConfig.size() <= 0)) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_MASTER_CRL"));
+ //throw new ECAException(CAResources.NO_CONFIG_FOR_MASTER_CRL);
+ return;
+ }
+ Enumeration issuePointIdEnum = crlConfig.getSubStoreNames();
+
+ if (issuePointIdEnum == null || !issuePointIdEnum.hasMoreElements()) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_MASTER_CRL_SUBSTORE"));
+ //throw new ECAException(CAResources.NO_CONFIG_FOR_MASTER_CRL);
+ return;
+ }
+
+ // a Master/full crl must exist.
+
+ while (issuePointIdEnum.hasMoreElements()) {
+ String issuePointId = (String) issuePointIdEnum.nextElement();
+
+ CMS.debug(
+ "initializing crl issue point " + issuePointId);
+ IConfigStore issuePointConfig = null;
+ String issuePointClassName = null;
+ Class issuePointClass = null;
+ CRLIssuingPoint issuePoint = null;
+
+ try {
+ issuePointConfig = crlConfig.getSubStore(issuePointId);
+ issuePointClassName = issuePointConfig.getString(PROP_CLASS);
+ issuePointClass = Class.forName(issuePointClassName);
+ issuePoint = (CRLIssuingPoint) issuePointClass.newInstance();
+ issuePoint.init(this, issuePointId, issuePointConfig);
+ mCRLIssuePoints.put(issuePointId, issuePoint);
+ if (mMasterCRLIssuePoint == null &&
+ issuePointId.equals(PROP_MASTER_CRL))
+ mMasterCRLIssuePoint = issuePoint;
+ } catch (ClassNotFoundException e) {
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUING_POINT_INIT_FAILED",
+ issuePointId, e.toString()));
+ } catch (InstantiationException e) {
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUING_POINT_INIT_FAILED",
+ issuePointId, e.toString()));
+ } catch (IllegalAccessException e) {
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_CRL_ISSUING_POINT_INIT_FAILED",
+ issuePointId, e.toString()));
+ }
+ }
+
+ /*
+ if (mMasterCRLIssuePoint == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_NO_FULL_CRL", PROP_MASTER_CRL));
+ throw new ECAException(CAResources.NO_CONFIG_FOR_MASTER_CRL);
+ }
+ */
+ log(ILogger.LL_INFO, "CRL Issuing Points inited");
+ }
+
+ public String getOfficialName() {
+ return OFFICIAL_NAME;
+ }
+
+ public long getNumOCSPRequest() {
+ return mNumOCSPRequest;
+ }
+
+ public long getOCSPRequestTotalTime() {
+ return mTotalTime;
+ }
+
+ public long getOCSPTotalData() {
+ return mTotalData;
+ }
+
+ public long getOCSPTotalSignTime() {
+ return mSignTime;
+ }
+
+ public long getOCSPTotalLookupTime()
+ {
+ return mLookupTime;
+ }
+
+ public ResponderID getResponderIDByName() {
+ try {
+ X500Name name = getOCSPX500Name();
+ Name.Template nameTemplate = new Name.Template();
+
+ return new NameID((Name) nameTemplate.decode(
+ new ByteArrayInputStream(name.getEncoded())));
+ } catch (IOException e) {
+ return null;
+ } catch (InvalidBERException e) {
+ return null;
+ }
+ }
+
+ public ResponderID getResponderIDByHash() {
+
+ /*
+ KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ --(excluding the tag and length fields)
+ */
+ PublicKey publicKey = getOCSPSigningUnit().getPublicKey();
+ MessageDigest md = null;
+
+ try {
+ md = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ md.update(publicKey.getEncoded());
+ byte digested[] = md.digest();
+
+ return new KeyHashID(new OCTET_STRING(digested));
+ }
+
+ /**
+ * Process OCSPRequest.
+ */
+ public OCSPResponse validate(OCSPRequest request)
+ throws EBaseException {
+
+ if (!mEnableOCSP) {
+ CMS.debug("Local ocsp service is disable.");
+ return null;
+ }
+
+ mNumOCSPRequest++;
+ IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats");
+ long startTime = CMS.getCurrentDate().getTime();
+ try {
+ //log(ILogger.LL_INFO, "start OCSP request");
+ TBSRequest tbsReq = request.getTBSRequest();
+
+ // (3) look into database to check the
+ // certificate's status
+ Vector singleResponses = new Vector();
+ if (statsSub != null) {
+ statsSub.startTiming("lookup");
+ }
+
+ long lookupStartTime = CMS.getCurrentDate().getTime();
+ for (int i = 0; i < tbsReq.getRequestCount(); i++) {
+ com.netscape.cmsutil.ocsp.Request req =
+ tbsReq.getRequestAt(i);
+ CertID cid = req.getCertID();
+ SingleResponse sr = processRequest(cid);
+
+ singleResponses.addElement(sr);
+ }
+ long lookupEndTime = CMS.getCurrentDate().getTime();
+ if (statsSub != null) {
+ statsSub.endTiming("lookup");
+ }
+ mLookupTime += lookupEndTime - lookupStartTime;
+
+ if (statsSub != null) {
+ statsSub.startTiming("build_response");
+ }
+ SingleResponse res[] = new SingleResponse[singleResponses.size()];
+
+ singleResponses.copyInto(res);
+
+ ResponderID rid = null;
+ if (mByName) {
+ if (mResponderIDByName == null) {
+ mResponderIDByName = getResponderIDByName();
+ }
+ rid = mResponderIDByName;
+ } else {
+ if (mResponderIDByHash == null) {
+ mResponderIDByHash = getResponderIDByHash();
+ }
+ rid = mResponderIDByHash;
+ }
+
+ Extension nonce[] = null;
+
+ for (int j = 0; j < tbsReq.getExtensionsCount(); j++) {
+ Extension thisExt = tbsReq.getRequestExtensionAt(j);
+
+ if (thisExt.getExtnId().equals(OCSP_NONCE)) {
+ nonce = new Extension[1];
+ nonce[0] = thisExt;
+ }
+ }
+ ResponseData rd = new ResponseData(rid,
+ new GeneralizedTime(CMS.getCurrentDate()), res, nonce);
+ if (statsSub != null) {
+ statsSub.endTiming("build_response");
+ }
+
+ if (statsSub != null) {
+ statsSub.startTiming("signing");
+ }
+ long signStartTime = CMS.getCurrentDate().getTime();
+ BasicOCSPResponse basicRes = sign(rd);
+ long signEndTime = CMS.getCurrentDate().getTime();
+ mSignTime += signEndTime - signStartTime;
+ if (statsSub != null) {
+ statsSub.endTiming("signing");
+ }
+
+ OCSPResponse response = new OCSPResponse(
+ OCSPResponseStatus.SUCCESSFUL,
+ new ResponseBytes(ResponseBytes.OCSP_BASIC,
+ new OCTET_STRING(ASN1Util.encode(basicRes))));
+
+ //log(ILogger.LL_INFO, "done OCSP request");
+ long endTime = CMS.getCurrentDate().getTime();
+ mTotalTime += endTime - startTime;
+ return response;
+ } catch (Exception e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_REQUEST", e.toString()));
+ return null;
+ }
+ }
+
+ private BasicOCSPResponse sign(ResponseData rd) throws EBaseException {
+ try {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream tmp = new DerOutputStream();
+
+ String algname = mOCSPSigningUnit.getDefaultAlgorithm();
+
+ byte rd_data[] = ASN1Util.encode(rd);
+ if (rd_data != null) {
+ mTotalData += rd_data.length;
+ }
+ rd.encode(tmp);
+ AlgorithmId.get(algname).encode(tmp);
+ CMS.debug("adding signature");
+ byte[] signature = mOCSPSigningUnit.sign(rd_data, algname);
+
+ tmp.putBitString(signature);
+ // optional, put the certificate chains in also
+
+ DerOutputStream tmpChain = new DerOutputStream();
+ DerOutputStream tmp1 = new DerOutputStream();
+ DerOutputStream outChain = new DerOutputStream();
+ java.security.cert.X509Certificate chains[] =
+ mOCSPCertChain.getChain();
+
+ for (int i = 0; i < chains.length; i++) {
+ tmpChain.putDerValue(new DerValue(chains[i].getEncoded()));
+ }
+ tmp1.write(DerValue.tag_Sequence, tmpChain);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
+ tmp1);
+
+ out.write(DerValue.tag_Sequence, tmp);
+
+ BasicOCSPResponse response = new BasicOCSPResponse(out.toByteArray());
+
+ return response;
+ } catch (Exception e) {
+ e.printStackTrace();
+ // error e
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_CA_OCSP_SIGN", e.toString()));
+ return null;
+ }
+ }
+
+ private SingleResponse processRequest(CertID cid) {
+ INTEGER serialNo = cid.getSerialNumber();
+
+ CMS.debug("process request " + serialNo);
+ CertStatus certStatus = null;
+ GeneralizedTime thisUpdate = new GeneralizedTime(CMS.getCurrentDate());
+ GeneralizedTime nextUpdate = null;
+
+ boolean ocspUseCache = true;
+
+ try {
+ /* enable OCSP cache by default */
+ ocspUseCache = mConfig.getBoolean("ocspUseCache", false);
+ } catch (EBaseException e) {
+ }
+
+ if (ocspUseCache) {
+ String issuingPointId = PROP_MASTER_CRL;
+
+ try {
+ issuingPointId = mConfig.getString(
+ "ocspUseCacheIssuingPointId", PROP_MASTER_CRL);
+
+ } catch (EBaseException e) {
+ }
+ CRLIssuingPoint point = (CRLIssuingPoint)
+ getCRLIssuingPoint(issuingPointId);
+
+ if (point.isCRLCacheEnabled()) {
+ // only do this if cache is enabled
+ BigInteger sno = new BigInteger(serialNo.toString());
+ boolean checkDeltaCache = false;
+ boolean includeExpiredCerts = false;
+
+ try {
+ checkDeltaCache = mConfig.getBoolean("ocspUseCacheCheckDeltaCache", false);
+ } catch (EBaseException e) {
+ }
+ try {
+ includeExpiredCerts = mConfig.getBoolean("ocspUseCacheIncludeExpiredCerts", false);
+ } catch (EBaseException e) {
+ }
+ Date revokedOn = point.getRevocationDateFromCache(
+ sno, checkDeltaCache, includeExpiredCerts);
+
+ if (revokedOn == null) {
+ certStatus = new GoodInfo();
+ } else {
+ certStatus = new RevokedInfo(new GeneralizedTime(revokedOn));
+ }
+ return new SingleResponse(cid, certStatus, thisUpdate, nextUpdate);
+ }
+ }
+
+ try {
+ ICertRecord rec = mCertRepot.readCertificateRecord(serialNo);
+ String status = rec.getStatus();
+
+ if (status == null) {
+ certStatus = new UnknownInfo();
+ } else if (status.equals(CertRecord.STATUS_VALID)) {
+ certStatus = new GoodInfo();
+ } else if (status.equals(CertRecord.STATUS_INVALID)) {
+ // not yet valid
+ certStatus = new UnknownInfo();
+ } else if (status.equals(CertRecord.STATUS_REVOKED)) {
+ certStatus = new RevokedInfo(new GeneralizedTime(rec.getRevokedOn()));
+ } else if (status.equals(CertRecord.STATUS_EXPIRED)) {
+ certStatus = new UnknownInfo();
+ } else if (status.equals(CertRecord.STATUS_REVOKED_EXPIRED)) {
+ certStatus = new RevokedInfo(new GeneralizedTime(rec.getRevokedOn()));
+ } else {
+ certStatus = new UnknownInfo();
+ }
+ } catch (Exception e) {
+ // not found
+ certStatus = new UnknownInfo(); // not issued not all
+ }
+
+ return new SingleResponse(cid, certStatus, thisUpdate, nextUpdate);
+ }
+}
+
diff --git a/pki/base/ca/src/com/netscape/ca/SigningUnit.java b/pki/base/ca/src/com/netscape/ca/SigningUnit.java
new file mode 100644
index 000000000..5a95c530b
--- /dev/null
+++ b/pki/base/ca/src/com/netscape/ca/SigningUnit.java
@@ -0,0 +1,381 @@
+// --- 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.ca;
+
+
+import java.io.*;
+import java.security.SignatureException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.InvalidKeyException;
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import org.mozilla.jss.*;
+import org.mozilla.jss.crypto.*;
+import org.mozilla.jss.util.*;
+import org.mozilla.jss.crypto.Signature;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.security.*;
+import com.netscape.certsrv.ca.*;
+import com.netscape.cmsutil.util.*;
+
+import com.netscape.cmscore.security.JssSubsystem;
+
+
+/**
+ * CA signing unit based on JSS.
+ *
+ * $Revision$ $Date$
+ */
+
+public final class SigningUnit implements ISigningUnit {
+ public static final String PROP_DEFAULT_SIGNALG = "defaultSigningAlgorithm";
+ public static final String PROP_CERT_NICKNAME = "cacertnickname";
+ // This signing unit is being used in OCSP and CRL also. So
+ // it is better to have a more generic name
+ public static final String PROP_RENAMED_CERT_NICKNAME = "certnickname";
+ public static final String PROP_TOKEN_NAME = "tokenname";
+ public static final String PROP_NEW_NICKNAME = "newNickname";
+
+ private CryptoManager mManager = null;
+ private CryptoToken mToken = null;
+ private PublicKey mPubk = null;
+ private PrivateKey mPrivk = null;
+
+ protected X509Certificate mCert = null;
+ protected X509CertImpl mCertImpl = null;
+ protected String mNickname = null;
+
+ private boolean mInited = false;
+ private ILogger mLogger = CMS.getLogger();
+ private IConfigStore mConfig;
+
+ private ISubsystem mOwner = null;
+
+ private String mDefSigningAlgname = null;
+ private SignatureAlgorithm mDefSigningAlgorithm = null;
+
+ public SigningUnit() {
+ }
+
+ public X509Certificate getCert() {
+ return mCert;
+ }
+
+ public X509CertImpl getCertImpl() {
+ return mCertImpl;
+ }
+
+ public String getNickname() {
+ return mNickname;
+ }
+
+ public String getNewNickName() throws EBaseException {
+ return mConfig.getString(PROP_NEW_NICKNAME, "");
+ }
+
+ public void setNewNickName(String name) {
+ mConfig.putString(PROP_NEW_NICKNAME, name);
+ }
+
+ public PublicKey getPublicKey() {
+ return mPubk;
+ }
+
+ public PrivateKey getPrivateKey() {
+ return mPrivk;
+ }
+
+ public void updateConfig(String nickname, String tokenname) {
+ mConfig.putString(PROP_CERT_NICKNAME, nickname);
+ mConfig.putString(PROP_TOKEN_NAME, tokenname);
+ }
+
+ public String getTokenName() throws EBaseException {
+ return mConfig.getString(PROP_TOKEN_NAME);
+ }
+
+ public String getNickName() throws EBaseException {
+ try {
+ return mConfig.getString(PROP_RENAMED_CERT_NICKNAME);
+ } catch (EBaseException e) {
+ return mConfig.getString(PROP_CERT_NICKNAME);
+ }
+ }
+
+ public void init(ISubsystem owner, IConfigStore config)
+ throws EBaseException {
+ mOwner = owner;
+ mConfig = config;
+
+ String tokenname = null;
+ try {
+ mManager = CryptoManager.getInstance();
+
+ mNickname = getNickName();
+
+ tokenname = config.getString(PROP_TOKEN_NAME);
+ if (tokenname.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) ||
+ tokenname.equalsIgnoreCase("Internal Key Storage Token")) {
+ mToken = mManager.getInternalKeyStorageToken();
+ setNewNickName(mNickname);
+ } else {
+ mToken = mManager.getTokenByName(tokenname);
+ mNickname = tokenname + ":" + mNickname;
+ setNewNickName(mNickname);
+ }
+ CMS.debug(config.getName() + " Signing Unit nickname " + mNickname);
+ CMS.debug("Got token " + tokenname + " by name");
+
+ PasswordCallback cb = JssSubsystem.getInstance().getPWCB();
+
+ mToken.login(cb); // ONE_TIME by default.
+
+ mCert = mManager.findCertByNickname(mNickname);
+ CMS.debug("Found cert by nickname: '"+mNickname+"' with serial number: "+mCert.getSerialNumber());
+
+ mCertImpl = new X509CertImpl(mCert.getEncoded());
+ CMS.debug("converted to x509CertImpl");
+
+ mPrivk = mManager.findPrivKeyByCert(mCert);
+ CMS.debug("Got private key from cert");
+
+ mPubk = mCert.getPublicKey();
+ CMS.debug("Got public key from cert");
+
+ // get def alg and check if def sign alg is valid for token.
+ mDefSigningAlgname = config.getString(PROP_DEFAULT_SIGNALG);
+ mDefSigningAlgorithm =
+ checkSigningAlgorithmFromName(mDefSigningAlgname);
+ CMS.debug(
+ "got signing algorithm " + mDefSigningAlgorithm);
+ mInited = true;
+ } catch (java.security.cert.CertificateException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_CA_CERT", e.getMessage()));
+ throw new ECAException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString()));
+ } catch (CryptoManager.NotInitializedException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_TOKEN_INIT", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CRYPTO_NOT_INITIALIZED"));
+ } catch (IncorrectPasswordException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_WRONG_PWD", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_INVALID_PASSWORD"));
+ } catch (NoSuchTokenException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_TOKEN_NOT_FOUND", tokenname, e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_NOT_FOUND", tokenname));
+ } catch (ObjectNotFoundException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_CERT_NOT_FOUND", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_CERT_OBJECT_NOT_FOUND"));
+ } catch (TokenException e) {
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ throw new ECAException(CMS.getUserMessage("CMS_CA_TOKEN_ERROR"));
+ } catch (Exception e){
+ CMS.debug("SigningUnit init: debug "+ e.toString());
+ }
+ }
+
+ /**
+ * Check if the signing algorithm name is supported and valid for this
+ * signing unit's token and key.
+ *
+ * @param algname a signing algorithm name from JCA.
+ * @return the mapped JSS signature algorithm object.
+ *
+ * @exception EBaseException if signing algorithm is not supported.
+ */
+ public SignatureAlgorithm checkSigningAlgorithmFromName(String algname)
+ throws EBaseException {
+ try {
+ SignatureAlgorithm sigalg = null;
+
+ sigalg = mapAlgorithmToJss(algname);
+ if (sigalg == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname, ""));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ }
+ Signature signer = mToken.getSignatureContext(sigalg);
+
+ signer.initSign(mPrivk);
+ return sigalg;
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname, e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ } catch (TokenException e) {
+ // from get signature context or from initSign
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname, e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname, e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED_FOR_KEY", algname));
+ }
+ }
+
+ /**
+ * @param algname is expected to be one of JCA's algorithm names.
+ */
+ public byte[] sign(byte[] data, String algname)
+ throws EBaseException {
+ if (!mInited) {
+ throw new EBaseException("CASigningUnit not initialized!");
+ }
+ try {
+ // XXX for now do this mapping until James changes the names
+ // to match JCA names and provide a getAlgorithm method.
+ SignatureAlgorithm signAlg = mDefSigningAlgorithm;
+
+ if (algname != null) {
+ signAlg = checkSigningAlgorithmFromName(algname);
+ }
+
+ // XXX use a pool of signers based on alg ?
+ // XXX Map algor. name to id. hack: use hardcoded define for now.
+ CMS.debug(
+ "Getting algorithm context for " + algname + " " + signAlg);
+ Signature signer = mToken.getSignatureContext(signAlg);
+
+ signer.initSign(mPrivk);
+ signer.update(data);
+ // XXX add something more descriptive.
+ CMS.debug("Signing Certificate");
+ return signer.sign();
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ } catch (TokenException e) {
+ // from get signature context or from initSign
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ } catch (InvalidKeyException e) {
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ } catch (SignatureException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ public boolean verify(byte[] data, byte[] signature, String algname)
+ throws EBaseException {
+ if (!mInited) {
+ throw new EBaseException("CASigningUnit not initialized!");
+ }
+ try {
+ SignatureAlgorithm signAlg = mapAlgorithmToJss(algname);
+
+ if (signAlg == null) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_CA_SIGNING_ALG_NOT_SUPPORTED", algname, ""));
+ throw new ECAException(
+ CMS.getUserMessage("CMS_CA_SIGNING_ALGOR_NOT_SUPPORTED", algname));
+ }
+ // XXX make this configurable. hack: use hardcoded for now.
+ Signature signer = mToken.getSignatureContext(signAlg);
+
+ signer.initVerify(mPubk);
+ signer.update(data);
+ return signer.verify(signature);
+ } catch (NoSuchAlgorithmException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ } catch (TokenException e) {
+ // from get signature context or from initSign
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ } catch (InvalidKeyException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ } catch (SignatureException e) {
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString()));
+ // XXX fix this exception later.
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ private void log(int level, String msg) {
+ if (mLogger == null)
+ return;
+ mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_CA,
+ level, "CASigningUnit: " + msg);
+ }
+
+ /**
+ * returns default signature algorithm
+ */
+ public SignatureAlgorithm getDefaultSignatureAlgorithm() {
+ return mDefSigningAlgorithm;
+ }
+
+ /**
+ * returns default signing algorithm name.
+ */
+ public String getDefaultAlgorithm() {
+ return mDefSigningAlgname;
+ }
+
+ public void setDefaultAlgorithm(String algorithm) throws EBaseException {
+ mConfig.putString(PROP_DEFAULT_SIGNALG, algorithm);
+ mDefSigningAlgname = algorithm;
+ log(ILogger.LL_INFO,
+ "Default signing algorithm is set to " + algorithm);
+ }
+
+ /**
+ * get all possible algorithms for the CA signing key type.
+ */
+ public String[] getAllAlgorithms() throws EBaseException {
+ byte[] keybytes = mPubk.getEncoded();
+ X509Key key = new X509Key();
+
+ try {
+ key.decode(keybytes);
+ } catch (java.security.InvalidKeyException e) {
+ String msg = "Invalid encoding in CA signing key.";
+
+ log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", msg));
+ throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", msg));
+ }
+
+ if (key.getAlgorithmId().getOID().equals(AlgorithmId.DSA_oid)) {
+ return AlgorithmId.DSA_SIGNING_ALGORITHMS;
+ } else {
+ return AlgorithmId.ALL_SIGNING_ALGORITHMS;
+ }
+ }
+
+ public static SignatureAlgorithm mapAlgorithmToJss(String algname) {
+ return Cert.mapAlgorithmToJss(algname);
+ }
+}
+