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 --- .../cmscore/dbs/CertificateRepository.java | 2030 ++++++++++++++++++++ 1 file changed, 2030 insertions(+) create mode 100644 base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java (limited to 'base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java') diff --git a/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java new file mode 100644 index 000000000..0df563cad --- /dev/null +++ b/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java @@ -0,0 +1,2030 @@ +// --- 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.cmscore.dbs; + +import java.io.Serializable; +import java.math.BigInteger; +import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPSearchResults; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.dbs.EDBException; +import com.netscape.certsrv.dbs.IDBSSession; +import com.netscape.certsrv.dbs.IDBSearchResults; +import com.netscape.certsrv.dbs.IDBSubsystem; +import com.netscape.certsrv.dbs.IDBVirtualList; +import com.netscape.certsrv.dbs.IElementProcessor; +import com.netscape.certsrv.dbs.Modification; +import com.netscape.certsrv.dbs.ModificationSet; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.certdb.IRevocationInfo; +import com.netscape.certsrv.dbs.repository.IRepository; +import com.netscape.certsrv.logging.ILogger; + +/** + * A class represents a certificate repository. It + * stores all the issued certificate. + *

+ * + * @author thomask + * @author kanda + * @version $Revision$, $Date$ + */ +public class CertificateRepository extends Repository + implements ICertificateRepository { + + public final String CERT_X509ATTRIBUTE = "x509signedcert"; + + private IDBSubsystem mDBService; + private String mBaseDN; + private String mRequestBaseDN; + private boolean mConsistencyCheck = false; + private boolean mSkipIfInconsistent = false; + + private int mCertStatusUpdateInterval = 0; + private Hashtable mCRLIssuingPoints = new Hashtable(); + + private int mTransitMaxRecords = 1000000; + private int mTransitRecordPageSize = 200; + + CertStatusUpdateTask certStatusUpdateTask; + RetrieveModificationsTask retrieveModificationsTask; + + IRepository requestRepository; + + /** + * Constructs a certificate repository. + */ + public CertificateRepository(IDBSubsystem dbService, String certRepoBaseDN, int increment, String baseDN) + throws EDBException { + super(dbService, increment, baseDN); + mBaseDN = certRepoBaseDN; + mDBService = dbService; + } + + public ICertRecord createCertRecord(BigInteger id, Certificate cert, MetaInfo meta) { + return new CertRecord(id, cert, meta); + } + + public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) + throws EBaseException { + + CMS.debug("CertificateRepository: in getLastSerialNumberInRange: low " + + serial_low_bound + " high " + serial_upper_bound); + + if (serial_low_bound == null + || serial_upper_bound == null || serial_low_bound.compareTo(serial_upper_bound) >= 0) { + return null; + + } + + String ldapfilter = "(" + "certstatus" + "=*" + ")"; + + String[] attrs = null; + + ICertRecordList recList = + findCertRecordsInList(ldapfilter, attrs, serial_upper_bound.toString(10), "serialno", 5 * -1); + + int size = recList.getSize(); + + CMS.debug("CertificateRepository:getLastSerialNumberInRange: recList size " + size); + + if (size <= 0) { + CMS.debug("CertificateRepository:getLastSerialNumberInRange: index may be empty"); + + BigInteger ret = new BigInteger(serial_low_bound.toString(10)); + + ret = ret.add(new BigInteger("-1")); + CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret); + return ret; + } + int ltSize = recList.getSizeBeforeJumpTo(); + + CMS.debug("CertificateRepository:getLastSerialNumberInRange: ltSize " + ltSize); + + CertRecord curRec = null; + + int i; + Object obj = null; + + for (i = 0; i < 5; i++) { + obj = recList.getCertRecord(i); + + if (obj != null) { + curRec = (CertRecord) obj; + + BigInteger serial = curRec.getSerialNumber(); + + CMS.debug("CertificateRepository:getLastCertRecordSerialNo: serialno " + serial); + + if (((serial.compareTo(serial_low_bound) == 0) || (serial.compareTo(serial_low_bound) == 1)) && + ((serial.compareTo(serial_upper_bound) == 0) || (serial.compareTo(serial_upper_bound) == -1))) { + CMS.debug("getLastSerialNumberInRange returning: " + serial); + return serial; + } + } else { + CMS.debug("getLastSerialNumberInRange:found null from getCertRecord"); + } + } + + BigInteger ret = new BigInteger(serial_low_bound.toString(10)); + + ret = ret.add(new BigInteger("-1")); + + CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret); + return ret; + + } + + /** + * Removes all objects with this repository. + */ + public void removeCertRecords(BigInteger beginS, BigInteger endS) throws EBaseException { + String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*" + ")"; + ICertRecordList list = findCertRecordsInList(filter, + null, "serialno", 10); + int size = list.getSize(); + Enumeration e = list.getCertRecords(0, size - 1); + while (e.hasMoreElements()) { + CertRecord rec = (CertRecord) e.nextElement(); + BigInteger cur = rec.getSerialNumber(); + BigInteger max = cur.max(beginS); + BigInteger min = cur; + if (endS != null) + min = cur.min(endS); + if (cur.equals(beginS) || cur.equals(endS) || + (cur.equals(max) && cur.equals(min))) + deleteCertificateRecord(cur); + } + } + + public void setConsistencyCheck(boolean ConsistencyCheck) { + mConsistencyCheck = ConsistencyCheck; + } + + public void setSkipIfInConsistent(boolean SkipIfInconsistent) { + mSkipIfInconsistent = SkipIfInconsistent; + } + + public void setTransitMaxRecords(int max) { + mTransitMaxRecords = max; + } + + public void setTransitRecordPageSize(int size) { + mTransitRecordPageSize = size; + + } + + /** + * register CRL Issuing Point + */ + public void addCRLIssuingPoint(String id, ICRLIssuingPoint crlIssuingPoint) { + mCRLIssuingPoints.put(id, crlIssuingPoint); + } + + /** + * interval value: (in seconds) + * 0 - disable + * >0 - enable + */ + public void setCertStatusUpdateInterval(IRepository requestRepository, int interval, boolean listenToCloneModifications) { + + CMS.debug("In setCertStatusUpdateInterval " + interval); + + this.requestRepository = requestRepository; + + if (interval == 0) { + CMS.debug("In setCertStatusUpdateInterval interval = 0"); + if (certStatusUpdateTask != null) { + certStatusUpdateTask.stop(); + } + if (retrieveModificationsTask != null) { + retrieveModificationsTask.stop(); + } + return; + } + + CMS.debug("In setCertStatusUpdateInterval listenToCloneModifications=" + listenToCloneModifications); + + if (listenToCloneModifications) { + CMS.debug("In setCertStatusUpdateInterval listening to modifications"); + try { + retrieveModificationsTask = new RetrieveModificationsTask(this); + retrieveModificationsTask.start(); + } catch (EBaseException e) { + retrieveModificationsTask = null; + e.printStackTrace(); + } + } + + CMS.debug("In setCertStatusUpdateInterval scheduling cert status update every " + interval + " seconds."); + certStatusUpdateTask = new CertStatusUpdateTask(this, interval); + certStatusUpdateTask.start(); + } + + /** + * This method blocks when another thread (such as the CRL Update) is running + */ + public synchronized void updateCertStatus() { + + CMS.debug("In updateCertStatus()"); + + try { + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_START_VALID_SEARCH")); + transitInvalidCertificates(); + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_FINISH_VALID_SEARCH")); + + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_START_EXPIRED_SEARCH")); + transitValidCertificates(); + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_FINISH_EXPIRED_SEARCH")); + + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_START_REVOKED_EXPIRED_SEARCH")); + transitRevokedExpiredCertificates(); + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + CMS.getLogMessage("CMSCORE_DBS_FINISH_REVOKED_EXPIRED_SEARCH")); + + CMS.debug("Starting cert checkRanges"); + checkRanges(); + CMS.debug("cert checkRanges done"); + + CMS.debug("Starting request checkRanges"); + requestRepository.checkRanges(); + CMS.debug("request checkRanges done"); + + } catch (Exception e) { + CMS.debug("updateCertStatus done: " + e.toString()); + } + } + + public synchronized void processRevokedCerts(IElementProcessor p, String filter, int pageSize) + throws EBaseException { + + CMS.debug("Starting processRevokedCerts (entered lock)"); + ICertRecordList list = findCertRecordsInList(filter, + new String[] { ICertRecord.ATTR_ID, ICertRecord.ATTR_REVO_INFO, "objectclass" }, + "serialno", + pageSize); + + int totalSize = list.getSize(); + + list.processCertRecords(0, totalSize - 1, p); + CMS.debug("processRevokedCerts done"); + } + + /** + * Retrieves DN of this repository. + */ + public String getDN() { + return mBaseDN; + } + + public void setRequestDN(String requestDN) { + mRequestBaseDN = requestDN; + } + + public String getRequestDN() { + return mRequestBaseDN; + } + + /** + * Retrieves backend database handle. + */ + public IDBSubsystem getDBSubsystem() { + return mDBService; + } + + /** + * Adds a certificate record to the repository. Each certificate + * record contains four parts: certificate, meta-attributes, + * issue information and reovcation information. + *

+ * + * @param cert X.509 certificate + * @exception EBaseException failed to add new certificate to + * the repository + */ + public void addCertificateRecord(ICertRecord record) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + ((CertRecord) record).getSerialNumber().toString() + "," + getDN(); + SessionContext ctx = SessionContext.getContext(); + String uid = (String) ctx.get(SessionContext.USER_ID); + + if (uid == null) { + // XXX is this right? + record.set(CertRecord.ATTR_ISSUED_BY, "system"); + + /** + * System.out.println("XXX servlet should set USER_ID"); + * throw new EBaseException(BaseResources.UNKNOWN_PRINCIPAL_1, + * "null"); + **/ + } else { + record.set(CertRecord.ATTR_ISSUED_BY, uid); + } + + // Check validity of this certificate. If it is not invalid, + // mark it so. We will have a thread to transit the status + // from INVALID to VALID. + X509CertImpl x509cert = (X509CertImpl) record.get( + CertRecord.ATTR_X509CERT); + + if (x509cert != null) { + Date now = CMS.getCurrentDate(); + + if (x509cert.getNotBefore().after(now)) { + // not yet valid + record.set(ICertRecord.ATTR_CERT_STATUS, + ICertRecord.STATUS_INVALID); + } + } + + s.add(name, record); + } finally { + if (s != null) + s.close(); + } + } + + /** + * Used by the Clone Master (CLA) to add a revoked certificate + * record to the repository. + *

+ * + * @param record a CertRecord + * @exception EBaseException failed to add new certificate to + * the repository + */ + public void addRevokedCertRecord(CertRecord record) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + record.getSerialNumber().toString() + "," + getDN(); + + s.add(name, record); + } finally { + if (s != null) + s.close(); + } + } + + /** + * This transits a certificate status from VALID to EXPIRED + * if a certificate becomes expired. + */ + public void transitValidCertificates() throws EBaseException { + + Date now = CMS.getCurrentDate(); + ICertRecordList recList = getValidCertsByNotAfterDate(now, -1 * mTransitRecordPageSize); + + int size = recList.getSize(); + + if (size <= 0) { + CMS.debug("index may be empty"); + return; + } + int ltSize = recList.getSizeBeforeJumpTo(); + + ltSize = Math.min(ltSize, mTransitMaxRecords); + + Vector cList = new Vector(ltSize); + + CMS.debug("transidValidCertificates: list size: " + size); + CMS.debug("transitValidCertificates: ltSize " + ltSize); + + CertRecord curRec = null; + + int i; + ICertRecord obj = null; + + for (i = 0; i < ltSize; i++) { + obj = recList.getCertRecord(i); + + if (obj != null) { + curRec = (CertRecord) obj; + + Date notAfter = curRec.getNotAfter(); + + //CMS.debug("notAfter " + notAfter.toString() + " now " + now.toString()); + if (notAfter.after(now)) { + CMS.debug("Record does not qualify,notAfter " + notAfter.toString() + " date " + now.toString()); + continue; + } + + CMS.debug("transitValid: curRec: " + i + " " + curRec.toString()); + + if (mConsistencyCheck) { + cList.add(curRec); + } else { + cList.add(curRec.getSerialNumber()); + } + } else { + CMS.debug("found null from getCertRecord"); + } + } + + transitCertList(cList, CertRecord.STATUS_EXPIRED); + } + + /** + * This transits a certificate status from REVOKED to REVOKED_EXPIRED + * if an revoked certificate becomes expired. + */ + public void transitRevokedExpiredCertificates() throws EBaseException { + Date now = CMS.getCurrentDate(); + ICertRecordList recList = getRevokedCertsByNotAfterDate(now, -1 * mTransitRecordPageSize); + + int size = recList.getSize(); + + if (size <= 0) { + CMS.debug("index may be empty"); + return; + } + + int ltSize = recList.getSizeBeforeJumpTo(); + Vector cList = new Vector(ltSize); + + ltSize = Math.min(ltSize, mTransitMaxRecords); + + CMS.debug("transitRevokedExpiredCertificates: list size: " + size); + CMS.debug("transitRevokedExpiredCertificates: ltSize " + ltSize); + + CertRecord curRec = null; + int i; + Object obj = null; + + for (i = 0; i < ltSize; i++) { + obj = recList.getCertRecord(i); + if (obj != null) { + curRec = (CertRecord) obj; + CMS.debug("transitRevokedExpired: curRec: " + i + " " + curRec.toString()); + + Date notAfter = curRec.getNotAfter(); + + // CMS.debug("notAfter " + notAfter.toString() + " now " + now.toString()); + if (notAfter.after(now)) { + CMS.debug("Record does not qualify,notAfter " + notAfter.toString() + " date " + now.toString()); + continue; + } + + if (mConsistencyCheck) { + cList.add(curRec); + } else { + cList.add(curRec.getSerialNumber()); + } + } else { + CMS.debug("found null record in getCertRecord"); + } + } + + transitCertList(cList, CertRecord.STATUS_REVOKED_EXPIRED); + + } + + /** + * This transits a certificate status from INVALID to VALID + * if a certificate becomes valid. + */ + public void transitInvalidCertificates() throws EBaseException { + + Date now = CMS.getCurrentDate(); + + ICertRecordList recList = getInvalidCertsByNotBeforeDate(now, -1 * mTransitRecordPageSize); + + int size = recList.getSize(); + + if (size <= 0) { + CMS.debug("index may be empty"); + return; + } + int ltSize = recList.getSizeBeforeJumpTo(); + + ltSize = Math.min(ltSize, mTransitMaxRecords); + + Vector cList = new Vector(ltSize); + + CMS.debug("transidInValidCertificates: list size: " + size); + CMS.debug("transitInValidCertificates: ltSize " + ltSize); + + CertRecord curRec = null; + + int i; + + Object obj = null; + + for (i = 0; i < ltSize; i++) { + obj = recList.getCertRecord(i); + + if (obj != null) { + curRec = (CertRecord) obj; + + Date notBefore = curRec.getNotBefore(); + + //CMS.debug("notBefore " + notBefore.toString() + " now " + now.toString()); + if (notBefore.after(now)) { + CMS.debug("Record does not qualify,notBefore " + notBefore.toString() + " date " + now.toString()); + continue; + + } + CMS.debug("transitInValid: curRec: " + i + " " + curRec.toString()); + + if (mConsistencyCheck) { + cList.add(curRec); + } else { + cList.add(curRec.getSerialNumber()); + } + + } else { + CMS.debug("found null from getCertRecord"); + } + } + + transitCertList(cList, CertRecord.STATUS_VALID); + + } + + private void transitCertList(Vector cList, String newCertStatus) throws EBaseException { + CertRecord cRec = null; + BigInteger serial = null; + + int i; + + CMS.debug("transitCertList " + newCertStatus); + + for (i = 0; i < cList.size(); i++) { + if (mConsistencyCheck) { + cRec = (CertRecord) cList.elementAt(i); + + if (cRec == null) + continue; + + serial = cRec.getSerialNumber(); + } else { + serial = (BigInteger) cList.elementAt(i); + } + + updateStatus(serial, newCertStatus); + + if (newCertStatus.equals(CertRecord.STATUS_REVOKED_EXPIRED)) { + + // inform all CRLIssuingPoints about revoked and expired certificate + + Enumeration eIPs = mCRLIssuingPoints.elements(); + + while (eIPs.hasMoreElements()) { + ICRLIssuingPoint ip = eIPs.nextElement(); + + if (ip != null) { + ip.addExpiredCert(serial); + } + } + + } + + CMS.debug("transitCertList number at: " + i + " = " + serial); + } + + cList.removeAllElements(); + } + + /** + * Reads the certificate identified by the given serial no. + */ + public X509CertImpl getX509Certificate(BigInteger serialNo) + throws EBaseException { + ICertRecord cr = readCertificateRecord(serialNo); + + return (cr.getCertificate()); + } + + /** + * Deletes certificate record. + */ + public void deleteCertificateRecord(BigInteger serialNo) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + s.delete(name); + } finally { + if (s != null) + s.close(); + } + } + + /** + * Reads certificate from repository. + */ + public ICertRecord readCertificateRecord(BigInteger serialNo) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + CertRecord rec = null; + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + rec = (CertRecord) s.read(name); + } finally { + if (s != null) + s.close(); + } + return rec; + } + + public synchronized void modifyCertificateRecord(BigInteger serialNo, + ModificationSet mods) throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + mods.add(CertRecord.ATTR_MODIFY_TIME, Modification.MOD_REPLACE, + CMS.getCurrentDate()); + s.modify(name, mods); + } finally { + if (s != null) + s.close(); + } + } + + /** + * Checks if the specified certificate is in the repository. + */ + public boolean containsCertificate(BigInteger serialNo) + throws EBaseException { + try { + ICertRecord cr = readCertificateRecord(serialNo); + + if (cr != null) + return true; + } catch (EBaseException e) { + } + return false; + } + + /** + * Marks certificate as revoked. + */ + public void markAsRevoked(BigInteger id, IRevocationInfo info) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_ADD, info); + SessionContext ctx = SessionContext.getContext(); + String uid = (String) ctx.get(SessionContext.USER_ID); + + if (uid == null) { + mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_ADD, + "system"); + } else { + mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_ADD, + uid); + } + mods.add(CertRecord.ATTR_REVOKED_ON, Modification.MOD_ADD, + CMS.getCurrentDate()); + mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE, + CertRecord.STATUS_REVOKED); + modifyCertificateRecord(id, mods); + } + + /** + * Unmarks revoked certificate. + */ + public void unmarkRevoked(BigInteger id, IRevocationInfo info, + Date revokedOn, String revokedBy) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + mods.add(CertRecord.ATTR_REVO_INFO, Modification.MOD_DELETE, info); + mods.add(CertRecord.ATTR_REVOKED_BY, Modification.MOD_DELETE, revokedBy); + mods.add(CertRecord.ATTR_REVOKED_ON, Modification.MOD_DELETE, revokedOn); + mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE, + CertRecord.STATUS_VALID); + modifyCertificateRecord(id, mods); + } + + /** + * Updates the certificiate record status to the specified. + */ + public void updateStatus(BigInteger id, String status) + throws EBaseException { + CMS.debug("updateStatus: " + id + " status " + status); + ModificationSet mods = new ModificationSet(); + + mods.add(CertRecord.ATTR_CERT_STATUS, Modification.MOD_REPLACE, + status); + modifyCertificateRecord(id, mods); + } + + public Enumeration searchCertificates(String filter, int maxSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + CMS.debug("searchCertificates filter " + filter + " maxSize " + maxSize); + try { + e = s.search(getDN(), filter, maxSize); + } finally { + if (s != null) + s.close(); + } + return e; + } + + public Enumeration searchCertificates(String filter, int maxSize, int timeLimit) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Vector v = new Vector(); + + CMS.debug("searchCertificateswith time limit filter " + filter); + try { + IDBSearchResults sr = s.search(getDN(), filter, maxSize, timeLimit); + while (sr.hasMoreElements()) { + v.add((ICertRecord) sr.nextElement()); + } + } finally { + if (s != null) + s.close(); + } + return v.elements(); + } + + /** + * Returns a list of X509CertImp that satisfies the filter. + * + * @deprecated replaced by findCertificatesInList + */ + public Enumeration findCertRecs(String filter) + throws EBaseException { + CMS.debug("findCertRecs " + filter); + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + try { + e = s.search(getDN(), filter); + } finally { + if (s != null) + s.close(); + } + return e; + } + + public Enumeration findCertRecs(String filter, String[] attrs) + throws EBaseException { + + CMS.debug("findCertRecs " + filter + + "attrs " + Arrays.toString(attrs)); + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + try { + e = s.search(getDN(), filter, attrs); + } finally { + if (s != null) + s.close(); + } + return e; + + } + + public Enumeration findCertificates(String filter) + throws EBaseException { + Enumeration e = findCertRecords(filter); + Vector v = new Vector(); + + while (e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + + v.addElement(rec.getCertificate()); + } + return v.elements(); + } + + /** + * Finds a list of certificate records that satisifies + * the filter. + * If you are going to process everything in the list, + * use this. + */ + public Enumeration findCertRecords(String filter) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + //e = s.search(getDN(), filter); + ICertRecordList list = null; + + list = findCertRecordsInList(filter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * Finds certificate records. Here is a list of filter + * attribute can be used: + * + *
+     *   certRecordId
+     *   certMetaInfo
+     *   certStatus
+     *   certCreateTime
+     *   certModifyTime
+     *   x509Cert.notBefore
+     *   x509Cert.notAfter
+     *   x509Cert.subject
+     * 
+ * + * The filter should follow RFC1558 LDAP filter syntax. + * For example, + * + *
+     *   (&(certRecordId=5)(x509Cert.notBefore=934398398))
+     * 
+ */ + public ICertRecordList findCertRecordsInList(String filter, + String attrs[], int pageSize) throws EBaseException { + return findCertRecordsInList(filter, attrs, CertRecord.ATTR_ID, + pageSize); + } + + public ICertRecordList findCertRecordsInList(String filter, + String attrs[], String sortKey, int pageSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + CMS.debug("In findCertRecordsInList"); + CertRecordList list = null; + + try { + IDBVirtualList vlist = s.createVirtualList(getDN(), filter, attrs, + sortKey, pageSize); + + list = new CertRecordList(vlist); + } finally { + if (s != null) + s.close(); + } + return list; + } + + public ICertRecordList findCertRecordsInList(String filter, + String attrs[], String jumpTo, String sortKey, int pageSize) + throws EBaseException { + return findCertRecordsInList(filter, attrs, jumpTo, false, sortKey, pageSize); + + } + + public ICertRecordList findCertRecordsInList(String filter, + String attrs[], String jumpTo, boolean hardJumpTo, + String sortKey, int pageSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + CertRecordList list = null; + + CMS.debug("In findCertRecordsInList with Jumpto " + jumpTo); + try { + String jumpToVal = null; + + if (hardJumpTo) { + CMS.debug("In findCertRecordsInList with hardJumpto "); + jumpToVal = "99"; + } else { + int len = jumpTo.length(); + + if (len > 9) { + jumpToVal = Integer.toString(len) + jumpTo; + } else { + jumpToVal = "0" + Integer.toString(len) + jumpTo; + } + } + + IDBVirtualList vlist = s.createVirtualList(getDN(), filter, + attrs, jumpToVal, sortKey, pageSize); + + list = new CertRecordList(vlist); + } finally { + if (s != null) + s.close(); + } + return list; + } + + public ICertRecordList findCertRecordsInListRawJumpto(String filter, + String attrs[], String jumpTo, String sortKey, int pageSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + CertRecordList list = null; + + CMS.debug("In findCertRecordsInListRawJumpto with Jumpto " + jumpTo); + + try { + + IDBVirtualList vlist = s.createVirtualList(getDN(), filter, + attrs, jumpTo, sortKey, pageSize); + + list = new CertRecordList(vlist); + } finally { + if (s != null) + s.close(); + } + return list; + } + + /** + * Marks certificate as renewable. + */ + public void markCertificateAsRenewable(ICertRecord record) + throws EBaseException { + changeRenewalAttribute(((CertRecord) record).getSerialNumber().toString(), + CertRecord.AUTO_RENEWAL_ENABLED); + } + + /** + * Marks certificate as renewable. + */ + public void markCertificateAsNotRenewable(ICertRecord record) + throws EBaseException { + changeRenewalAttribute(((CertRecord) record).getSerialNumber().toString(), + CertRecord.AUTO_RENEWAL_DISABLED); + } + + public void markCertificateAsRenewed(String serialNo) + throws EBaseException { + changeRenewalAttribute(serialNo, CertRecord.AUTO_RENEWAL_DONE); + } + + public void markCertificateAsRenewalNotified(String serialNo) + throws EBaseException { + changeRenewalAttribute(serialNo, CertRecord.AUTO_RENEWAL_NOTIFIED); + } + + private void changeRenewalAttribute(String serialno, String value) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + serialno + + "," + getDN(); + ModificationSet mods = new ModificationSet(); + + mods.add(CertRecord.ATTR_AUTO_RENEW, Modification.MOD_REPLACE, + value); + s.modify(name, mods); + } finally { + if (s != null) + s.close(); + } + } + + /** + * temp solution... + */ + public class RenewableCertificateCollection { + Vector mToRenew = null; + Vector mToNotify = null; + + public RenewableCertificateCollection() { + } + + public Vector getRenewable() { + return mToRenew; + } + + public Vector getNotifiable() { + return mToNotify; + } + + public void addCertificate(String renewalFlag, Object o) { + if (renewalFlag.equals(CertRecord.AUTO_RENEWAL_ENABLED)) { + if (mToRenew == null) + mToRenew = new Vector(); + mToRenew.addElement(o); + } + if (renewalFlag.equals(CertRecord.AUTO_RENEWAL_DISABLED)) { + if (mToNotify == null) + mToNotify = new Vector(); + mToNotify.addElement(o); + } + } + } + + public Hashtable getRenewableCertificates(String renewalTime) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + Hashtable tab = null; + + try { + String filter = "(&(" + CertRecord.ATTR_CERT_STATUS + "=" + + CertRecord.STATUS_VALID + ")(" + + CertRecord.ATTR_X509CERT + + "." + CertificateValidity.NOT_AFTER + "<=" + renewalTime + + ")(!(" + CertRecord.ATTR_AUTO_RENEW + "=" + + CertRecord.AUTO_RENEWAL_DONE + + "))(!(" + CertRecord.ATTR_AUTO_RENEW + "=" + + CertRecord.AUTO_RENEWAL_NOTIFIED + ")))"; + //Enumeration e = s.search(getDN(), filter); + ICertRecordList list = null; + + list = findCertRecordsInList(filter, null, "serialno", 10); + int size = list.getSize(); + Enumeration e = list.getCertRecords(0, size - 1); + + tab = new Hashtable(); + while (e.hasMoreElements()) { + CertRecord rec = (CertRecord) e.nextElement(); + X509CertImpl cert = rec.getCertificate(); + String subjectDN = cert.getSubjectDN().toString(); + String renewalFlag = rec.getAutoRenew(); + + // See if the subjectDN is in the table + Object val = null; + + if ((val = tab.get(subjectDN)) == null) { + RenewableCertificateCollection collection = + new RenewableCertificateCollection(); + + collection.addCertificate(renewalFlag, cert); + tab.put(subjectDN, collection); + } else { + ((RenewableCertificateCollection) val).addCertificate(renewalFlag, cert); + } + } + } finally { + if (s != null) + s.close(); + } + return tab; + } + + /** + * Gets all valid and unexpired certificates pertaining + * to a subject DN. + * + * @param subjectDN The distinguished name of the subject. + * @param validityType The type of certificates to get. + * @return An array of certificates. + */ + + public X509CertImpl[] getX509Certificates(String subjectDN, + int validityType) throws EBaseException { + IDBSSession s = mDBService.createSession(); + + X509CertImpl certs[] = null; + + try { + // XXX - not checking validityType... + String filter = "(&(" + CertRecord.ATTR_X509CERT + + "." + X509CertInfo.SUBJECT + "=" + subjectDN; + + if (validityType == ALL_VALID_CERTS) { + filter += ")(" + + CertRecord.ATTR_CERT_STATUS + "=" + + CertRecord.STATUS_VALID; + } + if (validityType == ALL_UNREVOKED_CERTS) { + filter += ")(|(" + + CertRecord.ATTR_CERT_STATUS + "=" + + CertRecord.STATUS_VALID + ")(" + + CertRecord.ATTR_CERT_STATUS + "=" + + CertRecord.STATUS_EXPIRED + ")"; + } + filter += "))"; + + //Enumeration e = s.search(getDN(), filter); + ICertRecordList list = null; + + list = findCertRecordsInList(filter, null, "serialno", 10); + int size = list.getSize(); + Enumeration e = list.getCertRecords(0, size - 1); + + Vector v = new Vector(); + + while (e.hasMoreElements()) { + CertRecord rec = (CertRecord) e.nextElement(); + + v.addElement(rec.getCertificate()); + } + if (v.size() == 0) + return null; + certs = new X509CertImpl[v.size()]; + v.copyInto(certs); + } finally { + if (s != null) + s.close(); + } + return certs; + } + + public X509CertImpl[] getX509Certificates(String filter) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + X509CertImpl certs[] = null; + + try { + Enumeration e = null; + + if (filter != null && filter.length() > 0) { + //e = s.search(getDN(), filter); + ICertRecordList list = null; + + list = findCertRecordsInList(filter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } + + Vector v = new Vector(); + + while (e != null && e.hasMoreElements()) { + CertRecord rec = (CertRecord) e.nextElement(); + + v.addElement(rec.getCertificate()); + } + if (v.size() > 0) { + certs = new X509CertImpl[v.size()]; + v.copyInto(certs); + } + } finally { + if (s != null) + s.close(); + } + return certs; + } + + /** + * Retrives all valid certificates excluding ones already revoked. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getValidCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Vector v = new Vector(); + + try { + + // 'from' determines 'jumpto' value + // 'to' determines where to stop looking + + String ldapfilter = "(certstatus=VALID)"; + + String fromVal = "0"; + try { + if (from != null) { + Integer.parseInt(from); + fromVal = from; + } + } catch (Exception e1) { + // from is not integer + } + + ICertRecordList list = + findCertRecordsInList(ldapfilter, null, fromVal, "serialno", 40); + + BigInteger toInt = null; + if (to != null && !to.trim().equals("")) { + toInt = new BigInteger(to); + } + + for (int i = 0;; i++) { + CertRecord rec = (CertRecord) list.getCertRecord(i); + CMS.debug("processing record: " + i); + if (rec == null) { + break; // no element returned + } else { + + CMS.debug("processing record: " + i + " " + rec.getSerialNumber()); + // Check if we are past the 'to' marker + if (toInt != null) { + if (rec.getSerialNumber().compareTo(toInt) > 0) { + break; + } + } + v.addElement(rec); + } + } + + } finally { + if (s != null) + s.close(); + } + CMS.debug("returning " + v.size() + " elements"); + return v.elements(); + } + + /** + * Retrives all valid certificates excluding ones already revoked. + */ + public Enumeration getAllValidCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&(!(" + CertRecord.ATTR_REVO_INFO + "=*))(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_BEFORE + "<=" + + DateMapper.dateToDB(now) + ")(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + "))"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all valid not published certificates + * excluding ones already revoked. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getValidNotPublishedCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&("; + + if (from != null && from.length() > 0) + ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")("; + if (to != null && to.length() > 0) + ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")("; + ldapfilter += "!(" + CertRecord.ATTR_REVO_INFO + "=*))(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_BEFORE + "<=" + + DateMapper.dateToDB(now) + ")(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + ")(!(" + + "certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true)))"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all valid not published certificates + * excluding ones already revoked. + */ + public Enumeration getAllValidNotPublishedCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&(!(" + CertRecord.ATTR_REVO_INFO + "=*))(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_BEFORE + "<=" + + DateMapper.dateToDB(now) + ")(" + + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + ")(!(" + + "certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true)))"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all expired certificates. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getExpiredCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&("; + + if (from != null && from.length() > 0) + ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")("; + if (to != null && to.length() > 0) + ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")("; + ldapfilter += "!(" + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + ")))"; + //e = s.search(getDN(), ldapfilter); + + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all expired certificates. + */ + public Enumeration getAllExpiredCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(!(" + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + "))"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all expired published certificates. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getExpiredPublishedCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&("; + + if (from != null && from.length() > 0) + ldapfilter += CertRecord.ATTR_ID + ">=" + from + ")("; + if (to != null && to.length() > 0) + ldapfilter += CertRecord.ATTR_ID + "<=" + to + ")("; + ldapfilter += "!(" + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + //DateMapper.dateToDB(now) + ")))"; + DateMapper.dateToDB(now) + "))(" + + "certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true))"; + //e = s.search(getDN(), ldapfilter); + + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all expired publishedcertificates. + */ + public Enumeration getAllExpiredPublishedCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + Date now = CMS.getCurrentDate(); + String ldapfilter = "(&"; + + ldapfilter += "(!(" + CertRecord.ATTR_X509CERT + "." + + CertificateValidity.NOT_AFTER + ">=" + + DateMapper.dateToDB(now) + "))"; + ldapfilter += "(certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true))"; + + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + public ICertRecordList getInvalidCertsByNotBeforeDate(Date date, int pageSize) + throws EBaseException { + + ICertRecordList list = null; + IDBSSession s = mDBService.createSession(); + + try { + String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_INVALID + ")"; + + String[] attrs = null; + + if (mConsistencyCheck == false) { + attrs = new String[] { "objectclass", CertRecord.ATTR_ID, CertRecord.ATTR_X509CERT }; + } + + CMS.debug("getInvalidCertificatesByNotBeforeDate filter " + ldapfilter); + //e = s.search(getDN(), ldapfilter); + CMS.debug("getInvalidCertificatesByNotBeforeDate: about to call findCertRecordsInList"); + + list = findCertRecordsInListRawJumpto(ldapfilter, attrs, + DateMapper.dateToDB(date), "notBefore", pageSize); + + //e = list.getCertRecords(0, size - 1); + + } finally { + // XXX - transaction is not done at this moment + + CMS.debug("In getInvalidCertsByNotBeforeDate finally."); + + if (s != null) + s.close(); + } + return list; + + } + + public ICertRecordList getValidCertsByNotAfterDate(Date date, int pageSize) + throws EBaseException { + + ICertRecordList list = null; + IDBSSession s = mDBService.createSession(); + + try { + String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_VALID + ")"; + + String[] attrs = null; + + if (mConsistencyCheck == false) { + attrs = new String[] { "objectclass", CertRecord.ATTR_ID, CertRecord.ATTR_X509CERT }; + } + + CMS.debug("getValidCertsByNotAfterDate filter " + ldapfilter); + //e = s.search(getDN(), ldapfilter); + list = findCertRecordsInListRawJumpto(ldapfilter, attrs, DateMapper.dateToDB(date), "notAfter", pageSize); + + } finally { + // XXX - transaction is not done at this moment + + if (s != null) + s.close(); + } + return list; + } + + public ICertRecordList getRevokedCertsByNotAfterDate(Date date, int pageSize) + throws EBaseException { + + ICertRecordList list = null; + IDBSSession s = mDBService.createSession(); + + try { + String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")"; + + String[] attrs = null; + + if (mConsistencyCheck == false) { + attrs = new String[] { "objectclass", CertRecord.ATTR_REVOKED_ON, CertRecord.ATTR_ID, + CertRecord.ATTR_REVO_INFO, CertificateValidity.NOT_AFTER, CertRecord.ATTR_X509CERT }; + } + + CMS.debug("getRevokedCertificatesByNotAfterDate filter " + ldapfilter); + //e = s.search(getDN(), ldapfilter); + CMS.debug("getRevokedCertificatesByNotAfterDate: about to call findCertRecordsInList"); + + list = findCertRecordsInListRawJumpto(ldapfilter, attrs, + DateMapper.dateToDB(date), "notafter", pageSize); + + } finally { + // XXX - transaction is not done at this moment + + if (s != null) + s.close(); + } + return list; + + } + + /** + * Retrieves all revoked certificates in the serial number range. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getRevokedCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + String ldapfilter = "(&(" + CertRecord.ATTR_REVO_INFO + "=*)"; + + if (from != null && from.length() > 0) + ldapfilter += "(" + CertRecord.ATTR_ID + ">=" + from + ")"; + if (to != null && to.length() > 0) + ldapfilter += "(" + CertRecord.ATTR_ID + "<=" + to + ")"; + ldapfilter += ")"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all revoked certificates including ones already expired or + * not yet valid. + */ + public Enumeration getAllRevokedCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + // index is setup for this filter + String ldapfilter = "(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; + + try { + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrieves all revoked publishedcertificates in the serial number range. + * + * @param from The starting point of the serial number range. + * @param to The ending point of the serial number range. + */ + public Enumeration getRevokedPublishedCertificates(String from, String to) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + String ldapfilter = "(&(" + CertRecord.ATTR_REVO_INFO + "=*)"; + + if (from != null && from.length() > 0) + ldapfilter += "(" + CertRecord.ATTR_ID + ">=" + from + ")"; + if (to != null && to.length() > 0) + ldapfilter += "(" + CertRecord.ATTR_ID + "<=" + to + ")"; + //ldapfilter += ")"; + ldapfilter += "(certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true))"; + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all revoked published certificates including ones + * already expired or not yet valid. + */ + public Enumeration getAllRevokedPublishedCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + // index is setup for this filter + String ldapfilter = "(&(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; + + ldapfilter += "(certMetainfo=" + + CertRecord.META_LDAPPUBLISH + + ":true))"; + try { + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrieves all revoked certificates that have not expired. + */ + public Enumeration getRevokedCertificates(Date asOfDate) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + + /*e = s.search(getDN(), "(&(" + + CertRecord.ATTR_REVO_INFO + "=*)(" + CertRecord.ATTR_X509CERT + + "." + CertificateValidity.NOT_AFTER + " >= " + + DateMapper.dateToDB(asOfDate) + "))");*/ + String ldapfilter = "(&(" + + CertRecord.ATTR_REVO_INFO + "=*)(" + CertRecord.ATTR_X509CERT + + "." + CertificateValidity.NOT_AFTER + " >= " + + DateMapper.dateToDB(asOfDate) + "))"; + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + // XXX - transaction is not done at this moment + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrives all revoked certificates excluing ones already expired. + */ + public Enumeration getAllRevokedNonExpiredCertificates() + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + String ldapfilter = "(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")"; // index is setup for this filter + + try { + //e = s.search(getDN(), ldapfilter); + ICertRecordList list = null; + + list = findCertRecordsInList(ldapfilter, null, "serialno", 10); + int size = list.getSize(); + + e = list.getCertRecords(0, size - 1); + } finally { + if (s != null) + s.close(); + } + return e; + } + + LDAPSearchResults searchForModifiedCertificateRecords(IDBSSession session) { + CMS.debug("searchForModifiedCertificateRecords"); + LDAPSearchResults results = null; + + String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*)"; + try { + results = session.persistentSearch(getDN(), filter, null); + + } catch (Exception e) { + CMS.debug("startSearchForModifiedCertificateRecords persistentSearch Exception=" + e); + } + + return results; + } + + public void getModifications(LDAPEntry entry) { + if (entry != null) { + CMS.debug("getModifications entry DN=" + entry.getDN()); + + LDAPAttributeSet entryAttrs = entry.getAttributeSet(); + ICertRecord certRec = null; + try { + certRec = (ICertRecord) mDBService.getRegistry().createObject(entryAttrs); + } catch (Exception e) { + } + if (certRec != null) { + String status = certRec.getStatus(); + CMS.debug("getModifications serialNumber=" + certRec.getSerialNumber() + + " status=" + status); + if (status != null && (status.equals(ICertRecord.STATUS_VALID) || + status.equals(ICertRecord.STATUS_REVOKED))) { + + Enumeration eIPs = mCRLIssuingPoints.elements(); + + while (eIPs.hasMoreElements()) { + ICRLIssuingPoint ip = eIPs.nextElement(); + + if (ip != null) { + if (status.equals(ICertRecord.STATUS_REVOKED)) { + IRevocationInfo rInfo = certRec.getRevocationInfo(); + if (rInfo != null) { + ip.addRevokedCert(certRec.getSerialNumber(), + new RevokedCertImpl(certRec.getSerialNumber(), + rInfo.getRevocationDate(), + rInfo.getCRLEntryExtensions())); + } + } else { + ip.addUnrevokedCert(certRec.getSerialNumber()); + } + } + } + + } + } + } else { + CMS.debug("getModifications entry == null"); + } + } + + /** + * Checks if the presented certificate belongs to the repository + * and is revoked. + * + * @param cert certificate to verify. + * @return RevocationInfo if the presented certificate is revoked otherwise null. + */ + public RevocationInfo isCertificateRevoked(X509CertImpl cert) + throws EBaseException { + RevocationInfo info = null; + + // 615932 + if (cert == null) + return null; + + ICertRecord rec = readCertificateRecord(cert.getSerialNumber()); + + if (rec != null) { + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + X500Name name = (X500Name) cert.getSubjectDN(); + X500Name repCertName = (X500Name) rec.getCertificate().getSubjectDN(); + + if (name.equals(repCertName)) { + byte[] certEncoded = null; + byte[] repCertEncoded = null; + + try { + certEncoded = cert.getEncoded(); + repCertEncoded = rec.getCertificate().getEncoded(); + } catch (Exception e) { + } + + if (certEncoded != null && + repCertEncoded != null && + certEncoded.length == repCertEncoded.length) { + int i; + + for (i = 0; i < certEncoded.length; i++) { + if (certEncoded[i] != repCertEncoded[i]) + break; + } + if (i >= certEncoded.length) { + info = (RevocationInfo) ((CertRecord) rec).getRevocationInfo(); + } + } + } + } + } + + return info; + } + + public void shutdown() { + if (certStatusUpdateTask != null) { + certStatusUpdateTask.stop(); + } + + if (retrieveModificationsTask != null) { + retrieveModificationsTask.stop(); + } + } +} + +class CertStatusUpdateTask implements Runnable { + + CertificateRepository repository; + int interval; + + ScheduledExecutorService executorService; + + public CertStatusUpdateTask(CertificateRepository repository, int interval) { + this.repository = repository; + this.interval = interval; + } + + public void start() { + // schedule task to run immediately and repeat after specified interval + executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + return new Thread(r, "CertStatusUpdateTask"); + } + }); + executorService.scheduleWithFixedDelay(this, 0, interval, TimeUnit.SECONDS); + } + + public void run() { + repository.updateCertStatus(); + } + + public void stop() { + // shutdown executorService without interrupting running task + if (executorService != null) executorService.shutdown(); + } +} + +class RetrieveModificationsTask implements Runnable { + + CertificateRepository repository; + + IDBSSession session; + LDAPSearchResults results; + + ScheduledExecutorService executorService; + + public RetrieveModificationsTask(CertificateRepository repository) { + this.repository = repository; + } + + public void start() throws EBaseException { + // start persistent search + try { + session = repository.getDBSubsystem().createSession(); + results = repository.searchForModifiedCertificateRecords(session); + } catch (EBaseException e) { + stop(); // avoid leaks + throw e; + } + + // schedule task to run immediately and repeat without delay + executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + return new Thread(r, "RetrieveModificationsTask"); + } + }); + executorService.scheduleWithFixedDelay(this, 0, 1, TimeUnit.MICROSECONDS); + } + + public void run() { + CMS.debug("Inside run method of RetrieveModificationsThread"); + + try { + // results.hasMoreElements() will block until next element becomes available + // or return false if the search is abandoned or connection is closed + if (results.hasMoreElements()) { + LDAPEntry entry = results.next(); + repository.getModifications(entry); + } + } catch (Exception e) { + CMS.debug("Exception: " + e.toString()); + } + CMS.debug("Done with run method of RetrieveModificationsThread"); + } + + public void stop() { + if (executorService != null) executorService.shutdown(); + + if (session != null) { + // closing the session doesn't actually close the connection, + // so the search needs to be abandoned explicitly + if (results != null) try { session.abandon(results); } catch (Exception e) { e.printStackTrace(); } + + // close session + try { session.close(); } catch (Exception e) { e.printStackTrace(); } + } + } +} -- cgit