From a4682ceae6774956461edd03b2485bbacea445f4 Mon Sep 17 00:00:00 2001 From: mharmsen Date: Tue, 4 Oct 2011 01:17:41 +0000 Subject: Bugzilla Bug #688225 - (dogtagIPAv2.1) TRACKER: of the Dogtag fixes for freeIPA 2.1 git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/IPA_v2_RHEL_6_2_20111003@2252 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- .../com/netscape/cmscore/dbs/BigIntegerMapper.java | 118 ++ .../com/netscape/cmscore/dbs/ByteArrayMapper.java | 93 + .../src/com/netscape/cmscore/dbs/CRLDBSchema.java | 57 + .../cmscore/dbs/CRLIssuingPointRecord.java | 325 ++++ .../com/netscape/cmscore/dbs/CRLRepository.java | 365 ++++ .../src/com/netscape/cmscore/dbs/CertDBSchema.java | 64 + .../src/com/netscape/cmscore/dbs/CertRecord.java | 278 +++ .../com/netscape/cmscore/dbs/CertRecordList.java | 118 ++ .../com/netscape/cmscore/dbs/CertRecordMapper.java | 98 + .../cmscore/dbs/CertificateRepository.java | 1985 ++++++++++++++++++++ .../src/com/netscape/cmscore/dbs/DBRegistry.java | 553 ++++++ .../src/com/netscape/cmscore/dbs/DBSSession.java | 447 +++++ .../src/com/netscape/cmscore/dbs/DBSUtil.java | 56 + .../com/netscape/cmscore/dbs/DBSearchResults.java | 92 + .../src/com/netscape/cmscore/dbs/DBSubsystem.java | 951 ++++++++++ .../com/netscape/cmscore/dbs/DBVirtualList.java | 769 ++++++++ .../com/netscape/cmscore/dbs/DateArrayMapper.java | 105 ++ .../src/com/netscape/cmscore/dbs/DateMapper.java | 108 ++ .../com/netscape/cmscore/dbs/IntegerMapper.java | 86 + .../src/com/netscape/cmscore/dbs/KeyDBSchema.java | 58 + .../src/com/netscape/cmscore/dbs/KeyRecord.java | 348 ++++ .../com/netscape/cmscore/dbs/KeyRecordList.java | 93 + .../com/netscape/cmscore/dbs/KeyRecordMapper.java | 111 ++ .../com/netscape/cmscore/dbs/KeyRepository.java | 553 ++++++ .../com/netscape/cmscore/dbs/KeyStateMapper.java | 80 + .../netscape/cmscore/dbs/LdapFilterConverter.java | 61 + .../src/com/netscape/cmscore/dbs/LongMapper.java | 117 ++ .../com/netscape/cmscore/dbs/MetaInfoMapper.java | 119 ++ .../netscape/cmscore/dbs/ObjectStreamMapper.java | 135 ++ .../com/netscape/cmscore/dbs/PublicKeyMapper.java | 150 ++ .../netscape/cmscore/dbs/ReplicaIDRepository.java | 82 + .../src/com/netscape/cmscore/dbs/Repository.java | 504 +++++ .../com/netscape/cmscore/dbs/RepositoryRecord.java | 112 ++ .../com/netscape/cmscore/dbs/RepositorySchema.java | 44 + .../com/netscape/cmscore/dbs/RevocationInfo.java | 81 + .../netscape/cmscore/dbs/RevocationInfoMapper.java | 167 ++ .../src/com/netscape/cmscore/dbs/StringMapper.java | 91 + .../netscape/cmscore/dbs/StringVectorMapper.java | 106 ++ .../com/netscape/cmscore/dbs/X500NameMapper.java | 107 ++ .../netscape/cmscore/dbs/X509CertImplMapper.java | 363 ++++ 40 files changed, 10150 insertions(+) create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CertRecordMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/Repository.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java create mode 100644 pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java (limited to 'pki/base/common/src/com/netscape/cmscore/dbs') diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java new file mode 100644 index 000000000..c0afbe742 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/BigIntegerMapper.java @@ -0,0 +1,118 @@ +// --- 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.util.*; +import java.math.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java BigInteger object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class BigIntegerMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs BigInteger mapper. + */ + public BigIntegerMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Returns a list of supported ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object into ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + BigIntegerToDB((BigInteger) obj))); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + parent.set(name, BigIntegerFromDB( + (String) attr.getStringValues().nextElement())); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + String v = null; + + try { + if (value.startsWith("0x") || value.startsWith("0X")) { + v = BigIntegerToDB(new + BigInteger(value.substring(2), 16)); + } else { + v = BigIntegerToDB(new BigInteger(value)); + } + } catch (NumberFormatException e) { + v = value; + } + return mLdapName + op + v; + } + + public static String BigIntegerToDB(BigInteger i) { + int len = i.toString().length(); + String ret = null; + + if (len < 10) { + ret = "0" + Integer.toString(len) + i.toString(); + } else { + ret = Integer.toString(len) + i.toString(); + } + return ret; + } + + public static BigInteger BigIntegerFromDB(String i) { + String s = i.substring(2); + + // possibly check length + return new BigInteger(s); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java new file mode 100644 index 000000000..fcb806bb5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/ByteArrayMapper.java @@ -0,0 +1,93 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java byte array object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class ByteArrayMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs a byte array mapper. + */ + public ByteArrayMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Lists a list of supported ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + byte data[] = (byte[]) obj; + if (data == null) { + CMS.debug("ByteArrayMapper:mapObjectToLDAPAttributeSet " + name + + " size=0"); + } else { + CMS.debug("ByteArrayMapper:mapObjectToLDAPAttributeSet " + name + + " size=" + data.length); + } + attrs.add(new LDAPAttribute(mLdapName, data)); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + parent.set(name, (byte[]) attr.getByteValues().nextElement()); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java new file mode 100644 index 000000000..ad065f924 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLDBSchema.java @@ -0,0 +1,57 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a collection of schema information + * for CRL. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CRLDBSchema { + + public static final String LDAP_OC_TOP = "top"; + public static final String LDAP_OC_CRL_RECORD = "crlIssuingPointRecord"; + public static final String LDAP_ATTR_CRL_ID = "cn"; + public static final String LDAP_ATTR_CRL_NUMBER = "crlNumber"; + public static final String LDAP_ATTR_DELTA_NUMBER = "deltaNumber"; + public static final String LDAP_ATTR_CRL_SIZE = "crlSize"; + public static final String LDAP_ATTR_DELTA_SIZE = "deltaSize"; + public static final String LDAP_ATTR_THIS_UPDATE = "thisUpdate"; + public static final String LDAP_ATTR_NEXT_UPDATE = "nextUpdate"; + public static final String LDAP_ATTR_FIRST_UNSAVED = "firstUnsaved"; + public static final String LDAP_ATTR_CRL = "certificateRevocationList"; + public static final String LDAP_ATTR_CA_CERT = "cACertificate"; + public static final String LDAP_ATTR_CRL_CACHE = "crlCache"; + public static final String LDAP_ATTR_REVOKED_CERTS = "revokedCerts"; + public static final String LDAP_ATTR_UNREVOKED_CERTS = "unrevokedCerts"; + public static final String LDAP_ATTR_EXPIRED_CERTS = "expiredCerts"; + public static final String LDAP_ATTR_DELTA_CRL = "deltaRevocationList"; +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java new file mode 100644 index 000000000..8d7f19ca6 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLIssuingPointRecord.java @@ -0,0 +1,325 @@ +// --- 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.util.*; +import java.math.*; +import java.io.*; +import java.security.cert.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.crldb.*; + + +/** + * A class represents a CRL issuing point record. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CRLIssuingPointRecord implements ICRLIssuingPointRecord, IDBObj { + + protected String mId = null; // internal unique id + protected BigInteger mCRLNumber = null; // CRL number + protected Long mCRLSize = null; + protected Date mThisUpdate = null; + protected Date mNextUpdate = null; + protected BigInteger mDeltaCRLNumber = null; // delta CRL number + protected Long mDeltaCRLSize = null; + protected String mFirstUnsaved = null; + protected byte mCRL[] = null; + protected byte mCACert[] = null; + protected Hashtable mCRLCache = null; + protected Hashtable mRevokedCerts = null; + protected Hashtable mUnrevokedCerts = null; + protected Hashtable mExpiredCerts = null; + protected byte mDeltaCRL[] = null; + protected static Vector mNames = new Vector(); + static { + mNames.addElement(ATTR_ID); + mNames.addElement(ATTR_CRL_NUMBER); + mNames.addElement(ATTR_DELTA_NUMBER); + mNames.addElement(ATTR_CRL_SIZE); + mNames.addElement(ATTR_DELTA_SIZE); + mNames.addElement(ATTR_THIS_UPDATE); + mNames.addElement(ATTR_NEXT_UPDATE); + mNames.addElement(ATTR_FIRST_UNSAVED); + mNames.addElement(ATTR_CRL); + mNames.addElement(ATTR_CA_CERT); + mNames.addElement(ATTR_CRL_CACHE); + mNames.addElement(ATTR_REVOKED_CERTS); + mNames.addElement(ATTR_UNREVOKED_CERTS); + mNames.addElement(ATTR_EXPIRED_CERTS); + mNames.addElement(ATTR_DELTA_CRL); + } + + /** + * Constructs empty CRLIssuingPointRecord. This is + * required in database framework. + */ + public CRLIssuingPointRecord() { + } + + /** + * Constructs a CRLIssuingPointRecord + */ + public CRLIssuingPointRecord(String id, BigInteger crlNumber, Long crlSize, + Date thisUpdate, Date nextUpdate) { + mId = id; + mCRLNumber = crlNumber; + mCRLSize = crlSize; + mThisUpdate = thisUpdate; + mNextUpdate = nextUpdate; + mDeltaCRLNumber = BigInteger.ZERO; + mFirstUnsaved = NEW_CACHE; + mDeltaCRLSize = Long.valueOf(-1L); + mCRLCache = null; + mRevokedCerts = null; + mUnrevokedCerts = null; + mExpiredCerts = null; + } + + /** + * Constructs a CRLIssuingPointRecord + */ + public CRLIssuingPointRecord(String id, BigInteger crlNumber, Long crlSize, + Date thisUpdate, Date nextUpdate, BigInteger deltaCRLNumber, Long deltaCRLSize, + Hashtable revokedCerts, Hashtable unrevokedCerts, Hashtable expiredCerts) { + mId = id; + mCRLNumber = crlNumber; + mCRLSize = crlSize; + mThisUpdate = thisUpdate; + mNextUpdate = nextUpdate; + mDeltaCRLNumber = deltaCRLNumber; + mDeltaCRLSize = deltaCRLSize; + mFirstUnsaved = NEW_CACHE; + mCRLCache = null; + mRevokedCerts = revokedCerts; + mUnrevokedCerts = unrevokedCerts; + mExpiredCerts = expiredCerts; + } + + public void set(String name, Object obj) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_ID)) { + mId = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_CRL_NUMBER)) { + mCRLNumber = (BigInteger) obj; + } else if (name.equalsIgnoreCase(ATTR_CRL_SIZE)) { + mCRLSize = (Long) obj; + } else if (name.equalsIgnoreCase(ATTR_THIS_UPDATE)) { + mThisUpdate = (Date) obj; + } else if (name.equalsIgnoreCase(ATTR_NEXT_UPDATE)) { + mNextUpdate = (Date) obj; + } else if (name.equalsIgnoreCase(ATTR_DELTA_NUMBER)) { + mDeltaCRLNumber = (BigInteger) obj; + } else if (name.equalsIgnoreCase(ATTR_DELTA_SIZE)) { + mDeltaCRLSize = (Long) obj; + } else if (name.equalsIgnoreCase(ATTR_FIRST_UNSAVED)) { + mFirstUnsaved = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_CRL)) { + mCRL = (byte[]) obj; + } else if (name.equalsIgnoreCase(ATTR_CA_CERT)) { + mCACert = (byte[]) obj; + } else if (name.equalsIgnoreCase(ATTR_CRL_CACHE)) { + mCRLCache = (Hashtable) obj; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_CERTS)) { + mRevokedCerts = (Hashtable) obj; + } else if (name.equalsIgnoreCase(ATTR_UNREVOKED_CERTS)) { + mUnrevokedCerts = (Hashtable) obj; + } else if (name.equalsIgnoreCase(ATTR_EXPIRED_CERTS)) { + mExpiredCerts = (Hashtable) obj; + } else if (name.equalsIgnoreCase(ATTR_DELTA_CRL)) { + mDeltaCRL = (byte[]) obj; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + public Object get(String name) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_ID)) { + return mId; + } else if (name.equalsIgnoreCase(ATTR_CRL_NUMBER)) { + return mCRLNumber; + } else if (name.equalsIgnoreCase(ATTR_CRL_SIZE)) { + return mCRLSize; + } else if (name.equalsIgnoreCase(ATTR_THIS_UPDATE)) { + return mThisUpdate; + } else if (name.equalsIgnoreCase(ATTR_NEXT_UPDATE)) { + return mNextUpdate; + } else if (name.equalsIgnoreCase(ATTR_DELTA_NUMBER)) { + return mDeltaCRLNumber; + } else if (name.equalsIgnoreCase(ATTR_DELTA_SIZE)) { + return mDeltaCRLSize; + } else if (name.equalsIgnoreCase(ATTR_FIRST_UNSAVED)) { + return mFirstUnsaved; + } else if (name.equalsIgnoreCase(ATTR_CRL)) { + return mCRL; + } else if (name.equalsIgnoreCase(ATTR_CA_CERT)) { + return mCACert; + } else if (name.equalsIgnoreCase(ATTR_CRL_CACHE)) { + return mCRLCache; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_CERTS)) { + return mRevokedCerts; + } else if (name.equalsIgnoreCase(ATTR_UNREVOKED_CERTS)) { + return mUnrevokedCerts; + } else if (name.equalsIgnoreCase(ATTR_EXPIRED_CERTS)) { + return mExpiredCerts; + } else if (name.equalsIgnoreCase(ATTR_DELTA_CRL)) { + return mDeltaCRL; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + public void delete(String name) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + + public Enumeration getElements() { + return mNames.elements(); + } + + public Enumeration getSerializableAttrNames() { + return mNames.elements(); + } + + /** + * Retrieve unique CRL identifier. + */ + public String getId() { + return mId; + } + + /** + * Retrieves CRL number. + */ + public BigInteger getCRLNumber() { + return mCRLNumber; + } + + /** + * Retrieves CRL size. + */ + public Long getCRLSize() { + return mCRLSize; + } + + /** + * Retrieves this update time. + */ + public Date getThisUpdate() { + return mThisUpdate; + } + + /** + * Retrieves next update time. + */ + public Date getNextUpdate() { + return mNextUpdate; + } + + /** + * Retrieves delta CRL number. + */ + public BigInteger getDeltaCRLNumber() { + return mDeltaCRLNumber; + } + + /** + * Retrieves CRL size. + */ + public Long getDeltaCRLSize() { + return mDeltaCRLSize; + } + + /** + * Retrieve unique CRL identifier. + */ + public String getFirstUnsaved() { + return mFirstUnsaved; + } + + /** + * Retrieves CRL encodings. + */ + public byte[] getCRL() { + return mCRL; + } + + /** + * Retrieves CRL encodings. + */ + public byte[] getDeltaCRL() { + return mDeltaCRL; + } + + public byte[] getCACert() { + return mCACert; + } + + public Hashtable getCRLCacheNoClone() { + if (mCRLCache == null) + return null; + else + return (Hashtable) mCRLCache; + } + + public Hashtable getCRLCache() { + if (mCRLCache == null) + return null; + else + return (Hashtable) mCRLCache.clone(); + } + + /** + * Retrieves cache info of revoked certificates. + */ + public Hashtable getRevokedCerts() { + if (mRevokedCerts == null) + return null; + else + return (Hashtable) mRevokedCerts.clone(); + } + + /** + * Retrieves cache info of unrevoked certificates. + */ + public Hashtable getUnrevokedCerts() { + if (mUnrevokedCerts == null) + return null; + else + return (Hashtable) mUnrevokedCerts.clone(); + } + + /** + * Retrieves cache info of expired certificates. + */ + public Hashtable getExpiredCerts() { + if (mExpiredCerts == null) + return null; + else + return (Hashtable) mExpiredCerts.clone(); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java new file mode 100644 index 000000000..c2eba5acb --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CRLRepository.java @@ -0,0 +1,365 @@ +// --- 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.math.*; +import java.util.*; +import java.io.*; +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.repository.*; + +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.*; + +import com.netscape.certsrv.apps.*; + +/** + * A class represents a CRL repository. It stores all the + * CRL issuing points. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CRLRepository extends Repository implements ICRLRepository { + + private final String mLdapCRLIssuingPointName = "cn"; + private IDBSubsystem mDBService; + private String mBaseDN; + + /** + * Constructs a CRL repository. + */ + public CRLRepository(IDBSubsystem dbService, int increment, String baseDN) + throws EDBException { + super(dbService, increment, baseDN); + mBaseDN = baseDN; + mDBService = dbService; + + IDBRegistry reg = dbService.getRegistry(); + + /** + String crlRecordOC[] = new String[1]; + crlRecordOC[0] = Schema.LDAP_OC_CRL_RECORD; + reg.registerObjectClass(CRLIssuingPointRecord.class.getName(), + crlRecordOC); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_ID, new + StringMapper(Schema.LDAP_ATTR_CRL_ID)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_NUMBER, new + BigIntegerMapper(Schema.LDAP_ATTR_CRL_NUMBER)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_SIZE, new + LongMapper(Schema.LDAP_ATTR_CRL_SIZE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_THIS_UPDATE, new + DateMapper(Schema.LDAP_ATTR_THIS_UPDATE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, new + DateMapper(Schema.LDAP_ATTR_NEXT_UPDATE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL, new + ByteArrayMapper(Schema.LDAP_ATTR_CRL)); + **/ + } + + /** + * Retrieves backend database handle. + */ + public IDBSubsystem getDBSubsystem() { + return mDBService; + } + + /** + * Retrieves DN of this repository. + */ + public String getDN() { + return mBaseDN; + } + + /** + * Removes all objects with this repository. + */ + public void removeAllObjects() throws EBaseException + { + } + + /** + * Adds CRL issuing points. + */ + public void addCRLIssuingPointRecord(ICRLIssuingPointRecord rec) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = mLdapCRLIssuingPointName + "=" + + ((CRLIssuingPointRecord) rec).getId().toString() + "," + getDN(); + + s.add(name, rec); + } finally { + if (s != null) + s.close(); + } + } + + /** + * Retrieves all issuing points' names + */ + public Vector getIssuingPointsNames() throws EBaseException { + IDBSSession s = mDBService.createSession(); + try { + String[] attrs = {ICRLIssuingPointRecord.ATTR_ID, "objectclass"}; + String filter = "objectclass=" + CMS.getCRLIssuingPointRecordName(); + IDBSearchResults res = s.search(getDN(), filter, attrs); + Vector v = new Vector(); + while (res.hasMoreElements()) { + ICRLIssuingPointRecord nextelement = + (ICRLIssuingPointRecord)res.nextElement(); + CMS.debug("CRLRepository getIssuingPointsNames(): name = " + +nextelement.getId()); + v.addElement(nextelement.getId()); + } + + return v; + } finally { + if (s != null) + s.close(); + } + } + + /** + * Reads issuing point record. + */ + public ICRLIssuingPointRecord readCRLIssuingPointRecord(String id) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + CRLIssuingPointRecord rec = null; + + try { + String name = mLdapCRLIssuingPointName + "=" + id + + "," + getDN(); + + if (s != null) { + rec = (CRLIssuingPointRecord) s.read(name); + } + } finally { + if (s != null) s.close(); + } + return rec; + } + + /** + * deletes issuing point record. + */ + public void deleteCRLIssuingPointRecord(String id) + throws EBaseException { + IDBSSession s = null; + + try { + s = mDBService.createSession(); + String name = mLdapCRLIssuingPointName + "=" + id + + "," + getDN(); + + if (s != null) s.delete(name); + } finally { + if (s != null) s.close(); + } + } + + public void modifyCRLIssuingPointRecord(String id, + ModificationSet mods) throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = mLdapCRLIssuingPointName + "=" + id + + "," + getDN(); + + if (s != null) s.modify(name, mods); + } finally { + if (s != null) s.close(); + } + } + + /** + * Updates CRL issuing point record. + */ + public void updateCRLIssuingPointRecord(String id, byte[] newCRL, + Date thisUpdate, Date nextUpdate, BigInteger crlNumber, Long crlSize) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + if (newCRL != null) { + mods.add(ICRLIssuingPointRecord.ATTR_CRL, + Modification.MOD_REPLACE, newCRL); + } + if (nextUpdate != null) { + mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, + Modification.MOD_REPLACE, nextUpdate); + } + mods.add(ICRLIssuingPointRecord.ATTR_THIS_UPDATE, + Modification.MOD_REPLACE, thisUpdate); + mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER, + Modification.MOD_REPLACE, crlNumber); + mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE, + Modification.MOD_REPLACE, crlSize); + modifyCRLIssuingPointRecord(id, mods); + } + + /** + * Updates CRL issuing point record. + */ + public void updateCRLIssuingPointRecord(String id, byte[] newCRL, + Date thisUpdate, Date nextUpdate, BigInteger crlNumber, Long crlSize, + Hashtable revokedCerts, Hashtable unrevokedCerts, Hashtable expiredCerts) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + if (newCRL != null) { + mods.add(ICRLIssuingPointRecord.ATTR_CRL, + Modification.MOD_REPLACE, newCRL); + } + if (nextUpdate != null) { + mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, + Modification.MOD_REPLACE, nextUpdate); + } + mods.add(ICRLIssuingPointRecord.ATTR_THIS_UPDATE, + Modification.MOD_REPLACE, thisUpdate); + mods.add(ICRLIssuingPointRecord.ATTR_CRL_NUMBER, + Modification.MOD_REPLACE, crlNumber); + mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE, + Modification.MOD_REPLACE, crlSize); + if (revokedCerts != null) { + mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS, + Modification.MOD_REPLACE, revokedCerts); + } + if (unrevokedCerts != null) { + mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS, + Modification.MOD_REPLACE, unrevokedCerts); + } + if (expiredCerts != null) { + mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS, + Modification.MOD_REPLACE, expiredCerts); + } + if (revokedCerts != null || unrevokedCerts != null) { + mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, + Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE); + } + modifyCRLIssuingPointRecord(id, mods); + } + + /** + * Updates CRL issuing point record with recently revoked certificates info. + */ + public void updateRevokedCerts(String id, Hashtable revokedCerts, + Hashtable unrevokedCerts) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS, + Modification.MOD_REPLACE, revokedCerts); + mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS, + Modification.MOD_REPLACE, unrevokedCerts); + mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, + Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE); + modifyCRLIssuingPointRecord(id, mods); + } + + /** + * Updates CRL issuing point record with recently expired certificates info. + */ + public void updateExpiredCerts(String id, Hashtable expiredCerts) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS, + Modification.MOD_REPLACE, expiredCerts); + modifyCRLIssuingPointRecord(id, mods); + } + + /** + * Updates CRL issuing point record with CRL cache info. + */ + public void updateCRLCache(String id, Long crlSize, + Hashtable revokedCerts, + Hashtable unrevokedCerts, + Hashtable expiredCerts) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + if (crlSize != null) { + mods.add(ICRLIssuingPointRecord.ATTR_CRL_SIZE, + Modification.MOD_REPLACE, crlSize); + } + mods.add(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS, + Modification.MOD_REPLACE, revokedCerts); + mods.add(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS, + Modification.MOD_REPLACE, unrevokedCerts); + mods.add(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS, + Modification.MOD_REPLACE, expiredCerts); + mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, + Modification.MOD_REPLACE, ICRLIssuingPointRecord.CLEAN_CACHE); + modifyCRLIssuingPointRecord(id, mods); + } + + /** + * Updates CRL issuing point record with delta-CRL. + */ + public void updateDeltaCRL(String id, BigInteger deltaCRLNumber, + Long deltaCRLSize, Date nextUpdate, + byte[] deltaCRL) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + if (deltaCRLNumber != null) { + mods.add(ICRLIssuingPointRecord.ATTR_DELTA_NUMBER, + Modification.MOD_REPLACE, deltaCRLNumber); + } + if (deltaCRLSize != null) { + mods.add(ICRLIssuingPointRecord.ATTR_DELTA_SIZE, + Modification.MOD_REPLACE, deltaCRLSize); + } + if (nextUpdate != null) { + mods.add(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, + Modification.MOD_REPLACE, nextUpdate); + } + if (deltaCRL != null) { + mods.add(ICRLIssuingPointRecord.ATTR_DELTA_CRL, + Modification.MOD_REPLACE, deltaCRL); + } + modifyCRLIssuingPointRecord(id, mods); + } + + public void updateFirstUnsaved(String id, String firstUnsaved) + throws EBaseException { + ModificationSet mods = new ModificationSet(); + + if (firstUnsaved != null) { + mods.add(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, + Modification.MOD_REPLACE, firstUnsaved); + } + modifyCRLIssuingPointRecord(id, mods); + } + + public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) + throws EBaseException { + + return null; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java new file mode 100644 index 000000000..c444a45ac --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertDBSchema.java @@ -0,0 +1,64 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a collection of certificate record + * specific schema information. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CertDBSchema { + + public static final String LDAP_OC_TOP = "top"; + public static final String LDAP_ATTR_META_INFO = "metaInfo"; + public static final String LDAP_ATTR_SERIALNO = "serialno"; + public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate"; + public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify"; + public static final String LDAP_ATTR_PUBLIC_KEY_DATA = "publicKeyData"; + + public static final String LDAP_OC_CERT_RECORD = "certificateRecord"; + public static final String LDAP_ATTR_CERT_RECORD_ID = "certRecordId"; + public static final String LDAP_ATTR_NOT_BEFORE = "notBefore"; + public static final String LDAP_ATTR_NOT_AFTER = "notAfter"; + public static final String LDAP_ATTR_SIGNED_CERT = "userCertificate"; + public static final String LDAP_ATTR_VERSION = "version"; + public static final String LDAP_ATTR_DURATION = "duration"; + public static final String LDAP_ATTR_SUBJECT = "subjectName"; + public static final String LDAP_ATTR_ALGORITHM = "algorithmId"; + public static final String LDAP_ATTR_SIGNING_ALGORITHM = "signingAlgorithmId"; + public static final String LDAP_ATTR_REVO_INFO = "revInfo"; + public static final String LDAP_ATTR_CERT_STATUS = "certStatus"; + public static final String LDAP_ATTR_AUTO_RENEW = "autoRenew"; + public static final String LDAP_ATTR_ISSUED_BY = "issuedBy"; + public static final String LDAP_ATTR_REVOKED_BY = "revokedBy"; + public static final String LDAP_ATTR_REVOKED_ON = "revokedOn"; + public static final String LDAP_ATTR_EXTENSION = "extension"; +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java new file mode 100644 index 000000000..308d801e3 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecord.java @@ -0,0 +1,278 @@ +// --- 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.*; +import java.math.*; +import java.util.*; +import java.security.cert.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents a serializable certificate record. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CertRecord implements IDBObj, ICertRecord { + + private BigInteger mId = null; + private X509CertImpl mX509Certificate = null; + private String mStatus = null; + private String mAutoRenew = null; + private MetaInfo mMetaInfo = null; + // XXX revocationInfo not serializable + private transient RevocationInfo mRevocationInfo = null; + private Date mCreateTime = null; + private Date mModifyTime = null; + private String mIssuedBy = null; + private String mRevokedBy = null; + private Date mRevokedOn = null; + + protected static Vector mNames = new Vector(); + static { + mNames.addElement(ATTR_ID); + mNames.addElement(ATTR_META_INFO); + mNames.addElement(ATTR_REVO_INFO); + mNames.addElement(ATTR_X509CERT); + mNames.addElement(ATTR_CREATE_TIME); + mNames.addElement(ATTR_MODIFY_TIME); + mNames.addElement(ATTR_CERT_STATUS); + mNames.addElement(ATTR_AUTO_RENEW); + mNames.addElement(ATTR_ISSUED_BY); + mNames.addElement(ATTR_REVOKED_BY); + mNames.addElement(ATTR_REVOKED_ON); + } + + /** + * Constructs empty certificate record. + */ + public CertRecord() { + } + + /** + * Constructs certiificate record with certificate + * and meta info. + */ + public CertRecord(BigInteger id, Certificate cert, MetaInfo meta) { + mId = id; + if (cert instanceof X509CertImpl) + mX509Certificate = (X509CertImpl) cert; + mMetaInfo = meta; + mStatus = STATUS_VALID; + mAutoRenew = AUTO_RENEWAL_ENABLED; + mCreateTime = CMS.getCurrentDate(); + mModifyTime = CMS.getCurrentDate(); + } + + /** + * Sets attribute to this record. + */ + public void set(String name, Object obj) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_REVO_INFO)) { + mRevocationInfo = (RevocationInfo) obj; + } else if (name.equalsIgnoreCase(ATTR_ID)) { + mId = (BigInteger) obj; + } else if (name.equalsIgnoreCase(ATTR_META_INFO)) { + mMetaInfo = (MetaInfo) obj; + } else if (name.equalsIgnoreCase(ATTR_X509CERT)) { + mX509Certificate = (X509CertImpl) obj; + } else if (name.equalsIgnoreCase(ATTR_CERT_STATUS)) { + mStatus = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_AUTO_RENEW)) { + mAutoRenew = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) { + mCreateTime = (Date) obj; + } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) { + mModifyTime = (Date) obj; + } else if (name.equalsIgnoreCase(ATTR_ISSUED_BY)) { + mIssuedBy = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_BY)) { + mRevokedBy = (String) obj; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_ON)) { + mRevokedOn = (Date) obj; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Retrieves attributes from this record. + */ + public Object get(String name) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_REVO_INFO)) { + return mRevocationInfo; + } else if (name.equalsIgnoreCase(ATTR_ID)) { + return mId; + } else if (name.equalsIgnoreCase(ATTR_META_INFO)) { + return mMetaInfo; + } else if (name.equalsIgnoreCase(ATTR_X509CERT)) { + return mX509Certificate; + } else if (name.equalsIgnoreCase(ATTR_CERT_STATUS)) { + return mStatus; + } else if (name.equalsIgnoreCase(ATTR_AUTO_RENEW)) { + return mAutoRenew; + } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) { + return mCreateTime; + } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) { + return mModifyTime; + } else if (name.equalsIgnoreCase(ATTR_ISSUED_BY)) { + return mIssuedBy; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_BY)) { + return mRevokedBy; + } else if (name.equalsIgnoreCase(ATTR_REVOKED_ON)) { + return mRevokedOn; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Deletes attribute from this record. + */ + public void delete(String name) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + + public Enumeration getElements() { + return mNames.elements(); + } + + public Enumeration getSerializableAttrNames() { + return mNames.elements(); + } + + /** + * Retrieves X509 certificate. + */ + public X509CertImpl getCertificate() { + return mX509Certificate; + } + + /** + * Retrieves meta information. + */ + public MetaInfo getMetaInfo() { + return mMetaInfo; + } + + /** + * Retrieves certificate status. + */ + public String getStatus() { + return mStatus; + } + + /** + * Retrieves the auto renew mode. + */ + public String getAutoRenew() { + return mAutoRenew; + } + + /** + * Retrieves revocation information. + */ + public IRevocationInfo getRevocationInfo() { + return mRevocationInfo; + } + + /** + * Retrieves serial number of this record. Usually, + * it is the same of the serial number of the + * associated certificate. + */ + public BigInteger getSerialNumber() { + return mId; + } + + /** + * Retrieves the person who issues this certificate. + */ + public String getIssuedBy() { + return mIssuedBy; + } + + /** + * Retrieves the person who revokes this certificate. + */ + public String getRevokedBy() { + return mRevokedBy; + } + + /** + * Retrieves the date which this record is revoked. + */ + public Date getRevokedOn() { + return mRevokedOn; + } + + /** + * Retrieves certificate serial number. + */ + public BigInteger getCertificateSerialNumber() { + return mX509Certificate.getSerialNumber(); + } + + /** + * Retrieves not after. + */ + public Date getNotAfter() { + return mX509Certificate.getNotAfter(); + } + + public Date getNotBefore() { + return mX509Certificate.getNotBefore(); + } + + /** + * Return revocation date. + */ + public Date getRevocationDate() throws EDBException { + return mRevocationInfo.getRevocationDate(); + } + + public Date getCreateTime() { + return mCreateTime; + } + + public Date getModifyTime() { + return mModifyTime; + } + + /** + * String representation + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + + buf.append("CertRecord: "); + if (getSerialNumber() != null) + buf.append(" " + getSerialNumber().toString()); + return buf.toString(); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java new file mode 100644 index 000000000..18b8c1bf5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertRecordList.java @@ -0,0 +1,118 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; + +import com.netscape.cmscore.dbs.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents a list of certificate records. + *

+ * + * @author thomask mzhao + * @version $Revision$, $Date$ + */ +public class CertRecordList implements ICertRecordList { + + private IDBVirtualList mVlist = null; + + /** + * Constructs a request list. + */ + public CertRecordList(IDBVirtualList vlist) { + mVlist = vlist; + } + + public int getCurrentIndex() { + return mVlist.getCurrentIndex(); + } + + /** + * Retrieves the size of request list. + */ + public int getSize() { + // get the size of the virtual list + return mVlist.getSize(); + } + + public int getSizeBeforeJumpTo() { + return mVlist.getSizeBeforeJumpTo(); + + } + + public int getSizeAfterJumpTo() { + return mVlist.getSizeAfterJumpTo(); + + } + + /** + * Process certificate record as soon as it is returned. + * kmccarth: changed to ignore startidx and endidx because VLVs don't + * provide a stable list. + */ + public void processCertRecords(int startidx, int endidx, + IElementProcessor ep) throws EBaseException { + int i = 0; + while ( i + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class CertRecordMapper implements IDBAttrMapper { + + private ICertificateRepository mDB = null; + + public CertRecordMapper(ICertificateRepository db) { + mDB = db; + } + + public Enumeration getSupportedLDAPAttributeNames() { + Vector v = new Vector(); + + v.addElement(CertDBSchema.LDAP_ATTR_CERT_RECORD_ID); + return v.elements(); + } + + public void mapObjectToLDAPAttributeSet(IDBObj parent, String name, + Object obj, LDAPAttributeSet attrs) + throws EBaseException { + try { + CertRecord rec = (CertRecord) obj; + + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_CERT_RECORD_ID, + rec.getSerialNumber().toString())); + } catch (Exception e) { + Debug.trace(e.toString()); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name)); + } + } + + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + try { + LDAPAttribute attr = attrs.getAttribute( + CertDBSchema.LDAP_ATTR_CERT_RECORD_ID); + + if (attr == null) + return; + String serialno = (String) attr.getStringValues().nextElement(); + ICertRecord rec = mDB.readCertificateRecord( + new BigInteger(serialno)); + + parent.set(name, rec); + } catch (Exception e) { + Debug.trace(e.toString()); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } + } + + public String mapSearchFilter(String name, String op, String value) + throws EBaseException { + return name + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java new file mode 100644 index 000000000..526e855e6 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java @@ -0,0 +1,1985 @@ +// --- 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.math.BigInteger; +import java.util.*; +import java.io.*; +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import netscape.security.x509.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.repository.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; + +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.*; +import com.netscape.cmscore.cert.*; + + +/** + * 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; + + /** + * Constructs a certificate repository. + */ + public CertificateRepository(IDBSubsystem dbService, String certRepoBaseDN, int increment, String baseDN) + throws EDBException { + super(dbService, increment, baseDN); + mBaseDN = certRepoBaseDN; + + mDBService = dbService; + + // registers CMS database attributes + IDBRegistry reg = dbService.getRegistry(); + + IConfigStore cfg = mDBService.getConfigStore(); + } + + 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(); + + Vector cList = new Vector(ltSize); + + 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 CertStatusUpdateThread mCertStatusUpdateThread = null; + public RetrieveModificationsThread mRetrieveModificationsThread = null; + + public void setCertStatusUpdateInterval(IRepository requestRepo, int interval, boolean listenToCloneModifications) { + CMS.debug("In setCertStatusUpdateInterval " + interval); + if (interval == 0) { + CMS.debug("In setCertStatusUpdateInterval interval = 0" + interval); + if (mCertStatusUpdateThread != null) { + mCertStatusUpdateThread.stop(); + } + if (mRetrieveModificationsThread != null) { + mRetrieveModificationsThread.stop(); + } + return; + } + + CMS.debug("In setCertStatusUpdateInterval listenToCloneModifications="+listenToCloneModifications+ + " mRetrieveModificationsThread="+mRetrieveModificationsThread); + if (listenToCloneModifications && mRetrieveModificationsThread == null) { + CMS.debug("In setCertStatusUpdateInterval about to create RetrieveModificationsThread"); + mRetrieveModificationsThread = new RetrieveModificationsThread(this, "RetrieveModificationsThread"); + LDAPSearchResults mResults = null; + try { + mResults = startSearchForModifiedCertificateRecords(); + } catch (Exception e) { + mResults = null; + } + if (mResults != null) { + mRetrieveModificationsThread.setResults(mResults); + mRetrieveModificationsThread.start(); + } + } + + CMS.debug("In setCertStatusUpdateInterval mCertStatusUpdateThread " + mCertStatusUpdateThread); + if (mCertStatusUpdateThread == null) { + CMS.debug("In setCertStatusUpdateInterval about to create CertStatusUpdateThread "); + mCertStatusUpdateThread = new CertStatusUpdateThread(this, requestRepo, "CertStatusUpdateThread"); + mCertStatusUpdateThread.setInterval(interval); + mCertStatusUpdateThread.start(); + } else { + CMS.debug("In setCertStatusUpdateInterval it thinks the thread is up already "); + mCertStatusUpdateThread.setInterval(interval); + // dont do anything if we have a thread running already + } + } + + + /** + * Blocking method. + */ + public void updateCertStatus() throws EBaseException { + + CMS.debug("In updateCertStatus()"); + + 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")); + } + + /** + * 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; + Object 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"); + } + } + + CertRecord cRec = null; + BigInteger serial = null; + + 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 = (ICRLIssuingPoint) 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 { + X509CertImpl cert = null; + 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(); + Enumeration e = null; + + CMS.debug("searchCertificateswith time limit filter " + filter); + try { + e = s.search(getDN(), filter, maxSize, timeLimit); + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * 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()) { + CertRecord rec = (CertRecord) 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 { + DBVirtualList vlist = (DBVirtualList) 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; + } + } + + DBVirtualList vlist = (DBVirtualList) 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 { + + DBVirtualList vlist = (DBVirtualList) 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) { + int fv = 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 { + + String now = null; + + Date rightNow = CMS.getCurrentDate(); + + 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 { + + String now = null; + + 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; + String ldapfilter = "(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; // 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; + } + + /** + * 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; + String ldapfilter = "(&(|(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED + ")(" + CertRecord.ATTR_CERT_STATUS + "=" + CertRecord.STATUS_REVOKED_EXPIRED + "))"; // index is setup for this filter + + 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; + } + + private LDAPSearchResults startSearchForModifiedCertificateRecords() + throws EBaseException { + CMS.debug("startSearchForModifiedCertificateRecords"); + LDAPSearchResults r = null; + IDBSSession s = mDBService.createSession(); + + String filter = "(" + CertRecord.ATTR_CERT_STATUS + "=*)"; + try { + r = s.persistentSearch(getDN(), filter, null); + CMS.debug("startSearchForModifiedCertificateRecords persistentSearch started"); + } catch (Exception e) { + CMS.debug("startSearchForModifiedCertificateRecords persistentSearch Exception="+e); + r = null; + if (s != null) + s.close(); + } + return r; + } + + 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 = (ICRLIssuingPoint) 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 (mCertStatusUpdateThread != null) + mCertStatusUpdateThread.destroy(); + + if (mRetrieveModificationsThread != null) + mRetrieveModificationsThread.destroy(); + } +} + + +class CertStatusUpdateThread extends Thread { + CertificateRepository _cr = null; + IRepository _rr = null; + int _interval; + + CertStatusUpdateThread(CertificateRepository cr, IRepository rr, String name) { + super(name); + CMS.debug("new CertStatusUpdateThread"); + //setName(name); + + _cr = cr; + _rr = rr; + } + + public void setInterval(int interval) { + _interval = interval; + } + + public void run() { + CMS.debug("Inside run method of CertStatusUpdateThread"); + + while (true) { + try { + // block the update while another thread + // (such as the CRL Update) is running + CMS.debug("About to start updateCertStatus"); + synchronized (_cr.mCertStatusUpdateThread) { + CMS.debug("Starting updateCertStatus (entered lock)"); + _cr.updateCertStatus(); + CMS.debug("updateCertStatus done"); + + CMS.debug("Starting cert checkRanges"); + _cr.checkRanges(); + CMS.debug("cert checkRanges done"); + + CMS.debug("Starting request checkRanges"); + _rr.checkRanges(); + CMS.debug("request checkRanges done"); + } + + } catch (Exception e) { + CMS.debug("updateCertStatus done: " + e.toString()); + } + try { + sleep(_interval * 1000); + } catch (InterruptedException e) { + } + } + } +} + + +class RetrieveModificationsThread extends Thread { + CertificateRepository _cr = null; + LDAPSearchResults _results = null; + + RetrieveModificationsThread(CertificateRepository cr, String name) { + super(name); + CMS.debug("new RetrieveModificationsThread"); + //setName(name); + + _cr = cr; + } + + public void setResults(LDAPSearchResults results) { + _results = results; + } + + public void run() { + CMS.debug("Inside run method of RetrieveModificationsThread"); + + if (_results != null) { + try { + while (_results.hasMoreElements()) { + LDAPEntry entry = _results.next(); + _cr.getModifications(entry); + } + } catch (LDAPException e) { + CMS.debug("LDAPException: "+e.toString()); + } + } else { + CMS.debug("_results are null"); + } + CMS.debug("Done with run method of RetrieveModificationsThread"); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java new file mode 100644 index 000000000..660e385fe --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBRegistry.java @@ -0,0 +1,553 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a registry where all the + * schema (object classes and attribute) information + * is stored. + * + * Attribute mappers can be registered with this + * registry. + * + * Given the schema information stored, this registry + * has knowledge to convert a Java object into a + * LDAPAttributeSet or vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DBRegistry implements IDBRegistry, ISubsystem { + + private IConfigStore mConfig = null; + private Hashtable mOCclassNames = new Hashtable(); + private Hashtable mOCldapNames = new Hashtable(); + private Hashtable mAttrufNames = new Hashtable(); + private IFilterConverter mConverter = null; + private Vector mDynAttrMappers = new Vector(); + + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs registry. + */ + public DBRegistry() { + } + + /** + * Retrieves subsystem identifier. + */ + public String getId() { + return "dbsregistry"; + } + + /** + * Sets subsystem identifier. This is an internal + * subsystem, and is not loadable. + */ + public void setId(String id) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION")); + } + + /** + * Initializes the internal registery. Connects to the + * data source, and create a pool of connection of which + * applications can use. Optionally, check the integrity + * of the database. + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + mConfig = config; + mConverter = new LdapFilterConverter(mAttrufNames); + } + + /** + * Retrieves configuration store. + */ + public IConfigStore getConfigStore() { + return mConfig; + } + + /** + * Starts up this subsystem. + */ + public void startup() throws EBaseException { + } + + /** + * Shutdowns this subsystem gracefully. + */ + public void shutdown() { + mOCclassNames.clear(); + mOCclassNames = null; + mOCldapNames.clear(); + mOCldapNames = null; + mAttrufNames.clear(); + mAttrufNames = null; + mConverter = null; + } + + /** + * Registers object class. + */ + public void registerObjectClass(String className, String ldapNames[]) + throws EDBException { + try { + Class c = Class.forName(className); + + mOCclassNames.put(className, ldapNames); + mOCldapNames.put(sortAndConcate( + ldapNames).toLowerCase(), + new NameAndObject(className, c)); + } catch (ClassNotFoundException e) { + + /*LogDoc + * + * @phase db startup + * @reason failed to register object class + * @message DBRegistry: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_INVALID_CLASS_NAME", className)); + } + } + + /** + * See if an object class is registered. + */ + public boolean isObjectClassRegistered(String className) { + return mOCclassNames.containsKey(className); + } + + /** + * Registers attribute mapper. + */ + public void registerAttribute(String ufName, IDBAttrMapper mapper) + throws EDBException { + // should not allows 'objectclass' as attribute; it has + // special meaning + mAttrufNames.put(ufName.toLowerCase(), mapper); + } + + /** + * See if an attribute is registered. + */ + public boolean isAttributeRegistered(String ufName) { + return mAttrufNames.containsKey(ufName.toLowerCase()); + } + + public void registerDynamicMapper(IDBDynAttrMapper mapper) { + mDynAttrMappers.add(mapper); + } + + /** + * Creates LDAP-based search filters with help of + * registered mappers. + * Parses filter from filter string specified in RFC1558. + *
+     *  ::= '('  ')'
+     *  ::=  |  |  | 
+     *  ::= '&' 
+     *  ::= '|' 
+     *  ::= '!' 
+     *  ::=  |  
+     *  ::=  |  | 
+     *  ::=   
+     *  ::=  |  |  | 
+     *  ::= '='
+     *  ::= '~='
+     *  ::= '>='
+     *  ::= '<='
+     *  ::=  '=*'
+     *  ::=  '='   
+     *  ::= NULL | 
+     *  ::= '*' 
+     *  ::= NULL |  '*' 
+     *  ::= NULL | 
+     * 
+ */ + public String getFilter(String filter) throws EBaseException { + return getFilter(filter, mConverter); + } + + public String getFilter(String filter, IFilterConverter c) + throws EBaseException { + String f = filter; + + f = f.trim(); + if (f.startsWith("(") && f.endsWith(")")) { + return "(" + getFilterComp(f.substring(1, + f.length() - 1), c) + ")"; + } else { + return getFilterComp(filter, c); + } + } + + private String getFilterComp(String f, IFilterConverter c) + throws EBaseException { + f = f.trim(); + if (f.startsWith("&")) { // AND operation + return "&" + getFilterList(f.substring(1, + f.length()), c); + } else if (f.startsWith("|")) { // OR operation + return "|" + getFilterList(f.substring(1, + f.length()), c); + } else if (f.startsWith("!")) { // NOT operation + return "!" + getFilter(f.substring(1, f.length()), c); + } else { // item + return getFilterItem(f, c); + } + } + + private String getFilterList(String f, IFilterConverter c) + throws EBaseException { + f = f.trim(); + int level = 0; + int start = 0; + int end = 0; + Vector v = new Vector(); + + for (int i = 0; i < f.length(); i++) { + if (f.charAt(i) == '(') { + if (level == 0) { + start = i; + } + level++; + } + if (f.charAt(i) == ')') { + level--; + if (level == 0) { + end = i; + String filter = getFilter(f.substring(start, end + 1), c); + + v.addElement(filter); + } + } + } + String result = ""; + + for (int i = 0; i < v.size(); i++) { + result += (String) v.elementAt(i); + } + return result; + } + + /** + * So, here we need to separate item into name, op, value. + */ + private String getFilterItem(String f, IFilterConverter c) + throws EBaseException { + f = f.trim(); + int idx = f.indexOf('='); + + if (idx == -1) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_INVALID_FILTER_ITEM", "=")); + } + + String type = f.substring(0, idx).trim(); + String value = f.substring(idx + 1).trim(); // skip '=' + + // make decision by looking at the type + type = type.trim(); + if (type.endsWith("~")) { + // approximate match + String name = type.substring(0, type.length() - 1).trim(); + + return c.convert(name, "~=", value); + } else if (type.endsWith("!")) { + String name = type.substring(0, type.length() - 1).trim(); + + return c.convert(name, "!=", value); + } else if (type.endsWith(">")) { + // greater than + String name = type.substring(0, type.length() - 1).trim(); + + return c.convert(name, ">=", value); + } else if (type.endsWith("<")) { + String name = type.substring(0, type.length() - 1).trim(); + + return c.convert(name, "<=", value); + } + + // for those that are not simple + if (value.startsWith("*") && value.length() == 1) { + return c.convert(type, "=", "*"); + } + + // if value contains no '*', then it is equality + if (value.indexOf('*') == -1) { + if (type.equals("objectclass")) { + String ldapNames[] = (String[]) + mOCclassNames.get(value); + + if (ldapNames == null) + throw new EDBException( + CMS.getUserMessage("CMS_DBS_INVALID_FILTER_ITEM", f)); + String filter = ""; + + for (int g = 0; g < ldapNames.length; g++) { + filter += "(objectclass=" + + ldapNames[g] + ")"; + } + return "&" + filter; + } else { + return c.convert(type, "=", value); + } + } + // XXX - does not support substring!! + return c.convert(type, "=", value); + } + + /** + * Maps object into LDAP attribute set. + */ + public void mapObject(IDBObj parent, String name, Object obj, + LDAPAttributeSet attrs) throws EBaseException { + IDBAttrMapper mapper = (IDBAttrMapper) mAttrufNames.get( + name.toLowerCase()); + + if (mapper == null) { + return; // no mapper found, just skip this attribute + } + mapper.mapObjectToLDAPAttributeSet(parent, name, obj, attrs); + } + + /** + * Retrieves a list of LDAP attributes that are associated + * with the given attributes. + * This method is used for searches, to map the database attributes + * to LDAP attributes. + */ + public String[] getLDAPAttributes(String attrs[]) + throws EBaseException { + IDBAttrMapper mapper; + + if (attrs == null) + return null; + Vector v = new Vector(); + + for (int i = 0; i < attrs.length; i++) { + + if (attrs[i].equals("objectclass")) { + v.addElement("objectclass"); + continue; + } + + if (isAttributeRegistered(attrs[i])) { + mapper = (IDBAttrMapper) + mAttrufNames.get(attrs[i].toLowerCase()); + if (mapper == null) { + throw new EDBException(CMS.getUserMessage("CMS_DBS_INVALID_ATTRS")); + } + Enumeration e = mapper.getSupportedLDAPAttributeNames(); + + while (e.hasMoreElements()) { + String s = (String) e.nextElement(); + + if (!v.contains(s)) { + v.addElement(s); + } + } + } else { + IDBDynAttrMapper matchingDynAttrMapper = null; + // check if a dynamic mapper can handle the attribute + for (Iterator dynMapperIter = mDynAttrMappers.iterator(); + dynMapperIter.hasNext();) { + IDBDynAttrMapper dynAttrMapper = + (IDBDynAttrMapper)dynMapperIter.next(); + if (dynAttrMapper.supportsLDAPAttributeName(attrs[i])) { + matchingDynAttrMapper = dynAttrMapper; + break; + } + } + if (matchingDynAttrMapper != null) { + v.addElement(attrs[i]); + } else { + /*LogDoc + * + * @phase retrieve ldap attr + * @reason failed to get registered object class + * @message DBRegistry: is not registered + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_DBS_ATTR_NOT_REGISTER", attrs[i])); + throw new EDBException(CMS.getLogMessage("CMSCORE_DBS_ATTR_NOT_REGISTER", attrs[i])); + } + } + + } + if (v.size() == 0) + return null; + String ldapAttrs[] = new String[v.size()]; + + v.copyInto(ldapAttrs); + return ldapAttrs; + } + + /** + * Creates attribute set from object. + */ + public LDAPAttributeSet createLDAPAttributeSet(IDBObj obj) + throws EBaseException { + Enumeration e = obj.getSerializableAttrNames(); + LDAPAttributeSet attrs = new LDAPAttributeSet(); + + // add object class to attribute set + String className = ((Object) obj).getClass().getName(); + String vals[] = (String[]) mOCclassNames.get(className); + + attrs.add(new LDAPAttribute("objectclass", vals)); + + // give every attribute a chance to put stuff in attr set + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (obj.get(name) != null) { + mapObject(obj, name, obj.get(name), attrs); + } + } + return attrs; + } + + /** + * Creates object from attribute set. + */ + public IDBObj createObject(LDAPAttributeSet attrs) + throws EBaseException { + // map object class attribute to object + LDAPAttribute attr = attrs.getAttribute("objectclass"); + + //CMS.debug("createObject: attrs " + attrs.toString()); + + attrs.remove("objectclass"); + + // sort the object class values + Enumeration vals = attr.getStringValues(); + Vector v = new Vector(); + + while (vals.hasMoreElements()) { + v.addElement(vals.nextElement()); + } + String s[] = new String[v.size()]; + + v.copyInto(s); + String sorted = sortAndConcate(s).toLowerCase(); + NameAndObject no = (NameAndObject) mOCldapNames.get(sorted); + + if (no == null) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_INVALID_CLASS_NAME", sorted)); + } + Class c = (Class) no.getObject(); + + try { + IDBObj obj = (IDBObj) c.newInstance(); + Enumeration ee = obj.getSerializableAttrNames(); + + while (ee.hasMoreElements()) { + String oname = (String) ee.nextElement(); + IDBAttrMapper mapper = (IDBAttrMapper) + mAttrufNames.get( + oname.toLowerCase()); + + if (mapper == null) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_NO_MAPPER_FOUND", oname)); + } + mapper.mapLDAPAttributeSetToObject(attrs, + oname, obj); + } + return obj; + } catch (Exception e) { + + /*LogDoc + * + * @phase create ldap attr + * @reason failed to create object class + * @message DBRegistry: is not registered + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); + throw new EDBException(CMS.getUserMessage("CMS_DBS_INVALID_ATTRS")); + } + } + + /** + * Sorts and concate given strings. + */ + private String sortAndConcate(String s[]) { + Vector v = new Vector(); + + // sort it first + for (int i = 0; i < s.length; i++) { + for (int j = 0; j < v.size(); j++) { + String t = (String) v.elementAt(j); + + if (s[i].compareTo(t) < 0) { + v.insertElementAt(s[i], j); + break; + } + } + if (i != (v.size() - 1)) + v.addElement(s[i]); + } + + // concate them + String result = ""; + + for (int i = 0; i < v.size(); i++) { + result += ((String) v.elementAt(i) + "+"); + } + return result; + } +} + + +/** + * Just a convenient container class. + */ +class NameAndObject { + + private String mN = null; + private Object mO = null; + + public NameAndObject(String name, Object o) { + mN = name; + mO = o; + } + + public String getName() { + return mN; + } + + public Object getObject() { + return mO; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java new file mode 100644 index 000000000..03c86a219 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSSession.java @@ -0,0 +1,447 @@ +// --- 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.util.*; +import netscape.ldap.*; +import netscape.ldap.controls.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents the database session. Operations + * can be performed with a session. + * + * Transaction and Caching support can be integrated + * into session. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DBSSession implements IDBSSession { + + private IDBSubsystem mDBSystem = null; + private LDAPConnection mConn = null; + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs a database session. + * + * @param system the database subsytem + * @param c the ldap connection + */ + public DBSSession(IDBSubsystem system, LDAPConnection c) { + mDBSystem = system; + mConn = c; + try { + // no limit + mConn.setOption(LDAPv2.SIZELIMIT, Integer.valueOf(0)); + } catch (LDAPException e) { + } + } + + /** + * Returns database subsystem. + */ + public ISubsystem getDBSubsystem() { + return mDBSystem; + } + + /** + * Closes this session. + */ + public void close() throws EDBException { + // return ldap connection. + mDBSystem.returnConn(mConn); + } + + /** + * Adds object to backend database. For example, + *
+     *    session.add("cn=123459,o=certificate repository,o=airius.com",
+     * 			certRec);
+     * 
+ * + * @param name the name of the ldap entry + * @param obj the DBobj that can be mapped to ldap attrubute set + */ + public void add(String name, IDBObj obj) throws EBaseException { + try { + LDAPAttributeSet attrs = mDBSystem.getRegistry( + ).createLDAPAttributeSet(obj); + LDAPEntry e = new LDAPEntry(name, attrs); + + /*LogDoc + * + * @phase local ldap add + * @message DBSSession: begin LDAP add + */ + mConn.add(e); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + name + " " + e.toString())); + } + } + + /** + * Reads an object from the database. + * all attributes will be returned + * + * @param name the name of the ldap entry + */ + public IDBObj read(String name) throws EBaseException { + return read(name, null); + } + + /** + * Reads an object from the database, and only populates + * the selected attributes. + * + * @param name the name of the ldap entry + * @param attrs the attributes to be selected + */ + public IDBObj read(String name, String attrs[]) + throws EBaseException { + try { + String ldapattrs[] = null; + + if (attrs != null) { + ldapattrs = mDBSystem.getRegistry( + ).getLDAPAttributes(attrs); + } + + /*LogDoc + * + * @phase local ldap read + * @message DBSSession: begin LDAP read + */ + LDAPSearchResults res = mConn.search(name, + LDAPv2.SCOPE_BASE, "(objectclass=*)", + ldapattrs, false); + LDAPEntry entry = (LDAPEntry) res.nextElement(); + + return mDBSystem.getRegistry().createObject( + entry.getAttributeSet()); + } catch (LDAPException e) { + + /*LogDoc + * + * @phase local ldap read + * @message DBSSession: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_INFO, "DBSSession: " + e.toString()); + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) + throw new EDBRecordNotFoundException( + CMS.getUserMessage("CMS_DBS_RECORD_NOT_FOUND")); + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + name + " " + e.toString())); + } + } + + /** + * Deletes object from database. + */ + public void delete(String name) throws EBaseException { + try { + mConn.delete(name); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + name + " " + e.toString())); + } + } + + /** + * Modify an object in the database. + */ + public void modify(String name, ModificationSet mods) + throws EBaseException { + try { + LDAPModificationSet ldapMods = new + LDAPModificationSet(); + Enumeration e = mods.getModifications(); + + while (e.hasMoreElements()) { + Modification mod = (Modification) + e.nextElement(); + LDAPAttributeSet attrs = new LDAPAttributeSet(); + + mDBSystem.getRegistry().mapObject(null, + mod.getName(), mod.getValue(), attrs); + Enumeration e0 = attrs.getAttributes(); + + while (e0.hasMoreElements()) { + ldapMods.add(toLdapModOp(mod.getOp()), + (LDAPAttribute) + e0.nextElement()); + } + } + + /*LogDoc + * + * @phase local ldap add + * @message DBSSession: begin LDAP modify + */ + mConn.modify(name, ldapMods); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + name + " " + e.toString())); + } + } + + private int toLdapModOp(int modOp) throws EBaseException { + switch (modOp) { + case Modification.MOD_ADD: + return LDAPModification.ADD; + + case Modification.MOD_DELETE: + return LDAPModification.DELETE; + + case Modification.MOD_REPLACE: + return LDAPModification.REPLACE; + } + throw new EBaseException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + Integer.toString(modOp))); + } + + /** + * Searchs for a list of objects that match the + * filter. + */ + public IDBSearchResults search(String base, String filter) + throws EBaseException { + return search(base, filter, null); + } + + public IDBSearchResults search(String base, String filter, int maxSize) + throws EBaseException { + try { + String ldapattrs[] = null; + String ldapfilter = + mDBSystem.getRegistry().getFilter(filter); + + LDAPSearchConstraints cons = new LDAPSearchConstraints(); + + cons.setMaxResults(maxSize); + + LDAPSearchResults res = mConn.search(base, + LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); + + return new DBSearchResults(mDBSystem.getRegistry(), + res); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + // XXX error handling, should not raise exception if + // entry not found + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + e.toString())); + } + } + + public IDBSearchResults search(String base, String filter, int maxSize, int timeLimit) + throws EBaseException { + try { + String ldapattrs[] = null; + String ldapfilter = + mDBSystem.getRegistry().getFilter(filter); + + LDAPSearchConstraints cons = new LDAPSearchConstraints(); + + cons.setMaxResults(maxSize); + cons.setServerTimeLimit(timeLimit); + + LDAPSearchResults res = mConn.search(base, + LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); + + return new DBSearchResults(mDBSystem.getRegistry(), + res); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + // XXX error handling, should not raise exception if + // entry not found + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + e.toString())); + } + } + + /** + * Retrieves a list of object that satifies the given + * filter. + */ + public IDBSearchResults search(String base, String filter, + String attrs[]) throws EBaseException { + try { + String ldapattrs[] = null; + + if (attrs != null) { + ldapattrs = mDBSystem.getRegistry( + ).getLDAPAttributes(attrs); + } + String ldapfilter = + mDBSystem.getRegistry().getFilter(filter); + + /*LogDoc + * + * @phase local ldap add + * @message DBSSession: begin LDAP search + */ + LDAPSearchConstraints cons = new LDAPSearchConstraints(); + + cons.setMaxResults(0); + + LDAPSearchResults res = mConn.search(base, + LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); + + return new DBSearchResults(mDBSystem.getRegistry(), + res); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + // XXX error handling, should not raise exception if + // entry not found + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + e.toString())); + } + } + + public LDAPSearchResults persistentSearch(String base, String filter, String attrs[]) + throws EBaseException { + try { + String ldapattrs[] = null; + if (attrs != null) { + ldapattrs = mDBSystem.getRegistry( + ).getLDAPAttributes(attrs); + } + String ldapfilter = + mDBSystem.getRegistry().getFilter(filter); + + Integer version = (Integer)(mConn.getOption(LDAPv2.PROTOCOL_VERSION)); + + // Only version 3 protocol supports persistent search. + if (version.intValue() == 2) { + mConn.setOption(LDAPv2.PROTOCOL_VERSION, Integer.valueOf(3)); + } + + int op = LDAPPersistSearchControl.MODIFY; + + boolean changesOnly = true; + boolean returnControls = true; + boolean isCritical = true; + LDAPPersistSearchControl persistCtrl = new + LDAPPersistSearchControl( op, changesOnly, + returnControls, isCritical ); + + LDAPSearchConstraints cons = new LDAPSearchConstraints(); + cons.setBatchSize(0); + cons.setServerControls( persistCtrl ); + + LDAPSearchResults res = mConn.search(base, + LDAPv2.SCOPE_ONE, ldapfilter, ldapattrs, false, cons); + return res; + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.UNAVAILABLE) + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + // XXX error handling, should not raise exception if + // entry not found + throw new EDBException(CMS.getUserMessage("CMS_DBS_LDAP_OP_FAILURE", + e.toString())); + } + } + + /** + * Retrieves a list of objects. + */ + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[]) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs); + } + + /** + * Retrieves a list of objects. + */ + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[], String sortKey[]) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs, sortKey); + } + + /** + * Retrieves a list of objects. + */ + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[], String sortKey) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs, sortKey); + } + + /** + * Retrieves a list of objects. + */ + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[], String sortKey[], int pageSize) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs, sortKey, pageSize); + } + + /** + * Retrieves a list of objects. + */ + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[], String sortKey, int pageSize) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs, sortKey, pageSize); + } + + public IDBVirtualList createVirtualList(String base, String filter, + String attrs[], String startFrom, String sortKey, int pageSize) throws EBaseException { + return new DBVirtualList(mDBSystem.getRegistry(), mConn, base, + filter, attrs, startFrom, sortKey, pageSize); + + } + + /** + * Releases object to this interface. This allows us to + * use memory more efficiently. + */ + public void release(Object obj) { + // not implemented + } + +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java new file mode 100644 index 000000000..475a77dcb --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSUtil.java @@ -0,0 +1,56 @@ +// --- 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.util.*; +import java.math.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java BigInteger object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DBSUtil { + + public static String longToDB(long val) { + String s = Long.toString(val); + // prefix with 2 digits that represents + // the length of the value + int l = s.length(); + String dbVal = ""; + + if (s.length() < 10) { + dbVal = "0"; + } + return dbVal + Integer.toString(l) + s; + } + + public static long longFromDB(String dbLong) { + // remove the first 2 digits + String s = dbLong.substring(2); + + return Long.parseLong(s); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java new file mode 100644 index 000000000..b7f6cd616 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSearchResults.java @@ -0,0 +1,92 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents the search results. A search + * results object contain a enumeration of + * Java objects that are just read from the database. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DBSearchResults implements IDBSearchResults { + + private IDBRegistry mRegistry = null; + private Enumeration mRes = null; + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs search results. + */ + public DBSearchResults(IDBRegistry registry, Enumeration res) { + mRegistry = registry; + mRes = res; + } + + /** + * Checks if any element is available. + */ + public boolean hasMoreElements() { + return mRes.hasMoreElements(); + } + + /** + * Retrieves next element. + */ + public Object nextElement() { + LDAPEntry entry = null; + + try { + Object o = mRes.nextElement(); + + if (o instanceof LDAPEntry) { + entry = (LDAPEntry) o; + return mRegistry.createObject(entry.getAttributeSet()); + } else { + if (o instanceof LDAPException) + ; + // doing nothing because the last object in the search + // results is always LDAPException + else + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, "DBSearchResults: result format error class=" + o.getClass().getName()); + } + } catch (Exception e) { + + /*LogDoc + * + * @phase local ldap search + * @reason failed to get next element + * @message DBSearchResults: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, "DBSearchResults: " + e.toString()); + } + return null; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java new file mode 100644 index 000000000..797dd8324 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java @@ -0,0 +1,951 @@ +// --- 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.math.*; +import java.io.*; +import java.util.*; +import netscape.ldap.*; +import netscape.ldap.util.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.repository.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmscore.base.*; +import com.netscape.cmscore.ldapconn.*; +import com.netscape.cmscore.cert.*; + + +/** + * A class represents the database subsystem that manages + * the backend data storage. + * + * This subsystem maintains multiple sessions that allows + * operations to be performed, and provide a registry + * where all the schema information is stored. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DBSubsystem implements IDBSubsystem { + + public static String ID = IDBSubsystem.SUB_ID; + + private IConfigStore mConfig = null; + private IConfigStore mDBConfig = null; + private LdapBoundConnFactory mLdapConnFactory = null; + private DBRegistry mRegistry = null; + private String mBaseDN = null; + private ISubsystem mOwner = null; + + private Hashtable[] mRepos = null; + + private BigInteger mNextSerialConfig = null; + private boolean mEnableSerialMgmt = false; + + private static final String PEOPLE_DN = "ou=people"; + private static final String GROUPS_DN = "ou=groups"; + private static final String REQUESTS_DN = "ou=requests"; + private static final String XCERTS_DN = "cn=crossCerts"; + private static final String BASEDN = "o=netscapeCertificateServer"; + private static final String DEFAULT_DATABASE = "userRoot"; + private static final String AT_OC = "objectclass"; + private static final String AT_O = "o"; + private static final String AT_OU = "ou"; + private static final String CA_DN = "ou=ca"; + private static final String CR_DN = "ou=certificateRepository, ou=ca"; + private static final String CRL_DN = "ou=crlIssuingPoints, ou=ca"; + private static final String CA_REQUESTS_DN = "ou=ca, ou=requests"; + private static final String KRA_DN = "ou=kra"; + private static final String KR_DN = "ou=keyRepository, ou=kra"; + private static final String KRA_REQUESTS_DN = "ou=kra, ou=requests"; + private static final String REPLICA_DN = "ou=replica"; + private static final String PROP_ENABLE_SERIAL_NUMBER_RECOVERY = + "enableSerialNumberRecovery"; + // This value is only equal to the next Serial number that the CA's + // going to issue when cms just start up or it's just set from console. + // It doesn't record the next serial number at other time when cms's + // runing not to increase overhead when issuing certs. + private static final String PROP_NEXT_SERIAL_NUMBER = + "nextSerialNumber"; + private static final String PROP_MIN_SERIAL_NUMBER="beginSerialNumber"; + private static final String PROP_MAX_SERIAL_NUMBER = "endSerialNumber"; + private static final String PROP_NEXT_MIN_SERIAL_NUMBER="nextBeginSerialNumber"; + private static final String PROP_NEXT_MAX_SERIAL_NUMBER ="nextEndSerialNumber"; + private static final String PROP_SERIAL_LOW_WATER_MARK="serialLowWaterMark"; + private static final String PROP_SERIAL_INCREMENT="serialIncrement"; + private static final String PROP_SERIAL_BASEDN="serialDN"; + private static final String PROP_SERIAL_RANGE_DN="serialRangeDN"; + + private static final String PROP_MIN_REQUEST_NUMBER="beginRequestNumber"; + private static final String PROP_MAX_REQUEST_NUMBER="endRequestNumber"; + private static final String PROP_NEXT_MIN_REQUEST_NUMBER="nextBeginRequestNumber"; + private static final String PROP_NEXT_MAX_REQUEST_NUMBER="nextEndRequestNumber"; + private static final String PROP_REQUEST_LOW_WATER_MARK="requestLowWaterMark"; + private static final String PROP_REQUEST_INCREMENT="requestIncrement"; + private static final String PROP_REQUEST_BASEDN="requestDN"; + private static final String PROP_REQUEST_RANGE_DN="requestRangeDN"; + + private static final String PROP_MIN_REPLICA_NUMBER="beginReplicaNumber"; + private static final String PROP_MAX_REPLICA_NUMBER = "endReplicaNumber"; + private static final String PROP_NEXT_MIN_REPLICA_NUMBER="nextBeginReplicaNumber"; + private static final String PROP_NEXT_MAX_REPLICA_NUMBER ="nextEndReplicaNumber"; + private static final String PROP_REPLICA_LOW_WATER_MARK="replicaLowWaterMark"; + private static final String PROP_REPLICA_INCREMENT="replicaIncrement"; + private static final String PROP_REPLICA_BASEDN="replicaDN"; + private static final String PROP_REPLICA_RANGE_DN="replicaRangeDN"; + + private static final String PROP_INFINITE_SERIAL_NUMBER = "1000000000"; + private static final String PROP_INFINITE_REQUEST_NUMBER = "1000000000"; + private static final String PROP_INFINITE_REPLICA_NUMBER = "1000"; + private static final String PROP_BASEDN = "basedn"; + private static final String PROP_LDAP = "ldap"; + private static final String PROP_NEXT_RANGE = "nextRange"; + private static final String PROP_ENABLE_SERIAL_MGMT = "enableSerialManagement"; + + // hash keys + private static final String NAME="name"; + private static final String PROP_MIN="min"; + private static final String PROP_MIN_NAME="min_name"; + private static final String PROP_MAX = "max"; + private static final String PROP_MAX_NAME = "max_name"; + private static final String PROP_NEXT_MIN="next_min"; + private static final String PROP_NEXT_MIN_NAME="next_min_name"; + private static final String PROP_NEXT_MAX = "next_max"; + private static final String PROP_NEXT_MAX_NAME = "next_max_name"; + private static final String PROP_LOW_WATER_MARK="lowWaterMark"; + private static final String PROP_LOW_WATER_MARK_NAME="lowWaterMark_name"; + private static final String PROP_INCREMENT = "increment"; + private static final String PROP_INCREMENT_NAME = "increment_name"; + private static final String PROP_RANGE_DN="rangeDN"; + + private static final BigInteger BI_ONE = new BigInteger("1"); + + private ILogger mLogger = null; + + // singleton enforcement + + private static IDBSubsystem mInstance = new DBSubsystem(); + + public static IDBSubsystem getInstance() { + return mInstance; + } + + /** + * This method is used for unit tests. It allows the underlying instance + * to be stubbed out. + * @param dbSubsystem The stubbed out subsystem to override with. + */ + public static void setInstance(IDBSubsystem dbSubsystem) { + mInstance = dbSubsystem; + } + + // end singleton enforcement. + + /** + * Constructs database subsystem. + */ + private DBSubsystem() { + } + + /** + * Retrieves subsystem identifier. + */ + public String getId() { + return IDBSubsystem.SUB_ID; + } + + /** + * Sets subsystem identifier. + */ + public void setId(String id) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_OPERATION")); + } + + public boolean enableSerialNumberRecovery() { + try { + return mDBConfig.getBoolean( + PROP_ENABLE_SERIAL_NUMBER_RECOVERY, true); + } catch (EBaseException e) { + // by default + return true; + } + } + + public boolean getEnableSerialMgmt() { + return mEnableSerialMgmt; + } + + public void setEnableSerialMgmt(boolean v) + throws EBaseException { + if (v) { + CMS.debug("DBSubsystem: Enabling Serial Number Management"); + } else { + CMS.debug("DBSubsystem: Disabling Serial Number Management"); + } + + mDBConfig.putBoolean(PROP_ENABLE_SERIAL_MGMT, v); + IConfigStore rootStore = getOwner().getConfigStore(); + rootStore.commit(false); + mEnableSerialMgmt = v; + } + + public BigInteger getNextSerialConfig() { + return mNextSerialConfig; + } + + public void setNextSerialConfig(BigInteger serial) + throws EBaseException { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_INFO, "DBSubsystem: " + + "Setting next serial number: 0x" + serial.toString(16)); + mDBConfig.putString(PROP_NEXT_SERIAL_NUMBER, + serial.toString(16)); + } + + /** + * Gets minimum serial number limit in config file + * + * @param repo repo identifier + * @return min serial number + */ + public String getMinSerialConfig(int repo) + { + return (String) (mRepos[repo]).get(PROP_MIN); + } + + /** + * Gets maximum serial number limit in config file + * + * @param repo repo identifier + * @return max serial number + */ + public String getMaxSerialConfig(int repo) { + return (String) (mRepos[repo]).get(PROP_MAX); + } + + /** + * Gets minimum serial number limit in next range in config file + * + * @param repo repo identifier + * @return min serial number in next range + */ + public String getNextMinSerialConfig(int repo) + { + String ret = (String) (mRepos[repo]).get(PROP_NEXT_MIN); + if (ret.equals("-1")) { + return null; + } + else { + return ret; + } + } + + /** + * Gets maximum serial number limit in next range in config file + * + * @param repo repo identifier + * @return max serial number in next range + */ + public String getNextMaxSerialConfig(int repo) { + String ret = (String) (mRepos[repo]).get(PROP_NEXT_MAX); + if (ret.equals("-1")) { + return null; + } + else { + return ret; + } + } + + /** + * Gets low water mark limit in config file + * + * @param repo repo identifier + * @return low water mark + */ + public String getLowWaterMarkConfig(int repo) { + return (String) (mRepos[repo]).get(PROP_LOW_WATER_MARK); + } + + /** + * Gets range increment for next range in config file + * + * @param repo repo identifier + * @return range increment + */ + public String getIncrementConfig(int repo) + { + return (String) (mRepos[repo]).get(PROP_INCREMENT); + } + + /** + * Sets maximum serial number limit in config file + * + * @param repo repo identifier + * @param serial max serial number + * @exception EBaseException failed to set + */ + public void setMaxSerialConfig(int repo, String serial) + throws EBaseException { + Hashtable h = mRepos[repo]; + CMS.debug("DBSubsystem: Setting max serial number for " + h.get(NAME) + ": " + serial); + + //persist to file + mDBConfig.putString((String) h.get(PROP_MAX_NAME), serial); + IConfigStore rootStore = getOwner().getConfigStore(); + rootStore.commit(false); + + h.put(PROP_MAX, serial); + mRepos[repo] = h; + } + + /** + * Sets minimum serial number limit in config file + * + * @param repo repo identifier + * @param serial min serial number + * @exception EBaseException failed to set + */ + public void setMinSerialConfig(int repo, String serial) + throws EBaseException { + Hashtable h = mRepos[repo]; + CMS.debug("DBSubsystem: Setting min serial number for " + h.get(NAME) + ": " + serial); + + //persist to file + mDBConfig.putString((String) h.get(PROP_MIN_NAME), serial); + IConfigStore rootStore = getOwner().getConfigStore(); + rootStore.commit(false); + + h.put(PROP_MIN, serial); + mRepos[repo] = h; + } + + /** + * Sets maximum serial number limit for next range in config file + * + * @param repo repo identifier + * @param serial max serial number for next range + * @exception EBaseException failed to set + */ + public void setNextMaxSerialConfig(int repo, String serial) + throws EBaseException { + Hashtable h = mRepos[repo]; + if (serial == null) { + CMS.debug("DBSubsystem: Removing next max " + h.get(NAME) + " number"); + mDBConfig.remove((String) h.get(PROP_NEXT_MAX_NAME)); + } else { + CMS.debug("DBSubsystem: Setting next max " + h.get(NAME) + " number: " + serial); + mDBConfig.putString((String) h.get(PROP_NEXT_MAX_NAME), serial); + } + IConfigStore rootStore = getOwner().getConfigStore(); + rootStore.commit(false); + if (serial == null) { + Object o2 = h.remove(PROP_NEXT_MAX); + } else { + h.put(PROP_NEXT_MAX, serial); + } + mRepos[repo] = h; + } + + /** + * Sets minimum serial number limit for next range in config file + * + * @param repo repo identifier + * @param serial min serial number for next range + * @exception EBaseException failed to set + */ + public void setNextMinSerialConfig(int repo, String serial) + throws EBaseException { + Hashtable h = mRepos[repo]; + if (serial == null) { + CMS.debug("DBSubsystem: Removing next min " + h.get(NAME) + " number"); + mDBConfig.remove((String) h.get(PROP_NEXT_MIN_NAME)); + } else { + CMS.debug("DBSubsystem: Setting next min " + h.get(NAME) + " number: " + serial); + mDBConfig.putString((String) h.get(PROP_NEXT_MIN_NAME), serial); + } + IConfigStore rootStore = getOwner().getConfigStore(); + rootStore.commit(false); + if (serial == null) { + Object o2 = h.remove(PROP_NEXT_MIN); + } else { + h.put(PROP_NEXT_MIN, serial); + } + mRepos[repo] = h; + } + + /** + * Gets start of next range from database. + * Increments the nextRange attribute and allocates + * this range to the current instance by creating a pkiRange object. + * + * @param repo repo identifier + * @return start of next range + */ + public String getNextRange(int repo) { + LDAPConnection conn = null; + String nextRange = null; + try { + Hashtable h = mRepos[repo]; + conn = mLdapConnFactory.getConn(); + String dn = (String) h.get(PROP_BASEDN) + "," + mBaseDN; + String rangeDN = (String) h.get(PROP_RANGE_DN) + "," + mBaseDN; + + LDAPEntry entry = conn.read(dn); + LDAPAttribute attr = entry.getAttribute(PROP_NEXT_RANGE); + nextRange = (String) attr.getStringValues().nextElement(); + + BigInteger nextRangeNo = new BigInteger(nextRange); + if (nextRangeNo == null) { + throw new EBaseException("nextRangeNo is null!"); + } + + BigInteger incrementNo = new BigInteger((String) h.get(PROP_INCREMENT)); + if (incrementNo == null) { + throw new EBaseException("incrementNo is null!"); + } + + // To make sure attrNextRange always increments, first delete the current value and then + // increment. Two operations in the same transaction + + LDAPAttribute attrNextRange = new LDAPAttribute(PROP_NEXT_RANGE, nextRangeNo.add(incrementNo).toString()); + LDAPModification [] mods = { + new LDAPModification( LDAPModification.DELETE, attr), + new LDAPModification( LDAPModification.ADD, attrNextRange ) }; + conn.modify( dn, mods ); + + // Add new range object + String endRange = nextRangeNo.add(incrementNo).subtract(BI_ONE).toString(); + LDAPAttributeSet attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectClass", "top")); + attrs.add(new LDAPAttribute("objectClass", "pkiRange")); + attrs.add(new LDAPAttribute("beginRange" , nextRange)); + attrs.add(new LDAPAttribute("endRange" , endRange)); + attrs.add(new LDAPAttribute("cn", nextRange)); + attrs.add(new LDAPAttribute("host", CMS.getEESSLHost())); + attrs.add(new LDAPAttribute("securePort", CMS.getEESSLPort())); + String dn2 = "cn=" + nextRange + "," + rangeDN; + LDAPEntry rangeEntry = new LDAPEntry(dn2, attrs); + conn.add(rangeEntry); + } catch (Exception e) { + CMS.debug("DBSubsystem: getNextRange. Unable to provide next range :" + e); + e.printStackTrace(); + nextRange = null; + } finally { + try { + if ((conn != null) && (mLdapConnFactory!= null)) { + CMS.debug("Releasing ldap connection"); + mLdapConnFactory.returnConn(conn); + } + } + catch (Exception e) { + CMS.debug("Error releasing the ldap connection" + e.toString()); + } + } + return nextRange; + } + + /** + * Determines if a range conflict has been observed in database. + * If so, delete the conflict entry and remove the next range. + * When the next number is requested, if the number of certs is still + * below the low water mark, then a new range will be requested. + * + * @param repo repo identifier + * @return true if range conflict, false otherwise + */ + public boolean hasRangeConflict(int repo) + { + LDAPConnection conn = null; + boolean conflict = false; + try { + String nextRangeStart = getNextMinSerialConfig(repo); + if (nextRangeStart == null) { + return false; + } + Hashtable h = mRepos[repo]; + conn = mLdapConnFactory.getConn(); + String rangedn = (String) h.get(PROP_RANGE_DN) + "," + mBaseDN; + String filter = "(&(nsds5ReplConflict=*)(objectClass=pkiRange)(host= " + + CMS.getEESSLHost() + ")(SecurePort=" + CMS.getEESSLPort() + + ")(beginRange=" + nextRangeStart + "))"; + LDAPSearchResults results = conn.search(rangedn, LDAPv3.SCOPE_SUB, + filter, null, false); + + while (results.hasMoreElements()) { + conflict = true; + LDAPEntry entry = results.next(); + String dn = entry.getDN(); + CMS.debug("Deleting conflict entry:" + dn); + conn.delete(dn); + } + } catch (Exception e) { + CMS.debug("DBSubsystem: hasRangeConflict. Error while checking next range." + e); + e.printStackTrace(); + } finally { + try { + if ((conn != null) && (mLdapConnFactory!= null)) { + CMS.debug("Releasing ldap connection"); + mLdapConnFactory.returnConn(conn); + } + } + catch (Exception e) { + CMS.debug("Error releasing the ldap connection" + e.toString()); + } + } + return conflict; + } + + public ISubsystem getOwner() { + return mOwner; + } + + /** + * Initializes the internal registery. Connects to the + * data source, and create a pool of connection of which + * applications can use. Optionally, check the integrity + * of the database. + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + + + mLogger = CMS.getLogger(); + mDBConfig = config; + mRepos = new Hashtable[IDBSubsystem.NUM_REPOS]; + + mConfig = config.getSubStore(PROP_LDAP); + IConfigStore tmpConfig = null; + try { + mBaseDN = mConfig.getString(PROP_BASEDN, "o=NetscapeCertificateServer"); + + mOwner = owner; + + mNextSerialConfig = new BigInteger(mDBConfig.getString( + PROP_NEXT_SERIAL_NUMBER, "0"), 16); + + mEnableSerialMgmt = mDBConfig.getBoolean(PROP_ENABLE_SERIAL_MGMT, false); + + // populate the certs hash entry + Hashtable certs = new Hashtable(); + certs.put(NAME, "certs"); + certs.put(PROP_BASEDN, mDBConfig.getString(PROP_SERIAL_BASEDN,"")); + certs.put(PROP_RANGE_DN, mDBConfig.getString(PROP_SERIAL_RANGE_DN, "")); + + certs.put(PROP_MIN_NAME, PROP_MIN_SERIAL_NUMBER); + certs.put(PROP_MIN, mDBConfig.getString( + PROP_MIN_SERIAL_NUMBER, "0")); + + certs.put(PROP_MAX_NAME, PROP_MAX_SERIAL_NUMBER); + certs.put(PROP_MAX, mDBConfig.getString( + PROP_MAX_SERIAL_NUMBER, PROP_INFINITE_SERIAL_NUMBER)); + + certs.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_SERIAL_NUMBER); + certs.put(PROP_NEXT_MIN, mDBConfig.getString( + PROP_NEXT_MIN_SERIAL_NUMBER, "-1")); + + certs.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_SERIAL_NUMBER); + certs.put(PROP_NEXT_MAX, mDBConfig.getString( + PROP_NEXT_MAX_SERIAL_NUMBER, "-1")); + + certs.put(PROP_LOW_WATER_MARK_NAME, PROP_SERIAL_LOW_WATER_MARK); + certs.put(PROP_LOW_WATER_MARK, mDBConfig.getString( + PROP_SERIAL_LOW_WATER_MARK, "5000")); + + certs.put(PROP_INCREMENT_NAME, PROP_SERIAL_INCREMENT); + certs.put(PROP_INCREMENT, mDBConfig.getString( + PROP_SERIAL_INCREMENT, PROP_INFINITE_SERIAL_NUMBER)); + + mRepos[CERTS]=certs; + + // populate the requests hash entry + Hashtable requests = new Hashtable(); + requests.put(NAME, "requests"); + requests.put(PROP_BASEDN, mDBConfig.getString(PROP_REQUEST_BASEDN,"")); + requests.put(PROP_RANGE_DN, mDBConfig.getString(PROP_REQUEST_RANGE_DN, "")); + + requests.put(PROP_MIN_NAME, PROP_MIN_REQUEST_NUMBER); + requests.put(PROP_MIN, mDBConfig.getString( + PROP_MIN_REQUEST_NUMBER, "0")); + + requests.put(PROP_MAX_NAME, PROP_MAX_REQUEST_NUMBER); + requests.put(PROP_MAX, mDBConfig.getString( + PROP_MAX_REQUEST_NUMBER, PROP_INFINITE_REQUEST_NUMBER)); + + requests.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_REQUEST_NUMBER); + requests.put(PROP_NEXT_MIN, mDBConfig.getString( + PROP_NEXT_MIN_REQUEST_NUMBER, "-1")); + + requests.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_REQUEST_NUMBER); + requests.put(PROP_NEXT_MAX, mDBConfig.getString( + PROP_NEXT_MAX_REQUEST_NUMBER, "-1")); + + requests.put(PROP_LOW_WATER_MARK_NAME, PROP_REQUEST_LOW_WATER_MARK); + requests.put(PROP_LOW_WATER_MARK, mDBConfig.getString( + PROP_REQUEST_LOW_WATER_MARK, "5000")); + + requests.put(PROP_INCREMENT_NAME, PROP_REQUEST_INCREMENT); + requests.put(PROP_INCREMENT, mDBConfig.getString( + PROP_REQUEST_INCREMENT, PROP_INFINITE_REQUEST_NUMBER)); + + mRepos[REQUESTS] = requests; + + // populate replica ID hash entry + Hashtable replicaID = new Hashtable(); + replicaID.put(NAME, "requests"); + replicaID.put(PROP_BASEDN, mDBConfig.getString(PROP_REPLICA_BASEDN,"")); + replicaID.put(PROP_RANGE_DN, mDBConfig.getString(PROP_REPLICA_RANGE_DN, "")); + + replicaID.put(PROP_MIN_NAME, PROP_MIN_REPLICA_NUMBER); + replicaID.put(PROP_MIN, mDBConfig.getString( + PROP_MIN_REPLICA_NUMBER, "1")); + + replicaID.put(PROP_MAX_NAME, PROP_MAX_REPLICA_NUMBER); + replicaID.put(PROP_MAX, mDBConfig.getString( + PROP_MAX_REPLICA_NUMBER, PROP_INFINITE_REPLICA_NUMBER)); + + replicaID.put(PROP_NEXT_MIN_NAME, PROP_NEXT_MIN_REPLICA_NUMBER); + replicaID.put(PROP_NEXT_MIN, mDBConfig.getString( + PROP_NEXT_MIN_REPLICA_NUMBER, "-1")); + + replicaID.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_REPLICA_NUMBER); + replicaID.put(PROP_NEXT_MAX, mDBConfig.getString( + PROP_NEXT_MAX_REPLICA_NUMBER, "-1")); + + replicaID.put(PROP_LOW_WATER_MARK_NAME, PROP_REPLICA_LOW_WATER_MARK); + replicaID.put(PROP_LOW_WATER_MARK, mDBConfig.getString( + PROP_REPLICA_LOW_WATER_MARK, "10")); + + replicaID.put(PROP_INCREMENT_NAME, PROP_REPLICA_INCREMENT); + replicaID.put(PROP_INCREMENT, mDBConfig.getString( + PROP_REPLICA_INCREMENT, PROP_INFINITE_REPLICA_NUMBER)); + + mRepos[REPLICA_ID] = replicaID; + + + // initialize registry + mRegistry = new DBRegistry(); + mRegistry.init(this, null); + + // initialize LDAP connection factory + // by default return error if server is down at startup time. + mLdapConnFactory = new LdapBoundConnFactory(true); + tmpConfig = (IConfigStore) (((PropConfigStore) mConfig).clone()); + + tmpConfig.putString(PROP_BASEDN, mBaseDN); + } catch (EBaseException e) { + if (CMS.isPreOpMode()) + return; + throw e; + } + + try { + mLdapConnFactory.init(tmpConfig); + } catch (ELdapServerDownException e) { + if (CMS.isPreOpMode()) + return; + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + } catch (ELdapException ex) { + if (CMS.isPreOpMode()) + return; + throw new EDBException(CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_ERROR", ex.toString())); + } catch (EBaseException e) { + if (CMS.isPreOpMode()) + return; + throw e; + } + + try { + // registers CMS database attributes + IDBRegistry reg = getRegistry(); + + String certRecordOC[] = new String[2]; + + certRecordOC[0] = CertDBSchema.LDAP_OC_TOP; + certRecordOC[1] = CertDBSchema.LDAP_OC_CERT_RECORD; + + if (!reg.isObjectClassRegistered(CertRecord.class.getName())) { + reg.registerObjectClass(CertRecord.class.getName(), + certRecordOC); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_ID)) { + reg.registerAttribute(CertRecord.ATTR_ID, new + BigIntegerMapper(CertDBSchema.LDAP_ATTR_SERIALNO)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_META_INFO)) { + reg.registerAttribute(CertRecord.ATTR_META_INFO, new + MetaInfoMapper(CertDBSchema.LDAP_ATTR_META_INFO)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_REVO_INFO)) { + reg.registerAttribute(CertRecord.ATTR_REVO_INFO, new + RevocationInfoMapper()); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_X509CERT)) { + reg.registerAttribute(CertRecord.ATTR_X509CERT, new + X509CertImplMapper()); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_CERT_STATUS)) { + reg.registerAttribute(CertRecord.ATTR_CERT_STATUS, new + StringMapper(CertDBSchema.LDAP_ATTR_CERT_STATUS)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_AUTO_RENEW)) { + reg.registerAttribute(CertRecord.ATTR_AUTO_RENEW, new + StringMapper(CertDBSchema.LDAP_ATTR_AUTO_RENEW)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_CREATE_TIME)) { + reg.registerAttribute(CertRecord.ATTR_CREATE_TIME, new + DateMapper(CertDBSchema.LDAP_ATTR_CREATE_TIME)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_MODIFY_TIME)) { + reg.registerAttribute(CertRecord.ATTR_MODIFY_TIME, new + DateMapper(CertDBSchema.LDAP_ATTR_MODIFY_TIME)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_ISSUED_BY)) { + reg.registerAttribute(CertRecord.ATTR_ISSUED_BY, new + StringMapper(CertDBSchema.LDAP_ATTR_ISSUED_BY)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_REVOKED_BY)) { + reg.registerAttribute(CertRecord.ATTR_REVOKED_BY, new + StringMapper(CertDBSchema.LDAP_ATTR_REVOKED_BY)); + } + if (!reg.isAttributeRegistered(CertRecord.ATTR_REVOKED_ON)) { + reg.registerAttribute(CertRecord.ATTR_REVOKED_ON, new + DateMapper(CertDBSchema.LDAP_ATTR_REVOKED_ON)); + } + + if (!reg.isAttributeRegistered(CertificateValidity.NOT_AFTER)) { + reg.registerAttribute(CertificateValidity.NOT_AFTER, new + DateMapper(CertDBSchema.LDAP_ATTR_NOT_AFTER)); + } + + if (!reg.isAttributeRegistered(CertificateValidity.NOT_BEFORE)) { + reg.registerAttribute(CertificateValidity.NOT_BEFORE, new + DateMapper(CertDBSchema.LDAP_ATTR_NOT_BEFORE)); + } + + String crlRecordOC[] = new String[2]; + + crlRecordOC[0] = CRLDBSchema.LDAP_OC_TOP; + crlRecordOC[1] = CRLDBSchema.LDAP_OC_CRL_RECORD; + reg.registerObjectClass(CRLIssuingPointRecord.class.getName(), + crlRecordOC); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_ID, new + StringMapper(CRLDBSchema.LDAP_ATTR_CRL_ID)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_NUMBER, new + BigIntegerMapper(CRLDBSchema.LDAP_ATTR_CRL_NUMBER)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_NUMBER, new + BigIntegerMapper(CRLDBSchema.LDAP_ATTR_DELTA_NUMBER)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_SIZE, new + LongMapper(CRLDBSchema.LDAP_ATTR_CRL_SIZE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_SIZE, new + LongMapper(CRLDBSchema.LDAP_ATTR_DELTA_SIZE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_THIS_UPDATE, new + DateMapper(CRLDBSchema.LDAP_ATTR_THIS_UPDATE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_NEXT_UPDATE, new + DateMapper(CRLDBSchema.LDAP_ATTR_NEXT_UPDATE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_FIRST_UNSAVED, new + StringMapper(CRLDBSchema.LDAP_ATTR_FIRST_UNSAVED)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL, new + ByteArrayMapper(CRLDBSchema.LDAP_ATTR_CRL)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_DELTA_CRL, new + ByteArrayMapper(CRLDBSchema.LDAP_ATTR_DELTA_CRL)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CA_CERT, new + ByteArrayMapper(CRLDBSchema.LDAP_ATTR_CA_CERT)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_CRL_CACHE, new + ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_CRL_CACHE)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_REVOKED_CERTS, new + ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_REVOKED_CERTS)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_UNREVOKED_CERTS, new + ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_UNREVOKED_CERTS)); + reg.registerAttribute(ICRLIssuingPointRecord.ATTR_EXPIRED_CERTS, new + ObjectStreamMapper(CRLDBSchema.LDAP_ATTR_EXPIRED_CERTS)); + + if (!reg.isObjectClassRegistered( + RepositoryRecord.class.getName())) { + String repRecordOC[] = new String[2]; + + repRecordOC[0] = RepositorySchema.LDAP_OC_TOP; + repRecordOC[1] = RepositorySchema.LDAP_OC_REPOSITORY; + reg.registerObjectClass( + RepositoryRecord.class.getName(), repRecordOC); + } + if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_SERIALNO)) { + reg.registerAttribute(IRepositoryRecord.ATTR_SERIALNO, + new BigIntegerMapper(RepositorySchema.LDAP_ATTR_SERIALNO)); + } + if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_PUB_STATUS)) { + reg.registerAttribute(IRepositoryRecord.ATTR_PUB_STATUS, + new StringMapper(RepositorySchema.LDAP_ATTR_PUB_STATUS)); + } + + } catch (EBaseException e) { + if (CMS.isPreOpMode()) + return; + throw e; + } + } + + /** + * Starts up this service. + */ + public void startup() throws EBaseException { + } + + /** + * Retrieves configuration store. + */ + public IConfigStore getConfigStore() { + return mConfig; + } + + /** + * Retrieves base DN of backend database. + */ + public String getBaseDN() { + return mBaseDN; + } + + /** + * Retrieves LDAP connection info (host, port, secure) + */ + public LdapConnInfo getLdapConnInfo() { + if (mLdapConnFactory != null) + return mLdapConnFactory.getConnInfo(); + return null; + } + + public LdapAuthInfo getLdapAuthInfo() { + if (mLdapConnFactory != null) + return mLdapConnFactory.getAuthInfo(); + return null; + } + + /** + * Shutdowns this subsystem gracefully. + */ + public void shutdown() { + try { + if (mLdapConnFactory != null) { + mLdapConnFactory.reset(); + mLdapConnFactory = null; + } + } catch (ELdapException e) { + + /*LogDoc + * + * @phase shutdown server + * @reason shutdown db subsystem + * @message DBSubsystem: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, + ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); + } + if (mRegistry != null) + mRegistry.shutdown(); + } + + /** + * Retrieves the registry. + */ + public IDBRegistry getRegistry() { + return mRegistry; + } + + /** + * Creates a database session. + */ + public IDBSSession createSession() throws EDBException { + LDAPConnection conn = null; + + try { + conn = mLdapConnFactory.getConn(); + + String schemaAdded = mDBConfig.getString("newSchemaEntryAdded", ""); + + if (schemaAdded.equals("")) { + LDAPSchema dirSchema = new LDAPSchema(); + + // create new attribute: userType + dirSchema.fetchSchema(conn); + LDAPAttributeSchema userType = dirSchema.getAttribute("usertype"); + + if (userType == null) { + userType = new LDAPAttributeSchema("usertype", "usertype-oid", + "Distinguish whether the user is administrator, agent or subsystem.", + LDAPAttributeSchema.cis, false); + userType.add(conn); + } + + // create new objectclass: cmsuser + dirSchema.fetchSchema(conn); + LDAPObjectClassSchema newObjClass = dirSchema.getObjectClass("cmsuser"); + String[] requiredAttrs = {"usertype"}; + String[] optionalAttrs = new String[0]; + + if (newObjClass == null) { + newObjClass = new LDAPObjectClassSchema("cmsuser", "cmsuser-oid", + "top", "CMS User", requiredAttrs, optionalAttrs); + newObjClass.add(conn); + } + mDBConfig.putString("newSchemaEntryAdded", "true"); + IConfigStore rootStore = getOwner().getConfigStore(); + + rootStore.commit(false); + } + } catch (ELdapException e) { + if (e instanceof ELdapServerDownException) { + throw new EDBNotAvailException( + CMS.getUserMessage("CMS_DBS_INTERNAL_DIR_UNAVAILABLE")); + } + + /*LogDoc + * + * @phase create db session + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_CONN_ERROR", e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_CONNECT_LDAP_FAILED", e.toString())); + } catch (LDAPException e) { + if (e.getLDAPResultCode() != 20) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_SCHEMA_ERROR", e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_ADD_ENTRY_FAILED", e.toString())); + } + } catch (EBaseException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_CONF_ERROR", + e.toString())); + } + return new DBSSession(this, conn); + } + + public void returnConn(LDAPConnection conn) { + mLdapConnFactory.returnConn(conn); + } + +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java new file mode 100644 index 000000000..8a3b3cba7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBVirtualList.java @@ -0,0 +1,769 @@ +// --- 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.util.*; +import netscape.ldap.*; +import netscape.ldap.controls.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents a virtual list of search results. + * Note that this class must be used with DS4.0. + * + * @author thomask + * @author mzhao + * @version $Revision$, $Date$ + */ +public class DBVirtualList implements IDBVirtualList { + + private IDBRegistry mRegistry = null; + private LDAPConnection mConn = null; + private String mBase = null; + private String mFilter = null; + private String mAttrs[] = null; + // virtual list size + private int mSize = -1; + + private Vector mEntries = new Vector(); + // mSize is get or not? + private boolean mInitialized = false; + private LDAPSortKey[] mKeys; + private LDAPControl[] mPageControls = null; + // page buffer size + private int mPageSize = 10; + // the top of the buffer + private int mTop = 0; + private int mBeforeCount; + private int mAfterCount; + // the index of the first entry returned + private int mSelectedIndex = 0; + private int mJumpToIndex = 0; + private int mJumpToInitialIndex = 0; // Initial index hit in jumpto operation + private int mJumpToDirection = 1; // Do we proceed forward or backwards + private String mJumpTo = null; // Determines if this is the jumpto case + + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs a virtual list. + * Be sure to setPageSize() later if your pageSize is not the default 10 + * Be sure to setSortKey() before fetchs + * + * param registry the registry of attribute mappers + * param c the ldap connection. It has to be version 3 and upper + * param base the base distinguished name to search from + * param filter search filter specifying the search criteria + * param attrs list of attributes that you want returned in the search results + */ + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[]) throws EBaseException { + mRegistry = registry; + mFilter = filter; + mBase = base; + mAttrs = attrs; + CMS.debug( "In DBVirtualList filter attrs filter: " + filter + + " attrs: " + Arrays.toString( attrs ) ); + mPageControls = new LDAPControl[2]; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + } + + /** + * Constructs a virtual list. + * Be sure to setPageSize() later if your pageSize is not the default 10 + * + * param registry the registry of attribute mappers + * param c the ldap connection. It has to be version 3 and upper + * param base the base distinguished name to search from + * param filter search filter specifying the search criteria + * param attrs list of attributes that you want returned in the search results + * param sortKey the attributes to sort by + */ + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[], String sortKey[]) + throws EBaseException { + + CMS.debug( "In DBVirtualList filter attrs sotrKey[] filter: " + filter + + " attrs: " + Arrays.toString( attrs ) ); + mRegistry = registry; + mFilter = filter; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + mBase = base; + mAttrs = attrs; + mPageControls = new LDAPControl[2]; + setSortKey(sortKey); + } + + /** + * Constructs a virtual list. + * Be sure to setPageSize() later if your pageSize is not the default 10 + * + * param registry the registry of attribute mappers + * param c the ldap connection. It has to be version 3 and upper + * param base the base distinguished name to search from + * param filter search filter specifying the search criteria + * param attrs list of attributes that you want returned in the search results + * param sortKey the attribute to sort by + */ + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[], String sortKey) + throws EBaseException { + + CMS.debug( "In DBVirtualList filter attrs sortKey filter: " + filter + " attrs: " + Arrays.toString( attrs ) ); + mRegistry = registry; + mFilter = filter; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + mBase = base; + mAttrs = attrs; + mPageControls = new LDAPControl[2]; + setSortKey(sortKey); + } + + /** + * Constructs a virtual list. + * + * param registry the registry of attribute mappers + * param c the ldap connection. It has to be version 3 and upper + * param base the base distinguished name to search from + * param filter search filter specifying the search criteria + * param attrs list of attributes that you want returned in the search results + * param sortKey the attributes to sort by + * param pageSize the size of a page. There is a 3*pageSize buffer maintained so + * pageUp and pageDown won't invoke fetch from ldap server + */ + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[], String sortKey[], + int pageSize) throws EBaseException { + + CMS.debug( "In DBVirtualList filter attrs sortKey[] pageSize filter: " + + filter + " attrs: " + Arrays.toString( attrs ) + + " pageSize " + pageSize ); + mRegistry = registry; + mFilter = filter; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + mBase = base; + mAttrs = attrs; + mPageControls = new LDAPControl[2]; + setSortKey(sortKey); + setPageSize(pageSize); + } + + /** + * Constructs a virtual list. + * + * param registry the registry of attribute mappers + * param c the ldap connection. It has to be version 3 and upper + * param base the base distinguished name to search from + * param filter search filter specifying the search criteria + * param attrs list of attributes that you want returned in the search results + * param sortKey the attribute to sort by + * param pageSize the size of a page. There is a 3*pageSize buffer maintained so + * pageUp and pageDown won't invoke fetch from ldap server + */ + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[], String sortKey, + int pageSize) throws EBaseException { + + CMS.debug( "In DBVirtualList filter attrs sortKey pageSize filter: " + + filter + " attrs: " + Arrays.toString( attrs ) + + " pageSize " + pageSize ); + mRegistry = registry; + mFilter = filter; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + mBase = base; + mAttrs = attrs; + mPageControls = new LDAPControl[2]; + setSortKey(sortKey); + setPageSize(pageSize); + } + + public DBVirtualList(IDBRegistry registry, LDAPConnection c, + String base, String filter, String attrs[], + String startFrom, String sortKey, + int pageSize) throws EBaseException { + + CMS.debug( "In DBVirtualList filter attrs startFrom sortKey pageSize " + + "filter: " + filter + + " attrs: " + Arrays.toString( attrs ) + + " pageSize " + pageSize + " startFrom " + startFrom ); + mRegistry = registry; + mFilter = filter; + try { + mConn = (LDAPConnection) c.clone(); + } catch (Exception e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", + e.toString())); + } + mBase = base; + mAttrs = attrs; + mPageControls = new LDAPControl[2]; + mJumpTo = startFrom; + setSortKey(sortKey); + // setPageSize(pageSize); + + if (pageSize < 0) { + mJumpToDirection = -1; + } + mPageSize = pageSize; + + mBeforeCount = 0; + mAfterCount = mPageSize; + } + + /** + * Set the paging size of this virtual list. + * The page size here is just a buffer size. A buffer is kept around + * that is three times as large as the number of visible entries. + * That way, you can scroll up/down several items(up to a page-full) + * without refetching entries from the directory. + * + * @param size the page size + */ + public void setPageSize(int size) { + + if (mJumpTo != null) { + return; + } + + mPageSize = size; + mBeforeCount = 0; //mPageSize; + mAfterCount = mPageSize; // mPageSize + mPageSize; + + //CMS.debug("In setPageSize " + size + " mBeforeCount " + mBeforeCount + " mAfterCount " + mAfterCount); + } + + /** + * set the sort key + * + * @param sortKey the attribute to sort by + */ + public void setSortKey(String sortKey) throws EBaseException { + String keys[] = new String[1]; + + keys[0] = sortKey; + setSortKey(keys); + } + + /** + * set the sort key + * + * @param sortKey the attributes to sort by + */ + public void setSortKey(String[] sortKeys) throws EBaseException { + if (sortKeys == null) + throw new EBaseException("sort keys cannot be null"); + try { + + mKeys = new LDAPSortKey[sortKeys.length]; + String la[] = mRegistry.getLDAPAttributes(sortKeys); + + for (int j = 0; j < sortKeys.length; j++) { + mKeys[j] = new LDAPSortKey(la[j]); + } + } catch (Exception e) { + + /*LogDoc + * + * @phase local ldap search + * @reason Failed at setSortKey. + * @message DBVirtualList: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("OPERATION_ERROR", e.toString())); + } + // Paged results also require a sort control + if (mKeys != null) { + mPageControls[0] = + new LDAPSortControl(mKeys, true); + }else { + throw new EBaseException("sort keys cannot be null"); + } + } + + /** + * Retrieves the size of this virtual list. + * Recommend to call getSize() before getElementAt() or getElements() + * since you'd better check if the index is out of bound first. + */ + public int getSize() { + if (!mInitialized) { + mInitialized = true; + // Do an initial search to get the virtual list size + // Keep one page before and one page after the start + if (mJumpTo == null) { + mBeforeCount = 0; //mPageSize; + mAfterCount = mPageSize; // mPageSize + mPageSize; + } + // Create the initial paged results control + /* Since this one is only used to get the size of the virtual list; + we don't care about the starting index. If there is no partial + match, the first one before (or after, if none before) is returned + as the index entry. Instead of "A", you could use the other + constructor and specify 0 both for startIndex and for + contentCount. */ + LDAPVirtualListControl cont = null; + + if (mJumpTo == null) { + cont = new LDAPVirtualListControl("A", + mBeforeCount, + mAfterCount); + } else { + + if (mPageSize < 0) { + mBeforeCount = mPageSize * -1; + mAfterCount = 0; + } + cont = new LDAPVirtualListControl(mJumpTo, + mBeforeCount, + mAfterCount); + } + mPageControls[1] = cont; + getJumpToPage(); + } + + CMS.debug("Getting Virtual List size: " + mSize); + return mSize; + } + + public int getSizeBeforeJumpTo() { + + if (!mInitialized || mJumpTo == null) + return 0; + + int size = 0; + + if (mJumpToDirection < 0) { + size = mTop + mEntries.size(); + } else { + size = mTop; + + } + + return size; + + } + + public int getSizeAfterJumpTo() { + + if (!mInitialized || mJumpTo == null) + return 0; + + int size = mSize - mTop; + + return size; + + } + + private synchronized boolean getEntries() { + // Specify necessary controls for vlist + // LDAPSearchConstraints cons = mConn.getSearchConstraints(); + LDAPSearchConstraints cons = new LDAPSearchConstraints(); + + cons.setMaxResults(0); + if (mPageControls != null) { + cons.setServerControls(mPageControls); + //System.out.println( "setting vlist control" ); + } + // Empty the buffer + mEntries.removeAllElements(); + // Do a search + try { + //what happen if there is no matching? + String ldapFilter = mRegistry.getFilter(mFilter); + String ldapAttrs[] = null; + LDAPSearchResults result; + + if (mAttrs != null) { + ldapAttrs = mRegistry.getLDAPAttributes(mAttrs); + + /* + LDAPv2.SCOPE_BASE: + (search only the base DN) + LDAPv2.SCOPE_ONE: + (search only entries under the base DN) + LDAPv2.SCOPE_SUB: + (search the base DN and all entries within its subtree) + */ + result = mConn.search(mBase, + LDAPConnection.SCOPE_ONE, ldapFilter, ldapAttrs, + false, cons); + + } else { + result = mConn.search(mBase, + LDAPConnection.SCOPE_ONE, ldapFilter, null, + false, cons); + } + if (result == null) { + return false; + } + int damageCounter = 0; + + while (result.hasMoreElements()) { + LDAPEntry entry = (LDAPEntry) result.nextElement(); + + try { + //maintain mEntries as vector of LDAPEntry + Object o = mRegistry.createObject(entry.getAttributeSet()); + + mEntries.addElement(o); + } catch (Exception e) { + + CMS.debug("Exception " + e); + + /*LogDoc + * + * @phase local ldap search + * @reason Failed to get enties. + * @message DBVirtualList: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_VL_ADD", e.toString())); + // #539044 + damageCounter++; + if (damageCounter > 100) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_VL_CORRUPTED_ENTRIES", Integer.toString(damageCounter))); + return false; + } + } + } + } catch (Exception e) { + + /*LogDoc + * + * @phase local ldap search + * @reason Failed to get enties. + * @message DBVirtualList: + */ + CMS.debug("getEntries: exception " + e); + + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("OPERATION_ERROR", e.toString())); + } + //System.out.println( "Returning " + mEntries.size() + + // " entries" ); + + CMS.debug("getEntries returning " + mEntries.size()); + return true; + } + + public int getCurrentIndex() { + return mTop; + } + + private synchronized boolean getJumpToPage() { + try { + // Get the actual entries + if (!getEntries()) + return false; + + // Check if we have a control returned + LDAPControl[] c = mConn.getResponseControls(); + LDAPVirtualListResponse nextCont = + LDAPVirtualListResponse.parseResponse(c); + + if (nextCont != null) { + mSelectedIndex = nextCont.getFirstPosition() - 1; + mTop = Math.max(0, mSelectedIndex - mBeforeCount); + + CMS.debug("mTop " + mTop); + if (mJumpTo != null) { + mJumpToInitialIndex = mTop; + } + + // Now we know the total size of the virtual list box + mSize = nextCont.getContentCount(); + ((LDAPVirtualListControl) mPageControls[1]).setListSize(mSize); + mInitialized = true; + //System.out.println( "Virtual window: " + mTop + + // ".." + (mTop+mEntries.size()-1) + + // " of " + mSize ); + } else { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_DBS_VL_NULL_RESPONSE")); + } + return true; + } catch (Exception e) { + // happens when connection is not available + return false; + } + } + + /** Get a page starting at "first" (although we may also fetch + * some preceding entries) + * Recommend to call getSize() before getElementAt() or getElements() + * since you'd better check if the index is out of bound first. + * + * @param first the index of the first entry of the page you want to fetch + */ + public boolean getPage(int first) { + CMS.debug("getPage " + first); + if (!mInitialized) { + LDAPVirtualListControl cont = new LDAPVirtualListControl(0, + mBeforeCount, + mAfterCount, 0); + + mPageControls[1] = cont; + } + + //CMS.debug("about to set range first " + first + " mBeforeCount " + mBeforeCount + " mAfterCount " + mAfterCount); + ((LDAPVirtualListControl) mPageControls[1]).setRange(first, mBeforeCount, mAfterCount); + return getPage(); + } + + /** Fetch a buffer + */ + private boolean getPage() { + // Get the actual entries + if (!getEntries()) + return false; + + // Check if we have a control returned + LDAPControl[] c = mConn.getResponseControls(); + LDAPVirtualListResponse nextCont = + LDAPVirtualListResponse.parseResponse(c); + + if (nextCont != null) { + mSelectedIndex = nextCont.getFirstPosition() - 1; + mTop = Math.max(0, mSelectedIndex - mBeforeCount); + //CMS.debug("New mTop: " + mTop + " mSelectedIndex " + mSelectedIndex); + // Now we know the total size of the virtual list box + mSize = nextCont.getContentCount(); + ((LDAPVirtualListControl) mPageControls[1]).setListSize(mSize); + mInitialized = true; + //System.out.println( "Virtual window: " + mTop + + // ".." + (mTop+mEntries.size()-1) + + // " of " + mSize ); + } else { + + /*LogDoc + * + * @phase local ldap search + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_VL_NULL_RESPONSE")); + } + return true; + } + + /** Called by application to scroll the list with initial letters. + * Consider text to be an initial substring of the attribute of the + * primary sorting key(the first one specified in the sort key array) + * of an entry. + * If no entries match, the one just before(or after, if none before) + * will be returned as mSelectedIndex + * + * @param text the prefix of the first entry of the page you want to fetch + */ + public boolean getPage(String text) { + mPageControls[1] = + new LDAPVirtualListControl(text, + mBeforeCount, + mAfterCount); + //System.out.println( "Setting requested start to " + + // text + ", -" + mBeforeCount + ", +" + + // mAfterCount ); + return getPage(); + } + + /** + * fetch data of a single list item + * Recommend to call getSize() before getElementAt() or getElements() + * since you'd better check if the index is out of bound first. + * If the index is out of range of the virtual list, an exception will be thrown + * and return null + * + * @param index the index of the element to fetch + */ + public Object getElementAt(int index) { + + /* mSize may not be init at this time! Bad ! + * the caller should really check the index is within bound before this + * but I'll take care of this just in case they are too irresponsible + */ + int baseJumpTo = 0; + + if (!mInitialized) + mSize = getSize(); + + CMS.debug("getElementAt: " + index + " mTop " + mTop); + + //System.out.println( "need entry " + index ); + if ((index < 0) || (index >= mSize)) { + CMS.debug("returning null"); + return null; + } + + if (mJumpTo != null) { //Handle the explicit jumpto case + + if (index == 0) + mJumpToIndex = 0; // Keep a running jumpto index for this page of data + else + mJumpToIndex++; + + //CMS.debug("getElementAtJT: " + index + " mTop " + mTop + " mEntries.size() " + mEntries.size()); + + if ((mJumpToDirection > 0) && (mJumpToInitialIndex + index >= mSize)) // out of data in forward paging jumpto case + { + CMS.debug("mJumpTo virtual list exhausted mTop " + mTop + " mSize " + mSize); + return null; + } + + if (mJumpToIndex >= mEntries.size()) // In jumpto case, page of data has been exhausted + { + mJumpToIndex = 0; // new page will be needed reset running count + + if (mJumpToDirection > 0) { //proceed in positive direction past hit point + getPage(index + mJumpToInitialIndex + 1); + } else { //proceed backwards from hit point + if (mTop == 0) { + getPage(0); + CMS.debug("asking for a page less than zero in reverse case, return null"); + return null; + } + + CMS.debug("getting page reverse mJumptoIndex " + mJumpToIndex + " mTop " + mTop); + getPage(mTop); + + } + + } + + if (mJumpToDirection > 0) // handle getting entry in forward direction + { + return mEntries.elementAt(mJumpToIndex); + } else { // handle getting entry in reverse direction + int reverse_index = mEntries.size() - mJumpToIndex - 1; + + CMS.debug("reverse direction getting index " + reverse_index); + + if (reverse_index < 0 || reverse_index >= mEntries.size()) { + CMS.debug("reverse_index out of range " + reverse_index); + return null; + } + return mEntries.elementAt(reverse_index); + } + } + + //CMS.debug("getElementAt noJumpto: " + index); + + if ((index < mTop) || (index >= mTop + mEntries.size())) { // handle the non jumpto case + //fetch a new page + //System.out.println( "fetching a page starting at " + + // index ); + // CMS.debug("getElementAt noJumpto: getting page index: " + index + " mEntries.size() " + mEntries.size() + " mTop: " + mTop); + getPage(index); + } + + int offset = index - mTop; + + if ((offset < 0) || (offset >= mEntries.size())) + //XXX + return ("No entry at " + index); + else + return mEntries.elementAt(offset); + } + + public Object getJumpToElementAt(int i) { + return mEntries.elementAt(i); + } + + /** + * This function processes elements as soon as it arrives. It is + * more memory-efficient. + */ + public void processElements(int startidx, int endidx, IElementProcessor ep) + throws EBaseException { + + /* mSize may not be init at this time! Bad ! + * the caller should really check the index is within bound before this + * but I'll take care of this just in case they are too irresponsible + */ + if (!mInitialized) + mSize = getSize(); + + // short-cut the existing code ... :( + if (mJumpTo != null) { + for (int i = startidx; i <= endidx; i++) { + Object element = getJumpToElementAt(i); + + if (element != null) + ep.process(element); + } + return; + } + + //guess this is what you really mean to try to improve performance + if (startidx >= endidx) { + throw new EBaseException("startidx must be less than endidx"); + }else { + setPageSize(endidx - startidx); + getPage(startidx); + } + + for (int i = startidx; i <= endidx; i++) { + Object element = getElementAt(i); + + if (element != null) + ep.process(element); + } + } + + /** + * get the virutal selected index + */ + public int getSelectedIndex() { + return mSelectedIndex; + } + + /** + * get the top of the buffer + */ + public int getFirstIndex() { + return mTop; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java new file mode 100644 index 000000000..e073fe633 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DateArrayMapper.java @@ -0,0 +1,105 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java Date array object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DateArrayMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs a date array mapper. + */ + public DateArrayMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of support ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to a set of attributes. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + Date dates[] = (Date[]) obj; + + if (dates == null) + return; + LDAPAttribute attr = new LDAPAttribute(mLdapName); + + for (int i = 0; i < dates.length; i++) { + attr.addValue(DateMapper.dateToDB(dates[i])); + } + attrs.add(attr); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + Enumeration e = attr.getStringValues(); + Vector v = new Vector(); + + while (e.hasMoreElements()) { + v.addElement(DateMapper.dateFromDB((String) + e.nextElement())); + } + if (v.size() == 0) + return; + Date dates[] = new Date[v.size()]; + + v.copyInto(dates); + parent.set(name, dates); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java new file mode 100644 index 000000000..8b0009479 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DateMapper.java @@ -0,0 +1,108 @@ +// --- 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.util.*; +import java.text.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java Date object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class DateMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + private static SimpleDateFormat formatter = new + SimpleDateFormat("yyyyMMddHHmmss'Z'"); + + /** + * Constructs date mapper. + */ + public DateMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + dateToDB((Date) obj))); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + parent.set(name, dateFromDB((String) + attr.getStringValues().nextElement())); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + String val = null; + + try { + val = dateToDB(new Date(Long.parseLong(value))); + } catch (NumberFormatException e) { + val = value; + } + return mLdapName + op + val; + } + + public synchronized static String dateToDB(Date date) { + return formatter.format(date); + } + + public synchronized static Date dateFromDB(String dbDate) { + try { + return formatter.parse(dbDate); + } catch (ParseException e) { + } + return null; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java new file mode 100644 index 000000000..2293bea26 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/IntegerMapper.java @@ -0,0 +1,86 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java Integer object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class IntegerMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs mapper to deal with Integer. + */ + public IntegerMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of supported ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + ((Integer) obj).toString())); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + parent.set(name, new Integer((String) + attr.getStringValues().nextElement())); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java new file mode 100644 index 000000000..7a5e02a04 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyDBSchema.java @@ -0,0 +1,58 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a collection of key record + * specific schema information. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyDBSchema { + + public static final String LDAP_OC_TOP = "top"; + public static final String LDAP_ATTR_SERIALNO = "serialno"; + public static final String LDAP_ATTR_CREATE_TIME = "dateOfCreate"; + public static final String LDAP_ATTR_MODIFY_TIME = "dateOfModify"; + public static final String LDAP_ATTR_META_INFO = "metaInfo"; + public static final String LDAP_OC_KEYRECORD = "keyRecord"; + public static final String LDAP_ATTR_OWNER_NAME = "ownerName"; + public static final String LDAP_ATTR_PRIVATE_KEY_DATA = "privateKeyData"; + public static final String LDAP_ATTR_KEY_RECORD_ID = "keyRecordId"; + public static final String LDAP_ATTR_PUBLIC_KEY_DATA = "publicKeyData"; + public static final String LDAP_ATTR_KEY_SIZE = "keySize"; + public static final String LDAP_ATTR_ALGORITHM = "algorithm"; + public static final String LDAP_ATTR_STATE = "keyState"; + public static final String LDAP_ATTR_DATE_OF_RECOVERY = + "dateOfRecovery"; + public static final String LDAP_ATTR_PUBLIC_KEY_FORMAT = + "publicKeyFormat"; + public static final String LDAP_ATTR_ARCHIVED_BY = "archivedBy"; +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java new file mode 100644 index 000000000..7b6fcdb8d --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecord.java @@ -0,0 +1,348 @@ +// --- 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.math.*; +import java.io.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +//import netscape.security.provider.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.ldap.*; +import com.netscape.cmscore.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.keydb.*; + + +/** + * A class represents a Key record. It maintains the key + * life cycle as well as other information about an + * archived key. Namely, whether a key is inactive because + * of compromise. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyRecord implements IDBObj, IKeyRecord { + + private BigInteger mSerialNo = null; + private KeyState mState = null; + private MetaInfo mMetaInfo = null; + private String mAlgorithm = null; + private byte mPrivateKey[] = null; + private byte mPublicKey[] = null; + private Integer mSize = null; + private String mOwnerName = null; + private Date mDatesOfRecovery[] = null; + private Date mCreateTime = null; + private Date mModifyTime = null; + private String mArchivedBy = null; + + protected static Vector mNames = new Vector(); + static { + mNames.addElement(ATTR_STATE); + mNames.addElement(ATTR_ID); + mNames.addElement(ATTR_OWNER_NAME); + mNames.addElement(ATTR_KEY_SIZE); + mNames.addElement(ATTR_ALGORITHM); + mNames.addElement(ATTR_PRIVATE_KEY_DATA); + mNames.addElement(ATTR_PUBLIC_KEY_DATA); + mNames.addElement(ATTR_DATE_OF_RECOVERY); + mNames.addElement(ATTR_META_INFO); + mNames.addElement(ATTR_CREATE_TIME); + mNames.addElement(ATTR_MODIFY_TIME); + mNames.addElement(ATTR_ARCHIVED_BY); + } + + /** + * Constructs empty key record. + */ + public KeyRecord() { + } + + /* + * Constructs key record. + * + * @param key key to be archived + */ + public KeyRecord(BigInteger serialNo, byte publicData[], + byte privateData[], String owner, + String algorithm, String agentId) + throws EBaseException { + mSerialNo = serialNo; + mPublicKey = publicData; + mPrivateKey = privateData; + mOwnerName = owner; + mAlgorithm = algorithm; + mState = KeyState.VALID; + mCreateTime = com.netscape.certsrv.apps.CMS.getCurrentDate(); + mModifyTime = com.netscape.certsrv.apps.CMS.getCurrentDate(); + mArchivedBy = agentId; + } + + /** + * Sets an attribute. + *

+ */ + public void set(String name, Object object) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_STATE)) { + mState = (KeyState) object; + } else if (name.equalsIgnoreCase(ATTR_ID)) { + mSerialNo = (BigInteger) object; + } else if (name.equalsIgnoreCase(ATTR_KEY_SIZE)) { + mSize = (Integer) object; + } else if (name.equalsIgnoreCase(ATTR_OWNER_NAME)) { + mOwnerName = (String) object; + } else if (name.equalsIgnoreCase(ATTR_ALGORITHM)) { + mAlgorithm = (String) object; + } else if (name.equalsIgnoreCase(ATTR_PRIVATE_KEY_DATA)) { + mPrivateKey = (byte[]) object; + } else if (name.equalsIgnoreCase(ATTR_PUBLIC_KEY_DATA)) { + mPublicKey = (byte[]) object; + } else if (name.equalsIgnoreCase(ATTR_DATE_OF_RECOVERY)) { + mDatesOfRecovery = (Date[]) object; + } else if (name.equalsIgnoreCase(ATTR_META_INFO)) { + mMetaInfo = (MetaInfo) object; + } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) { + mCreateTime = (Date) object; + } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) { + mModifyTime = (Date) object; + } else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) { + mArchivedBy = (String) object; + } else { + throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Retrieves an attribute. + *

+ */ + public Object get(String name) throws EBaseException { + if (name.equalsIgnoreCase(ATTR_STATE)) { + return mState; + } else if (name.equalsIgnoreCase(ATTR_ID)) { + return mSerialNo; + } else if (name.equalsIgnoreCase(ATTR_KEY_SIZE)) { + return mSize; + } else if (name.equalsIgnoreCase(ATTR_OWNER_NAME)) { + return mOwnerName; + } else if (name.equalsIgnoreCase(ATTR_ALGORITHM)) { + return mAlgorithm; + } else if (name.equalsIgnoreCase(ATTR_PRIVATE_KEY_DATA)) { + return mPrivateKey; + } else if (name.equalsIgnoreCase(ATTR_PUBLIC_KEY_DATA)) { + return mPublicKey; + } else if (name.equalsIgnoreCase(ATTR_DATE_OF_RECOVERY)) { + return mDatesOfRecovery; + } else if (name.equalsIgnoreCase(ATTR_CREATE_TIME)) { + return mCreateTime; + } else if (name.equalsIgnoreCase(ATTR_MODIFY_TIME)) { + return mModifyTime; + } else if (name.equalsIgnoreCase(ATTR_META_INFO)) { + return mMetaInfo; + } else if (name.equalsIgnoreCase(ATTR_ARCHIVED_BY)) { + return mArchivedBy; + } else { + throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Deletes an attribute. + *

+ */ + public void delete(String name) throws EBaseException { + throw new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + + /** + * Retrieves an enumeration of attributes. + *

+ */ + public Enumeration getElements() { + return mNames.elements(); + } + + /** + * Retrieves serializable attribute names. + */ + public Enumeration getSerializableAttrNames() { + return mNames.elements(); + } + + /** + * Retrieves serial number of the key record. Each key record + * is uniquely identified by serial number. + *

+ * + * @return serial number of this key record + */ + public BigInteger getSerialNumber() throws EBaseException { + return mSerialNo; + } + + /** + * Sets serial number. + */ + public void setSerialNumber(BigInteger serialno) throws EBaseException { + mSerialNo = serialno; + } + + /** + * Retrieves the key state. This gives key life cycle + * information. + *

+ * + * @return key state + */ + public KeyState getState() throws EBaseException { + return mState; + } + + /** + * Sets key state. + *

+ */ + public void setState(KeyState state) throws EBaseException { + mState = state; + } + + /** + * Retrieves the uid of person who archived this record. + */ + public String getArchivedBy() { + return mArchivedBy; + } + + /** + * Retrieves key. + *

+ * + * @return archived key + */ + public byte[] getPrivateKeyData() throws EBaseException { + return mPrivateKey; + } + + /** + * Sets key data. + */ + public void setPrivateKeyData(byte keydata[]) throws EBaseException { + mPrivateKey = keydata; + } + + /** + * Retrieves the key size. + *

+ * + * @return key size + */ + public Integer getKeySize() throws EBaseException { + return mSize; + } + + /** + * Sets key size. + *

+ */ + public void setKeySize(Integer keySize) throws EBaseException { + mSize = keySize; + } + + /** + * Retrieves owner name. + *

+ */ + public String getOwnerName() throws EBaseException { + return mOwnerName; + } + + /** + * Sets owner name. + *

+ */ + public void setOwnerName(String name) throws EBaseException { + mOwnerName = name; + } + + /** + * Retrieves the public key. + *

+ */ + public byte[] getPublicKeyData() throws EBaseException { + return mPublicKey; + } + + /** + * Sets the public key. + *

+ */ + public void setPublicKeyData(byte key[]) throws EBaseException { + mPublicKey = key; + } + + /** + * Retrieves the date(s) of revocation. + *

+ */ + public Date[] getDateOfRevocation() throws EBaseException { + return mDatesOfRecovery; + } + + /** + * Sets the dateso of revocation. + *

+ */ + public void setDateOfRevocation(Date dates[]) throws EBaseException { + mDatesOfRecovery = dates; + } + + /** + * Retrieves algorithm of the key pair. + */ + public String getAlgorithm() { + return mAlgorithm; + } + + public MetaInfo getMetaInfo() { + return mMetaInfo; + } + + /** + * Retrieves the creation time of this record. + */ + public Date getCreateTime() { + return mCreateTime; + } + + /** + * Retrieves the last modification time of + * this record. + */ + public Date getModifyTime() { + return mModifyTime; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java new file mode 100644 index 000000000..250e66e6c --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordList.java @@ -0,0 +1,93 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.cmscore.dbs.*; + + +/** + * A class represents a list of key records. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyRecordList implements IKeyRecordList { + + private IDBVirtualList mVlist = null; + + /** + * Constructs a key list. + */ + public KeyRecordList(IDBVirtualList vlist) { + mVlist = vlist; + } + + /** + * Retrieves the size of key list. + */ + public int getSize() { + return mVlist.getSize(); + } + + public int getSizeBeforeJumpTo() { + + return mVlist.getSizeBeforeJumpTo(); + + } + + public int getSizeAfterJumpTo() { + + return mVlist.getSizeAfterJumpTo(); + } + + public IKeyRecord getKeyRecord(int i) { + KeyRecord record = (KeyRecord) mVlist.getElementAt(i); + + if (record == null) return null; + + return record; + } + /** + * Retrieves requests. + */ + public Enumeration getKeyRecords(int startidx, int endidx) + throws EBaseException { + Vector entries = new Vector(); + + for (int i = startidx; i <= endidx; i++) { + Object element = mVlist.getElementAt(i); + + if (element != null) { + entries.addElement(element); + } + } + if (entries != null) { + return entries.elements(); + } else { + return null; + } + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java new file mode 100644 index 000000000..eaaf3779f --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRecordMapper.java @@ -0,0 +1,111 @@ +// --- 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.math.*; +import java.io.*; +import java.util.*; +import java.security.cert.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents a mapper to serialize + * key record into database. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyRecordMapper implements IDBAttrMapper { + + private IKeyRepository mDB = null; + private ILogger mLogger = CMS.getLogger(); + + public KeyRecordMapper(IKeyRepository db) { + mDB = db; + } + + public Enumeration getSupportedLDAPAttributeNames() { + Vector v = new Vector(); + + v.addElement(KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID); + return v.elements(); + } + + public void mapObjectToLDAPAttributeSet(IDBObj parent, String name, + Object obj, LDAPAttributeSet attrs) throws EBaseException { + try { + KeyRecord rec = (KeyRecord) obj; + + attrs.add(new LDAPAttribute(KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID, + rec.getSerialNumber().toString())); + } catch (Exception e) { + + /*LogDoc + * + * @phase Maps object to ldap attribute set + * @message KeyRecordMapper: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_KEYRECORD_MAPPER_ERROR", e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name)); + } + } + + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + try { + LDAPAttribute attr = attrs.getAttribute( + KeyDBSchema.LDAP_ATTR_KEY_RECORD_ID); + + if (attr == null) + return; + String serialno = (String) attr.getStringValues().nextElement(); + IKeyRecord rec = mDB.readKeyRecord(new + BigInteger(serialno)); + + parent.set(name, rec); + } catch (Exception e) { + + /*LogDoc + * + * @phase Maps ldap attribute set to object + * @message KeyRecordMapper: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_KEYRECORD_MAPPER_ERROR", e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } + } + + public String mapSearchFilter(String name, String op, String value) + throws EBaseException { + return name + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java new file mode 100644 index 000000000..06b5f2614 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java @@ -0,0 +1,553 @@ +// --- 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.math.*; +import java.io.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.dbs.repository.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmscore.util.*; +import com.netscape.cmscore.dbs.*; + + +/** + * A class represents a Key repository. This is the container of + * archived keys. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyRepository extends Repository implements IKeyRepository { + + public KeyStatusUpdateThread mKeyStatusUpdateThread = null; + protected IDBSubsystem mDBService = null; + + /** + * Internal constants + */ + private String mBaseDN = null; + + /** + * Constructs a key repository. It checks if the key repository + * does exist. If not, it creates the repository. + *

+ * + * @param service db service + * @exception EBaseException failed to setup key repository + */ + public KeyRepository(IDBSubsystem service, int increment, String baseDN) + throws EDBException { + super(service, increment, baseDN); + mBaseDN = baseDN; + mDBService = service; + + // register key record schema + IDBRegistry reg = service.getRegistry(); + String keyRecordOC[] = new String[2]; + + keyRecordOC[0] = KeyDBSchema.LDAP_OC_TOP; + keyRecordOC[1] = KeyDBSchema.LDAP_OC_KEYRECORD; + + if (!reg.isObjectClassRegistered(KeyRecord.class.getName())) { + reg.registerObjectClass(KeyRecord.class.getName(), + keyRecordOC); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_ID)) { + reg.registerAttribute(KeyRecord.ATTR_ID, new + BigIntegerMapper(KeyDBSchema.LDAP_ATTR_SERIALNO)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_ALGORITHM)) { + reg.registerAttribute(KeyRecord.ATTR_ALGORITHM, new + StringMapper(KeyDBSchema.LDAP_ATTR_ALGORITHM)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_STATE)) { + reg.registerAttribute(KeyRecord.ATTR_STATE, new + KeyStateMapper(KeyDBSchema.LDAP_ATTR_STATE)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_KEY_SIZE)) { + reg.registerAttribute(KeyRecord.ATTR_KEY_SIZE, new + IntegerMapper(KeyDBSchema.LDAP_ATTR_KEY_SIZE)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_OWNER_NAME)) { + reg.registerAttribute(KeyRecord.ATTR_OWNER_NAME, new + StringMapper(KeyDBSchema.LDAP_ATTR_OWNER_NAME)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_PRIVATE_KEY_DATA)) { + reg.registerAttribute(KeyRecord.ATTR_PRIVATE_KEY_DATA, new + ByteArrayMapper(KeyDBSchema.LDAP_ATTR_PRIVATE_KEY_DATA)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_PUBLIC_KEY_DATA)) { + reg.registerAttribute(KeyRecord.ATTR_PUBLIC_KEY_DATA, new + PublicKeyMapper(KeyDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_DATE_OF_RECOVERY)) { + reg.registerAttribute(KeyRecord.ATTR_DATE_OF_RECOVERY, new + DateArrayMapper(KeyDBSchema.LDAP_ATTR_DATE_OF_RECOVERY)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_CREATE_TIME)) { + reg.registerAttribute(KeyRecord.ATTR_CREATE_TIME, new + DateMapper(KeyDBSchema.LDAP_ATTR_CREATE_TIME)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_MODIFY_TIME)) { + reg.registerAttribute(KeyRecord.ATTR_MODIFY_TIME, new + DateMapper(KeyDBSchema.LDAP_ATTR_MODIFY_TIME)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_META_INFO)) { + reg.registerAttribute(KeyRecord.ATTR_META_INFO, new + MetaInfoMapper(KeyDBSchema.LDAP_ATTR_META_INFO)); + } + if (!reg.isAttributeRegistered(KeyRecord.ATTR_ARCHIVED_BY)) { + reg.registerAttribute(KeyRecord.ATTR_ARCHIVED_BY, new + StringMapper(KeyDBSchema.LDAP_ATTR_ARCHIVED_BY)); + } + } + + public void setKeyStatusUpdateInterval(IRepository requestRepo, int interval) { + CMS.debug("In setKeyStatusUpdateInterval " + interval); + // don't run the thread if serial management is disabled. + if ((interval == 0) || (!mDBService.getEnableSerialMgmt())) { + CMS.debug("In setKeyStatusUpdateInterval interval = 0" + interval); + if (mKeyStatusUpdateThread != null) { + mKeyStatusUpdateThread.stop(); + } + return; + } + + CMS.debug("In setKeyStatusUpdateInterval mKeyStatusUpdateThread " + mKeyStatusUpdateThread); + if (mKeyStatusUpdateThread == null) { + CMS.debug("In setKeyStatusUpdateInterval about to create KeyStatusUpdateThread "); + mKeyStatusUpdateThread = new KeyStatusUpdateThread(this, requestRepo, "KeyStatusUpdateThread"); + mKeyStatusUpdateThread.setInterval(interval); + mKeyStatusUpdateThread.start(); + } else { + CMS.debug("In setKeyStatusUpdateInterval it thinks the thread is up already "); + mKeyStatusUpdateThread.setInterval(interval); + // dont do anything if we have a thread running already + } + } + + public IDBSubsystem getDBSubsystem() { + return mDBService; + } + + /** + * Retrieves the DN of this repository. + */ + public String getDN() { + return mBaseDN; + } + + /** + * Removes all objects with this repository. + */ + public void removeAllObjects() throws EBaseException + { + String filter = "(" + KeyRecord.ATTR_OWNER_NAME + "=*" + ")"; + IKeyRecordList list = findKeyRecordsInList(filter, + null, "serialno", 10); + int size = list.getSize(); + Enumeration e = list.getKeyRecords(0, size - 1); + while (e.hasMoreElements()) { + KeyRecord rec = (KeyRecord) e.nextElement(); + deleteKeyRecord(rec.getSerialNumber()); + } + } + + /** + * Archives a key to the repository. + *

+ * + * @param record key record + * @exception EBaseException failed to archive key + */ + public void addKeyRecord(IKeyRecord record) throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + ((KeyRecord) record).getSerialNumber().toString() + "," + getDN(); + + if (s != null) s.add(name, (KeyRecord) record); + } finally { + if (s != null) s.close(); + } + } + + /** + * Recovers an archived key by serial number. + *

+ * + * @param serialNo serial number + * @return key record + * @exception EBaseException failed to recover key + */ + public IKeyRecord readKeyRecord(BigInteger serialNo) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + KeyRecord rec = null; + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + if (s != null) rec = (KeyRecord) s.read(name); + } finally { + if (s != null) s.close(); + } + return rec; + } + + /** + * Recovers an archived key by owner name. + *

+ * + * @param ownerName owner name + * @return key record + * @exception EBaseException failed to recover key + */ + public IKeyRecord readKeyRecord(X500Name ownerName) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + KeyRecord keyRec = null; + + try { + if (ownerName != null) { + String filter = "(" + KeyRecord.ATTR_OWNER_NAME + "=" + + ownerName.toString() + ")"; + IDBSearchResults res = s.search(getDN(), filter); + + keyRec = (KeyRecord) res.nextElement(); + } + } finally { + if (s != null) s.close(); + } + return keyRec; + } + + /** + * Recovers archived key using public key. + */ + public IKeyRecord readKeyRecord(PublicKey publicKey) + throws EBaseException { + // XXX - setup binary search attributes + byte data[] = publicKey.getEncoded(); + + if (data == null) + throw new EBaseException("null data"); + IDBSSession s = mDBService.createSession(); + KeyRecord rec = null; + + try { + String filter = "(" + KeyRecord.ATTR_PUBLIC_KEY_DATA + "=" + + escapeBinaryData(data) + ")"; + if( s != null ) { + IDBSearchResults res = s.search(getDN(), filter); + + rec = (KeyRecord) res.nextElement(); + } + } finally { + if (s != null) s.close(); + } + return rec; + } + + + /** + * Recovers archived key using b64 encoded cert + */ + public IKeyRecord readKeyRecord(String cert) + throws EBaseException { + + IDBSSession s = mDBService.createSession(); + KeyRecord rec = null; + + try { + String filter = "(publicKey=x509cert#\"" +cert+"\")"; +CMS.debug("filter= " + filter); + + if( s != null ) { + IDBSearchResults res = s.search(getDN(), filter); + + rec = (KeyRecord) res.nextElement(); + } + } finally { + if (s != null) s.close(); + } + return rec; + } + + /** + * Modifies key record. + */ + public void modifyKeyRecord(BigInteger serialNo, ModificationSet mods) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + mods.add(KeyRecord.ATTR_MODIFY_TIME, Modification.MOD_REPLACE, + new Date()); + if (s != null) s.modify(name, mods); + } finally { + if (s != null) s.close(); + } + } + + public void deleteKeyRecord(BigInteger serialNo) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + + try { + String name = "cn" + "=" + + serialNo.toString() + "," + getDN(); + + if (s != null) s.delete(name); + } finally { + if (s != null) s.close(); + } + } + + /** + * Read RFC-2254 + */ + public static String escapeBinaryData(byte data[]) { + String result = ""; + + for (int i = 0; i < data.length; i++) { + result = result + "\\" + Integer.toHexString((int) data[i]); + } + return result; + } + + public Enumeration searchKeys(String filter, int maxSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + e = s.search(getDN(), filter, maxSize); + } finally { + if (s != null) + s.close(); + } + return e; + } + + public Enumeration searchKeys(String filter, int maxSize, int timeLimit) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + Enumeration e = null; + + try { + e = s.search(getDN(), filter, maxSize, timeLimit); + } finally { + if (s != null) + s.close(); + } + return e; + } + + /** + * Retrieves key record list. + */ + public IKeyRecordList findKeyRecordsInList(String filter, + String attrs[], int pageSize) throws EBaseException { + return findKeyRecordsInList(filter, attrs, IKeyRecord.ATTR_ID, + pageSize); + } + + public IKeyRecordList findKeyRecordsInList(String filter, + String attrs[], String sortKey, int pageSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + IKeyRecordList list = null; + + try { + if (s != null) { + list = new KeyRecordList( + s.createVirtualList(getDN(), "(&(objectclass=" + + KeyRecord.class.getName() + ")" + filter + ")", + attrs, sortKey, pageSize)); + } + } finally { + if (s != null) s.close(); + } + return list; + } + + public IKeyRecordList findKeyRecordsInList(String filter, + String attrs[],String jumpTo, String sortKey, int pageSize) + throws EBaseException { + IDBSSession s = mDBService.createSession(); + IKeyRecordList list = null; + + int len = jumpTo.length(); + + String jumpToVal = null; + + if (len > 9) { + jumpToVal = Integer.toString(len) + jumpTo; + } else { + jumpToVal = "0" + Integer.toString(len) + jumpTo; + } + + try { + if (s != null) { + list = new KeyRecordList( + s.createVirtualList(getDN(), "(&(objectclass=" + + KeyRecord.class.getName() + ")" + filter + ")", + attrs,jumpToVal, sortKey, pageSize)); + } + } finally { + if (s != null) s.close(); + } + return list; + } + + public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) throws + EBaseException { + + CMS.debug("KeyRepository: 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 = "(" + "serialno" + "=*" + ")"; + String[] attrs = null; + + KeyRecordList recList = (KeyRecordList) findKeyRecordsInList(ldapfilter,attrs,serial_upper_bound.toString(10),"serialno", 5 * -1); + + int size = recList.getSize(); + + CMS.debug("KeyRepository: getLastSerialNumberInRange: recList size " + size); + + if (size <= 0) { + CMS.debug("KeyRepository: getLastSerialNumberInRange: index may be empty"); + + BigInteger ret = new BigInteger(serial_low_bound.toString(10)); + + ret = ret.add(new BigInteger("-1")); + + CMS.debug("KeyRepository: getLastSerialNumberInRange returning: " + ret ); + return ret; + } + int ltSize = recList.getSizeBeforeJumpTo(); + + Vector cList = new Vector(ltSize); + + CMS.debug("KeyRepository:getLastSerialNumberInRange: ltSize " + ltSize); + + int i; + KeyRecord curRec = null; + + for (i = 0; i < 5; i++) { + curRec = (KeyRecord) recList.getKeyRecord(i); + + if (curRec != null) { + + BigInteger serial = curRec.getSerialNumber(); + + CMS.debug("KeyRepository: 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("KeyRepository: getLastSerialNumberInRange returning: " + serial); + return serial; + } + } else { + CMS.debug("KeyRepository: getLastSerialNumberInRange:found null from getCertRecord"); + } + } + + BigInteger ret = new BigInteger(serial_low_bound.toString(10)); + + ret = ret.add(new BigInteger("-1")); + + CMS.debug("KeyRepository: getLastSerialNumberInRange returning: " + ret ); + return ret ; + + } + + public void shutdown() { + if (mKeyStatusUpdateThread != null) + mKeyStatusUpdateThread.destroy(); + } + +} + +class KeyStatusUpdateThread extends Thread { + KeyRepository _kr = null; + IRepository _rr = null; + int _interval; + + KeyStatusUpdateThread(KeyRepository kr, IRepository rr, String name) { + super(name); + CMS.debug("new KeyStatusUpdateThread"); + + _kr = kr; + _rr = rr; + } + + public void setInterval(int interval) { + _interval = interval; + } + + public void run() { + CMS.debug("Inside run method of KeyStatusUpdateThread"); + + while (true) { + try { + // block the update while another thread + // (such as the CRL Update) is running + CMS.debug("About to start checkRanges"); + synchronized (_kr.mKeyStatusUpdateThread) { + CMS.debug("Starting key checkRanges"); + _kr.checkRanges(); + CMS.debug("key checkRanges done"); + + CMS.debug("Starting request checkRanges"); + _rr.checkRanges(); + CMS.debug("request checkRanges done"); + } + } catch (Exception e) { + CMS.debug("key checkRanges done"); + } + try { + sleep(_interval * 1000); + } catch (InterruptedException e) { + } + } + } +} + + diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java new file mode 100644 index 000000000..0630efa7c --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyStateMapper.java @@ -0,0 +1,80 @@ +// --- 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.util.*; +import java.math.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; + + +/** + * A class represents a key state mapper. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class KeyStateMapper implements IDBAttrMapper { + + private String mLdapName = null; + + public KeyStateMapper(String ldapName) { + mLdapName = ldapName; + } + + public Enumeration getSupportedLDAPAttributeNames() { + Vector v = new Vector(); + + v.addElement(mLdapName); + return v.elements(); + } + + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + ((KeyState) obj).toString())); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) { + return; + } + parent.set(name, KeyState.toKeyState( + ((String) attr.getStringValues().nextElement()))); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java b/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java new file mode 100644 index 000000000..db5db02c9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/LdapFilterConverter.java @@ -0,0 +1,61 @@ +// --- 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.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a filter converter + * that understands how to convert a attribute + * type from one defintion to another. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class LdapFilterConverter implements IFilterConverter { + + private Hashtable mReg = null; + + /** + * Constructs filter convertor. + */ + public LdapFilterConverter(Hashtable reg) { + mReg = reg; + } + + /** + * Converts database filter to ldap filter. + */ + public String convert(String name, String op, String value) { + AttributeNameHelper h = new AttributeNameHelper(name); + IDBAttrMapper mapper = (IDBAttrMapper) mReg.get( + h.getPrefix().toLowerCase()); + + if (mapper == null) + return null; + try { + return mapper.mapSearchFilter(name, op, value); + } catch (EBaseException e) { + } + return null; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java new file mode 100644 index 000000000..9006081f5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/LongMapper.java @@ -0,0 +1,117 @@ +// --- 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.util.*; +import java.math.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java Long object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class LongMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs Long mapper. + */ + public LongMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Returns a list of supported ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object into ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + LongToDB((Long) obj))); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + parent.set(name, LongFromDB( + (String) attr.getStringValues().nextElement())); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + String v = null; + + try { + if (value.startsWith("0x") || value.startsWith("0X")) { + v = LongToDB(Long.valueOf(value.substring(2), 16)); + } else { + v = LongToDB(Long.valueOf(value)); + } + } catch (NumberFormatException e) { + v = value; + } + return mLdapName + op + v; + } + + public static String LongToDB(Long i) { + int len = i.toString().length(); + String ret = null; + + if (len < 10) { + ret = "0" + Integer.toString(len) + i.toString(); + } else { + ret = Integer.toString(len) + i.toString(); + } + return ret; + } + + public static Long LongFromDB(String i) { + String s = i.substring(2); + + // possibly check length + return new Long(s); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java new file mode 100644 index 000000000..c3248ec12 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/MetaInfoMapper.java @@ -0,0 +1,119 @@ +// --- 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.util.*; +import java.math.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represent mapper for metainfo attribute. Metainfo + * is in format of the following: + * + *

+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * metaInfoType:metaInfoValue
+ * 
+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class MetaInfoMapper implements IDBAttrMapper { + + public static final String SEP = ":"; + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs a metainfo object. + */ + public MetaInfoMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Returns a list of supported ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object into ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + MetaInfo info = (MetaInfo) obj; + Enumeration e = info.getElements(); + + if (!e.hasMoreElements()) + return; // dont add anything + LDAPAttribute attr = new LDAPAttribute(mLdapName); + + while (e.hasMoreElements()) { + String s = null; + String attrName = (String) e.nextElement(); + String value = (String) info.get(attrName); + + s = attrName + SEP + value; + attr.addValue(s); + } + attrs.add(attr); + } + + /** + * Maps LDAP attributes into object, and put the object into + * 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + Enumeration values = attr.getStringValues(); + MetaInfo info = new MetaInfo(); + + while (values.hasMoreElements()) { + String s = (String) values.nextElement(); + StringTokenizer st = new StringTokenizer(s, SEP); + + info.set(st.nextToken(), st.nextToken()); + } + parent.set(name, info); + } + + /** + * Map search filters into LDAP search filter. + * Possible search filter: + * (&(metaInfo=reserver0:value0)(metaInfo=reserved1:value1)) + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java new file mode 100644 index 000000000..5c02b4014 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/ObjectStreamMapper.java @@ -0,0 +1,135 @@ +// --- 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Enumeration; +import java.util.Vector; +import netscape.ldap.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.EDBException; +import com.netscape.certsrv.dbs.IDBAttrMapper; +import com.netscape.certsrv.dbs.IDBObj; +import com.netscape.certsrv.logging.ILogger; + + +/** + * A class represents ann attribute mapper that maps + * a Java object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class ObjectStreamMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs object stream mapper. + */ + public ObjectStreamMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of supported ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, String name, + Object obj, LDAPAttributeSet attrs) + throws EBaseException { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream os = new ObjectOutputStream(bos); + + os.writeObject(obj); + byte data[] = bos.toByteArray(); + if (data == null) { + CMS.debug("ObjectStreamMapper:mapObjectToLDAPAttributeSet " + + name + " size=0"); + } else { + CMS.debug("ObjectStreamMapper:mapObjectToLDAPAttributeSet " + + name + " size=" + data.length); + } + attrs.add(new LDAPAttribute(mLdapName, + data)); + } catch (IOException e) { + + /*LogDoc + * + * @phase Maps object to ldap attribute set + * @message ObjectStreamMapper: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_OBJECTSTREAM_MAPPER_ERROR", + e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name)); + } + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + try { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) { + return; + } + ByteArrayInputStream bis = new ByteArrayInputStream( + (byte[]) attr.getByteValues().nextElement()); + ObjectInputStream is = new ObjectInputStream(bis); + + parent.set(name, is.readObject()); + } catch (IOException e) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } catch (ClassNotFoundException e) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java new file mode 100644 index 000000000..4d93f843a --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/PublicKeyMapper.java @@ -0,0 +1,150 @@ +// --- 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.util.*; +import netscape.ldap.*; +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmscore.cert.*; + + +/** + * A class represents an attribute mapper that maps + * a public key data into LDAP attribute and + * vice versa. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class PublicKeyMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs a byte array mapper. + */ + public PublicKeyMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Lists a list of supported ldap attribute names. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps object to ldap attribute set. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, (byte[]) obj)); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) { + return; + } + parent.set(name, (byte[]) attr.getByteValues().nextElement()); + } + + /** + * Maps search filters into LDAP search filter. It knows + * how to extract public key from the certificate. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + int i = value.indexOf("#"); + + if (i != -1) { + String tag = value.substring(0, i); + String val = value.substring(i + 1); + + try { + if (val.startsWith("\"")) { + val = val.substring(1, val.length() - 1); + } + X509Certificate cert = CertUtils.mapCert(val); + PublicKey key = cert.getPublicKey(); + byte pub[] = key.getEncoded(); + + return mLdapName + op + escapeBinaryData(pub); + } catch (Exception e) { + + /*LogDoc + * + * @phase Maps search filters into LDAP search filter + * @message PublicKeyMapper: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_PUBLICKEY_MAPPER_ERROR", + e.toString())); + } + } + return mLdapName + op + value; + } + + private String normalize(String s) { + String val = ""; + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\n') { + continue; + } else if (s.charAt(i) == '\r') { + continue; + } else if (s.charAt(i) == '"') { + continue; + } + val += s.charAt(i); + } + return val; + } + + public static String escapeBinaryData(byte data[]) { + String result = ""; + + for (int i = 0; i < data.length; i++) { + int v = 0xff & data[i]; + + result = result + "\\" + (v < 16 ? "0" : "") + + Integer.toHexString(v); + } + return result; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java new file mode 100644 index 000000000..ddf292b12 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java @@ -0,0 +1,82 @@ +// --- 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.math.BigInteger; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.replicadb.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.CMS; + +/** + * A class represents a replica repository. It + * creates unique managed replica IDs. + *

+ * + * @author alee + * @version $Revision$, $Date$ + */ +public class ReplicaIDRepository extends Repository + implements IReplicaIDRepository { + + private IDBSubsystem mDBService; + private String mBaseDN; + + /** + * Constructs a certificate repository. + */ + public ReplicaIDRepository(IDBSubsystem dbService, int increment, String baseDN) + throws EDBException { + super(dbService, increment, baseDN); + mBaseDN = baseDN; + mDBService = dbService; + } + + + /** + * Returns last serial number in given range + */ + public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) + throws EBaseException { + CMS.debug("ReplicaIDReposoitory: 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; + } + BigInteger ret = new BigInteger(getMinSerial()); + if ((ret==null) || (ret.compareTo(serial_upper_bound) >0) || (ret.compareTo(serial_low_bound) <0)) { + return null; + } + return ret; + } + + /** + * Retrieves DN of this repository. + */ + public String getDN() { + return mBaseDN; + } + + /** + * Retrieves backend database handle. + */ + public IDBSubsystem getDBSubsystem() { + return mDBService; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java b/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java new file mode 100644 index 000000000..df84b1156 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java @@ -0,0 +1,504 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.repository.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.dbs.replicadb.*; + +/** + * A class represents a generic repository. It maintains unique + * serial number within repository. + *

+ * To build domain specific repository, subclass should be + * created. + *

+ * + * @author galperin + * @author thomask + * @version $Revision: 1.4 + * + $, $Date$ + */ + +public abstract class Repository implements IRepository { + + private static final BigInteger BI_ONE = new BigInteger("1"); + private BigInteger BI_INCREMENT = null; + private static final BigInteger BI_ZERO = new BigInteger("0"); + // (the next serialNo to be issued) - 1 + private BigInteger mSerialNo = null; + // the serialNo attribute stored in db + private BigInteger mNext = null; + + private String mMaxSerial = null; + private String mMinSerial = null; + private String mNextMaxSerial = null; + private String mNextMinSerial = null; + + private BigInteger mMinSerialNo = null; + private BigInteger mMaxSerialNo = null; + private BigInteger mNextMinSerialNo = null; + private BigInteger mNextMaxSerialNo = null; + + private BigInteger mIncrementNo = null; + private BigInteger mLowWaterMarkNo = null; + + private IDBSubsystem mDB = null; + private String mBaseDN = null; + private boolean mInit = false; + private int mRadix = 10; + private int mRepo = -1; + + + private BigInteger mLastSerialNo = null; + /** + * Constructs a repository. + *

+ */ + public Repository(IDBSubsystem db, int increment, String baseDN) + throws EDBException { + mDB = db; + mBaseDN = baseDN; + + + BI_INCREMENT = new BigInteger(Integer.toString(increment)); + + // register schema + IDBRegistry reg = db.getRegistry(); + + /** + if (!reg.isObjectClassRegistered( + RepositoryRecord.class.getName())) { + String repRecordOC[] = new String[2]; + repRecordOC[0] = RepositorySchema.LDAP_OC_TOP; + repRecordOC[1] = RepositorySchema.LDAP_OC_REPOSITORY; + reg.registerObjectClass( + RepositoryRecord.class.getName(), repRecordOC); + } + if (!reg.isAttributeRegistered(RepositoryRecord.ATTR_SERIALNO)) { + reg.registerAttribute(RepositoryRecord.ATTR_SERIALNO, + new BigIntegerMapper(RepositorySchema.LDAP_ATTR_SERIALNO)); + } + **/ + } + + /** + * Resets serial number. + */ + public void resetSerialNumber(BigInteger serial) throws EBaseException + { + IDBSSession s = mDB.createSession(); + + try { + String name = mBaseDN; + ModificationSet mods = new ModificationSet(); + mods.add(IRepositoryRecord.ATTR_SERIALNO, + Modification.MOD_REPLACE, serial); + s.modify(name, mods); + } finally { + if (s != null) + s.close(); + } + } + + /** + * Retrieves the next serial number attr in db. + *

+ * + * @return next serial number + */ + protected BigInteger getSerialNumber() throws EBaseException { + IDBSSession s = mDB.createSession(); + + CMS.debug("Repository: getSerialNumber."); + RepositoryRecord rec = null; + + try { + if (s != null) rec = (RepositoryRecord) s.read(mBaseDN); + } finally { + if (s != null) s.close(); + } + + if( rec == null ) { + CMS.debug( "Repository::getSerialNumber() - " + + "- rec is null!" ); + throw new EBaseException( "rec is null" ); + } + + BigInteger serial = rec.getSerialNumber(); + + if (!mInit) { + // cms may crash after issue a cert but before update + // the serial number record + try { + IDBObj obj = s.read("cn=" + + serial + "," + mBaseDN); + + if (obj != null) { + serial = serial.add(BI_ONE); + setSerialNumber(serial); + } + }catch (EBaseException e) { + // do nothing + } + mInit = true; + } + return serial; + } + + /** + * Updates the serial number to the specified in db. + *

+ * + * @param num serial number + */ + protected void setSerialNumber(BigInteger num) throws EBaseException { + + CMS.debug("Repository:setSerialNumber " + num.toString()); + + return; + + } + + /** + * Get the maximum serial number. + * + * @return maximum serial number + */ + public String getMaxSerial() { + return mMaxSerial; + } + + /** + * Set the maximum serial number. + * + * @param serial maximum number + * @exception EBaseException failed to set maximum serial number + */ + public void setMaxSerial(String serial) throws EBaseException { + BigInteger maxSerial = null; + CMS.debug("Repository:setMaxSerial " + serial); + + maxSerial = new BigInteger(serial, mRadix); + if (maxSerial != null) { + mMaxSerial = serial; + mMaxSerialNo = maxSerial; + } + } + + /** + * Get the maximum serial number in next range. + * + * @return maximum serial number in next range + */ + public String getNextMaxSerial() { + return mNextMaxSerial; + } + + /** + * Set the maximum serial number in next range + * + * @param serial maximum number in next range + * @exception EBaseException failed to set maximum serial number in next range + */ + public void setNextMaxSerial(String serial) throws EBaseException { + BigInteger maxSerial = null; + CMS.debug("Repository:setNextMaxSerial " + serial); + + maxSerial = new BigInteger(serial, mRadix); + if (maxSerial != null) { + mNextMaxSerial = serial; + mNextMaxSerialNo = maxSerial; + } + + return; + } + + /** + * Get the minimum serial number. + * + * @return minimum serial number + */ + public String getMinSerial() { + return mMinSerial; + } + + + /** + * init serial number cache + */ + private void initCache() throws EBaseException { + mNext = getSerialNumber(); + BigInteger serialConfig = new BigInteger("0"); + mRadix = 10; + + CMS.debug("Repository: in InitCache"); + + if (this instanceof ICertificateRepository) { + CMS.debug("Repository: Instance of Certificate Repository."); + mRadix = 16; + mRepo = IDBSubsystem.CERTS; + } else if (this instanceof IKeyRepository) { + // Key Repository uses the same configuration parameters as Certificate + // Repository. This is ok because they are on separate subsystems. + CMS.debug("Repository: Instance of Key Repository"); + mRadix = 16; + mRepo = IDBSubsystem.CERTS; + } else if (this instanceof IReplicaIDRepository) { + CMS.debug("Repository: Instance of Replica ID repository"); + mRepo = IDBSubsystem.REPLICA_ID; + } else { + // CRLRepository subclasses this too, but does not use serial number stuff + CMS.debug("Repository: Instance of Request Repository or CRLRepository."); + mRepo = IDBSubsystem.REQUESTS; + } + + mMinSerial = mDB.getMinSerialConfig(mRepo); + mMaxSerial = mDB.getMaxSerialConfig(mRepo); + mNextMinSerial = mDB.getNextMinSerialConfig(mRepo); + mNextMaxSerial = mDB.getNextMaxSerialConfig(mRepo); + String increment = mDB.getIncrementConfig(mRepo); + String lowWaterMark = mDB.getLowWaterMarkConfig(mRepo); + + CMS.debug("Repository: minSerial " + mMinSerial + " maxSerial: " + mMaxSerial); + + if(mMinSerial != null) + mMinSerialNo = new BigInteger(mMinSerial,mRadix); + + if(mMaxSerial != null) + mMaxSerialNo = new BigInteger(mMaxSerial,mRadix); + + if(mNextMinSerial != null) + mNextMinSerialNo = new BigInteger(mNextMinSerial,mRadix); + + if(mNextMaxSerial != null) + mNextMaxSerialNo = new BigInteger(mNextMaxSerial,mRadix); + + if(lowWaterMark != null) + mLowWaterMarkNo = new BigInteger(lowWaterMark,mRadix); + + if(increment != null) + mIncrementNo = new BigInteger(increment,mRadix); + + BigInteger theSerialNo = null; + theSerialNo = getLastSerialNumberInRange(mMinSerialNo,mMaxSerialNo); + + if(theSerialNo != null) { + + mLastSerialNo = new BigInteger(theSerialNo.toString()); + CMS.debug("Repository: mLastSerialNo: " + mLastSerialNo.toString()); + + } + else { + + throw new EBaseException("Error in obtaining the last serial number in the repository!"); + + } + + } + + /** + * get the next serial number in cache + */ + public BigInteger getTheSerialNumber() throws EBaseException { + + CMS.debug("Repository:In getTheSerialNumber " ); + if (mLastSerialNo == null) + initCache(); + BigInteger serial = new BigInteger((mLastSerialNo.add(BI_ONE)).toString()); + + if (mMaxSerialNo != null && serial.compareTo(mMaxSerialNo) > 0) + return null; + else + return serial; + } + + /** + * Updates the serial number to the specified in db and cache. + *

+ * + * @param num serial number + */ + public void setTheSerialNumber(BigInteger num) throws EBaseException { + // mSerialNo is already set. But just in case + + CMS.debug("Repository:In setTheSerialNumber " + num.toString()); + if (mLastSerialNo == null) + initCache(); + + if (num.compareTo(mSerialNo) <= 0) { + throw new EDBException(CMS.getUserMessage("CMS_DBS_SETBACK_SERIAL", + mSerialNo.toString(16))); + } + // write the config parameter. It's needed in case the serialNum gap + // < BI_INCREMENT and server restart right afterwards. + mDB.setNextSerialConfig(num); + + mSerialNo = num.subtract(BI_ONE); + mNext = num.add(BI_INCREMENT); + setSerialNumber(mNext); + } + + /** + * Retrieves the next serial number, and also increase the + * serial number by one. + *

+ * + * @return serial number + */ + public synchronized BigInteger getNextSerialNumber() throws + EBaseException { + + CMS.debug("Repository: in getNextSerialNumber. "); + + if (mLastSerialNo == null) { + initCache(); + + mLastSerialNo = mLastSerialNo.add(BI_ONE); + + + } else { + mLastSerialNo = mLastSerialNo.add(BI_ONE); + } + + if( mLastSerialNo == null ) { + CMS.debug( "Repository::getNextSerialNumber() " + + "- mLastSerialNo is null!" ); + throw new EBaseException( "mLastSerialNo is null" ); + } + + // check if we have reached the end of the range + // if so, move to next range + if (mLastSerialNo.compareTo( mMaxSerialNo ) > 0 ) { + if (mDB.getEnableSerialMgmt()) { + CMS.debug("Reached the end of the range. Attempting to move to next range"); + mMinSerialNo = mNextMinSerialNo; + mMaxSerialNo = mNextMaxSerialNo; + mLastSerialNo = mMinSerialNo; + mNextMinSerialNo = null; + mNextMaxSerialNo = null; + if ((mMaxSerialNo == null) || (mMinSerialNo == null)) { + throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED", + mLastSerialNo.toString())); + } + + // persist the changes + mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString()); + mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString()); + mDB.setNextMinSerialConfig(mRepo, null); + mDB.setNextMaxSerialConfig(mRepo, null); + } else { + throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED", + mLastSerialNo.toString())); + } + } + + BigInteger retSerial = new BigInteger(mLastSerialNo.toString()); + + CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial); + return retSerial; + } + + /** + * Checks to see if a new range is needed, or if we have reached the end of the + * current range, or if a range conflict has occurred. + * + * @exception EBaseException failed to check next range for conflicts + */ + public void checkRanges() throws EBaseException + { + if (!mDB.getEnableSerialMgmt()) { + CMS.debug("Serial Management not enabled. Returning .. "); + return; + } + if (CMS.getEESSLPort() == null) { + CMS.debug("Server not completely started. Returning .."); + return; + } + + if (mLastSerialNo == null) + initCache(); + + BigInteger numsInRange = mMaxSerialNo.subtract(mLastSerialNo); + BigInteger numsInNextRange = null; + BigInteger numsAvail = null; + CMS.debug("Serial numbers left in range: " + numsInRange.toString()); + CMS.debug("Last Serial Number: " + mLastSerialNo.toString()); + if ((mNextMaxSerialNo != null) && (mNextMinSerialNo != null)) { + numsInNextRange = mNextMaxSerialNo.subtract(mNextMinSerialNo); + numsAvail = numsInRange.add(numsInNextRange); + CMS.debug("Serial Numbers in next range: " + numsInNextRange.toString()); + CMS.debug("Serial Numbers available: " + numsAvail.toString()); + } else { + numsAvail = numsInRange; + CMS.debug("Serial Numbers available: " + numsAvail.toString()); + } + + if ((numsAvail.compareTo(mLowWaterMarkNo) < 0) && (!CMS.isPreOpMode()) ) { + CMS.debug("Low water mark reached. Requesting next range"); + mNextMinSerialNo = new BigInteger(mDB.getNextRange(mRepo), mRadix); + if (mNextMinSerialNo == null) { + CMS.debug("Next Range not available"); + } else { + CMS.debug("nNextMinSerialNo has been set to " + mNextMinSerialNo.toString(mRadix)); + mNextMaxSerialNo = mNextMinSerialNo.add(mIncrementNo); + numsAvail = numsAvail.add(mIncrementNo); + mDB.setNextMinSerialConfig(mRepo, mNextMinSerialNo.toString(mRadix)); + mDB.setNextMaxSerialConfig(mRepo, mNextMaxSerialNo.toString(mRadix)); + } + } + + if (numsInRange.compareTo (mLowWaterMarkNo) < 0 ) { + // check for a replication error + CMS.debug("Checking for a range conflict"); + if (mDB.hasRangeConflict(mRepo)) { + CMS.debug("Range Conflict found! Removing next range."); + mNextMaxSerialNo = null; + mNextMinSerialNo= null; + mDB.setNextMinSerialConfig(mRepo, null); + mDB.setNextMaxSerialConfig(mRepo, null); + } + } + } + + /** + * Sets whether serial number management is enabled for certs + * and requests. + * + * @param value true/false + * @exception EBaseException failed to set + */ + public void setEnableSerialMgmt(boolean value) throws EBaseException + { + mDB.setEnableSerialMgmt(value); + } + + public abstract BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound) throws + EBaseException; +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java b/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java new file mode 100644 index 000000000..7aa63fa1d --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java @@ -0,0 +1,112 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.repository.*; + + +/** + * A class represents a repository record. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class RepositoryRecord implements IRepositoryRecord { + + private BigInteger mSerialNo = null; + private String mPublishingStatus = null; + + protected static Vector mNames = new Vector(); + static { + mNames.addElement(IRepositoryRecord.ATTR_SERIALNO); + mNames.addElement(IRepositoryRecord.ATTR_PUB_STATUS); + } + + /** + * Constructs a repository record. + *

+ */ + public RepositoryRecord() { + } + + /** + * Sets attribute. + */ + public void set(String name, Object obj) throws EBaseException { + if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_SERIALNO)) { + mSerialNo = (BigInteger) obj; + } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) { + mPublishingStatus = (String) obj; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Retrieves attribute from this record. + */ + public Object get(String name) throws EBaseException { + if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_SERIALNO)) { + return mSerialNo; + } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) { + return mPublishingStatus; + } else { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + } + + /** + * Deletes an attribute. + */ + public void delete(String name) throws EBaseException { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name)); + } + + /** + * Retrieves a list of attribute names. + */ + public Enumeration getElements() { + return mNames.elements(); + } + + public Enumeration getSerializableAttrNames() { + return mNames.elements(); + } + + /** + * Retrieves serial number. + */ + public BigInteger getSerialNumber() { + return mSerialNo; + } + + public String getPublishingStatus() { + return mPublishingStatus; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java b/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java new file mode 100644 index 000000000..436c8633e --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java @@ -0,0 +1,44 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents a collection of repository-specific + * schema information. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class RepositorySchema { + + public static final String LDAP_OC_TOP = "top"; + public static final String LDAP_OC_REPOSITORY = "repository"; + public static final String LDAP_ATTR_SERIALNO = "serialno"; + public static final String LDAP_ATTR_PUB_STATUS = "publishingStatus"; +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java new file mode 100644 index 000000000..81ae72053 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfo.java @@ -0,0 +1,81 @@ +// --- 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.util.*; +import java.io.*; +import java.math.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.certdb.*; + +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.*; + + +/** + * A class represents a certificate revocation info. This + * object is written as an attribute of certificate record + * which essentially signifies a revocation act. + *

+ * + * @author galperin + * @version $Revision$, $Date$ + */ +public class RevocationInfo implements IRevocationInfo, Serializable { + + private Date mRevocationDate = null; + private CRLExtensions mCRLEntryExtensions = null; + + /** + * Constructs revocation info. + */ + public RevocationInfo() { + } + + /** + * Constructs revocation info used by revocation + * request implementation. + * + * @param reason if not null contains CRL entry extension + * that specifies revocation reason + * @see CRLReasonExtension + */ + public RevocationInfo(Date revocationDate, CRLExtensions exts) { + mRevocationDate = revocationDate; + mCRLEntryExtensions = exts; + } + + /** + * Retrieves revocation date. + */ + public Date getRevocationDate() { + return mRevocationDate; + } + + /** + * Retrieves CRL extensions. + */ + public CRLExtensions getCRLEntryExtensions() { + return mCRLEntryExtensions; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java new file mode 100644 index 000000000..6ee2c7bb2 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/RevocationInfoMapper.java @@ -0,0 +1,167 @@ +// --- 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.math.*; +import java.io.*; +import java.util.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.Debug; + + +/** + * A class represents a mapper to serialize + * revocation information into database. + *

+ * + * @author thomask + * @version $Revision$, $Date$ + */ +public class RevocationInfoMapper implements IDBAttrMapper { + + protected static Vector mNames = new Vector(); + static { + mNames.addElement(CertDBSchema.LDAP_ATTR_REVO_INFO); + } + + /** + * Constructs revocation information mapper. + */ + public RevocationInfoMapper() { + } + + public Enumeration getSupportedLDAPAttributeNames() { + return mNames.elements(); + } + + public void mapObjectToLDAPAttributeSet(IDBObj parent, String name, + Object obj, LDAPAttributeSet attrs) + throws EBaseException { + try { + // in format of ; + String value = ""; + RevocationInfo info = (RevocationInfo) obj; + Date d = info.getRevocationDate(); + + value = DateMapper.dateToDB(d); + CRLExtensions exts = info.getCRLEntryExtensions(); + // CRLExtension's DER encoding and decoding does not work! + // That is why we need to do our own serialization. + Enumeration e = exts.getElements(); + + while (e.hasMoreElements()) { + Extension ext = (Extension) e.nextElement(); + + if (ext instanceof CRLReasonExtension) { + RevocationReason reason = + ((CRLReasonExtension) ext).getReason(); + + value = value + ";CRLReasonExtension=" + + Integer.toString(reason.toInt()); + } else if (ext instanceof InvalidityDateExtension) { + Date invalidityDate = + ((InvalidityDateExtension) ext).getInvalidityDate(); + + value = value + ";InvalidityDateExtension=" + + DateMapper.dateToDB(invalidityDate); + } else { + Debug.trace("XXX skipped extension"); + } + } + attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_REVO_INFO, + value)); + } catch (Exception e) { + Debug.trace(e.toString()); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name)); + } + } + + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + try { + LDAPAttribute attr = attrs.getAttribute( + CertDBSchema.LDAP_ATTR_REVO_INFO); + + if (attr == null) + return; + String value = (String) attr.getStringValues().nextElement(); + int i = value.indexOf(';'); // look for 1st ";" + String str = null; + CRLExtensions exts = new CRLExtensions(); + Date d = null; + + if (i == -1) { + // only date found; no extensions + d = DateMapper.dateFromDB(value); + } else { + String s = value; + + str = s.substring(0, i); + d = DateMapper.dateFromDB(str); + s = s.substring(i + 1); + do { + i = s.indexOf(';'); + if (i == -1) { + str = s; + } else { + str = s.substring(0, i); + s = s.substring(i + 1); + } + if (str.startsWith("CRLReasonExtension=")) { + String reasonStr = str.substring(19); + RevocationReason reason = RevocationReason.fromInt( + Integer.parseInt(reasonStr)); + CRLReasonExtension ext = new CRLReasonExtension(reason); + + exts.set(CRLReasonExtension.NAME, ext); + } else if (str.startsWith("InvalidityDateExtension=")) { + String invalidityDateStr = str.substring(24); + Date invalidityDate = DateMapper.dateFromDB(invalidityDateStr); + InvalidityDateExtension ext = + new InvalidityDateExtension(invalidityDate); + + exts.set(InvalidityDateExtension.NAME, ext); + } else { + Debug.trace("XXX skipped extension"); + } + } + while (i != -1); + } + RevocationInfo info = new RevocationInfo(d, exts); + + parent.set(name, info); + } catch (Exception e) { + Debug.trace(e.toString()); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } + } + + public String mapSearchFilter(String name, String op, String value) + throws EBaseException { + return CertDBSchema.LDAP_ATTR_REVO_INFO + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java new file mode 100644 index 000000000..e9fbd64e7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/StringMapper.java @@ -0,0 +1,91 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java String object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class StringMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs string mapper. + */ + public StringMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of supported ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps attribute value to ldap attributes. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, (String) obj)); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) + throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) { + return; + } + try { + parent.set(name, (String) + attr.getStringValues().nextElement()); + } catch (NoSuchElementException e) { + // attribute present, but without value + } + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java new file mode 100644 index 000000000..2ec203eb6 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/StringVectorMapper.java @@ -0,0 +1,106 @@ +// --- 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.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java String object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class StringVectorMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + /** + * Constructs string vector mapper. + */ + public StringVectorMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of supported ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps attribute value to ldap attributes. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + Vector v = (Vector) obj; + int s = v.size(); + + if (s == 0) { + return; + } + String m[] = new String[s]; + + for (int i = 0; i < s; i++) { + m[i] = (String) v.elementAt(i); + } + attrs.add(new LDAPAttribute(mLdapName, m)); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) + return; + Enumeration e = attr.getStringValues(); + Vector v = new Vector(); + + while (e.hasMoreElements()) { + v.addElement((String) e.nextElement()); + } + if (v.size() == 0) + return; + String m[] = new String[v.size()]; + + v.copyInto(m); + parent.set(name, m); + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java new file mode 100644 index 000000000..b7e386f77 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/X500NameMapper.java @@ -0,0 +1,107 @@ +// --- 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.*; +import java.util.*; +import netscape.security.x509.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class represents ann attribute mapper that maps + * a Java X500Name object into LDAP attribute, + * and vice versa. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class X500NameMapper implements IDBAttrMapper { + + private String mLdapName = null; + private Vector v = new Vector(); + + private ILogger mLogger = CMS.getLogger(); + + /** + * Constructs X500Name mapper. + */ + public X500NameMapper(String ldapName) { + mLdapName = ldapName; + v.addElement(mLdapName); + } + + /** + * Retrieves a list of ldap attributes. + */ + public Enumeration getSupportedLDAPAttributeNames() { + return v.elements(); + } + + /** + * Maps attribute value to ldap attributes. + */ + public void mapObjectToLDAPAttributeSet(IDBObj parent, + String name, Object obj, LDAPAttributeSet attrs) + throws EBaseException { + attrs.add(new LDAPAttribute(mLdapName, + ((X500Name) obj).toString())); + } + + /** + * Maps LDAP attributes into object, and put the object + * into 'parent'. + */ + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + LDAPAttribute attr = attrs.getAttribute(mLdapName); + + if (attr == null) { + return; + } + try { + parent.set(name, new X500Name((String) + attr.getStringValues().nextElement())); + } catch (IOException e) { + + /*LogDoc + * + * @phase Maps LDAP attributes into object + * @message X500NameMapper: + */ + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_DBS_X500NAME_MAPPER_ERROR", + e.toString())); + throw new EDBException( + CMS.getUserMessage("CMS_DBS_DESERIALIZE_FAILED", name)); + } + } + + /** + * Maps search filters into LDAP search filter. + */ + public String mapSearchFilter(String name, String op, + String value) throws EBaseException { + return mLdapName + op + value; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java b/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java new file mode 100644 index 000000000..29e1db849 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/dbs/X509CertImplMapper.java @@ -0,0 +1,363 @@ +// --- 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.*; +import java.util.*; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.extensions.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.cert.*; +import com.netscape.cmscore.util.Debug; + + +/** + * A class represents a mapper to serialize + * x509 certificate into database. + * + * @author thomask + * @version $Revision$, $Date$ + */ +public class X509CertImplMapper implements IDBAttrMapper { + + public X509CertImplMapper() { + } + + public Enumeration getSupportedLDAPAttributeNames() { + Vector v = new Vector(); + + v.addElement(CertDBSchema.LDAP_ATTR_NOT_BEFORE); + v.addElement(CertDBSchema.LDAP_ATTR_NOT_AFTER); + v.addElement(CertDBSchema.LDAP_ATTR_DURATION); + v.addElement(CertDBSchema.LDAP_ATTR_EXTENSION); + v.addElement(CertDBSchema.LDAP_ATTR_SUBJECT); + v.addElement(CertDBSchema.LDAP_ATTR_SIGNED_CERT); + v.addElement(CertDBSchema.LDAP_ATTR_VERSION); + v.addElement(CertDBSchema.LDAP_ATTR_ALGORITHM); + v.addElement(CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM); + v.addElement(CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA); + return v.elements(); + } + + public void mapObjectToLDAPAttributeSet(IDBObj parent, String name, + Object obj, LDAPAttributeSet attrs) throws EBaseException { + try { + X509CertImpl cert = (X509CertImpl) obj; + // make information searchable + Date notBefore = cert.getNotBefore(); + + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_NOT_BEFORE, + DateMapper.dateToDB(notBefore))); + Date notAfter = cert.getNotAfter(); + + attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_NOT_AFTER, + DateMapper.dateToDB(notAfter))); + attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_DURATION, + DBSUtil.longToDB(notAfter.getTime() - notBefore.getTime()))); + attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_SUBJECT, + cert.getSubjectDN().getName())); + attrs.add(new LDAPAttribute(CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA, cert.getPublicKey().getEncoded())); + // make extension searchable + Set nonCritSet = cert.getNonCriticalExtensionOIDs(); + + if (nonCritSet != null) { + for (Iterator i = nonCritSet.iterator(); i.hasNext();) { + String oid = (String) i.next(); + + if (oid.equals("2.16.840.1.113730.1.1")) { + String extVal = getCertTypeExtensionInfo(cert); + + if (extVal != null) { + oid = oid + ";" + extVal; + } + } else if (oid.equals("2.5.29.19")) { + String extVal = getBasicConstraintsExtensionInfo(cert); + + if (extVal != null) { + oid = oid + ";" + extVal; + } + } + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_EXTENSION, oid)); + } + } + Set critSet = cert.getCriticalExtensionOIDs(); + + if (critSet != null) { + for (Iterator i = critSet.iterator(); i.hasNext();) { + String oid = (String) i.next(); + + if (oid.equals("2.16.840.1.113730.1.1")) { + String extVal = getCertTypeExtensionInfo(cert); + + if (extVal != null) { + oid = oid + ";" + extVal; + } + } else if (oid.equals("2.5.29.19")) { + String extVal = getBasicConstraintsExtensionInfo(cert); + + if (extVal != null) { + oid = oid + ";" + extVal; + } + } + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_EXTENSION, oid)); + } + } + + // something extra; so that we can rebuild the + // object quickly + // if we dont add ";binary", communicator does + // not know how to display the certificate in + // pretty print format. + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_SIGNED_CERT + ";binary", + cert.getEncoded())); + + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_VERSION, + Integer.toString(cert.getVersion()))); + X509Key pubKey = (X509Key) cert.getPublicKey(); + + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_ALGORITHM, + pubKey.getAlgorithmId().getOID().toString())); + attrs.add(new LDAPAttribute( + CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM, + cert.getSigAlgOID())); + } catch (CertificateEncodingException e) { + throw new EDBException( + CMS.getUserMessage("CMS_DBS_SERIALIZE_FAILED", name)); + } + } + + private String getCertTypeExtensionInfo(X509CertImpl cert) { + try { + Extension ext = cert.getExtension("2.16.840.1.113730.1.1"); + + if (ext == null) { + // sometime time (during installation) it + // is named differently + ext = cert.getExtension(NSCertTypeExtension.NAME); + if (ext == null) + return null; + } + NSCertTypeExtension nsExt = (NSCertTypeExtension) ext; + + String result = ""; + + Boolean sslServer = (Boolean) nsExt.get( + NSCertTypeExtension.SSL_SERVER); + + result += "SSLServer=" + sslServer.toString() + ","; + Boolean sslClient = (Boolean) nsExt.get( + NSCertTypeExtension.SSL_CLIENT); + + result += "SSLClient=" + sslClient.toString() + ","; + Boolean email = (Boolean) nsExt.get( + NSCertTypeExtension.EMAIL); + + result += "Email=" + email.toString() + ","; + Boolean sslCA = (Boolean) nsExt.get( + NSCertTypeExtension.SSL_CA); + + result += "SSLCA=" + sslCA.toString() + ","; + Boolean mailCA = (Boolean) nsExt.get( + NSCertTypeExtension.EMAIL_CA); + + result += "EmailCA=" + mailCA.toString() + ","; + Boolean objectSigning = (Boolean) nsExt.get( + NSCertTypeExtension.OBJECT_SIGNING); + + result += "objectSigning=" + + objectSigning.toString(); + return result; + } catch (Exception e) { + return null; + } + } + + private String getBasicConstraintsExtensionInfo(X509CertImpl cert) { + try { + Extension ext = cert.getExtension("2.5.29.19"); + + if (ext == null) { + // sometime time (during installation) it + // is named differently + ext = cert.getExtension(BasicConstraintsExtension.NAME); + if (ext == null) + return null; + } + BasicConstraintsExtension bcExt = (BasicConstraintsExtension) ext; + + String result = ""; + + Boolean isCA = (Boolean) bcExt.get( + BasicConstraintsExtension.IS_CA); + + result += "isCA=" + isCA.toString() + ","; + Integer pathLen = (Integer) bcExt.get( + BasicConstraintsExtension.PATH_LEN); + + result += "pathLen=" + pathLen.toString(); + return result; + } catch (Exception e) { + return null; + } + } + + public void mapLDAPAttributeSetToObject(LDAPAttributeSet attrs, + String name, IDBObj parent) throws EBaseException { + try { + // rebuild object quickly using binary image + // XXX bad! when we add this attribute, + // we add it as userCertificate, but when + // we retrieve it, DS returns it as + // userCertificate;binary. So I cannot do the + // following: + // LDAPAttribute attr = attrs.getAttribute( + // Schema.LDAP_ATTR_SIGNED_CERT); + + X509CertInfo certinfo = new X509CertInfo(); + LDAPAttribute attr = attrs.getAttribute( + CertDBSchema.LDAP_ATTR_SIGNED_CERT); + + if (attr == null) { + // YUK! + attr = attrs.getAttribute( + CertDBSchema.LDAP_ATTR_SIGNED_CERT + ";binary"); + } + if (attr != null) { + byte der[] = (byte[]) + attr.getByteValues().nextElement(); + X509CertImpl impl = new X509CertImpl(der); + + parent.set(name, impl); + } + } catch (CertificateException e) { + //throw new EDBException( + // DBResources.FAILED_TO_DESERIALIZE_1, name); + parent.set(name, null); + } catch (Exception e) { + //throw new EDBException( + // DBResources.FAILED_TO_DESERIALIZE_1, name); + parent.set(name, null); + + } + } + + public String mapSearchFilter(String name, String op, String value) + throws EBaseException { + AttributeNameHelper h = new AttributeNameHelper(name); + String suffix = h.getSuffix(); + + if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_NOT_BEFORE)) { + name = CertDBSchema.LDAP_ATTR_NOT_BEFORE; + try { + value = DateMapper.dateToDB(new + Date(Long.parseLong(value))); + } catch (NumberFormatException e) { + } + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_NOT_AFTER)) { + name = CertDBSchema.LDAP_ATTR_NOT_AFTER; + try { + value = DateMapper.dateToDB(new + Date(Long.parseLong(value))); + } catch (NumberFormatException e) { + } + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SUBJECT)) { + name = CertDBSchema.LDAP_ATTR_SUBJECT; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_PUBLIC_KEY_DATA)) { + name = CertDBSchema.LDAP_ATTR_PUBLIC_KEY_DATA; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_DURATION)) { + name = CertDBSchema.LDAP_ATTR_DURATION; + value = DBSUtil.longToDB(Long.parseLong(value)); + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_VERSION)) { + name = CertDBSchema.LDAP_ATTR_VERSION; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_ALGORITHM)) { + name = CertDBSchema.LDAP_ATTR_ALGORITHM; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SIGNING_ALGORITHM)) { + name = CertDBSchema.LDAP_ATTR_SIGNING_ALGORITHM; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_SERIAL_NUMBER)) { + name = CertDBSchema.LDAP_ATTR_CERT_RECORD_ID; + } else if (suffix.equalsIgnoreCase(ICertRecord.X509CERT_EXTENSION)) { + name = CertDBSchema.LDAP_ATTR_EXTENSION; + } else if (suffix.equalsIgnoreCase(ICertRecord.ATTR_REVO_INFO)) { + name = CertDBSchema.LDAP_ATTR_REVO_INFO; + value = "*;CRLReasonExtension=" + value + "*"; + } else if (suffix.equalsIgnoreCase("nsExtension.SSLClient")) { + // special case for NS cert type extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.16.840.1.113730.1.1;*SSLClient=true*"; + } else { + value = "2.16.840.1.113730.1.1;*SSLClient=false*"; + } + } else if (suffix.equalsIgnoreCase("nsExtension.SSLServer")) { + // special case for NS cert type extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.16.840.1.113730.1.1;*SSLServer=true*"; + } else { + value = "2.16.840.1.113730.1.1;*SSLServer=false*"; + } + } else if (suffix.equalsIgnoreCase("nsExtension.SecureEmail")) { + // special case for NS cert type extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.16.840.1.113730.1.1;*Email=true*"; + } else { + value = "2.16.840.1.113730.1.1;*Email=false*"; + } + } else if (suffix.equalsIgnoreCase("nsExtension.SubordinateSSLCA")) { + // special case for NS cert type extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.16.840.1.113730.1.1;*SSLCA=true*"; + } else { + value = "2.16.840.1.113730.1.1;*SSLCA=false*"; + } + } else if (suffix.equalsIgnoreCase("nsExtension.SubordinateEmailCA")) { + // special case for NS cert type extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.16.840.1.113730.1.1;*EmailCA=true*"; + } else { + value = "2.16.840.1.113730.1.1;*EmailCA=false*"; + } + } else if (suffix.equalsIgnoreCase("BasicConstraints.isCA")) { + // special case for Basic Constraints extension + name = CertDBSchema.LDAP_ATTR_EXTENSION; + if (value.equals("on")) { + value = "2.5.29.19;*isCA=true*"; + } else { + value = "2.5.29.19;*isCA=false*"; + } + } + return name + op + value; + } +} -- cgit