Blob Blame History Raw
From 696422ef74f9e143684d6a79769217a32811ec16 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@cfu-rhel7.usersys.redhat.com>
Date: Mon, 9 Sep 2019 20:36:26 -0400
Subject: [PATCH 01/14] Bug 1638891 - TPS - (addl fix) Add External
 Registration Support to PIN Reset

This small patch fixes a critical typo (during patch merge) that causes KeySet
 to be accidentally written to token Type instead.

(cherry picked from commit 78c86e6cf33e85a23e666e06708441ac58b46a75)
---
 .../src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
index a8589fe..de5c634 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
@@ -209,7 +209,7 @@ public class TPSPinResetProcessor extends TPSProcessor {
                     BaseMappingResolver resolverInst =
                             subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
                     String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet");
-                    setSelectedTokenType(keySet);
+                    setSelectedKeySet(keySet);
                     CMS.debug(method + " resolved keySet: " + keySet);
                 }
             } catch (TPSException e) {
-- 
1.8.3.1


From eee11e26487e7993d4923df4c30d72b667a14a2b Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 10 Sep 2019 15:50:38 -0500
Subject: [PATCH 02/14] Fixed TPSTokendb.tdbFindTokenRecordsByUID()

The TPSTokendb.tdbFindTokenRecordsByUID() has been modified such
that it uses (tokenUserID=<UIID>) filter to find tokens with exact
owner UID instead of filter with wildcards.

https://bugzilla.redhat.com/show_bug.cgi?id=1520258
(cherry picked from commit e8c81c59f03a3db5886924e4e7ec272bc864d953)
---
 .../src/com/netscape/cmscore/dbs/LDAPDatabase.java | 23 +++++++++++++++++++---
 .../src/org/dogtagpki/server/tps/TPSTokendb.java   | 22 ++++++++++++---------
 .../dogtagpki/server/tps/dbs/TokenDatabase.java    |  1 +
 3 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
index 8773423..8e7f1f3 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java
@@ -108,12 +108,22 @@ public abstract class LDAPDatabase<E extends IDBObj> extends Database<E> {
         // if no attributes specified, don't change filter
         if (attributes == null || attributes.isEmpty()) return;
 
-        // wrap current filter with attribute matching filter
-        sb.insert(0, "(&");
+        // count filter components
+        int components = 0;
+        if (sb.length() > 0) components++; // count original filter
+        components += attributes.size(); // count attribute filters
+
+        // concatenate the original filter and attribute filters:
+        // <original filter>(<attribute>=<value>)...(<attribute>=<value>)
         for (Map.Entry<String, String> entry : attributes.entrySet()) {
             sb.append("(" + entry.getKey() + "=" + LDAPUtil.escapeFilter(entry.getValue()) + ")");
         }
-        sb.append(")");
+
+        // if there are multiple filter components, join with AND operator
+        if (components > 1) {
+            sb.insert(0, "(&");
+            sb.append(")");
+        }
     }
 
     @Override
@@ -121,13 +131,20 @@ public abstract class LDAPDatabase<E extends IDBObj> extends Database<E> {
         return findRecords(keyword, null);
     }
 
+    /**
+     * Search for LDAP records with the specified keyword and attributes.
+     * The keyword parameter will be used to search with wildcards on certain attributes.
+     * The attributes parameter will be used to find exact matches of the specified attributes.
+     */
     public Collection<E> findRecords(String keyword, Map<String, String> attributes) throws Exception {
 
         CMS.debug("LDAPDatabase: findRecords()");
 
         try (IDBSSession session = dbSubsystem.createSession()) {
             Collection<E> list = new ArrayList<E>();
+
             String ldapFilter = createFilter(keyword, attributes);
+
             CMS.debug("LDAPDatabase: searching " + baseDN + " with filter " + ldapFilter);
             IDBSearchResults results = session.search(baseDN, ldapFilter);
 
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
index 80c9bb1..da0b51d 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
@@ -141,17 +142,20 @@ public class TPSTokendb {
      */
     public ArrayList<TokenRecord> tdbFindTokenRecordsByUID(String uid)
             throws Exception {
-        ArrayList<TokenRecord> tokenRecords = new ArrayList<TokenRecord>();
-        String filter = uid;
-        Iterator<TokenRecord> records = null;
-        records = tps.tokenDatabase.findRecords(filter).iterator();
 
-       while (records.hasNext()) {
-           TokenRecord tokenRecord = records.next();
-           tokenRecords.add(tokenRecord);
-       }
+        // search for tokens with (tokenUserID=<owner UID>)
+        Map<String, String> attributes = new LinkedHashMap<>();
+        attributes.put("tokenUserID", uid);
+
+        Iterator<TokenRecord> records = tps.tokenDatabase.findRecords(null, attributes).iterator();
+
+        ArrayList<TokenRecord> tokenRecords = new ArrayList<TokenRecord>();
+        while (records.hasNext()) {
+            TokenRecord tokenRecord = records.next();
+            tokenRecords.add(tokenRecord);
+        }
 
-       return tokenRecords;
+        return tokenRecords;
     }
 
     public void tdbHasActiveToken(String userid)
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java
index 9235e78..b349cb2 100644
--- a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java
@@ -60,6 +60,7 @@ public class TokenDatabase extends LDAPDatabase<TokenRecord> {
         StringBuilder sb = new StringBuilder();
 
         if (keyword != null) {
+            // if keyword is specified, generate filter with wildcards
             keyword = LDAPUtil.escapeFilter(keyword);
             sb.append("(|(id=*" + keyword + "*)(userID=*" + keyword + "*))");
         }
-- 
1.8.3.1


From 3cc98ae77dff2351c1ea6af0086d4d0daeb28497 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 13 Sep 2019 17:31:21 -0500
Subject: [PATCH 03/14] Fixed TPSTokendb.tdbFindTokenRecordsByUID() (part 2)

The TPSTokendb.tdbFindTokenRecordsByUID() has been modified to
construct (userID=<UID>) filter which will be translated into
(tokenUserID=<UID>) LDAP filter as defined in TokenRecord.

https://bugzilla.redhat.com/show_bug.cgi?id=1520258
(cherry picked from commit def3453308c68493f7417e485a1db14419187af0)
---
 base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
index da0b51d..49bfb7f 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -143,9 +143,11 @@ public class TPSTokendb {
     public ArrayList<TokenRecord> tdbFindTokenRecordsByUID(String uid)
             throws Exception {
 
-        // search for tokens with (tokenUserID=<owner UID>)
+        // search for tokens with (userID=<UID>) filter which will be
+        // translated into (tokenUserID=<UID>) LDAP filter as defined
+        // in TokenRecord
         Map<String, String> attributes = new LinkedHashMap<>();
-        attributes.put("tokenUserID", uid);
+        attributes.put("userID", uid);
 
         Iterator<TokenRecord> records = tps.tokenDatabase.findRecords(null, attributes).iterator();
 
-- 
1.8.3.1


From 53766e02131741dc0cb6434755b3ba488f0bd927 Mon Sep 17 00:00:00 2001
From: Dinesh Prasanth M K <SilleBille@users.noreply.github.com>
Date: Wed, 18 Sep 2019 15:36:51 -0400
Subject: [PATCH 04/14] Update KRATool to support netkeyKeyRecovery entries
 (#248)

The `netkeyKeyRecovery` request entries are generated when
the TPS retrieves encryption cert onto tokens.

The attributes processed by KRATool include:
* requestId
* dn
* dateOfModify
* cn
* extdata-requestid
* extdata-request-notes (creates, if it doesn't exist)

Resolves: BZ#1445479

Signed-off-by: Dinesh Prasanth M K <dmoluguw@redhat.com>

(cherry picked from commit b02bc04fe16c59aec28d90323e7c9e31dbd7261f)
---
 base/java-tools/man/man1/KRATool.1                 |  44 +-
 .../src/com/netscape/cmstools/KRATool.cfg          |  21 +
 .../src/com/netscape/cmstools/KRATool.java         | 460 ++++++++++++++++++++-
 3 files changed, 506 insertions(+), 19 deletions(-)

diff --git a/base/java-tools/man/man1/KRATool.1 b/base/java-tools/man/man1/KRATool.1
index b04cd2b..1e2fe99 100644
--- a/base/java-tools/man/man1/KRATool.1
+++ b/base/java-tools/man/man1/KRATool.1
@@ -1,7 +1,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH KRATool 1 "July 18, 2016" "version 10.3" "PKI Key Recovery Authority (KRA) Tool" Dogtag Team
+.TH KRATool 1 "Sep 11, 2019" "version 10.5" "PKI Key Recovery Authority (KRA) Tool" Dogtag Team
 .\" Please adjust this date whenever revising the man page.
 .\"
 .\" Some roff macros, for reference:
@@ -33,6 +33,8 @@ The syntax for rewrapping keys:
 	[-source_pki_security_database_pwdfile </path/to/password_file>]]
 	[-source_kra_naming_context <name> -target_kra_naming_context <name>]
 	[-process_requests_and_key_records_only]
+	[-unwrap_algorithm AES|DES3]
+
 .fi
 .PP
 The syntax for renumbering keys:
@@ -130,6 +132,12 @@ Gives the path and filename to a password file that contains only the password f
 
 This argument is optional when other rewrap parameters are used. If this argument is not used, then the script prompts for the password.
 
+.TP
+.B -unwrap_algorithm <algorithm>
+Specifies the symmetric key algorithm used by source KRA. Available options include \fBDES3\fP and \fBAES\fP
+
+This argument is optional and defaults to \fBDES3\fP if unspecified.
+
 .PP
 The following parameters are optional for renumbering keys:
 
@@ -147,13 +155,14 @@ If \fB-remove_id_offset\fP is used, then do not use the \fB-append_id_offset\fP
 
 .SH Configuration File (.cfg)
 .PP
-The required configuration file instructs the KRATool how to process attributes in the key archival and key request entries in the LDIF file. There are six types of entries:
+The required configuration file instructs the KRATool how to process attributes in the key archival and key request entries in the LDIF file. There are seven types of entries:
 .IP
 * CA enrollment requests
 * TPS enrollment requests
 * CA key records
 * TPS key records
 * CA and TPS recovery requests (which are treated the same in the KRA)
+* TPS token key recovery requests
 .PP
 Each key and key request has an LDAP entry with attributes that are specific to that kind of record. For example, for a recovery request:
 .IP
@@ -198,7 +207,7 @@ nsUniqueId: b2891805-1dd111b2-a6d7e85f-2c2f0000
 .PP
 Much of that information passes through the script processing unchanged, so it is entered into the new, target KRA just the same. However, some of those attributes can and should be edited, like the Common Name (CN) and DN being changed to match the new KRA instance. The fields which can safely be changed are listed in the configuration file for each type of key entry. (Any attribute not listed is not touched by the tool under any circumstances.)
 .PP
-If a field /fIshould/fP be edited — meaning, the tool can update the record ID number or rename the entry — then the value is set to true in the configuration file. For example, this configuration updates the CN, DN, ID number, last modified date, and associated entry notes for all CA enrollment requests:
+If a field \fIshould\fP be edited — meaning, the tool can update the record ID number or rename the entry — then the value is set to true in the configuration file. For example, this configuration updates the CN, DN, ID number, last modified date, and associated entry notes for all CA enrollment requests:
 .IP
 .nf
 kratool.ldif.caEnrollmentRequest.cn=true
@@ -324,9 +333,9 @@ kratool.ldif.namingContext._037=##    uid                                 ##
 kratool.ldif.namingContext._038=##    uniqueMember                        ##
 kratool.ldif.namingContext._039=##                                        ##
 kratool.ldif.namingContext._040=##  If '-source_naming_context            ##
-kratool.ldif.namingContext._041=##  original source KRA naming context'   ##
+kratool.ldif.namingContext._041=##  <original source KRA naming context>' ##
 kratool.ldif.namingContext._042=##  and '-target_naming_context           ##
-kratool.ldif.namingContext._043=##  renamed target KRA naming context'    ##
+kratool.ldif.namingContext._043=##  <renamed target KRA naming context>'  ##
 kratool.ldif.namingContext._044=##  options are specified, ALWAYS         ##
 kratool.ldif.namingContext._045=##  require 'KRATOOL' to change the       ##
 kratool.ldif.namingContext._046=##  KRA 'naming context' data in ALL of   ##
@@ -355,6 +364,10 @@ kratool.ldif.namingContext._068=##    tpsNetkeyKeygenRequest:             ##
 kratool.ldif.namingContext._069=##                                        ##
 kratool.ldif.namingContext._070=##      dn                                ##
 kratool.ldif.namingContext._071=##                                        ##
+kratool.ldif.namingContext._072=##    tpsNetkeyKeyRecoveryRequest:        ##
+kratool.ldif.namingContext._073=##                                        ##
+kratool.ldif.namingContext._074=##      dn                                ##
+kratool.ldif.namingContext._075=##                                        ##
 kratool.ldif.namingContext._072=############################################
 kratool.ldif.recoveryRequest._000=#####################################
 kratool.ldif.recoveryRequest._001=##  KRA CA / TPS Recovery Request  ##
@@ -401,6 +414,23 @@ kratool.ldif.tpsNetkeyKeygenRequest.extdata.keyRecord=true
 kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestId=true
 kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestNotes=true
 kratool.ldif.tpsNetkeyKeygenRequest.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._000=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._001=## KRA TPS Netkey Keyrecovery Request ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._002=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._003=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._004=##  NEVER allow 'KRATOOL' the ability ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._005=##  to change the TPS 'naming context'##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._006=##  data in the following fields:     ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._007=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._008=##        extdata-updatedby           ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._009=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._010=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.cn=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dn=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dateOfModify=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestNotes=true
 .if
 
 .SH EXAMPLES
@@ -448,10 +478,10 @@ KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldi
 .if
 
 .SH AUTHORS
-Matthew Harmsen <mharmsen@redhat.com>.
+Matthew Harmsen <mharmsen@redhat.com> and Dinesh Prasanth M K <dmoluguw@redhat.com>
 
 .SH COPYRIGHT
-Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public
+Copyright (c) 2019 Red Hat, Inc. This is licensed under the GNU General Public
 License, version 2 (GPLv2). A copy of this license is available at
 http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 
diff --git a/base/java-tools/src/com/netscape/cmstools/KRATool.cfg b/base/java-tools/src/com/netscape/cmstools/KRATool.cfg
index cad2bf4..b2a4892 100644
--- a/base/java-tools/src/com/netscape/cmstools/KRATool.cfg
+++ b/base/java-tools/src/com/netscape/cmstools/KRATool.cfg
@@ -111,6 +111,10 @@ kratool.ldif.namingContext._068=##    tpsNetkeyKeygenRequest:             ##
 kratool.ldif.namingContext._069=##                                        ##
 kratool.ldif.namingContext._070=##      dn                                ##
 kratool.ldif.namingContext._071=##                                        ##
+kratool.ldif.namingContext._072=##    tpsNetkeyKeyRecoveryRequest:        ##
+kratool.ldif.namingContext._073=##                                        ##
+kratool.ldif.namingContext._074=##      dn                                ##
+kratool.ldif.namingContext._075=##                                        ##
 kratool.ldif.namingContext._072=############################################
 kratool.ldif.recoveryRequest._000=#####################################
 kratool.ldif.recoveryRequest._001=##  KRA CA / TPS Recovery Request  ##
@@ -157,4 +161,21 @@ kratool.ldif.tpsNetkeyKeygenRequest.extdata.keyRecord=true
 kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestId=true
 kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestNotes=true
 kratool.ldif.tpsNetkeyKeygenRequest.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._000=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._001=## KRA TPS Netkey Keyrecovery Request ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._002=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._003=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._004=##  NEVER allow 'KRATOOL' the ability ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._005=##  to change the TPS 'naming context'##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._006=##  data in the following fields:     ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._007=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._008=##        extdata-updatedby           ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._009=##                                    ##
+kratool.ldif.tpsNetkeyKeyRecoveryRequest._010=########################################
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.cn=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dn=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dateOfModify=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestId=true
+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestNotes=true
 
diff --git a/base/java-tools/src/com/netscape/cmstools/KRATool.java b/base/java-tools/src/com/netscape/cmstools/KRATool.java
index 74e5a6a..e4b9ae8 100644
--- a/base/java-tools/src/com/netscape/cmstools/KRATool.java
+++ b/base/java-tools/src/com/netscape/cmstools/KRATool.java
@@ -699,6 +699,7 @@ public class KRATool {
     private static final String KRATOOL_CFG_RECOVERY = "recoveryRequest";
     private static final String KRATOOL_CFG_TPS_KEY_RECORD = "tpsKeyRecord";
     private static final String KRATOOL_CFG_KEYGEN = "tpsNetkeyKeygenRequest";
+    private static final String KRATOOL_CFG_KEYRECOVERY = "tpsNetkeyKeyRecoveryRequest";
 
     // Constants:  KRATOOL Config File (KRA CA Enrollment Request Fields)
     private static final String KRATOOL_CFG_ENROLLMENT_CN = KRATOOL_CFG_PREFIX
@@ -860,6 +861,42 @@ public class KRATool {
                                       + DOT
                                       + "requestId";
 
+    private static final String KRATOOL_CFG_KEYRECOVERY_REQUEST_ID = KRATOOL_CFG_PREFIX
+                                                                       + DOT
+                                                                       + KRATOOL_CFG_KEYRECOVERY
+                                                                       + DOT
+                                                                       + "requestId";
+
+    private static final String KRATOOL_CFG_KEYRECOVERY_DN = KRATOOL_CFG_PREFIX
+                                      + DOT
+                                      + KRATOOL_CFG_KEYRECOVERY
+                                      + DOT
+                                      + "dn";
+
+    private static final String KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY = KRATOOL_CFG_PREFIX
+                                      + DOT
+                                      + KRATOOL_CFG_KEYRECOVERY
+                                      + DOT
+                                      + "dateOfModify";
+
+    private static final String KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID = KRATOOL_CFG_PREFIX
+                                          + DOT
+                                          + KRATOOL_CFG_KEYRECOVERY
+                                          + DOT
+                                          + "extdata.requestId";
+
+    private static final String KRATOOL_CFG_KEYRECOVERY_CN = KRATOOL_CFG_PREFIX
+                          + DOT
+                          + KRATOOL_CFG_KEYRECOVERY
+                          + DOT
+                          + "cn";
+
+    private static final String KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES = KRATOOL_CFG_PREFIX
+                                             + DOT
+                                             + KRATOOL_CFG_KEYRECOVERY
+                                             + DOT
+                                             + "extdata.requestNotes";
+
     // Constants:  Target Certificate Information
     private static final String HEADER = "-----BEGIN";
     private static final String TRAILER = "-----END";
@@ -892,6 +929,7 @@ public class KRATool {
     private static final String KRA_LDIF_KEYGEN = "netkeyKeygen";
     private static final String KRA_LDIF_RECOVERY = "recovery";
     private static final String KRA_LDIF_TPS_KEY_RECORD = "TPS";
+    private static final String KRA_LDIF_KEYRECOVERY = "netkeyKeyRecovery";
 
     // Constants:  KRA LDIF Record Messages
     private static final String KRA_LDIF_REWRAP_MESSAGE = "REWRAPPED the '"
@@ -2334,6 +2372,15 @@ public class KRATool {
             } else {
                 output = line;
             }
+        } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+            if( kratoolCfg.get(KRATOOL_CFG_KEYRECOVERY_CN ) ) {
+                output = compose_numeric_line(KRA_LDIF_CN,
+                    SPACE,
+                    line,
+                    false );
+            } else {
+                output = line;
+            }
         } else if (record_type.equals(KRA_LDIF_RECORD)) {
             // Non-Request / Non-Key Record:
             //     Pass through the original
@@ -2439,6 +2486,21 @@ public class KRATool {
             } else {
                 output = line;
             }
+        } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+            if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY ) ) {
+                output = KRA_LDIF_DATE_OF_MODIFY
+                        + SPACE
+                        + mDateOfModify;
+
+                 log( "Changed '"
+                    + line
+                    + "' to '"
+                    + output
+                    + "'."
+                    + NEWLINE, false );
+            } else {
+                    output = line;
+            }
         } else {
             log("ERROR:  Mismatched record field='"
                     + KRA_LDIF_DATE_OF_MODIFY
@@ -2657,6 +2719,44 @@ public class KRATool {
                 } else {
                     output = line;
                 }
+            } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+                if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_DN ) ) {
+                    // First check for an embedded "cn=<value>"
+                    // name-value pair
+                    if( line.startsWith( KRA_LDIF_DN_EMBEDDED_CN_DATA ) ) {
+                        // At this point, always extract
+                        // the embedded "cn=<value>" name-value pair
+                        // which will ALWAYS be the first
+                        // portion of the "dn: " attribute
+                        embedded_cn_data = line.split( COMMA, 2 );
+
+                        embedded_cn_output = compose_numeric_line(
+                                                 KRA_LDIF_DN_EMBEDDED_CN_DATA,
+                                                 EQUAL_SIGN,
+                                                 embedded_cn_data[0],
+                                                 false );
+
+                        input = embedded_cn_output
+                              + COMMA
+                              + embedded_cn_data[1];
+                    } else {
+                        input = line;
+                    }
+
+                    // Since "-source_kra_naming_context", and
+                    // "-target_kra_naming_context" are OPTIONAL
+                    // parameters, ONLY process this portion of the field
+                    // if both of these options have been selected
+                    if( mKraNamingContextsFlag ) {
+                        output = input.replace( mSourceKraNamingContext,
+                                                mTargetKraNamingContext );
+            } else {
+                output = input;
+            }
+
+        } else {
+                output = line;
+        }
             } else if (record_type.equals(KRA_LDIF_RECORD)) {
                 // Non-Request / Non-Key Record:
                 //     Pass through the original
@@ -2771,6 +2871,15 @@ public class KRATool {
             } else {
                 output = line;
             }
+        } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+            if( kratoolCfg.get(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID ) ) {
+                output = compose_numeric_line(KRA_LDIF_EXTDATA_REQUEST_ID,
+                        SPACE,
+                        line,
+                        false );
+            } else {
+                output = line;
+            }
         } else {
             log("ERROR:  Mismatched record field='"
                     + KRA_LDIF_EXTDATA_REQUEST_ID
@@ -3307,6 +3416,167 @@ public class KRATool {
             } else {
                 output = line;
             }
+        } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+            if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES ) ) {
+                // write out a revised 'extdata-requestnotes' line
+                if( mRewrapFlag && mAppendIdOffsetFlag ) {
+                    data = input
+                         + SPACE
+                         + LEFT_BRACE
+                         + mDateOfModify
+                         + RIGHT_BRACE
+                         + COLON + SPACE
+                         + KRA_LDIF_REWRAP_MESSAGE
+                         + mPublicKeySize
+                         + KRA_LDIF_RSA_MESSAGE
+                         + mSourcePKISecurityDatabasePwdfileMessage
+                         + SPACE
+                         + PLUS + SPACE
+                         + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE
+                         + SPACE
+                         + TIC
+                         + mAppendIdOffset.toString()
+                         + TIC
+                         + mKraNamingContextMessage
+                         + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                    // Unformat the data
+                    unformatted_data = stripEOL( data );
+
+                    // Format the unformatted_data
+                    // to match the desired LDIF format
+                    output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                           + SPACE
+                           + format_ldif_data(
+                                 EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                 unformatted_data );
+                } else if( mRewrapFlag && mRemoveIdOffsetFlag ) {
+                    data = input
+                         + SPACE
+                         + LEFT_BRACE
+                         + mDateOfModify
+                         + RIGHT_BRACE
+                         + COLON + SPACE
+                         + KRA_LDIF_REWRAP_MESSAGE
+                         + mPublicKeySize
+                         + KRA_LDIF_RSA_MESSAGE
+                         + mSourcePKISecurityDatabasePwdfileMessage
+                         + SPACE
+                         + PLUS + SPACE
+                         + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE
+                         + SPACE
+                         + TIC
+                         + mRemoveIdOffset.toString()
+                         + TIC
+                         + mKraNamingContextMessage
+                         + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                    // Unformat the data
+                    unformatted_data = stripEOL( data );
+
+                    // Format the unformatted_data
+                    // to match the desired LDIF format
+                    output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                           + SPACE
+                           + format_ldif_data(
+                                 EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                 unformatted_data );
+                } else if( mRewrapFlag ) {
+                    data = input
+                         + SPACE
+                         + LEFT_BRACE
+                         + mDateOfModify
+                         + RIGHT_BRACE
+                         + COLON + SPACE
+                         + KRA_LDIF_REWRAP_MESSAGE
+                         + mPublicKeySize
+                         + KRA_LDIF_RSA_MESSAGE
+                         + mSourcePKISecurityDatabasePwdfileMessage
+                         + mKraNamingContextMessage
+                         + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                    // Unformat the data
+                    unformatted_data = stripEOL( data );
+
+                    // Format the unformatted_data
+                    // to match the desired LDIF format
+                    output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                           + SPACE
+                           + format_ldif_data(
+                                 EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                 unformatted_data );
+                } else if( mAppendIdOffsetFlag ) {
+                    data = input
+                         + SPACE
+                         + LEFT_BRACE
+                         + mDateOfModify
+                         + RIGHT_BRACE
+                         + COLON + SPACE
+                         + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE
+                         + SPACE
+                         + TIC
+                         + mAppendIdOffset.toString()
+                         + TIC
+                         + mKraNamingContextMessage
+                         + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                    // Unformat the data
+                    unformatted_data = stripEOL( data );
+
+                    // Format the unformatted_data
+                    // to match the desired LDIF format
+                    output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                           + SPACE
+                           + format_ldif_data(
+                                 EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                 unformatted_data );
+                } else if( mRemoveIdOffsetFlag ) {
+                    data = input
+                         + SPACE
+                         + LEFT_BRACE
+                         + mDateOfModify
+                         + RIGHT_BRACE
+                         + COLON + SPACE
+                         + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE
+                         + SPACE
+                         + TIC
+                         + mRemoveIdOffset.toString()
+                         + TIC
+                         + mKraNamingContextMessage
+                         + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                    // Unformat the data
+                    unformatted_data = stripEOL( data );
+
+                    // Format the unformatted_data
+                    // to match the desired LDIF format
+                    output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                           + SPACE
+                           + format_ldif_data(
+                                 EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                 unformatted_data );
+                }
+
+                // log this information
+                log( "Changed:"
+                   + NEWLINE
+                   + TIC
+                   + KRA_LDIF_EXTDATA_REQUEST_NOTES
+                   + SPACE
+                   + format_ldif_data(
+                         EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                         input.toString() )
+                   + TIC
+                   + NEWLINE
+                   + "--->"
+                   + NEWLINE
+                   + TIC
+                   + output
+                   + TIC
+                   + NEWLINE, false );
+            } else {
+                output = line;
+            }
         } else {
             log("ERROR:  Mismatched record field='"
                     + KRA_LDIF_EXTDATA_REQUEST_NOTES
@@ -3634,6 +3904,153 @@ public class KRATool {
                     System.out.print(".");
                 }
             }
+        } else if (record_type.equals(KRA_LDIF_KEYRECOVERY)) {
+            if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES ) ) {
+                if(!previous_line.startsWith( KRA_LDIF_EXTDATA_REQUEST_NOTES)) {
+                    // write out the missing 'extdata-requestnotes' line
+                    if( mRewrapFlag && mAppendIdOffsetFlag ) {
+                        data = LEFT_BRACE
+                             + mDateOfModify
+                             + RIGHT_BRACE
+                             + COLON + SPACE
+                             + KRA_LDIF_REWRAP_MESSAGE
+                             + mPublicKeySize
+                             + KRA_LDIF_RSA_MESSAGE
+                             + mSourcePKISecurityDatabasePwdfileMessage
+                             + SPACE
+                             + PLUS + SPACE
+                             + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE
+                             + SPACE
+                             + TIC
+                             + mAppendIdOffset.toString()
+                             + TIC
+                             + mKraNamingContextMessage
+                             + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                        // Unformat the data
+                        unformatted_data = stripEOL( data );
+
+                        // Format the unformatted_data
+                        // to match the desired LDIF format
+                        output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                               + SPACE
+                               + format_ldif_data(
+                                   EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                   unformatted_data );
+                    } else if( mRewrapFlag && mRemoveIdOffsetFlag ) {
+                        data = LEFT_BRACE
+                             + mDateOfModify
+                             + RIGHT_BRACE
+                             + COLON + SPACE
+                             + KRA_LDIF_REWRAP_MESSAGE
+                             + mPublicKeySize
+                             + KRA_LDIF_RSA_MESSAGE
+                             + mSourcePKISecurityDatabasePwdfileMessage
+                             + SPACE
+                             + PLUS + SPACE
+                             + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE
+                             + SPACE
+                             + TIC
+                             + mRemoveIdOffset.toString()
+                             + TIC
+                             + mKraNamingContextMessage
+                             + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                        // Unformat the data
+                        unformatted_data = stripEOL( data );
+
+                        // Format the unformatted_data
+                        // to match the desired LDIF format
+                        output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                               + SPACE
+                               + format_ldif_data(
+                                   EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                   unformatted_data );
+                    } else if( mRewrapFlag ) {
+                        data = LEFT_BRACE
+                             + mDateOfModify
+                             + RIGHT_BRACE
+                             + COLON + SPACE
+                             + KRA_LDIF_REWRAP_MESSAGE
+                             + mPublicKeySize
+                             + KRA_LDIF_RSA_MESSAGE
+                             + mSourcePKISecurityDatabasePwdfileMessage
+                             + mKraNamingContextMessage
+                             + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                        // Unformat the data
+                        unformatted_data = stripEOL( data );
+
+                        // Format the unformatted_data
+                        // to match the desired LDIF format
+                        output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                               + SPACE
+                               + format_ldif_data(
+                                   EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                   unformatted_data );
+                    } else if( mAppendIdOffsetFlag ) {
+                        data = LEFT_BRACE
+                             + mDateOfModify
+                             + RIGHT_BRACE
+                             + COLON + SPACE
+                             + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE
+                             + SPACE
+                             + TIC
+                             + mAppendIdOffset.toString()
+                             + TIC
+                             + mKraNamingContextMessage
+                             + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                        // Unformat the data
+                        unformatted_data = stripEOL( data );
+
+                        // Format the unformatted_data
+                        // to match the desired LDIF format
+                        output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                               + SPACE
+                               + format_ldif_data(
+                                   EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                   unformatted_data );
+                    } else if( mRemoveIdOffsetFlag ) {
+                        data = LEFT_BRACE
+                             + mDateOfModify
+                             + RIGHT_BRACE
+                             + COLON + SPACE
+                             + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE
+                             + SPACE
+                             + TIC
+                             + mRemoveIdOffset.toString()
+                             + TIC
+                             + mKraNamingContextMessage
+                             + mProcessRequestsAndKeyRecordsOnlyMessage;
+
+                        // Unformat the data
+                        unformatted_data = stripEOL( data );
+
+                        // Format the unformatted_data
+                        // to match the desired LDIF format
+                        output = KRA_LDIF_EXTDATA_REQUEST_NOTES
+                               + SPACE
+                               + format_ldif_data(
+                                   EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH,
+                                   unformatted_data );
+                    }
+
+                    // log this information
+                    log( "Created:"
+                       + NEWLINE
+                       + TIC
+                       + output
+                       + TIC
+                       + NEWLINE, false );
+
+                    // Write out this revised line
+                    // and flush the buffer
+                    writer.write( output + NEWLINE );
+                    writer.flush();
+                    System.out.print( "." );
+                }
+            }
         }
     }
 
@@ -3897,6 +4314,15 @@ public class KRATool {
             } else {
                 output = line;
             }
+        } else if ( record_type.equals( KRA_LDIF_KEYRECOVERY ) ) {
+            if ( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_REQUEST_ID ) ) {
+                    output = compose_numeric_line(KRA_LDIF_REQUEST_ID,
+                                                  SPACE,
+                                                  line,
+                                                  true);
+            } else {
+                    output = line;
+            }
         } else {
             log("ERROR:  Mismatched record field='"
                     + KRA_LDIF_REQUEST_ID
@@ -4115,7 +4541,8 @@ public class KRATool {
                                       ).trim();
                         if (!record_type.equals(KRA_LDIF_ENROLLMENT) &&
                                 !record_type.equals(KRA_LDIF_KEYGEN) &&
-                                !record_type.equals(KRA_LDIF_RECOVERY)) {
+                                !record_type.equals(KRA_LDIF_RECOVERY) &&
+                                !record_type.equals( KRA_LDIF_KEYRECOVERY)) {
                             log("ERROR:  Unknown LDIF record type='"
                                     + record_type
                                     + "'!"
@@ -4398,7 +4825,13 @@ public class KRATool {
                             || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_KEY_RECORD)
                             || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_REQUEST_ID)
                             || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_REQUEST_NOTES)
-                            || name.equals(KRATOOL_CFG_KEYGEN_REQUEST_ID)) {
+                            || name.equals(KRATOOL_CFG_KEYGEN_REQUEST_ID)
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_REQUEST_ID )
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_DN )
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY)
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID)
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_CN)
+                            || name.equals(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES) ) {
                         kratoolCfg.put(name, value);
                         System.out.print(".");
                     }
@@ -4496,6 +4929,7 @@ public class KRATool {
                 (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 5)) &&
                 (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 6)) &&
                 (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 7)) &&
+                (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 8)) &&
                 (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 9))) {
             System.err.println("ERROR:  Incorrect number of arguments!"
                               + NEWLINE);
@@ -4892,16 +5326,18 @@ public class KRATool {
         }
 
         // Check for the Key Unwrap Algorithm provided by user.
-        // If unprovided, choose DES3 as the default (to maintain consistency with old code)
-        if (keyUnwrapAlgorithmName.equalsIgnoreCase("DES3")) {
-            keyUnwrapAlgorithm = SymmetricKey.DES3;
-        } else if (keyUnwrapAlgorithmName.equalsIgnoreCase("AES")) {
-            keyUnwrapAlgorithm = SymmetricKey.AES;
-        } else {
-            System.err.println("ERROR:  Unsupported key unwrap algorithm '"
-                    + keyUnwrapAlgorithmName + "'"
-                    + NEWLINE);
-            System.exit(1);
+        // If unprovided, DES3 is chosen as the default (to maintain consistency with old code)
+        if (keyUnwrapAlgorithmName != null) {
+            if (keyUnwrapAlgorithmName.equalsIgnoreCase("DES3")) {
+                keyUnwrapAlgorithm = SymmetricKey.DES3;
+            } else if (keyUnwrapAlgorithmName.equalsIgnoreCase("AES")) {
+                keyUnwrapAlgorithm = SymmetricKey.AES;
+            } else {
+                System.err.println("ERROR:  Unsupported key unwrap algorithm '"
+                        + keyUnwrapAlgorithmName + "'"
+                        + NEWLINE);
+                System.exit(1);
+            }
         }
 
         // Check for OPTIONAL "Process Requests and Key Records ONLY" option
-- 
1.8.3.1


From b8f619e12ac90aab1ad845bffbdefffcb1e9229d Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 19 Sep 2019 15:41:40 +1000
Subject: [PATCH 05/14] SecurityDataProcess.archive: log decryption failure

(cherry picked from commit df26b7e86b3341c2cc7c0d5d9c3d9f680496a071)
---
 base/kra/src/com/netscape/kra/SecurityDataProcessor.java | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
index 5a64530..05e73ce 100644
--- a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
+++ b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java
@@ -208,6 +208,8 @@ public class SecurityDataProcessor {
                             KeyRequestService.SYMKEY_TYPES.get(algorithm),
                             strength);
                 } catch (Exception e) {
+                    CMS.debug("Can't decrypt symmetric key:");
+                    CMS.debug(e);
                     throw new EBaseException("Can't decrypt symmetric key.", e);
                 }
             }
@@ -222,6 +224,8 @@ public class SecurityDataProcessor {
                         secdata,
                         null);
             } catch (Exception e) {
+                CMS.debug("Can't decrypt passphrase.");
+                CMS.debug(e);
                 throw new EBaseException("Can't decrypt passphrase.", e);
             }
 
-- 
1.8.3.1


From 38a8d9d7fb4e18027c763a553c5ab20cfe709a76 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 19 Sep 2019 17:17:24 +1000
Subject: [PATCH 06/14] CryptoUtil: include OID in NoSuchAlgorithmException

(cherry picked from commit c08b0cdbf069033d7ddc4e769890bf6281200659)
---
 base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 083b9f2..e9bc0dd 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -3114,7 +3114,7 @@ public class CryptoUtil {
         if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID))
             return KeyWrapAlgorithm.DES3_CBC_PAD;
 
-        throw new NoSuchAlgorithmException();
+        throw new NoSuchAlgorithmException(wrapOID);
     }
 
 }
-- 
1.8.3.1


From 4ade0812dac8bebb81500ea74641f3bf79548f42 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 19 Sep 2019 20:54:17 +1000
Subject: [PATCH 07/14] CryptoUtil.getKeywrapAlgorithmFromOID: Fix DES-EDE3-CBC
 selection

Commit dbd2d9b587f46b8af2f78b73d62715c1fd3344fc contained the edit:

-        if (oid.equals(KW_DES_CBC_PAD))
+        if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID))

KW_DES_CBC_PAD was 1.2.840.113549.3.7 (DES-EDE3-CBC; this definition
was removed in the same commit). But
KeyWrapAlgorithm.DES_CBC_PAD_OID is 1.3.14.3.2.7.  This is a
behaviour change that breaks KRA archival (possibly recovery too).

Test equality to KeyWrapAlgorithm.DES3_CBC_PAD_OID to restore the
correct behaviour.  Also fix a similar error in WrappingParams.java.

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1709585
(cherry picked from commit 4d9b4f23d761621073eb7f858e654fc7aceb406d)
---
 base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java | 2 +-
 base/util/src/netscape/security/util/WrappingParams.java  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index e9bc0dd..3d85a14 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -3111,7 +3111,7 @@ public class CryptoUtil {
         if (oid.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID))
             return KeyWrapAlgorithm.AES_CBC_PAD;
 
-        if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID))
+        if (oid.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID))
             return KeyWrapAlgorithm.DES3_CBC_PAD;
 
         throw new NoSuchAlgorithmException(wrapOID);
diff --git a/base/util/src/netscape/security/util/WrappingParams.java b/base/util/src/netscape/security/util/WrappingParams.java
index f1ebc95..b0d4600 100644
--- a/base/util/src/netscape/security/util/WrappingParams.java
+++ b/base/util/src/netscape/security/util/WrappingParams.java
@@ -67,7 +67,7 @@ public class WrappingParams {
             // New clients set this correctly.
             // We'll assume the old DES3 wrapping here.
             encrypt = EncryptionAlgorithm.DES_CBC_PAD;
-        } else if (encryptOID.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID.toString())) {
+        } else if (encryptOID.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID.toString())) {
             encrypt = EncryptionAlgorithm.DES3_CBC_PAD;
         } else if (encryptOID.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID.toString())) {
             encrypt = EncryptionAlgorithm.AES_128_CBC_PAD;
-- 
1.8.3.1


From 78c8448064afddeefea8938f01100a03f6a10d2d Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 29 Aug 2018 16:55:31 +1000
Subject: [PATCH 08/14] getTheSerialNumber: only return null if next range not
 available

When cloning, if the master's current number range has been depleted
due to a previous UpdateNumberRange request,
Repository.getTheSerialNumber() returns null because the next serial
number is out of the current range, but the next range has not been
activated yet.  NullPointerException ensues.

Update getTheSerialNumber() to return the next serial number even
when it exceeds the current number range, as long as there is a next
range.  If there is no next range, return null (as before).  It is
assumed that the next range is non-empty

Also do a couple of drive-by method extractions to improve
readability.

Part of: https://pagure.io/dogtagpki/issue/3055

(cherry picked from commit f1615df509053a8f474b82ea6a2fa0883ab06d09)
---
 .../src/com/netscape/cmscore/dbs/Repository.java   | 61 ++++++++++++++++------
 1 file changed, 44 insertions(+), 17 deletions(-)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
index afe9013..c5120c4 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -317,7 +317,15 @@ public abstract class Repository implements IRepository {
     }
 
     /**
-     * get the next serial number in cache
+     * Peek at the next serial number in cache (does not consume the
+     * number).
+     *
+     * The returned number is not necessarily the previously emitted
+     * serial number plus one, i.e. if we are going to roll into the
+     * next range.  This method does not actually switch the range.
+     *
+     * Returns null if the next number exceeds the current range and
+     * there is not a next range.
      */
     public BigInteger getTheSerialNumber() throws EBaseException {
 
@@ -327,7 +335,7 @@ public abstract class Repository implements IRepository {
         BigInteger serial = mLastSerialNo.add(BigInteger.ONE);
 
         if (mMaxSerialNo != null && serial.compareTo(mMaxSerialNo) > 0)
-            return null;
+            return hasNextRange() ? mNextMinSerialNo : null;
         else
             return serial;
     }
@@ -390,9 +398,13 @@ public abstract class Repository implements IRepository {
     }
 
     /**
-     * Checks to see if range needs to be switched.
+     * Checks if the given number is in the current range.
+     * If it does not exceed the current range, return cleanly.
+     * If it exceeds the given range, and there is a next range, switch the range.
+     * If it exceeds the given range, and there is not a next range, throw EDBException.
      *
-     * @exception EBaseException thrown when next range is not allocated
+     * @exception EDBException thrown when range switch is needed
+     *                           but next range is not allocated
      */
     protected void checkRange() throws EBaseException
     {
@@ -413,7 +425,7 @@ public abstract class Repository implements IRepository {
 
             if (mDB.getEnableSerialMgmt()) {
                 CMS.debug("Reached the end of the range.  Attempting to move to next range");
-                if ((mNextMinSerialNo == null) || (mNextMaxSerialNo == null)) {
+                if (!hasNextRange()) {
                     if (rangeLength != null && mCounter.compareTo(rangeLength) < 0) {
                         return;
                     } else {
@@ -421,18 +433,7 @@ public abstract class Repository implements IRepository {
                                                                   mLastSerialNo.toString()));
                     }
                 }
-                mMinSerialNo = mNextMinSerialNo;
-                mMaxSerialNo = mNextMaxSerialNo;
-                mLastSerialNo = mMinSerialNo;
-                mNextMinSerialNo  = null;
-                mNextMaxSerialNo  = null;
-                mCounter = BigInteger.ZERO;
-
-                // persist the changes
-                mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix));
-                mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix));
-                mDB.setNextMinSerialConfig(mRepo, null);
-                mDB.setNextMaxSerialConfig(mRepo, null);
+                switchToNextRange();
             } else {
                 throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED",
                         mLastSerialNo.toString()));
@@ -441,6 +442,32 @@ public abstract class Repository implements IRepository {
     }
 
     /**
+     * Return true iff there is a next range ready to go.
+     */
+    private boolean hasNextRange() {
+        return (mNextMinSerialNo != null) && (mNextMaxSerialNo != null);
+    }
+
+    /**
+     * Switch to the next range and persist the changes.
+     */
+    private void switchToNextRange()
+            throws EBaseException {
+        mMinSerialNo = mNextMinSerialNo;
+        mMaxSerialNo = mNextMaxSerialNo;
+        mLastSerialNo = mMinSerialNo;
+        mNextMinSerialNo  = null;
+        mNextMaxSerialNo  = null;
+        mCounter = BigInteger.ZERO;
+
+        // persist the changes
+        mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix));
+        mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix));
+        mDB.setNextMinSerialConfig(mRepo, null);
+        mDB.setNextMaxSerialConfig(mRepo, null);
+    }
+
+    /**
      * Checks to see if a new range is needed, or if we have reached the end of the
      * current range, or if a range conflict has occurred.
      *
-- 
1.8.3.1


From 30fa68e6241763c5c117014e9e5cacc410cc3a56 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Mon, 3 Sep 2018 15:55:35 +1000
Subject: [PATCH 09/14] Repository: handle depleted range in initCache()

Repository.initCache() does not handle the case where the current
range has been fully depleted, but the switch to the next range has
not occurred yet.  This situation arises when the range has been
fully depleted by servicing UpdateNumberRange requests for clones.

Detect this situation and handle it by switching to the next range
(when available).

Part of: https://pagure.io/dogtagpki/issue/3055

(cherry picked from commit 2fb3611db5145dbdd5e7e14daaad1470691494f0)
---
 .../src/com/netscape/cmscore/dbs/Repository.java      | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
index c5120c4..828217c 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -298,6 +298,25 @@ public abstract class Repository implements IRepository {
         BigInteger theSerialNo = null;
         theSerialNo = getLastSerialNumberInRange(mMinSerialNo, mMaxSerialNo);
 
+        if (theSerialNo == null) {
+            // This arises when range has been depleted by servicing
+            // UpdateNumberRange requests for clones.  Attempt to
+            // move to next range.
+            CMS.debug(
+                "Repository: failed to get last serial number in range "
+                + mMinSerialNo + ".." + mMaxSerialNo);
+
+            if (hasNextRange()) {
+                CMS.debug("Repository: switching to next range.");
+                switchToNextRange();
+                CMS.debug("Repository: new range: " + mMinSerialNo + ".." + mMaxSerialNo);
+                // try again with updated range
+                theSerialNo = getLastSerialNumberInRange(mMinSerialNo, mMaxSerialNo);
+            } else {
+                CMS.debug("Repository: next range not available.");
+            }
+        }
+
         if (theSerialNo != null) {
 
             mLastSerialNo = new BigInteger(theSerialNo.toString());
-- 
1.8.3.1


From 920187e48e4971069ac114a3a41a5be79578f17c Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 29 Aug 2018 17:31:34 +1000
Subject: [PATCH 10/14] rename method getTheSerialNumber ->
 peekNextSerialNumber

Rename Repository.getTheSerialNumber -> peekNextSerialNumber to more
accurately reflect what it does: peek at the next serial number
without actually consuming it.

Part of: https://pagure.io/dogtagpki/issue/3055

(cherry picked from commit 85e356580f64f87c0b01736b71dc3d385db0bcba)
---
 base/ca/src/com/netscape/ca/CertificateAuthority.java                   | 2 +-
 base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java    | 2 +-
 .../cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java     | 2 +-
 base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java        | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 0281db0..f414628 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -1077,7 +1077,7 @@ public class CertificateAuthority
     public String getStartSerial() {
         try {
             BigInteger serial =
-                    mCertRepot.getTheSerialNumber();
+                    mCertRepot.peekNextSerialNumber();
 
             if (serial == null)
                 return "";
diff --git a/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java b/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java
index 39744ac..d0b6135 100644
--- a/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java
+++ b/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java
@@ -50,7 +50,7 @@ public interface IRepository {
      * @return serial number
      * @exception EBaseException failed to retrieve next serial number
      */
-    public BigInteger getTheSerialNumber() throws EBaseException;
+    public BigInteger peekNextSerialNumber() throws EBaseException;
 
     /**
      * Set the maximum serial number.
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
index 2586da2..e5b5168 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
@@ -187,7 +187,7 @@ public class UpdateNumberRange extends CMSServlet {
             BigInteger decrement = new BigInteger(decrementStr, radix);
             beginNum = endNum.subtract(decrement).add(oneNum);
 
-            if (beginNum.compareTo(repo.getTheSerialNumber()) < 0) {
+            if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) {
                 String nextEndNumStr = cs.getString(nextEndConfig, "");
                 BigInteger endNum2 = new BigInteger(nextEndNumStr, radix);
                 CMS.debug("Transferring from the end of on-deck range");
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
index 828217c..55068ea 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -346,7 +346,7 @@ public abstract class Repository implements IRepository {
      * Returns null if the next number exceeds the current range and
      * there is not a next range.
      */
-    public BigInteger getTheSerialNumber() throws EBaseException {
+    public BigInteger peekNextSerialNumber() throws EBaseException {
 
         CMS.debug("Repository:In getTheSerialNumber ");
         if (mLastSerialNo == null)
-- 
1.8.3.1


From 60e78b19edb91b5d7130f591dec5232f30877871 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 29 Aug 2018 21:42:40 +1000
Subject: [PATCH 11/14] checkRange: small refactor and add commentary

Add some commentary about the behaviour and proper usage of
Repository.checkRange().  Also perform a small refactor, avoiding
a redundant stringify and parse.

Part of: https://pagure.io/dogtagpki/issue/3055

(cherry picked from commit 5a606e83719272fb488047b28a9ca7d5ce2ea30b)
---
 .../src/com/netscape/cmscore/dbs/Repository.java      | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
index 55068ea..9bc7e2a 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -406,14 +406,17 @@ public abstract class Repository implements IRepository {
             throw new EBaseException("mLastSerialNo is null");
         }
 
+        /* Advance the serial number.  checkRange() will check if it exceeds
+         * the current range and, if so, rolls to the next range and resets
+         * mLastSerialNo to the start of the new range.  Hence we return
+         * mLastSerialNo below, after the call to checkRange().
+         */
         mLastSerialNo = mLastSerialNo.add(BigInteger.ONE);
 
         checkRange();
 
-        BigInteger retSerial = new BigInteger(mLastSerialNo.toString());
-
-        CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial);
-        return retSerial;
+        CMS.debug("Repository: getNextSerialNumber: returning " + mLastSerialNo);
+        return mLastSerialNo;
     }
 
     /**
@@ -422,6 +425,14 @@ public abstract class Repository implements IRepository {
      * If it exceeds the given range, and there is a next range, switch the range.
      * If it exceeds the given range, and there is not a next range, throw EDBException.
      *
+     * Precondition: the serial number should already have been advanced.
+     * This method will detect that and switch to the next range, including
+     * resetting mLastSerialNo to the start of the new (now current) range.
+     *
+     * Postcondition: the caller should again read mLastSerialNo after
+     * calling checkRange(), in case checkRange switched the range and the
+     * new range is not adjacent to the current range.
+     *
      * @exception EDBException thrown when range switch is needed
      *                           but next range is not allocated
      */
-- 
1.8.3.1


From a2c05cef94753ee1914aeb9c1b88789a322d4015 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 29 Aug 2018 22:22:10 +1000
Subject: [PATCH 12/14] Add missing synchronisation for range management

Several methods in Repository (and CertificateRepository) need
synchronisation on the intrisic lock.  Make these methods
synchronised.

Also take the lock in UpdateNumberRange so that no serial numbers
can be handed out in other threads between peekNextSerialNumber()
and set(Next)?MaxSerial().  Without this synchronisation, it is
possible that the master instance will use some of the serial
numbers it transfers to the clone.

Fixes: https://pagure.io/dogtagpki/issue/3055
(cherry picked from commit 851a0bdd79c12c627a04cfc376338c1727cd50d9)
---
 .../cms/servlet/csadmin/UpdateNumberRange.java     | 35 +++++++-----
 .../cmscore/dbs/CertificateRepository.java         | 62 ++++++++++------------
 .../src/com/netscape/cmscore/dbs/Repository.java   |  6 +--
 3 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
index e5b5168..c2ff7ed 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java
@@ -187,20 +187,27 @@ public class UpdateNumberRange extends CMSServlet {
             BigInteger decrement = new BigInteger(decrementStr, radix);
             beginNum = endNum.subtract(decrement).add(oneNum);
 
-            if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) {
-                String nextEndNumStr = cs.getString(nextEndConfig, "");
-                BigInteger endNum2 = new BigInteger(nextEndNumStr, radix);
-                CMS.debug("Transferring from the end of on-deck range");
-                String newValStr = endNum2.subtract(decrement).toString(radix);
-                repo.setNextMaxSerial(newValStr);
-                cs.putString(nextEndConfig, newValStr);
-                beginNum = endNum2.subtract(decrement).add(oneNum);
-                endNum = endNum2;
-            } else {
-                CMS.debug("Transferring from the end of the current range");
-                String newValStr = beginNum.subtract(oneNum).toString(radix);
-                repo.setMaxSerial(newValStr);
-                cs.putString(endNumConfig, newValStr);
+            /* We need to synchronise on repo because we peek the next
+             * serial number, then set the max serial of the current or
+             * next range.  If we don't synchronize, we could end up
+             * using serial numbers that were transferred.
+             */
+            synchronized (repo) {
+                if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) {
+                    String nextEndNumStr = cs.getString(nextEndConfig, "");
+                    BigInteger endNum2 = new BigInteger(nextEndNumStr, radix);
+                    CMS.debug("Transferring from the end of on-deck range");
+                    String newValStr = endNum2.subtract(decrement).toString(radix);
+                    repo.setNextMaxSerial(newValStr);
+                    cs.putString(nextEndConfig, newValStr);
+                    beginNum = endNum2.subtract(decrement).add(oneNum);
+                    endNum = endNum2;
+                } else {
+                    CMS.debug("Transferring from the end of the current range");
+                    String newValStr = beginNum.subtract(oneNum).toString(radix);
+                    repo.setMaxSerial(newValStr);
+                    cs.putString(endNumConfig, newValStr);
+                }
             }
 
             if (beginNum == null) {
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
index 367917f..94087c8 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java
@@ -251,49 +251,45 @@ public class CertificateRepository extends Repository
         return nextSerialNumber;
     }
 
-    private Object nextSerialNumberMonitor = new Object();
-
-    public BigInteger getNextSerialNumber() throws
+    public synchronized BigInteger getNextSerialNumber() throws
             EBaseException {
 
         BigInteger nextSerialNumber = null;
         BigInteger randomNumber = null;
 
-        synchronized (nextSerialNumberMonitor) {
-            super.initCacheIfNeeded();
-            CMS.debug("CertificateRepository: getNextSerialNumber  mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers);
+        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 (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 (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);
+            if (nextSerialNumber == null) {
+                CMS.debug("CertificateRepository: in getNextSerialNumber  nextSerialNumber is null");
+                throw new EBaseException( "nextSerialNumber is null" );
+            }
 
-                super.checkRange();
-            } else {
-                nextSerialNumber = super.getNextSerialNumber();
+            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;
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
index 9bc7e2a..c31d376 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java
@@ -185,7 +185,7 @@ public abstract class Repository implements IRepository {
      * @param serial maximum number
      * @exception EBaseException failed to set maximum serial number
      */
-    public void setMaxSerial(String serial) throws EBaseException {
+    public synchronized void setMaxSerial(String serial) throws EBaseException {
         BigInteger maxSerial = null;
         CMS.debug("Repository:setMaxSerial " + serial);
 
@@ -211,7 +211,7 @@ public abstract class Repository implements IRepository {
      * @param serial maximum number in next range
      * @exception EBaseException failed to set maximum serial number in next range
      */
-    public void setNextMaxSerial(String serial) throws EBaseException {
+    public synchronized void setNextMaxSerial(String serial) throws EBaseException {
         BigInteger maxSerial = null;
         CMS.debug("Repository:setNextMaxSerial " + serial);
 
@@ -346,7 +346,7 @@ public abstract class Repository implements IRepository {
      * Returns null if the next number exceeds the current range and
      * there is not a next range.
      */
-    public BigInteger peekNextSerialNumber() throws EBaseException {
+    public synchronized BigInteger peekNextSerialNumber() throws EBaseException {
 
         CMS.debug("Repository:In getTheSerialNumber ");
         if (mLastSerialNo == null)
-- 
1.8.3.1


From 2fb237853c3f730f4f96141d9710d1394de5649d Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 20 Sep 2019 10:59:07 -0500
Subject: [PATCH 13/14] Replaced "Advanced Search" with "Filter" in TPS UI

(cherry picked from commit df3ece37320c2de7db025aa172c2344b07a55483)
---
 base/tps/shared/webapps/tps/ui/tokens.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/base/tps/shared/webapps/tps/ui/tokens.html b/base/tps/shared/webapps/tps/ui/tokens.html
index c2f6227..41d8d94 100644
--- a/base/tps/shared/webapps/tps/ui/tokens.html
+++ b/base/tps/shared/webapps/tps/ui/tokens.html
@@ -30,7 +30,7 @@
          <th class="pki-table-actions" colspan="10">
              <span name="search">
                  <input name="search" type="text" placeholder="Search...">
-                 <a name="filter" href="#tokens-search">Advanced Search</a>
+                 <a name="filter" href="#tokens-search">Filter</a>
              </span>
              <span class="pki-table-buttons">
                  <button name="add">Add</button>
-- 
1.8.3.1


From f2186a497978b778a808e6ad892bfd4180acf8a6 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@localhost.localdomain>
Date: Fri, 20 Sep 2019 20:20:13 -0400
Subject: [PATCH 14/14] Fix Bug 1534013 - Attempting to add new keys using a
 PUT KEY APDU to a token that is loaded only with the default/factory keys
 (Key Version Number 0xFF) returns an APDU with error code 0x6A88.

The token returns 0x6A88 (Referenced data not found) because sending it a key version number of 1, implies that the token already has a key with key version 1. In the case of a token with only default/factory keys with version 0xFF, the key with version #1 is not present.

Giving zero as the key version number in the APDU specifically tells the token to add a new key, with a new key version number. A non-zero key version number instructs the card to replace an existing key. If the existing key is not present then an error occurs.

(cherry picked from commit 19bb64a98881e4651126bcdc544e3fa04ea989ea)
---
 base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index cb08970..7369e58 100644
--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -1558,8 +1558,8 @@ public class SecureChannel {
         byte keyVersion = curVersion;
 
         if (curVersion == (byte) 0xff) {
-            CMS.debug("Setting keyVersion to 1");
-            keyVersion = 0x1;
+            CMS.debug("Setting keyVersion to 0");
+            keyVersion = 0x0;
         }
 
         CMS.debug("keyVersion now set to: " + keyVersion);
-- 
1.8.3.1