Index: pki/dogtag/console-ui/CMSAdminRS.properties =================================================================== --- pki/dogtag/console-ui/CMSAdminRS.properties (revision 2521) +++ pki/dogtag/console-ui/CMSAdminRS.properties (working copy) @@ -378,6 +378,12 @@ 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 @@ -387,6 +393,9 @@ CAGENERAL_BORDER_VALIDITY_LABEL=Certificate Validity CAGENERAL_CHECKBOX_VALIDITY_LABEL=Override validity nesting requirement CAGENERAL_CHECKBOXL_VALIDITY_TTIP=Allow CA to issue certificates with validity beyond that of the CA's signing certificate +CAGENERAL_BORDER_RANDOM_VALIDITY_LABEL=Randomize Certificate Validity +CAGENERAL_CHECKBOX_RANDOM_VALIDITY_LABEL=Randomize certificate validity +CAGENERAL_CHECKBOXL_RANDOM_VALIDITY_TTIP=Allow CA to issue certificates with randomized validity CAGENERAL_DIALOG_NUMBERFORMAT_MESSAGE=You must specify a numeric value CAGENERAL_DIALOG_NUMBERFORMAT_TITLE=Error CAGENERAL_CHECKBOX_RA_LABEL=Enable registration authority interaction Index: pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java =================================================================== --- pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java (revision 2521) +++ pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java (working copy) @@ -1479,6 +1479,10 @@ getSigningAlgConfig(params); getSerialConfig(params); getMaxSerialConfig(params); + params.add(Constants.PR_SN_MANAGEMENT, + Boolean.toString(mCA.getDBSubsystem().getEnableSerialMgmt())); + params.add(Constants.PR_RANDOM_SN, + Boolean.toString(mCA.getCertificateRepository().getEnableRandomSerialNumbers())); sendResponse(SUCCESS, null, params, resp); } @@ -1555,6 +1559,11 @@ 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)); + //mCA.getCertificateRepository().setEnableSerialMgmt(Boolean.valueOf(value)); + } else if (key.equals(Constants.PR_RANDOM_SN)) { + mCA.getCertificateRepository().setEnableRandomSerialNumbers(Boolean.valueOf(value), true); } } Index: pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java =================================================================== --- pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java (revision 2521) +++ pki/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java (working copy) @@ -33,6 +33,7 @@ import com.netscape.certsrv.policy.*; import com.netscape.certsrv.security.*; import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.dbs.*; import com.netscape.certsrv.dbs.certdb.*; import com.netscape.certsrv.dbs.crldb.*; import com.netscape.certsrv.dbs.replicadb.*; @@ -465,6 +466,13 @@ 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 Index: pki/base/common/src/com/netscape/certsrv/common/Constants.java =================================================================== --- pki/base/common/src/com/netscape/certsrv/common/Constants.java (revision 2521) +++ pki/base/common/src/com/netscape/certsrv/common/Constants.java (working copy) @@ -341,10 +341,14 @@ * Certificate Authority *========================================================*/ public final static String PR_VALIDITY = "validity"; + //public final static String PR_RANDOM_VALIDITY = "randomValidity"; + //public final static String PR_RANDOM_VALIDITY_BITS = "randomValidityBits"; public final static String PR_DEFAULT_ALGORITHM = "defaultSigningAlgorithm"; 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 Index: pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java =================================================================== --- pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java (revision 2521) +++ pki/base/common/src/com/netscape/certsrv/dbs/repository/IRepositoryRecord.java (working copy) @@ -37,6 +37,7 @@ 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. @@ -46,4 +47,6 @@ public BigInteger getSerialNumber(); public String getPublishingStatus(); + + public String getDescription(); } Index: pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java =================================================================== --- pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java (revision 2521) +++ pki/base/common/src/com/netscape/certsrv/dbs/IDBSubsystem.java (working copy) @@ -205,6 +205,39 @@ public void setEnableSerialMgmt(boolean value) throws EBaseException; /** + * Gets replica ID + * + * @return replica ID + */ + public int getReplicaID(); + + /** + * 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 Index: pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java =================================================================== --- pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java (revision 2521) +++ pki/base/common/src/com/netscape/certsrv/dbs/certdb/ICertificateRepository.java (working copy) @@ -508,5 +508,22 @@ */ 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 + */ + public void setEnableRandomSerialNumbers(boolean random, boolean updateMode); + public void shutdown(); } Index: pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java =================================================================== --- pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java (revision 2521) +++ pki/base/common/src/com/netscape/cmscore/dbs/DBSubsystem.java (working copy) @@ -59,6 +59,7 @@ private DBRegistry mRegistry = null; private String mBaseDN = null; private ISubsystem mOwner = null; + private int mReplicaID = -1; private Hashtable[] mRepos = null; @@ -141,8 +142,6 @@ 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 @@ -212,6 +211,10 @@ mEnableSerialMgmt = v; } + public int getReplicaID() { + return mReplicaID; + } + public BigInteger getNextSerialConfig() { return mNextSerialConfig; } @@ -437,7 +440,7 @@ 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")); @@ -449,6 +452,8 @@ 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(); @@ -547,6 +552,7 @@ 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 certs = new Hashtable(); @@ -800,14 +806,72 @@ 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()) return; throw e; } + + if (!CMS.isPreOpMode()) { + String dn = null; + try { + dn = "cn=replica,cn=\""+mBaseDN+"\",cn=mapping tree,cn=config"; + mReplicaID = Integer.parseInt(getEntryAttribute(dn, "nsDS5ReplicaId", "0", "-1")); + CMS.debug("DBSubsystem: init() mReplicaID="+mReplicaID); + } catch (Exception e) { + CMS.debug("DBSubsystem: init(). Unable to identify replica ID:" + e.getMessage()); + } + } } + public String getEntryAttribute(String dn, String attrName, + String defaultValue, String errorValue) { + LDAPConnection conn = null; + String attrValue = null; + //CMS.debug("DBSubsystem: getEntryAttribute: dn="+dn+" attrName="+attrName+ + // " defaultValue="+defaultValue+" errorValue="+errorValue); + 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. */ @@ -815,13 +879,20 @@ } /** - * 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() { Index: pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java =================================================================== --- pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java (revision 2521) +++ pki/base/common/src/com/netscape/cmscore/dbs/RepositoryRecord.java (working copy) @@ -41,11 +41,13 @@ private BigInteger mSerialNo = null; private String mPublishingStatus = null; + private String mDescription = null; protected static Vector mNames = new Vector(); static { mNames.addElement(IRepositoryRecord.ATTR_SERIALNO); mNames.addElement(IRepositoryRecord.ATTR_PUB_STATUS); + mNames.addElement(IRepositoryRecord.ATTR_DESCRIPTION); } /** @@ -63,6 +65,8 @@ 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)); } @@ -76,6 +80,8 @@ 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)); } @@ -109,4 +115,8 @@ public String getPublishingStatus() { return mPublishingStatus; } + + public String getDescription() { + return mDescription; + } } Index: pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java =================================================================== --- pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java (revision 2521) +++ pki/base/common/src/com/netscape/cmscore/dbs/RepositorySchema.java (working copy) @@ -41,4 +41,5 @@ 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"; } Index: pki/base/common/src/com/netscape/cmscore/dbs/Repository.java =================================================================== --- pki/base/common/src/com/netscape/cmscore/dbs/Repository.java (revision 2521) +++ pki/base/common/src/com/netscape/cmscore/dbs/Repository.java (working copy) @@ -48,9 +48,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 @@ -61,8 +59,10 @@ 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; @@ -152,6 +152,7 @@ } BigInteger serial = rec.getSerialNumber(); + CMS.debug("Repository: getSerialNumber serial="+serial); if (!mInit) { // cms may crash after issue a cert but before update @@ -161,7 +162,7 @@ serial + "," + mBaseDN); if (obj != null) { - serial = serial.add(BI_ONE); + serial = serial.add(BigInteger.ONE); setSerialNumber(serial); } }catch (EBaseException e) { @@ -249,6 +250,9 @@ return mMinSerial; } + protected void setLastSerialNo(BigInteger lastSN) { + mLastSerialNo = lastSN; + } /** * init serial number cache @@ -323,6 +327,11 @@ } + protected void initCacheIfNeeded() throws EBaseException { + if (mLastSerialNo == null) + initCache(); + } + /** * get the next serial number in cache */ @@ -331,7 +340,7 @@ 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; @@ -360,7 +369,7 @@ // < 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); } @@ -379,23 +388,43 @@ if (mLastSerialNo == null) { initCache(); - - mLastSerialNo = mLastSerialNo.add(BI_ONE); - - - } else { - mLastSerialNo = mLastSerialNo.add(BI_ONE); } - - if( mLastSerialNo == null ) { + 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; + if ((this instanceof ICertificateRepository) && + mDB.getEnableSerialMgmt() && mEnableRandomSerialNumbers) { + randomLimit = mMaxSerialNo.subtract(mMinSerialNo).add(BigInteger.ONE); + randomLimit = randomLimit.subtract(mLowWaterMarkNo.shiftRight(1)); + CMS.debug("Repository: checkRange randomLimit="+randomLimit); + } + CMS.debug("Repository: checkRange mLastSerialNo="+mLastSerialNo); + if (mLastSerialNo.compareTo( mMaxSerialNo ) > 0 || + (randomLimit != null && mCounter.compareTo(randomLimit) > 0)) { + if (mDB.getEnableSerialMgmt()) { CMS.debug("Reached the end of the range. Attempting to move to next range"); mMinSerialNo = mNextMinSerialNo; @@ -409,8 +438,8 @@ } // 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 { @@ -418,11 +447,6 @@ mLastSerialNo.toString())); } } - - BigInteger retSerial = new BigInteger(mLastSerialNo.toString()); - - CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial); - return retSerial; } /** @@ -445,13 +469,19 @@ 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()); @@ -467,7 +497,7 @@ 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)); Index: pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java =================================================================== --- pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java (revision 2521) +++ pki/base/common/src/com/netscape/cmscore/dbs/CertificateRepository.java (working copy) @@ -52,7 +52,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 BigInteger BI_MINUS_ONE = (BigInteger.ZERO).subtract(BigInteger.ONE); + private final int REPLICA_BITS = 16; private IDBSubsystem mDBService; private String mBaseDN; @@ -66,6 +74,18 @@ private int mTransitMaxRecords = 1000000; private int mTransitRecordPageSize = 200; + private Random mRandom = null; + private int mBitLength = 0; + private BigInteger mRangeSize = null; + private BigInteger mRandomRangeSize = null; + private BigInteger mReplicaID = null; + private int mMinRandomBitLength = 4; + private int mReplicaBitLength = REPLICA_BITS; + private int mMaxCollisionRecoverySteps = 10; + private int mMaxCollisionRecoveryRegenerations = 3; + private IConfigStore mDBConfig = null; + private boolean mForceModeChange = false; + /** * Constructs a certificate repository. */ @@ -75,17 +95,297 @@ mBaseDN = certRepoBaseDN; mDBService = dbService; - - // registers CMS database attributes - IDBRegistry reg = dbService.getRegistry(); - - IConfigStore cfg = mDBService.getConfigStore(); + 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) { + if (mEnableRandomSerialNumbers ^ random) { + 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 || mReplicaID == null) { + mRangeSize = (mMaxSerialNo.subtract(mMinSerialNo)).add(BigInteger.ONE); + mBitLength = mRangeSize.bitLength(); + int rid = mDBService.getReplicaID(); + rid = -1; // shared ranges using replica IDs are postponed + if (rid > -1) { + mReplicaID = new BigInteger((new Integer(rid)).toString()); + } else { + mReplicaBitLength = 0; + } + mRandomRangeSize = mRangeSize.shiftRight(mReplicaBitLength); + } + if (mBitLength - mReplicaBitLength < 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-mReplicaBitLength), mRandom); + randomNumber = (randomNumber.multiply(mRandomRangeSize)).shiftRight(mBitLength-mReplicaBitLength); + CMS.debug("CertificateRepository: getRandomNumber randomNumber="+randomNumber); + + return randomNumber; + } + + private BigInteger getRandomSerialNumber(BigInteger randomNumber) throws EBaseException { + BigInteger nextSerialNumber = null; + + if (mReplicaBitLength > 0) { + nextSerialNumber = (randomNumber.shiftLeft(mReplicaBitLength)).add(mReplicaID); + } else { + nextSerialNumber = randomNumber; + } + nextSerialNumber = (nextSerialNumber.add(mMinSerialNo)).subtract(BigInteger.ONE); + 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) { + 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 modeChange="+modeChange); + if (modeChange) { + if (mForceModeChange) { + setEnableRandomSerialNumbers(mEnableRandomSerialNumbers, true); + } else { + setEnableRandomSerialNumbers(!mEnableRandomSerialNumbers, false); + } + } 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 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):"")); + + BigInteger counter = new BigInteger(c); + BigInteger count = BigInteger.ZERO; + 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 { @@ -97,8 +397,42 @@ } - 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); + 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+ + " 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; ICertRecordList recList = findCertRecordsInList(ldapfilter,attrs,serial_upper_bound.toString(10),"serialno", 5 * -1); @@ -112,7 +446,7 @@ 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; } @@ -151,7 +485,7 @@ 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; @@ -279,6 +613,7 @@ transitRevokedExpiredCertificates(); CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, CMS.getLogMessage("CMSCORE_DBS_FINISH_REVOKED_EXPIRED_SEARCH")); + updateCounter(); } /** @@ -653,6 +988,50 @@ 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(); @@ -1191,7 +1570,7 @@ String fromVal = "0"; try { if (from != null) { - int fv = Integer.parseInt(from); + new BigInteger(from); fromVal = from; } } catch (Exception e1) { Index: pki/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java =================================================================== --- pki/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java (revision 2521) +++ pki/base/console/src/com/netscape/admin/certsrv/config/CMSCAGeneralPanel.java (working copy) @@ -47,6 +47,10 @@ private JTextField mSerialNumber; private JTextField mMaxSerialNumber; private JCheckBox mValidity; + private JCheckBox mRandomValidity; + private JTextField mRandomBits; + private JCheckBox mEnableSerialNumberManagement; + private JCheckBox mEnableRandomSerialNumbers; private Vector mGroupData; private static final String HELPINDEX = "configuration-ca-general-help"; @@ -139,11 +143,11 @@ gb1.setConstraints(mOCSPEnable, gbc); adminPanel.add(mOCSPEnable); - // add validity block + // add validity block CMSAdminUtil.resetGBC(gbc); mValidity = makeJCheckBox("VALIDITY"); gbc.anchor = gbc.CENTER; - //gbc.gridwidth = gbc.REMAINDER; + //gbc.gridwidth = gbc.REMAINDER; remove this comment when adding random validity //gbc.gridheight = gbc.REMAINDER; //gbc.weightx = 1.0; gbc.weighty = 1.0; @@ -151,6 +155,20 @@ validityPanel.add(mValidity); CMSAdminUtil.resetGBC(gbc); + mRandomValidity = makeJCheckBox("RANDOM_VALIDITY"); + gbc.anchor = gbc.CENTER; + gbc.weighty = 1.0; + gb4.setConstraints(mRandomValidity, gbc); + //validityPanel.add(mRandomValidity); + + CMSAdminUtil.resetGBC(gbc); + mRandomBits = makeJTextField(10); + gbc.anchor = gbc.CENTER; + gbc.weighty = 1.0; + gb4.setConstraints(mRandomBits, gbc); + //validityPanel.add(mRandomBits); + + CMSAdminUtil.resetGBC(gbc); JLabel dummy4 = new JLabel(" "); gbc.anchor = gbc.NORTHWEST; gbc.gridwidth = gbc.REMAINDER; @@ -189,49 +207,86 @@ 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); + maxSerialLabel.setEnabled(false); + gbc.anchor = gbc.CENTER; + gbc.gridwidth = 1; + gbc.gridheight = 1; gbc.weightx = 0.0; - gbc.gridwidth = 1; + 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 +304,17 @@ public void refresh() { mModel.progressStart(); NameValuePairs nvps = new NameValuePairs(); - nvps.add(Constants.PR_EE_ENABLED, ""); + //nvps.add(Constants.PR_EE_ENABLED, ""); //nvps.add(Constants.PR_RA_ENABLED, ""); nvps.add(Constants.PR_DEFAULT_ALGORITHM, ""); nvps.add(Constants.PR_ALL_ALGORITHMS, ""); nvps.add(Constants.PR_SERIAL, ""); nvps.add(Constants.PR_MAXSERIAL, ""); nvps.add(Constants.PR_VALIDITY, ""); + //nvps.add(Constants.PR_RANDOM_VALIDITY, ""); + //nvps.add(Constants.PR_RANDOM_VALIDITY_BITS, ""); + nvps.add(Constants.PR_SN_MANAGEMENT, ""); + nvps.add(Constants.PR_RANDOM_SN, ""); try { NameValuePairs val = mAdmin.read(DestDef.DEST_CA_ADMIN, @@ -268,6 +327,7 @@ } mModel.progressStop(); clearDirtyFlag(); + enableFields(); } protected void populate(NameValuePairs nvps) { @@ -275,16 +335,21 @@ for (int i=0; i