diff options
author | alee <alee@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2009-01-05 16:58:25 +0000 |
---|---|---|
committer | alee <alee@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2009-01-05 16:58:25 +0000 |
commit | 12037cf9cf935bda5259e531b11a876ff2b41098 (patch) | |
tree | 2dd9029e94369398638d8467ddd895acae80cfb3 /pki/base/common | |
parent | dca02910f6de3f9631589ee3c12c229fa58629c8 (diff) | |
download | pki-12037cf9cf935bda5259e531b11a876ff2b41098.tar.gz pki-12037cf9cf935bda5259e531b11a876ff2b41098.tar.xz pki-12037cf9cf935bda5259e531b11a876ff2b41098.zip |
BZ472006 Serial number management
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@168 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
Diffstat (limited to 'pki/base/common')
19 files changed, 1232 insertions, 196 deletions
diff --git a/pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java index 311a7891b..a828a69bf 100644 --- a/pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java +++ b/pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java @@ -34,6 +34,7 @@ import com.netscape.certsrv.security.*; import com.netscape.certsrv.publish.*; import com.netscape.certsrv.dbs.certdb.*; import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.replicadb.*; /** @@ -243,6 +244,13 @@ public interface ICertificateAuthority extends ISubsystem { public ICRLRepository getCRLRepository(); /** + * Retrieves the Replica ID repository. + * + * @return CA's Replica ID repository + */ + public IReplicaIDRepository getReplicaRepository(); + + /** * Retrieves the request in queue listener. * * @return the request in queue listener diff --git a/pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java b/pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java index e3914427f..933fd607c 100644 --- a/pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java +++ b/pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java @@ -37,6 +37,13 @@ public interface IDBSubsystem extends ISubsystem { public static final String SUB_ID = "dbs"; + + // values for repos + public static final int CERTS = 0; + public static final int REQUESTS = 1; + public static final int REPLICA_ID = 2; + public static final int NUM_REPOS = 3; + /** * Retrieves the base DN. * @@ -85,25 +92,118 @@ public interface IDBSubsystem extends ISubsystem { * Records maximum serial number limit in config file * * @param serial max serial number + * @param repo repo identifier + * @exception EBaseException failed to set + */ + public void setMaxSerialConfig(int repo, String serial) throws EBaseException; + + /** + * Records minimum serial number limit in config file + * + * @param serial min serial number + * @param repo repo identifier + * @exception EBaseException failed to set + */ + public void setMinSerialConfig(int repo, String serial) throws EBaseException; + + /** + * Records maximum serial number limit for the next range in config file + * + * @param serial max serial number + * @param repo repo identifier * @exception EBaseException failed to set */ - public void setMaxSerialConfig(String serial) throws EBaseException; + public void setNextMaxSerialConfig(int repo, String serial) throws EBaseException; + /** + * Records minimum serial number limit for the next range in config file + * + * @param serial min serial number + * @param repo repo identifier + * @exception EBaseException failed to set + */ + public void setNextMinSerialConfig(int repo, String serial) throws EBaseException; - public String getMinSerialConfig(); + /** + * Gets minimum serial number limit in config file + * + * @param repo repo identifier + * @return min serial number + */ + public String getMinSerialConfig(int repo); /** * Gets the maximum serial number limit in config file * + * @param repo repo identifier * @return max serial number */ - public String getMaxSerialConfig(); + public String getMaxSerialConfig(int repo); + /** + * Gets the maximum serial number limit for next range in config file + * + * @param repo repo identifier + * @return max serial number + */ + public String getNextMaxSerialConfig(int repo); - public String getMinRequestConfig(); + /** + * Gets minimum serial number limit for next range in config file + * + * @param repo repo identifier + * @return min serial number + */ + public String getNextMinSerialConfig(int repo); + + /** + * Gets low water mark limit in config file + * + * @param repo repo identifier + * @return low water mark + */ + public String getLowWaterMarkConfig(int repo); - public String getMaxRequestConfig(); + /** + * Gets range increment limit for next range in config file + * + * @param repo repo identifier + * @return range increment + */ + public String getIncrementConfig(int repo); + + /** + * Gets number corresponding to start of next range from database + * + * @param repo repo identifier + * @return start of next range + */ + public String getNextRange(int repo); + /** + * Determines if a range conflict has been observed in database + * + * @param repo repo identifier + * @return true if range conflict, false otherwise + */ + public boolean hasRangeConflict(int repo); + + /** + * Determines if serial number management has been enabled + * + * @param repo repo identifier + * @return true if enabled, false otherwise + */ + public boolean getEnableSerialMgmt(); + + /** + * 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; /** * Returns LDAP connection to connection pool. diff --git a/pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java b/pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java index 3b76bbbf3..4b89650ee 100644 --- a/pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java +++ b/pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java @@ -76,10 +76,12 @@ public interface ICertificateRepository extends IRepository { /** * Sets certificate status update internal * + * @param requestRepo request repository * @param interval update interval * @param listenToCloneModifications enable listening to clone modifications */ - public void setCertStatusUpdateInterval(int interval, + public void setCertStatusUpdateInterval(IRepository requestRepo, + int interval, boolean listenToCloneModifications); /** diff --git a/pki/base/common/src/com/netscape/certsrv/dbs/replicadb/IReplicaIDRepository.java b/pki/base/common/src/com/netscape/certsrv/dbs/replicadb/IReplicaIDRepository.java new file mode 100644 index 000000000..6448e8d3a --- /dev/null +++ b/pki/base/common/src/com/netscape/certsrv/dbs/replicadb/IReplicaIDRepository.java @@ -0,0 +1,32 @@ +// --- 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.certsrv.dbs.replicadb; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.repository.*; + + +/** + * An interface represents a ReplicaID Repository. + * It provides unique managed replica IDs. + * <P> + * + * @version $Revision: 14561 $, $Date: 2008-11-18 10:28:56 -0700 (Tue, 18 Nov 2008) $ + */ +public interface IReplicaIDRepository extends IRepository { +} diff --git a/pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java b/pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java index 15162e77e..aed6a5482 100644 --- a/pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java +++ b/pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java @@ -34,17 +34,59 @@ import com.netscape.certsrv.dbs.*; */ public interface IRepository { - /** - * Retrieves the next serial number, and also increase the - * serial number by one. - * - * @return serial number + /** + * Retrieves the next serial number, and also increase the + * serial number by one. + * + * @return serial number * @exception EBaseException failed to retrieve next serial number - */ - public BigInteger getNextSerialNumber() throws EBaseException; + */ + public BigInteger getNextSerialNumber() throws EBaseException; /** * Resets serial number. */ public void resetSerialNumber(BigInteger serial) throws EBaseException; + + /** + * Retrieves the next serial number without increasing the serial number. + * + * @return serial number + * @exception EBaseException failed to retrieve next serial number + */ + public BigInteger getTheSerialNumber() throws EBaseException; + + /** + * Set the maximum serial number. + * + * @param serial maximum number + * @exception EBaseException failed to set maximum serial number + */ + public void setMaxSerial (String serial) throws EBaseException; + + /** + * Set the maximum serial number in next range. + * + * @param serial maximum number + * @exception EBaseException failed to set maximum serial number in next range + */ + public void setNextMaxSerial(String serial) throws EBaseException; + + /** + * 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; + + /** + * 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; + } diff --git a/pki/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java b/pki/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java index 40e8831ce..a2174d7cd 100644 --- a/pki/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java +++ b/pki/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java @@ -28,6 +28,7 @@ import com.netscape.certsrv.logging.*; import com.netscape.certsrv.base.*; import com.netscape.certsrv.dbs.*; import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.dbs.replicadb.*; import com.netscape.certsrv.request.*; import com.netscape.certsrv.policy.*; import com.netscape.certsrv.security.*; @@ -87,6 +88,13 @@ public interface IKeyRecoveryAuthority extends ISubsystem { public IKeyRepository getKeyRepository(); /** + * Retrieves the Replica ID repository. + * + * @return KRA's Replica ID repository + */ + public IReplicaIDRepository getReplicaRepository(); + + /** * Enables the auto recovery state. Once KRA is in the auto * recovery state, no recovery agents need to be present for * providing credentials. This feature is for enabling diff --git a/pki/base/common/src/com/netscape/certsrv/request/IRequestQueue.java b/pki/base/common/src/com/netscape/certsrv/request/IRequestQueue.java index f37421ffd..cfbea225f 100644 --- a/pki/base/common/src/com/netscape/certsrv/request/IRequestQueue.java +++ b/pki/base/common/src/com/netscape/certsrv/request/IRequestQueue.java @@ -19,6 +19,7 @@ package com.netscape.certsrv.request; import java.math.*; import java.util.Enumeration; +import com.netscape.certsrv.dbs.repository.IRepository; import com.netscape.certsrv.base.EBaseException; @@ -399,4 +400,11 @@ public interface IRequestQueue { * Removes all objects with this repository. */ public void removeAllObjects() throws EBaseException; + + /** + * Gets request repository. + * + * @return request repository + */ + public IRepository getRequestRepository(); } diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java index 985b5f244..e9523e52b 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java @@ -928,19 +928,6 @@ public class DatabasePanel extends WizardPanelBase { } catch (Exception e) { } - if (select.equals("clone")) { - CMS.debug("Start setting up replication."); - setupReplication(request, context, (secure.equals("on")?"true":"false")); - CMS.debug("Finish setting up replication."); - - try { - CMS.reinit(IDBSubsystem.SUB_ID); - CMS.reinit(IAuthSubsystem.ID); - CMS.reinit(IAuthzSubsystem.ID); - } catch (Exception e) { - } - } - // always populate the index the last try { CMS.debug("Populating local indexes"); @@ -974,6 +961,21 @@ public class DatabasePanel extends WizardPanelBase { CMS.debug("Populating index failure - " + e); } + // setup replication after indexes have been created + if (select.equals("clone")) { + CMS.debug("Start setting up replication."); + setupReplication(request, context, (secure.equals("on")?"true":"false")); + CMS.debug("Finish setting up replication."); + + try { + CMS.reinit(IDBSubsystem.SUB_ID); + CMS.reinit(IAuthSubsystem.ID); + CMS.reinit(IAuthzSubsystem.ID); + } catch (Exception e) { + } + } + + if (hasErr == false) { cs.putBoolean("preop.Database.done", true); try { @@ -1072,8 +1074,11 @@ public class DatabasePanel extends WizardPanelBase { String replicadn = "cn=replica,cn=\""+suffix+"\",cn=mapping tree,cn=config"; CMS.debug("DatabasePanel setupReplication: replicadn="+replicadn); - createReplicationManager(conn1, master1_replicationpwd); - createReplicationManager(conn2, master2_replicationpwd); + String masterBindUser = "Replication Manager " + masterAgreementName; + String cloneBindUser = "Replication Manager " + cloneAgreementName; + + createReplicationManager(conn1, masterBindUser, master1_replicationpwd); + createReplicationManager(conn2, cloneBindUser, master2_replicationpwd); String dir1 = getInstanceDir(conn1); createChangeLog(conn1, dir1 + "/changelogs"); @@ -1081,16 +1086,19 @@ public class DatabasePanel extends WizardPanelBase { String dir2 = getInstanceDir(conn2); createChangeLog(conn2, dir2 + "/changelogs"); - enableReplication(replicadn, conn1, basedn, "1"); - enableReplication(replicadn, conn2, basedn, "2"); + int replicaId = cs.getInteger("dbs.beginReplicaNumber", 1); + + replicaId = enableReplication(replicadn, conn1, masterBindUser, basedn, replicaId); + replicaId = enableReplication(replicadn, conn2, cloneBindUser, basedn, replicaId); + cs.putString("dbs.beginReplicaNumber", Integer.toString(replicaId)); CMS.debug("DatabasePanel setupReplication: Finished enabling replication"); createReplicationAgreement(replicadn, conn1, masterAgreementName, - master2_hostname, master2_port, master2_replicationpwd, basedn); + master2_hostname, master2_port, master2_replicationpwd, basedn, cloneBindUser); createReplicationAgreement(replicadn, conn2, cloneAgreementName, - master1_hostname, master1_port, master1_replicationpwd, basedn); + master1_hostname, master1_port, master1_replicationpwd, basedn, masterBindUser); // initialize consumer initializeConsumer(replicadn, conn1, masterAgreementName); @@ -1170,20 +1178,19 @@ public class DatabasePanel extends WizardPanelBase { return false; } - private void createReplicationManager(LDAPConnection conn, String pwd) + private void createReplicationManager(LDAPConnection conn, String bindUser, String pwd) throws LDAPException { LDAPAttributeSet attrs = null; LDAPEntry entry = null; - String dn = "cn=Replication Manager,cn=config"; + String dn = "cn=" + bindUser + ",cn=config"; try { attrs = new LDAPAttributeSet(); attrs.add(new LDAPAttribute("objectclass", "top")); attrs.add(new LDAPAttribute("objectclass", "person")); attrs.add(new LDAPAttribute("userpassword", pwd)); - attrs.add(new LDAPAttribute("cn", "Replication Manager")); + attrs.add(new LDAPAttribute("cn", bindUser)); attrs.add(new LDAPAttribute("sn", "manager")); - entry = new LDAPEntry("cn=Replication Manager,cn=config", - attrs); + entry = new LDAPEntry(dn, attrs); conn.add(entry); } catch (LDAPException e) { if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { @@ -1201,7 +1208,7 @@ public class DatabasePanel extends WizardPanelBase { } } - CMS.debug("DatabasePanel createReplicationManager: Successfully create Replication Manager"); + CMS.debug("DatabasePanel createReplicationManager: Successfully created Replication Manager"); } private void createChangeLog(LDAPConnection conn, String dir) @@ -1238,7 +1245,7 @@ public class DatabasePanel extends WizardPanelBase { CMS.debug("DatabasePanel createChangeLog: Successfully create change log entry"); } - private void enableReplication(String replicadn, LDAPConnection conn, String basedn, String id) + private int enableReplication(String replicadn, LDAPConnection conn, String bindUser, String basedn, int id) throws LDAPException { CMS.debug("DatabasePanel enableReplication: replicadn: "+replicadn); LDAPAttributeSet attrs = null; @@ -1251,33 +1258,42 @@ public class DatabasePanel extends WizardPanelBase { attrs.add(new LDAPAttribute("nsDS5ReplicaRoot", basedn)); attrs.add(new LDAPAttribute("nsDS5ReplicaType", "3")); attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN", - "cn=replication manager,cn=config")); + "cn=" + bindUser + ",cn=config")); attrs.add(new LDAPAttribute("cn", "replica")); - attrs.add(new LDAPAttribute("nsDS5ReplicaId", id)); + attrs.add(new LDAPAttribute("nsDS5ReplicaId", Integer.toString(id))); attrs.add(new LDAPAttribute("nsds5flags", "1")); entry = new LDAPEntry(replicadn, attrs); conn.add(entry); } catch (LDAPException e) { if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { - CMS.debug("DatabasePanel enableReplication: "+replicadn+" has already used"); + /* BZ 470918 -we cant just add the new dn. We need to do a replace instead + * until the DS code is fixed */ + CMS.debug("DatabasePanel enableReplication: "+replicadn+" has already been used"); + try { - conn.delete(replicadn); - conn.add(entry); + entry = conn.read(replicadn); + LDAPAttribute attr = entry.getAttribute("nsDS5ReplicaBindDN"); + attr.addValue( "cn=" + bindUser + ",cn=config"); + LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr); + conn.modify(replicadn, mod); } catch (LDAPException ee) { + CMS.debug("DatabasePanel enableReplication: Failed to modify " + +replicadn+" entry. Exception: "+e.toString()); } - return; + return id; } else { CMS.debug("DatabasePanel enableReplication: Failed to create "+replicadn+" entry. Exception: "+e.toString()); - return; + return id; } } CMS.debug("DatabasePanel enableReplication: Successfully create "+replicadn+" entry."); + return id + 1; } private void createReplicationAgreement(String replicadn, LDAPConnection conn, String name, String replicahost, int replicaport, - String replicapwd, String basedn) throws LDAPException { + String replicapwd, String basedn, String bindUser) throws LDAPException { String dn = "cn="+name+","+replicadn; CMS.debug("DatabasePanel createReplicationAgreement: dn: "+dn); LDAPEntry entry = null; @@ -1292,7 +1308,7 @@ public class DatabasePanel extends WizardPanelBase { attrs.add(new LDAPAttribute("nsDS5ReplicaHost", replicahost)); attrs.add(new LDAPAttribute("nsDS5ReplicaPort", ""+replicaport)); attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN", - "cn=replication manager,cn=config")); + "cn=" + bindUser + ",cn=config")); attrs.add(new LDAPAttribute("nsDS5ReplicaBindMethod", "Simple")); attrs.add(new LDAPAttribute("nsds5replicacredentials", replicapwd)); CMS.debug("About to set description attr to " + name); diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java index f6cd67e32..583548257 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java @@ -289,6 +289,7 @@ public class DonePanel extends WizardPanelBase { } cs.putString("securitydomain.store", "ldap"); CMS.debug("DonePanel display: finish updating domain info"); + conn.disconnect(); } catch (Exception e) { CMS.debug("DonePanel display: "+e.toString()); } @@ -397,12 +398,30 @@ public class DonePanel extends WizardPanelBase { BigInteger endRequestNum = new BigInteger(endRequestNumStr); BigInteger endSerialNum = new BigInteger(endSerialNumStr); BigInteger oneNum = new BigInteger("1"); - cs.putString("dbs.nextBeginRequestNumber", - endRequestNum.add(oneNum).toString()); - cs.putString("dbs.nextBeginSerialNumber", - endSerialNum.add(oneNum).toString()); + + // update global next range entries + LDAPConnection conn = getLDAPConn(context); + String basedn = cs.getString("internaldb.basedn"); + + String serialdn = ""; + if (type.equals("CA")) { + serialdn = "ou=certificateRepository,ou=" + type.toLowerCase() + "," + basedn; + } else { + serialdn = "ou=keyRepository,ou=" + type.toLowerCase() + "," + basedn; + } + LDAPAttribute attrSerialNextRange = new LDAPAttribute( "nextRange", endSerialNum.add(oneNum).toString()); + LDAPModification serialmod = new LDAPModification( LDAPModification.REPLACE, attrSerialNextRange ); + conn.modify( serialdn, serialmod ); + + String requestdn = "ou=" + type.toLowerCase() + ",ou=requests," + basedn; + LDAPAttribute attrRequestNextRange = new LDAPAttribute( "nextRange", endRequestNum.add(oneNum).toString()); + LDAPModification requestmod = new LDAPModification( LDAPModification.REPLACE, attrRequestNextRange ); + conn.modify( requestdn, requestmod ); + + conn.disconnect(); } catch (Exception e) { - } + CMS.debug("Unable to update global next range numbers: " + e); + } } } diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java index dbbe90d27..0cb7feba6 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java @@ -352,24 +352,15 @@ public class RestoreKeyCertPanel extends WizardPanelBase { String content = ""; if (cstype.equals("ca") || cstype.equals("kra")) { - String increment = config.getString("dbs.requestNumber.increment", ""); - String previncrement = config.getString("dbs.requestNumber.previncrement", ""); - if (!increment.equals(previncrement)) { - content = "type=request&xmlOutput=true&sessionID="+session_id+"&increment="+increment; - CMS.debug("http content=" + content); - updateNumberRange(master_hostname, master_port, true, content, "request", response); - config.putString("dbs.requestNumber.previncrement", increment); - config.commit(false); - } + content = "type=request&xmlOutput=true&sessionID="+session_id; + CMS.debug("http content=" + content); + updateNumberRange(master_hostname, master_port, true, content, "request", response); - previncrement = config.getString("dbs.serialNumber.previncrement", ""); - increment = config.getString("dbs.serialNumber.increment", ""); - if (!increment.equals(previncrement)) { - content = "type=serialNo&xmlOutput=true&sessionID="+session_id+"&increment="+increment; - updateNumberRange(master_hostname, master_port, true, content, "serialNo", response); - config.putString("dbs.serialNumber.previncrement", increment); - config.commit(false); - } + content = "type=serialNo&xmlOutput=true&sessionID="+session_id; + updateNumberRange(master_hostname, master_port, true, content, "serialNo", response); + + content = "type=replicaId&xmlOutput=true&sessionID="+session_id; + updateNumberRange(master_hostname, master_port, true, content, "replicaId", response); } String list = ""; diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java index 21cf773c8..2b9f7328b 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java @@ -199,10 +199,19 @@ public class UpdateDomainXML extends CMSServlet { HttpServletResponse httpResp = cmsReq.getHttpResp(); CMS.debug("UpdateDomainXML process: authentication starts"); - IAuthToken authToken = authenticate(cmsReq); + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } if (authToken == null) { CMS.debug("UpdateDomainXML process: authToken is null"); - outputError(httpResp, "Error: not authenticated"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + return; } CMS.debug("UpdateDomainXML process: authentication done"); @@ -214,18 +223,19 @@ public class UpdateDomainXML extends CMSServlet { } catch (EAuthzAccessDenied e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); - outputError(httpResp, "Error: Not authorized"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); return; } catch (Exception e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); outputError(httpResp, + AUTH_FAILURE, "Error: Encountered problem during authorization."); return; } if (authzToken == null) { CMS.debug("UpdateDomainXML process: authorization error"); - outputError(httpResp, "Error: Not authorized"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); return; } diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java index 9c2ed9123..01126e228 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java @@ -34,11 +34,14 @@ import com.netscape.certsrv.policy.*; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.dbs.*; import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.repository.*; import com.netscape.certsrv.ldap.*; import com.netscape.certsrv.logging.*; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authentication.*; import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.kra.*; import com.netscape.cms.servlet.*; import com.netscape.cmsutil.xml.*; import org.w3c.dom.*; @@ -115,48 +118,98 @@ public class UpdateNumberRange extends CMSServlet { try { String type = httpReq.getParameter("type"); - String incrementStr = httpReq.getParameter("increment"); - BigInteger increment = new BigInteger(incrementStr); IConfigStore cs = CMS.getConfigStore(); + String cstype = cs.getString("cs.type", ""); BigInteger beginNum = null; BigInteger endNum = null; BigInteger oneNum = new BigInteger("1"); - BigInteger nextNum = null; - if (type.equals("request")) { - String beginNumStr = cs.getString("dbs.nextBeginRequestNumber"); - beginNum = new BigInteger(beginNumStr); - if( beginNum == null ) { - CMS.debug( "UpdateNumberRange::process() - " + - "request beginNum is null!" ); - return; + String endNumConfig = null; + String cloneNumConfig = null; + String nextEndConfig = null; + int radix = 10; + + IRepository repo = null; + if (cstype.equals("KRA")) { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem( + IKeyRecoveryAuthority.ID); + if (type.equals("request")) { + repo = kra.getRequestQueue().getRequestRepository(); + } else if (type.equals("serialNo")) { + repo = kra.getKeyRepository(); + } else if (type.equals("replicaId")) { + repo = kra.getReplicaRepository(); } - endNum = beginNum.add(increment); - if( endNum == null ) { - CMS.debug( "UpdateNumberRange::process() - " + - "request endNum is null!" ); - return; + } else { // CA + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + if (type.equals("request")) { + repo = ca.getRequestQueue().getRequestRepository(); + } else if (type.equals("serialNo")) { + repo = ca.getCertificateRepository(); + } else if (type.equals("replicaId")) { + repo = ca.getReplicaRepository(); } - nextNum = endNum.add(oneNum); - cs.putString("dbs.nextBeginRequestNumber", nextNum.toString()); + } + + if (type.equals("request")) { + radix = 10; + endNumConfig = "dbs.endRequestNumber"; + cloneNumConfig = "dbs.requestCloneTransferNumber"; + nextEndConfig = "dbs.nextEndRequestNumber"; } else if (type.equals("serialNo")) { - String beginNumStr = cs.getString("dbs.nextBeginSerialNumber"); - beginNum = new BigInteger(beginNumStr); - if( beginNum == null ) { - CMS.debug( "UpdateNumberRange::process() - " + - "serialNo beginNum is null!" ); - return; - } - endNum = beginNum.add(increment); - if( endNum == null ) { - CMS.debug( "UpdateNumberRange::process() - " + - "serialNo endNum is null!" ); + radix=16; + endNumConfig = "dbs.endSerialNumber"; + cloneNumConfig = "dbs.serialCloneTransferNumber"; + nextEndConfig = "dbs.nextEndSerialNumber"; + } else if (type.equals("replicaId")) { + radix=10; + endNumConfig = "dbs.endReplicaNumber"; + cloneNumConfig = "dbs.replicaCloneTransferNumber"; + nextEndConfig = "dbs.nextEndReplicaNumber"; + } + + String endNumStr = cs.getString(endNumConfig, ""); + endNum = new BigInteger(endNumStr, radix); + if ( endNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "request endNum is null!" ); + return; + } + + String decrementStr = cs.getString(cloneNumConfig, ""); + BigInteger decrement = new BigInteger(decrementStr, radix); + if (decrement == null) { + CMS.debug("UpdateNumberRange::process() - " + + "request decrement string is null!" ); + return; + } + + beginNum = endNum.subtract(decrement).add(oneNum); + + if (beginNum.compareTo(repo.getTheSerialNumber()) < 0) { + String nextEndNumStr = cs.getString(nextEndConfig, ""); + BigInteger endNum2 = new BigInteger(nextEndNumStr, radix); + if (endNum2 == null) { + CMS.debug("UpdateNumberRange::process() - " + + "Unused requests less than cloneTransferNumber!" ); return; + } else { + CMS.debug("Transferring from the end of on-deck range"); + String newValStr = endNum2.subtract(decrement).toString(radix); + repo.setNextMaxSerial(newValStr); + cs.putString(nextEndConfig, newValStr); + beginNum = endNum2.subtract(decrement).add(oneNum); + endNum = endNum2; } - nextNum = endNum.add(oneNum); - cs.putString("dbs.nextBeginSerialNumber", nextNum.toString()); + } else { + CMS.debug("Transferring from the end of the current range"); + String newValStr = beginNum.subtract(oneNum).toString(radix); + repo.setMaxSerial(newValStr); + cs.putString(endNumConfig, newValStr); } + if( beginNum == null ) { CMS.debug( "UpdateNumberRange::process() - " + "beginNum is null!" ); @@ -169,6 +222,13 @@ public class UpdateNumberRange extends CMSServlet { return; } + // checkRanges for replicaID - we do this each time a replica is created. + // Also enable serial number management in master for certs and requests + if (type.equals("replicaId")) { + repo.checkRanges(); + repo.setEnableSerialMgmt(true); + } + // insert info CMS.debug("UpdateNumberRange: Sending response"); @@ -177,8 +237,8 @@ public class UpdateNumberRange extends CMSServlet { Node root = xmlObj.createRoot("XMLResponse"); xmlObj.addItemToContainer(root, "Status", SUCCESS); - xmlObj.addItemToContainer(root, "beginNumber", beginNum.toString()); - xmlObj.addItemToContainer(root, "endNumber", endNum.toString()); + xmlObj.addItemToContainer(root, "beginNumber", beginNum.toString(radix)); + xmlObj.addItemToContainer(root, "endNumber", endNum.toString(radix)); byte[] cb = xmlObj.toByteArray(); outputResult(httpResp, "application/xml", cb); diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java index c6c786f55..be00bd73c 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java @@ -726,7 +726,12 @@ public class WizardPanelBase implements IWizardPanel { } else if (type.equals("serialNo")) { cs.putString("dbs.beginSerialNumber", beginNum); cs.putString("dbs.endSerialNumber", endNum); + } else if (type.equals("replicaId")) { + cs.putString("dbs.beginReplicaNumber", beginNum); + cs.putString("dbs.endReplicaNumber", endNum); } + // enable serial number management in clone + cs.putString("dbs.enableSerialManagement", "true"); cs.commit(false); } else if (status.equals(AUTH_FAILURE)) { reloginSecurityDomain(response); diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java index 4d84b1fdf..43a520bd5 100644 --- a/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java +++ b/pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java @@ -213,7 +213,7 @@ public class CertificateRepository extends Repository public CertStatusUpdateThread mCertStatusUpdateThread = null; public RetrieveModificationsThread mRetrieveModificationsThread = null; - public void setCertStatusUpdateInterval(int interval, boolean listenToCloneModifications) { + public void setCertStatusUpdateInterval(IRepository requestRepo, int interval, boolean listenToCloneModifications) { CMS.debug("In setCertStatusUpdateInterval " + interval); if (interval == 0) { CMS.debug("In setCertStatusUpdateInterval interval = 0" + interval); @@ -246,7 +246,7 @@ public class CertificateRepository extends Repository CMS.debug("In setCertStatusUpdateInterval mCertStatusUpdateThread " + mCertStatusUpdateThread); if (mCertStatusUpdateThread == null) { CMS.debug("In setCertStatusUpdateInterval about to create CertStatusUpdateThread "); - mCertStatusUpdateThread = new CertStatusUpdateThread(this, "CertStatusUpdateThread"); + mCertStatusUpdateThread = new CertStatusUpdateThread(this, requestRepo, "CertStatusUpdateThread"); mCertStatusUpdateThread.setInterval(interval); mCertStatusUpdateThread.start(); } else { @@ -1893,14 +1893,16 @@ public class CertificateRepository extends Repository class CertStatusUpdateThread extends Thread { CertificateRepository _cr = null; + IRepository _rr = null; int _interval; - CertStatusUpdateThread(CertificateRepository cr, String name) { + CertStatusUpdateThread(CertificateRepository cr, IRepository rr, String name) { super(name); CMS.debug("new CertStatusUpdateThread"); //setName(name); _cr = cr; + _rr = rr; } public void setInterval(int interval) { @@ -1919,10 +1921,18 @@ class CertStatusUpdateThread extends Thread { 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"); + CMS.debug("updateCertStatus done: " + e.toString()); } try { sleep(_interval * 1000); diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java index 30c708446..3038e0026 100644 --- a/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java +++ b/pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java @@ -59,12 +59,12 @@ public class DBSubsystem implements IDBSubsystem { private DBRegistry mRegistry = null; private String mBaseDN = null; private ISubsystem mOwner = null; + + private Hashtable[] mRepos = null; + private BigInteger mNextSerialConfig = null; - private String mMaxSerialConfig = null; - private String mMinSerialConfig = null; + private boolean mEnableSerialMgmt = false; - private String mMinRequestConfig=null; - private String mMaxRequestConfig=null; private static final String PEOPLE_DN = "ou=people"; private static final String GROUPS_DN = "ou=groups"; private static final String REQUESTS_DN = "ou=requests"; @@ -81,6 +81,7 @@ public class DBSubsystem implements IDBSubsystem { 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 @@ -90,17 +91,58 @@ public class DBSubsystem implements IDBSubsystem { 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_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 @@ -152,6 +194,24 @@ public class DBSubsystem implements IDBSubsystem { } } + 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; } @@ -165,31 +225,297 @@ public class DBSubsystem implements IDBSubsystem { serial.toString(16)); } - public String getMinSerialConfig() + /** + * Gets minimum serial number limit in config file + * + * @param repo repo identifier + * @return min serial number + */ + public String getMinSerialConfig(int repo) { - return mMinSerialConfig; + return (String) (mRepos[repo]).get(PROP_MIN); } - public String getMaxSerialConfig() { - return mMaxSerialConfig; + + /** + * 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); } - public String getMinRequestConfig() + /** + * 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) { - return mMinRequestConfig; + 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); } - public String getMaxRequestConfig() + /** + * Gets range increment for next range in config file + * + * @param repo repo identifier + * @return range increment + */ + public String getIncrementConfig(int repo) { - return mMaxRequestConfig; + return (String) (mRepos[repo]).get(PROP_INCREMENT); } - public void setMaxSerialConfig(String serial) + /** + * 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 { - mLogger.log(ILogger.EV_SYSTEM, ILogger.S_DB, - ILogger.LL_INFO, "DBSubsystem: " + - "Setting max serial number: 0x" + serial); - mDBConfig.putString(PROP_MAX_SERIAL_NUMBER, - serial); + 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() { @@ -205,8 +531,10 @@ public class DBSubsystem implements IDBSubsystem { 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; @@ -214,46 +542,109 @@ public class DBSubsystem implements IDBSubsystem { mBaseDN = mConfig.getString(PROP_BASEDN, "o=NetscapeCertificateServer"); mOwner = owner; + mNextSerialConfig = new BigInteger(mDBConfig.getString( - PROP_NEXT_SERIAL_NUMBER, "0"), 16); + PROP_NEXT_SERIAL_NUMBER, "0"), 16); - mMinSerialConfig = mDBConfig.getString( - PROP_MIN_SERIAL_NUMBER,null); + mEnableSerialMgmt = mDBConfig.getBoolean(PROP_ENABLE_SERIAL_MGMT, false); - if(mMinSerialConfig == null) - { - mMinSerialConfig = "0"; - } + // 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")); - mMaxSerialConfig = mDBConfig.getString( - PROP_MAX_SERIAL_NUMBER,null ); + certs.put(PROP_MAX_NAME, PROP_MAX_SERIAL_NUMBER); + certs.put(PROP_MAX, mDBConfig.getString( + PROP_MAX_SERIAL_NUMBER, PROP_INFINITE_SERIAL_NUMBER)); - if(mMaxSerialConfig == null) - { - mMaxSerialConfig = 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")); - CMS.debug("DBSubsystem: mMinSerialConfig: " + mMinSerialConfig + " mMaxSerialConfig: " + mMaxSerialConfig); + certs.put(PROP_NEXT_MAX_NAME, PROP_NEXT_MAX_SERIAL_NUMBER); + certs.put(PROP_NEXT_MAX, mDBConfig.getString( + PROP_NEXT_MAX_SERIAL_NUMBER, "-1")); - mMinRequestConfig = mDBConfig.getString(PROP_MIN_REQUEST_NUMBER,null); + 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")); - if(mMinRequestConfig == null) - { - CMS.debug("DBSubsystem: missing mMinSerialConfig value!"); - mMinRequestConfig = "0"; - } + certs.put(PROP_INCREMENT_NAME, PROP_SERIAL_INCREMENT); + certs.put(PROP_INCREMENT, mDBConfig.getString( + PROP_SERIAL_INCREMENT, PROP_INFINITE_SERIAL_NUMBER)); - mMaxRequestConfig = mDBConfig.getString(PROP_MAX_REQUEST_NUMBER,null); + mRepos[CERTS]=certs; - if(mMaxRequestConfig == null) - { - CMS.debug("DBSubsystem: missing mMaxSerialConfig value!"); - mMaxRequestConfig = PROP_INFINITE_REQUEST_NUMBER; + // 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; - } - CMS.debug("DBSubsystem: mMinRequestConfig: " + mMinRequestConfig + " mMaxRequestConfig: " + mMaxRequestConfig); // initialize registry mRegistry = new DBRegistry(); mRegistry.init(this, null); diff --git a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java index 099c5bdcd..a631a17a9 100644 --- a/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java +++ b/pki/base/common/src/com/netscape/cmscore/dbs/KeyRepository.java @@ -44,6 +44,7 @@ import com.netscape.cmscore.dbs.*; */ public class KeyRepository extends Repository implements IKeyRepository { + public KeyStatusUpdateThread mKeyStatusUpdateThread = null; protected IDBSubsystem mDBService = null; /** @@ -126,6 +127,30 @@ public class KeyRepository extends Repository implements IKeyRepository { } } + 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; } @@ -472,6 +497,57 @@ CMS.debug("filter= " + filter); 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/ReplicaIDRepository.java b/pki/base/common/src/com/netscape/cmscore/dbs/ReplicaIDRepository.java new file mode 100644 index 000000000..026e54a6a --- /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. + * <P> + * + * @author alee + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 index db7cc707d..86c08b40e 100644 --- a/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java +++ b/pki/base/common/src/com/netscape/cmscore/dbs/Repository.java @@ -29,6 +29,8 @@ 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. @@ -48,6 +50,7 @@ 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 @@ -55,13 +58,22 @@ public abstract class Repository implements IRepository { 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; @@ -121,7 +133,7 @@ public abstract class Repository implements IRepository { * * @return next serial number */ - private BigInteger getSerialNumber() throws EBaseException { + protected BigInteger getSerialNumber() throws EBaseException { IDBSSession s = mDB.createSession(); CMS.debug("Repository: getSerialNumber."); @@ -166,7 +178,7 @@ public abstract class Repository implements IRepository { * * @param num serial number */ - private void setSerialNumber(BigInteger num) throws EBaseException { + protected void setSerialNumber(BigInteger num) throws EBaseException { IDBSSession s = mDB.createSession(); CMS.debug("Repository:setSerialNumber " + num.toString()); @@ -175,17 +187,69 @@ public abstract class Repository implements IRepository { } + /** + * 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 @@ -193,47 +257,55 @@ public abstract class Repository implements IRepository { private void initCache() throws EBaseException { mNext = getSerialNumber(); BigInteger serialConfig = new BigInteger("0"); - - int radix = 10; - + mRadix = 10; + CMS.debug("Repository: in InitCache"); - String minSerial = mDB.getMinSerialConfig(); - String maxSerial = mDB.getMaxSerialConfig(); - String minRequest = mDB.getMinRequestConfig(); - String maxRequest = mDB.getMaxRequestConfig(); - - CMS.debug("Repository: minSerial " + minSerial + " maxSerial: " + maxSerial + " minRequest " + minRequest + " maxRequest " + maxRequest); if (this instanceof ICertificateRepository) { - - mMaxSerial = maxSerial; - mMinSerial = minSerial; - radix = 16; CMS.debug("Repository: Instance of Certificate Repository."); - } else { + 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; + } - if(this instanceof IKeyRepository) { + 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); - mMaxSerial = maxSerial; - mMinSerial = minSerial; - radix = 16; - CMS.debug("Repository: Instance of Key Repository."); + CMS.debug("Repository: minSerial " + mMinSerial + " maxSerial: " + mMaxSerial); - } else { // request repository + if(mMinSerial != null) + mMinSerialNo = new BigInteger(mMinSerial,mRadix); - mMaxSerial = maxRequest; - mMinSerial = minRequest; - radix = 10; - CMS.debug("Repository: Instance of Request Repository."); + if(mMaxSerial != null) + mMaxSerialNo = new BigInteger(mMaxSerial,mRadix); - } - } + if(mNextMinSerial != null) + mNextMinSerialNo = new BigInteger(mNextMinSerial,mRadix); - if(mMinSerial != null) - mMinSerialNo = new BigInteger(mMinSerial,radix); + if(mNextMaxSerial != null) + mNextMaxSerialNo = new BigInteger(mNextMaxSerial,mRadix); - if(mMaxSerial != null) - mMaxSerialNo = new BigInteger(mMaxSerial,radix); + if(lowWaterMark != null) + mLowWaterMarkNo = new BigInteger(lowWaterMark,mRadix); + + if(increment != null) + mIncrementNo = new BigInteger(increment,mRadix); BigInteger theSerialNo = null; theSerialNo = getLastSerialNumberInRange(mMinSerialNo,mMaxSerialNo); @@ -278,7 +350,6 @@ public abstract class Repository implements IRepository { // mSerialNo is already set. But just in case CMS.debug("Repository:In setTheSerialNumber " + num.toString()); - if (mLastSerialNo == null) initCache(); @@ -306,6 +377,7 @@ public abstract class Repository implements IRepository { EBaseException { CMS.debug("Repository: in getNextSerialNumber. "); + if (mLastSerialNo == null) { initCache(); @@ -320,10 +392,32 @@ public abstract class Repository implements IRepository { CMS.debug( "Repository::getNextSerialNumber() " + "- mLastSerialNo is null!" ); throw new EBaseException( "mLastSerialNo is null" ); - } else if( mLastSerialNo.compareTo( mMaxSerialNo ) > 0 ) { - mLastSerialNo = mLastSerialNo.subtract(BI_ONE); - throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED", - mLastSerialNo.toString())); + } + + // 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()); @@ -332,6 +426,80 @@ public abstract class Repository implements IRepository { 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/request/RequestQueue.java b/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java index 60c476d3e..ff9ceb4f6 100644 --- a/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java +++ b/pki/base/common/src/com/netscape/cmscore/request/RequestQueue.java @@ -44,6 +44,7 @@ import com.netscape.certsrv.request.IService; import com.netscape.certsrv.request.IRequestList; import com.netscape.certsrv.request.IRequestVirtualList; import com.netscape.cmscore.request.ARequestQueue; +import com.netscape.certsrv.dbs.repository.IRepository; import com.netscape.cmscore.util.Debug; @@ -594,6 +595,13 @@ public class RequestQueue } } + /* + * return request repository + */ + public IRepository getRequestRepository() { + return (IRepository) mRepository; + } + protected String mBaseDN; protected IDBSubsystem mDB; protected RequestRepository mRepository; |