Blob Blame History Raw
From 9c24a655511c911c8acc724a45f79b3ea4986b9f Mon Sep 17 00:00:00 2001
From: Dinesh Prasanth M K <dmoluguw@redhat.com>
Date: Thu, 1 Nov 2018 16:29:11 -0400
Subject: [PATCH 01/13] Add --force flag to pki-destroy

Resolves: Bug 1372056
Ticket: https://pagure.io/dogtagpki/issue/1172

List of changes with this commit:
- Adds new flag `--force` to pkidestroy to force remove a subsystem
- Use `os.path.join()` instead of appending '/' between path names
- Remove the `pki_database_path` dir instead of removing contents of the dir
    - This is moved to `security_database.py` instead of `configuration.py`
- pkidestroy and pkispawn logs are owned by `root` instead of configured pkiuser

Signed-off-by: Dinesh Prasanth M K<dmoluguw@redhat.com>
(cherry picked from commit 926c26e10db1b3fde8f24802d7a77419d0f2f28d)
---
 .../python/pki/server/deployment/pkihelper.py      |  6 +-
 .../server/deployment/scriptlets/configuration.py  |  7 +-
 .../server/deployment/scriptlets/finalization.py   |  5 +-
 .../server/deployment/scriptlets/initialization.py | 92 ++++++++++++----------
 .../deployment/scriptlets/security_databases.py    |  8 +-
 .../deployment/scriptlets/webapp_deployment.py     |  2 +-
 base/server/sbin/pkidestroy                        | 44 ++++++++---
 7 files changed, 96 insertions(+), 68 deletions(-)

diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index 79f1e57..e1b9a02 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -947,8 +947,10 @@ class Instance:
         rv = []
         try:
             for subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
-                path = self.mdict['pki_instance_path'] + \
-                    "/" + subsystem.lower()
+                path = os.path.join(
+                    self.mdict['pki_instance_path'],
+                    subsystem.lower()
+                )
                 if os.path.exists(path) and os.path.isdir(path):
                     rv.append(subsystem)
         except OSError as exc:
diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py
index 1b62445..7bc0023 100644
--- a/base/server/python/pki/server/deployment/scriptlets/configuration.py
+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py
@@ -1274,9 +1274,4 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             raise RuntimeError("server failed to restart")
 
     def destroy(self, deployer):
-
-        config.pki_log.info(log.CONFIGURATION_DESTROY_1, __name__,
-                            extra=config.PKI_INDENTATION_LEVEL_1)
-        if len(deployer.instance.tomcat_instance_subsystems()) == 1:
-            if deployer.directory.exists(deployer.mdict['pki_client_dir']):
-                deployer.directory.delete(deployer.mdict['pki_client_dir'])
+        pass
diff --git a/base/server/python/pki/server/deployment/scriptlets/finalization.py b/base/server/python/pki/server/deployment/scriptlets/finalization.py
index e62051f..3c7e118 100644
--- a/base/server/python/pki/server/deployment/scriptlets/finalization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/finalization.py
@@ -68,19 +68,18 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                             deployer.mdict['pki_subsystem'],
                             deployer.mdict['pki_instance_name'],
                             extra=config.PKI_INDENTATION_LEVEL_0)
-        deployer.file.modify(deployer.mdict['pki_spawn_log'], silent=True)
 
     def destroy(self, deployer):
 
         config.pki_log.info(log.FINALIZATION_DESTROY_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        deployer.file.modify(deployer.mdict['pki_destroy_log'], silent=True)
         # If this is the last remaining PKI instance, ALWAYS remove the
         # link to start configured PKI instances upon system reboot
         if deployer.mdict['pki_subsystem'] in config.PKI_SUBSYSTEMS and\
            deployer.instance.pki_instance_subsystems() == 0:
             deployer.systemd.disable()
-        # Start this Tomcat PKI Process
+
+        # Start this Tomcat PKI Process back if there are any subsystems still existing
         if len(deployer.instance.tomcat_instance_subsystems()) >= 1:
             deployer.systemd.start()
         config.pki_log.info(log.PKIDESTROY_END_MESSAGE_2,
diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py
index 9528ec5..efd1536 100644
--- a/base/server/python/pki/server/deployment/scriptlets/initialization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py
@@ -86,45 +86,53 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         deployer.configuration_file.verify_ds_secure_connection_data()
 
     def destroy(self, deployer):
-
-        # begin official logging
-        config.pki_log.info(log.PKIDESTROY_BEGIN_MESSAGE_2,
-                            deployer.mdict['pki_subsystem'],
-                            deployer.mdict['pki_instance_name'],
-                            extra=config.PKI_INDENTATION_LEVEL_0)
-        config.pki_log.info(log.INITIALIZATION_DESTROY_1, __name__,
-                            extra=config.PKI_INDENTATION_LEVEL_1)
-        # verify that this type of "subsystem" currently EXISTS
-        # for this "instance"
-        deployer.instance.verify_subsystem_exists()
-        # verify that the command-line parameters match the values
-        # that are present in the corresponding configuration file
-        deployer.configuration_file.verify_command_matches_configuration_file()
-        # establish 'uid' and 'gid'
-        deployer.identity.set_uid(deployer.mdict['pki_user'])
-        deployer.identity.set_gid(deployer.mdict['pki_group'])
-        # get ports to remove selinux context
-        deployer.configuration_file.populate_non_default_ports()
-
-        # remove kra connector from CA if this is a KRA
-        deployer.kra_connector.deregister()
-
-        # remove tps connector from TKS if this is a TPS
-        deployer.tps_connector.deregister()
-
-        # de-register instance from its Security Domain
-        #
-        #     NOTE:  Since the security domain of an instance must be up
-        #            and running in order to be de-registered, this step
-        #            must be done PRIOR to instance shutdown because this
-        #            instance's security domain may be a part of a
-        #            tightly-coupled shared instance.
-        #
-
-        # Previously we obtained the token through a command line interface
-        # no longer supported. Thus we assume no token and the deregister op will
-        # take place without the token using an alternate method.
-
-        deployer.security_domain.deregister(None)
-        # ALWAYS Stop this Tomcat PKI Process
-        deployer.systemd.stop()
+        try:
+            # begin official logging
+            config.pki_log.info(log.PKIDESTROY_BEGIN_MESSAGE_2,
+                                deployer.mdict['pki_subsystem'],
+                                deployer.mdict['pki_instance_name'],
+                                extra=config.PKI_INDENTATION_LEVEL_0)
+            config.pki_log.info(log.INITIALIZATION_DESTROY_1, __name__,
+                                extra=config.PKI_INDENTATION_LEVEL_1)
+            # verify that this type of "subsystem" currently EXISTS
+            # for this "instance"
+            deployer.instance.verify_subsystem_exists()
+            # verify that the command-line parameters match the values
+            # that are present in the corresponding configuration file
+            deployer.configuration_file.verify_command_matches_configuration_file()
+            # establish 'uid' and 'gid'
+            deployer.identity.set_uid(deployer.mdict['pki_user'])
+            deployer.identity.set_gid(deployer.mdict['pki_group'])
+            # get ports to remove selinux context
+            deployer.configuration_file.populate_non_default_ports()
+
+            # remove kra connector from CA if this is a KRA
+            deployer.kra_connector.deregister()
+
+            # remove tps connector from TKS if this is a TPS
+            deployer.tps_connector.deregister()
+
+            # de-register instance from its Security Domain
+            #
+            #     NOTE:  Since the security domain of an instance must be up
+            #            and running in order to be de-registered, this step
+            #            must be done PRIOR to instance shutdown because this
+            #            instance's security domain may be a part of a
+            #            tightly-coupled shared instance.
+            #
+
+            # Previously we obtained the token through a command line interface
+            # no longer supported. Thus we assume no token and the deregister op will
+            # take place without the token using an alternate method.
+
+            deployer.security_domain.deregister(None)
+
+        except Exception as e:  # pylint: disable=broad-except
+            config.pki_log.error(str(e))
+            # If it is a normal destroy, pass any exception
+            if not deployer.mdict['pki_force_destroy']:
+                raise
+
+        finally:
+            # ALWAYS Stop this Tomcat PKI Process
+            deployer.systemd.stop()
diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index b8550ad..02f4713 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -259,7 +259,9 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         config.pki_log.info(log.SECURITY_DATABASES_DESTROY_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
         if len(deployer.instance.tomcat_instance_subsystems()) == 0:
-            deployer.file.delete(deployer.mdict['pki_cert_database'])
-            deployer.file.delete(deployer.mdict['pki_key_database'])
-            deployer.file.delete(deployer.mdict['pki_secmod_database'])
+
+            if deployer.directory.exists(deployer.mdict['pki_client_dir']):
+                deployer.directory.delete(deployer.mdict['pki_client_dir'])
+
+            deployer.directory.delete(deployer.mdict['pki_database_path'])
             deployer.file.delete(deployer.mdict['pki_shared_password_conf'])
diff --git a/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py
index bfa3c32..8957d9d 100644
--- a/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py
+++ b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py
@@ -70,7 +70,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         config.pki_log.info(log.WEBAPP_DEPLOYMENT_DESTROY_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
 
-        # Delete <instance>/conf/Catalina/localhost/<subsystem>.xml
+        # Delete <instance>/Catalina/localhost/<subsystem>.xml
         deployer.file.delete(
             os.path.join(
                 deployer.mdict['pki_instance_configuration_path'],
diff --git a/base/server/sbin/pkidestroy b/base/server/sbin/pkidestroy
index 58f0541..4692e36 100755
--- a/base/server/sbin/pkidestroy
+++ b/base/server/sbin/pkidestroy
@@ -95,6 +95,13 @@ def main(argv):
         nargs=1, metavar='<security domain password file>',
         help='security domain password file path')
 
+    parser.optional.add_argument(
+        '--force',
+        dest='pki_force_destroy',
+        action='store_true',
+        help='force removal of subsystem'
+    )
+
     args = parser.process_command_line_arguments()
 
     interactive = False
@@ -155,20 +162,26 @@ def main(argv):
                 pwd_file:
             config.pki_secdomain_pass = pwd_file.readline().strip('\n')
 
+    #   '--force'
+    force_destroy = args.pki_force_destroy
+
     # verify that previously deployed instance exists
-    deployed_pki_instance_path = \
-        config.pki_root_prefix + config.PKI_DEPLOYMENT_BASE_ROOT + "/" + \
-        config.pki_deployed_instance_name
-    if not os.path.exists(deployed_pki_instance_path):
+    deployed_pki_instance_path = os.path.join(
+        config.PKI_DEPLOYMENT_BASE_ROOT, config.pki_deployed_instance_name
+    )
+
+    if not os.path.exists(deployed_pki_instance_path) and not force_destroy:
         print("ERROR:  " + log.PKI_INSTANCE_DOES_NOT_EXIST_1 %
               deployed_pki_instance_path)
         print()
         parser.arg_parser.exit(-1)
 
     # verify that previously deployed subsystem for this instance exists
-    deployed_pki_subsystem_path = \
-        deployed_pki_instance_path + "/" + deployer.subsystem_name.lower()
-    if not os.path.exists(deployed_pki_subsystem_path):
+    deployed_pki_subsystem_path = os.path.join(
+        deployed_pki_instance_path, deployer.subsystem_name.lower()
+    )
+
+    if not os.path.exists(deployed_pki_subsystem_path) and not force_destroy:
         print("ERROR:  " + log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2 %
               (deployer.subsystem_name, deployed_pki_instance_path))
         print()
@@ -178,11 +191,16 @@ def main(argv):
         config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
 
     # establish complete path to previously deployed configuration file
-    config.user_deployment_cfg =\
-        deployed_pki_subsystem_path + "/" +\
-        "registry" + "/" +\
-        deployer.subsystem_name.lower() + "/" +\
+    config.user_deployment_cfg = os.path.join(
+        deployed_pki_subsystem_path,
+        "registry",
+        deployer.subsystem_name.lower(),
         config.USER_DEPLOYMENT_CONFIGURATION
+    )
+
+    if force_destroy and not os.path.exists(config.user_deployment_cfg):
+        # During force destroy, try to load the file. If file doesn't exist, we ignore it
+        config.user_deployment_cfg = None
 
     parser.validate()
     parser.init_config()
@@ -213,6 +231,10 @@ def main(argv):
     parser.compose_pki_master_dictionary()
     parser.mdict['pki_destroy_log'] = \
         config.pki_log_dir + "/" + config.pki_log_name
+
+    # Add force_destroy to master dictionary
+    parser.mdict['pki_force_destroy'] = force_destroy
+
     config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
                          extra=config.PKI_INDENTATION_LEVEL_0)
     config.pki_log.debug(pkilogging.log_format(parser.mdict),
-- 
1.8.3.1


From 7f0af3958605c9826c5bb71fcb43cfccb3056d90 Mon Sep 17 00:00:00 2001
From: Dinesh Prasanth M K <dmoluguw@redhat.com>
Date: Thu, 1 Nov 2018 16:43:36 -0400
Subject: [PATCH 02/13] Add --remove-logs flag to pki-destroy

Partially resolves: Bug 1372056

List of changes by this commit:

- Logs are preserved by default (comment #1 in BZ)
- Add `--remove-flags` flag to pkidestroy to remove logs

Signed-off-by: Dinesh Prasanth M K <dmoluguw@redhat.com>
(cherry picked from commit 9e2cdb0b2f5df552ef50ba7883b4c686adec41b3)
---
 .../server/deployment/scriptlets/instance_layout.py   |  7 +++++--
 .../server/deployment/scriptlets/subsystem_layout.py  | 19 +++++++++++--------
 base/server/sbin/pkidestroy                           | 13 +++++++++++++
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
index 2095212..568c0a0 100644
--- a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
+++ b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
@@ -199,8 +199,11 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
         # remove Tomcat instance base
         deployer.directory.delete(deployer.mdict['pki_instance_path'])
-        # remove Tomcat instance logs
-        deployer.directory.delete(deployer.mdict['pki_instance_log_path'])
+
+        # remove Tomcat instance logs only if --remove-logs is specified
+        if deployer.mdict['pki_remove_logs']:
+            deployer.directory.delete(deployer.mdict['pki_instance_log_path'])
+
         # remove shared NSS security database path for this instance
         deployer.directory.delete(deployer.mdict['pki_database_path'])
         # remove Tomcat instance configuration
diff --git a/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py b/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py
index a0e4658..fb9f754 100644
--- a/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py
+++ b/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py
@@ -124,15 +124,18 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             deployer.directory.delete(
                 deployer.mdict['pki_subsystem_profiles_path'])
         deployer.directory.delete(deployer.mdict['pki_subsystem_path'])
-        # remove instance-based subsystem logs
-        if deployer.mdict['pki_subsystem'] in \
-                config.PKI_SIGNED_AUDIT_SUBSYSTEMS:
+
+        # remove instance-based subsystem logs only if --remove-logs flag is specified
+        if deployer.mdict['pki_remove_logs']:
+            if deployer.mdict['pki_subsystem'] in \
+                    config.PKI_SIGNED_AUDIT_SUBSYSTEMS:
+                deployer.directory.delete(
+                    deployer.mdict['pki_subsystem_signed_audit_log_path'])
             deployer.directory.delete(
-                deployer.mdict['pki_subsystem_signed_audit_log_path'])
-        deployer.directory.delete(
-            deployer.mdict['pki_subsystem_archive_log_path'])
-        deployer.directory.delete(
-            deployer.mdict['pki_subsystem_log_path'])
+                deployer.mdict['pki_subsystem_archive_log_path'])
+            deployer.directory.delete(
+                deployer.mdict['pki_subsystem_log_path'])
+
         # remove instance-based subsystem configuration
         deployer.directory.delete(
             deployer.mdict['pki_subsystem_configuration_path'])
diff --git a/base/server/sbin/pkidestroy b/base/server/sbin/pkidestroy
index 4692e36..4095d13 100755
--- a/base/server/sbin/pkidestroy
+++ b/base/server/sbin/pkidestroy
@@ -102,6 +102,13 @@ def main(argv):
         help='force removal of subsystem'
     )
 
+    parser.optional.add_argument(
+        '--remove-logs',
+        dest='pki_remove_logs',
+        action='store_true',
+        help='remove subsystem logs'
+    )
+
     args = parser.process_command_line_arguments()
 
     interactive = False
@@ -165,6 +172,9 @@ def main(argv):
     #   '--force'
     force_destroy = args.pki_force_destroy
 
+    #   '--remove-logs'
+    remove_logs = args.pki_remove_logs
+
     # verify that previously deployed instance exists
     deployed_pki_instance_path = os.path.join(
         config.PKI_DEPLOYMENT_BASE_ROOT, config.pki_deployed_instance_name
@@ -235,6 +245,9 @@ def main(argv):
     # Add force_destroy to master dictionary
     parser.mdict['pki_force_destroy'] = force_destroy
 
+    # Add remove logs to master dictionary
+    parser.mdict['pki_remove_logs'] = remove_logs
+
     config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
                          extra=config.PKI_INDENTATION_LEVEL_0)
     config.pki_log.debug(pkilogging.log_format(parser.mdict),
-- 
1.8.3.1


From 24405fac463e59250ccf42507bba7fb811e3a2fb Mon Sep 17 00:00:00 2001
From: Dinesh Prasanth M K <dmoluguw@redhat.com>
Date: Thu, 1 Nov 2018 17:02:03 -0400
Subject: [PATCH 03/13] Reuse same instance log dirs (if exists)

Resolves: Bug 1644769
Ticket: https://pagure.io/dogtagpki/issue/3077

- `pkidestroy` behaviour was chagned to preserve the logs by default.
  When `pkispawn` is run, it throws a name space collision error.
- This patch reuses the log dir and appends logs to the same log dir
  structure (if exists) and logs it accordingly.

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

(cherry picked from commit c6c6757b4c566d10d25fe220fa9f59539c7a55ee)
---
 base/server/python/pki/server/deployment/pkihelper.py   | 12 +++++-------
 base/server/python/pki/server/deployment/pkimessages.py |  2 ++
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index e1b9a02..3b55f78 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -345,18 +345,16 @@ class Namespace:
                     log.PKIHELPER_NAMESPACE_COLLISION_2 % (
                         self.mdict['pki_instance_name'],
                         self.mdict['pki_cgroup_cpu_systemd_service_path']))
+
         if os.path.exists(self.mdict['pki_instance_log_path']) and\
            os.path.exists(self.mdict['pki_subsystem_log_path']):
-            # Top-Level PKI log path collision
-            config.pki_log.error(
-                log.PKIHELPER_NAMESPACE_COLLISION_2,
+            # Check if logs already exist. If so, append to it. Log it as info
+            config.pki_log.info(
+                log.PKIHELPER_LOG_REUSE,
                 self.mdict['pki_instance_name'],
                 self.mdict['pki_instance_log_path'],
                 extra=config.PKI_INDENTATION_LEVEL_2)
-            raise Exception(
-                log.PKIHELPER_NAMESPACE_COLLISION_2 % (
-                    self.mdict['pki_instance_name'],
-                    self.mdict['pki_instance_log_path']))
+
         if os.path.exists(self.mdict['pki_instance_configuration_path']) and\
            os.path.exists(self.mdict['pki_subsystem_configuration_path']):
             # Top-Level PKI configuration path collision
diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py
index 7bb79ca..6539295 100644
--- a/base/server/python/pki/server/deployment/pkimessages.py
+++ b/base/server/python/pki/server/deployment/pkimessages.py
@@ -277,6 +277,8 @@ PKIHELPER_NAMESPACE_COLLISION_2 = \
     "PKI instance '%s' would produce a namespace collision with '%s'!"
 PKIHELPER_NAMESPACE_RESERVED_NAME_2 = \
     "PKI instance '%s' is already a reserved name under '%s'!"
+PKIHELPER_LOG_REUSE = \
+    "previous logs of PKI instance '%s' already exist. Appending logs to '%s'"
 PKIHELPER_NCIPHER_RESTART_1 = "executing '%s'"
 PKIHELPER_NOISE_FILE_2 = \
     "generating noise file called '%s' and filling it with '%d' random bytes"
-- 
1.8.3.1


From 2a0d9c8c8ee7333198a8f5cb09c988eeeb3d528f Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 22 Aug 2018 00:02:03 +0200
Subject: [PATCH 04/13] Updated pki.nssdb to support multiple CSR delimiters
 types

The pki.nssdb module has been modified to support both standard
and legacy CSR delimiters as defined in RFC 7468.

https://pagure.io/dogtagpki/issue/3053

Change-Id: I609d640a66357f5293ff3a565027c1a395a47db7
(cherry picked from commit 8bf25507886c446594fa1bd82e3040ab79b271b3)
---
 base/common/python/pki/nssdb.py | 46 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py
index f350255..d4ae804 100644
--- a/base/common/python/pki/nssdb.py
+++ b/base/common/python/pki/nssdb.py
@@ -34,8 +34,11 @@ from cryptography.hazmat.backends import default_backend
 
 import pki
 
-CSR_HEADER = '-----BEGIN NEW CERTIFICATE REQUEST-----'
-CSR_FOOTER = '-----END NEW CERTIFICATE REQUEST-----'
+CSR_HEADER = '-----BEGIN CERTIFICATE REQUEST-----'
+CSR_FOOTER = '-----END CERTIFICATE REQUEST-----'
+
+LEGACY_CSR_HEADER = '-----BEGIN NEW CERTIFICATE REQUEST-----'
+LEGACY_CSR_FOOTER = '-----END NEW CERTIFICATE REQUEST-----'
 
 CERT_HEADER = '-----BEGIN CERTIFICATE-----'
 CERT_FOOTER = '-----END CERTIFICATE-----'
@@ -51,10 +54,18 @@ logger = logging.LoggerAdapter(
     extra={'indent': ''})
 
 
-def convert_data(data, input_format, output_format, header=None, footer=None):
+def convert_data(data, input_format, output_format,
+                 header=None, footer=None,
+                 headers=None, footers=None):
+    '''
+    This method converts a PEM file to base-64 and vice versa.
+    It supports CSR, certificate, and PKCS #7 certificate chain.
+    '''
+
     if input_format == output_format:
         return data
 
+    # converting from base-64 to PEM
     if input_format == 'base64' and output_format == 'pem':
 
         # join base-64 data into a single line
@@ -66,16 +77,30 @@ def convert_data(data, input_format, output_format, header=None, footer=None):
         # add header and footer
         return '%s\n%s\n%s\n' % (header, '\n'.join(lines), footer)
 
+    # converting from PEM to base-64
     if input_format == 'pem' and output_format == 'base64':
 
+        # initialize list of headers if not provided
+        if not headers:
+            headers = [header]
+
+        # initialize list of footers if not provided
+        if not footers:
+            footers = [footer]
+
         # join multiple lines into a single line
         lines = []
         for line in data.splitlines():
             line = line.rstrip('\r\n')
-            if line == header:
+
+            # if the line is a header, skip
+            if line in headers:
                 continue
-            if line == footer:
+
+            # if the line is a footer, skip
+            if line in footers:
                 continue
+
             lines.append(line)
 
         return ''.join(lines)
@@ -86,7 +111,9 @@ def convert_data(data, input_format, output_format, header=None, footer=None):
 
 def convert_csr(csr_data, input_format, output_format):
     return convert_data(csr_data, input_format, output_format,
-                        CSR_HEADER, CSR_FOOTER)
+                        CSR_HEADER, CSR_FOOTER,
+                        headers=[CSR_HEADER, LEGACY_CSR_HEADER],
+                        footers=[CSR_FOOTER, LEGACY_CSR_FOOTER])
 
 
 def convert_cert(cert_data, input_format, output_format):
@@ -100,10 +127,15 @@ def convert_pkcs7(pkcs7_data, input_format, output_format):
 
 
 def get_file_type(filename):
+    '''
+    This method detects the content of a PEM file. It supports
+    CSR, certificate, PKCS #7 certificate chain.
+    '''
+
     with open(filename, 'r') as f:
         data = f.read()
 
-    if data.startswith(CSR_HEADER):
+    if data.startswith(CSR_HEADER) or data.startswith(LEGACY_CSR_HEADER):
         return 'csr'
 
     if data.startswith(CERT_HEADER):
-- 
1.8.3.1


From b9867142f4971a98b6c79ba16788db8829dfd79d Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Mon, 20 Aug 2018 23:14:25 +0200
Subject: [PATCH 05/13] Removed default CSR paths

The default.cfg has been modified to remove default CSR paths.

The verify_predefined_configuration_file_data() has been modified
to no longer require CSR path parameters in the first step of
external CA scenario.

https://pagure.io/dogtagpki/issue/3053

Change-Id: Idef6849b8bd7ee00d13151e0de10357a1f1d9ef2
(cherry picked from commit f3dc6c79370d8b57362272c40bd9f67aaf791710)
---
 base/server/etc/default.cfg                        | 24 ++++++++--------
 .../python/pki/server/deployment/pkihelper.py      | 32 +---------------------
 2 files changed, 13 insertions(+), 43 deletions(-)

diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index b92cca7..2c0430a 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -330,7 +330,7 @@ pki_ca_signing_subject_dn=cn=CA Signing Certificate,ou=%(pki_instance_name)s,o=%
 pki_ca_signing_token=
 
 # DEPRECATED: Use 'pki_ca_signing_csr_path' instead.
-pki_external_csr_path=%(pki_instance_configuration_path)s/external_ca.csr
+pki_external_csr_path=
 pki_ca_signing_csr_path=%(pki_external_csr_path)s
 
 pki_ocsp_signing_csr_path=
@@ -442,12 +442,12 @@ pki_kra_ephemeral_requests=False
 
 # DEPRECATED
 # Use 'pki_*_csr_path' instead.
-pki_external_admin_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_admin.csr
-pki_external_audit_signing_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_audit_signing.csr
-pki_external_sslserver_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_sslserver.csr
-pki_external_storage_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_storage.csr
-pki_external_subsystem_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_subsystem.csr
-pki_external_transport_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_transport.csr
+pki_external_admin_csr_path=
+pki_external_audit_signing_csr_path=
+pki_external_sslserver_csr_path=
+pki_external_storage_csr_path=
+pki_external_subsystem_csr_path=
+pki_external_transport_csr_path=
 
 pki_admin_csr_path=%(pki_external_admin_csr_path)s
 pki_audit_signing_csr_path=%(pki_external_audit_signing_csr_path)s
@@ -527,11 +527,11 @@ pki_standalone=False
 
 # DEPRECATED
 # Use 'pki_*_csr_path' instead.
-pki_external_admin_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_admin.csr
-pki_external_audit_signing_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_audit_signing.csr
-pki_external_signing_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_signing.csr
-pki_external_sslserver_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_sslserver.csr
-pki_external_subsystem_csr_path=%(pki_instance_configuration_path)s/%(pki_subsystem_type)s_subsystem.csr
+pki_external_admin_csr_path=
+pki_external_audit_signing_csr_path=
+pki_external_signing_csr_path=
+pki_external_sslserver_csr_path=
+pki_external_subsystem_csr_path=
 
 pki_admin_csr_path=%(pki_external_admin_csr_path)s
 pki_audit_signing_csr_path=%(pki_external_audit_signing_csr_path)s
diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index 3b55f78..b3c3ccb 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -712,39 +712,9 @@ class ConfigurationFile:
                 # pki_ca_signing_cert_path are optional.
                 pass
         elif not self.skip_configuration and self.standalone:
-            if not self.external_step_two:
-
-                # Stand-alone PKI Admin CSR (Step 1)
-                self.confirm_data_exists("pki_admin_csr_path")
-
-                # Stand-alone PKI Audit Signing CSR (Step 1)
-                self.confirm_data_exists(
-                    "pki_audit_signing_csr_path")
 
-                # Stand-alone PKI SSL Server CSR (Step 1)
-                self.confirm_data_exists("pki_sslserver_csr_path")
+            if self.external_step_two:
 
-                # Stand-alone PKI Subsystem CSR (Step 1)
-                self.confirm_data_exists("pki_subsystem_csr_path")
-
-                # Stand-alone PKI KRA CSRs
-                if self.subsystem == "KRA":
-
-                    # Stand-alone PKI KRA Storage CSR (Step 1)
-                    self.confirm_data_exists(
-                        "pki_storage_csr_path")
-
-                    # Stand-alone PKI KRA Transport CSR (Step 1)
-                    self.confirm_data_exists(
-                        "pki_transport_csr_path")
-
-                # Stand-alone PKI OCSP CSRs
-                if self.subsystem == "OCSP":
-                    # Stand-alone PKI OCSP OCSP Signing CSR (Step 1)
-                    self.confirm_data_exists(
-                        "pki_ocsp_signing_csr_path")
-
-            else:
                 # Stand-alone PKI External CA Certificate (Step 2)
                 # The pki_ca_signing_cert_path is optional.
 
-- 
1.8.3.1


From e2563b186203e5e89d281ff5c39ca182f62cfefa Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 21 Aug 2018 01:03:11 +0200
Subject: [PATCH 06/13] Added support for installation with custom CSRs

The installation code has been modified to import custom
CSRs for KRA and OCSP system certicates if provided. The
CA installation already supports this functionality.

https://pagure.io/dogtagpki/issue/3053

Change-Id: Ic6a7a462bf07f2ca07275a01fc04b8d194005188
(cherry picked from commit 88271a9b3d829669fb997ee6158081da18faed97)
---
 .../netscape/cms/servlet/csadmin/ConfigurationUtils.java | 11 +++--------
 .../pki/server/deployment/scriptlets/configuration.py    | 16 ++++++++++++----
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index d8b4965..7398891 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -2986,14 +2986,9 @@ public class ConfigurationUtils {
 
         CMS.debug("ConfigurationUtils.loadCertRequest(" + tag + ")");
 
-        try {
-            String certreq = config.getString(subsystem + "." + tag + ".certreq");
-            return CryptoUtil.base64Decode(certreq);
-
-        } catch (EPropertyNotFound e) {
-            // The CSR is optional for existing CA case.
-            return null;
-        }
+        // the CSR must exist in the second step of external CA scenario
+        String certreq = config.getString(subsystem + "." + tag + ".certreq");
+        return CryptoUtil.base64Decode(certreq);
     }
 
     public static void generateCertRequest(IConfigStore config, String certTag, Cert cert) throws Exception {
diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py
index 7bc0023..cf02205 100644
--- a/base/server/python/pki/server/deployment/scriptlets/configuration.py
+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py
@@ -368,7 +368,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             csr_data = f.read()
 
         b64_csr = pki.nssdb.convert_csr(csr_data, 'pem', 'base64')
-        subsystem.config['ca.%s.certreq' % tag] = b64_csr
+        subsystem.config['%s.%s.certreq' % (subsystem.name, tag)] = b64_csr
 
     def import_ca_signing_csr(self, deployer, subsystem):
 
@@ -391,9 +391,17 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         if subsystem.name == 'ca':
             self.import_ca_signing_csr(deployer, subsystem)
             self.import_system_cert_request(deployer, subsystem, 'ocsp_signing')
-            self.import_system_cert_request(deployer, subsystem, 'audit_signing')
-            self.import_system_cert_request(deployer, subsystem, 'subsystem')
-            self.import_system_cert_request(deployer, subsystem, 'sslserver')
+
+        if subsystem.name == 'kra':
+            self.import_system_cert_request(deployer, subsystem, 'storage')
+            self.import_system_cert_request(deployer, subsystem, 'transport')
+
+        if subsystem.name == 'ocsp':
+            self.import_system_cert_request(deployer, subsystem, 'signing')
+
+        self.import_system_cert_request(deployer, subsystem, 'audit_signing')
+        self.import_system_cert_request(deployer, subsystem, 'subsystem')
+        self.import_system_cert_request(deployer, subsystem, 'sslserver')
 
     def import_ca_signing_cert(self, deployer, nssdb):
 
-- 
1.8.3.1


From e3b8099fb20b6806020bab1a1687340da643eacf Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 21 Aug 2018 20:01:30 +0200
Subject: [PATCH 07/13] Fixed messages for installation with custom keys

The pkispawn has been modified to display the proper message
for installation with custom keys where the CSRs will not be
generated.

https://pagure.io/dogtagpki/issue/3053

Change-Id: Ibd0ae62c88c2b10520231de3e485e305c715218c
(cherry picked from commit e50f3b0b6034c2c18a0775f2e91fd2e5ea21678f)
---
 base/server/sbin/pkispawn | 81 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 16 deletions(-)

diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index ab94b8b..64c7a67 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -760,9 +760,17 @@ def print_external_ca_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      A CSR for the CA certificate has been generated at:\n"
-          "            %s"
-          % mdict['pki_ca_signing_csr_path'])
+    print("      NSS database: %s" % mdict['pki_database_path'])
+    print()
+
+    signing_csr = mdict['pki_ca_signing_csr_path']
+
+    if signing_csr:
+        print("      A CSR for the CA signing certificate has been generated in:")
+        print("            %s" % mdict['pki_ca_signing_csr_path'])
+    else:
+        print("      No CSR has been generated for CA signing certificate.")
+
     print(log.PKI_RUN_INSTALLATION_STEP_TWO)
     print(log.PKI_SPAWN_INFORMATION_FOOTER)
 
@@ -773,13 +781,35 @@ def print_kra_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      The CSRs for KRA certificates have been generated in:")
-    print("          storage:       %s" % mdict['pki_storage_csr_path'])
-    print("          transport:     %s" % mdict['pki_transport_csr_path'])
-    print("          subsystem:     %s" % mdict['pki_subsystem_csr_path'])
-    print("          SSL server:    %s" % mdict['pki_sslserver_csr_path'])
-    print("          audit signing: %s" % mdict['pki_audit_signing_csr_path'])
-    print("          admin:         %s" % mdict['pki_admin_csr_path'])
+    print("      NSS database: %s" % mdict['pki_database_path'])
+    print()
+
+    storage_csr = mdict['pki_storage_csr_path']
+    transport_csr = mdict['pki_transport_csr_path']
+    subsystem_csr = mdict['pki_subsystem_csr_path']
+    sslserver_csr = mdict['pki_sslserver_csr_path']
+    audit_csr = mdict['pki_audit_signing_csr_path']
+    admin_csr = mdict['pki_admin_csr_path']
+
+    if storage_csr or transport_csr or subsystem_csr or sslserver_csr \
+            or audit_csr or admin_csr:
+        print("      The CSRs for KRA certificates have been generated in:")
+    else:
+        print("      No CSRs have been generated for KRA certificates.")
+
+    if storage_csr:
+        print("          storage:       %s" % storage_csr)
+    if transport_csr:
+        print("          transport:     %s" % transport_csr)
+    if subsystem_csr:
+        print("          subsystem:     %s" % subsystem_csr)
+    if sslserver_csr:
+        print("          SSL server:    %s" % sslserver_csr)
+    if audit_csr:
+        print("          audit signing: %s" % audit_csr)
+    if admin_csr:
+        print("          admin:         %s" % admin_csr)
+
     print(log.PKI_RUN_INSTALLATION_STEP_TWO)
     print(log.PKI_SPAWN_INFORMATION_FOOTER)
 
@@ -790,12 +820,31 @@ def print_ocsp_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      The CSRs for OCSP certificates have been generated in:")
-    print("          OCSP signing:  %s" % mdict['pki_ocsp_signing_csr_path'])
-    print("          subsystem:     %s" % mdict['pki_subsystem_csr_path'])
-    print("          SSL server:    %s" % mdict['pki_sslserver_csr_path'])
-    print("          audit signing: %s" % mdict['pki_audit_signing_csr_path'])
-    print("          admin:         %s" % mdict['pki_admin_csr_path'])
+    print("      NSS database: %s" % mdict['pki_database_path'])
+    print()
+
+    signing_csr = mdict['pki_ocsp_signing_csr_path']
+    subsystem_csr = mdict['pki_subsystem_csr_path']
+    sslserver_csr = mdict['pki_sslserver_csr_path']
+    audit_csr = mdict['pki_audit_signing_csr_path']
+    admin_csr = mdict['pki_admin_csr_path']
+
+    if signing_csr or subsystem_csr or sslserver_csr or audit_csr or admin_csr:
+        print("      The CSRs for OCSP certificates have been generated in:")
+    else:
+        print("      No CSRs have been generated for OCSP certificates.")
+
+    if signing_csr:
+        print("          OCSP signing:  %s" % signing_csr)
+    if subsystem_csr:
+        print("          subsystem:     %s" % subsystem_csr)
+    if sslserver_csr:
+        print("          SSL server:    %s" % sslserver_csr)
+    if audit_csr:
+        print("          audit signing: %s" % audit_csr)
+    if admin_csr:
+        print("          admin:         %s" % admin_csr)
+
     print(log.PKI_RUN_INSTALLATION_STEP_TWO)
     print(log.PKI_SPAWN_INFORMATION_FOOTER)
 
-- 
1.8.3.1


From 6c7079adf8878a2c799cd716c3df9ec75816accd Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 23 Aug 2018 06:10:44 +0200
Subject: [PATCH 08/13] Fixed pki client-cert-import to accept PKCS #7 CA cert
 chain

The NSSDatabase.add_cert() has been modified to accept both single
certificates and PKCS #7 certificate chains in PEM format.

The pki client-cert-import has been modified to support importing
CA cert chain in PKCS #7 format.

The Cert.parseCertificate() has been modified to parse PKCS #7
cert chain properly.

https://pagure.io/dogtagpki/issue/3053

Change-Id: Ibeffcfa4915638df7b13a0cb6deb8c4afc775ca1
(cherry picked from commit 9cef57869f01e89653331c0e22c9d3bacf7744ce)
---
 base/common/python/pki/nssdb.py                            |  2 ++
 .../com/netscape/cmstools/client/ClientCertImportCLI.java  | 14 +++++++++++---
 base/util/src/com/netscape/cmsutil/util/Cert.java          | 12 +++++++++---
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py
index d4ae804..05d2c62 100644
--- a/base/common/python/pki/nssdb.py
+++ b/base/common/python/pki/nssdb.py
@@ -223,6 +223,7 @@ class NSSDatabase(object):
                 '-P', self.token,
                 '-f', self.password_file,
                 '-n', nickname,
+                '-a',
                 '-i', cert_file,
                 '-t', ''
             ]
@@ -242,6 +243,7 @@ class NSSDatabase(object):
                 '-d', self.directory,
                 '-f', self.internal_password_file,
                 '-n', nickname,
+                '-a',
                 '-i', cert_file,
                 '-t', trust_attributes
             ]
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
index 99b215e..62fd4d6 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertImportCLI.java
@@ -19,7 +19,6 @@
 package com.netscape.cmstools.client;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.PrintWriter;
 import java.net.URI;
@@ -45,6 +44,7 @@ import com.netscape.cmstools.cli.CLI;
 import com.netscape.cmstools.cli.MainCLI;
 import com.netscape.cmsutil.crypto.CryptoUtil;
 import com.netscape.cmsutil.util.Cert;
+import com.netscape.cmsutil.util.Utils;
 
 import netscape.security.pkcs.PKCS12;
 import netscape.security.pkcs.PKCS7;
@@ -250,8 +250,11 @@ public class ClientCertImportCLI extends CLI {
             File certFile = File.createTempFile("pki-client-cert-import-", ".crt");
             certFile.deleteOnExit();
 
-            try (FileOutputStream out = new FileOutputStream(certFile)) {
-                out.write(bytes);
+            try (FileWriter fw = new FileWriter(certFile);
+                    PrintWriter out = new PrintWriter(fw)) {
+                out.println(PKCS7.HEADER);
+                out.print(Utils.base64encode(bytes, true));
+                out.println(PKCS7.FOOTER);
             }
 
             if (trustAttributes == null)
@@ -338,6 +341,9 @@ public class ClientCertImportCLI extends CLI {
             command.add(dbPasswordFile.getAbsolutePath());
         }
 
+        // accept PEM or PKCS #7 certificate
+        command.add("-a");
+
         command.add("-i");
         command.add(certFile);
         command.add("-n");
@@ -362,10 +368,12 @@ public class ClientCertImportCLI extends CLI {
             String trustAttributes) throws Exception {
 
         if (nickname != null) {
+            // import a single CA certificate with the provided nickname
             importCert(dbPath, dbPasswordFile, certFile, nickname, trustAttributes);
             return;
         }
 
+        // import CA certificate chain with auto-generated nicknames
         String pemCert = new String(Files.readAllBytes(Paths.get(certFile))).trim();
         byte[] binCert = Cert.parseCertificate(pemCert);
 
diff --git a/base/util/src/com/netscape/cmsutil/util/Cert.java b/base/util/src/com/netscape/cmsutil/util/Cert.java
index f084395..e6f2460 100644
--- a/base/util/src/com/netscape/cmsutil/util/Cert.java
+++ b/base/util/src/com/netscape/cmsutil/util/Cert.java
@@ -33,6 +33,9 @@ public class Cert {
     public static final String HEADER = "-----BEGIN CERTIFICATE-----";
     public static final String FOOTER = "-----END CERTIFICATE-----";
 
+    public static final String PKCS7_HEADER = "-----BEGIN PKCS7-----";
+    public static final String PKCS7_FOOTER = "-----END PKCS7-----";
+
     // From https://www.rfc-editor.org/rfc/rfc7468.txt
     public static final String REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
     public static final String REQUEST_FOOTER = "-----END CERTIFICATE REQUEST-----";
@@ -68,9 +71,12 @@ public class Cert {
             return s;
         }
 
-        if ((s.startsWith(HEADER)) &&
-                (s.endsWith(FOOTER))) {
-            return (s.substring(27, (s.length() - 25)));
+        if (s.startsWith(HEADER) && s.endsWith(FOOTER)) {
+            return s.substring(HEADER.length(), s.length() - FOOTER.length());
+        }
+
+        if (s.startsWith(PKCS7_HEADER) && s.endsWith(PKCS7_FOOTER)) {
+            return s.substring(PKCS7_HEADER.length(), s.length() - PKCS7_FOOTER.length());
         }
 
         // To support Thawte's header and footer
-- 
1.8.3.1


From ea9b582909d10d8f6c485860615319b6f6c31741 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 31 Aug 2018 00:32:44 +0200
Subject: [PATCH 09/13] Renamed server NSS database parameters

The following parameters have been renamed for consistency:
* pki_database_path -> pki_server_database_path
* pki_pin -> pki_server_database_password

The old parameters are still usable but they have been
deprecated.

The pki_client_pin is redundant so it has been removed.

https://pagure.io/dogtagpki/issue/3053

Change-Id: I243a01b360f573a16a160e9a415f786e38681603
(cherry picked from commit 80defb1b7602eb59f5ee817a76acac86490ce853)
---
 base/server/etc/default.cfg                        | 10 ++++++-
 .../python/pki/server/deployment/pkihelper.py      | 10 +++----
 .../python/pki/server/deployment/pkiparser.py      | 34 +++++++++++++---------
 .../server/deployment/scriptlets/configuration.py  |  4 +--
 .../deployment/scriptlets/instance_layout.py       |  6 ++--
 .../deployment/scriptlets/security_databases.py    | 21 ++++++-------
 .../server/deployment/scriptlets/selinux_setup.py  |  8 ++---
 base/server/sbin/pkispawn                          |  6 ++--
 8 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index 2c0430a..0ae0764 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -31,6 +31,7 @@ sensitive_parameters=
     pki_pin
     pki_replication_password
     pki_security_domain_password
+    pki_server_database_password
     pki_server_pkcs12_password
     pki_token_password
 
@@ -173,6 +174,14 @@ pki_cert_chain_path=%(pki_external_ca_cert_chain_path)s
 pki_external_ca_cert_chain_nickname=caSigningCert External CA
 pki_cert_chain_nickname=%(pki_external_ca_cert_chain_nickname)s
 
+# DEPRECATED: Use 'pki_server_database_path' instead.
+pki_database_path=%(pki_instance_configuration_path)s/alias
+pki_server_database_path=%(pki_database_path)s
+
+# DEPRECATED: Use 'pki_server_database_password' instead.
+pki_pin=
+pki_server_database_password=
+
 pki_pkcs12_path=
 pki_pkcs12_password=
 
@@ -201,7 +210,6 @@ pki_registry_path=%(pki_root_prefix)s/etc/sysconfig/pki
 pki_instance_path=%(pki_path)s/%(pki_instance_name)s
 pki_instance_log_path=%(pki_log_path)s/%(pki_instance_name)s
 pki_instance_configuration_path=%(pki_configuration_path)s/%(pki_instance_name)s
-pki_database_path=%(pki_instance_configuration_path)s/alias
 pki_instance_database_link=%(pki_instance_path)s/alias
 pki_instance_conf_link=%(pki_instance_path)s/conf
 pki_instance_logs_link=%(pki_instance_path)s/logs
diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index b3c3ccb..77594ec 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -3092,7 +3092,7 @@ class KRAConnector:
                    "-h", cahost,
                    "-n", subsystemnick,
                    "-P", "https",
-                   "-d", self.mdict['pki_database_path'],
+                   "-d", self.mdict['pki_server_database_path'],
                    "-c", token_pwd,
                    "ca-kraconnector-del",
                    "--host", krahost,
@@ -3125,7 +3125,7 @@ class KRAConnector:
         command = ["/usr/bin/sslget",
                    "-n", subsystemnick,
                    "-p", token_pwd,
-                   "-d", self.mdict['pki_database_path'],
+                   "-d", self.mdict['pki_server_database_path'],
                    "-e", params,
                    "-v",
                    "-r", update_url, cahost + ":" + str(caport)]
@@ -3236,7 +3236,7 @@ class TPSConnector:
                    "-h", tkshost,
                    "-n", subsystemnick,
                    "-P", "https",
-                   "-d", self.mdict['pki_database_path'],
+                   "-d", self.mdict['pki_server_database_path'],
                    "-c", token_pwd,
                    "-t", "tks",
                    "tks-tpsconnector-del",
@@ -3336,7 +3336,7 @@ class SecurityDomain:
                 admin_update_url = "/ca/admin/ca/updateDomainXML"
                 command = ["/usr/bin/sslget",
                            "-p", str(123456),
-                           "-d", self.mdict['pki_database_path'],
+                           "-d", self.mdict['pki_server_database_path'],
                            "-e", params,
                            "-v",
                            "-r", admin_update_url,
@@ -3451,7 +3451,7 @@ class SecurityDomain:
         command = ["/usr/bin/sslget",
                    "-n", subsystemnick,
                    "-p", token_pwd,
-                   "-d", self.mdict['pki_database_path'],
+                   "-d", self.mdict['pki_server_database_path'],
                    "-e", params,
                    "-v",
                    "-r", update_url, sechost + ":" + str(secagentport)]
diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py
index 2397f43..5b8cdd3 100644
--- a/base/server/python/pki/server/deployment/pkiparser.py
+++ b/base/server/python/pki/server/deployment/pkiparser.py
@@ -84,7 +84,11 @@ class PKIConfigParser:
         (None, 'pki_ssl_server_subject_dn',
          None, 'pki_sslserver_subject_dn'),
         (None, 'pki_ssl_server_token',
-         None, 'pki_sslserver_token')
+         None, 'pki_sslserver_token'),
+        (None, 'pki_database_path',
+         None, 'pki_server_database_path'),
+        (None, 'pki_pin',
+         None, 'pki_server_database_password'),
     ]
 
     DEPRECATED_CA_PARAMS = [
@@ -490,6 +494,7 @@ class PKIConfigParser:
                     'pki_pin',
                     'pki_replication_password',
                     'pki_security_domain_password',
+                    'pki_server_database_password',
                     'pki_server_pkcs12_password',
                     'pki_token_password')
 
@@ -766,17 +771,23 @@ class PKIConfigParser:
 
             # if instance already exists and has password, reuse the password
             if internal_token in instance.passwords:
-                self.mdict['pki_pin'] = instance.passwords.get(internal_token)
+                self.mdict['pki_server_database_password'] = instance.passwords.get(internal_token)
 
             # otherwise, use user-provided password if specified
-            elif 'pki_pin' in self.mdict:
+            elif self.mdict['pki_server_database_password']:
                 pass
 
+            # otherwise, use user-provided pin if specified
+            elif self.mdict['pki_pin']:
+                self.mdict['pki_server_database_password'] = self.mdict['pki_pin']
+
             # otherwise, generate a random password
             else:
-                self.mdict['pki_pin'] = pki.generate_password()
+                self.mdict['pki_server_database_password'] = pki.generate_password()
 
-            self.mdict['pki_client_pin'] = pki.generate_password()
+            # generate random password for client database if not specified
+            if not self.mdict['pki_client_database_password']:
+                self.mdict['pki_client_database_password'] = pki.generate_password()
 
             pkilogging.sensitive_parameters = \
                 self.mdict['sensitive_parameters'].split()
@@ -1231,13 +1242,13 @@ class PKIConfigParser:
                     self.mdict['pki_instance_configuration_path'],
                     "password.conf")
             self.mdict['pki_cert_database'] = \
-                os.path.join(self.mdict['pki_database_path'],
+                os.path.join(self.mdict['pki_server_database_path'],
                              "cert8.db")
             self.mdict['pki_key_database'] = \
-                os.path.join(self.mdict['pki_database_path'],
+                os.path.join(self.mdict['pki_server_database_path'],
                              "key3.db")
             self.mdict['pki_secmod_database'] = \
-                os.path.join(self.mdict['pki_database_path'],
+                os.path.join(self.mdict['pki_server_database_path'],
                              "secmod.db")
             self.mdict['pki_self_signed_nickname'] = \
                 self.mdict['pki_sslserver_nickname']
@@ -1262,11 +1273,6 @@ class PKIConfigParser:
                     self.mdict['pki_subsystem_configuration_path'],
                     "password.conf")
 
-            if not len(self.mdict['pki_client_database_password']):
-                # use randomly generated client 'pin'
-                self.mdict['pki_client_database_password'] = \
-                    str(self.mdict['pki_client_pin'])
-
             # Configuration scriptlet
             # 'Security Domain' Configuration name/value pairs
             # 'Subsystem Name'  Configuration name/value pairs
@@ -1393,7 +1399,7 @@ class PKIConfigParser:
                 # NOTE:  ALWAYS store the PKCS #12 backup keys file
                 #        in with the NSS "server" security databases
                 self.mdict['pki_backup_keys_p12'] = \
-                    self.mdict['pki_database_path'] + "/" + \
+                    self.mdict['pki_server_database_path'] + "/" + \
                     self.mdict['pki_subsystem'].lower() + "_" + \
                     "backup" + "_" + "keys" + "." + "p12"
 
diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py
index cf02205..f085e80 100644
--- a/base/server/python/pki/server/deployment/scriptlets/configuration.py
+++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py
@@ -865,7 +865,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
             deployer.password.create_password_conf(
                 deployer.mdict['pki_shared_pfile'],
-                deployer.mdict['pki_pin'], pin_sans_token=True)
+                deployer.mdict['pki_server_database_password'], pin_sans_token=True)
 
             # only create a self signed cert for a new instance
             #
@@ -884,7 +884,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 f.write("not_so_random_data")
 
             deployer.certutil.generate_self_signed_certificate(
-                deployer.mdict['pki_database_path'],
+                deployer.mdict['pki_server_database_path'],
                 deployer.mdict['pki_cert_database'],
                 deployer.mdict['pki_key_database'],
                 deployer.mdict['pki_secmod_database'],
diff --git a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
index 568c0a0..e5ce820 100644
--- a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
+++ b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
@@ -162,10 +162,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         deployer.systemd.daemon_reload()
 
         # establish shared NSS security databases for this instance
-        deployer.directory.create(deployer.mdict['pki_database_path'])
+        deployer.directory.create(deployer.mdict['pki_server_database_path'])
         # establish instance convenience symbolic links
         deployer.symlink.create(
-            deployer.mdict['pki_database_path'],
+            deployer.mdict['pki_server_database_path'],
             deployer.mdict['pki_instance_database_link'])
         deployer.symlink.create(
             deployer.mdict['pki_instance_configuration_path'],
@@ -205,7 +205,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             deployer.directory.delete(deployer.mdict['pki_instance_log_path'])
 
         # remove shared NSS security database path for this instance
-        deployer.directory.delete(deployer.mdict['pki_database_path'])
+        deployer.directory.delete(deployer.mdict['pki_server_database_path'])
         # remove Tomcat instance configuration
         deployer.directory.delete(
             deployer.mdict['pki_instance_configuration_path'])
diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index 02f4713..7ce32a8 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -54,12 +54,12 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         if config.str2bool(deployer.mdict['pki_hsm_enable']):
             deployer.password.create_hsm_password_conf(
                 deployer.mdict['pki_shared_password_conf'],
-                deployer.mdict['pki_pin'],
+                deployer.mdict['pki_server_database_password'],
                 deployer.mdict['pki_token_password'])
         else:
             deployer.password.create_password_conf(
                 deployer.mdict['pki_shared_password_conf'],
-                deployer.mdict['pki_pin'])
+                deployer.mdict['pki_server_database_password'])
 
         # Since 'certutil' does NOT strip the 'token=' portion of
         # the 'token=password' entries, create a temporary server 'pfile'
@@ -67,11 +67,11 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         # allowing 'certutil' to generate the security databases
         deployer.password.create_password_conf(
             deployer.mdict['pki_shared_pfile'],
-            deployer.mdict['pki_pin'], pin_sans_token=True)
+            deployer.mdict['pki_server_database_password'], pin_sans_token=True)
         deployer.file.modify(deployer.mdict['pki_shared_password_conf'])
 
         deployer.certutil.create_security_databases(
-            deployer.mdict['pki_database_path'],
+            deployer.mdict['pki_server_database_path'],
             deployer.mdict['pki_cert_database'],
             deployer.mdict['pki_key_database'],
             deployer.mdict['pki_secmod_database'],
@@ -79,7 +79,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
         if config.str2bool(deployer.mdict['pki_hsm_enable']):
             deployer.modutil.register_security_module(
-                deployer.mdict['pki_database_path'],
+                deployer.mdict['pki_server_database_path'],
                 deployer.mdict['pki_hsm_modulename'],
                 deployer.mdict['pki_hsm_libfile'])
         deployer.file.modify(
@@ -103,7 +103,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 raise Exception('Missing pki_server_pkcs12_password property.')
 
             nssdb = pki.nssdb.NSSDatabase(
-                directory=deployer.mdict['pki_database_path'],
+                directory=deployer.mdict['pki_server_database_path'],
                 password_file=deployer.mdict['pki_shared_pfile'])
 
             try:
@@ -129,7 +129,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 raise Exception('Missing pki_clone_pkcs12_password property.')
 
             nssdb = pki.nssdb.NSSDatabase(
-                directory=deployer.mdict['pki_database_path'],
+                directory=deployer.mdict['pki_server_database_path'],
                 password_file=deployer.mdict['pki_shared_pfile'])
 
             try:
@@ -162,7 +162,8 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                     nickname=deployer.mdict['pki_audit_signing_nickname'],
                     trust_attributes='u,u,Pu')
 
-                print('Imported certificates in %s:' % deployer.mdict['pki_database_path'])
+                print('Imported certificates into %s:' %
+                      deployer.mdict['pki_server_database_path'])
 
                 nssdb.show_certs()
 
@@ -180,7 +181,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 #        the instance will utilize 'softokn' or an HSM
                 #
                 rv = deployer.certutil.verify_certificate_exists(
-                    deployer.mdict['pki_database_path'],
+                    deployer.mdict['pki_server_database_path'],
                     deployer.mdict['pki_cert_database'],
                     deployer.mdict['pki_key_database'],
                     deployer.mdict['pki_secmod_database'],
@@ -195,7 +196,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                             'pki_ds_secure_connection_ca_trustargs'],
                         deployer.mdict['pki_ds_secure_connection_ca_pem_file'],
                         password_file=deployer.mdict['pki_shared_pfile'],
-                        path=deployer.mdict['pki_database_path'],
+                        path=deployer.mdict['pki_server_database_path'],
                         token=deployer.mdict['pki_self_signed_token'])
 
         # Always delete the temporary 'pfile'
diff --git a/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py b/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py
index d5e4b0c..7d324d4 100644
--- a/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py
+++ b/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py
@@ -115,10 +115,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
                         config.pki_log.info(
                             "adding selinux fcontext \"%s\"",
-                            deployer.mdict['pki_database_path'] + self.suffix,
+                            deployer.mdict['pki_server_database_path'] + self.suffix,
                             extra=config.PKI_INDENTATION_LEVEL_2)
                         fcon.add(
-                            deployer.mdict['pki_database_path'] + self.suffix,
+                            deployer.mdict['pki_server_database_path'] + self.suffix,
                             config.PKI_CERTDB_SELINUX_CONTEXT, "", "s0", "")
 
                         port_records = seobject.portRecords(trans)
@@ -206,10 +206,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
                         config.pki_log.info(
                             "deleting selinux fcontext \"%s\"",
-                            deployer.mdict['pki_database_path'] + self.suffix,
+                            deployer.mdict['pki_server_database_path'] + self.suffix,
                             extra=config.PKI_INDENTATION_LEVEL_2)
                         fcon.delete(
-                            deployer.mdict['pki_database_path'] +
+                            deployer.mdict['pki_server_database_path'] +
                             self.suffix, "")
 
                         port_records = seobject.portRecords(trans)
diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index 64c7a67..867a381 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -760,7 +760,7 @@ def print_external_ca_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      NSS database: %s" % mdict['pki_database_path'])
+    print("      NSS database: %s" % mdict['pki_server_database_path'])
     print()
 
     signing_csr = mdict['pki_ca_signing_csr_path']
@@ -781,7 +781,7 @@ def print_kra_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      NSS database: %s" % mdict['pki_database_path'])
+    print("      NSS database: %s" % mdict['pki_server_database_path'])
     print()
 
     storage_csr = mdict['pki_storage_csr_path']
@@ -820,7 +820,7 @@ def print_ocsp_step_one_information(mdict):
     print("      The %s subsystem of the '%s' instance is still incomplete." %
           (deployer.subsystem_name, mdict['pki_instance_name']))
     print()
-    print("      NSS database: %s" % mdict['pki_database_path'])
+    print("      NSS database: %s" % mdict['pki_server_database_path'])
     print()
 
     signing_csr = mdict['pki_ocsp_signing_csr_path']
-- 
1.8.3.1


From a3d27ed43b9c119cfaff100573d89c2caa08e3b7 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 7 Sep 2018 16:32:47 +0200
Subject: [PATCH 10/13] Fixed password generation in pkispawn

Previously the NSS database passwords were generated in
pkiparser.py. Under certain scenarios the password may be
overwritten by a subsequent code in pkispawn. To avoid the
problem the code that generates the NSS database passwords
has been moved into the initialization scriptlet.

https://pagure.io/dogtagpki/issue/3061

Change-Id: Ieabfaea7465b615f214820d2ed877f4da589dadb
(cherry picked from commit 9a984ee0a709645fe9b6044367ed28076692ee86)
---
 .../python/pki/server/deployment/pkiparser.py      | 25 --------------------
 .../server/deployment/scriptlets/initialization.py | 27 ++++++++++++++++++++++
 2 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py
index 5b8cdd3..2ea7319 100644
--- a/base/server/python/pki/server/deployment/pkiparser.py
+++ b/base/server/python/pki/server/deployment/pkiparser.py
@@ -764,31 +764,6 @@ class PKIConfigParser:
 
             self.deployer.flatten_master_dict()
 
-            instance = pki.server.PKIInstance(self.mdict['pki_instance_name'])
-            instance.load()
-
-            internal_token = self.mdict['pki_self_signed_token']
-
-            # if instance already exists and has password, reuse the password
-            if internal_token in instance.passwords:
-                self.mdict['pki_server_database_password'] = instance.passwords.get(internal_token)
-
-            # otherwise, use user-provided password if specified
-            elif self.mdict['pki_server_database_password']:
-                pass
-
-            # otherwise, use user-provided pin if specified
-            elif self.mdict['pki_pin']:
-                self.mdict['pki_server_database_password'] = self.mdict['pki_pin']
-
-            # otherwise, generate a random password
-            else:
-                self.mdict['pki_server_database_password'] = pki.generate_password()
-
-            # generate random password for client database if not specified
-            if not self.mdict['pki_client_database_password']:
-                self.mdict['pki_client_database_password'] = pki.generate_password()
-
             pkilogging.sensitive_parameters = \
                 self.mdict['sensitive_parameters'].split()
 
diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py
index efd1536..4515b55 100644
--- a/base/server/python/pki/server/deployment/scriptlets/initialization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py
@@ -19,6 +19,7 @@
 #
 
 from __future__ import absolute_import
+import pki
 
 # PKI Deployment Imports
 from .. import pkiconfig as config
@@ -36,6 +37,32 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                             deployer.mdict['pki_subsystem'],
                             deployer.mdict['pki_instance_name'],
                             extra=config.PKI_INDENTATION_LEVEL_0)
+
+        instance = pki.server.PKIInstance(deployer.mdict['pki_instance_name'])
+        instance.load()
+
+        internal_token = deployer.mdict['pki_self_signed_token']
+
+        # if instance already exists and has password, reuse the password
+        if internal_token in instance.passwords:
+            deployer.mdict['pki_server_database_password'] = instance.passwords.get(internal_token)
+
+        # otherwise, use user-provided password if specified
+        elif deployer.mdict['pki_server_database_password']:
+            pass
+
+        # otherwise, use user-provided pin if specified
+        elif deployer.mdict['pki_pin']:
+            deployer.mdict['pki_server_database_password'] = deployer.mdict['pki_pin']
+
+        # otherwise, generate a random password
+        else:
+            deployer.mdict['pki_server_database_password'] = pki.generate_password()
+
+        # generate random password for client database if not specified
+        if not deployer.mdict['pki_client_database_password']:
+            deployer.mdict['pki_client_database_password'] = pki.generate_password()
+
         # ALWAYS initialize 'uid' and 'gid'
         deployer.identity.add_uid_and_gid(deployer.mdict['pki_user'],
                                           deployer.mdict['pki_group'])
-- 
1.8.3.1


From 4886a7f4fa3678cd26c7c38c5140784dc53b76b5 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Tue, 2 Oct 2018 18:11:43 +0200
Subject: [PATCH 11/13] Updated pki-server subsystem-cert-validate output

The pki-server subsystem-cert-validate CLI has been modified to
show the actual message generated by NSS if the validation fails.

(cherry picked from commit eb8baf8b51e3c897caddbc16df2fd226308a0876)
---
 base/server/python/pki/server/cli/subsystem.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py
index 57093d4..068d1db 100644
--- a/base/server/python/pki/server/cli/subsystem.py
+++ b/base/server/python/pki/server/cli/subsystem.py
@@ -1038,10 +1038,11 @@ class SubsystemCertValidateCLI(pki.cli.CLI):
             return True
 
         except subprocess.CalledProcessError as e:
-            if e.returncode == 1:
-                print('  Status: INVALID')
+            if e.output:
+                status = e.output.decode('utf-8')
             else:
-                print('  Status: ERROR: %s' % e.output)
+                status = 'ERROR'
+            print('  Status: %s' % status)
             return False
 
         finally:
-- 
1.8.3.1


From 0115c05727962dac2bdb3865388144315719a0b0 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 24 Aug 2018 03:36:15 +0200
Subject: [PATCH 12/13] Added docs for installation with custom keys

https://pagure.io/dogtagpki/issue/3053

Change-Id: I8f8fdbb7cc1888092bd7ba686a626137113ed2d5
(cherry picked from commit a8405a1f8bd4c3fd10213725a32da0419e622252)
---
 .../Installing_CA_with_Custom_CA_Signing_Key.md    | 169 ++++++++++++++++++
 .../Installing_KRA_with_Custom_Keys.md             | 190 +++++++++++++++++++++
 .../Installing_OCSP_with_Custom_Keys.md            | 183 ++++++++++++++++++++
 3 files changed, 542 insertions(+)
 create mode 100644 docs/installation/Installing_CA_with_Custom_CA_Signing_Key.md
 create mode 100644 docs/installation/Installing_KRA_with_Custom_Keys.md
 create mode 100644 docs/installation/Installing_OCSP_with_Custom_Keys.md

diff --git a/docs/installation/Installing_CA_with_Custom_CA_Signing_Key.md b/docs/installation/Installing_CA_with_Custom_CA_Signing_Key.md
new file mode 100644
index 0000000..5cdf786
--- /dev/null
+++ b/docs/installation/Installing_CA_with_Custom_CA_Signing_Key.md
@@ -0,0 +1,169 @@
+Installing CA with Custom CA Signing Key
+========================================
+
+Overview
+--------
+
+This page describes the process to install a CA subsystem with a custom CA signing key, CSR, and certificate.
+
+Starting CA Subsystem Installation
+----------------------------------
+
+Prepare a file (e.g. ca-step1.cfg) that contains the deployment configuration step 1, for example:
+
+```
+[DEFAULT]
+pki_server_database_password=Secret.123
+
+[CA]
+pki_admin_email=caadmin@example.com
+pki_admin_name=caadmin
+pki_admin_nickname=caadmin
+pki_admin_password=Secret.123
+pki_admin_uid=caadmin
+
+pki_client_database_password=Secret.123
+pki_client_database_purge=False
+pki_client_pkcs12_password=Secret.123
+
+pki_ds_base_dn=dc=ca,dc=pki,dc=example,dc=com
+pki_ds_database=ca
+pki_ds_password=Secret.123
+
+pki_security_domain_name=EXAMPLE
+
+pki_ca_signing_nickname=ca_signing
+pki_ocsp_signing_nickname=ca_ocsp_signing
+pki_audit_signing_nickname=ca_audit_signing
+pki_sslserver_nickname=sslserver
+pki_subsystem_nickname=subsystem
+
+pki_external=True
+pki_external_step_two=False
+```
+
+Then execute the following command:
+
+```
+$ pkispawn -f ca-step1.cfg -s CA
+```
+
+It will install CA subsystem in a Tomcat instance (default is pki-tomcat) and create the following NSS databases:
+* server NSS database: /etc/pki/pki-tomcat/alias
+* admin NSS database: ~/.dogtag/pki-tomcat/ca/alias
+
+Since there is no CSR path parameter specified, it will not generate the CA signing key by default.
+
+Generating CA Signing Key, CSR, and Certificate
+-----------------------------------------------
+
+Generate a custom CA signing key in the server NSS database, then generate a CSR and store it in a file (e.g. ca_signing.csr).
+
+Use the CSR to issue the CA signing certificate:
+* for root CA installation, generate a self-signed CA signing certificate
+* for subordinate CA installation, submit the CSR to an external CA to issue the CA signing certificate
+
+Store the CA signing certificate in a file (e.g. ca_signing.crt). The CA signing certificate can be specified as a single certificate or a PKCS #7 certificate chain in PEM format.
+
+If the CA signing certificate was issued by an external CA, store the external CA certificate chain in a file (e.g. external.crt). The certificate chain can be specified as a single certificate or a PKCS #7 certificate chain in PEM format. The certificate chain should include all CA certificates from the root CA to the external CA that issued the CA signing certificate, but it should not include the CA signing certificate itself.
+
+See also:
+* [Generating CA Signing Certificate](http://www.dogtagpki.org/wiki/Generating_CA_Signing_Certificate)
+
+Finishing CA Subsystem Installation
+-----------------------------------
+
+Prepare another file (e.g. ca-step2.cfg) that contains the deployment configuration step 2. The file can be copied from step 1 (i.e. ca-step1.cfg) with additional changes below.
+
+Specify step 2 with the following parameter:
+
+```
+pki_external_step_two=True
+```
+
+Specify the custom CA signing CSR with the following parameter:
+
+```
+pki_ca_signing_csr_path=ca_signing.csr
+```
+
+Specify the custom CA signing certificate with the following parameter:
+
+```
+pki_ca_signing_cert_path=ca_signing.crt
+```
+
+If the CA signing certificate was issued by an external CA, specify the external CA certificate chain with the following parameters:
+
+```
+pki_cert_chain_nickname=external
+pki_cert_chain_path=external.crt
+```
+
+Finally, execute the following command:
+
+```
+$ pkispawn -f ca-step2.cfg -s CA
+```
+
+Verifying System Certificates
+-----------------------------
+
+Verify that the server NSS database contains the following certificates:
+
+```
+$ certutil -L -d /etc/pki/pki-tomcat/alias
+
+Certificate Nickname                                         Trust Attributes
+                                                             SSL,S/MIME,JAR/XPI
+
+external                                                     CT,C,C
+ca_signing                                                   CTu,Cu,Cu
+ca_ocsp_signing                                              u,u,u
+subsystem                                                    u,u,u
+ca_audit_signing                                             u,u,Pu
+sslserver                                                    u,u,u
+```
+
+Verifying Admin Certificate
+---------------------------
+
+Prepare a client NSS database (e.g. ~/.dogtag/nssdb):
+
+```
+$ pki -c Secret.123 client-init
+```
+
+Import the external CA certificate chain:
+
+```
+$ pki -c Secret.123 client-cert-import --ca-cert external.crt
+```
+
+Import the CA signing certificate:
+
+```
+$ pki -c Secret.123 client-cert-import ca_signing --ca-cert ca_signing.crt
+```
+
+Import admin key and certificate:
+
+```
+$ pki -c Secret.123 client-cert-import \
+ --pkcs12 ~/.dogtag/pki-tomcat/ca_admin_cert.p12 \
+ --pkcs12-password-file ~/.dogtag/pki-tomcat/ca/pkcs12_password.conf
+```
+
+Verify that the admin certificate can be used to access the CA subsystem by executing the following command:
+
+```
+$ pki -c Secret.123 -n caadmin ca-user-show caadmin
+--------------
+User "caadmin"
+--------------
+  User ID: caadmin
+  Full name: caadmin
+  Email: caadmin@example.com
+  Type: adminType
+  State: 1
+```
diff --git a/docs/installation/Installing_KRA_with_Custom_Keys.md b/docs/installation/Installing_KRA_with_Custom_Keys.md
new file mode 100644
index 0000000..e555363
--- /dev/null
+++ b/docs/installation/Installing_KRA_with_Custom_Keys.md
@@ -0,0 +1,190 @@
+Installing KRA with Custom Keys
+===============================
+
+Overview
+--------
+
+This page describes the process to install a KRA subsystem with custom KRA system and admin keys, CSRs, and certificates.
+
+Starting KRA Subsystem Installation
+-----------------------------------
+
+Prepare a file (e.g. kra-step1.cfg) that contains the deployment configuration step 1, for example:
+
+```
+[DEFAULT]
+pki_server_database_password=Secret.123
+
+[KRA]
+pki_admin_email=kraadmin@example.com
+pki_admin_name=kraadmin
+pki_admin_nickname=kraadmin
+pki_admin_password=Secret.123
+pki_admin_uid=kraadmin
+
+pki_client_database_password=Secret.123
+pki_client_database_purge=False
+pki_client_pkcs12_password=Secret.123
+
+pki_ds_base_dn=dc=kra,dc=pki,dc=example,dc=com
+pki_ds_database=kra
+pki_ds_password=Secret.123
+
+pki_security_domain_name=EXAMPLE
+pki_security_domain_user=caadmin
+pki_security_domain_password=Secret.123
+
+pki_storage_nickname=kra_storage
+pki_transport_nickname=kra_transport
+pki_subsystem_nickname=subsystem
+pki_sslserver_nickname=sslserver
+pki_audit_signing_nickname=kra_audit_signing
+
+pki_external=True
+pki_external_step_two=False
+```
+
+Then execute the following command:
+
+```
+$ pkispawn -f kra-step1.cfg -s KRA
+```
+
+It will install KRA subsystem in a Tomcat instance (default is pki-tomcat) and create the following NSS databases:
+* server NSS database: /etc/pki/pki-tomcat/alias
+* admin NSS database: ~/dogtag/pki-tomcat/kra/alias
+
+Since there are no CSR path parameters specified, it will not generate KRA system and admin keys.
+
+Generating KRA Keys, CSRs, and Certificates
+-------------------------------------------
+
+Generate custom KRA system keys in the server NSS database and admin key in the admin NSS database, then generate the CSRs and store them in files, for example:
+* kra_storage.csr
+* kra_transport.csr
+* subsystem.csr
+* sslserver.csr
+* kra_audit_signing.csr
+* kra_admin.csr
+
+Submit the CSRs to an external CA to issue the certificates, then store the certificates in files, for example:
+* kra_storage.crt
+* kra_transport.crt
+* subsystem.crt
+* sslserver.crt
+* kra_audit_signing.crt
+* kra_admin.crt
+
+The certificates can be specified as single certificates or PKCS #7 certificate chains in PEM format.
+
+Store the external CA certificate chain in a file (e.g. ca_signing.crt). The certificate chain can be specified as a single certificate or PKCS #7 certificate chain in PEM format. The certificate chain should include all CA certificates from the root CA to the external CA that issued the KRA system and admin certificates.
+
+See also:
+* [Generating KRA Storage Certificate](http://www.dogtagpki.org/wiki/Generating_KRA_Storage_Certificate)
+* [Generating KRA Transport Certificate](http://www.dogtagpki.org/wiki/Generating_KRA_Transport_Certificate)
+* [Generating Subsystem Certificate](http://www.dogtagpki.org/wiki/Generating_Subsystem_Certificate)
+* [Generating SSL Server Certificate](http://www.dogtagpki.org/wiki/Generating_SSL_Server_Certificate)
+* [Generating Audit Signing Certificate](http://www.dogtagpki.org/wiki/Generating_Audit_Signing_Certificate)
+* [Generating Admin Certificate](http://www.dogtagpki.org/wiki/Generating_Admin_Certificate)
+
+Finishing KRA Subsystem Installation
+------------------------------------
+
+Prepare another file (e.g. kra-step2.cfg) that contains the deployment configuration step 2. The file can be copied from step 1 (i.e. kra-step1.cfg) with additional changes below.
+
+Specify step 2 with the following parameter:
+
+```
+pki_external_step_two=True
+```
+
+Specify the custom CSRs with the following parameters:
+
+```
+pki_storage_csr_path=kra_storage.csr
+pki_transport_csr_path=kra_transport.csr
+pki_subsystem_csr_path=subsystem.csr
+pki_sslserver_csr_path=sslserver.csr
+pki_audit_signing_csr_path=kra_audit_signing.csr
+pki_admin_csr_path=kra_admin.csr
+```
+
+Specify the custom certificates with the following parameters:
+
+```
+pki_storage_cert_path=kra_storage.crt
+pki_transport_cert_path=kra_transport.crt
+pki_subsystem_cert_path=subsystem.crt
+pki_sslserver_cert_path=sslserver.crt
+pki_audit_signing_cert_path=kra_audit_signing.crt
+pki_admin_cert_path=kra_admin.crt
+```
+
+Specify the external CA certificate chain with the following parameters:
+
+```
+pki_cert_chain_nickname=ca_signing
+pki_cert_chain_path=ca_signing.crt
+```
+
+Finally, execute the following command:
+
+```
+$ pkispawn -f kra-step2.cfg -s KRA
+```
+
+Verifying System Certificates
+-----------------------------
+
+Verify that the server NSS database contains the following certificates:
+
+```
+$ certutil -L -d /etc/pki/pki-tomcat/alias
+
+Certificate Nickname                                         Trust Attributes
+                                                             SSL,S/MIME,JAR/XPI
+
+ca_signing                                                   CT,C,C
+kra_storage                                                  CTu,Cu,Cu
+kra_transport                                                u,u,u
+subsystem                                                    u,u,u
+kra_audit_signing                                            u,u,Pu
+sslserver                                                    u,u,u
+```
+
+Verifying Admin Certificate
+---------------------------
+
+Prepare a client NSS database (e.g. ~/.dogtag/nssdb):
+
+```
+$ pki -c Secret.123 client-init
+```
+
+Import the external CA certificate chain:
+
+```
+$ pki -c Secret.123 client-cert-import --ca-cert ca_signing.crt
+```
+
+Import the admin key and certificate:
+
+```
+$ pki -c Secret.123 client-cert-import \
+ --pkcs12 ~/.dogtag/pki-tomcat/kra_admin_cert.p12 \
+ --pkcs12-password-file ~/.dogtag/pki-tomcat/ca/pkcs12_password.conf
+```
+
+Verify that the admin certificate can be used to access KRA by executing the following command:
+
+```
+$ pki -c Secret.123 -n kraadmin kra-user-show kraadmin
+---------------
+User "kraadmin"
+---------------
+  User ID: kraadmin
+  Full name: kraadmin
+  Email: kraadmin@example.com
+  Type: adminType
+  State: 1
+```
diff --git a/docs/installation/Installing_OCSP_with_Custom_Keys.md b/docs/installation/Installing_OCSP_with_Custom_Keys.md
new file mode 100644
index 0000000..dca4f79
--- /dev/null
+++ b/docs/installation/Installing_OCSP_with_Custom_Keys.md
@@ -0,0 +1,183 @@
+Installing OCSP with Custom Keys
+================================
+
+Overview
+--------
+
+This page describes the process to install a OCSP subsystem with custom OCSP system and admin keys, CSRs, and certificates.
+
+Starting OCSP Subsystem Installation
+------------------------------------
+
+Prepare a file (e.g. ocsp-step1.cfg) that contains the deployment configuration step 1, for example:
+
+```
+[DEFAULT]
+pki_server_database_password=Secret.123
+
+[OCSP]
+pki_admin_email=ocspadmin@example.com
+pki_admin_name=ocspadmin
+pki_admin_nickname=ocspadmin
+pki_admin_password=Secret.123
+pki_admin_uid=ocspadmin
+
+pki_client_database_password=Secret.123
+pki_client_database_purge=False
+pki_client_pkcs12_password=Secret.123
+
+pki_ds_base_dn=dc=ocsp,dc=pki,dc=example,dc=com
+pki_ds_database=ocsp
+pki_ds_password=Secret.123
+
+pki_security_domain_name=EXAMPLE
+pki_security_domain_user=caadmin
+pki_security_domain_password=Secret.123
+
+pki_ocsp_signing_nickname=ocsp_signing
+pki_subsystem_nickname=subsystem
+pki_sslserver_nickname=sslserver
+pki_audit_signing_nickname=ocsp_audit_signing
+
+pki_external=True
+pki_external_step_two=False
+```
+
+Then execute the following command:
+
+```
+$ pkispawn -f ocsp-step1.cfg -s OCSP
+```
+
+It will install OCSP subsystem in a Tomcat instance (default is pki-tomcat) and create the following NSS databases:
+* server NSS database: /etc/pki/pki-tomcat/alias
+* admin NSS database: ~/.dogtag/pki-tomcat/ocsp/alias
+
+Since there are no CSR path parameters specified, it will not generate the OCSP system and admin keys.
+
+Generating OCSP Keys, CSRs, and Certificates
+--------------------------------------------
+
+Generate custom OCSP system keys in the server NSS database and admin key in the admin NSS database, then generate the CSRs and store them in files, for example:
+* ocsp_signing.csr
+* subsystem.csr
+* sslserver.csr
+* ocsp_audit_signing.csr
+* ocsp_admin.csr
+
+Submit the CSRs to an external CA to issue the certificates, then store the certificates in files, for example:
+* ocsp_signing.crt
+* subsystem.crt
+* sslserver.crt
+* ocsp_audit_signing.crt
+* ocsp_admin.crt
+
+The certificates can be specified as single certificates or PKCS #7 certificate chains in PEM format.
+
+Store the external CA certificate chain in a file (e.g. ca_signing.crt). The certificate chain can be specified as a single certificate or PKCS #7 certificate chain in PEM format. The certificate chain should include all CA certificates from the root CA to the external CA that issued the OCSP system and admin certificates.
+
+See also:
+* [Generating OCSP Signing Certificate](http://www.dogtagpki.org/wiki/Generating_OCSP_Signing_Certificate)
+* [Generating Subsystem Certificate](http://www.dogtagpki.org/wiki/Generating_Subsystem_Certificate)
+* [Generating SSL Server Certificate](http://www.dogtagpki.org/wiki/Generating_SSL_Server_Certificate)
+* [Generating Audit Signing Certificate](http://www.dogtagpki.org/wiki/Generating_Audit_Signing_Certificate)
+* [Generating Admin Certificate](http://www.dogtagpki.org/wiki/Generating_Admin_Certificate)
+
+Finishing OCSP Subsystem Installation
+-------------------------------------
+
+Prepare another file (e.g. ocsp-step2.cfg) that contains the deployment configuration step 2. The file can be copied from step 1 (i.e. ocsp-step1.cfg) with additional changes below.
+
+Specify step 2 with the following parameter:
+
+```
+pki_external_step_two=True
+```
+
+Specify the custom CSRs with the following parameters:
+
+```
+pki_ocsp_signing_csr_path=ocsp_signing.csr
+pki_subsystem_csr_path=subsystem.csr
+pki_sslserver_csr_path=sslserver.csr
+pki_audit_signing_csr_path=ocsp_audit_signing.csr
+pki_admin_csr_path=ocsp_admin.csr
+```
+
+Specify the custom certificates with the following parameters:
+
+```
+pki_ocsp_signing_cert_path=ocsp_signing.crt
+pki_subsystem_cert_path=subsystem.crt
+pki_sslserver_cert_path=sslserver.crt
+pki_audit_signing_cert_path=ocsp_audit_signing.crt
+pki_admin_cert_path=ocsp_admin.crt
+```
+
+Specify the external CA certificate chain with the following parameters:
+
+```
+pki_cert_chain_nickname=ca_signing
+pki_cert_chain_path=ca_signing.crt
+```
+
+Finally, execute the following command:
+
+```
+$ pkispawn -f ocsp-step2.cfg -s OCSP
+```
+
+Verifying System Certificates
+-----------------------------
+
+Verify that the server NSS database contains the following certificates:
+
+```
+$ certutil -L -d /etc/pki/pki-tomcat/alias
+
+Certificate Nickname                                         Trust Attributes
+                                                             SSL,S/MIME,JAR/XPI
+
+ca_signing                                                   CT,C,C
+ocsp_signing                                                 CTu,Cu,Cu
+subsystem                                                    u,u,u
+ocsp_audit_signing                                           u,u,Pu
+sslserver                                                    u,u,u
+```
+
+Verifying Admin Certificate
+---------------------------
+
+Prepare a client NSS database (e.g. ~/.dogtag/nssdb):
+
+```
+$ pki -c Secret.123 client-init
+```
+
+Import the external CA certificate chain:
+
+```
+$ pki -c Secret.123 client-cert-import --ca-cert ca_signing.crt
+```
+
+Import the admin key and certificate:
+
+```
+$ pki -c Secret.123 client-cert-import \
+ --pkcs12 ~/.dogtag/pki-tomcat/ocsp_admin_cert.p12 \
+ --pkcs12-password-file ~/.dogtag/pki-tomcat/ca/pkcs12_password.conf
+```
+
+Verify that the admin certificate can be used to access the OCSP subsystem by executing the following command:
+
+```
+$ pki -c Secret.123 -n ocspadmin ocsp-user-show ocspadmin
+----------------
+User "ocspadmin"
+----------------
+  User ID: ocspadmin
+  Full name: ocspadmin
+  Email: ocspadmin@example.com
+  Type: adminType
+  State: 1
+```
-- 
1.8.3.1


From 253f16813de60b1951b769a437c92322e36647bf Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 9 Nov 2018 11:06:57 -0800
Subject: [PATCH 13/13] bug 1653863 tools supporting CMC requests output keyID
 needs to be captured in file

This patch adds code in both CRMFPopClient and PKCS10Client to automatically
write the private key id into a file named <output>.keyId so that
they can be featched later for CMCRequest
<output>is the name of the file specified with the "-o" option.

This patch also changed all references from "CMC self-test" to
"CMC shared secret" instead.

A test feature is also added to CMCRequest.

fixes https://bugzilla.redhat.com/show_bug.cgi?id=1655951

Change-Id: Iaf2772be54f9937da456655cdec688f13f6e8b71
(cherry picked from commit cb99e112b9421f6fe98b4ac5ab5885c28ee958c3)
---
 base/ca/shared/conf/CS.cfg                         |  10 +-
 base/ca/shared/conf/registry.cfg                   |   8 +-
 .../profiles/ca/caECFullCMCSelfSignedCert.cfg      |  82 --------
 .../profiles/ca/caECFullCMCSharedTokenCert.cfg     |  82 ++++++++
 .../shared/profiles/ca/caFullCMCSelfSignedCert.cfg |  82 --------
 .../profiles/ca/caFullCMCSharedTokenCert.cfg       |  82 ++++++++
 base/java-tools/man/man1/CMCRequest.1              |  22 +-
 base/java-tools/man/man1/PKCS10Client.1            |   3 +-
 .../src/com/netscape/cmstools/CMCRequest.java      | 227 ++++++++++++++++-----
 .../src/com/netscape/cmstools/CRMFPopClient.java   |  22 +-
 .../src/com/netscape/cmstools/PKCS10Client.java    |  24 ++-
 .../CMCSelfSignedSubjectNameConstraint.java        | 129 ------------
 .../CMCSharedTokenSubjectNameConstraint.java       | 130 ++++++++++++
 13 files changed, 526 insertions(+), 377 deletions(-)
 delete mode 100644 base/ca/shared/profiles/ca/caECFullCMCSelfSignedCert.cfg
 create mode 100644 base/ca/shared/profiles/ca/caECFullCMCSharedTokenCert.cfg
 delete mode 100644 base/ca/shared/profiles/ca/caFullCMCSelfSignedCert.cfg
 create mode 100644 base/ca/shared/profiles/ca/caFullCMCSharedTokenCert.cfg
 delete mode 100644 base/server/cms/src/com/netscape/cms/profile/constraint/CMCSelfSignedSubjectNameConstraint.java
 create mode 100644 base/server/cms/src/com/netscape/cms/profile/constraint/CMCSharedTokenSubjectNameConstraint.java

diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
index 4cef240..29d4fd4 100644
--- a/base/ca/shared/conf/CS.cfg
+++ b/base/ca/shared/conf/CS.cfg
@@ -975,7 +975,7 @@ oidmap.pse.oid=2.16.840.1.113730.1.18
 oidmap.subject_info_access.class=netscape.security.extensions.SubjectInfoAccessExtension
 oidmap.subject_info_access.oid=1.3.6.1.5.5.7.1.11
 os.userid=nobody
-profile.list=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSelfSignedCert,caECFullCMCSelfSignedCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment
+profile.list=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSharedTokenCert,caECFullCMCSharedTokenCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment
 profile.caUUIDdeviceCert.class_id=caEnrollImpl
 profile.caUUIDdeviceCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caUUIDdeviceCert.cfg
 profile.caManualRenewal.class_id=caEnrollImpl
@@ -1050,10 +1050,10 @@ profile.caFullCMCUserSignedCert.class_id=caEnrollImpl
 profile.caFullCMCUserSignedCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caFullCMCUserSignedCert.cfg
 profile.caECFullCMCUserSignedCert.class_id=caEnrollImpl
 profile.caECFullCMCUserSignedCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caECFullCMCUserSignedCert.cfg
-profile.caFullCMCSelfSignedCert.class_id=caEnrollImpl
-profile.caFullCMCSelfSignedCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caFullCMCSelfSignedCert.cfg
-profile.caECFullCMCSelfSignedCert.class_id=caEnrollImpl
-profile.caECFullCMCSelfSignedCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caECFullCMCSelfSignedCert.cfg
+profile.caFullCMCSharedTokenCert.class_id=caEnrollImpl
+profile.caFullCMCSharedTokenCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caFullCMCSharedTokenCert.cfg
+profile.caECFullCMCSharedTokenCert.class_id=caEnrollImpl
+profile.caECFullCMCSharedTokenCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caECFullCMCSharedTokenCert.cfg
 profile.caInternalAuthOCSPCert.class_id=caEnrollImpl
 profile.caInternalAuthOCSPCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caInternalAuthOCSPCert.cfg
 profile.caInternalAuthAuditSigningCert.class_id=caEnrollImpl
diff --git a/base/ca/shared/conf/registry.cfg b/base/ca/shared/conf/registry.cfg
index 4fe6e93..a78af86 100644
--- a/base/ca/shared/conf/registry.cfg
+++ b/base/ca/shared/conf/registry.cfg
@@ -1,5 +1,5 @@
 types=profile,defaultPolicy,constraintPolicy,profileInput,profileOutput,profileUpdater
-constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,cmcSelfSignedSubjectNameConstraintImpl,cmcUserSignedSubjectNameConstraintImpl,caValidityConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl,externalProcessConstraintImpl
+constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,cmcSharedTokenSubjectNameConstraintImpl,cmcUserSignedSubjectNameConstraintImpl,caValidityConstraintImpl,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl,externalProcessConstraintImpl
 constraintPolicy.signingAlgConstraintImpl.class=com.netscape.cms.profile.constraint.SigningAlgConstraint
 constraintPolicy.signingAlgConstraintImpl.desc=Signing Algorithm Constraint
 constraintPolicy.signingAlgConstraintImpl.name=Signing Algorithm Constraint
@@ -36,9 +36,9 @@ constraintPolicy.uniqueSubjectNameConstraintImpl.name=Unique Subject Name Constr
 constraintPolicy.userSubjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.UserSubjectNameConstraint
 constraintPolicy.userSubjectNameConstraintImpl.desc=User Subject Name Constraint
 constraintPolicy.userSubjectNameConstraintImpl.name=User Subject Name Constraint
-constraintPolicy.cmcSelfSignedSubjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.CMCSelfSignedSubjectNameConstraint
-constraintPolicy.cmcSelfSignedSubjectNameConstraintImpl.desc=CMC Self-Signed request User Subject Name Constraint
-constraintPolicy.cmcSelfSignedSubjectNameConstraintImpl.name=CMC Self-Signed request User Subject Name Constraint
+constraintPolicy.cmcSharedTokenSubjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.CMCSharedTokenSubjectNameConstraint
+constraintPolicy.cmcSharedTokenSubjectNameConstraintImpl.desc=CMC Shared Token request User Subject Name Constraint
+constraintPolicy.cmcSharedTokenSubjectNameConstraintImpl.name=CMC Shared Token request User Subject Name Constraint
 constraintPolicy.cmcUserSignedSubjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.CMCUserSignedSubjectNameConstraint
 constraintPolicy.cmcUserSignedSubjectNameConstraintImpl.desc=CMC User-Signed request User Subject Name Constraint
 constraintPolicy.cmcUserSignedSubjectNameConstraintImpl.name=CMC User-Signed request User Subject Name Constraint
diff --git a/base/ca/shared/profiles/ca/caECFullCMCSelfSignedCert.cfg b/base/ca/shared/profiles/ca/caECFullCMCSelfSignedCert.cfg
deleted file mode 100644
index b3cc471..0000000
--- a/base/ca/shared/profiles/ca/caECFullCMCSelfSignedCert.cfg
+++ /dev/null
@@ -1,82 +0,0 @@
-desc=This certificate profile is for enrolling user certificates with ECC keys by using the self-signed CMC certificate request
-enable=false
-enableBy=admin
-name=Self-Signed CMC User Certificate Enrollment
-visible=false
-auth.instance_id=CMCUserSignedAuth
-input.list=i1
-input.i1.class_id=cmcCertReqInputImpl
-output.list=o1
-output.o1.class_id=certOutputImpl
-policyset.list=cmcUserCertSet
-policyset.cmcUserCertSet.list=1,2,3,4,5,6,7,8
-policyset.cmcUserCertSet.1.constraint.class_id=cmcSelfSignedSubjectNameConstraintImpl
-policyset.cmcUserCertSet.1.constraint.name=CMC User-Signed Subject Name Constraint
-policyset.cmcUserCertSet.1.default.class_id=authTokenSubjectNameDefaultImpl
-policyset.cmcUserCertSet.1.default.name=Subject Name Default
-policyset.cmcUserCertSet.1.default.params.name=
-policyset.cmcUserCertSet.2.constraint.class_id=validityConstraintImpl
-policyset.cmcUserCertSet.2.constraint.name=Validity Constraint
-policyset.cmcUserCertSet.2.constraint.params.notAfterCheck=false
-policyset.cmcUserCertSet.2.constraint.params.notBeforeCheck=false
-policyset.cmcUserCertSet.2.constraint.params.range=365
-policyset.cmcUserCertSet.2.default.class_id=validityDefaultImpl
-policyset.cmcUserCertSet.2.default.name=Validity Default
-policyset.cmcUserCertSet.2.default.params.range=180
-policyset.cmcUserCertSet.2.default.params.startTime=0
-policyset.cmcUserCertSet.3.constraint.class_id=keyConstraintImpl
-policyset.cmcUserCertSet.3.constraint.name=Key Constraint
-policyset.cmcUserCertSet.3.constraint.params.keyParameters=nistp256,nistp521
-policyset.cmcUserCertSet.3.constraint.params.keyType=EC
-policyset.cmcUserCertSet.3.default.class_id=userKeyDefaultImpl
-policyset.cmcUserCertSet.3.default.name=Key Default
-policyset.cmcUserCertSet.4.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.4.constraint.name=No Constraint
-policyset.cmcUserCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
-policyset.cmcUserCertSet.4.default.name=Authority Key Identifier Default
-policyset.cmcUserCertSet.5.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.5.constraint.name=No Constraint
-policyset.cmcUserCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
-policyset.cmcUserCertSet.5.default.name=AIA Extension Default
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADEnable_0=true
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocation_0=
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
-policyset.cmcUserCertSet.5.default.params.authInfoAccessCritical=false
-policyset.cmcUserCertSet.5.default.params.authInfoAccessNumADs=1
-policyset.cmcUserCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
-policyset.cmcUserCertSet.6.constraint.name=Key Usage Extension Constraint
-policyset.cmcUserCertSet.6.constraint.params.keyUsageCritical=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageCrlSign=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDataEncipherment=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDecipherOnly=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDigitalSignature=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageEncipherOnly=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyAgreement=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyCertSign=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyEncipherment=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageNonRepudiation=true
-policyset.cmcUserCertSet.6.default.class_id=keyUsageExtDefaultImpl
-policyset.cmcUserCertSet.6.default.name=Key Usage Default
-policyset.cmcUserCertSet.6.default.params.keyUsageCritical=true
-policyset.cmcUserCertSet.6.default.params.keyUsageCrlSign=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDataEncipherment=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDecipherOnly=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDigitalSignature=true
-policyset.cmcUserCertSet.6.default.params.keyUsageEncipherOnly=false
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyAgreement=true
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyCertSign=false
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyEncipherment=false
-policyset.cmcUserCertSet.6.default.params.keyUsageNonRepudiation=true
-policyset.cmcUserCertSet.7.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.7.constraint.name=No Constraint
-policyset.cmcUserCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
-policyset.cmcUserCertSet.7.default.name=Extended Key Usage Extension Default
-policyset.cmcUserCertSet.7.default.params.exKeyUsageCritical=false
-policyset.cmcUserCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
-policyset.cmcUserCertSet.8.constraint.class_id=signingAlgConstraintImpl
-policyset.cmcUserCertSet.8.constraint.name=No Constraint
-policyset.cmcUserCertSet.8.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA512withRSA,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC
-policyset.cmcUserCertSet.8.default.class_id=signingAlgDefaultImpl
-policyset.cmcUserCertSet.8.default.name=Signing Alg
-policyset.cmcUserCertSet.8.default.params.signingAlg=-
diff --git a/base/ca/shared/profiles/ca/caECFullCMCSharedTokenCert.cfg b/base/ca/shared/profiles/ca/caECFullCMCSharedTokenCert.cfg
new file mode 100644
index 0000000..ffdccb1
--- /dev/null
+++ b/base/ca/shared/profiles/ca/caECFullCMCSharedTokenCert.cfg
@@ -0,0 +1,82 @@
+desc=This certificate profile is for enrolling user certificates with ECC keys by using the CMC Shared Token certificate request
+enable=false
+enableBy=admin
+name=CMC Shared Token User Certificate Enrollment
+visible=false
+auth.instance_id=CMCUserSignedAuth
+input.list=i1
+input.i1.class_id=cmcCertReqInputImpl
+output.list=o1
+output.o1.class_id=certOutputImpl
+policyset.list=cmcUserCertSet
+policyset.cmcUserCertSet.list=1,2,3,4,5,6,7,8
+policyset.cmcUserCertSet.1.constraint.class_id=cmcSharedTokenSubjectNameConstraintImpl
+policyset.cmcUserCertSet.1.constraint.name=CMC Shared Token Subject Name Constraint
+policyset.cmcUserCertSet.1.default.class_id=authTokenSubjectNameDefaultImpl
+policyset.cmcUserCertSet.1.default.name=Subject Name Default
+policyset.cmcUserCertSet.1.default.params.name=
+policyset.cmcUserCertSet.2.constraint.class_id=validityConstraintImpl
+policyset.cmcUserCertSet.2.constraint.name=Validity Constraint
+policyset.cmcUserCertSet.2.constraint.params.notAfterCheck=false
+policyset.cmcUserCertSet.2.constraint.params.notBeforeCheck=false
+policyset.cmcUserCertSet.2.constraint.params.range=365
+policyset.cmcUserCertSet.2.default.class_id=validityDefaultImpl
+policyset.cmcUserCertSet.2.default.name=Validity Default
+policyset.cmcUserCertSet.2.default.params.range=180
+policyset.cmcUserCertSet.2.default.params.startTime=0
+policyset.cmcUserCertSet.3.constraint.class_id=keyConstraintImpl
+policyset.cmcUserCertSet.3.constraint.name=Key Constraint
+policyset.cmcUserCertSet.3.constraint.params.keyParameters=nistp256,nistp521
+policyset.cmcUserCertSet.3.constraint.params.keyType=EC
+policyset.cmcUserCertSet.3.default.class_id=userKeyDefaultImpl
+policyset.cmcUserCertSet.3.default.name=Key Default
+policyset.cmcUserCertSet.4.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.4.constraint.name=No Constraint
+policyset.cmcUserCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
+policyset.cmcUserCertSet.4.default.name=Authority Key Identifier Default
+policyset.cmcUserCertSet.5.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.5.constraint.name=No Constraint
+policyset.cmcUserCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
+policyset.cmcUserCertSet.5.default.name=AIA Extension Default
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADEnable_0=true
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocation_0=
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
+policyset.cmcUserCertSet.5.default.params.authInfoAccessCritical=false
+policyset.cmcUserCertSet.5.default.params.authInfoAccessNumADs=1
+policyset.cmcUserCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
+policyset.cmcUserCertSet.6.constraint.name=Key Usage Extension Constraint
+policyset.cmcUserCertSet.6.constraint.params.keyUsageCritical=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageCrlSign=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDataEncipherment=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDecipherOnly=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDigitalSignature=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageEncipherOnly=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyAgreement=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyCertSign=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyEncipherment=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageNonRepudiation=true
+policyset.cmcUserCertSet.6.default.class_id=keyUsageExtDefaultImpl
+policyset.cmcUserCertSet.6.default.name=Key Usage Default
+policyset.cmcUserCertSet.6.default.params.keyUsageCritical=true
+policyset.cmcUserCertSet.6.default.params.keyUsageCrlSign=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDataEncipherment=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDecipherOnly=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDigitalSignature=true
+policyset.cmcUserCertSet.6.default.params.keyUsageEncipherOnly=false
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyAgreement=true
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyCertSign=false
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyEncipherment=false
+policyset.cmcUserCertSet.6.default.params.keyUsageNonRepudiation=true
+policyset.cmcUserCertSet.7.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.7.constraint.name=No Constraint
+policyset.cmcUserCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
+policyset.cmcUserCertSet.7.default.name=Extended Key Usage Extension Default
+policyset.cmcUserCertSet.7.default.params.exKeyUsageCritical=false
+policyset.cmcUserCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
+policyset.cmcUserCertSet.8.constraint.class_id=signingAlgConstraintImpl
+policyset.cmcUserCertSet.8.constraint.name=No Constraint
+policyset.cmcUserCertSet.8.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA512withRSA,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC
+policyset.cmcUserCertSet.8.default.class_id=signingAlgDefaultImpl
+policyset.cmcUserCertSet.8.default.name=Signing Alg
+policyset.cmcUserCertSet.8.default.params.signingAlg=-
diff --git a/base/ca/shared/profiles/ca/caFullCMCSelfSignedCert.cfg b/base/ca/shared/profiles/ca/caFullCMCSelfSignedCert.cfg
deleted file mode 100644
index 538b16a..0000000
--- a/base/ca/shared/profiles/ca/caFullCMCSelfSignedCert.cfg
+++ /dev/null
@@ -1,82 +0,0 @@
-desc=This certificate profile is for enrolling user certificates by using the self-signed CMC certificate request
-enable=false
-enableBy=admin
-name=Self-Signed CMC User Certificate Enrollment
-visible=false
-auth.instance_id=CMCUserSignedAuth
-input.list=i1
-input.i1.class_id=cmcCertReqInputImpl
-output.list=o1
-output.o1.class_id=certOutputImpl
-policyset.list=cmcUserCertSet
-policyset.cmcUserCertSet.list=1,2,3,4,5,6,7,8
-policyset.cmcUserCertSet.1.constraint.class_id=cmcSelfSignedSubjectNameConstraintImpl
-policyset.cmcUserCertSet.1.constraint.name=CMC Self-Signed Subject Name Constraint
-policyset.cmcUserCertSet.1.default.class_id=authTokenSubjectNameDefaultImpl
-policyset.cmcUserCertSet.1.default.name=Subject Name Default
-policyset.cmcUserCertSet.1.default.params.name=
-policyset.cmcUserCertSet.2.constraint.class_id=validityConstraintImpl
-policyset.cmcUserCertSet.2.constraint.name=Validity Constraint
-policyset.cmcUserCertSet.2.constraint.params.notAfterCheck=false
-policyset.cmcUserCertSet.2.constraint.params.notBeforeCheck=false
-policyset.cmcUserCertSet.2.constraint.params.range=365
-policyset.cmcUserCertSet.2.default.class_id=validityDefaultImpl
-policyset.cmcUserCertSet.2.default.name=Validity Default
-policyset.cmcUserCertSet.2.default.params.range=180
-policyset.cmcUserCertSet.2.default.params.startTime=0
-policyset.cmcUserCertSet.3.constraint.class_id=keyConstraintImpl
-policyset.cmcUserCertSet.3.constraint.name=Key Constraint
-policyset.cmcUserCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096
-policyset.cmcUserCertSet.3.constraint.params.keyType=RSA
-policyset.cmcUserCertSet.3.default.class_id=userKeyDefaultImpl
-policyset.cmcUserCertSet.3.default.name=Key Default
-policyset.cmcUserCertSet.4.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.4.constraint.name=No Constraint
-policyset.cmcUserCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
-policyset.cmcUserCertSet.4.default.name=Authority Key Identifier Default
-policyset.cmcUserCertSet.5.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.5.constraint.name=No Constraint
-policyset.cmcUserCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
-policyset.cmcUserCertSet.5.default.name=AIA Extension Default
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADEnable_0=true
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocation_0=
-policyset.cmcUserCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
-policyset.cmcUserCertSet.5.default.params.authInfoAccessCritical=false
-policyset.cmcUserCertSet.5.default.params.authInfoAccessNumADs=1
-policyset.cmcUserCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
-policyset.cmcUserCertSet.6.constraint.name=Key Usage Extension Constraint
-policyset.cmcUserCertSet.6.constraint.params.keyUsageCritical=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageCrlSign=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDataEncipherment=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDecipherOnly=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageDigitalSignature=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageEncipherOnly=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyAgreement=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyCertSign=false
-policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyEncipherment=true
-policyset.cmcUserCertSet.6.constraint.params.keyUsageNonRepudiation=true
-policyset.cmcUserCertSet.6.default.class_id=keyUsageExtDefaultImpl
-policyset.cmcUserCertSet.6.default.name=Key Usage Default
-policyset.cmcUserCertSet.6.default.params.keyUsageCritical=true
-policyset.cmcUserCertSet.6.default.params.keyUsageCrlSign=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDataEncipherment=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDecipherOnly=false
-policyset.cmcUserCertSet.6.default.params.keyUsageDigitalSignature=true
-policyset.cmcUserCertSet.6.default.params.keyUsageEncipherOnly=false
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyAgreement=false
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyCertSign=false
-policyset.cmcUserCertSet.6.default.params.keyUsageKeyEncipherment=true
-policyset.cmcUserCertSet.6.default.params.keyUsageNonRepudiation=true
-policyset.cmcUserCertSet.7.constraint.class_id=noConstraintImpl
-policyset.cmcUserCertSet.7.constraint.name=No Constraint
-policyset.cmcUserCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
-policyset.cmcUserCertSet.7.default.name=Extended Key Usage Extension Default
-policyset.cmcUserCertSet.7.default.params.exKeyUsageCritical=false
-policyset.cmcUserCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
-policyset.cmcUserCertSet.8.constraint.class_id=signingAlgConstraintImpl
-policyset.cmcUserCertSet.8.constraint.name=No Constraint
-policyset.cmcUserCertSet.8.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA512withRSA,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC
-policyset.cmcUserCertSet.8.default.class_id=signingAlgDefaultImpl
-policyset.cmcUserCertSet.8.default.name=Signing Alg
-policyset.cmcUserCertSet.8.default.params.signingAlg=-
diff --git a/base/ca/shared/profiles/ca/caFullCMCSharedTokenCert.cfg b/base/ca/shared/profiles/ca/caFullCMCSharedTokenCert.cfg
new file mode 100644
index 0000000..5ef8004
--- /dev/null
+++ b/base/ca/shared/profiles/ca/caFullCMCSharedTokenCert.cfg
@@ -0,0 +1,82 @@
+desc=This certificate profile is for enrolling user certificates by using the CMC Shared Token certificate request
+enable=false
+enableBy=admin
+name=CMC Shared Token User Certificate Enrollment
+visible=false
+auth.instance_id=CMCUserSignedAuth
+input.list=i1
+input.i1.class_id=cmcCertReqInputImpl
+output.list=o1
+output.o1.class_id=certOutputImpl
+policyset.list=cmcUserCertSet
+policyset.cmcUserCertSet.list=1,2,3,4,5,6,7,8
+policyset.cmcUserCertSet.1.constraint.class_id=cmcSharedTokenSubjectNameConstraintImpl
+policyset.cmcUserCertSet.1.constraint.name=CMC Shared Token Subject Name Constraint
+policyset.cmcUserCertSet.1.default.class_id=authTokenSubjectNameDefaultImpl
+policyset.cmcUserCertSet.1.default.name=Subject Name Default
+policyset.cmcUserCertSet.1.default.params.name=
+policyset.cmcUserCertSet.2.constraint.class_id=validityConstraintImpl
+policyset.cmcUserCertSet.2.constraint.name=Validity Constraint
+policyset.cmcUserCertSet.2.constraint.params.notAfterCheck=false
+policyset.cmcUserCertSet.2.constraint.params.notBeforeCheck=false
+policyset.cmcUserCertSet.2.constraint.params.range=365
+policyset.cmcUserCertSet.2.default.class_id=validityDefaultImpl
+policyset.cmcUserCertSet.2.default.name=Validity Default
+policyset.cmcUserCertSet.2.default.params.range=180
+policyset.cmcUserCertSet.2.default.params.startTime=0
+policyset.cmcUserCertSet.3.constraint.class_id=keyConstraintImpl
+policyset.cmcUserCertSet.3.constraint.name=Key Constraint
+policyset.cmcUserCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096
+policyset.cmcUserCertSet.3.constraint.params.keyType=RSA
+policyset.cmcUserCertSet.3.default.class_id=userKeyDefaultImpl
+policyset.cmcUserCertSet.3.default.name=Key Default
+policyset.cmcUserCertSet.4.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.4.constraint.name=No Constraint
+policyset.cmcUserCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
+policyset.cmcUserCertSet.4.default.name=Authority Key Identifier Default
+policyset.cmcUserCertSet.5.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.5.constraint.name=No Constraint
+policyset.cmcUserCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
+policyset.cmcUserCertSet.5.default.name=AIA Extension Default
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADEnable_0=true
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADLocation_0=
+policyset.cmcUserCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
+policyset.cmcUserCertSet.5.default.params.authInfoAccessCritical=false
+policyset.cmcUserCertSet.5.default.params.authInfoAccessNumADs=1
+policyset.cmcUserCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
+policyset.cmcUserCertSet.6.constraint.name=Key Usage Extension Constraint
+policyset.cmcUserCertSet.6.constraint.params.keyUsageCritical=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageCrlSign=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDataEncipherment=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDecipherOnly=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageDigitalSignature=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageEncipherOnly=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyAgreement=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyCertSign=false
+policyset.cmcUserCertSet.6.constraint.params.keyUsageKeyEncipherment=true
+policyset.cmcUserCertSet.6.constraint.params.keyUsageNonRepudiation=true
+policyset.cmcUserCertSet.6.default.class_id=keyUsageExtDefaultImpl
+policyset.cmcUserCertSet.6.default.name=Key Usage Default
+policyset.cmcUserCertSet.6.default.params.keyUsageCritical=true
+policyset.cmcUserCertSet.6.default.params.keyUsageCrlSign=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDataEncipherment=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDecipherOnly=false
+policyset.cmcUserCertSet.6.default.params.keyUsageDigitalSignature=true
+policyset.cmcUserCertSet.6.default.params.keyUsageEncipherOnly=false
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyAgreement=false
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyCertSign=false
+policyset.cmcUserCertSet.6.default.params.keyUsageKeyEncipherment=true
+policyset.cmcUserCertSet.6.default.params.keyUsageNonRepudiation=true
+policyset.cmcUserCertSet.7.constraint.class_id=noConstraintImpl
+policyset.cmcUserCertSet.7.constraint.name=No Constraint
+policyset.cmcUserCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
+policyset.cmcUserCertSet.7.default.name=Extended Key Usage Extension Default
+policyset.cmcUserCertSet.7.default.params.exKeyUsageCritical=false
+policyset.cmcUserCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
+policyset.cmcUserCertSet.8.constraint.class_id=signingAlgConstraintImpl
+policyset.cmcUserCertSet.8.constraint.name=No Constraint
+policyset.cmcUserCertSet.8.constraint.params.signingAlgsAllowed=SHA256withRSA,SHA512withRSA,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC
+policyset.cmcUserCertSet.8.default.class_id=signingAlgDefaultImpl
+policyset.cmcUserCertSet.8.default.name=Signing Alg
+policyset.cmcUserCertSet.8.default.params.signingAlg=-
diff --git a/base/java-tools/man/man1/CMCRequest.1 b/base/java-tools/man/man1/CMCRequest.1
index 8c67fc0..18f5e50 100644
--- a/base/java-tools/man/man1/CMCRequest.1
+++ b/base/java-tools/man/man1/CMCRequest.1
@@ -63,7 +63,7 @@ name of crypto token where user signing certificate key can be found (default is
 .B nickname
 The nickname of the user certificate that corresponds to the private key that is used to sign the request.
 
-This parameter is ignored if \fBselfSign\fP or \fBidentityProofV2.enable\fP is true.
+This parameter is ignored if \fBuseSharedSecret\fP or \fBidentityProofV2.enable\fP is true.
 
 .TP
 .B password
@@ -114,27 +114,27 @@ Supported keyGenAlg are: \fBSHA-256, SHA-384, and SHA-512\fP
 Supported macAlg are: \fBSHA-256-HMAC, SHA-384-HMAC, and SHA-512-HMAC\fP
 
 .TP
-.B request.selfSign
-\fBtrue\fP or \fBfalse\fP.  If \fBselfSign\fP is true, the CMC request will be "signed" with the pairing private key of the enrollment request; and in which case the \fBnickname\fP parameter will be ignored.
+.B request.useSharedSecret
+\fBtrue\fP or \fBfalse\fP.  If \fBuseSharedSecret\fP is true, the CMC request will be "signed" with the pairing private key of the enrollment request; and in which case the \fBnickname\fP parameter will be ignored.
 
-\fBrequest.selfSign\fP is only used if a signing certificate (of the agent or user herself) is not available to sign. Because the request itself is not signed with a certificate (a proven identity), the proof of origin (proof of identification) must be provided by some other means.
+\fBrequest.useSharedSecret\fP is only used if a signing certificate (of the agent or user herself) is not available to sign. Because the request itself is not signed with a certificate (a proven identity), the proof of origin (proof of identification) must be provided by some other means.
 
-In Dogtag, if \fBselfSign\fP is true, it must be used in conjunction with the \fBidentityProofV2\fP and \fBidentification\fP parameters.  And in that case the Proof Of Origin is accomplished by the Shared Secret (\fBwitness.sharedSecret\fP) mechanism.
+In Dogtag, if \fBrequest.useSharedSecret\fP is true, it must be used in conjunction with the \fBidentityProofV2\fP and \fBidentification\fP parameters.  And in that case the Proof Of Origin is accomplished by the Shared Secret (\fBwitness.sharedSecret\fP) mechanism.
 
-The \fBselfSign\fP option is normally used to enroll for a user's first signing certificate while auto-approval (without agent's pre-approval) is preferred. In general, once a user has obtained the first signing certificate, such signing certificate can be used to sign (thus proving origin) and obtain other certificate such as encryption-only ceritifcate, or when doing a renewal or revocation.
+The \fBrequest.useSharedSecret\fP option is normally used to enroll for a user's first signing certificate while auto-approval (without agent's pre-approval) is preferred. In general, once a user has obtained the first signing certificate, such signing certificate can be used to sign (thus proving origin) and obtain other certificate such as encryption-only ceritifcate, or when doing a renewal or revocation.
 
-By default, if unspecified, \fBselfSign\fP is false.
+By default, if unspecified, \fBrequest.useSharedSecret\fP is false.
 
-\fBNote\fP: to employ the \fBselfSign\fP option, the PKCS#10 or CRMF requests must have the \fBSubjectKeyIdentifier extension\fP. (hint: \fBCRMFPopClient\fP and \fBPKCS10Client\fP should be called with the "-y" option)
+\fBNote\fP: to employ the \fBrequest.useSharedSecret\fP option, the PKCS#10 or CRMF requests must have the \fBSubjectKeyIdentifier extension\fP. (hint: \fBCRMFPopClient\fP and \fBPKCS10Client\fP should be called with the "-y" option)
 
-If \fBselfSign\fP is true, \fBrequest.privKeyId\fP must be specified.
+If \fBrequest.useSharedSecret\fP is true, \fBrequest.privKeyId\fP must be specified.
 It is crutial that the caller that employs this option has access to the private key of the certificate request.
 
 .TP
 .B request.privKeyId
 The \fBrequest.privKeyId\fP parameter is required in the following cases:
 
-\fBselfSign\fP, \fBpopLinkWitnessV2\fP, and \fBdecryptedPop\fP
+\fBrequest.useSharedSecret\fP, \fBpopLinkWitnessV2\fP, and \fBdecryptedPop\fP
 
 .TP
 .B decryptedPop.enable, encryptedPopResponseFile, decryptedPopRequestFile
@@ -149,7 +149,7 @@ When preparing for the second trip, the following parameters must be present:
 
 \fBrequest.privKeyId\fP - see descripton for \fBrequest.privKeyId\fP; It is used to decrypt the EncryptedPop, thereby proving the possession of the private key.
 
-Please note that the \fBPopLinkWitnessV2\fP control as well as the \fBselfSign\fP directive do not apply to EncryptedPOP/DecryptedPOP for the simple fact that the enrollment private key is not capable of signing.
+Please note that the \fBPopLinkWitnessV2\fP control as well as the \fBrequest.useSharedSecret\fP directive do not apply to EncryptedPOP/DecryptedPOP for the simple fact that the enrollment private key is not capable of signing.
 
 .TP
 .B revRequest.[enable, serial, reason, comment, issuer, sharedSecret]
diff --git a/base/java-tools/man/man1/PKCS10Client.1 b/base/java-tools/man/man1/PKCS10Client.1
index e85c833..122680c 100644
--- a/base/java-tools/man/man1/PKCS10Client.1
+++ b/base/java-tools/man/man1/PKCS10Client.1
@@ -84,7 +84,8 @@ Gives the subject DN of the certificate.
 .B -x <true for SSL cert that does ECDH ECDSA; false otherwise; default false>
 
 .TP
-.B -y <true for adding SubjectKeyIdentifier extensionfor self-signed cmc requests; false otherwise; default false>
+.B -y <true for adding SubjectKeyIdentifier extensionfor self-signed cmc Shared Secret requests; false otherwise; default false>
+To be used with "request.useSharedSecret=true" when running CMCRequest.
 
 .SH AUTHORS
 Amol Kahat <akahat@redhat.com>.
diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
index 4e40143..1070a93 100644
--- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
+++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java
@@ -268,13 +268,19 @@ public class CMCRequest {
     }
 
     /*
-     * signData self-signs the PKIData using the private key that matches
-     * the public key in the request
+     * signData self-signs (for Shared Token) the PKIData using the private key
+     * that matches the public key in the request
      */
     static SignedData signData(
             java.security.PrivateKey privKey,
             PKIData pkidata) {
-        String method = "signData for selfSign: ";
+        return signData(privKey, pkidata, null);
+    }
+    static SignedData signData(
+            java.security.PrivateKey privKey,
+            PKIData pkidata,
+            SignerIdentifier test_cmc_si /*for TEST_CMC use_shared_secret case only*/) {
+        String method = "signData for useSharedSecret begins: ";
         System.out.println(method + "begins: ");
         SignedData req = null;
 
@@ -286,10 +292,15 @@ public class CMCRequest {
 
         KeyIdentifier keyIdObj = null;
         try {
-            keyIdObj = (KeyIdentifier) skiExtn.get(SubjectKeyIdentifierExtension.KEY_ID);
-            SignerIdentifier si = new SignerIdentifier(
+            SignerIdentifier si = null;
+            if (test_cmc_si == null) {
+                keyIdObj = (KeyIdentifier) skiExtn.get(SubjectKeyIdentifierExtension.KEY_ID);
+                si = new SignerIdentifier(
                     SignerIdentifier.SUBJECT_KEY_IDENTIFIER,
                     null, new OCTET_STRING(keyIdObj.getIdentifier()));
+            } else //TEST_CMC use_shared_secret case
+                si = test_cmc_si;
+
             req = createSignedData(privKey, si, null /*certChain*/, pkidata);
         } catch (Exception e) {
             e.printStackTrace();
@@ -430,7 +441,7 @@ public class CMCRequest {
      * @return request in PKIData
      */
     static PKIData createPKIData(
-            String selfSign,
+            String useSharedSecret,
             String[] rValue, String format, String transactionMgtEnable,
             String transactionMgtId,
             String identificationEnable, String identification,
@@ -495,16 +506,16 @@ public class CMCRequest {
 
                         CertRequest certReq = certReqMsg.getCertReq();
                         CertTemplate certTemplate = certReq.getCertTemplate();
-                        if (selfSign.equals("true")) {
+                        if (useSharedSecret.equals("true")) {
                             skiExtn = (SubjectKeyIdentifierExtension) CryptoUtil.getExtensionFromCertTemplate(
                                     certTemplate,
                                     PKIXExtensions.SubjectKey_Id);
                             if (skiExtn != null) {
                                 System.out.println(method +
-                                        " SubjectKeyIdentifier extension found in self-signed request");
+                                        " SubjectKeyIdentifier extension found in self-signed Shared Token request");
                             } else {
                                 System.out.println(method +
-                                        " SubjectKeyIdentifier extension missing in self-signed request");
+                                        " SubjectKeyIdentifier extension missing in self-signed Shared Token request");
                                 System.exit(1);
                             }
                         }
@@ -569,7 +580,7 @@ public class CMCRequest {
                             System.exit(1);
                         }
 
-                        if (selfSign.equals("true")) {
+                        if (useSharedSecret.equals("true")) {
                             try {
                                 skiExtn = (SubjectKeyIdentifierExtension) CryptoUtil.getExtensionFromPKCS10(
                                         pkcs, "SubjectKeyIdentifier");
@@ -798,13 +809,13 @@ public class CMCRequest {
         System.out.println("#nickname: nickname for user certificate which will be used");
         System.out.println("#to sign the CMC full request (enrollment or revocation).");
         System.out.println("");
-        System.out.println("#selfSign: if selfSign is true, the CMC request will be");
+        System.out.println("#request.useSharedSecret: if request.useSharedSecret is true, the CMC request will be");
         System.out.println("#signed with the pairing private key of the enrollment request;");
         System.out.println("#and in which case the nickname will be ignored");
         System.out.println("#If revRequest.sharedSecret is specified, then nickname will also be ignored.");
         System.out.println("nickname=CMS User Signing Certificate");
         System.out.println("");
-        System.out.println("selfSign=false");
+        System.out.println("request.useSharedSecret=false");
         System.out.println("");
         System.out.println("#dbdir: directory for cert8.db, key3.db and secmod.db");
         System.out.println("dbdir=./");
@@ -1219,7 +1230,7 @@ public class CMCRequest {
  * Constructing OtherMsg to include the SignerInfo makes no sense here
  * as the outer layer SignedData would have SignerInfo.
  * It is possibly done because the original code assumed a self-signed
- * revocation request that is subsequently signed by an agent...
+ * Shared Token revocation request that is subsequently signed by an agent...
  * which is not conforming to the RFC.
 
             EncapsulatedContentInfo revokeContent = new EncapsulatedContentInfo(
@@ -1881,6 +1892,7 @@ public class CMCRequest {
                 HMACDigest hmacDigest = new HMACDigest(SHA2Digest, challenge);
                 hmacDigest.update(ASN1Util.encode(request));
                 popProofValue = hmacDigest.digest();
+                System.out.println(method + "popProofValue length = " + popProofValue.length);
             } catch (Exception ex) {
                 CryptoUtil.obscureBytes(challenge, "random");
                 System.out.println(method + "calculating POP Proof Value failed: " + ex);
@@ -1926,6 +1938,137 @@ public class CMCRequest {
         return pkidata;
     }
 
+    static void outputContentInfo(ContentInfo cmcblob, String ofilename) {
+            try (FileOutputStream os = new FileOutputStream(ofilename)){
+                cmcblob.encode(os);
+                System.out.println("");
+                System.out.println("");
+                System.out.println("The CMC enrollment request in binary format is stored in " +
+                        ofilename);
+            } catch (IOException e) {
+                System.out.println("CMCRequest:  unable to open file " + ofilename +
+                        " for writing:\n" + e);
+            }
+    }
+
+
+    /*
+     *  processResignCMC
+     *
+     *  This is for testing only, for the purpose of producing
+     *  negative tests consisted of deliberate alteration of
+     *  CMC controls to see how CA reacts to these variations.
+     *
+     *  It takes in a blob of the format cmc (with altered fields):
+     *      format=test_cmc
+     *  which is the same as output format from CMCRequest,
+     *  and re-signs it with either signerCert or privKeyID
+     *  and spits out to output
+     *  Note: if signerCert is not null, then privKeyID is ignored
+     *
+     * @author cfu
+     */
+    static void processResignCMC(String ifilename, String ofilename, X509Certificate signerCert, String privKeyId, String tokenName, String nickname, CryptoManager cm) {
+        try {
+            if (ifilename == null || ifilename.equals("")) {
+                System.out.println("TEST_CMC: param input needed for test_cmc");
+                System.exit(1);
+            }
+            if (ofilename == null || ofilename.equals("")) {
+                System.out.println("TEST_CMC: param output needed for test_cmc");
+                System.exit(1);
+            }
+
+            PrivateKey privk = null;
+            if (signerCert == null) {
+                if (privKeyId == null) {
+                    System.out.println("TEST_CMC: signerCert not supplied, need privKeyId to re-sign.");
+                    System.exit(1);
+                } else {
+                    System.out.println("TEST_CMC: got re-signing privKeyId: " + privKeyId);
+
+                    byte[] keyIDb = CryptoUtil.decodeKeyID(privKeyId);
+
+                    privk = CryptoUtil.findPrivateKeyFromID(keyIDb);
+
+                    if (privk != null) {
+                        System.out.println("TEST_CMC: got private key");
+                    } else {
+                        System.out.println("TEST_CMC: error getting private key null");
+                        System.exit(1);
+                    }
+                }
+            }
+
+            FileInputStream inputBlob = null;
+            FileOutputStream outputBlob = null;
+            try {
+                inputBlob = new FileInputStream(ifilename);
+            } catch (FileNotFoundException e) {
+                System.out.println("can''t find file " +
+                        ifilename + e);
+                System.exit(1);
+            }
+
+            byte data[] = new byte[inputBlob.available()];
+            inputBlob.read(data);
+            System.out.println("TEST_CMC: input read");
+            ContentInfo.Template ci_template = new ContentInfo.Template();
+            ContentInfo ci =
+                    (ContentInfo) ci_template.decode(new ByteArrayInputStream(data));
+            if (ci != null)
+                System.out.println("TEST_CMC: ContentInfo template decoded");
+
+            SignedData signedData = (SignedData) ci.getInterpretedContent();
+            if (signedData != null)
+                System.out.println("TEST_CMC: SignedData retrieved");
+
+            EncapsulatedContentInfo eci = signedData.getContentInfo();
+            if (eci != null)
+                System.out.println("TEST_CMC: EncapsulatedContentInfo retrieved");
+            OCTET_STRING os = eci.getContent(); //this is the orig data
+            if (os != null)
+                System.out.println("TEST_CMC: orig data retrieved");
+            byte origData [] = os.toByteArray();
+            PKIData.Template pkidata_template = new PKIData.Template();
+            PKIData pkidata =
+                    (PKIData) pkidata_template.decode(new ByteArrayInputStream(origData));
+            if (pkidata != null)
+                System.out.println("TEST_CMC: PKIData decoded");
+
+            // now re-sign
+            SignedData newSignedData = null;
+            if (signerCert != null) {
+                System.out.println("TEST_CMC: re-signing using signer cert:" +
+                    nickname);
+                newSignedData = signData(signerCert, tokenName, nickname, cm, pkidata);
+            } else { // self-signed Shared Token request
+                System.out.println("TEST_CMC: re-signing using private key: " +
+                    privKeyId);
+                SET signInfos = signedData.getSignerInfos();
+                SignerInfo si = (SignerInfo) (ASN1Util.decode(SignerInfo.getTemplate(), ASN1Util.encode(signInfos.elementAt(0))));
+                newSignedData = signData(privk, pkidata, si.getSignerIdentifier());
+            }
+
+            if (newSignedData == null) {
+                System.out.println("TEST_CMC: PKIData signing returned null");
+                System.exit(1);
+            }
+            System.out.println("TEST_CMC: PKIData signed");
+            ContentInfo  cmcblob = getCMCBlob(newSignedData, null);
+            if (cmcblob == null) {
+                System.out.println("TEST_CMC: getCMCBlob returned null");
+                System.exit(1);
+            }
+
+            outputContentInfo(cmcblob, ofilename);
+            System.out.println("TEST_CMC: completed");
+        } catch (Exception ex) {
+            System.out.println("TEST_CMC: exception caught: " + ex);
+            System.exit(1);
+        }
+    }
+
     public static void main(String[] s) {
         String numRequests = null;
         String dbdir = null, nickname = null;
@@ -1948,7 +2091,7 @@ public class CMCRequest {
         String popLinkWitnessV2Enable = "false", popLinkWitnessV2keyGenAlg = "SHA256", popLinkWitnessV2macAlg = "SHA256";
         String popLinkWitnessEnable = "false";
         String bodyPartIDs = null, lraPopWitnessEnable = "false";
-        String selfSign = "false";
+        String useSharedSecret = "false";
 
         System.out.println("");
 
@@ -2009,8 +2152,9 @@ public class CMCRequest {
                         decryptedPopEnable = val;
                     } else if (name.equals("encryptedPopResponseFile")) {
                         encryptedPopResponseFile = val;
-                    } else if (name.equals("request.selfSign")) {
-                        selfSign = val;
+                    } else if (name.equals("request.useSharedSecret") ||
+                        name.equals("request.selfSign")) {
+                        useSharedSecret = val;
                     } else if (name.equals("request.privKeyId")) {
                         privKeyId = val;
                     } else if (name.equals("decryptedPopRequestFile")) {
@@ -2095,12 +2239,13 @@ public class CMCRequest {
             printUsage();
         }
 
-        if ((!selfSign.equals("true") && (revRequestSharedSecret == null))
+        if ((!useSharedSecret.equals("true") && (revRequestSharedSecret == null))
                 && nickname == null) {
             System.out.println("Missing nickname.");
             printUsage();
         }
 
+
         try {
             // initialize CryptoManager
             if (dbdir == null)
@@ -2142,7 +2287,7 @@ public class CMCRequest {
                 certname.append(tokenName);
                 certname.append(":");
             }
-            if ((!selfSign.equals("true") || (revRequestSharedSecret == null))
+            if ((!useSharedSecret.equals("true") || (revRequestSharedSecret == null))
                     && nickname != null) {
                 certname.append(nickname);
                 signerCert = cm.findCertByNickname(certname.toString());
@@ -2151,14 +2296,22 @@ public class CMCRequest {
                 }
             }
 
+            // TEST_CMC
+            if (format.equals("test_cmc")) {
+                System.out.println("TEST_CMC: request format is test_cmc; re-signing the request");
+                processResignCMC(ifilename, ofilename, signerCert, privKeyId,
+                        tokenName, nickname, cm);
+                System.exit(0);
+            }
+
             ContentInfo cmcblob = null;
             PKIData pkidata = null;
             PrivateKey privk = null;
-            if (selfSign.equalsIgnoreCase("true") ||
+            if (useSharedSecret.equalsIgnoreCase("true") ||
                     decryptedPopEnable.equalsIgnoreCase("true") ||
                     popLinkWitnessV2Enable.equalsIgnoreCase("true")) {
                 if (privKeyId == null) {
-                    System.out.println("selfSign or ecryptedPop.enable or popLinkWitnessV2 true, but privKeyId not specified.");
+                    System.out.println("useSharedSecret or ecryptedPop.enable or popLinkWitnessV2 true, but privKeyId not specified.");
                     printUsage();
                 } else {
                     System.out.println("got request privKeyId: " + privKeyId);
@@ -2353,7 +2506,7 @@ public class CMCRequest {
 
                     // create the request PKIData
                     pkidata = createPKIData(
-                        selfSign,
+                        useSharedSecret,
                         requests,
                         format, transactionMgtEnable, transactionMgtId,
                         identificationEnable, identification,
@@ -2381,13 +2534,13 @@ public class CMCRequest {
                 SignedData signedData = null;
 
                 // sign the request
-                if (selfSign.equalsIgnoreCase("true")) {
-                    // selfSign signs with private key
-                    System.out.println("selfSign is true...");
+                if (useSharedSecret.equalsIgnoreCase("true")) {
+                    // useSharedSecret signs with private key
+                    System.out.println("useSharedSecret is true...");
                     signedData = signData(privk, pkidata);
                 } else {
-                    // none selfSign signs with  existing cert
-                    System.out.println("selfSign is false...");
+                    // none useSharedSecret signs with  existing cert
+                    System.out.println("useSharedSecret is false...");
                     signedData = signData(signerCert, tokenName, nickname, cm, pkidata);
                 }
                 if (signedData == null) {
@@ -2404,27 +2557,7 @@ public class CMCRequest {
 
             // (6) Finally, print the actual CMC blob to the
             //     specified output file
-            FileOutputStream os = null;
-            try {
-                os = new FileOutputStream(ofilename);
-                cmcblob.encode(os);
-                System.out.println("");
-                System.out.println("");
-                System.out.println("The CMC enrollment request in binary format is stored in " +
-                        ofilename);
-            } catch (IOException e) {
-                System.out.println("CMCRequest:  unable to open file " + ofilename +
-                        " for writing:\n" + e);
-            }
-
-            try {
-                os.close();
-            } catch (IOException e) {
-                System.out.println("CMCRequest:  Unexpected error " +
-                        "encountered while attempting to close() " +
-                        "\n" + e);
-            }
-
+            outputContentInfo(cmcblob, ofilename);
         } catch (Exception e) {
             e.printStackTrace();
             System.exit(1);
diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
index 747b7d6..dd7a264 100644
--- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -190,7 +190,7 @@ public class CRMFPopClient {
         option.setArgName("keywrap algorithm");
         options.addOption(option);
 
-        options.addOption("y", false, "for Self-signed cmc.");
+        options.addOption("y", false, "for cmc SharedSecret requests.");
 
         options.addOption("v", "verbose", false, "Run in verbose mode.");
         options.addOption(null, "help", false, "Show help message.");
@@ -210,7 +210,7 @@ public class CRMFPopClient {
         System.out.println("  -k <true|false>              Attribute value encoding in subject DN (default: false)");
         System.out.println("                               - true: enabled");
         System.out.println("                               - false: disabled");
-        System.out.println("  -y <true|false>              Add SubjectKeyIdentifier extension in case of self-signed CMC requests (default: false)");
+        System.out.println("  -y <true|false>              Add SubjectKeyIdentifier extension in case of CMC SharedSecret requests (default: false); To be used with 'request.useSharedSecret=true' when running CMCRequest.");
         System.out.println("                               - true: enabled");
         System.out.println("                               - false: disabled");
         System.out.println("  -a <rsa|ec>                  Key algorithm (default: rsa)");
@@ -320,7 +320,7 @@ public class CRMFPopClient {
         int sensitive = Integer.parseInt(cmd.getOptionValue("s", "-1"));
         int extractable = Integer.parseInt(cmd.getOptionValue("e", "-1"));
 
-        boolean self_sign = cmd.hasOption("y");
+        boolean use_shared_secret = cmd.hasOption("y");
 
         // get the keywrap algorithm
         KeyWrapAlgorithm keyWrapAlgorithm = null;
@@ -335,6 +335,7 @@ public class CRMFPopClient {
         }
 
         String output = cmd.getOptionValue("o");
+        String output_kid = output + ".keyId";
 
         String hostPort = cmd.getOptionValue("m");
         String username = cmd.getOptionValue("u");
@@ -507,7 +508,7 @@ public class CRMFPopClient {
 
             if (verbose) System.out.println("Creating certificate request");
             CertRequest certRequest = client.createCertRequest(
-                    self_sign,
+                    use_shared_secret,
                     token, transportCert, algorithm, keyPair,
                     subject, keyWrapAlgorithm);
 
@@ -558,11 +559,16 @@ public class CRMFPopClient {
                         requestor);
 
             } else if (output != null) {
-                System.out.println("Storing CRMF requrest into " + output);
+                System.out.println("Storing CRMF request into " + output);
                 try (FileWriter out = new FileWriter(output)) {
                     out.write(csr);
                 }
 
+                System.out.println("Storing CRMF request key id into " + output_kid);
+                try (FileWriter out_kid = new FileWriter(output_kid)) {
+                    out_kid.write(kid);
+                }
+
             } else {
                 System.out.println(csr);
             }
@@ -655,7 +661,7 @@ public class CRMFPopClient {
     }
 
     public CertRequest createCertRequest(
-            boolean self_sign,
+            boolean use_shared_secret,
             CryptoToken token,
             X509Certificate transportCert,
             String algorithm,
@@ -701,8 +707,8 @@ public class CRMFPopClient {
         seq.addElement(new AVA(OBJECT_IDENTIFIER.id_cmc_idPOPLinkWitness, ostr));
         */
 
-        if (self_sign) { // per rfc 5272
-            System.out.println("CRMFPopClient: self_sign true. Generating SubjectKeyIdentifier extension.");
+        if (use_shared_secret) { // per rfc 5272
+            System.out.println("CRMFPopClient: use_shared_secret true. Generating SubjectKeyIdentifier extension.");
             KeyIdentifier subjKeyId = CryptoUtil.createKeyIdentifier(keyPair);
             OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER(PKIXExtensions.SubjectKey_Id.toString());
             SEQUENCE extns = new SEQUENCE();
diff --git a/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java b/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java
index 9f39430..137049e 100644
--- a/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java
+++ b/base/java-tools/src/com/netscape/cmstools/PKCS10Client.java
@@ -18,6 +18,7 @@
 package com.netscape.cmstools;
 
 import java.io.FileOutputStream;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.security.KeyPair;
@@ -84,11 +85,11 @@ public class PKCS10Client {
         System.out.println(
                 "   available ECC curve names (if provided by the crypto module): nistp256 (secp256r1),nistp384 (secp384r1),nistp521 (secp521r1),nistk163 (sect163k1),sect163r1,nistb163 (sect163r2),sect193r1,sect193r2,nistk233 (sect233k1),nistb233 (sect233r1),sect239k1,nistk283 (sect283k1),nistb283 (sect283r1),nistk409 (sect409k1),nistb409 (sect409r1),nistk571 (sect571k1),nistb571 (sect571r1),secp160k1,secp160r1,secp160r2,secp192k1,nistp192 (secp192r1, prime192v1),secp224k1,nistp224 (secp224r1),secp256k1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,c2pnb163v1,c2pnb163v2,c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359w1,c2pnb368w1,c2tnb431r1,secp112r1,secp112r2,secp128r1,secp128r2,sect113r1,sect113r2,sect131r1,sect131r2\n");
         System.out.println(
-                "In addition: -y <true for adding SubjectKeyIdentifier extensionfor self-signed cmc requests; false otherwise; default false>\n");
+                "In addition: -y <true for adding SubjectKeyIdentifier extensionfor cmc Shared Secret requests; false otherwise; default false> To be used with 'request.useSharedSecret=true' when running CMCRequest.\n");
     }
 
     public static void main(String args[]) throws Exception {
-        String dbdir = null, ofilename = null, password = null, subjectName = null, tokenName = null;
+        String dbdir = null, ofilename = null, kid_ofilename = null, password = null, subjectName = null, tokenName = null;
 
         String alg = "rsa";
         String ecc_curve = "nistp256";
@@ -99,7 +100,7 @@ public class PKCS10Client {
         boolean ec_ssl_ecdh = false;
         int rsa_keylen = 2048;
 
-        boolean self_sign = false;
+        boolean use_shared_secret = false;
 
         if (args.length < 4) {
             printUsage();
@@ -163,6 +164,7 @@ public class PKCS10Client {
                 rsa_keylen = Integer.parseInt(args[i+1]);
             } else if (name.equals("-o")) {
                 ofilename = args[i+1];
+                kid_ofilename = ofilename + ".keyId";
             } else if (name.equals("-n")) {
                 subjectName = args[i+1];
             } else if (name.equals("-h")) {
@@ -170,9 +172,9 @@ public class PKCS10Client {
             } else if (name.equals("-y")) {
                 String temp = args[i+1];
                 if (temp.equals("true"))
-                    self_sign = true;
+                    use_shared_secret = true;
                 else
-                    self_sign = false;
+                    use_shared_secret = false;
             } else {
                 System.out.println("Unrecognized argument(" + i + "): "
                     + name);
@@ -277,8 +279,8 @@ public class PKCS10Client {
 
 
             Extensions extns = new Extensions();
-            if (self_sign) { // per rfc 5272
-                System.out.println("PKCS10Client: self_sign true. Generating SubjectKeyIdentifier extension.");
+            if (use_shared_secret) { // per rfc 5272
+                System.out.println("PKCS10Client: use_shared_secret true. Generating SubjectKeyIdentifier extension.");
                 KeyIdentifier subjKeyId = CryptoUtil.createKeyIdentifier(pair);
                 SubjectKeyIdentifierExtension extn = new SubjectKeyIdentifierExtension(false,
                         subjKeyId.getIdentifier());
@@ -318,7 +320,13 @@ public class PKCS10Client {
             ps.println(Cert.REQUEST_FOOTER);
             ps.flush();
             ps.close();
-            System.out.println("PKCS10Client: done. Request written to file: "+ ofilename);
+            System.out.println("PKCS10Client: done. Certificate request written into "+ ofilename);
+
+            try (FileWriter out_kid = new FileWriter(kid_ofilename)) {
+                out_kid.write(kid);
+            }
+            System.out.println("PKCS10Client: PKCS#10 request key id written into " + kid_ofilename);
+
         } catch (Exception e) {
             System.out.println("PKCS10Client: Exception caught: "+e.toString());
             System.exit(1);
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSelfSignedSubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSelfSignedSubjectNameConstraint.java
deleted file mode 100644
index d4554ca..0000000
--- a/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSelfSignedSubjectNameConstraint.java
+++ /dev/null
@@ -1,129 +0,0 @@
-// --- BEGIN COPYRIGHT BLOCK ---
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; version 2 of the License.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// (C) 2013 Red Hat, Inc.
-// All rights reserved.
-// --- END COPYRIGHT BLOCK ---
-package com.netscape.cms.profile.constraint;
-
-import java.util.Locale;
-
-import com.netscape.certsrv.apps.CMS;
-import com.netscape.certsrv.authentication.IAuthToken;
-import com.netscape.certsrv.authentication.IAuthManager;
-import com.netscape.certsrv.base.IConfigStore;
-import com.netscape.certsrv.profile.EProfileException;
-import com.netscape.certsrv.profile.ERejectException;
-import com.netscape.certsrv.profile.IPolicyDefault;
-import com.netscape.certsrv.profile.IProfile;
-import com.netscape.certsrv.property.IDescriptor;
-import com.netscape.certsrv.request.IRequest;
-import com.netscape.cms.profile.common.EnrollProfile;
-import com.netscape.cms.profile.def.AuthTokenSubjectNameDefault;
-
-import netscape.security.x509.CertificateSubjectName;
-import netscape.security.x509.X500Name;
-import netscape.security.x509.X509CertInfo;
-
-/**
- * This class implements the user subject name constraint for self-signed cmc requests.
- * It makes sure the SharedSecret authenticated subjectDN and the rsulting cert match
- *
- * @author cfu
- * @version $Revision$, $Date$
- */
-public class CMCSelfSignedSubjectNameConstraint extends EnrollConstraint {
-
-    public CMCSelfSignedSubjectNameConstraint() {
-    }
-
-    public void init(IProfile profile, IConfigStore config)
-            throws EProfileException {
-        super.init(profile, config);
-    }
-
-    public IDescriptor getConfigDescriptor(Locale locale, String name) {
-        return null;
-    }
-
-    public String getDefaultConfig(String name) {
-        return null;
-    }
-
-    /**
-     * Validates the request. The request is not modified
-     * during the validation. User encoded subject name
-     * is copied into the certificate template.
-     */
-    public void validate(IRequest request, X509CertInfo info)
-            throws ERejectException {
-        String method = "CMCSelfSignedSubjectNameConstraint: ";
-        String msg = "";
-
-        CertificateSubjectName infoCertSN = null;
-        String authTokenSharedTokenSN = null;
-
-        try {
-            infoCertSN = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
-            if (infoCertSN == null) {
-                msg = method + "infoCertSN null";
-                CMS.debug(msg);
-                throw new Exception(msg);
-            }
-            CMS.debug(method + "validate user subject ="+
-                      infoCertSN.toString());
-            X500Name infoCertName = (X500Name) infoCertSN.get(CertificateSubjectName.DN_NAME);
-            if (infoCertName == null) {
-                msg = method + "infoCertName null";
-                CMS.debug(msg);
-                throw new Exception(msg);
-            }
-
-            authTokenSharedTokenSN = request.getExtDataInString(IAuthToken.TOKEN_SHARED_TOKEN_AUTHENTICATED_CERT_SUBJECT);
-            if (authTokenSharedTokenSN == null) {
-                msg = method + "authTokenSharedTokenSN null";
-                CMS.debug(msg);
-                throw new Exception(msg);
-            }
-            if (infoCertName.getName().equalsIgnoreCase(authTokenSharedTokenSN)) {
-                CMS.debug(method + "names matched");
-            } else {
-                msg = method + "names do not match; authTokenSharedTokenSN =" +
-                        authTokenSharedTokenSN;
-                CMS.debug(msg);
-                throw new Exception(msg);
-            }
-
-        } catch (Exception e) {
-            throw new ERejectException(
-                    CMS.getUserMessage(getLocale(request),
-                        "CMS_PROFILE_SUBJECT_NAME_NOT_MATCHED") + e);
-        }
-    }
-
-    public String getText(Locale locale) {
-        return CMS.getUserMessage(locale,
-                   "CMS_PROFILE_CONSTRAINT_CMC_SELF_SIGNED_SUBJECT_NAME_TEXT");
-    }
-
-    public boolean isApplicable(IPolicyDefault def) {
-        String method = "CMCSelfSignedSubjectNameConstraint: isApplicable: ";
-        if (def instanceof AuthTokenSubjectNameDefault) {
-            CMS.debug(method + "true");
-            return true;
-        }
-        CMS.debug(method + "false");
-        return false;
-    }
-}
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSharedTokenSubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSharedTokenSubjectNameConstraint.java
new file mode 100644
index 0000000..879e1cc
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/CMCSharedTokenSubjectNameConstraint.java
@@ -0,0 +1,130 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.constraint;
+
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IPolicyDefault;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+import com.netscape.cms.profile.def.AuthTokenSubjectNameDefault;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+/**
+ * This class implements the user subject name constraint for cmc requests
+ * authenticated by the SharedSecret
+ * The resulting cert should match that of the authenticating DN
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CMCSharedTokenSubjectNameConstraint extends EnrollConstraint {
+
+    public CMCSharedTokenSubjectNameConstraint() {
+    }
+
+    public void init(IProfile profile, IConfigStore config)
+            throws EProfileException {
+        super.init(profile, config);
+    }
+
+    public IDescriptor getConfigDescriptor(Locale locale, String name) {
+        return null;
+    }
+
+    public String getDefaultConfig(String name) {
+        return null;
+    }
+
+    /**
+     * Validates the request. The request is not modified
+     * during the validation. User encoded subject name
+     * is copied into the certificate template.
+     */
+    public void validate(IRequest request, X509CertInfo info)
+            throws ERejectException {
+        String method = "CMCSharedTokenSubjectNameConstraint: ";
+        String msg = "";
+
+        CertificateSubjectName infoCertSN = null;
+        String authTokenSharedTokenSN = null;
+
+        try {
+            infoCertSN = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+            if (infoCertSN == null) {
+                msg = method + "infoCertSN null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            CMS.debug(method + "validate user subject ="+
+                      infoCertSN.toString());
+            X500Name infoCertName = (X500Name) infoCertSN.get(CertificateSubjectName.DN_NAME);
+            if (infoCertName == null) {
+                msg = method + "infoCertName null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+
+            authTokenSharedTokenSN = request.getExtDataInString(IAuthToken.TOKEN_SHARED_TOKEN_AUTHENTICATED_CERT_SUBJECT);
+            if (authTokenSharedTokenSN == null) {
+                msg = method + "authTokenSharedTokenSN null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            if (infoCertName.getName().equalsIgnoreCase(authTokenSharedTokenSN)) {
+                CMS.debug(method + "names matched");
+            } else {
+                msg = method + "names do not match; authTokenSharedTokenSN =" +
+                        authTokenSharedTokenSN;
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+
+        } catch (Exception e) {
+            throw new ERejectException(
+                    CMS.getUserMessage(getLocale(request),
+                        "CMS_PROFILE_SUBJECT_NAME_NOT_MATCHED") + e);
+        }
+    }
+
+    public String getText(Locale locale) {
+        return CMS.getUserMessage(locale,
+                   "CMS_PROFILE_CONSTRAINT_CMC_SELF_SIGNED_SUBJECT_NAME_TEXT");
+    }
+
+    public boolean isApplicable(IPolicyDefault def) {
+        String method = "CMCSharedTokenSubjectNameConstraint: isApplicable: ";
+        if (def instanceof AuthTokenSubjectNameDefault) {
+            CMS.debug(method + "true");
+            return true;
+        }
+        CMS.debug(method + "false");
+        return false;
+    }
+}
-- 
1.8.3.1