From 621d9e5c413e561293d7484b93882d985b3fe15f Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Sat, 24 Mar 2012 02:27:47 -0500 Subject: Removed unnecessary pki folder. Previously the source code was located inside a pki folder. This folder was created during svn migration and is no longer needed. This folder has now been removed and the contents have been moved up one level. Ticket #131 --- .../src/com/netscape/cmscore/dbs/DBSubsystem.java | 948 +++++++++++++++++++++ 1 file changed, 948 insertions(+) create mode 100644 base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java (limited to 'base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java') diff --git a/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java b/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java new file mode 100644 index 000000000..4bc5b6471 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java @@ -0,0 +1,948 @@ +// --- 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.Hashtable; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSchema; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; +import netscape.ldap.LDAPObjectClassSchema; +import netscape.ldap.LDAPSchema; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv3; +import netscape.security.x509.CertificateValidity; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.dbs.EDBException; +import com.netscape.certsrv.dbs.EDBNotAvailException; +import com.netscape.certsrv.dbs.IDBRegistry; +import com.netscape.certsrv.dbs.IDBSSession; +import com.netscape.certsrv.dbs.IDBSubsystem; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.repository.IRepositoryRecord; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.ldap.ELdapServerDownException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cmscore.base.PropConfigStore; +import com.netscape.cmscore.ldapconn.LdapAuthInfo; +import com.netscape.cmscore.ldapconn.LdapBoundConnFactory; +import com.netscape.cmscore.ldapconn.LdapConnInfo; + +/** + * 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 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 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 = 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 = 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 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 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) { + 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) { + 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); + BigInteger incrementNo = new BigInteger((String) h.get(PROP_INCREMENT)); + // 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. + */ + @SuppressWarnings("unchecked") + 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); + } + +} -- cgit