summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Wnuk <awnuk@redhat.com>2013-04-19 22:52:18 -0400
committerAndrew Wnuk <awnuk@redhat.com>2013-04-19 22:54:49 -0400
commit3f2611881453a5ec995560cad4a073d8f073ea97 (patch)
tree0f27b11041b7c689cffb3cf0f261e444768d0037
parent01505048c904d154fe29f5f715f87dec8500e188 (diff)
downloadpki-3f2611881453a5ec995560cad4a073d8f073ea97.tar.gz
pki-3f2611881453a5ec995560cad4a073d8f073ea97.tar.xz
pki-3f2611881453a5ec995560cad4a073d8f073ea97.zip
random certificate serial numbers
This patch adds support for random certificate serial numbers. Bug 912554.
-rw-r--r--base/ca/shared/conf/CS.cfg.in4
-rw-r--r--base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java8
-rw-r--r--base/common/src/com/netscape/certsrv/common/Constants.java2
-rw-r--r--base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java27
-rw-r--r--base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java28
-rw-r--r--base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java3
-rw-r--r--base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java8
-rw-r--r--base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java409
-rw-r--r--base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java61
-rw-r--r--base/common/src/com/netscape/cmscore/dbs/Repository.java104
-rw-r--r--base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java10
-rw-r--r--base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java1
-rw-r--r--base/common/test/com/netscape/cmscore/dbs/DBSubsystemDefaultStub.java13
-rw-r--r--base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java109
-rw-r--r--base/server/config/pkislots.cfg1
-rw-r--r--base/server/etc/default.cfg1
-rw-r--r--base/server/src/engine/pkiparser.py4
-rw-r--r--dogtag/console-ui/src/CMSAdminRS.properties6
18 files changed, 739 insertions, 60 deletions
diff --git a/base/ca/shared/conf/CS.cfg.in b/base/ca/shared/conf/CS.cfg.in
index a1acde2df..1316e9b23 100644
--- a/base/ca/shared/conf/CS.cfg.in
+++ b/base/ca/shared/conf/CS.cfg.in
@@ -769,7 +769,9 @@ cmsgateway._029=##
cmsgateway.enableAdminEnroll=false
https.port=8443
http.port=8080
-dbs.enableSerialManagement=false
+dbs.enableSerialManagement=[PKI_ENABLE_RANDOM_SERIAL_NUMBERS]
+dbs.enableRandomSerialNumbers=[PKI_ENABLE_RANDOM_SERIAL_NUMBERS]
+dbs.randomSerialNumberCounter=0
dbs.beginRequestNumber=1
dbs.endRequestNumber=10000000
dbs.requestIncrement=10000000
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index 21859a0f2..39f336b5f 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -34,6 +34,7 @@ import org.mozilla.jss.crypto.SignatureAlgorithm;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.IDBSubsystem;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
import com.netscape.certsrv.dbs.crldb.ICRLRepository;
import com.netscape.certsrv.dbs.replicadb.IReplicaIDRepository;
@@ -473,6 +474,13 @@ public interface ICertificateAuthority extends ISubsystem {
public IService getCAService();
/**
+ * Retrieves the DB subsystem managing internal data storage.
+ *
+ * @return DB subsystem object
+ */
+ public IDBSubsystem getDBSubsystem();
+
+ /**
* Returns the in-memory count of the processed OCSP requests.
*
* @return number of processed OCSP requests in memory
diff --git a/base/common/src/com/netscape/certsrv/common/Constants.java b/base/common/src/com/netscape/certsrv/common/Constants.java
index 880e14643..bc8dcefad 100644
--- a/base/common/src/com/netscape/certsrv/common/Constants.java
+++ b/base/common/src/com/netscape/certsrv/common/Constants.java
@@ -346,6 +346,8 @@ public interface Constants {
public final static String PR_ALL_ALGORITHMS = "allSigningAlgorithms";
public final static String PR_SERIAL = "startSerialNumber";
public final static String PR_MAXSERIAL = "maxSerialNumber";
+ public final static String PR_SN_MANAGEMENT = "serialNumberManagement";
+ public final static String PR_RANDOM_SN = "randomSerialNumbers";
/*========================================================
* Access Control
diff --git a/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java b/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java
index dfa5312e5..de4060e34 100644
--- a/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java
+++ b/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java
@@ -23,6 +23,7 @@ import netscape.ldap.LDAPConnection;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.base.IConfigStore;
/**
* An interface represents certificate server
@@ -204,6 +205,32 @@ public interface IDBSubsystem extends ISubsystem {
public void setEnableSerialMgmt(boolean value) throws EBaseException;
/**
+ * Gets internal DB configuration store
+ *
+ * @return internal DB configuration store
+ */
+ public IConfigStore getConfigStore();
+
+ /**
+ * Gets DB subsystem configuration store
+ *
+ * @return DB subsystem configuration store
+ */
+ public IConfigStore getDBConfigStore();
+
+ /**
+ * Gets attribute value for specified entry
+ *
+ * @param dn entry's distinguished name
+ * @param attrName attribute's name
+ * @param defaultValue attribute's default value
+ * @param errorValue attribute's error value
+ * @return attribute value
+ */
+ public String getEntryAttribute(String dn, String attrName,
+ String defaultValue, String errorValue);
+
+ /**
* Returns LDAP connection to connection pool.
*
* @param conn connection to be returned
diff --git a/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java b/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java
index d54cfb353..40d22d614 100644
--- a/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java
+++ b/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java
@@ -42,6 +42,16 @@ import com.netscape.cmscore.dbs.CertificateRepository.RenewableCertificateCollec
public interface ICertificateRepository extends IRepository {
/**
+ * Retrieves the next certificate serial number, and also increases
+ * the serial number by one.
+ *
+ * @return serial number
+ * @exception EBaseException failed to retrieve next serial number
+ */
+ public BigInteger getNextSerialNumber()
+ throws EBaseException;
+
+ /**
* Adds a certificate record to the repository. Each certificate
* record contains four parts: certificate, meta-attributes,
* issue information and reovcation information.
@@ -512,5 +522,23 @@ public interface ICertificateRepository extends IRepository {
*/
public void removeCertRecords(BigInteger beginS, BigInteger endS) throws EBaseException;
+ /**
+ * Retrieves serial number management mode.
+ *
+ * @return serial number management mode,
+ * "true" indicates random serial number management,
+ * "false" indicates sequential serial number management.
+ */
+ public boolean getEnableRandomSerialNumbers();
+
+ /**
+ * Sets serial number management mode for certificates..
+ *
+ * @param random "true" sets random serial number management, "false" sequential
+ * @param updateMode "true" updates "description" attribute in certificate repository
+ * @param forceModeChange "true" forces certificate repository mode change
+ */
+ public void setEnableRandomSerialNumbers(boolean random, boolean updateMode, boolean forceModeChange);
+
public void shutdown();
}
diff --git a/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java b/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java
index 12dc71c46..dd5f557ec 100644
--- a/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java
+++ b/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java
@@ -32,6 +32,7 @@ public interface IRepositoryRecord extends IDBObj {
public final static String ATTR_SERIALNO = "serialNo";
public final static String ATTR_PUB_STATUS = "publishingStatus";
+ public final static String ATTR_DESCRIPTION = "description";
/**
* Retrieves serial number.
@@ -41,4 +42,6 @@ public interface IRepositoryRecord extends IDBObj {
public BigInteger getSerialNumber();
public String getPublishingStatus();
+
+ public String getDescription();
}
diff --git a/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java
index 9e06f04bd..09c77e557 100644
--- a/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java
+++ b/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java
@@ -1480,6 +1480,10 @@ public class CAAdminServlet extends AdminServlet {
getSigningAlgConfig(params);
getSerialConfig(params);
getMaxSerialConfig(params);
+ params.put(Constants.PR_SN_MANAGEMENT,
+ Boolean.toString(mCA.getDBSubsystem().getEnableSerialMgmt()));
+ params.put(Constants.PR_RANDOM_SN,
+ Boolean.toString(mCA.getCertificateRepository().getEnableRandomSerialNumbers()));
sendResponse(SUCCESS, null, params, resp);
}
@@ -1549,6 +1553,10 @@ public class CAAdminServlet extends AdminServlet {
mCA.setStartSerial(value);
} else if (key.equals(Constants.PR_MAXSERIAL)) {
mCA.setMaxSerial(value);
+ } else if (key.equals(Constants.PR_SN_MANAGEMENT)) {
+ mCA.getDBSubsystem().setEnableSerialMgmt(Boolean.valueOf(value));
+ } else if (key.equals(Constants.PR_RANDOM_SN)) {
+ mCA.getCertificateRepository().setEnableRandomSerialNumbers(Boolean.valueOf(value), true, false);
}
}
diff --git a/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java
index c2ecb8710..b95335149 100644
--- a/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java
+++ b/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java
@@ -25,6 +25,7 @@ import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
+import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
@@ -43,8 +44,10 @@ import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.MetaInfo;
import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.ca.ICRLIssuingPoint;
import com.netscape.certsrv.dbs.EDBException;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
import com.netscape.certsrv.dbs.IDBSSession;
import com.netscape.certsrv.dbs.IDBSearchResults;
import com.netscape.certsrv.dbs.IDBSubsystem;
@@ -56,6 +59,7 @@ import com.netscape.certsrv.dbs.certdb.ICertRecordList;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
import com.netscape.certsrv.dbs.certdb.IRevocationInfo;
import com.netscape.certsrv.dbs.repository.IRepository;
+import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
import com.netscape.certsrv.logging.ILogger;
/**
@@ -71,6 +75,15 @@ public class CertificateRepository extends Repository
implements ICertificateRepository {
public final String CERT_X509ATTRIBUTE = "x509signedcert";
+ private static final String PROP_ENABLE_RANDOM_SERIAL_NUMBERS = "enableRandomSerialNumbers";
+ private static final String PROP_RANDOM_SERIAL_NUMBER_COUNTER = "randomSerialNumberCounter";
+ private static final String PROP_FORCE_MODE_CHANGE = "forceModeChange";
+ private static final String PROP_RANDOM_MODE = "random";
+ private static final String PROP_SEQUENTIAL_MODE = "sequential";
+ private static final String PROP_COLLISION_RECOVERY_STEPS = "collisionRecoverySteps";
+ private static final String PROP_COLLISION_RECOVERY_REGENERATIONS = "collisionRecoveryRegenerations";
+ private static final String PROP_MINIMUM_RANDOM_BITS = "minimumRandomBits";
+ private static final BigInteger BI_MINUS_ONE = (BigInteger.ZERO).subtract(BigInteger.ONE);
private IDBSubsystem mDBService;
private String mBaseDN;
@@ -85,6 +98,15 @@ public class CertificateRepository extends Repository
private int mTransitMaxRecords = 1000000;
private int mTransitRecordPageSize = 200;
+ private Random mRandom = null;
+ private int mBitLength = 0;
+ private BigInteger mRangeSize = null;
+ private int mMinRandomBitLength = 4;
+ private int mMaxCollisionRecoverySteps = 10;
+ private int mMaxCollisionRecoveryRegenerations = 3;
+ private IConfigStore mDBConfig = null;
+ private boolean mForceModeChange = false;
+
public CertStatusUpdateTask certStatusUpdateTask;
public RetrieveModificationsTask retrieveModificationsTask;
@@ -96,12 +118,302 @@ public class CertificateRepository extends Repository
super(dbService, increment, baseDN);
mBaseDN = certRepoBaseDN;
mDBService = dbService;
+ mDBConfig = mDBService.getDBConfigStore();
}
public ICertRecord createCertRecord(BigInteger id, Certificate cert, MetaInfo meta) {
return new CertRecord(id, cert, meta);
}
+ public boolean getEnableRandomSerialNumbers() {
+ return mEnableRandomSerialNumbers;
+ }
+
+ public void setEnableRandomSerialNumbers(boolean random, boolean updateMode, boolean forceModeChange) {
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers random="+random+" updateMode="+updateMode);
+ if (mEnableRandomSerialNumbers ^ random || forceModeChange) {
+ mEnableRandomSerialNumbers = random;
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers switching to " +
+ ((random)?PROP_RANDOM_MODE:PROP_SEQUENTIAL_MODE) + " mode");
+ if (updateMode) {
+ setCertificateRepositoryMode((mEnableRandomSerialNumbers)? PROP_RANDOM_MODE: PROP_SEQUENTIAL_MODE);
+ }
+ mDBConfig.putBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, mEnableRandomSerialNumbers);
+
+ BigInteger lastSerialNumber = null;
+ try {
+ lastSerialNumber = getLastSerialNumberInRange(mMinSerialNo,mMaxSerialNo);
+ } catch (Exception e) {
+ }
+ if (lastSerialNumber != null) {
+ super.setLastSerialNo(lastSerialNumber);
+ if (mEnableRandomSerialNumbers) {
+ mCounter = lastSerialNumber.subtract(mMinSerialNo).add(BigInteger.ONE);
+ CMS.debug("CertificateRepository: setEnableRandomSerialNumbers mCounter="+
+ mCounter+"="+lastSerialNumber+"-"+mMinSerialNo+"+1");
+ long t = System.currentTimeMillis();
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString()+","+t);
+ } else {
+ mCounter = BI_MINUS_ONE;
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString());
+ }
+ }
+
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ private BigInteger getRandomNumber() throws EBaseException {
+ BigInteger randomNumber = null;
+
+ if (mRandom == null) {
+ mRandom = new Random();
+ }
+ super.initCacheIfNeeded();
+
+ if (mRangeSize == null) {
+ mRangeSize = (mMaxSerialNo.subtract(mMinSerialNo)).add(BigInteger.ONE);
+ CMS.debug("CertificateRepository: getRandomNumber mRangeSize="+mRangeSize);
+ mBitLength = mRangeSize.bitLength();
+ CMS.debug("CertificateRepository: getRandomNumber mBitLength="+mBitLength+
+ " >mMinRandomBitLength="+mMinRandomBitLength);
+ }
+ if (mBitLength < mMinRandomBitLength) {
+ CMS.debug("CertificateRepository: getRandomNumber mBitLength="+mBitLength+
+ " <mMinRandomBitLength="+mMinRandomBitLength);
+ CMS.debug("CertificateRepository: getRandomNumber: Range size is too small to support random certificate serial numbers.");
+ throw new EBaseException ("Range size is too small to support random certificate serial numbers.");
+ }
+ randomNumber = new BigInteger((mBitLength), mRandom);
+ randomNumber = (randomNumber.multiply(mRangeSize)).shiftRight(mBitLength);
+ CMS.debug("CertificateRepository: getRandomNumber randomNumber="+randomNumber);
+
+ return randomNumber;
+ }
+
+ private BigInteger getRandomSerialNumber(BigInteger randomNumber) throws EBaseException {
+ BigInteger nextSerialNumber = null;
+
+ nextSerialNumber = randomNumber.add(mMinSerialNo);
+ CMS.debug("CertificateRepository: getRandomSerialNumber nextSerialNumber="+nextSerialNumber);
+
+ return nextSerialNumber;
+ }
+
+ private BigInteger checkSerialNumbers(BigInteger randomNumber, BigInteger serialNumber) throws EBaseException {
+ BigInteger nextSerialNumber = null;
+ BigInteger initialRandomNumber = randomNumber;
+ BigInteger delta = BigInteger.ZERO;
+ int i = 0;
+ int n = mMaxCollisionRecoverySteps;
+
+ do {
+ CMS.debug("CertificateRepository: checkSerialNumbers checking("+(i+1)+")="+serialNumber);
+ try {
+ if (readCertificateRecord(serialNumber) != null) {
+ CMS.debug("CertificateRepository: checkSerialNumbers collision detected for serialNumber="+serialNumber);
+ }
+ } catch (EDBRecordNotFoundException nfe) {
+ CMS.debug("CertificateRepository: checkSerialNumbers serial number "+serialNumber+" is available");
+ nextSerialNumber = serialNumber;
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: checkSerialNumbers Exception="+e.getMessage());
+ }
+
+ if (nextSerialNumber == null) {
+ if (i%2 == 0) {
+ delta = delta.add(BigInteger.ONE);
+ serialNumber = getRandomSerialNumber(initialRandomNumber.add(delta));
+
+ if (mMaxSerialNo != null && serialNumber.compareTo(mMaxSerialNo) > 0) {
+ serialNumber = getRandomSerialNumber(initialRandomNumber.subtract(delta));
+ i++;
+ n++;
+ }
+ } else {
+ serialNumber = getRandomSerialNumber(initialRandomNumber.subtract(delta));
+ if (mMinSerialNo != null && serialNumber.compareTo(mMinSerialNo) < 0) {
+ delta = delta.add(BigInteger.ONE);
+ serialNumber = getRandomSerialNumber(initialRandomNumber.add(delta));
+ i++;
+ n++;
+ }
+ }
+ i++;
+ }
+ } while (nextSerialNumber == null && i < n);
+
+ return nextSerialNumber;
+ }
+
+ private Object nextSerialNumberMonitor = new Object();
+
+ public BigInteger getNextSerialNumber() throws
+ EBaseException {
+
+ BigInteger nextSerialNumber = null;
+ BigInteger randomNumber = null;
+
+ synchronized (nextSerialNumberMonitor) {
+ super.initCacheIfNeeded();
+ CMS.debug("CertificateRepository: getNextSerialNumber mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+
+ if (mEnableRandomSerialNumbers) {
+ int i = 0;
+ do {
+ if (i > 0) {
+ CMS.debug("CertificateRepository: getNextSerialNumber regenerating serial number");
+ }
+ randomNumber = getRandomNumber();
+ nextSerialNumber = getRandomSerialNumber(randomNumber);
+ nextSerialNumber = checkSerialNumbers(randomNumber, nextSerialNumber);
+ i++;
+ } while (nextSerialNumber == null && i < mMaxCollisionRecoveryRegenerations);
+
+ if (nextSerialNumber == null) {
+ CMS.debug("CertificateRepository: in getNextSerialNumber nextSerialNumber is null");
+ throw new EBaseException( "nextSerialNumber is null" );
+ }
+
+ if (mCounter.compareTo(BigInteger.ZERO) >= 0 &&
+ mMinSerialNo != null && mMaxSerialNo != null &&
+ nextSerialNumber != null &&
+ nextSerialNumber.compareTo(mMinSerialNo) >= 0 &&
+ nextSerialNumber.compareTo(mMaxSerialNo) <= 0) {
+ mCounter = mCounter.add(BigInteger.ONE);
+ }
+ CMS.debug("CertificateRepository: getNextSerialNumber nextSerialNumber="+
+ nextSerialNumber+" mCounter="+mCounter);
+
+ super.checkRange();
+ } else {
+ nextSerialNumber = super.getNextSerialNumber();
+ }
+ }
+
+ return nextSerialNumber;
+ }
+
+ private void updateCounter() {
+ CMS.debug("CertificateRepository: updateCounter mEnableRandomSerialNumbers="+
+ mEnableRandomSerialNumbers+" mCounter="+mCounter);
+ try {
+ super.initCacheIfNeeded();
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception from initCacheIfNeeded: "+e.getMessage());
+ }
+
+ String crMode = mDBService.getEntryAttribute(mBaseDN, IRepositoryRecord.ATTR_DESCRIPTION, "", null);
+
+ boolean modeChange = (mEnableRandomSerialNumbers && crMode != null && crMode.equals(PROP_SEQUENTIAL_MODE)) ||
+ ((!mEnableRandomSerialNumbers) && crMode != null && crMode.equals(PROP_RANDOM_MODE));
+ CMS.debug("CertificateRepository: updateCounter mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+ CMS.debug("CertificateRepository: updateCounter CertificateRepositoryMode ="+crMode);
+ CMS.debug("CertificateRepository: updateCounter modeChange="+modeChange);
+ if (modeChange) {
+ if (mForceModeChange) {
+ setEnableRandomSerialNumbers(mEnableRandomSerialNumbers, true, mForceModeChange);
+ } else {
+ setEnableRandomSerialNumbers(!mEnableRandomSerialNumbers, false, mForceModeChange);
+ }
+ } else if (mEnableRandomSerialNumbers && mCounter != null &&
+ mCounter.compareTo(BigInteger.ZERO) >= 0) {
+ long t = System.currentTimeMillis();
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString()+","+t);
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception committing ConfigStore="+e.getMessage());
+ }
+ }
+ CMS.debug("CertificateRepository: UpdateCounter mEnableRandomSerialNumbers="+
+ mEnableRandomSerialNumbers+" mCounter="+mCounter);
+ }
+
+ private BigInteger getInRangeCount(String fromTime, BigInteger minSerialNo, BigInteger maxSerialNo)
+ throws EBaseException {
+ BigInteger count = BigInteger.ZERO;
+ String filter = null;
+
+ if (fromTime != null && fromTime.length() > 0) {
+ filter = "(certCreateTime >= "+fromTime+")";
+ } else {
+ filter = "(&("+ICertRecord.ATTR_ID+">="+minSerialNo+")("+
+ ICertRecord.ATTR_ID+"<="+maxSerialNo+"))";
+ }
+ CMS.debug("CertificateRepository: getInRangeCount filter="+filter+
+ " minSerialNo="+minSerialNo+" maxSerialNo="+maxSerialNo);
+
+ Enumeration<Object> e = findCertRecs(filter, new String[] {ICertRecord.ATTR_ID, "objectclass"});
+ while (e != null && e.hasMoreElements()) {
+ ICertRecord rec = (ICertRecord) e.nextElement();
+ if (rec != null) {
+ BigInteger sn = rec.getSerialNumber();
+ if (fromTime == null || fromTime.length() == 0 ||
+ (minSerialNo != null && maxSerialNo != null &&
+ sn != null && sn.compareTo(minSerialNo) >= 0 &&
+ sn.compareTo(maxSerialNo) <= 0)) {
+ count = count.add(BigInteger.ONE);
+ }
+ }
+ }
+ CMS.debug("CertificateRepository: getInRangeCount count=" + count);
+
+ return count;
+ }
+
+ private BigInteger getInRangeCounter(BigInteger minSerialNo, BigInteger maxSerialNo)
+ throws EBaseException {
+ String c = null;
+ String t = null;
+ String s = (mDBConfig.getString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, "-1")).trim();
+ CMS.debug("CertificateRepository: getInRangeCounter: saved counter string="+s);
+ int i = s.indexOf(',');
+ int n = s.length();
+ if (i > -1) {
+ if (i > 0) {
+ c = s.substring(0, i);
+ if (i < n) {
+ t = s.substring(i+1);
+ }
+ } else {
+ c = "-1";
+ }
+ } else {
+ c = s;
+ }
+ CMS.debug("CertificateRepository: getInRangeCounter: c=" + c + ((t != null)?(" t="+t):"null"));
+
+ BigInteger counter = new BigInteger(c);
+ BigInteger count = BigInteger.ZERO;
+ if (CMS.isPreOpMode()) {
+ CMS.debug("CertificateRepository: getInRangeCounter: CMS.isPreOpMode");
+ counter = new BigInteger("-2");
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, "-2");
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: updateCounter Exception committing ConfigStore="+e.getMessage());
+ }
+ } else if (t != null) {
+ count = getInRangeCount(t, minSerialNo, maxSerialNo);
+ if (count.compareTo(BigInteger.ZERO) > 0) {
+ counter = counter.add(count);
+ }
+ } else if (s.equals("-2")) {
+ count = getInRangeCount(t, minSerialNo, maxSerialNo);
+ if (count.compareTo(BigInteger.ZERO) >= 0) {
+ counter = count;
+ }
+ }
+ CMS.debug("CertificateRepository: getInRangeCounter: counter=" + counter);
+
+ return counter;
+ }
+
public BigInteger getLastSerialNumberInRange(BigInteger serial_low_bound, BigInteger serial_upper_bound)
throws EBaseException {
@@ -114,7 +426,43 @@ public class CertificateRepository extends Repository
}
- String ldapfilter = "(" + "certstatus" + "=*" + ")";
+ mEnableRandomSerialNumbers = mDBConfig.getBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, false);
+ mForceModeChange = mDBConfig.getBoolean(PROP_FORCE_MODE_CHANGE, false);
+ String crMode = mDBService.getEntryAttribute(mBaseDN, IRepositoryRecord.ATTR_DESCRIPTION, "", null);
+ mMinRandomBitLength = mDBConfig.getInteger(PROP_MINIMUM_RANDOM_BITS, 4);
+ mMaxCollisionRecoverySteps = mDBConfig.getInteger(PROP_COLLISION_RECOVERY_STEPS, 10);
+ mMaxCollisionRecoveryRegenerations = mDBConfig.getInteger(PROP_COLLISION_RECOVERY_REGENERATIONS, 3);
+ boolean modeChange = (mEnableRandomSerialNumbers && crMode != null && crMode.equals(PROP_SEQUENTIAL_MODE)) ||
+ ((!mEnableRandomSerialNumbers) && crMode != null && crMode.equals(PROP_RANDOM_MODE));
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange"+
+ " mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers+
+ " mMinRandomBitLength="+mMinRandomBitLength+
+ " CollisionRecovery="+mMaxCollisionRecoveryRegenerations+","+mMaxCollisionRecoverySteps);
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange modeChange="+modeChange+
+ " mForceModeChange="+mForceModeChange+((crMode != null)?(" mode="+crMode):""));
+ if (modeChange) {
+ if (mForceModeChange) {
+ setCertificateRepositoryMode((mEnableRandomSerialNumbers)? PROP_RANDOM_MODE: PROP_SEQUENTIAL_MODE);
+ mForceModeChange = false;
+ mDBConfig.remove(PROP_FORCE_MODE_CHANGE);
+ } else {
+ mEnableRandomSerialNumbers = !mEnableRandomSerialNumbers;
+ mDBConfig.putBoolean(PROP_ENABLE_RANDOM_SERIAL_NUMBERS, mEnableRandomSerialNumbers);
+ }
+ }
+ if (mEnableRandomSerialNumbers && mCounter == null) {
+ mCounter = getInRangeCounter(serial_low_bound, serial_upper_bound);
+ } else {
+ mCounter = BI_MINUS_ONE;
+ }
+ mDBConfig.putString(PROP_RANDOM_SERIAL_NUMBER_COUNTER, mCounter.toString());
+ try {
+ CMS.getConfigStore().commit(false);
+ } catch (Exception e) {
+ }
+ CMS.debug("CertificateRepository: getLastSerialNumberInRange mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+
+ String ldapfilter = "("+ICertRecord.ATTR_CERT_STATUS+"=*"+")";
String[] attrs = null;
@@ -130,7 +478,7 @@ public class CertificateRepository extends Repository
BigInteger ret = new BigInteger(serial_low_bound.toString(10));
- ret = ret.add(new BigInteger("-1"));
+ ret = ret.subtract(BigInteger.ONE);
CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
return ret;
}
@@ -156,6 +504,10 @@ public class CertificateRepository extends Repository
if (((serial.compareTo(serial_low_bound) == 0) || (serial.compareTo(serial_low_bound) == 1)) &&
((serial.compareTo(serial_upper_bound) == 0) || (serial.compareTo(serial_upper_bound) == -1))) {
CMS.debug("getLastSerialNumberInRange returning: " + serial);
+ if (modeChange && mEnableRandomSerialNumbers) {
+ mCounter = serial.subtract(serial_low_bound).add(BigInteger.ONE);
+ CMS.debug("getLastSerialNumberInRange mCounter: " + mCounter);
+ }
return serial;
}
} else {
@@ -165,9 +517,13 @@ public class CertificateRepository extends Repository
BigInteger ret = new BigInteger(serial_low_bound.toString(10));
- ret = ret.add(new BigInteger("-1"));
+ ret = ret.subtract(BigInteger.ONE);
CMS.debug("CertificateRepository:getLastCertRecordSerialNo: returning " + ret);
+ if (modeChange && mEnableRandomSerialNumbers) {
+ mCounter = BigInteger.ZERO;
+ CMS.debug("getLastSerialNumberInRange mCounter: " + mCounter);
+ }
return ret;
}
@@ -275,6 +631,7 @@ public class CertificateRepository extends Repository
transitRevokedExpiredCertificates();
CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER,
CMS.getLogMessage("CMSCORE_DBS_FINISH_REVOKED_EXPIRED_SEARCH"));
+ updateCounter();
}
/**
@@ -646,6 +1003,50 @@ public class CertificateRepository extends Repository
return rec;
}
+ public boolean checkCertificateRecord(BigInteger serialNo)
+ throws EBaseException {
+ IDBSSession s = mDBService.createSession();
+ CertRecord rec = null;
+ boolean exists = true;
+
+ try {
+ String name = "cn" + "=" +
+ serialNo.toString() + "," + getDN();
+ String attrs[] = { "DN" };
+
+ rec = (CertRecord) s.read(name, attrs);
+ if (rec == null) exists = false;
+ } catch (EDBRecordNotFoundException e) {
+ exists = false;
+ } catch (Exception e) {
+ throw new EBaseException(e.getMessage());
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ return exists;
+ }
+
+ private void setCertificateRepositoryMode(String mode) {
+ IDBSSession s = null;
+
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode setting mode: "+mode);
+ try {
+ s = mDBService.createSession();
+ ModificationSet mods = new ModificationSet();
+ String name = getDN();
+ mods.add(IRepositoryRecord.ATTR_DESCRIPTION, Modification.MOD_REPLACE, mode);
+ s.modify(name, mods);
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode Exception: "+e.getMessage());
+ }
+ try {
+ if (s != null) s.close();
+ } catch (Exception e) {
+ CMS.debug("CertificateRepository: setCertificateRepositoryMode Exception: "+e.getMessage());
+ }
+ }
+
public synchronized void modifyCertificateRecord(BigInteger serialNo,
ModificationSet mods) throws EBaseException {
IDBSSession s = mDBService.createSession();
@@ -1195,7 +1596,7 @@ public class CertificateRepository extends Repository
String fromVal = "0";
try {
if (from != null) {
- Integer.parseInt(from);
+ new BigInteger(from);
fromVal = from;
}
} catch (Exception e1) {
diff --git a/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java b/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java
index 0824cc9a7..be674bfd5 100644
--- a/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java
+++ b/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java
@@ -138,8 +138,6 @@ public class DBSubsystem implements IDBSubsystem {
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
@@ -424,7 +422,7 @@ public class DBSubsystem implements IDBSubsystem {
conn.modify(dn, mods);
// Add new range object
- String endRange = nextRangeNo.add(incrementNo).subtract(BI_ONE).toString();
+ String endRange = nextRangeNo.add(incrementNo).subtract(BigInteger.ONE).toString();
LDAPAttributeSet attrs = new LDAPAttributeSet();
attrs.add(new LDAPAttribute("objectClass", "top"));
attrs.add(new LDAPAttribute("objectClass", "pkiRange"));
@@ -436,6 +434,8 @@ public class DBSubsystem implements IDBSubsystem {
String dn2 = "cn=" + nextRange + "," + rangeDN;
LDAPEntry rangeEntry = new LDAPEntry(dn2, attrs);
conn.add(rangeEntry);
+ CMS.debug("DBSubsystem: getNextRange Next range has been added: " +
+ nextRange + " - " + endRange);
} catch (Exception e) {
CMS.debug("DBSubsystem: getNextRange. Unable to provide next range :" + e);
e.printStackTrace();
@@ -531,6 +531,7 @@ public class DBSubsystem implements IDBSubsystem {
PROP_NEXT_SERIAL_NUMBER, "0"), 16);
mEnableSerialMgmt = mDBConfig.getBoolean(PROP_ENABLE_SERIAL_MGMT, false);
+ CMS.debug("DBSubsystem: init() mEnableSerialMgmt="+mEnableSerialMgmt);
// populate the certs hash entry
Hashtable<String, String> certs = new Hashtable<String, String>();
@@ -783,6 +784,10 @@ public class DBSubsystem implements IDBSubsystem {
reg.registerAttribute(IRepositoryRecord.ATTR_PUB_STATUS,
new StringMapper(RepositorySchema.LDAP_ATTR_PUB_STATUS));
}
+ if (!reg.isAttributeRegistered(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ reg.registerAttribute(IRepositoryRecord.ATTR_DESCRIPTION,
+ new StringMapper(RepositorySchema.LDAP_ATTR_DESCRIPTION));
+ }
} catch (EBaseException e) {
if (CMS.isPreOpMode())
@@ -791,6 +796,47 @@ public class DBSubsystem implements IDBSubsystem {
}
}
+ public String getEntryAttribute(String dn, String attrName,
+ String defaultValue, String errorValue) {
+ LDAPConnection conn = null;
+ String attrValue = null;
+ try {
+ conn = mLdapConnFactory.getConn();
+ String[] attrs = { attrName };
+ LDAPEntry entry = conn.read(dn, attrs);
+ if (entry != null) {
+ LDAPAttribute attr = entry.getAttribute(attrName);
+ if (attr != null) {
+ attrValue = (String) attr.getStringValues().nextElement();
+ } else {
+ attrValue = defaultValue;
+ }
+ } else {
+ attrValue = errorValue;
+ }
+ } catch (LDAPException e) {
+ CMS.debug("DBSubsystem: getEntryAttribute LDAPException code="+e.getLDAPResultCode());
+ if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) {
+ attrValue = defaultValue;
+ }
+ } catch (Exception e) {
+ CMS.debug("DBSubsystem: getEntryAttribute. Unable to retrieve '"+attrName+"': "+ e);
+ attrValue = errorValue;
+ } 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());
+ }
+ }
+ CMS.debug("DBSubsystem: getEntryAttribute: dn="+dn+" attr="+attrName+":"+attrValue+";");
+
+ return attrValue;
+ }
+
/**
* Starts up this service.
*/
@@ -798,13 +844,20 @@ public class DBSubsystem implements IDBSubsystem {
}
/**
- * Retrieves configuration store.
+ * Retrieves internal DB configuration store.
*/
public IConfigStore getConfigStore() {
return mConfig;
}
/**
+ * Retrieves DB subsystem configuration store.
+ */
+ public IConfigStore getDBConfigStore() {
+ return mDBConfig;
+ }
+
+ /**
* Retrieves base DN of backend database.
*/
public String getBaseDN() {
diff --git a/base/common/src/com/netscape/cmscore/dbs/Repository.java b/base/common/src/com/netscape/cmscore/dbs/Repository.java
index 57ac5004d..e6b6e831e 100644
--- a/base/common/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/common/src/com/netscape/cmscore/dbs/Repository.java
@@ -49,7 +49,6 @@ import com.netscape.certsrv.dbs.repository.IRepositoryRecord;
public abstract class Repository implements IRepository {
- private static final BigInteger BI_ONE = new BigInteger("1");
private BigInteger BI_INCREMENT = null;
// (the next serialNo to be issued) - 1
private BigInteger mSerialNo = null;
@@ -61,8 +60,10 @@ public abstract class Repository implements IRepository {
private String mNextMaxSerial = null;
private String mNextMinSerial = null;
- private BigInteger mMinSerialNo = null;
- private BigInteger mMaxSerialNo = null;
+ protected boolean mEnableRandomSerialNumbers = false;
+ protected BigInteger mCounter = null;
+ protected BigInteger mMinSerialNo = null;
+ protected BigInteger mMaxSerialNo = null;
private BigInteger mNextMinSerialNo = null;
private BigInteger mNextMaxSerialNo = null;
@@ -149,6 +150,7 @@ public abstract class Repository implements IRepository {
}
BigInteger serial = rec.getSerialNumber();
+ CMS.debug("Repository: getSerialNumber serial="+serial);
if (!mInit) {
// cms may crash after issue a cert but before update
@@ -158,7 +160,7 @@ public abstract class Repository implements IRepository {
serial + "," + mBaseDN);
if (obj != null) {
- serial = serial.add(BI_ONE);
+ serial = serial.add(BigInteger.ONE);
setSerialNumber(serial);
}
} catch (EBaseException e) {
@@ -246,6 +248,10 @@ public abstract class Repository implements IRepository {
return mMinSerial;
}
+ protected void setLastSerialNo(BigInteger lastSN) {
+ mLastSerialNo = lastSN;
+ }
+
/**
* init serial number cache
*/
@@ -281,7 +287,10 @@ public abstract class Repository implements IRepository {
String increment = mDB.getIncrementConfig(mRepo);
String lowWaterMark = mDB.getLowWaterMarkConfig(mRepo);
- CMS.debug("Repository: minSerial " + mMinSerial + " maxSerial: " + mMaxSerial);
+ CMS.debug("Repository: minSerial:" + mMinSerial + " maxSerial: " + mMaxSerial);
+ CMS.debug("Repository: nextMinSerial: " + ((mNextMinSerial == null)?"":mNextMinSerial) +
+ " nextMaxSerial: " + ((mNextMaxSerial == null)?"":mNextMaxSerial));
+ CMS.debug("Repository: increment:" + increment + " lowWaterMark: " + lowWaterMark);
if (mMinSerial != null)
mMinSerialNo = new BigInteger(mMinSerial, mRadix);
@@ -317,6 +326,11 @@ public abstract class Repository implements IRepository {
}
+ protected void initCacheIfNeeded() throws EBaseException {
+ if (mLastSerialNo == null)
+ initCache();
+ }
+
/**
* get the next serial number in cache
*/
@@ -325,7 +339,7 @@ public abstract class Repository implements IRepository {
CMS.debug("Repository:In getTheSerialNumber ");
if (mLastSerialNo == null)
initCache();
- BigInteger serial = new BigInteger((mLastSerialNo.add(BI_ONE)).toString());
+ BigInteger serial = mLastSerialNo.add(BigInteger.ONE);
if (mMaxSerialNo != null && serial.compareTo(mMaxSerialNo) > 0)
return null;
@@ -354,7 +368,7 @@ public abstract class Repository implements IRepository {
// < BI_INCREMENT and server restart right afterwards.
mDB.setNextSerialConfig(num);
- mSerialNo = num.subtract(BI_ONE);
+ mSerialNo = num.subtract(BigInteger.ONE);
mNext = num.add(BI_INCREMENT);
setSerialNumber(mNext);
}
@@ -373,36 +387,65 @@ public abstract class Repository implements IRepository {
if (mLastSerialNo == null) {
initCache();
-
- mLastSerialNo = mLastSerialNo.add(BI_ONE);
-
- } else {
- mLastSerialNo = mLastSerialNo.add(BI_ONE);
}
-
if (mLastSerialNo == null) {
CMS.debug("Repository::getNextSerialNumber() " +
"- mLastSerialNo is null!");
throw new EBaseException("mLastSerialNo is null");
}
+ mLastSerialNo = mLastSerialNo.add(BigInteger.ONE);
+
+ checkRange();
+
+ BigInteger retSerial = new BigInteger(mLastSerialNo.toString());
+
+ CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial);
+ return retSerial;
+ }
+
+ /**
+ * Checks to see if range needs to be switched.
+ *
+ * @exception EBaseException thrown when next range is not allocated
+ */
+ protected void checkRange() throws EBaseException
+ {
// check if we have reached the end of the range
// if so, move to next range
- if (mLastSerialNo.compareTo(mMaxSerialNo) > 0) {
+ BigInteger randomLimit = null;
+ BigInteger rangeLength = null;
+ if ((this instanceof ICertificateRepository) &&
+ mDB.getEnableSerialMgmt() && mEnableRandomSerialNumbers) {
+ rangeLength = mMaxSerialNo.subtract(mMinSerialNo).add(BigInteger.ONE);
+ randomLimit = rangeLength.subtract(mLowWaterMarkNo.shiftRight(1));
+ CMS.debug("Repository: checkRange rangeLength="+rangeLength);
+ CMS.debug("Repository: checkRange randomLimit="+randomLimit);
+ }
+ CMS.debug("Repository: checkRange mLastSerialNo="+mLastSerialNo);
+ if (mLastSerialNo.compareTo( mMaxSerialNo ) > 0 ||
+ ((!CMS.isPreOpMode()) && randomLimit != null && mCounter.compareTo(randomLimit) > 0)) {
+
if (mDB.getEnableSerialMgmt()) {
CMS.debug("Reached the end of the range. Attempting to move to next range");
+ if ((mNextMinSerialNo == null) || (mNextMaxSerialNo == null)) {
+ if (rangeLength != null && mCounter.compareTo(rangeLength) < 0) {
+ return;
+ } else {
+ throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
+ mLastSerialNo.toString()));
+ }
+ }
mMinSerialNo = mNextMinSerialNo;
mMaxSerialNo = mNextMaxSerialNo;
- mNextMinSerialNo = null;
- mNextMaxSerialNo = null;
- if ((mMaxSerialNo == null) || (mMinSerialNo == null)) {
- throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
- mLastSerialNo.toString()));
- }
mLastSerialNo = mMinSerialNo;
+ mNextMinSerialNo = null;
+ mNextMaxSerialNo = null;
+ mCounter = BigInteger.ZERO;
+
// persist the changes
- mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString());
- mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString());
+ mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix));
+ mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix));
mDB.setNextMinSerialConfig(mRepo, null);
mDB.setNextMaxSerialConfig(mRepo, null);
} else {
@@ -410,11 +453,6 @@ public abstract class Repository implements IRepository {
mLastSerialNo.toString()));
}
}
-
- BigInteger retSerial = new BigInteger(mLastSerialNo.toString());
-
- CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial);
- return retSerial;
}
/**
@@ -436,13 +474,19 @@ public abstract class Repository implements IRepository {
if (mLastSerialNo == null)
initCache();
- BigInteger numsInRange = mMaxSerialNo.subtract(mLastSerialNo);
+ BigInteger numsInRange = null;
+ if ((this instanceof ICertificateRepository) &&
+ mDB.getEnableSerialMgmt() && mEnableRandomSerialNumbers) {
+ numsInRange = (mMaxSerialNo.subtract(mMinSerialNo)).subtract(mCounter);
+ } else {
+ 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);
+ numsInNextRange = mNextMaxSerialNo.subtract(mNextMinSerialNo).add(BigInteger.ONE);
numsAvail = numsInRange.add(numsInNextRange);
CMS.debug("Serial Numbers in next range: " + numsInNextRange.toString());
CMS.debug("Serial Numbers available: " + numsAvail.toString());
@@ -458,7 +502,7 @@ public abstract class Repository implements IRepository {
CMS.debug("Next Range not available");
} else {
CMS.debug("nNextMinSerialNo has been set to " + mNextMinSerialNo.toString(mRadix));
- mNextMaxSerialNo = mNextMinSerialNo.add(mIncrementNo);
+ mNextMaxSerialNo = mNextMinSerialNo.add(mIncrementNo).subtract(BigInteger.ONE);
numsAvail = numsAvail.add(mIncrementNo);
mDB.setNextMinSerialConfig(mRepo, mNextMinSerialNo.toString(mRadix));
mDB.setNextMaxSerialConfig(mRepo, mNextMaxSerialNo.toString(mRadix));
diff --git a/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java b/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java
index 36d5ce914..a268f68a9 100644
--- a/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java
+++ b/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java
@@ -40,11 +40,13 @@ public class RepositoryRecord implements IRepositoryRecord {
private static final long serialVersionUID = 1648450747848783853L;
private BigInteger mSerialNo = null;
private String mPublishingStatus = null;
+ private String mDescription = null;
protected static Vector<String> mNames = new Vector<String>();
static {
mNames.addElement(IRepositoryRecord.ATTR_SERIALNO);
mNames.addElement(IRepositoryRecord.ATTR_PUB_STATUS);
+ mNames.addElement(IRepositoryRecord.ATTR_DESCRIPTION);
}
/**
@@ -62,6 +64,8 @@ public class RepositoryRecord implements IRepositoryRecord {
mSerialNo = (BigInteger) obj;
} else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) {
mPublishingStatus = (String) obj;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ mDescription = (String) obj;
} else {
throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
}
@@ -75,6 +79,8 @@ public class RepositoryRecord implements IRepositoryRecord {
return mSerialNo;
} else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_PUB_STATUS)) {
return mPublishingStatus;
+ } else if (name.equalsIgnoreCase(IRepositoryRecord.ATTR_DESCRIPTION)) {
+ return mDescription;
} else {
throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", name));
}
@@ -108,4 +114,8 @@ public class RepositoryRecord implements IRepositoryRecord {
public String getPublishingStatus() {
return mPublishingStatus;
}
+
+ public String getDescription() {
+ return mDescription;
+ }
}
diff --git a/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java b/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java
index 4ec8da629..5dfc55590 100644
--- a/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java
+++ b/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java
@@ -31,4 +31,5 @@ public class RepositorySchema {
public static final String LDAP_OC_REPOSITORY = "repository";
public static final String LDAP_ATTR_SERIALNO = "serialno";
public static final String LDAP_ATTR_PUB_STATUS = "publishingStatus";
+ public final static String LDAP_ATTR_DESCRIPTION = "description";
}
diff --git a/base/common/test/com/netscape/cmscore/dbs/DBSubsystemDefaultStub.java b/base/common/test/com/netscape/cmscore/dbs/DBSubsystemDefaultStub.java
index 396121b29..9b2221319 100644
--- a/base/common/test/com/netscape/cmscore/dbs/DBSubsystemDefaultStub.java
+++ b/base/common/test/com/netscape/cmscore/dbs/DBSubsystemDefaultStub.java
@@ -168,4 +168,17 @@ public class DBSubsystemDefaultStub implements IDBSubsystem {
// TODO Auto-generated method stub
}
+
+ @Override
+ public IConfigStore getDBConfigStore() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getEntryAttribute(String dn, String attrName,
+ String defaultValue, String errorValue) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java b/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java
index bee66d6ee..4c8919649 100644
--- a/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java
+++ b/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java
@@ -47,6 +47,8 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
private JTextField mSerialNumber;
private JTextField mMaxSerialNumber;
private JCheckBox mValidity;
+ private JCheckBox mEnableSerialNumberManagement;
+ private JCheckBox mEnableRandomSerialNumbers;
private Vector mGroupData;
private static final String HELPINDEX =
"configuration-ca-general-help";
@@ -189,49 +191,86 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
gb2.setConstraints(dummy1, gbc);
signingPanel.add(dummy1);
+ // add serial number management
+ CMSAdminUtil.resetGBC(gbc);
+ mEnableSerialNumberManagement = makeJCheckBox("MANAGEMENT");
+ //mEnableSerialNumberManagement.setEnabled(false);
+ gbc.anchor = gbc.CENTER;
+ gbc.gridwidth = gbc.REMAINDER;
+ gbc.gridheight = 1;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gb3.setConstraints(mEnableSerialNumberManagement, gbc);
+ serialPanel.add(mEnableSerialNumberManagement);
+
+ // add random serial numbers
+ CMSAdminUtil.resetGBC(gbc);
+ mEnableRandomSerialNumbers = makeJCheckBox("RANDOM");
+ gbc.anchor = gbc.CENTER;
+ gbc.gridwidth = gbc.REMAINDER;
+ gbc.gridheight = gbc.REMAINDER; //1;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gb3.setConstraints(mEnableRandomSerialNumbers, gbc);
+ serialPanel.add(mEnableRandomSerialNumbers);
+
// add serial number block
CMSAdminUtil.resetGBC(gbc);
JLabel serialLabel = makeJLabel("SERIAL");
+ serialLabel.setEnabled(false);
gbc.anchor = gbc.CENTER;
gb3.setConstraints(serialLabel, gbc);
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.weightx = 0.0;
gbc.weighty = 1.0;
- //gbc.insets = new Insets(COMPONENT_SPACE,0,COMPONENT_SPACE,0);
- serialPanel.add(serialLabel);
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ //serialPanel.add(serialLabel);
CMSAdminUtil.resetGBC(gbc);
mSerialNumber = makeJTextField(17);
mSerialNumber.setEnabled(false);
gbc.anchor = gbc.NORTHWEST;
- //gbc.gridwidth = gbc.REMAINDER;
- //gbc.gridheight = gbc.REMAINDER;
- //gbc.weightx = 1.0;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.weightx = 0.0;
gbc.weighty = 1.0;
+ gbc.gridx = 1;
+ gbc.gridy = 2;
gb3.setConstraints(mSerialNumber, gbc);
- serialPanel.add(mSerialNumber);
+ //serialPanel.add(mSerialNumber);
// add end serial number block
CMSAdminUtil.resetGBC(gbc);
JLabel maxSerialLabel = makeJLabel("MAXSERIAL");
- gbc.anchor = gbc.EAST;
- //gbc.insets = new Insets(COMPONENT_SPACE,DIFFERENT_COMPONENT_SPACE,0,0);
- gbc.weightx = 0.0;
+ maxSerialLabel.setEnabled(false);
+ gbc.anchor = gbc.CENTER;
gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.weightx = 0.0;
+ gbc.weighty = 1.0;
gbc.gridx = 0;
+ gbc.gridy = 3;
gb3.setConstraints(maxSerialLabel, gbc);
- //gbc.weighty = 1.0;
- serialPanel.add(maxSerialLabel);
+ //serialPanel.add(maxSerialLabel);
CMSAdminUtil.resetGBC(gbc);
mMaxSerialNumber = makeJTextField(17);
mMaxSerialNumber.setEnabled(false);
- gbc.anchor = gbc.NORTHWEST;
- gbc.gridy = 1;
- //gbc.gridwidth = gbc.REMAINDER;
- //gbc.gridheight = gbc.REMAINDER;
- //gbc.weightx = 1.0;
+ gbc.anchor = gbc.CENTER;
+ gbc.gridwidth = 1;
+ gbc.gridheight = 1;
+ gbc.weightx = 0.0;
gbc.weighty = 1.0;
+ gbc.gridx = 1;
+ gbc.gridy = 3;
gb3.setConstraints(mMaxSerialNumber, gbc);
- serialPanel.add(mMaxSerialNumber);
+ //serialPanel.add(mMaxSerialNumber);
CMSAdminUtil.resetGBC(gbc);
JLabel dummy2 = new JLabel(" ");
@@ -249,13 +288,15 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
public void refresh() {
mModel.progressStart();
NameValuePairs nvps = new NameValuePairs();
- nvps.put(Constants.PR_EE_ENABLED, "");
+ //nvps.put(Constants.PR_EE_ENABLED, "");
//nvps.add(Constants.PR_RA_ENABLED, "");
nvps.put(Constants.PR_DEFAULT_ALGORITHM, "");
nvps.put(Constants.PR_ALL_ALGORITHMS, "");
nvps.put(Constants.PR_SERIAL, "");
nvps.put(Constants.PR_MAXSERIAL, "");
nvps.put(Constants.PR_VALIDITY, "");
+ nvps.put(Constants.PR_SN_MANAGEMENT, "");
+ nvps.put(Constants.PR_RANDOM_SN, "");
try {
NameValuePairs val = mAdmin.read(DestDef.DEST_CA_ADMIN,
@@ -268,22 +309,27 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
}
mModel.progressStop();
clearDirtyFlag();
+ enableFields();
}
protected void populate(NameValuePairs nvps) {
String defaultAlgorithm = "";
for (String name : nvps.keySet()) {
String value = nvps.get(name);
+/*
if (name.equals(Constants.PR_EE_ENABLED)) {
mEEEnable.setSelected(getBoolean(value));
} else if (name.equals(Constants.PR_OCSP_ENABLED)) {
mOCSPEnable.setSelected(getBoolean(value));
-/*
} else if (name.equals(Constants.PR_RA_ENABLED)) {
mRAEnable.setSelected(getBoolean(nvp.getValue()));
*/
- } else if (name.equals(Constants.PR_VALIDITY)) {
+ if (name.equals(Constants.PR_VALIDITY)) {
mValidity.setSelected(getBoolean(value));
+ } else if (name.equals(Constants.PR_SN_MANAGEMENT)) {
+ mEnableSerialNumberManagement.setSelected(getBoolean(value));
+ } else if (name.equals(Constants.PR_RANDOM_SN)) {
+ mEnableRandomSerialNumbers.setSelected(getBoolean(value));
} else if (name.equals(Constants.PR_DEFAULT_ALGORITHM)) {
defaultAlgorithm = value;
} else if (name.equals(Constants.PR_ALL_ALGORITHMS)) {
@@ -321,9 +367,19 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
}
public void actionPerformed(ActionEvent e) {
+ if (e.getSource().equals(mEnableSerialNumberManagement)) {
+ enableFields();
+ }
super.actionPerformed(e);
}
+ private void enableFields() {
+ boolean enable = mEnableSerialNumberManagement.isSelected();
+ mEnableRandomSerialNumbers.setEnabled(enable);
+ if (!enable) mEnableRandomSerialNumbers.setSelected(enable);
+ CMSAdminUtil.repaintComp(mEnableRandomSerialNumbers);
+ }
+
private String hexToDecimal(String hex)
{
//String newHex = hex.substring(2);
@@ -338,6 +394,7 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
public boolean applyCallback() {
NameValuePairs nvps = new NameValuePairs();
+/*
if (mEEEnable.isSelected())
nvps.put(Constants.PR_EE_ENABLED, Constants.TRUE);
else
@@ -348,7 +405,6 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
else
nvps.put(Constants.PR_OCSP_ENABLED, Constants.FALSE);
-/*
if (mRAEnable.isSelected())
nvps.add(Constants.PR_RA_ENABLED, Constants.TRUE);
else
@@ -360,6 +416,17 @@ public class CMSCAGeneralPanel extends CMSBaseTab implements ItemListener {
else
nvps.put(Constants.PR_VALIDITY, Constants.FALSE);
+ if (mEnableSerialNumberManagement.isSelected())
+ nvps.put(Constants.PR_SN_MANAGEMENT, Constants.TRUE);
+ else
+ nvps.put(Constants.PR_SN_MANAGEMENT, Constants.FALSE);
+
+ if (mEnableSerialNumberManagement.isSelected() &&
+ mEnableRandomSerialNumbers.isSelected())
+ nvps.put(Constants.PR_RANDOM_SN, Constants.TRUE);
+ else
+ nvps.put(Constants.PR_RANDOM_SN, Constants.FALSE);
+
nvps.put(Constants.PR_DEFAULT_ALGORITHM,
(String) mAlgorithms.getSelectedItem());
diff --git a/base/server/config/pkislots.cfg b/base/server/config/pkislots.cfg
index a2a661f24..a68b45ee2 100644
--- a/base/server/config/pkislots.cfg
+++ b/base/server/config/pkislots.cfg
@@ -50,6 +50,7 @@ PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT=[PKI_EE_SECURE_CLIENT_AUTH_PORT_UI]
PKI_EE_SECURE_PORT_SLOT=[PKI_EE_SECURE_PORT]
PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT=[PKI_EE_SECURE_PORT_CONNECTOR_NAME]
PKI_EE_SECURE_PORT_SERVER_COMMENT_SLOT=[PKI_EE_SECURE_PORT_SERVER_COMMENT]
+PKI_ENABLE_RANDOM_SERIAL_NUMBERS=[PKI_ENABLE_RANDOM_SERIAL_NUMBERS]
PKI_GROUP_SLOT=[PKI_GROUP]
PKI_INSTANCE_ID_SLOT=[PKI_INSTANCE_ID]
PKI_INSTANCE_INITSCRIPT_SLOT=[PKI_INSTANCE_INITSCRIPT]
diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index e848363ab..21a192cfb 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -372,6 +372,7 @@ pki_ocsp_signing_nickname=ocspSigningCert cert-%(pki_instance_name)s CA
pki_ocsp_signing_signing_algorithm=SHA256withRSA
pki_ocsp_signing_subject_dn=cn=CA OCSP Signing Certificate,o=%(pki_security_domain_name)s
pki_ocsp_signing_token=Internal Key Storage Token
+pki_random_serial_numbers_enable=False
pki_subordinate=False
pki_admin_email=%(pki_admin_name)s@%(pki_dns_domainname)s
pki_admin_name=%(pki_admin_uid)s
diff --git a/base/server/src/engine/pkiparser.py b/base/server/src/engine/pkiparser.py
index 2e153764b..4fbabe1a3 100644
--- a/base/server/src/engine/pkiparser.py
+++ b/base/server/src/engine/pkiparser.py
@@ -810,6 +810,10 @@ class PKIConfigParser:
"+TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA," +\
"+TLS_DHE_RSA_WITH_AES_128_CBC_SHA," +\
"+TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
+ if config.pki_master_dict['pki_subsystem'] == "CA":
+ config.pki_master_dict['PKI_ENABLE_RANDOM_SERIAL_NUMBERS']=\
+ config.pki_master_dict\
+ ['pki_random_serial_numbers_enable'].lower()
# Shared Apache/Tomcat NSS security database name/value pairs
config.pki_master_dict['pki_shared_pfile'] =\
os.path.join(
diff --git a/dogtag/console-ui/src/CMSAdminRS.properties b/dogtag/console-ui/src/CMSAdminRS.properties
index e42104937..4cf156b7a 100644
--- a/dogtag/console-ui/src/CMSAdminRS.properties
+++ b/dogtag/console-ui/src/CMSAdminRS.properties
@@ -387,6 +387,12 @@ CAGENERAL_COMBOBOX_ALGORITHM_VALUE_2=SHA1 with RSA
CAGENERAL_COMBOBOX_ALGORITHM_VALUE_3=SHA256 with RSA
CAGENERAL_COMBOBOX_ALGORITHM_VALUE_4=SHA512 with RSA
CAGENERAL_COMBOBOX_ALGORITHM_VALUE_5=SHA1 with DSA
+CAGENERAL_BORDER_MANAGEMENT_LABEL=Serial Number Management
+CAGENERAL_CHECKBOX_MANAGEMENT_LABEL=Enable serial number management
+CAGENERAL_CHECKBOXL_MANAGEMENT_TTIP=Allow CA to manage serial numbers automatically
+CAGENERAL_BORDER_RANDOM_LABEL=Random Certificate Serial Numbers
+CAGENERAL_CHECKBOX_RANDOM_LABEL=Enable random certificate serial numbers
+CAGENERAL_CHECKBOXL_RANDOM_TTIP=Allow CA to generate random certificate serial numbers
CAGENERAL_BORDER_SERIAL_LABEL=Certificate Serial Number
CAGENERAL_LABEL_SERIAL_LABEL=Next Serial Number: (0x)
CAGENERAL_LABEL_SERIAL_TTIP=Specify the next serial number of the certificate that the CA issues