diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.0.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.0.patch
new file mode 100644
index 0000000..c25cb79
--- /dev/null
+++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.0.patch
@@ -0,0 +1,119 @@
+From 54a1664ddd7b6b2a8b2a0c7f0eec403507c246c1 Mon Sep 17 00:00:00 2001
+From: Jack Magne <jmagne@test.host.com>
+Date: Thu, 15 Apr 2021 18:42:31 -0400
+Subject: [PATCH 1/2] pkispawn fails against 389-ds 1.4.3.19 #3458 (#3465)
+
+    Add suggested patch from stanislavlevin to solve this issue.
+    Also add f34 to the ipa tests,this time really add the tests.
+    Upon further review, back out of f34 tests until the infractructure
+    supports it.
+
+    Also hardcode tomcat app setting in spec file for the moment to
+    avoid possible glitches on certain platform.
+
+    Co-authored-by: Jack Magne <jmagne@localhost.localdomain>
+
+(cherry picked from commit 9e1ef2557403d1a5117858322af0ae7fc1f4fd44)
+---
+ .../src/com/netscape/cmscore/apps/CMSEngine.java     | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
+index 08e6f8d..db341d5 100644
+--- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
++++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
+@@ -287,9 +287,8 @@ public class CMSEngine implements ICMSEngine {
+ 
+     private static final int PW_OK =0;
+     private static final int PW_BAD_SETUP = 1;
+-    private static final int PW_INVALID_PASSWORD = 2;
++    private static final int PW_INVALID_CREDENTIALS = 2;
+     private static final int PW_CANNOT_CONNECT = 3;
+-    private static final int PW_NO_USER = 4;
+     private static final int PW_MAX_ATTEMPTS = 3;
+ 
+ 
+@@ -365,7 +364,7 @@ public class CMSEngine implements ICMSEngine {
+ 
+         for (String tag : tags) {
+             int iteration = 0;
+-            int result = PW_INVALID_PASSWORD;
++            int result = PW_INVALID_CREDENTIALS;
+             String binddn;
+             String authType;
+             LdapConnInfo connInfo = null;
+@@ -450,10 +449,10 @@ public class CMSEngine implements ICMSEngine {
+                 String passwd = mPasswordStore.getPassword(tag, iteration);
+                 result = testLDAPConnection(tag, connInfo, binddn, passwd);
+                 iteration++;
+-            } while ((result == PW_INVALID_PASSWORD) && (iteration < PW_MAX_ATTEMPTS));
++            } while ((result == PW_INVALID_CREDENTIALS) && (iteration < PW_MAX_ATTEMPTS));
+ 
+             if (result != PW_OK) {
+-                if ((result == PW_NO_USER) && (tag.equals("replicationdb"))) {
++                if ((result == PW_INVALID_CREDENTIALS) && (tag.equals("replicationdb"))) {
+                     System.out.println(
+                         "CMSEngine: init(): password test execution failed for replicationdb" +
+                         "with NO_SUCH_USER.  This may not be a latest instance.  Ignoring ..");
+@@ -473,8 +472,10 @@ public class CMSEngine implements ICMSEngine {
+     public int testLDAPConnection(String name, LdapConnInfo info, String binddn, String pwd) {
+         int ret = PW_OK;
+ 
+-        if (StringUtils.isEmpty(pwd))
+-            return PW_INVALID_PASSWORD;
++        if (StringUtils.isEmpty(pwd)) {
++            return PW_INVALID_CREDENTIALS;
++        }
++
+ 
+         String host = info.getHost();
+         int port = info.getPort();
+@@ -488,12 +489,9 @@ public class CMSEngine implements ICMSEngine {
+         } catch (LDAPException e) {
+             switch (e.getLDAPResultCode()) {
+             case LDAPException.NO_SUCH_OBJECT:
+-                System.out.println("testLDAPConnection: The specified user " + binddn + " does not exist");
+-                ret = PW_NO_USER;
+-                break;
+             case LDAPException.INVALID_CREDENTIALS:
+                 System.out.println("testLDAPConnection: Invalid Password");
+-                ret = PW_INVALID_PASSWORD;
++                ret = PW_INVALID_CREDENTIALS;
+                 break;
+             default:
+                 System.out.println("testLDAPConnection: Unable to connect to " + name + ": " + e);
+-- 
+1.8.3.1
+
+
+From d511e7f255350881333b14ba9b68a879335abddc Mon Sep 17 00:00:00 2001
+From: Christina Fu <cfu@redhat.com>
+Date: Wed, 21 Apr 2021 17:32:42 -0700
+Subject: [PATCH 2/2] bug1949656 CRMF requests with non-SKID extensions
+
+This patch address the issue where if a CRMF request bears any extension
+other than SKID then it fails to process.
+
+fixes https://bugzilla.redhat.com/show_bug.cgi?id=1949656
+
+(cherry picked from commit fe133f9affcde7b56fe69bf0c7daef6930749e74)
+---
+ base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+index f9903c6..b7fdb9e 100644
+--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
++++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+@@ -2286,7 +2286,7 @@ public abstract class EnrollProfile extends BasicProfile
+                         ext = new SubjectKeyIdentifierExtension(false,
+                                 jssext.getExtnValue().toByteArray());
+                     } else {
+-                        new Extension(oid, isCritical, extValue);
++                        ext = new Extension(oid, isCritical, extValue);
+                     }
+ 
+                     extensions.parseExtension(ext);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.1.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.1.patch
new file mode 100644
index 0000000..5ec95bd
--- /dev/null
+++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-bu-6.1.patch
@@ -0,0 +1,760 @@
+From 6b5c8073187a69c09000e88394465228f08d64be Mon Sep 17 00:00:00 2001
+From: Christina Fu <cfu@redhat.com>
+Date: Wed, 28 Apr 2021 16:26:46 -0700
+Subject: [PATCH 1/4] Bug1911472 Revoke via REST API not working when Agent
+ certificate not issued by CA
+
+This patch resolves the issue that when a client cert is issued by an
+external CA, the revocation check inside the CA REST service handler
+(ca/src/org/dogtagpki/server/ca/rest/CertService.java)
+assumes that all client certs are issued by this CA.
+The fix is to check the issuer, and add an option, allowExtCASignedAgentCerts
+to allow for external CA signed agent certs.
+If the issuer is external, and ca.allowExtCASignedAgentCerts is true, then the
+internal cert status check is bypassed and to rely on OCSP enablement
+(enableOCSP) in server.xml.
+The ca.allowExtCASignedAgentCerts config param currently is only used in
+the rest revocation case.  It is not used anywhere else (not even unrevocation).
+
+fixes https://bugzilla.redhat.com/show_bug.cgi?id=1911472
+
+(cherry picked from commit 62f680f98e5bf9a3e6d44279fcc735e65c6d8d91)
+---
+ .../src/com/netscape/ca/CertificateAuthority.java  |  6 ++++
+ .../org/dogtagpki/server/ca/rest/CertService.java  | 38 +++++++++++++++++++---
+ .../netscape/certsrv/ca/ICertificateAuthority.java |  2 ++
+ 3 files changed, 41 insertions(+), 5 deletions(-)
+
+diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
+index bd99344..c519a5a 100644
+--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
++++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
+@@ -333,6 +333,7 @@ public class CertificateAuthority
+ 
+     private boolean mByName = true;
+ 
++    private boolean mAllowExtCASignedAgentCerts = false;
+     private boolean mUseNonces = true;
+     private int mMaxNonces = 100;
+ 
+@@ -454,6 +455,10 @@ public class CertificateAuthority
+         return mPolicy.getPolicyProcessor();
+     }
+ 
++    public boolean allowExtCASignedAgentCerts() {
++        return mAllowExtCASignedAgentCerts;
++    }
++
+     public boolean noncesEnabled() {
+         return mUseNonces;
+     }
+@@ -574,6 +579,7 @@ public class CertificateAuthority
+             if (initSigUnitSucceeded)
+                 checkForNewerCert();
+ 
++            mAllowExtCASignedAgentCerts = mConfig.getBoolean("allowExtCASignedAgentCerts", false);
+             mUseNonces = mConfig.getBoolean("enableNonces", true);
+             mMaxNonces = mConfig.getInteger("maxNumberOfNonces", 100);
+ 
+diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
+index 000ce32..74d3a5d 100644
+--- a/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
++++ b/base/ca/src/org/dogtagpki/server/ca/rest/CertService.java
+@@ -44,6 +44,7 @@ import netscape.security.x509.AlgorithmId;
+ import netscape.security.x509.CRLExtensions;
+ import netscape.security.x509.CRLReasonExtension;
+ import netscape.security.x509.RevocationReason;
++import netscape.security.x509.X500Name;
+ import netscape.security.x509.X509CertImpl;
+ import netscape.security.x509.X509ExtensionException;
+ import netscape.security.x509.X509Key;
+@@ -172,6 +173,8 @@ public class CertService extends PKIService implements CertResource {
+             return unrevokeCert(id);
+         }
+ 
++        String caIssuerDN = null;
++        X500Name caX500DN = null;
+         RevocationProcessor processor;
+         try {
+             processor = new RevocationProcessor("caDoRevoke-agent", getLocale(headers));
+@@ -190,6 +193,8 @@ public class CertService extends PKIService implements CertResource {
+ 
+             processor.setAuthority(authority);
+ 
++            caX500DN = (X500Name) authority.getCACert().getIssuerDN();
++
+         } catch (EBaseException e) {
+             throw new PKIException(e.getMessage());
+         }
+@@ -209,12 +214,35 @@ public class CertService extends PKIService implements CertResource {
+             if (clientCert != null) {
+                 clientSerialNumber = clientCert.getSerialNumber();
+                 clientSubjectDN = clientCert.getSubjectDN().toString();
+-                clientRecord = processor.getCertificateRecord(clientSerialNumber);
+ 
+-                // Verify client cert is not revoked.
+-                // TODO: This should be checked during authentication.
+-                if (clientRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
+-                    throw new UnauthorizedException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
++                X500Name x500issuerDN = (X500Name) clientCert.getIssuerDN();
++                /*
++                 * internal revocation check only to be conducted for certs
++                 * issued by this CA
++                 * For client certs issued by external CAs, TLS mutual auth
++                 * would have completed the authenticaton/verification if
++                 * OCSP was enabled;
++                 * Furthermore, prior to the actual revocation, client cert
++                 * is mapped against the agent group database for proper
++                 * privilege regardless of the issuer.
++                 */
++                if (x500issuerDN.equals(caX500DN)) {
++                    CMS.debug("CertService.revokeCert: client cert issued by this CA");
++                    clientRecord = processor.getCertificateRecord(clientSerialNumber);
++
++                    // Verify client cert is not revoked.
++                    // TODO: This should be checked during authentication.
++                    if (clientRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) {
++                        throw new UnauthorizedException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
++                    }
++                } else {
++                    CMS.debug("CertService.revokeCert: client cert not issued by this CA");
++                    if (!authority.allowExtCASignedAgentCerts()) {
++                        CMS.debug("CertService.revokeCert: allowExtCASignedAgentCerts false;");
++                        throw new UnauthorizedException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"));
++                    } else {
++                        CMS.debug("CertService.revokeCert: allowExtCASignedAgentCerts true;");
++                    }
+                 }
+             }
+ 
+diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+index d941624..c5604e3 100644
+--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
++++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+@@ -136,6 +136,8 @@ public interface ICertificateAuthority extends ISubsystem {
+      */
+     public IPolicyProcessor getPolicyProcessor();
+ 
++    public boolean allowExtCASignedAgentCerts();
++
+     public boolean noncesEnabled();
+ 
+     public Map<Object, Long> getNonces(HttpServletRequest request, String name);
+-- 
+1.8.3.1
+
+
+From a2599f832ed3036f84d507dce36548e0ca1351d0 Mon Sep 17 00:00:00 2001
+From: Jack Magne <jmagne@test.host.com>
+Date: Fri, 30 Apr 2021 20:10:58 -0400
+Subject: [PATCH 2/4] Fix Bug #1955633 - Recovery of Keys migrated to latest
+ version of KRA fail to recover and result in Null Point Exception
+ [rhel-7.9.z]
+
+This is a very simple fix to prevent the reported null pointer exception.
+Checking in directly using the trivial checkin policy.
+
+(cherry picked from commit c792a8545aecdb4ec17b1a18a401fcff288f877e)
+---
+ base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
+index 556c4a7..fd8fff9 100644
+--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
++++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/KeyRecord.java
+@@ -506,6 +506,10 @@ public class KeyRecord implements IDBObj, IKeyRecord {
+     }
+ 
+     public Boolean isEncrypted() throws EBaseException {
++        if(mMetaInfo == null) {
++            return null;
++        }
++
+         String encrypted = (String) mMetaInfo.get(KeyRecordParser.OUT_PL_ENCRYPTED);
+         if (encrypted == null)
+             return null;
+-- 
+1.8.3.1
+
+
+From 201cef17ad2a6fcc84277b9a62c7e986212c0622 Mon Sep 17 00:00:00 2001
+From: jmagne <jmagne@redhat.com>
+Date: Thu, 6 May 2021 17:17:37 -0700
+Subject: [PATCH 3/4] Fix: Bug 1942687 - TPS not populating Token Policy, or
+ switching PIN_RESET=YES to NO . (#3510)
+
+Now the behavior will be the following:
+
+    When a new token entry gets created in the token db, due to a token operation such
+    as format or enrollment, the db entry will get populated with the contents of the
+    CS.cfg value:
+    ex:
+    tokendb.defaultPolicy=RE_ENROLL=YES;RENEW=NO;FORCE_FORMAT=NO;PIN_RESET=NO;RESET_PIN_RESET_TO_NO=NO
+
+    Now the value of RESET_PIN_RESET_TO_NO is actually observed.
+    If this value is set to YES and pin reset is allowed, after a successful pin reset,
+    the value of PIN_RESET will be set to NO, thus not allowing further pin resets on this
+    token, until the value is manually changed in the token db entry.
+
+    Also, the class itself has been simplified to allow the cuid token number at constructor
+    time. Now if another token is desired , we must instantiate a new TPSTokenPolicy object for
+    that additional token.
+
+Co-authored-by: Jack Magne <jmagne@test.host.com>
+(cherry picked from commit 5f25323a9098af496196dbff0e7f0e89ee7621de)
+---
+ .../org/dogtagpki/server/tps/TPSTokenPolicy.java   | 133 ++++++++++++++++++---
+ .../src/org/dogtagpki/server/tps/TPSTokendb.java   |   4 +
+ .../server/tps/processor/TPSEnrollProcessor.java   |  23 ++--
+ .../server/tps/processor/TPSPinResetProcessor.java |  14 ++-
+ .../server/tps/processor/TPSProcessor.java         |  21 ++++
+ 5 files changed, 165 insertions(+), 30 deletions(-)
+
+diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java
+index 4d7af48..685319e 100644
+--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java
++++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java
+@@ -40,18 +40,31 @@ public class TPSTokenPolicy {
+     private boolean force_format = false;
+     private boolean pin_reset = true;
+     private boolean reset_pin_reset_to_no = false;
++    private String cuid = null;
+ 
+-    public TPSTokenPolicy (TPSSubsystem tps) throws TPSException {
++    //Construct with a single token in mind. Load the token's config from
++    //the db after the default. All operations will then be on this token.
++    //
++    public TPSTokenPolicy (TPSSubsystem tps,String cuid) throws TPSException {
+         if (tps == null) {
+             String msg = "TPSTokenPolicy.TPSTokenPolicy: tps cannnot be null";
+             CMS.debug(msg);
+             throw new TPSException(msg);
+         }
++        if (cuid == null) {
++            String msg = "TPSTokenPolicy.TPSTokenPolicy: cuid cannnot be null";
++            CMS.debug(msg);
++            throw new TPSException(msg);
++        }
++
+         this.tps = tps;
+-        // init from config first
++        // Get the CS.cfg defaults first
+         String policySetString = getDefaultPolicySetString();
+         parsePolicySetString(policySetString);
+ 
++        this.cuid = cuid;
++        //Read from the token db once and write at the end if needed
++        getUpdatedPolicy();
+     }
+ 
+     public String getDefaultPolicySetString() {
+@@ -92,6 +105,41 @@ public class TPSTokenPolicy {
+         }
+     }
+ 
++    /* Take the current state of the policyt variables, create a new policy string,
++     * and write the new value for the provided token cuid.
++     */
++    public void updatePolicySet()  throws TPSException {
++   
++        String method = "TPSTokenPolicy.updatePolicySet: "; 
++        String msg = method +  "Can't update token policy string to database.";
++
++        TokenRecord tokenRecord = null;
++        String policySetString = null;
++        try {
++            tokenRecord = tps.tdb.tdbGetTokenEntry(this.cuid);
++        } catch (Exception e) {
++            throw new TPSException(e.toString() + " " + msg);
++        }
++
++        String newPolicy = "";
++
++        newPolicy += "RE_ENROLL=" + getFromBool(re_enroll);
++        newPolicy += ";RENEW=" + getFromBool(renew);
++        newPolicy += ";FORCE_FORMAT=" + getFromBool(force_format);
++        newPolicy += ";PIN_RESET=" + getFromBool(pin_reset);
++        newPolicy += ";RESET_PIN_RESET_TO_NO=" + getFromBool(reset_pin_reset_to_no);
++        newPolicy += ";RENEW_KEEP_OLD_ENC_CERTS=" + getFromBool(renew_keep_old_enc_certs);  
++        
++        CMS.debug(method + "newPolicy: " + newPolicy); 
++        tokenRecord.setPolicy(newPolicy);
++        try {
++            tps.tdb.tdbUpdateTokenEntry(tokenRecord);
++        } catch(Exception e) {
++            throw new TPSException(e.toString() + " " + msg);
++        }
++
++    }
++
+ /*
+  * getBool translates string to boolean:
+  * true: "YES", "yes", "TRUE", "true"
+@@ -114,12 +162,19 @@ public class TPSTokenPolicy {
+         return defaultBool;
+     }
+ 
+-    private void getUpdatedPolicy(String cuid) {
++    private String getFromBool(boolean value) {
++        if(value == true) 
++            return "YES";
++
++        return "NO";
++    } 
++
++    private void getUpdatedPolicy() {
+         // note: default policy already initialized in the constructor
+         TokenRecord tokenRecord = null;
+         String policySetString = null;
+         try {
+-            tokenRecord = tps.tdb.tdbGetTokenEntry(cuid);
++            tokenRecord = tps.tdb.tdbGetTokenEntry(this.cuid);
+         } catch (Exception e) {
+             // just take the default;
+             return;
+@@ -129,38 +184,82 @@ public class TPSTokenPolicy {
+         parsePolicySetString(policySetString);
+     }
+ 
+-    public boolean isAllowedTokenPinReset(String cuid) {
+-        getUpdatedPolicy(cuid);
++    // Note we only want to allow one cuid to be operated upon
++    // by this class, since we are going to allow values to be changed
++    // as well as written.
++    
++    public boolean isAllowedTokenPinReset() {
++
++        return reset_pin_reset_to_no;
++    }
++
++    // Add better named version to get the value
++    // reset_pin_reset_to_no
++   
++    public boolean isAllowedResetPinResetToNo() {
+ 
+         return reset_pin_reset_to_no;
++
+     }
+ 
+-    public boolean isAllowedPinReset(String cuid) {
+-        getUpdatedPolicy(cuid);
++    public boolean isAllowedPinReset() {
+ 
+         return pin_reset;
+     }
+ 
+-    public boolean isForceTokenFormat(String cuid) {
+-        getUpdatedPolicy(cuid);
++    public boolean isForceTokenFormat() {
+ 
+         return force_format;
+     }
+ 
+-    public boolean isAllowdTokenReenroll(String cuid) {
+-        getUpdatedPolicy(cuid);
++    public boolean isAllowdTokenReenroll() {
+ 
+         return re_enroll;
+     }
+ 
+-    public boolean isAllowdRenewSaveOldEncCerts(String cuid) {
+-        getUpdatedPolicy(cuid);
++    public boolean isAllowdRenewSaveOldEncCerts() {
++
+         return renew_keep_old_enc_certs;
+     }
+ 
+-    public boolean isAllowdTokenRenew(String cuid) {
+-        getUpdatedPolicy(cuid);
++    public boolean isAllowdTokenRenew() {
+ 
+         return renew;
+     }
+-}
+\ No newline at end of file
++
++    public void setAllowedTokenPinReset(boolean value) {
++
++        reset_pin_reset_to_no = value;
++    }
++
++    public void setAllowedResetPinResetToNo(boolean value) {
++
++        reset_pin_reset_to_no = value;
++    }
++
++    public void setAllowedPinReset(boolean value) {
++
++        pin_reset = value;
++    }
++
++    public void setForceTokenFormat(boolean value) {
++
++        force_format = value;
++    }
++
++    public void setAllowdTokenReenroll(boolean value) {
++
++        re_enroll = value;
++    }
++
++    public void setAllowdRenewSaveOldEncCerts(boolean value) {
++
++        renew_keep_old_enc_certs = value;
++    }
++
++    public void setAllowdTokenRenew(boolean value) {
++
++        renew = value;
++    }
++
++}
+diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+index 7434502..b58c24f 100644
+--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
++++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+@@ -200,9 +200,13 @@ public class TPSTokendb {
+ 
+     public void tdbAddTokenEntry(TokenRecord tokenRecord, TokenStatus status)
+             throws Exception {
++
++        String method = "TPSTokendb.tdbAddTokenEntry: ";
+         tokenRecord.setTokenStatus(status);
+ 
+         tps.tokenDatabase.addRecord(tokenRecord.getId(), tokenRecord);
++
++        CMS.debug(method + "Added tokenRecord.");
+     }
+ 
+     public void tdbUpdateTokenEntry(TokenRecord tokenRecord)
+diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+index 5175344..2d8c89f 100644
+--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+@@ -95,7 +95,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
+         String logMsg = null;
+         String auditInfo = null;
+         TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+-        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
++        TPSTokenPolicy tokenPolicy = null; 
+         IConfigStore configStore = CMS.getConfigStore();
+         String configName;
+ 
+@@ -128,12 +128,13 @@ public class TPSEnrollProcessor extends TPSProcessor {
+         tokenRecord = isTokenRecordPresent(appletInfo);
+ 
+         if (tokenRecord != null) {
+-            CMS.debug(method + " found token...");
++            CMS.debug(method + " found token... policy: " + tokenRecord.getPolicy());
+             isTokenPresent = true;
+         } else {
+             CMS.debug(method + " token does not exist in tokendb... create one in memory");
+             tokenRecord = new TokenRecord();
+             tokenRecord.setId(appletInfo.getCUIDhexStringPlain());
++            fillTokenRecordDefaultPolicy(tokenRecord);
+         }
+ 
+         fillTokenRecord(tokenRecord, appletInfo);
+@@ -332,13 +333,14 @@ public class TPSEnrollProcessor extends TPSProcessor {
+                         " to " + newState);
+             }
+ 
+-            do_force_format = tokenPolicy.isForceTokenFormat(cuid);
++            tokenPolicy = new TPSTokenPolicy(tps,cuid);
++            do_force_format = tokenPolicy.isForceTokenFormat();
+             if (do_force_format)
+                 CMS.debug(method + " Will force format first due to policy.");
+ 
+             if (!isExternalReg &&
+-                    !tokenPolicy.isAllowdTokenReenroll(cuid) &&
+-                    !tokenPolicy.isAllowdTokenRenew(cuid)) {
++                    !tokenPolicy.isAllowdTokenReenroll() &&
++                    !tokenPolicy.isAllowdTokenRenew()) {
+                 CMS.debug(method + " token renewal or reEnroll disallowed ");
+                 logMsg = "Operation renewal or reEnroll for CUID " + cuid +
+                         " Disabled";
+@@ -524,7 +526,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
+         // at this point, enrollment, renewal, or recovery have been processed accordingly;
+         if (!isExternalReg &&
+                 status == TPSStatus.STATUS_RENEWAL_IS_PROCESSED &&
+-                tokenPolicy.isAllowdTokenRenew(cuid)) {
++                tokenPolicy.isAllowdTokenRenew()) {
+             renewed = true;
+             CMS.debug(method + " renewal happened.. ");
+         }
+@@ -1110,7 +1112,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
+         IConfigStore configStore = CMS.getConfigStore();
+         String configName;
+         TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+-        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
++        TPSTokenPolicy tokenPolicy = null;
+ 
+         ArrayList<TokenRecord> tokenRecords = null;
+         try {
+@@ -1157,7 +1159,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
+ 
+                 } else if (tokenRecord.getTokenStatus() == TokenStatus.ACTIVE) {
+                     // current token is already active; renew if allowed
+-                    if (tokenPolicy.isAllowdTokenRenew(aInfo.getCUIDhexStringPlain())) {
++                    tokenPolicy = new TPSTokenPolicy(tps,aInfo.getCUIDhexStringPlain());
++                    if (tokenPolicy.isAllowdTokenRenew()) {
+                         return processRenewal(certsInfo, channel, aInfo, tokenRecord);
+                     } else {
+                         logMsg = "token is already active; can't renew because renewal is not allowed; will re-enroll if allowed";
+@@ -1658,9 +1661,9 @@ public class TPSEnrollProcessor extends TPSProcessor {
+ 
+         //See if policy calls for this feature
+ 
+-        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
++        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps,tokenRecord.getId());
+ 
+-        boolean recoverOldEncCerts = tokenPolicy.isAllowdRenewSaveOldEncCerts(tokenRecord.getId());
++        boolean recoverOldEncCerts = tokenPolicy.isAllowdRenewSaveOldEncCerts();
+         CMS.debug(method + " Recover Old Encryption Certs for Renewed Certs: " + recoverOldEncCerts);
+         if (oldEncCertsToRecover.size() > 0 && recoverOldEncCerts == true) {
+             CMS.debug("About to attempt to recover old encryption certs just renewed.");
+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 805af20..2ee9186 100644
+--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
+@@ -121,14 +121,14 @@ public class TPSPinResetProcessor extends TPSProcessor {
+                     TPSStatus.STATUS_ERROR_UNKNOWN_TOKEN);
+         }
+ 
+-        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
+-
+         fillTokenRecord(tokenRecord, appletInfo);
+         session.setTokenRecord(tokenRecord);
+ 
+         String cuid = appletInfo.getCUIDhexStringPlain();
+         String tokenType = null;
+ 
++        TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps,cuid);
++
+         if(isExternalReg) {
+             CMS.debug(method + " isExternalReg: ON");
+ 
+@@ -309,7 +309,7 @@ public class TPSPinResetProcessor extends TPSProcessor {
+ 
+         }
+ 
+-        boolean pinResetAllowed = tokenPolicy.isAllowedPinReset(tokenRecord.getId());
++        boolean pinResetAllowed = tokenPolicy.isAllowedPinReset();
+ 
+         CMS.debug(method + ": PinResetPolicy: Pin Reset Allowed:  " + pinResetAllowed);
+         logMsg = method + " PinReset Policy forbids pin reset operation.";
+@@ -362,6 +362,14 @@ public class TPSPinResetProcessor extends TPSProcessor {
+             throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_UPDATE_TOKENDB_FAILED);
+         }
+ 
++        //If policy tells us to disallow pin reset after
++        //a successfull pin reset, do so.
++        //
++        if(tokenPolicy.isAllowedResetPinResetToNo()) {
++            tokenPolicy.setAllowedPinReset(false); 
++            tokenPolicy.updatePolicySet();
++            CMS.debug(method + ": Updating pin reset policy to NO.");
++        }
+         CMS.debug(method + ": Token Pin successfully reset!");
+ 
+     }
+diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+index baf0671..cadab1d 100644
+--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+@@ -1531,6 +1531,26 @@ public class TPSProcessor {
+ 
+     }
+ 
++    protected void fillTokenRecordDefaultPolicy(TokenRecord tokenRecord) throws TPSException {
++
++        String method = "TPSProcessor.fillTokenRecordDefaultPolicy: ";
++ 
++        try {
++            IConfigStore configStore = CMS.getConfigStore();
++
++            String config = "tokendb.defaultPolicy";
++            String defaultPolicy = configStore.getString(config);
++
++            CMS.debug(method + " default token policy: " + defaultPolicy);
++
++            tokenRecord.setPolicy(defaultPolicy);
++        } catch (Exception e) {
++            CMS.debug(method + "Problem with  adding the default policy to the token.");
++            throw new TPSException(e.toString(),TPSStatus.STATUS_ERROR_MISCONFIGURATION);
++        }
++
++    }
++
+     protected TokenRecord isTokenRecordPresent(AppletInfo appletInfo) throws TPSException {
+ 
+         if (appletInfo == null) {
+@@ -2353,6 +2373,7 @@ public class TPSProcessor {
+             try {
+                 tps.tdb.tdbAddTokenEntry(tokenRecord, TokenStatus.UNFORMATTED);
+                 tps.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord, session.getIpAddress(), logMsg, "success");
++                fillTokenRecordDefaultPolicy(tokenRecord);
+                 CMS.debug("TPSProcessor.format: token added");
+             } catch (Exception e) {
+                 logMsg = logMsg + ":" + e.toString();
+-- 
+1.8.3.1
+
+From e83bcc4f045bd6ad43798ff38306ab3c4bc4a52d Mon Sep 17 00:00:00 2001
+From: Chris Kelley <ckelley@redhat.com>
+Date: Fri, 7 May 2021 14:05:18 +0100
+Subject: [PATCH 4/4] Prevent debug exception when product version not found
+
+Resolves: #1914587
+(cherry picked from commit d86eefb661766342a4473c699dc6687986420161)
+---
+ base/common/src/com/netscape/certsrv/apps/CMS.java | 18 ++++++++
+ .../netscape/cms/servlet/csadmin/GetStatus.java    | 51 +++-------------------
+ 2 files changed, 23 insertions(+), 46 deletions(-)
+
+diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java
+index 1dace42..e852043 100644
+--- a/base/common/src/com/netscape/certsrv/apps/CMS.java
++++ b/base/common/src/com/netscape/certsrv/apps/CMS.java
+@@ -17,7 +17,9 @@
+ // --- END COPYRIGHT BLOCK ---
+ package com.netscape.certsrv.apps;
+ 
++import java.io.File;
+ import java.math.BigInteger;
++import java.nio.file.Files;
+ import java.security.NoSuchAlgorithmException;
+ import java.security.cert.Certificate;
+ import java.security.cert.CertificateEncodingException;
+@@ -135,6 +137,7 @@ public final class CMS {
+     public static final String SUBSYSTEM_SELFTESTS = ISelfTestSubsystem.ID;
+     public static final int PRE_OP_MODE = 0;
+     public static final int RUNNING_MODE = 1;
++    private static final String PRODUCT_NAME_FILE = "/usr/share/pki/CS_SERVER_VERSION";
+ 
+     /**
+      * Private constructor.
+@@ -1519,6 +1522,21 @@ public final class CMS {
+         _engine.sleepOneMinute();
+     }
+ 
++    /**
++     * Return the product name from /usr/share/pki/CS_SERVER_VERSION
++     * which is provided by the server theme package.
++     */
++    public static String getProductName() throws Exception {
++
++        File file = new File(PRODUCT_NAME_FILE);
++
++        if (!file.exists()) {
++            return null;
++        }
++
++        return new String(Files.readAllBytes(file.toPath())).trim();
++    }
++
+     public static boolean isExcludedLdapAttrsEnabled() {
+         return _engine.isExcludedLdapAttrsEnabled();
+     }
+diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java
+index 1cb8a4c..8f6d340 100644
+--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java
++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetStatus.java
+@@ -18,7 +18,6 @@
+ package com.netscape.cms.servlet.csadmin;
+ 
+ import java.io.IOException;
+-import java.io.FileInputStream;
+ import java.util.Locale;
+ 
+ import javax.servlet.ServletConfig;
+@@ -26,6 +25,7 @@ import javax.servlet.ServletException;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+ 
++import org.apache.commons.lang.StringUtils;
+ import org.w3c.dom.Node;
+ 
+ import com.netscape.certsrv.apps.CMS;
+@@ -35,8 +35,6 @@ import com.netscape.cms.servlet.base.CMSServlet;
+ import com.netscape.cms.servlet.base.UserInfo;
+ import com.netscape.cms.servlet.common.CMSRequest;
+ import com.netscape.cmsutil.xml.XMLObject;
+-import org.apache.commons.io.IOUtils;
+-import org.apache.commons.lang.StringUtils;
+ 
+ public class GetStatus extends CMSServlet {
+ 
+@@ -44,8 +42,6 @@ public class GetStatus extends CMSServlet {
+      *
+      */
+     private static final long serialVersionUID = -2852842030221659847L;
+-    // File below will be a member of a pki theme package.
+-    private static final String productVersionFILE = "/usr/share/pki/CS_SERVER_VERSION";
+ 
+     public GetStatus() {
+         super();
+@@ -85,13 +81,13 @@ public class GetStatus extends CMSServlet {
+             xmlObj.addItemToContainer(root, "Type", type);
+             xmlObj.addItemToContainer(root, "Status", status);
+             xmlObj.addItemToContainer(root, "Version", version);
++
+             // File below will be a member of a pki theme package.
+-            String productVersion = getProductVersion(productVersionFILE);
++            String productName = CMS.getProductName();
+ 
+-            if(!StringUtils.isEmpty(productVersion)) {
+-                xmlObj.addItemToContainer(root,"ProductVersion", productVersion);
++            if (!StringUtils.isEmpty(productName)) {
++                xmlObj.addItemToContainer(root, "ProductVersion", productName);
+             }
+-
+             byte[] cb = xmlObj.toByteArray();
+ 
+             outputResult(httpResp, "application/xml", cb);
+@@ -119,41 +115,4 @@ public class GetStatus extends CMSServlet {
+         }
+         return locale;
+     }
+-
+-    /**
+-     * Return the product version if the file: /usr/share/pki/CS_SERVER_VERSION
+-     * exists.
+-     *
+-     * Caller only cares if there is a string or not, exceptions handled here.
+-     */
+-    private String getProductVersion(String versionFilePathName) {
+-        String version = null;
+-        FileInputStream inputStream = null;
+-
+-        if(StringUtils.isEmpty(versionFilePathName)) {
+-            CMS.debug("Missing product version file path!");
+-            return null;
+-        }
+-
+-        try {
+-            inputStream = new FileInputStream(versionFilePathName);
+-            String contents = IOUtils.toString(inputStream);
+-
+-            if(contents != null) {
+-                CMS.debug("Returning product version: " + version);
+-                version = contents.trim();
+-            }
+-        } catch (Exception e) {
+-            CMS.debug("Failed to read product version String. " + e);
+-        }
+-        finally {
+-            if(inputStream != null) {
+-                try {
+-                    inputStream.close();
+-                } catch (IOException e) {
+-                }
+-            }
+-        }
+-        return version;
+-    }
+ }
+-- 
+1.8.3.1
+
diff --git a/SPECS/pki-core.spec b/SPECS/pki-core.spec
index afc93e3..452f790 100644
--- a/SPECS/pki-core.spec
+++ b/SPECS/pki-core.spec
@@ -65,13 +65,13 @@
 Name:             pki-core
 %if 0%{?rhel}
 Version:                10.5.18
-%define redhat_release  12
+%define redhat_release  14
 %define redhat_stage    0
 #%define default_release %{redhat_release}.%{redhat_stage}
 %define default_release %{redhat_release}
 %else
 Version:                10.5.18
-%define fedora_release  12
+%define fedora_release  14
 %define fedora_stage    0
 #%define default_release %{fedora_release}.%{fedora_stage}
 %define default_release %{fedora_release}
@@ -217,6 +217,8 @@ Patch7:  pki-core-Fix-auditProfileUpgrade.patch
 Patch8:  pki-core-Fix-AddProfileCaAuditSigningCert.patch
 Patch9:  pki-core-rhel-7-9-rhcs-9-7-bu-4.patch
 Patch10: pki-core-Change-var-TPS-to-tps.patch
+Patch11: pki-core-rhel-7-9-rhcs-9-7-bu-6.0.patch
+Patch12: pki-core-rhel-7-9-rhcs-9-7-bu-6.1.patch
 
 # Obtain version phase number (e. g. - used by "alpha", "beta", etc.)
 #
@@ -828,6 +830,8 @@ This package is a part of the PKI Core used by the Certificate System.
 %patch8 -p1
 %patch9 -p1
 %patch10 -p1
+%patch11 -p1
+%patch12 -p1
 
 %clean
 %{__rm} -rf %{buildroot}
@@ -1365,6 +1369,38 @@ fi
 %endif # %{with server}
 
 %changelog
+* Thu May 13 2021 Dogtag Team <pki-devel@redhat.com> 10.5.18-14
+- ##########################################################################
+- # RHEL 7.9:
+- ##########################################################################
+- Bugzilla Bug 1911472 - Revoke via REST API not working when Agent
+  certificate not issued by CA [rhel-7.9.z] (cfu)
+- Bugzilla Bug 1914587 - RHEL IPA PKI - Failed to read product version
+  String.java.io.FileNotFoundException (ckelley)
+- Bugzilla Bug 1942687 - TPS not populating Token Policy, or switching
+  PIN_RESET=YES to NO [rhel-7.9.z] (jmagne)
+- Bugzilla Bug 1955633 - Recovery of Keys migrated to latest version of KRA
+  fail to recover and result in Null Point Exception [rhel-7.9.z] (jmagne)
+- ##########################################################################
+- # RHCS 9.7:
+- ##########################################################################
+- Bugzilla Bug #1774177 - Rebase redhat-pki, redhat-pki-theme, pki-core, and
+  pki-console to 10.5.18 in RHCS 9.7 (Batch Update 6)
+
+* Thu Apr 22 2021 Dogtag Team <pki-devel@redhat.com> 10.5.18-13
+- ##########################################################################
+- # RHEL 7.9:
+- ##########################################################################
+- Bugzilla Bug 1949136 - PKI instance creation failed with new 389-ds-base
+  build (jmagne)
+- Bugzilla Bug 1949656 - CRMF requests with extensions other than SKID cannot
+  be processed (cfu)
+- ##########################################################################
+- # RHCS 9.7:
+- ##########################################################################
+- Bugzilla Bug #1774177 - Rebase redhat-pki, redhat-pki-theme, pki-core, and
+  pki-console to 10.5.18 in RHCS 9.7 (Batch Update 6)
+
 * Wed Feb 24 2021 Dogtag Team <pki-devel@redhat.com> 10.5.18-12
 - Change variable 'TPS' to 'tps'
 - ##########################################################################
@@ -1651,7 +1687,7 @@ fi
 - ##########################################################################
 - # RHEL 7.7:
 - ##########################################################################
-- Bugzilla Bug #1633422 - Rebase pki-core from 10.5.1 to 10.5.16 (RHEL) 
+- Bugzilla Bug #1633422 - Rebase pki-core from 10.5.1 to 10.5.16 (RHEL)
 - ##########################################################################
 - # RHCS 9.5:
 - ##########################################################################