From 621d9e5c413e561293d7484b93882d985b3fe15f Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Sat, 24 Mar 2012 02:27:47 -0500 Subject: Removed unnecessary pki folder. Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131 --- .../src/com/netscape/ca/CertificateAuthority.java | 2024 ++++++++++++++++++++ 1 file changed, 2024 insertions(+) create mode 100644 base/ca/src/com/netscape/ca/CertificateAuthority.java (limited to 'base/ca/src/com/netscape/ca/CertificateAuthority.java') diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java new file mode 100644 index 000000000..c8783f566 --- /dev/null +++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java @@ -0,0 +1,2024 @@ +// --- 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.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CRLException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import netscape.security.util.DerOutputStream; +import netscape.security.util.DerValue; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CRLImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509ExtensionException; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.GeneralizedTime; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.pkix.cert.Extension; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ECAException; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.IDBSubsystem; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.crldb.ICRLRepository; +import com.netscape.certsrv.dbs.replicadb.IReplicaIDRepository; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IOCSPService; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.publish.ICRLPublisher; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.ARequestNotifier; +import com.netscape.certsrv.request.IPolicy; +import com.netscape.certsrv.request.IRequestListener; +import com.netscape.certsrv.request.IRequestNotifier; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestScheduler; +import com.netscape.certsrv.request.IService; +import com.netscape.certsrv.security.ISigningUnit; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cmscore.dbs.CRLRepository; +import com.netscape.cmscore.dbs.CertRecord; +import com.netscape.cmscore.dbs.CertificateRepository; +import com.netscape.cmscore.dbs.DBSubsystem; +import com.netscape.cmscore.dbs.ReplicaIDRepository; +import com.netscape.cmscore.ldap.PublisherProcessor; +import com.netscape.cmscore.listeners.ListenerPlugin; +import com.netscape.cmscore.request.RequestSubsystem; +import com.netscape.cmscore.security.KeyCertUtil; +import com.netscape.cmscore.util.Debug; +import com.netscape.cmsutil.ocsp.BasicOCSPResponse; +import com.netscape.cmsutil.ocsp.CertID; +import com.netscape.cmsutil.ocsp.CertStatus; +import com.netscape.cmsutil.ocsp.GoodInfo; +import com.netscape.cmsutil.ocsp.KeyHashID; +import com.netscape.cmsutil.ocsp.NameID; +import com.netscape.cmsutil.ocsp.OCSPRequest; +import com.netscape.cmsutil.ocsp.OCSPResponse; +import com.netscape.cmsutil.ocsp.OCSPResponseStatus; +import com.netscape.cmsutil.ocsp.ResponderID; +import com.netscape.cmsutil.ocsp.ResponseBytes; +import com.netscape.cmsutil.ocsp.ResponseData; +import com.netscape.cmsutil.ocsp.RevokedInfo; +import com.netscape.cmsutil.ocsp.SingleResponse; +import com.netscape.cmsutil.ocsp.TBSRequest; +import com.netscape.cmsutil.ocsp.UnknownInfo; + +/** + * A class represents a Certificate Authority that is + * responsible for certificate specific operations. + *

+ * + * @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; + } + + /** + * @deprecated + */ + public IPolicyProcessor getPolicyProcessor() { + return mPolicy.getPolicyProcessor(); + } + + public boolean noncesEnabled() { + return mUseNonces; + } + + public Nonces getNonces() { + return mNonces; + } + + /** + * Initializes this CA subsystem. + *

+ * + * @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 { + @SuppressWarnings("unchecked") + Class pc = (Class) Class.forName(publisherClass); + + mCRLPublisher = 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 (CAService.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. + *

+ */ + 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. + *

+ */ + 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 = + 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 { + mCertRepot.setTheSerialNumber(new BigInteger(serial)); + } + + public String getMaxSerial() { + String serial = mCertRepot.getMaxSerial(); + + if (serial != null) + return serial; + else + return ""; + } + + public void setMaxSerial(String serial) throws EBaseException { + mCertRepot.setMaxSerial(serial); + } + + /** + * Retrieves certificate repository. + *

+ * + * @return certificate repository + */ + public ICertificateRepository getCertificateRepository() { + return mCertRepot; + } + + /** + * Retrieves replica repository. + *

+ * + * @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. + *

+ * + * @param id string id of the CRL issuing point + * @return CRL issuing point + */ + public ICRLIssuingPoint getCRLIssuingPoint(String id) { + return mCRLIssuePoints.get(id); + } + + /** + * Enumerates CRL issuing points + *

+ * + * @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. + */ + @SuppressWarnings("unchecked") + 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) 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 + *

+ * + * @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. + *

+ * + * @return CA signing cert nickname. + */ + public String getNickname() { + return mNickname; + } + + /** + * Returns nickname of OCSP's signing cert. + *

+ * + * @return OCSP signing cert nickname. + */ + public String getOCSPNickname() { + return mOCSPNickname; + } + + /** + * Returns default signing unit used by this CA + *

+ * + * @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. + *

+ * + * @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"); + } + + 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. + *

+ * + * @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"); + } + + 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. + *

+ * + * @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); + 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 = 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 + 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)); + } + + } 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 + */ + @SuppressWarnings("unchecked") + 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 = 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) Class.forName(issuePointClassName); + issuePoint = 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(); + 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); + } +} -- cgit