From f514cf776fd2918935bdd26939151f22f335cbe6 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Wed, 27 Jul 2016 11:43:33 -0700
Subject: [PATCH] Make starting CRL Number configurable.

Ticket #2406 Make starting CRL Number configurable

This simple patch provides a pkispawn config param that passes
some starting crl number value to the config process.

Here is a sample:

[CA]
pki_ca_starting_crl_number=4000

After the CA comes up the value of "crlNumber" in the db will
reflect that value of 4000.

Currently no other values are changed. We can talk about if we
need more values reset in the given case.

Also, this creates a setting in the CS.cfg

ca.crl.MasterCrl.startingCrlNumber=4000

This setting is only consulted when the crl Issuing Point record is created
for the first time.
---
 base/ca/src/com/netscape/ca/CRLIssuingPoint.java   | 65 +++++++++++++++-------
 .../server/ca/rest/CAInstallerService.java         |  7 +++
 .../certsrv/system/ConfigurationRequest.java       | 12 ++++
 base/server/etc/default.cfg                        |  1 +
 .../python/pki/server/deployment/pkihelper.py      |  4 ++
 5 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/base/ca/src/com/netscape/ca/CRLIssuingPoint.java b/base/ca/src/com/netscape/ca/CRLIssuingPoint.java
index fc9e6a3..a593eb8 100644
--- a/base/ca/src/com/netscape/ca/CRLIssuingPoint.java
+++ b/base/ca/src/com/netscape/ca/CRLIssuingPoint.java
@@ -31,6 +31,23 @@ import java.util.StringTokenizer;
 import java.util.TimeZone;
 import java.util.Vector;
 
+import netscape.security.util.BitArray;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CRLExtensions;
+import netscape.security.x509.CRLNumberExtension;
+import netscape.security.x509.CRLReasonExtension;
+import netscape.security.x509.DeltaCRLIndicatorExtension;
+import netscape.security.x509.Extension;
+import netscape.security.x509.FreshestCRLExtension;
+import netscape.security.x509.IssuingDistributionPoint;
+import netscape.security.x509.IssuingDistributionPointExtension;
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.RevokedCertificate;
+import netscape.security.x509.X509CRLImpl;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509ExtensionException;
+
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
@@ -66,23 +83,6 @@ import com.netscape.cmscore.dbs.CertRecord;
 import com.netscape.cmscore.dbs.CertificateRepository;
 import com.netscape.cmscore.util.Debug;
 
-import netscape.security.util.BitArray;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.CRLExtensions;
-import netscape.security.x509.CRLNumberExtension;
-import netscape.security.x509.CRLReasonExtension;
-import netscape.security.x509.DeltaCRLIndicatorExtension;
-import netscape.security.x509.Extension;
-import netscape.security.x509.FreshestCRLExtension;
-import netscape.security.x509.IssuingDistributionPoint;
-import netscape.security.x509.IssuingDistributionPointExtension;
-import netscape.security.x509.RevocationReason;
-import netscape.security.x509.RevokedCertImpl;
-import netscape.security.x509.RevokedCertificate;
-import netscape.security.x509.X509CRLImpl;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509ExtensionException;
-
 /**
  * This class encapsulates CRL issuing mechanism. CertificateAuthority
  * contains a map of CRLIssuingPoint indexed by string ids. Each issuing
@@ -112,6 +112,8 @@ public class CRLIssuingPoint implements ICRLIssuingPoint, Runnable {
 
     private static final int CRL_PAGE_SIZE = 10000;
 
+    private static final String PROP_CRL_STARTING_NUMBER = "startingCrlNumber";
+
     /* configuration file property names */
 
     public IPublisherProcessor mPublisherProcessor = null;
@@ -923,13 +925,36 @@ public class CRLIssuingPoint implements ICRLIssuingPoint, Runnable {
         if (crlRecord == null) {
             // no crl was ever created, or crl in db is corrupted.
             // create new one.
+
+            IConfigStore ipStore = mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE).getSubStore(mId);
             try {
-                crlRecord = new CRLIssuingPointRecord(mId, BigInteger.ZERO, Long.valueOf(-1),
+
+                BigInteger startingCrlNumberBig = ipStore.getBigInteger(PROP_CRL_STARTING_NUMBER, BigInteger.ZERO);
+                CMS.debug("startingCrlNumber: " + startingCrlNumberBig);
+
+                // Check for bogus negative value
+
+                if(startingCrlNumberBig.compareTo(BigInteger.ZERO) < 0) {
+                    //Make it the default of ZERO
+                    startingCrlNumberBig = BigInteger.ZERO;
+                }
+
+                crlRecord = new CRLIssuingPointRecord(mId, startingCrlNumberBig, Long.valueOf(-1),
                                                null, null, BigInteger.ZERO, Long.valueOf(-1),
                                           mRevokedCerts, mUnrevokedCerts, mExpiredCerts);
                 mCRLRepository.addCRLIssuingPointRecord(crlRecord);
-                mCRLNumber = BigInteger.ZERO; //BIG_ZERO;
-                mNextCRLNumber = BigInteger.ONE; //BIG_ONE;
+                mCRLNumber = startingCrlNumberBig;
+
+                // The default case calls for ZERO being the starting point where
+                // it is then incremented by one to ONE
+                // If we specificy an explicit starting point,
+                // We want that exact number to be the next CRL Number.
+                if(mCRLNumber.compareTo(BigInteger.ZERO) == 0) {
+                    mNextCRLNumber = BigInteger.ONE;
+                } else {
+                    mNextCRLNumber = mCRLNumber;
+                }
+
                 mLastCRLNumber = mCRLNumber;
                 mDeltaCRLNumber = mCRLNumber;
                 mNextDeltaCRLNumber = mNextCRLNumber;
diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java
index e1b7160..3c7e483 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/CAInstallerService.java
@@ -80,6 +80,8 @@ public class CAInstallerService extends SystemConfigService {
                 disableCRLCachingAndGenerationForClone(request);
             }
 
+            configureStartingCRLNumber(request);
+
         } catch (Exception e) {
             CMS.debug(e);
             throw new PKIException("Errors in determining if security domain host is a master CA");
@@ -187,6 +189,11 @@ public class CAInstallerService extends SystemConfigService {
         configStore.commit(false /* no backup */);
     }
 
+    private void configureStartingCRLNumber(ConfigurationRequest data) {
+        CMS.debug("CAInstallerService:configureStartingCRLNumber entering.");
+        cs.putString("ca.crl.MasterCRL.startingCrlNumber",data.getStartingCRLNumber() );
+
+    }
     private void disableCRLCachingAndGenerationForClone(ConfigurationRequest data) throws MalformedURLException {
 
         CMS.debug("CAInstallerService:disableCRLCachingAndGenerationForClone entering.");
diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
index 890f7d0..cd9d3c8 100644
--- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
+++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java
@@ -234,6 +234,9 @@ public class ConfigurationRequest {
     @XmlElement
     protected String sharedDBUserDN;
 
+    @XmlElement
+    protected String startingCRLNumber;
+
     public ConfigurationRequest() {
         // required for JAXB
     }
@@ -932,6 +935,14 @@ public class ConfigurationRequest {
         this.subordinateSecurityDomainName = subordinateSecurityDomainName;
     }
 
+    public String getStartingCRLNumber() {
+        return startingCRLNumber;
+    }
+
+    public void setStartingCRLNumber(String startingCRLNumber) {
+        this.startingCRLNumber = startingCRLNumber;
+    }
+
     @Override
     public String toString() {
         return "ConfigurationRequest [pin=XXXX" +
@@ -995,6 +1006,7 @@ public class ConfigurationRequest {
                ", setupReplication=" + setupReplication +
                ", subordinateSecurityDomainName=" + subordinateSecurityDomainName +
                ", reindexData=" + reindexData +
+               ", startingCrlNumber=" + startingCRLNumber +
                "]";
     }
 
diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index 4919cb4..3a7e005 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -296,6 +296,7 @@ pki_ca_signing_subject_dn=cn=CA Signing Certificate,o=%(pki_security_domain_name
 pki_ca_signing_token=Internal Key Storage Token
 pki_ca_signing_csr_path=
 pki_ca_signing_cert_path=
+pki_ca_starting_crl_number=0
 pki_external=False
 pki_req_ext_add=False
 # MS subca request ext data
diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index 6ac68b1..8a1dbdd 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -4113,6 +4113,10 @@ class ConfigClient:
         if self.subsystem == "TPS":
             self.set_tps_parameters(data)
 
+        # Misc CA parameters
+        if self.subsystem == "CA":
+            data.startingCRLNumber = self.mdict['pki_ca_starting_crl_number']
+
         return data
 
     def save_admin_csr(self):
-- 
2.5.0

