Blob Blame History Raw
From d4e83335d5ac6a6b39bf5abaa26075a9ec86f6b7 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Tue, 18 Apr 2017 08:09:00 +0200
Subject: [PATCH 01/49] Spawn a CA and KRA on Travis

Travis CI tests are now using a systemd container to install and run a
389-DS, CA and KRA instance.

Change-Id: Ibc7d1a6b1e218492a84e88d4339de34b1eb58c7c
---
 .travis.test            | 31 -----------------------------
 .travis.yml             | 51 +++++++++++++++++++++++++++++++++++++++---------
 .travis/00-init         | 36 ++++++++++++++++++++++++++++++++++
 .travis/10-compose-rpms | 31 +++++++++++++++++++++++++++++
 .travis/20-install-rpms |  6 ++++++
 .travis/30-setup-389ds  | 12 ++++++++++++
 .travis/40-spawn-ca     |  9 +++++++++
 .travis/50-spawn-kra    |  9 +++++++++
 .travis/pki.cfg         | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 197 insertions(+), 40 deletions(-)
 delete mode 100755 .travis.test
 create mode 100755 .travis/00-init
 create mode 100755 .travis/10-compose-rpms
 create mode 100755 .travis/20-install-rpms
 create mode 100755 .travis/30-setup-389ds
 create mode 100755 .travis/40-spawn-ca
 create mode 100755 .travis/50-spawn-kra
 create mode 100644 .travis/pki.cfg

diff --git a/.travis.test b/.travis.test
deleted file mode 100755
index ca81022..0000000
--- a/.travis.test
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-set -ex
-
-WORKDIR="${BUILDDIR:-/tmp/builddir}"
-BUILDUSER=builduser
-BUILDUSER_UID=${UID:-1000}
-BUILDUSER_GID=${GID:-1000}
-
-. /etc/os-release
-
-echo "$NAME $VERSION $1"
-
-## compose_pki_core_packages doesn't run as root, create a build user
-groupadd --non-unique -g $BUILDUSER_GID ${BUILDUSER}
-useradd --non-unique -u $BUILDUSER_UID -g $BUILDUSER_GID ${BUILDUSER}
-
-## chown workdir and enter pki dir
-chown ${BUILDUSER}:${BUILDUSER} ${WORKDIR}
-cd ${WORKDIR}/pki
-
-## prepare additional build dependencies
-dnf copr -y enable @pki/10.4
-dnf builddep -y ./specs/pki-core.spec
-
-# update, container might be outdated
-dnf update -y
-
-## run tox and build
-# run make with --quiet to reduce log verbosity. Travis CI has a log limit
-# of 10,000 lines.
-sudo -u ${BUILDUSER} MAKEFLAGS="-j2 --quiet" -s -- ./scripts/compose_pki_core_packages rpms
diff --git a/.travis.yml b/.travis.yml
index 2e1a69f..b443118 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,16 +5,49 @@ services:
   - docker
 
 env:
-  - CONTAINER=dogtagpki/pki-ci-containers:f25_104
-  - CONTAINER=dogtagpki/pki-ci-containers:f26_104
-  - CONTAINER=dogtagpki/pki-ci-containers:rawhide
+  global:
+    - CONTAINER=pkitest
+    - SCRIPTDIR=/tmp/workdir/pki/.travis
+  matrix:
+    - IMAGE=dogtagpki/pki-ci-containers:f25_104
+    # F26 repo is unstable
+    # - IMAGE=dogtagpki/pki-ci-containers:f26_104
+    # rawhide repo is unstable
+    # - IMAGE=dogtagpki/pki-ci-containers:rawhide
 
-script:
-  - docker pull $CONTAINER
+before_install:
+  - docker pull ${IMAGE}
   - >
     docker run
+    --detach
+    --name=${CONTAINER}
+    --hostname='pki.test'
+    --privileged
+    --tmpfs /tmp
+    --tmpfs /run
+    -v /sys/fs/cgroup:/sys/fs/cgroup:ro
     -v $(pwd):/tmp/workdir/pki
-    -e UID=$(id -u)
-    -e GID=$(id -g)
-    $CONTAINER
-    /tmp/workdir/pki/.travis.test $CONTAINER
+    -e BUILDUSER_UID=$(id -u)
+    -e BUILDUSER_GID=$(id -g)
+    -e TRAVIS=${TRAVIS}
+    -e TRAVIS_JOB_NUMBER=${TRAVIS_JOB_NUMBER}
+    -ti
+    ${IMAGE}
+  - docker ps -a
+
+install:
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/00-init
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/10-compose-rpms
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/20-install-rpms
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/30-setup-389ds
+
+script:
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/40-spawn-ca
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/50-spawn-kra
+
+after_script:
+  - docker kill ${CONTAINER}
+  - docker rm ${CONTAINER}
+
+after_failure:
+  - journalctl -l
diff --git a/.travis/00-init b/.travis/00-init
new file mode 100755
index 0000000..1b5aa53
--- /dev/null
+++ b/.travis/00-init
@@ -0,0 +1,36 @@
+#!/bin/bash
+set -e
+
+. /etc/os-release
+
+echo "$NAME $VERSION"
+
+if test -z "${BUILDDIR}" || ! test -d "${BUILDDIR}"; then
+    echo "BUILDDIR not set or ${BUILDDIR} is not a directory."
+    exit 1
+fi
+
+if test -z "${BUILDUSER}" -o -z "${BUILDUSER_UID}" -o -z "${BUILDUSER_GID}"; then
+    echo "BUILDUSER, BUILDUSER_UID, BUILDUSER_GID not set"
+    exit 2
+fi
+
+## compose_pki_core_packages doesn't run as root, create a build user
+groupadd --non-unique -g ${BUILDUSER_GID} ${BUILDUSER}
+useradd --non-unique -u ${BUILDUSER_UID} -g ${BUILDUSER_GID} ${BUILDUSER}
+
+## chown workdir and enter pki dir
+chown ${BUILDUSER}:${BUILDUSER} ${BUILDDIR}
+
+# workaround for
+# [Errno 2] No such file or directory: '/var/cache/dnf/metadata_lock.pid'
+rm -f /var/cache/dnf/metadata_lock.pid
+dnf clean all
+dnf makecache || true
+dnf makecache
+
+# update, container might be outdated
+dnf update -y
+
+## prepare additional build dependencies
+dnf builddep -y ${BUILDDIR}/pki/specs/pki-core.spec
diff --git a/.travis/10-compose-rpms b/.travis/10-compose-rpms
new file mode 100755
index 0000000..1e55548
--- /dev/null
+++ b/.travis/10-compose-rpms
@@ -0,0 +1,31 @@
+#!/bin/bash
+set -e
+
+BUILDLOG=/tmp/compose.log
+
+function compose {
+    pushd ${BUILDDIR}/pki
+    # run make with --quiet to reduce log verbosity.
+    sudo -u ${BUILDUSER} MAKEFLAGS="-j2 --quiet" -- \
+        ./scripts/compose_pki_core_packages rpms
+    popd
+}
+
+function upload {
+    if test -f $BUILDLOG; then
+        echo "Uploading build log to transfer"
+        curl --upload-file $BUILDLOG https://transfer.sh/pkitravis.txt
+    fi
+}
+
+if test "${TRAVIS}" != "true"; then
+    compose
+else
+    trap upload EXIT
+    echo "Runing compose_pki_core_packages rpms."
+    echo "Build log will be posted to transfer.sh"
+    echo $(date) > $BUILDLOG
+    echo "Travis job ${TRAVIS_JOB_NUMBER}" >> $BUILDLOG
+    compose >>$BUILDLOG 2>&1
+fi
+
diff --git a/.travis/20-install-rpms b/.travis/20-install-rpms
new file mode 100755
index 0000000..186efb8
--- /dev/null
+++ b/.travis/20-install-rpms
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+
+find ${BUILDDIR}/packages/RPMS/ -name '*.rpm' -and -not -name '*debuginfo*' \
+    | xargs dnf install -y --best --allowerasing
+
diff --git a/.travis/30-setup-389ds b/.travis/30-setup-389ds
new file mode 100755
index 0000000..cc16573
--- /dev/null
+++ b/.travis/30-setup-389ds
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+
+setup-ds.pl \
+    --silent \
+    slapd.ServerIdentifier="pkitest" \
+    General.SuiteSpotUserID=nobody \
+    General.SuiteSpotGroup=nobody \
+    slapd.ServerPort=389 \
+    slapd.Suffix="dc=pki,dc=test" \
+    slapd.RootDN="cn=Directory Manager" \
+    slapd.RootDNPwd="DMSecret.123"
diff --git a/.travis/40-spawn-ca b/.travis/40-spawn-ca
new file mode 100755
index 0000000..9986698
--- /dev/null
+++ b/.travis/40-spawn-ca
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+pkispawn -v -f ${BUILDDIR}/pki/.travis/pki.cfg -s CA
+
+echo "Waiting for port 8080"
+for i in {1..20}; do
+    curl http://localhost:8080 && break || sleep 1
+done
diff --git a/.travis/50-spawn-kra b/.travis/50-spawn-kra
new file mode 100755
index 0000000..80cb039
--- /dev/null
+++ b/.travis/50-spawn-kra
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+pkispawn -v -f ${BUILDDIR}/pki/.travis/pki.cfg -s KRA
+
+echo "Waiting for port 8080"
+for i in {1..20}; do
+    curl http://localhost:8080 && break || sleep 1
+done
diff --git a/.travis/pki.cfg b/.travis/pki.cfg
new file mode 100644
index 0000000..a168822
--- /dev/null
+++ b/.travis/pki.cfg
@@ -0,0 +1,52 @@
+# based on
+# https://fedorapeople.org/cgit/edewata/public_git/pki-dev.git/tree/scripts/ca.cfg
+# https://fedorapeople.org/cgit/edewata/public_git/pki-dev.git/tree/scripts/kra.cfg
+
+[DEFAULT]
+pki_instance_name=pkitest
+pki_https_port=8443
+pki_http_port=8080
+pki_master_https_port=8443
+pki_security_domain_https_port=8443
+pki_ds_bind_dn=cn=Directory Manager
+pki_ds_ldap_port=389
+pki_ds_password=DMSecret.123
+pki_backup_keys=True
+pki_backup_password=Secret.123
+pki_client_database_password=Secret.123
+pki_client_database_purge=False
+pki_client_pkcs12_password=Secret.123
+pki_clone_pkcs12_password=Secret.123
+pki_security_domain_name=pkitest
+pki_security_domain_user=caadmin
+pki_security_domain_password=Secret.123
+pki_token_password=Secret123
+
+[CA]
+pki_admin_email=caadmin@pki.test
+pki_admin_name=caadmin
+pki_admin_nickname=caadmin
+pki_admin_password=Secret.123
+pki_admin_uid=caadmin
+pki_ds_base_dn=dc=ca,dc=pki,dc=test
+pki_ds_database=ca
+
+[KRA]
+pki_admin_cert_file=/root/.dogtag/pkitest/ca_admin.cert
+pki_admin_email=kraadmin@pki.test
+pki_admin_name=kraadmin
+pki_admin_nickname=kraadmin
+pki_admin_password=Secret.123
+pki_admin_uid=kraadmin
+pki_ds_base_dn=dc=kra,dc=pki,dc=test
+pki_ds_database=kra
+
+[OCSP]
+pki_admin_cert_file=/root/.dogtag/pkitest/ca_admin.cert
+pki_admin_email=ocspadmin@pki.test
+pki_admin_name=ocspadmin
+pki_admin_nickname=ocspadmin
+pki_admin_password=Secret.123
+pki_admin_uid=ocspadmin
+pki_ds_base_dn=dc=ocsp,dc=pki,dc=test
+pki_ds_database=ocsp
-- 
1.8.3.1


From 08edc86f8397543f308818458a320fbbef06c90d Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Tue, 18 Apr 2017 16:24:53 +0200
Subject: [PATCH 02/49] Get journald output from test container

Change-Id: Ibc16a49b4a03524fb62ddb33326a36ffa0b0389f
Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index b443118..2714bbc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -50,4 +50,4 @@ after_script:
   - docker rm ${CONTAINER}
 
 after_failure:
-  - journalctl -l
+  - docker exec -ti ${CONTAINER} journalctl -l
-- 
1.8.3.1


From 749c137b59a9725a4cacdcd191b7e931303981df Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Mon, 17 Apr 2017 18:35:56 +0200
Subject: [PATCH 03/49] Fixed missing IP addresses and subject ID in audit log.

The PKIServerSocketListener has been modified to use WeakHashMap
to store socket info that might not be available after the socket
has been closed.

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

Change-Id: I7e86a9bbc46e7bba4cec36664780c52bf0e88416
---
 .../dogtagpki/server/PKIServerSocketListener.java  | 104 +++++++++++++--------
 1 file changed, 66 insertions(+), 38 deletions(-)

diff --git a/base/server/cms/src/org/dogtagpki/server/PKIServerSocketListener.java b/base/server/cms/src/org/dogtagpki/server/PKIServerSocketListener.java
index 093776f..d742317 100644
--- a/base/server/cms/src/org/dogtagpki/server/PKIServerSocketListener.java
+++ b/base/server/cms/src/org/dogtagpki/server/PKIServerSocketListener.java
@@ -19,6 +19,9 @@ package org.dogtagpki.server;
 
 import java.net.InetAddress;
 import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 import org.mozilla.jss.crypto.X509Certificate;
 import org.mozilla.jss.ssl.SSLAlertDescription;
@@ -38,6 +41,15 @@ public class PKIServerSocketListener implements SSLSocketListener {
 
     private static Logger logger = LoggerFactory.getLogger(PKIServerSocketListener.class);
 
+    /**
+     * The socketInfos map is a storage for socket information that may not be available
+     * after the socket has been closed such as client IP address and subject ID. The
+     * WeakHashMap is used here to allow the map key (i.e. the socket object) to be
+     * garbage-collected since there is no guarantee that socket will be closed with an
+     * SSL alert for a proper map entry removal.
+     */
+    Map<SSLSocket,Map<String,Object>> socketInfos = new WeakHashMap<>();
+
     @Override
     public void alertReceived(SSLAlertEvent event) {
         try {
@@ -57,9 +69,10 @@ public class PKIServerSocketListener implements SSLSocketListener {
             String reason = SSLAlertDescription.valueOf(description).toString();
 
             logger.debug("SSL alert received:");
-            logger.debug(" - client: " + clientAddress);
-            logger.debug(" - server: " + serverAddress);
             logger.debug(" - reason: " + reason);
+            logger.debug(" - client: " + clientIP);
+            logger.debug(" - server: " + serverIP);
+            logger.debug(" - subject: " + subjectID);
 
             IAuditor auditor = CMS.getAuditor();
 
@@ -73,7 +86,7 @@ public class PKIServerSocketListener implements SSLSocketListener {
             auditor.log(auditMessage);
 
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
     }
 
@@ -82,51 +95,59 @@ public class PKIServerSocketListener implements SSLSocketListener {
         try {
             SSLSocket socket = event.getSocket();
 
-            InetAddress clientAddress = socket.getInetAddress();
-            InetAddress serverAddress = socket.getLocalAddress();
-            String clientIP = clientAddress == null ? "" : clientAddress.getHostAddress();
-            String serverIP = serverAddress == null ? "" : serverAddress.getHostAddress();
-
-            SSLSecurityStatus status = socket.getStatus();
-            X509Certificate peerCertificate = status.getPeerCertificate();
-            Principal subjectDN = peerCertificate == null ? null : peerCertificate.getSubjectDN();
-            String subjectID = subjectDN == null ? "" : subjectDN.toString();
-
             int description = event.getDescription();
             String reason = SSLAlertDescription.valueOf(description).toString();
 
-            logger.debug("SSL alert sent:");
-            logger.debug(" - client: " + clientAddress);
-            logger.debug(" - server: " + serverAddress);
-            logger.debug(" - reason: " + reason);
-
-            IAuditor auditor = CMS.getAuditor();
+            String eventType;
+            String clientIP;
+            String serverIP;
+            String subjectID;
 
             if (description == SSLAlertDescription.CLOSE_NOTIFY.getID()) {
 
-                String auditMessage = CMS.getLogMessage(
-                        AuditEvent.ACCESS_SESSION_TERMINATED,
-                        clientIP,
-                        serverIP,
-                        subjectID,
-                        reason);
+                eventType = AuditEvent.ACCESS_SESSION_TERMINATED;
 
-                auditor.log(auditMessage);
+                // get socket info from socketInfos map since socket has been closed
+                Map<String,Object> info = socketInfos.get(socket);
+                clientIP = (String)info.get("clientIP");
+                serverIP = (String)info.get("serverIP");
+                subjectID = (String)info.get("subjectID");
 
             } else {
 
-                String auditMessage = CMS.getLogMessage(
-                        AuditEvent.ACCESS_SESSION_ESTABLISH_FAILURE,
-                        clientIP,
-                        serverIP,
-                        subjectID,
-                        reason);
+                eventType = AuditEvent.ACCESS_SESSION_ESTABLISH_FAILURE;
 
-                auditor.log(auditMessage);
+                // get socket info from the socket itself
+                InetAddress clientAddress = socket.getInetAddress();
+                InetAddress serverAddress = socket.getLocalAddress();
+                clientIP = clientAddress == null ? "" : clientAddress.getHostAddress();
+                serverIP = serverAddress == null ? "" : serverAddress.getHostAddress();
+
+                SSLSecurityStatus status = socket.getStatus();
+                X509Certificate peerCertificate = status.getPeerCertificate();
+                Principal subjectDN = peerCertificate == null ? null : peerCertificate.getSubjectDN();
+                subjectID = subjectDN == null ? "" : subjectDN.toString();
             }
 
+            logger.debug("SSL alert sent:");
+            logger.debug(" - reason: " + reason);
+            logger.debug(" - client: " + clientIP);
+            logger.debug(" - server: " + serverIP);
+            logger.debug(" - subject: " + subjectID);
+
+            IAuditor auditor = CMS.getAuditor();
+
+            String auditMessage = CMS.getLogMessage(
+                    eventType,
+                    clientIP,
+                    serverIP,
+                    subjectID,
+                    reason);
+
+            auditor.log(auditMessage);
+
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
     }
 
@@ -146,9 +167,16 @@ public class PKIServerSocketListener implements SSLSocketListener {
             String subjectID = subjectDN == null ? "" : subjectDN.toString();
 
             logger.debug("Handshake completed:");
-            logger.debug(" - client: " + clientAddress);
-            logger.debug(" - server: " + serverAddress);
-            logger.debug(" - subject: " + subjectDN);
+            logger.debug(" - client: " + clientIP);
+            logger.debug(" - server: " + serverIP);
+            logger.debug(" - subject: " + subjectID);
+
+            // store socket info in socketInfos map
+            Map<String,Object> info = new HashMap<>();
+            info.put("clientIP", clientIP);
+            info.put("serverIP", serverIP);
+            info.put("subjectID", subjectID);
+            socketInfos.put(socket, info);
 
             IAuditor auditor = CMS.getAuditor();
 
@@ -161,7 +189,7 @@ public class PKIServerSocketListener implements SSLSocketListener {
             auditor.log(auditMessage);
 
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
     }
 }
-- 
1.8.3.1


From 786d40f231f3636db381a835ce78904362ea72d0 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 2 Mar 2017 16:32:21 +1000
Subject: [PATCH 04/49] CMS.getLogMessage: escape format elements in arguments

CMS.getLogMessage performs message formatting via MessageFormat,
then the message gets logged via a Logger.  The Logger also performs
message formatting via MessageFormat.  If the formatted log message
contains '{' or '}' (e.g. if it contains JSON) the MessageFormat
implementation interprets these as FormatElement delimiters and
parsing fails.

Update CMS.getLogMessage() to scan arguments for unsafe characters
and if found, escape the whole message so that subsequent logging
will succeed.

Part of: https://pagure.io/dogtagpki/issue/1359
---
 .../src/com/netscape/cmscore/apps/CMSEngine.java     | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
index ef9a6a2..94a0783 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -1592,7 +1592,25 @@ public class CMSEngine implements ICMSEngine {
             return msg;
         MessageFormat mf = new MessageFormat(msg);
 
-        return mf.format(params);
+        Object escapedParams[] = new Object[params.length];
+        for (int i = 0; i < params.length; i++) {
+            if (params[i] instanceof String)
+                escapedParams[i] = escapeLogMessageParam((String) params[i]);
+            else
+                escapedParams[i] = params[i];
+        }
+
+        return mf.format(escapedParams);
+    }
+
+    /** Quote a string for inclusion in a java.text.MessageFormat
+     */
+    private String escapeLogMessageParam(String s) {
+        if (s == null)
+            return null;
+        if (s.contains("{") || s.contains("}"))
+            return "'" + s.replaceAll("'", "''") + "'";
+        return s;
     }
 
     public void debug(byte data[]) {
-- 
1.8.3.1


From a35c6cde1047e305142bec839b8953d90008c127 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Tue, 7 Feb 2017 10:36:20 +1000
Subject: [PATCH 05/49] Allow arbitrary user data in cert request

If a certificate request comes with additional data in the
'cert-request' query param, add that to the request.  Profile
components can then use this data.

This is needed to convey the subject principal name to the
ExternalProcessConstraint, when validating FreeIPA certificate
requests after we switch to GSS-API authentication.

Part of: https://pagure.io/dogtagpki/issue/1359
---
 base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java     | 5 +++++
 base/common/src/com/netscape/certsrv/request/IRequest.java           | 5 +++++
 .../cms/src/com/netscape/cms/profile/common/EnrollProfile.java       | 3 +++
 .../cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java   | 5 +++++
 4 files changed, 18 insertions(+)

diff --git a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
index 1266712..34543cb 100644
--- a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
+++ b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
@@ -180,6 +180,11 @@ public interface IEnrollProfile extends IProfile {
     public static final String REQUEST_AUTHORITY_ID = "req_authority_id";
 
     /**
+     * Arbitrary user-supplied data.
+     */
+    public static final String REQUEST_USER_DATA = "req_user_data";
+
+    /**
      * Set Default X509CertInfo in the request.
      *
      * @param request profile-based certificate request.
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index a57f08e..cfc4ca0 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -96,6 +96,11 @@ public interface IRequest extends Serializable {
      */
     public static final String AUTHORITY_ID = "req_authority_id";
 
+    /**
+     * Arbitrary user-supplied data that will be saved in request.
+     */
+    public static final String USER_DATA = "user_data";
+
     public static final String RESULT = "Result"; // service result.
     public static final Integer RES_SUCCESS = Integer.valueOf(1); // result value
     public static final Integer RES_ERROR = Integer.valueOf(2); // result value
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
index 5f7b0ef..1c44e2c 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -221,6 +221,9 @@ public abstract class EnrollProfile extends BasicProfile
 
             // set requested CA
             result[i].setExtData(IRequest.AUTHORITY_ID, ctx.get(REQUEST_AUTHORITY_ID));
+
+            // set user data
+            result[i].setExtData(IRequest.USER_DATA, ctx.get(REQUEST_USER_DATA));
         }
         return result;
     }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
index d394fd3..908cbe4 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -147,6 +147,11 @@ public class EnrollmentProcessor extends CertProcessor {
 
             IProfileContext ctx = profile.createContext();
 
+            // set arbitrary user data into request, if any
+            String userData = request.getParameter("user-data");
+            if (userData != null)
+                ctx.set(IEnrollProfile.REQUEST_USER_DATA, userData);
+
             if (aid != null)
                 ctx.set(IEnrollProfile.REQUEST_AUTHORITY_ID, aid.toString());
 
-- 
1.8.3.1


From f67071910c6b74790f7ad75329f05e599076dee4 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 8 Feb 2017 11:55:13 +1000
Subject: [PATCH 06/49] CertProcessor: set external principal attributes into
 request

When processing a certificate request, if the authenticated
principal is an ExternalPrincipal, add its whole attribute map to
the IRequest.  This provides a way for AJP request attributes to be
propagated through the profile system to profile components like
ExternalProcessConstraint.  One such attribute that is needed for
GSS-API support is "KRB5CCNAME".

Part of: https://pagure.io/dogtagpki/issue/1359
---
 .../netscape/cms/servlet/cert/CertProcessor.java    | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
index 0534f90..156060a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -18,6 +18,7 @@
 package com.netscape.cms.servlet.cert;
 
 import java.math.BigInteger;
+import java.security.Principal;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -26,6 +27,7 @@ import java.util.Locale;
 import javax.servlet.http.HttpServletRequest;
 
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.ExternalAuthToken;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
@@ -46,6 +48,7 @@ import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.request.RequestStatus;
 import com.netscape.cms.servlet.common.AuthCredentials;
 import com.netscape.cms.servlet.processors.CAProcessor;
+import com.netscape.cms.tomcat.ExternalPrincipal;
 import com.netscape.cmsutil.ldap.LDAPUtil;
 
 public class CertProcessor extends CAProcessor {
@@ -139,6 +142,24 @@ public class CertProcessor extends CAProcessor {
                 }
             }
         }
+
+        // special processing of ExternalAuthToken / ExternalPrincipal
+        if (authToken instanceof ExternalAuthToken) {
+            Principal principal =
+                ((ExternalAuthToken) authToken).getPrincipal();
+            if (principal instanceof ExternalPrincipal) {
+                HashMap<String, Object> m =
+                    ((ExternalPrincipal) principal).getAttributes();
+                for (String k : m.keySet()) {
+                    req.setExtData(
+                        IRequest.AUTH_TOKEN_PREFIX
+                            + "." + "PRINCIPAL"
+                            + "." + k
+                        , m.get(k).toString()
+                    );
+                }
+            }
+        }
     }
 
     /*
-- 
1.8.3.1


From dcc42ad4ed7fcbc566b7cf7ce1cbfae93b24a9a9 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 7 Dec 2016 15:24:07 +1000
Subject: [PATCH 07/49] Add ExternalProcessConstraint for request validation

Add the ExternalProcessConstraint profile policy constraint class.
It can be configured to execute an arbitrary program that performs
additional request validation, rejecting the request if it
terminates with a nonzero exit status.  Information about the
request is conveyed in the subprocess' environment.

Part of: https://pagure.io/dogtagpki/issue/1359
---
 base/ca/shared/conf/registry.cfg                   |   5 +-
 .../constraint/ExternalProcessConstraint.java      | 178 +++++++++++++++++++++
 .../04-AddExternalProcessConstraintToRegistry      |  67 ++++++++
 3 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java
 create mode 100755 base/server/upgrade/10.4.0/04-AddExternalProcessConstraintToRegistry

diff --git a/base/ca/shared/conf/registry.cfg b/base/ca/shared/conf/registry.cfg
index 280c713..2855b7a 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,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl
+constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,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
@@ -45,6 +45,9 @@ constraintPolicy.renewGracePeriodConstraintImpl.name=Renewal Grace Period Constr
 constraintPolicy.uniqueKeyConstraintImpl.class=com.netscape.cms.profile.constraint.UniqueKeyConstraint
 constraintPolicy.uniqueKeyConstraintImpl.desc=Unique Public Key Constraint
 constraintPolicy.uniqueKeyConstraintImpl.name=Unique Public Key Constraint
+constraintPolicy.externalProcessConstraintImpl.class=com.netscape.cms.profile.constraint.ExternalProcessConstraint
+constraintPolicy.externalProcessConstraintImpl.desc=External Process Constraint
+constraintPolicy.externalProcessConstraintImpl.name=External Process Constraint
 defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl
 defaultPolicy.autoAssignDefaultImpl.class=com.netscape.cms.profile.def.AutoAssignDefault
 defaultPolicy.autoAssignDefaultImpl.desc=Auto Request Assignment Default
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java
new file mode 100644
index 0000000..8fb91ab
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/ExternalProcessConstraint.java
@@ -0,0 +1,178 @@
+// --- 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) 2016, 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.profile.constraint;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.IOUtils;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.input.CertReqInput;
+
+import netscape.security.x509.X509CertInfo;
+
+
+public class ExternalProcessConstraint extends EnrollConstraint {
+
+    public static final String CONFIG_EXECUTABLE = "executable";
+    public static final String CONFIG_TIMEOUT = "timeout";
+
+    public static final long DEFAULT_TIMEOUT = 10;
+
+    /* Map of envvars to include, and the corresponding IRequest keys
+     *
+     * All keys will be prefixed with "DOGTAG_" when added to environment.
+     */
+    protected static final Map<String, String> envVars = new TreeMap<>();
+
+    protected Map<String, String> extraEnvVars = new TreeMap<>();
+
+    static {
+        envVars.put("DOGTAG_CERT_REQUEST", CertReqInput.VAL_CERT_REQUEST);
+        envVars.put("DOGTAG_USER",
+            IRequest.AUTH_TOKEN_PREFIX + "." + IAuthToken.USER_ID);
+        envVars.put("DOGTAG_PROFILE_ID", IRequest.PROFILE_ID);
+        envVars.put("DOGTAG_AUTHORITY_ID", IRequest.AUTHORITY_ID);
+        envVars.put("DOGTAG_USER_DATA", IRequest.USER_DATA);
+    }
+
+    protected String executable;
+    protected long timeout;
+
+    public ExternalProcessConstraint() {
+        addConfigName(CONFIG_EXECUTABLE);
+        addConfigName(CONFIG_TIMEOUT);
+    }
+
+    public void init(IProfile profile, IConfigStore config)
+            throws EProfileException {
+        super.init(profile, config);
+
+        this.executable = getConfig(CONFIG_EXECUTABLE);
+        if (this.executable == null || this.executable.isEmpty()) {
+            throw new EProfileException(
+                "Missing required config param 'executable'");
+        }
+
+        timeout = DEFAULT_TIMEOUT;
+        String timeoutConfig = getConfig(CONFIG_TIMEOUT);
+        if (this.executable != null && !this.executable.isEmpty()) {
+            try {
+                timeout = (new Integer(timeoutConfig)).longValue();
+            } catch (NumberFormatException e) {
+                throw new EProfileException("Invalid timeout value", e);
+            }
+            if (timeout < 1) {
+                throw new EProfileException(
+                    "Invalid timeout value: must be positive");
+            }
+        }
+
+        IConfigStore envConfig = config.getSubStore("params.env");
+        Enumeration<String> names = envConfig.getPropertyNames();
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+            try {
+                extraEnvVars.put(name, envConfig.getString(name));
+            } catch (EBaseException e) {
+                // shouldn't happen; log and move on
+                CMS.debug(
+                    "ExternalProcessConstraint: caught exception processing "
+                    + "'params.env' config: " + e
+                );
+
+            }
+        }
+    }
+
+    public IDescriptor getConfigDescriptor(Locale locale, String name) {
+        if (name.equals(CONFIG_EXECUTABLE)) {
+            return new Descriptor(
+                IDescriptor.STRING, null, null, "Executable path");
+        } else if (name.equals(CONFIG_TIMEOUT)) {
+            return new Descriptor(
+                IDescriptor.INTEGER, null, null, "Timeout in seconds");
+        } else {
+            return null;
+        }
+    }
+
+    public void validate(IRequest request, X509CertInfo info)
+            throws ERejectException {
+        CMS.debug("About to execute command: " + this.executable);
+        ProcessBuilder pb = new ProcessBuilder(this.executable);
+
+        // set up process environment
+        Map<String, String> env = pb.environment();
+        for (String k : envVars.keySet()) {
+            String v = request.getExtDataInString(envVars.get(k));
+            if (v != null)
+                env.put(k, v);
+        }
+        for (String k : extraEnvVars.keySet()) {
+            String v = request.getExtDataInString(extraEnvVars.get(k));
+            if (v != null)
+                env.put(k, v);
+        }
+
+        Process p;
+        String stdout = "";
+        String stderr = "";
+        boolean timedOut;
+        try {
+            p = pb.start();
+            timedOut = !p.waitFor(timeout, TimeUnit.SECONDS);
+            if (timedOut)
+                p.destroyForcibly();
+            else
+                stdout = IOUtils.toString(p.getInputStream());
+                stderr = IOUtils.toString(p.getErrorStream());
+        } catch (Throwable e) {
+            String msg =
+                "Caught exception while executing command: " + this.executable;
+            CMS.debug(msg);
+            CMS.debug(e);
+            throw new ERejectException(msg, e);
+        }
+        if (timedOut)
+            throw new ERejectException("Request validation timed out");
+        int exitValue = p.exitValue();
+        CMS.debug("ExternalProcessConstraint: exit value: " + exitValue);
+        CMS.debug("ExternalProcessConstraint: stdout: " + stdout);
+        CMS.debug("ExternalProcessConstraint: stderr: " + stderr);
+        if (exitValue != 0)
+            throw new ERejectException(stdout);
+    }
+
+}
diff --git a/base/server/upgrade/10.4.0/04-AddExternalProcessConstraintToRegistry b/base/server/upgrade/10.4.0/04-AddExternalProcessConstraintToRegistry
new file mode 100755
index 0000000..a9ee00a
--- /dev/null
+++ b/base/server/upgrade/10.4.0/04-AddExternalProcessConstraintToRegistry
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+# Authors:
+#     Fraser Tweedale <ftweedal@redhat.com>
+#
+# 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.
+#
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+
+from __future__ import absolute_import
+import os.path
+
+import pki
+from pki.server.upgrade import PKIServerUpgradeScriptlet
+
+
+class AddExternalProcessConstraintToRegistry(PKIServerUpgradeScriptlet):
+
+    new_config = {
+        'constraintPolicy.externalProcessConstraintImpl.class':
+            'com.netscape.cms.profile.constraint.ExternalProcessConstraint',
+        'constraintPolicy.externalProcessConstraintImpl.desc':
+            'External Process Constraint',
+        'constraintPolicy.externalProcessConstraintImpl.name':
+            'External Process Constraint',
+    }
+
+    constraint_name = 'externalProcessConstraintImpl'
+
+    def __init__(self):
+        super(AddExternalProcessConstraintToRegistry, self).__init__()
+        self.message = 'Add ExternalProcessConstraint to registry'
+
+    def upgrade_subsystem(self, instance, subsystem):
+        if subsystem.name == 'ca':
+            self.add_new_entries(instance, subsystem)
+
+    def add_new_entries(self, instance, subsystem):  # pylint: disable=W0613
+        filename = os.path.join(subsystem.conf_dir, 'registry.cfg')
+        self.backup(filename)
+
+        properties = pki.PropertyFile(filename)
+        properties.read()
+
+        # add constraint to constraint list
+        constraints = properties.get('constraintPolicy.ids').split(',')
+        if self.constraint_name in constraints:
+            return  # update not required
+
+        constraints.append(self.constraint_name)
+        properties.set('constraintPolicy.ids', ','.join(constraints))
+
+        for k, v in self.new_config.items():
+            properties.set(k, v)
+
+        properties.write()
-- 
1.8.3.1


From b099b631bb49e17e0aa4cd8c7a818ba1c923ec92 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 8 Feb 2017 12:18:03 +1000
Subject: [PATCH 08/49] Add authn manager that reuses auth token from session

To process a cert request immediately (rather than having it queued
as pending), the user must be authenticated *by the profile*; auth
tokens from the main authentication system are not used.

For external authentication support it is possible that the external
authentication is sufficient to authenticate use of a problem;
especially when the profile uses componenets like
ExternalProcessConstraint to perform validation of the cert request
against external sources of information.

To support this use case, add the SessionAuthentication profile
authenticator, which merely reuses the IAuthToken from the session
context, if present.

Part of: https://pagure.io/dogtagpki/issue/1359
---
 base/ca/shared/conf/CS.cfg                         |   2 +
 .../cms/authentication/SessionAuthentication.java  | 167 +++++++++++++++++++++
 base/server/upgrade/10.4.1/.gitignore              |   4 +
 .../10.4.2/01-AddSessionAuthenticationPlugin       |  51 +++++++
 4 files changed, 224 insertions(+)
 create mode 100644 base/server/cms/src/com/netscape/cms/authentication/SessionAuthentication.java
 create mode 100644 base/server/upgrade/10.4.1/.gitignore
 create mode 100755 base/server/upgrade/10.4.2/01-AddSessionAuthenticationPlugin

diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
index e800360..3923319 100644
--- a/base/ca/shared/conf/CS.cfg
+++ b/base/ca/shared/conf/CS.cfg
@@ -175,6 +175,7 @@ auths.impl.UidPwdGroupDirAuth.class=com.netscape.cms.authentication.UidPwdGroupD
 auths.impl.UserPwdDirAuth.class=com.netscape.cms.authentication.UserPwdDirAuthentication
 auths.impl.TokenAuth.class=com.netscape.cms.authentication.TokenAuthentication
 auths.impl.FlatFileAuth.class=com.netscape.cms.authentication.FlatFileAuth
+auths.impl.SessionAuthentication.class=com.netscape.cms.authentication.SessionAuthentication
 auths.instance.TokenAuth.pluginName=TokenAuth
 auths.instance.AgentCertAuth.agentGroup=Certificate Manager Agents
 auths.instance.AgentCertAuth.pluginName=AgentCertAuth
@@ -183,6 +184,7 @@ auths.instance.raCertAuth.pluginName=AgentCertAuth
 auths.instance.flatFileAuth.pluginName=FlatFileAuth
 auths.instance.flatFileAuth.fileName=[PKI_INSTANCE_PATH]/conf/[PKI_SUBSYSTEM_TYPE]/flatfile.txt
 auths.instance.SSLclientCertAuth.pluginName=SSLclientCertAuth
+auths.instance.SessionAuthentication.pluginName=SessionAuthentication
 auths.revocationChecking.bufferSize=50
 auths.revocationChecking.ca=ca
 auths.revocationChecking.enabled=true
diff --git a/base/server/cms/src/com/netscape/cms/authentication/SessionAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/SessionAuthentication.java
new file mode 100644
index 0000000..27f08cd
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/SessionAuthentication.java
@@ -0,0 +1,167 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cms.authentication;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+
+/**
+ * Pull any existing auth token from the session context.
+ *
+ * Use with caution as a profile authenticator; if there is a
+ * session it will unconditionally approve the request
+ * (subject to constraints, etc).
+ */
+public class SessionAuthentication
+        implements IProfileAuthenticator {
+
+    private String instName = null;
+    private String implName = null;
+    private IConfigStore config = null;
+
+    public SessionAuthentication() {
+    }
+
+    public void init(String instName, String implName, IConfigStore config)
+            throws EBaseException {
+        this.instName = instName;
+        this.implName = implName;
+        this.config = config;
+    }
+
+    /**
+     * Gets the name of this authentication manager.
+     */
+    public String getName() {
+        return instName;
+    }
+
+    /**
+     * Gets the plugin name of authentication manager.
+     */
+    public String getImplName() {
+        return implName;
+    }
+
+    public boolean isSSLClientRequired() {
+        return false;
+    }
+
+    /**
+     * Authenticate user.
+     *
+     * @return the auth token from existing session context, if any.
+     * @throws EMissingCredential if no auth token or no session
+     */
+    public IAuthToken authenticate(IAuthCredentials authCred)
+            throws EMissingCredential {
+        SessionContext context = SessionContext.getExistingContext();
+
+        if (context == null)
+            throw new EMissingCredential("SessionAuthentication: no session");
+
+        IAuthToken authToken = (IAuthToken)
+            context.get(SessionContext.AUTH_TOKEN);
+
+        if (authToken == null)
+            throw new EMissingCredential("SessionAuthentication: no auth token");
+
+        return authToken;
+    }
+
+    public String[] getRequiredCreds() {
+        String[] requiredCreds = { };
+        return requiredCreds;
+    }
+
+    public String[] getConfigParams() {
+        return null;
+    }
+
+    /**
+     * prepare this authentication manager for shutdown.
+     */
+    public void shutdown() {
+    }
+
+    /**
+     * gets the configuretion substore used by this authentication
+     * manager
+     *
+     * @return configuration store
+     */
+    public IConfigStore getConfigStore() {
+        return config;
+    }
+
+    // Profile-related methods
+
+    public void init(IProfile profile, IConfigStore config) {
+    }
+
+    /**
+     * Retrieves the localizable name of this policy.
+     */
+    public String getName(Locale locale) {
+        return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_NAME");
+    }
+
+    /**
+     * Retrieves the localizable description of this policy.
+     */
+    public String getText(Locale locale) {
+        return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_AGENT_TEXT");
+    }
+
+    /**
+     * Retrieves a list of names of the value parameter.
+     */
+    public Enumeration<String> getValueNames() {
+        return Collections.emptyEnumeration();
+    }
+
+    public boolean isValueWriteable(String name) {
+        return false;
+    }
+
+    /**
+     * Retrieves the descriptor of the given value
+     * parameter by name.
+     */
+    public IDescriptor getValueDescriptor(Locale locale, String name) {
+        return null;
+    }
+
+    public void populate(IAuthToken token, IRequest request) {
+    }
+}
diff --git a/base/server/upgrade/10.4.1/.gitignore b/base/server/upgrade/10.4.1/.gitignore
new file mode 100644
index 0000000..5e7d273
--- /dev/null
+++ b/base/server/upgrade/10.4.1/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/base/server/upgrade/10.4.2/01-AddSessionAuthenticationPlugin b/base/server/upgrade/10.4.2/01-AddSessionAuthenticationPlugin
new file mode 100755
index 0000000..62d508e
--- /dev/null
+++ b/base/server/upgrade/10.4.2/01-AddSessionAuthenticationPlugin
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+# Authors:
+#     Fraser Tweedale <ftweedal@redhat.com>
+#
+# 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.
+#
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+
+from __future__ import absolute_import
+import os.path
+
+import pki
+from pki.server.upgrade import PKIServerUpgradeScriptlet
+
+
+class AddSessionAuthenticationPlugin(PKIServerUpgradeScriptlet):
+    def __init__(self):
+        super(AddSessionAuthenticationPlugin, self).__init__()
+        self.message = 'Add SessionAuthentication to CS.cfg'
+
+    def upgrade_subsystem(self, instance, subsystem):
+        if subsystem.name == 'ca':
+            self.add_plugin(instance, subsystem)
+
+    def add_plugin(self, instance, subsystem):  # pylint: disable=W0613
+        filename = os.path.join(subsystem.conf_dir, 'CS.cfg')
+        self.backup(filename)
+
+        properties = pki.PropertyFile(filename)
+        properties.read()
+
+        properties.set(
+            'auths.impl.SessionAuthentication.class',
+            'com.netscape.cms.authentication.SessionAuthentication')
+        properties.set(
+            'auths.instance.SessionAuthentication.pluginName',
+            'SessionAuthentication')
+
+        properties.write()
-- 
1.8.3.1


From b9dc595806abb17f34a679976122e526bdc29de8 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Tue, 18 Apr 2017 16:46:12 -0400
Subject: [PATCH 09/49] Modify cert clients to check server for wrapping params

CRMFPopClient and the pki cert client both can send a CRMF request
to a CA directly.  Logic is added to check the CA for the required
KRA wrapping params and use those in place of any that have been
provided by the environment or command line.

Also, additional data for the supported KRA keyset has been added to
the CAInfoService.  This will need to be managed by the admin.  The
default is "1" which corresponds to AES.

Change-Id: I186f9c610005ec300bccf1b07470493ce7cdfeb4
---
 base/common/src/org/dogtagpki/common/CAInfo.java   | 16 +++++
 .../src/com/netscape/cmstools/CRMFPopClient.java   | 71 ++++++++++++++++++++--
 .../cmstools/client/ClientCertRequestCLI.java      | 32 ++++++----
 .../org/dogtagpki/server/rest/CAInfoService.java   | 10 +++
 4 files changed, 110 insertions(+), 19 deletions(-)

diff --git a/base/common/src/org/dogtagpki/common/CAInfo.java b/base/common/src/org/dogtagpki/common/CAInfo.java
index 89255ed..f21dcd0 100644
--- a/base/common/src/org/dogtagpki/common/CAInfo.java
+++ b/base/common/src/org/dogtagpki/common/CAInfo.java
@@ -54,6 +54,7 @@ public class CAInfo extends ResourceMessage {
     }
 
     String archivalMechanism;
+    String wrappingKeySet;
 
     @XmlElement(name="ArchivalMechanism")
     public String getArchivalMechanism() {
@@ -64,11 +65,21 @@ public class CAInfo extends ResourceMessage {
         this.archivalMechanism = archivalMechanism;
     }
 
+    @XmlElement(name="WrappingKeySet")
+    public String getWrappingKeySet() {
+        return wrappingKeySet;
+    }
+
+    public void setWrappingKeySet(String wrappingKeySet) {
+        this.wrappingKeySet = wrappingKeySet;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = super.hashCode();
         result = prime * result + ((archivalMechanism == null) ? 0 : archivalMechanism.hashCode());
+        result = prime * result + ((wrappingKeySet == null) ? 0 : wrappingKeySet.hashCode());
         return result;
     }
 
@@ -86,6 +97,11 @@ public class CAInfo extends ResourceMessage {
                 return false;
         } else if (!archivalMechanism.equals(other.archivalMechanism))
             return false;
+        if (wrappingKeySet == null) {
+            if (other.wrappingKeySet != null)
+                return false;
+        } else if (!wrappingKeySet.equals(other.wrappingKeySet))
+            return false;
         return true;
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
index 5d9f7f1..0168503 100644
--- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -40,6 +40,8 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.util.EntityUtils;
+import org.dogtagpki.common.CAInfo;
+import org.dogtagpki.common.CAInfoClient;
 import org.dogtagpki.common.KRAInfoResource;
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.asn1.ASN1Util;
@@ -75,6 +77,9 @@ import org.mozilla.jss.pkix.primitive.Name;
 import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
 import org.mozilla.jss.util.Password;
 
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.client.ClientConfig;
+import com.netscape.certsrv.client.PKIClient;
 import com.netscape.cmsutil.crypto.CryptoUtil;
 import com.netscape.cmsutil.util.Cert;
 import com.netscape.cmsutil.util.HMACDigest;
@@ -187,6 +192,10 @@ public class CRMFPopClient {
         option.setArgName("keyWrap");
         options.addOption(option);
 
+        option = new Option("w", true, "Wrapping Keyset");
+        option.setArgName("keySet");
+        options.addOption(option);
+
         options.addOption("v", "verbose", false, "Run in verbose mode.");
         options.addOption(null, "help", false, "Show help message.");
 
@@ -218,6 +227,7 @@ public class CRMFPopClient {
         System.out.println("  -g <true|false>              Use KeyWrapping to wrap private key (default: true)");
         System.out.println("                               - true: use a key wrapping algorithm");
         System.out.println("                               - false: use an encryption algorithm");
+        System.out.println("  -w <keyset_id>               Key set ID to use when wrapping the private key");
         System.out.println("  -b <transport cert>          PEM transport certificate (default: transport.txt)");
         System.out.println("  -v, --verbose                Run in verbose mode.");
         System.out.println("      --help                   Show help message.");
@@ -310,6 +320,7 @@ public class CRMFPopClient {
         int sensitive = Integer.parseInt(cmd.getOptionValue("s", "-1"));
         int extractable = Integer.parseInt(cmd.getOptionValue("e", "-1"));
 
+        // get the key wrapping mechanism
         boolean keyWrap = true;
         if (cmd.hasOption("g")) {
             keyWrap = Boolean.parseBoolean(cmd.getOptionValue("g"));
@@ -319,6 +330,10 @@ public class CRMFPopClient {
                 keyWrap = Boolean.parseBoolean(useKeyWrap);
             }
         }
+        String archivalMechanism = keyWrap ? KRAInfoResource.KEYWRAP_MECHANISM :
+            KRAInfoResource.ENCRYPT_MECHANISM;
+
+        String wrappingKeySet = cmd.getOptionValue("w");
 
         String output = cmd.getOptionValue("o");
 
@@ -326,6 +341,16 @@ public class CRMFPopClient {
         String username = cmd.getOptionValue("u");
         String requestor = cmd.getOptionValue("r");
 
+        if (hostPort != null) {
+            if (cmd.hasOption("g") || cmd.hasOption("w")) {
+                printError("Wrapping Key Set (-g) and keywrap (-w) options should " +
+                        "not be specified when hostport is specified.  " +
+                        "CRMFPopClient will contact the server to " +
+                        "determine the correct values for these parameters");
+                System.exit(1);
+            }
+        }
+
         if (subjectDN == null) {
             printError("Missing subject DN");
             System.exit(1);
@@ -458,11 +483,41 @@ public class CRMFPopClient {
             String kid = CryptoUtil.byte2string(id);
             System.out.println("Keypair private key id: " + kid);
 
-            String archivalMechanism = keyWrap ? KRAInfoResource.KEYWRAP_MECHANISM :
-                KRAInfoResource.ENCRYPT_MECHANISM;
+            if (hostPort != null) {
+                // check the CA for the required keyset and archival mechanism
+                // if found, override whatever has been set by the command line
+                // options or environment for archivalMechanism and wrappingKeySet
+
+                ClientConfig config = new ClientConfig();
+                String host = hostPort.substring(0, hostPort.indexOf(':'));
+                int port = Integer.parseInt(hostPort.substring(hostPort.indexOf(':')+1));
+                config.setServerURL("http", host, port);
+
+                PKIClient pkiclient = new PKIClient(config);
+
+                // get archival mechanism
+                CAInfoClient infoClient = new CAInfoClient(pkiclient, "ca");
+                try {
+                    CAInfo info = infoClient.getInfo();
+                    archivalMechanism = info.getArchivalMechanism();
+                    wrappingKeySet = info.getWrappingKeySet();
+                } catch (PKIException e) {
+                    if (e.getCode() == 404) {
+                        // assume this is an older server,
+                        archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM;
+                        wrappingKeySet = "0";
+                    } else {
+                        throw new Exception("Failed to retrieve archive wrapping information from the CA: " + e, e);
+                    }
+                } catch (Exception e) {
+                    throw new Exception("Failed to retrieve archive wrapping information from the CA: " + e, e);
+                }
+            }
+
             if (verbose) System.out.println("Creating certificate request");
             CertRequest certRequest = client.createCertRequest(
-                    token, transportCert, algorithm, keyPair, subject, archivalMechanism);
+                    token, transportCert, algorithm, keyPair,
+                    subject, archivalMechanism, wrappingKeySet);
 
             ProofOfPossession pop = null;
 
@@ -572,11 +627,15 @@ public class CRMFPopClient {
             String algorithm,
             KeyPair keyPair,
             Name subject,
-            String archivalMechanism) throws Exception {
+            String archivalMechanism,
+            String wrappingKeySet) throws Exception {
         EncryptionAlgorithm encryptAlg = null;
-        String keyset = System.getenv("KEY_WRAP_PARAMETER_SET");
 
-        if (keyset != null && keyset.equalsIgnoreCase("0")) {
+        if (wrappingKeySet == null) {
+            wrappingKeySet = System.getenv("KEY_WRAP_PARAMETER_SET");
+        }
+
+        if (wrappingKeySet != null && wrappingKeySet.equalsIgnoreCase("0")) {
             // talking to an old server?
             encryptAlg = EncryptionAlgorithm.DES3_CBC;
         } else {
diff --git a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java
index 8ca857b..696ab8b 100644
--- a/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/client/ClientCertRequestCLI.java
@@ -29,6 +29,7 @@ import java.util.Vector;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.io.FileUtils;
+import org.dogtagpki.common.CAInfo;
 import org.dogtagpki.common.CAInfoClient;
 import org.dogtagpki.common.KRAInfoResource;
 import org.mozilla.jss.CryptoManager;
@@ -39,6 +40,7 @@ import org.mozilla.jss.pkix.crmf.CertRequest;
 import org.mozilla.jss.pkix.crmf.ProofOfPossession;
 import org.mozilla.jss.pkix.primitive.Name;
 
+import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.cert.CertClient;
 import com.netscape.certsrv.cert.CertEnrollmentRequest;
 import com.netscape.certsrv.cert.CertRequestInfos;
@@ -250,23 +252,26 @@ public class ClientCertRequestCLI extends CLI {
             // get archival mechanism
             CAInfoClient infoClient = new CAInfoClient(client, "ca");
             String archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM;
+            String wrappingKeySet = "1";
             try {
-                archivalMechanism = infoClient.getInfo().getArchivalMechanism();
-            } catch (Exception e) {
-                // this could be an older server, check for environment variable.
-                String useKeyWrapping = System.getenv("KEY_ARCHIVAL_USE_KEY_WRAPPING");
-                if (useKeyWrapping != null) {
-                    if (Boolean.parseBoolean(useKeyWrapping)) {
-                        archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM;
-                    } else {
-                        archivalMechanism = KRAInfoResource.ENCRYPT_MECHANISM;
-                    }
+                CAInfo info = infoClient.getInfo();
+                archivalMechanism = info.getArchivalMechanism();
+                wrappingKeySet = info.getWrappingKeySet();
+            } catch (PKIException e) {
+                if (e.getCode() == 404) {
+                    // assume this is an older server,
+                    archivalMechanism = KRAInfoResource.KEYWRAP_MECHANISM;
+                    wrappingKeySet = "0";
+                } else {
+                    throw new Exception("Failed to retrieve archive wrapping information from the CA: " + e, e);
                 }
+            } catch (Exception e) {
+                throw new Exception("Failed to retrieve archive wrapping information from the CA: " + e, e);
             }
 
             csr = generateCrmfRequest(transportCert, subjectDN, attributeEncoding,
                     algorithm, length, curve, sslECDH, temporary, sensitive, extractable, withPop,
-                    archivalMechanism);
+                    archivalMechanism, wrappingKeySet);
 
         } else {
             throw new Exception("Unknown request type: " + requestType);
@@ -408,7 +413,8 @@ public class ClientCertRequestCLI extends CLI {
             int sensitive,
             int extractable,
             boolean withPop,
-            String archivalMechanism
+            String archivalMechanism,
+            String wrappingKeySet
             ) throws Exception {
 
         CryptoManager manager = CryptoManager.getInstance();
@@ -430,7 +436,7 @@ public class ClientCertRequestCLI extends CLI {
         }
 
         CertRequest certRequest = client.createCertRequest(
-                token, transportCert, algorithm, keyPair, subject, archivalMechanism);
+                token, transportCert, algorithm, keyPair, subject, archivalMechanism, wrappingKeySet);
 
         ProofOfPossession pop = null;
         if (withPop) {
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/CAInfoService.java b/base/server/cms/src/org/dogtagpki/server/rest/CAInfoService.java
index 975ad61..f4724a6 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/CAInfoService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/CAInfoService.java
@@ -50,6 +50,8 @@ public class CAInfoService extends PKIService implements CAInfoResource {
         if (archivalMechanism != null)
             info.setArchivalMechanism(getArchivalMechanism());
 
+        info.setWrappingKeySet(getWrappingKeySet());
+
         return createOKResponse(info);
     }
 
@@ -61,4 +63,12 @@ public class CAInfoService extends PKIService implements CAInfoResource {
         boolean encrypt_archival = cs.getBoolean("kra.allowEncDecrypt.archival", false);
         return encrypt_archival ? KRAInfoService.ENCRYPT_MECHANISM : KRAInfoService.KEYWRAP_MECHANISM;
     }
+
+    String getWrappingKeySet() throws EBaseException {
+        IConfigStore cs = CMS.getConfigStore();
+        boolean kra_present = cs.getBoolean("ca.connector.KRA.enable", false);
+        if (!kra_present) return null;
+
+        return cs.getString("kra.wrappingKeySet", "1");
+    }
 }
-- 
1.8.3.1


From 316e20d2e39542bcb2d2043f36633dc7b779c61b Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Wed, 19 Apr 2017 14:19:37 -0400
Subject: [PATCH 10/49] Make sure connection is always closed

When an exception is thrown, the connection is currently
not closed, leading to Invalid State exceptions when the
next connection is attempted.  This resolves this issue.

Change-Id: I531881434a73affb1c6536dfbb05bce151c854fb
---
 .../com/netscape/certsrv/client/PKIConnection.java | 30 ++++++++++++++--------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
index d5e4c00..d655023 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
@@ -429,23 +429,33 @@ public class PKIConnection {
     }
 
     public <T> T getEntity(Response response, Class<T> clazz) {
-        Family family = response.getStatusInfo().getFamily();
-        if (!family.equals(Family.CLIENT_ERROR) && !family.equals(Family.SERVER_ERROR)) {
-            if (response.hasEntity()) return response.readEntity(clazz);
+        try {
+            Family family = response.getStatusInfo().getFamily();
+            if (!family.equals(Family.CLIENT_ERROR) && !family.equals(Family.SERVER_ERROR)) {
+                if (response.hasEntity())
+                    return response.readEntity(clazz);
+                return null;
+            }
+            handleErrorResponse(response);
             return null;
+        } finally {
+            response.close();
         }
-        handleErrorResponse(response);
-        return null;
     }
 
     public <T> T getEntity(Response response, GenericType<T> clazz) {
-        Family family = response.getStatusInfo().getFamily();
-        if (!family.equals(Family.CLIENT_ERROR) && !family.equals(Family.SERVER_ERROR)) {
-            if (response.hasEntity()) return response.readEntity(clazz);
+        try {
+            Family family = response.getStatusInfo().getFamily();
+            if (!family.equals(Family.CLIENT_ERROR) && !family.equals(Family.SERVER_ERROR)) {
+                if (response.hasEntity())
+                    return response.readEntity(clazz);
+                return null;
+            }
+            handleErrorResponse(response);
             return null;
+        } finally {
+            response.close();
         }
-        handleErrorResponse(response);
-        return null;
     }
 
     private void handleErrorResponse(Response response) {
-- 
1.8.3.1


From 7033c5208fd315e9fd1c76d1755d1f7fd2bbf17a Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 19 Apr 2017 23:40:43 +0200
Subject: [PATCH 12/49] Added AuditEvent.setParameters().

A new method has been added to set AuditEvent's parameters.

Change-Id: I1b1e23030a819160b035ed67e908b6fbadedd714
---
 base/common/src/com/netscape/certsrv/logging/AuditEvent.java | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
index 716e0d4..72c93f8 100644
--- a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
+++ b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
@@ -387,6 +387,13 @@ public class AuditEvent implements IBundleLogEvent {
     }
 
     /**
+     * Sets audit event's parameters.
+     */
+    public void setParameters(Object[] params) {
+        mParams = params;
+    }
+
+    /**
      * Returns localized message string. This method should
      * only be called if a localized string is necessary.
      * <P>
-- 
1.8.3.1


From 6817c67bc93e99f36c79838fffc08145e6599580 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 19 Apr 2017 21:35:09 +0200
Subject: [PATCH 14/49] Updated default SSL connection timeout.

The default SSL connection timeout has been changed to 5 minutes
to improve PKI console usability.

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

Change-Id: I905ca855285ddd655d965488b175c2d11fe407fd
---
 base/server/tomcat7/conf/server.xml | 2 +-
 base/server/tomcat8/conf/server.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/base/server/tomcat7/conf/server.xml b/base/server/tomcat7/conf/server.xml
index cc3160d..35bd7a4 100644
--- a/base/server/tomcat7/conf/server.xml
+++ b/base/server/tomcat7/conf/server.xml
@@ -187,7 +187,7 @@ Tomcat Port         = [TOMCAT_SERVER_PORT] (for shutdown)
     -->
     <Connector name="[PKI_SECURE_PORT_CONNECTOR_NAME]" port="[PKI_SECURE_PORT]" protocol="HTTP/1.1" SSLEnabled="true" sslProtocol="SSL" scheme="https" secure="true"
            maxHttpHeaderSize="8192"
-           connectionTimeout="80000"
+           connectionTimeout="300000"
            acceptCount="100" maxThreads="150" minSpareThreads="25"
            enableLookups="false" disableUploadTimeout="true"
            sslImplementationName="org.apache.tomcat.util.net.jss.JSSImplementation"
diff --git a/base/server/tomcat8/conf/server.xml b/base/server/tomcat8/conf/server.xml
index af463f5..4daf85e 100644
--- a/base/server/tomcat8/conf/server.xml
+++ b/base/server/tomcat8/conf/server.xml
@@ -212,7 +212,7 @@ Tomcat Port         = [TOMCAT_SERVER_PORT] (for shutdown)
            sslProtocol="SSL"
            scheme="https"
            secure="true"
-           connectionTimeout="80000"
+           connectionTimeout="300000"
            maxHttpHeaderSize="8192"
            acceptCount="100" maxThreads="150" minSpareThreads="25"
            enableLookups="false" disableUploadTimeout="true"
-- 
1.8.3.1


From 470e6c6724fe59d9db9066971a9f24758d5fe0aa Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 01:06:18 +0200
Subject: [PATCH 15/49] Fixed SSL connection timeouts.

The connectionTimeout parameter has been restored to 80 seconds.
The keepAliveTimeout parameter has been set to 5 minutes.

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

Change-Id: I05bca0284ad946d833ed144e2f93a4ef4b9b6f0f
---
 base/server/tomcat7/conf/server.xml | 3 ++-
 base/server/tomcat8/conf/server.xml | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/base/server/tomcat7/conf/server.xml b/base/server/tomcat7/conf/server.xml
index 35bd7a4..2db8bca 100644
--- a/base/server/tomcat7/conf/server.xml
+++ b/base/server/tomcat7/conf/server.xml
@@ -187,7 +187,8 @@ Tomcat Port         = [TOMCAT_SERVER_PORT] (for shutdown)
     -->
     <Connector name="[PKI_SECURE_PORT_CONNECTOR_NAME]" port="[PKI_SECURE_PORT]" protocol="HTTP/1.1" SSLEnabled="true" sslProtocol="SSL" scheme="https" secure="true"
            maxHttpHeaderSize="8192"
-           connectionTimeout="300000"
+           connectionTimeout="80000"
+           keepAliveTimeout="300000"
            acceptCount="100" maxThreads="150" minSpareThreads="25"
            enableLookups="false" disableUploadTimeout="true"
            sslImplementationName="org.apache.tomcat.util.net.jss.JSSImplementation"
diff --git a/base/server/tomcat8/conf/server.xml b/base/server/tomcat8/conf/server.xml
index 4daf85e..64b1b00 100644
--- a/base/server/tomcat8/conf/server.xml
+++ b/base/server/tomcat8/conf/server.xml
@@ -212,7 +212,8 @@ Tomcat Port         = [TOMCAT_SERVER_PORT] (for shutdown)
            sslProtocol="SSL"
            scheme="https"
            secure="true"
-           connectionTimeout="300000"
+           connectionTimeout="80000"
+           keepAliveTimeout="300000"
            maxHttpHeaderSize="8192"
            acceptCount="100" maxThreads="150" minSpareThreads="25"
            enableLookups="false" disableUploadTimeout="true"
-- 
1.8.3.1


From 46cc674dcb6ff09167c69391054b36bdcfb36cbb Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 01:03:29 +0200
Subject: [PATCH 16/49] Refactored line concatenation.

The code that concatenates lines has been simplified using
String.replace().

Change-Id: Ib8532b12594604e3b013b5ac0ef30ce45f1351ea
---
 .../cms/profile/updater/SubsystemGroupUpdater.java  | 11 +++--------
 .../netscape/cms/servlet/csadmin/RegisterUser.java  | 14 ++++----------
 .../cms/servlet/processors/CAProcessor.java         | 21 ++++-----------------
 .../servlet/profile/ProfileSubmitCMCServlet.java    | 10 ++--------
 4 files changed, 13 insertions(+), 43 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
index 7daa8e4..4ecc255 100644
--- a/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
+++ b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
@@ -175,14 +175,9 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
                 byte[] certEncoded = cert.getEncoded();
                 b64 = CMS.BtoA(certEncoded).trim();
 
-                // extract all line separators
-                StringBuffer sb = new StringBuffer();
-                for (int i = 0; i < b64.length(); i++) {
-                    if (!Character.isWhitespace(b64.charAt(i))) {
-                        sb.append(b64.charAt(i));
-                    }
-                }
-                b64 = sb.toString();
+                // concatenate lines
+                b64 = b64.replace("\r", "").replace("\n", "");
+
             } catch (Exception ence) {
                 CMS.debug("SubsystemGroupUpdater update: user cert encoding failed: " + ence);
             }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
index f02932e..77ef4d8 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
@@ -27,8 +27,6 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.security.x509.X509CertImpl;
-
 import org.w3c.dom.Node;
 
 import com.netscape.certsrv.apps.CMS;
@@ -49,6 +47,8 @@ import com.netscape.cms.servlet.common.ICMSTemplateFiller;
 import com.netscape.cmsutil.util.Utils;
 import com.netscape.cmsutil.xml.XMLObject;
 
+import netscape.security.x509.X509CertImpl;
+
 /**
  * This servlet creates a TPS user in the CA,
  * and it associates TPS's server certificate to
@@ -207,14 +207,8 @@ public class RegisterUser extends CMSServlet {
                 audit(auditMessage);
             }
 
-            // extract all line separators
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < certsString.length(); i++) {
-                if (!Character.isWhitespace(certsString.charAt(i))) {
-                    sb.append(certsString.charAt(i));
-                }
-            }
-            certsString = sb.toString();
+            // concatenate lines
+            certsString = certsString.replace("\r", "").replace("\n", "");
 
             auditParams = "Scope;;certs+Operation;;OP_ADD+source;;RegisterUser" +
                         "+Resource;;" + uid +
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 8c4fef1..4bc738c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -1024,15 +1024,8 @@ public class CAProcessor extends Processor {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (!Character.isWhitespace(base64Data.charAt(i))) {
-                    sb.append(base64Data.charAt(i));
-
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
@@ -1180,14 +1173,8 @@ public class CAProcessor extends Processor {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (!Character.isWhitespace(base64Data.charAt(i))) {
-                    sb.append(base64Data.charAt(i));
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
index fd155a6..83bab5b 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -928,14 +928,8 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (!Character.isWhitespace(base64Data.charAt(i))) {
-                    sb.append(base64Data.charAt(i));
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
-- 
1.8.3.1


From 6bb1757a035d3439a65aa604a19dcdf48b7b2dbc Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 05:01:57 +0200
Subject: [PATCH 17/49] Refactored additional line concatenation.

The code that concatenates lines has been simplified using
String.replace().

Change-Id: Id376f089cb9b8a78cfd9b3fb922e9cd9055c0e74
---
 .../src/com/netscape/kra/EnrollmentService.java    | 12 ++++------
 .../src/com/netscape/kra/KeyRecoveryAuthority.java | 26 ++++-----------------
 .../cms/servlet/admin/CMSAdminServlet.java         | 11 ++-------
 .../netscape/cms/servlet/cert/EnrollServlet.java   | 27 ++++++++--------------
 .../cms/servlet/connector/ConnectorServlet.java    | 11 ++-------
 .../cms/servlet/request/ProcessCertReq.java        | 11 ++-------
 6 files changed, 25 insertions(+), 73 deletions(-)

diff --git a/base/kra/src/com/netscape/kra/EnrollmentService.java b/base/kra/src/com/netscape/kra/EnrollmentService.java
index 381fee8..a200c34 100644
--- a/base/kra/src/com/netscape/kra/EnrollmentService.java
+++ b/base/kra/src/com/netscape/kra/EnrollmentService.java
@@ -24,7 +24,6 @@ import java.security.InvalidKeyException;
 import java.security.PublicKey;
 import java.security.cert.CertificateException;
 import java.util.Arrays;
-import java.util.StringTokenizer;
 import java.util.Vector;
 
 import org.mozilla.jss.asn1.ASN1Util;
@@ -917,7 +916,7 @@ public class EnrollmentService implements IService {
             return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         }
 
-        StringBuffer key = new StringBuffer();
+        String key = "";
 
         // convert "rawData" into "base64Data"
         if (rawData != null) {
@@ -925,13 +924,10 @@ public class EnrollmentService implements IService {
 
             base64Data = CMS.BtoA(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            StringTokenizer st = new StringTokenizer(base64Data, "\r\n");
-            while (st.hasMoreTokens()) {
-                key.append(st.nextToken());
-            }
+            // concatenate lines
+            key = base64Data.replace("\r", "").replace("\n", "");
         }
-        String checkKey = key.toString().trim();
+        String checkKey = key.trim();
         if (checkKey.equals("")) {
             return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         } else {
diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
index 1df04db..ec920e6 100644
--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
+++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java
@@ -136,7 +136,6 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove
     public IRequestListener mReqInQListener = null;
 
     private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
-    private final static byte EOL[] = { Character.LINE_SEPARATOR };
     private final static String SIGNED_AUDIT_AGENT_DELIMITER = ", ";
     /**
      * Constructs an escrow authority.
@@ -1713,16 +1712,9 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove
         // convert "rawData" into "base64Data"
         if (rawData != null) {
             String base64Data = CMS.BtoA(rawData).trim();
-            StringBuffer key = new StringBuffer();
 
-            // extract all line separators from the "base64Data"
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    key.append(base64Data.substring(i, i));
-                }
-            }
-
-            return key.toString();
+            // concatenate lines
+            return base64Data.replace("\r", "").replace("\n", "");
         }
 
         return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
@@ -1757,23 +1749,15 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove
         }
 
         String key = null;
-        StringBuffer tempBuffer = new StringBuffer();
+
         // convert "rawData" into "base64Data"
         if (rawData != null) {
             String base64Data = null;
 
             base64Data = CMS.BtoA(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    tempBuffer.append(base64Data.substring(i, i));
-                }
-            }
-        }
-
-        if (tempBuffer.length() > 0) {
-            key = tempBuffer.toString();
+            // concatenate lines
+            key = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (key != null) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java
index 229c377..e5a1474 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java
@@ -105,7 +105,6 @@ public final class CMSAdminServlet extends AdminServlet {
     private final static String PROP_INTERNAL_DB = "internaldb";
 
     private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
-    private final static byte EOL[] = { Character.LINE_SEPARATOR };
 
     // CMS must be instantiated before this admin servlet.
 
@@ -3390,7 +3389,6 @@ public final class CMSAdminServlet extends AdminServlet {
         rawData = object.getPublic().getEncoded();
 
         String key = null;
-        StringBuffer sb = new StringBuffer();
 
         // convert "rawData" into "base64Data"
         if (rawData != null) {
@@ -3398,14 +3396,9 @@ public final class CMSAdminServlet extends AdminServlet {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    sb.append(base64Data.substring(i, i));
-                }
-            }
+            // concatenate lines
+            key = base64Data.replace("\r", "").replace("\n", "");
         }
-        key = sb.toString();
 
         if (key != null) {
             key = key.trim();
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
index 3757967..6f01d2a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
@@ -35,14 +35,6 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.dogtagpki.legacy.policy.IPolicyProcessor;
 
-import netscape.security.pkcs.PKCS10;
-import netscape.security.x509.AlgorithmId;
-import netscape.security.x509.CertificateAlgorithmId;
-import netscape.security.x509.CertificateX509Key;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509CertInfo;
-import netscape.security.x509.X509Key;
-
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.AuthToken;
 import com.netscape.certsrv.authentication.IAuthSubsystem;
@@ -78,6 +70,14 @@ import com.netscape.cms.servlet.processors.PKCS10Processor;
 import com.netscape.cms.servlet.processors.PKIProcessor;
 import com.netscape.cmsutil.util.Utils;
 
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.AlgorithmId;
+import netscape.security.x509.CertificateAlgorithmId;
+import netscape.security.x509.CertificateX509Key;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
 /**
  * Submit a Certificate Enrollment request
  *
@@ -138,7 +138,6 @@ public class EnrollServlet extends CMSServlet {
             "racertbasedenrollment";
     private final static String EE_RA_ENROLLMENT_SERVLET =
             "raenrollment";
-    private final static byte EOL[] = { Character.LINE_SEPARATOR };
     private final static String[] SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] {
 
     /* 0 */"automated non-profile cert request rejection:  "
@@ -1732,14 +1731,8 @@ public class EnrollServlet extends CMSServlet {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            StringBuffer sb = new StringBuffer();
-            // extract all line separators from the "base64Data"
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    sb.append(base64Data.substring(i, i));
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
index 13c732b..9c75cc1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -98,7 +98,6 @@ public class ConnectorServlet extends CMSServlet {
 
     protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
     private final static String SIGNED_AUDIT_PROTECTION_METHOD_SSL = "ssl";
-    private final static byte EOL[] = { Character.LINE_SEPARATOR };
 
     public ConnectorServlet() {
     }
@@ -1101,14 +1100,8 @@ public class ConnectorServlet extends CMSServlet {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            StringBuffer sb = new StringBuffer();
-            // extract all line separators from the "base64Data"
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    sb.append(base64Data.substring(i, i));
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
index d15774e..9d0da48 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
@@ -118,7 +118,6 @@ public class ProcessCertReq extends CMSServlet {
     private final static String SIGNED_AUDIT_CANCELLATION = "cancel";
     private final static String SIGNED_AUDIT_CLONING = "clone";
     private final static String SIGNED_AUDIT_REJECTION = "reject";
-    private final static byte EOL[] = { Character.LINE_SEPARATOR };
     private final static String[] SIGNED_AUDIT_MANUAL_CANCELLATION_REASON = new String[] {
 
     /* 0 */"manual non-profile cert request cancellation:  "
@@ -1840,14 +1839,8 @@ public class ProcessCertReq extends CMSServlet {
 
             base64Data = Utils.base64encode(rawData).trim();
 
-            // extract all line separators from the "base64Data"
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < base64Data.length(); i++) {
-                if (base64Data.substring(i, i).getBytes() != EOL) {
-                    sb.append(base64Data.substring(i, i));
-                }
-            }
-            cert = sb.toString();
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
         }
 
         if (cert != null) {
-- 
1.8.3.1


From 17e71d3ec1f52cc2e13590499dd70c5932885b20 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 09:56:16 +0200
Subject: [PATCH 18/49] Added AdminServlet.audit(AuditEvent).

A new audit() methods have been added to log AuditEvents in
AdminServlet.

Change-Id: I92a259363bdda553621491e46122365c7097946a
---
 .../cms/src/com/netscape/cms/servlet/admin/AdminServlet.java   | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index 089fcbe..16a2e39 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -1024,6 +1024,16 @@ public class AdminServlet extends HttpServlet {
         auditor.log(msg);
     }
 
+    protected void audit(AuditEvent event) {
+
+        String template = event.getMessage();
+        Object[] params = event.getParameters();
+
+        String message = CMS.getLogMessage(template, params);
+
+        audit(message);
+    }
+
     /**
      * Signed Audit Log Subject ID
      *
-- 
1.8.3.1


From 4a28ac15f5552d6594b6f6bb58af8f076ab5c46f Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 03:43:06 +0200
Subject: [PATCH 19/49] Refactored CAProcessor.auditInfoCertValue().

The auditInfoCertValue(IRequest) in CAProcessor has been merged
into auditInfoCertValue(X509CertImpl) since they are identical.

Change-Id: Iccdad7a3c1ff3bc05f1f0ac1830eada21337dfca
---
 .../netscape/cms/servlet/cert/CertProcessor.java   |  8 +--
 .../cms/servlet/processors/CAProcessor.java        | 57 ----------------------
 2 files changed, 5 insertions(+), 60 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
index 156060a..c16d8e0 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -36,6 +36,7 @@ import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.profile.EDeferException;
 import com.netscape.certsrv.profile.ERejectException;
+import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileContext;
@@ -51,6 +52,8 @@ import com.netscape.cms.servlet.processors.CAProcessor;
 import com.netscape.cms.tomcat.ExternalPrincipal;
 import com.netscape.cmsutil.ldap.LDAPUtil;
 
+import netscape.security.x509.X509CertImpl;
+
 public class CertProcessor extends CAProcessor {
 
     public CertProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
@@ -217,7 +220,6 @@ public class CertProcessor extends CAProcessor {
         String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = ILogger.UNIDENTIFIED;
-        String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         String errorCode = null;
         String errorReason = null;
 
@@ -244,8 +246,8 @@ public class CertProcessor extends CAProcessor {
                 profile.submit(authToken, req);
                 req.setRequestStatus(RequestStatus.COMPLETE);
 
-                // reset the "auditInfoCertValue"
-                auditInfoCertValue = auditInfoCertValue(req);
+                X509CertImpl x509cert = req.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+                String auditInfoCertValue = auditInfoCertValue(x509cert);
 
                 if (auditInfoCertValue != null) {
                     if (!(auditInfoCertValue.equals(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 4bc738c..a98d555 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -53,7 +53,6 @@ import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
-import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileSubsystem;
@@ -985,62 +984,6 @@ public class CAProcessor extends Processor {
         return requesterID;
     }
 
-    /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param request request containing an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    protected String auditInfoCertValue(IRequest request) {
-        // if no signed audit object exists, bail
-        if (signedAuditLogger == null) {
-            return null;
-        }
-
-        X509CertImpl x509cert = request.getExtDataInCert(
-                IEnrollProfile.REQUEST_ISSUED_CERT);
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
-
     protected String auditSubjectID() {
         // if no signed audit object exists, bail
         if (signedAuditLogger == null) {
-- 
1.8.3.1


From 41fcfc470c6462bc069774c74ecfe2fe09cf6ac3 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 04:24:18 +0200
Subject: [PATCH 20/49] Refactored ConnectorServlet.auditInfoCertValue().

The ConnectorServlet.auditInfoCertValue() has been refactored to
accept X509CertImpl like CAProcessor.auditInfoCertValue().

Change-Id: I42f4a17a20f43a8c9dd2b329b07de3a23da7ca33
---
 .../cms/servlet/connector/ConnectorServlet.java      | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
index 9c75cc1..6732e92 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -424,9 +424,6 @@ public class ConnectorServlet extends CMSServlet {
         String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         String subject = null;
 
-        // additional parms for LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED
-        String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-
         // "normalize" the "auditSubjectID"
         if (auditSubjectID != null) {
             auditSubjectID = auditSubjectID.trim();
@@ -622,8 +619,9 @@ public class ConnectorServlet extends CMSServlet {
                 queue.processRequest(thisreq);
 
                 if (isProfileRequest(thisreq)) {
-                    // reset the "auditInfoCertValue"
-                    auditInfoCertValue = auditInfoCertValue(thisreq);
+
+                    X509CertImpl x509cert = thisreq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+                    String auditInfoCertValue = auditInfoCertValue(x509cert);
 
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
@@ -643,8 +641,9 @@ public class ConnectorServlet extends CMSServlet {
                 }
             } catch (EBaseException eAudit1) {
                 if (isProfileRequest(thisreq)) {
-                    // reset the "auditInfoCertValue"
-                    auditInfoCertValue = auditInfoCertValue(thisreq);
+
+                    X509CertImpl x509cert = thisreq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+                    String auditInfoCertValue = auditInfoCertValue(x509cert);
 
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
@@ -1068,18 +1067,15 @@ public class ConnectorServlet extends CMSServlet {
      * "X509CertImpl" for a signed audit log message.
      * <P>
      *
-     * @param request a Request containing an X509CertImpl
+     * @param x509cert an X509CertImpl
      * @return cert string containing the certificate
      */
-    private String auditInfoCertValue(IRequest request) {
+    private String auditInfoCertValue(X509CertImpl x509cert) {
         // if no signed audit object exists, bail
         if (mSignedAuditLogger == null) {
             return null;
         }
 
-        X509CertImpl x509cert = request.getExtDataInCert(
-                IEnrollProfile.REQUEST_ISSUED_CERT);
-
         if (x509cert == null) {
             return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         }
-- 
1.8.3.1


From e74fca2ced2416d656a09613e6e56657f4f88d20 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 04:29:40 +0200
Subject: [PATCH 21/49] Refactored
 ProfileSubmitCMCServlet.auditInfoCertValue().

The ProfileSubmitCMCServlet.auditInfoCertValue() has been modified
to accept X509CertImpl like CAProcessor.auditInfoCertValue().

Change-Id: Ib3b4c4c19250df73a769590488cb5716a50a065b
---
 .../cms/servlet/profile/ProfileSubmitCMCServlet.java     | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
index 83bab5b..c3ada9a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -642,7 +642,6 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
         String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = ILogger.UNIDENTIFIED;
-        String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
 
         try {
             ///////////////////////////////////////////////
@@ -672,8 +671,8 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     profile.submit(authToken, reqs[k]);
                     reqs[k].setRequestStatus(RequestStatus.COMPLETE);
 
-                    // reset the "auditInfoCertValue"
-                    auditInfoCertValue = auditInfoCertValue(reqs[k]);
+                    X509CertImpl x509cert = reqs[k].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+                    String auditInfoCertValue = auditInfoCertValue(x509cert);
 
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
@@ -777,8 +776,8 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     profile.getRequestQueue().markAsServiced(provedReq);
                     CMS.debug("ProfileSubmitCMCServlet: provedReq set to complete");
 
-                    // reset the "auditInfoCertValue"
-                    auditInfoCertValue = auditInfoCertValue(reqs[0]);
+                    X509CertImpl x509cert = reqs[0].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
+                    String auditInfoCertValue = auditInfoCertValue(x509cert);
 
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
@@ -896,18 +895,15 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
      * "X509CertImpl" for a signed audit log message.
      * <P>
      *
-     * @param request request containing an X509CertImpl
+     * @param x509cert an X509CertImpl
      * @return cert string containing the certificate
      */
-    private String auditInfoCertValue(IRequest request) {
+    private String auditInfoCertValue(X509CertImpl x509cert) {
         // if no signed audit object exists, bail
         if (mSignedAuditLogger == null) {
             return null;
         }
 
-        X509CertImpl x509cert = request.getExtDataInCert(
-                IEnrollProfile.REQUEST_ISSUED_CERT);
-
         if (x509cert == null) {
             return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         }
-- 
1.8.3.1


From ba32351d7c362e6b0e313cde0929c56f3f55ec5f Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 21 Apr 2017 05:04:05 +0200
Subject: [PATCH 22/49] Fixed missing IAuditor.log(AuditEvent).

The IAuditor has been modified to define a log() method for
AuditEvent object.

Change-Id: Ie1ad720bd6d3bcd71a4567eed477f0e34a8274c9
---
 base/common/src/com/netscape/certsrv/logging/IAuditor.java        | 2 ++
 base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/base/common/src/com/netscape/certsrv/logging/IAuditor.java b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
index 216015f..9521228 100644
--- a/base/common/src/com/netscape/certsrv/logging/IAuditor.java
+++ b/base/common/src/com/netscape/certsrv/logging/IAuditor.java
@@ -73,4 +73,6 @@ public interface IAuditor {
      * Log audit message.
      */
     public void log(String message);
+
+    public void log(AuditEvent event);
 }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
index 48dfe3a..8962561 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/logging/Auditor.java
@@ -220,7 +220,8 @@ public class Auditor implements IAuditor {
                 message);
     }
 
-    protected void audit(AuditEvent event) {
+    @Override
+    public void log(AuditEvent event) {
 
         String template = event.getMessage();
         Object[] params = event.getParameters();
-- 
1.8.3.1


From fcbabc0ce929d91f63098bba4867d102ac04ead0 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Wed, 19 Apr 2017 08:50:06 +0200
Subject: [PATCH 23/49] Python 3 support and Travis testing

Fix Python 3 support for pkispawn: Config values are text values. Therefore
the config file has to be written as text file.

Test Python 3 support in Travis CI. The little script py3rewrite copies
pki.server Python files and rewrites pkispawn and pkidestroy to use
Python 3.

Change-Id: Ia516f80df94cacc2acfa70929ad16bb5b9c39ddf
Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 .travis.yml                               |  7 +++++
 .travis/40-spawn-ca                       |  2 +-
 .travis/50-spawn-kra                      |  2 +-
 .travis/99-destroy                        | 11 ++++++++
 .travis/py3rewrite                        | 46 +++++++++++++++++++++++++++++++
 base/server/python/pki/server/__init__.py |  4 +--
 6 files changed, 68 insertions(+), 4 deletions(-)
 create mode 100755 .travis/99-destroy
 create mode 100755 .travis/py3rewrite

diff --git a/.travis.yml b/.travis.yml
index 2714bbc..54ae884 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,6 +44,13 @@ install:
 script:
   - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/40-spawn-ca
   - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/50-spawn-kra
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/99-destroy
+  # copy pki.server for Python 3 and rewrite pkispawn/pkidestroy shebang
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/py3rewrite
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/30-setup-389ds
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/40-spawn-ca
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/50-spawn-kra
+  - docker exec -ti ${CONTAINER} ${SCRIPTDIR}/99-destroy
 
 after_script:
   - docker kill ${CONTAINER}
diff --git a/.travis/40-spawn-ca b/.travis/40-spawn-ca
index 9986698..d6771db 100755
--- a/.travis/40-spawn-ca
+++ b/.travis/40-spawn-ca
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -e
 
-pkispawn -v -f ${BUILDDIR}/pki/.travis/pki.cfg -s CA
+pkispawn -vv -f ${BUILDDIR}/pki/.travis/pki.cfg -s CA
 
 echo "Waiting for port 8080"
 for i in {1..20}; do
diff --git a/.travis/50-spawn-kra b/.travis/50-spawn-kra
index 80cb039..93f2f4c 100755
--- a/.travis/50-spawn-kra
+++ b/.travis/50-spawn-kra
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -e
 
-pkispawn -v -f ${BUILDDIR}/pki/.travis/pki.cfg -s KRA
+pkispawn -vv -f ${BUILDDIR}/pki/.travis/pki.cfg -s KRA
 
 echo "Waiting for port 8080"
 for i in {1..20}; do
diff --git a/.travis/99-destroy b/.travis/99-destroy
new file mode 100755
index 0000000..d2fb1ad
--- /dev/null
+++ b/.travis/99-destroy
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+
+if [ -d /etc/pki/pkitest/kra ]; then
+    pkidestroy -v -i pkitest -s KRA
+fi
+
+pkidestroy -v -i pkitest -s CA
+
+remove-ds.pl -f -i slapd-pkitest
+
diff --git a/.travis/py3rewrite b/.travis/py3rewrite
new file mode 100755
index 0000000..f8a208d
--- /dev/null
+++ b/.travis/py3rewrite
@@ -0,0 +1,46 @@
+#!/usr/bin/python3
+import os
+import shutil
+
+from distutils.sysconfig import get_python_lib
+
+
+BUILDDIR = os.environ['BUILDDIR']
+PKIBASE = os.path.join(BUILDDIR, 'pki', 'base')
+PKICLIENT = os.path.join(PKIBASE, 'common', 'python', 'pki')
+PKISERVER = os.path.join(PKIBASE, 'server', 'python', 'pki', 'server')
+PKISBIN = os.path.join(PKIBASE, 'server', 'sbin')
+
+SITEPACKAGES = get_python_lib()
+
+
+def copyscript(src, dst):
+    with open(src) as f:
+        lines = f.readlines()
+    lines[0] = '#!/usr/bin/python3\n'
+    with open(dst, 'w') as f:
+        os.fchmod(f.fileno(), 0o755)
+        f.writelines(lines)
+
+
+def copyfiles():
+    shutil.rmtree(os.path.join(SITEPACKAGES, 'pki'))
+    shutil.copytree(
+        PKICLIENT,
+        os.path.join(SITEPACKAGES, 'pki')
+    )
+    shutil.copytree(
+        PKISERVER,
+        os.path.join(SITEPACKAGES, 'pki', 'server')
+    )
+    copyscript(
+        os.path.join(PKISBIN, 'pkispawn'),
+        '/usr/sbin/pkispawn'
+    )
+    copyscript(
+        os.path.join(PKISBIN, 'pkidestroy'),
+        '/usr/sbin/pkidestroy'
+    )
+
+if __name__ == '__main__':
+    copyfiles()
diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py
index 8898654..46c6711 100644
--- a/base/server/python/pki/server/__init__.py
+++ b/base/server/python/pki/server/__init__.py
@@ -296,9 +296,9 @@ class PKISubsystem(object):
 
     def save(self):
         sorted_config = sorted(self.config.items(), key=operator.itemgetter(0))
-        with io.open(self.cs_conf, 'wb') as f:
+        with io.open(self.cs_conf, 'w') as f:
             for (key, value) in sorted_config:
-                f.write('%s=%s\n' % (key, value))
+                f.write(u'%s=%s\n' % (key, value))
 
     def is_valid(self):
         return os.path.exists(self.conf_dir)
-- 
1.8.3.1


From ce3304834dbb3e4d001ecbbfc1af61044ae7a74c Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 09:52:32 +0200
Subject: [PATCH 24/49] Added AuthSuccessEvent.

A new AuthSuccessEvent class of has been added to encapsulate the
AUTH_SUCCESS events.

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

Change-Id: Ie7cc751728ac079e30ece354ca44c5266474bcd3
---
 .../certsrv/logging/event/AuthSuccessEvent.java    | 39 ++++++++++++++++++++++
 .../cms/src/com/netscape/cms/realm/PKIRealm.java   | 16 ++++-----
 .../netscape/cms/servlet/admin/AdminServlet.java   | 21 +++++-------
 .../com/netscape/cms/servlet/base/CMSServlet.java  |  9 ++---
 .../cms/servlet/processors/CAProcessor.java        | 17 +++-------
 5 files changed, 61 insertions(+), 41 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/AuthSuccessEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/AuthSuccessEvent.java b/base/common/src/com/netscape/certsrv/logging/event/AuthSuccessEvent.java
new file mode 100644
index 0000000..5d4f973
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/AuthSuccessEvent.java
@@ -0,0 +1,39 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class AuthSuccessEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public AuthSuccessEvent(
+            String subjectID,
+            String outcome,
+            String authManagerID) {
+
+        super(AUTH_SUCCESS);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                authManagerID
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
index bcd3ff8..81de9fb 100644
--- a/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
+++ b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
@@ -18,6 +18,7 @@ import com.netscape.certsrv.authentication.IPasswdUserDBAuthentication;
 import com.netscape.certsrv.base.SessionContext;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IGroup;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -60,14 +61,11 @@ public class PKIRealm extends RealmBase {
             authToken.set(SessionContext.AUTH_MANAGER_ID, IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID);
             auditSubjectID = authToken.getInString(IAuthToken.USER_ID);
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_SUCCESS,
+            audit(new AuthSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
-                        IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID);
+                        IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID));
 
-            audit(auditMessage);
             return getPrincipal(username, authToken);
 
         } catch (Throwable e) {
@@ -120,14 +118,12 @@ public class PKIRealm extends RealmBase {
             auditSubjectID = authToken.getInString(IAuthToken.USER_ID);
 
             CMS.debug("PKIRealm: User ID: " + username);
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_SUCCESS,
+
+            audit(new AuthSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
-                        IAuthSubsystem.CERTUSERDB_AUTHMGR_ID);
+                        IAuthSubsystem.CERTUSERDB_AUTHMGR_ID));
 
-            audit(auditMessage);
             return getPrincipal(username, authToken);
 
         } catch (Throwable e) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index 16a2e39..d530f6a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -35,8 +35,6 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.security.x509.X509CertImpl;
-
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthCredentials;
 import com.netscape.certsrv.authentication.IAuthManager;
@@ -54,12 +52,15 @@ import com.netscape.certsrv.common.NameValuePairs;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
 import com.netscape.certsrv.usrgrp.IUser;
 import com.netscape.cms.servlet.base.UserInfo;
 import com.netscape.cmsutil.util.Utils;
 
+import netscape.security.x509.X509CertImpl;
+
 /**
  * A class represents an administration servlet that
  * is responsible to serve administrative
@@ -524,23 +525,17 @@ public class AdminServlet extends HttpServlet {
             sc.put(SessionContext.LOCALE, locale);
 
             if (authType.equals("sslclientauth")) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTH_SUCCESS,
+
+                audit(new AuthSuccessEvent(
                             auditSubjectID(),
                             ILogger.SUCCESS,
-                            CERTUSERDB);
+                            CERTUSERDB));
 
-                audit(auditMessage);
             } else {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTH_SUCCESS,
+                audit(new AuthSuccessEvent(
                             auditSubjectID(),
                             ILogger.SUCCESS,
-                            PASSWDUSERDB);
-
-                audit(auditMessage);
+                            PASSWDUSERDB));
             }
         } catch (IOException eAudit1) {
             if (authType.equals("sslclientauth")) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
index a007a00..9168870 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -66,6 +66,7 @@ import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.ra.IRegistrationAuthority;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestQueue;
@@ -1789,14 +1790,10 @@ public abstract class CMSServlet extends HttpServlet {
             // reset the "auditSubjectID"
             auditSubjectID = auditSubjectID();
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_SUCCESS,
+            audit(new AuthSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
-                        auditAuthMgrID);
-
-            audit(auditMessage);
+                        auditAuthMgrID));
 
             return authToken;
         } catch (EBaseException eAudit1) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index a98d555..93d6a9a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -53,6 +53,7 @@ import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileSubsystem;
@@ -520,14 +521,10 @@ public class CAProcessor extends Processor {
 
             authSubjectID = authSubjectID + " : " + uid_cred;
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTH_SUCCESS,
+            audit(new AuthSuccessEvent(
                     authSubjectID,
                     ILogger.SUCCESS,
-                    authMgrID);
-
-            audit(auditMessage);
+                    authMgrID));
         }
         endTiming("profile_authentication");
         return authToken;
@@ -655,14 +652,10 @@ public class CAProcessor extends Processor {
             // reset the "auditSubjectID"
             auditSubjectID = auditSubjectID();
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTH_SUCCESS,
+            audit(new AuthSuccessEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
-                    auditAuthMgrID);
-
-            audit(auditMessage);
+                    auditAuthMgrID));
 
             return authToken;
         } catch (EBaseException eAudit1) {
-- 
1.8.3.1


From 0de8be3084c4ccf23c2850331f86fc067e7c8383 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 10:07:44 +0200
Subject: [PATCH 25/49] Added AuthFailEvent.

A new AuthFailEvent class of has been added to encapsulate the
AUTH_FAIL events.

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

Change-Id: I870398f6a56df007c9520e50947a7b3c85baf79b
---
 .../certsrv/logging/event/AuthFailEvent.java       | 41 +++++++++
 .../cms/src/com/netscape/cms/realm/PKIRealm.java   | 22 +++--
 .../netscape/cms/servlet/admin/AdminServlet.java   | 96 ++++++++--------------
 .../com/netscape/cms/servlet/base/CMSServlet.java  | 11 ++-
 .../cms/servlet/processors/CAProcessor.java        | 27 +++---
 5 files changed, 102 insertions(+), 95 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/AuthFailEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/AuthFailEvent.java b/base/common/src/com/netscape/certsrv/logging/event/AuthFailEvent.java
new file mode 100644
index 0000000..a2c7d8d
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/AuthFailEvent.java
@@ -0,0 +1,41 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class AuthFailEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public AuthFailEvent(
+            String subjectID,
+            String outcome,
+            String authManagerID,
+            String attemptedUID) {
+
+        super(AUTH_FAIL);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                authManagerID,
+                attemptedUID
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
index 81de9fb..8306193 100644
--- a/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
+++ b/base/server/cms/src/com/netscape/cms/realm/PKIRealm.java
@@ -18,6 +18,7 @@ import com.netscape.certsrv.authentication.IPasswdUserDBAuthentication;
 import com.netscape.certsrv.base.SessionContext;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IGroup;
@@ -45,7 +46,7 @@ public class PKIRealm extends RealmBase {
     @Override
     public Principal authenticate(String username, String password) {
         CMS.debug("PKIRealm: Authenticating user " + username + " with password.");
-        String auditMessage = null;
+
         String auditSubjectID = ILogger.UNIDENTIFIED;
         String attemptedAuditUID = username;
 
@@ -69,14 +70,13 @@ public class PKIRealm extends RealmBase {
             return getPrincipal(username, authToken);
 
         } catch (Throwable e) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_FAIL,
+
+            audit(new AuthFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID,
-                        attemptedAuditUID);
-            audit(auditMessage);
+                        attemptedAuditUID));
+
             e.printStackTrace();
         }
 
@@ -87,7 +87,6 @@ public class PKIRealm extends RealmBase {
     public Principal authenticate(final X509Certificate certs[]) {
         CMS.debug("PKIRealm: Authenticating certificate chain:");
 
-        String auditMessage = null;
         // get the cert from the ssl client auth
         // in cert based auth, subject id from cert has already passed SSL authentication
         // what remains is to see if the user exists in the internal user db
@@ -127,14 +126,13 @@ public class PKIRealm extends RealmBase {
             return getPrincipal(username, authToken);
 
         } catch (Throwable e) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_FAIL,
+
+            audit(new AuthFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         IAuthSubsystem.CERTUSERDB_AUTHMGR_ID,
-                        attemptedAuditUID);
-            audit(auditMessage);
+                        attemptedAuditUID));
+
             e.printStackTrace();
         }
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index d530f6a..a715c73 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -52,6 +52,7 @@ import com.netscape.certsrv.common.NameValuePairs;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -274,7 +275,6 @@ public class AdminServlet extends HttpServlet {
     protected void authenticate(HttpServletRequest req) throws
             IOException {
 
-        String auditMessage = null;
         String auditUID = ILogger.UNIDENTIFIED;
         String authType = "";
 
@@ -297,15 +297,12 @@ public class AdminServlet extends HttpServlet {
                         (X509Certificate[]) req.getAttribute(CERT_ATTR);
 
                 if (allCerts == null || allCerts.length == 0) {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.AUTH_FAIL,
+
+                    audit(new AuthFailEvent(
                                 ILogger.UNIDENTIFIED,
                                 ILogger.FAILURE,
                                 CERTUSERDB,
-                                auditUID);
-
-                    audit(auditMessage);
+                                auditUID));
 
                     throw new IOException("No certificate");
                 }
@@ -389,25 +386,20 @@ public class AdminServlet extends HttpServlet {
                  */
 
                 if (authType.equals("sslclientauth")) {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.AUTH_FAIL,
+
+                    audit(new AuthFailEvent(
                                 ILogger.UNIDENTIFIED,
                                 ILogger.FAILURE,
                                 CERTUSERDB,
-                                auditUID);
+                                auditUID));
 
-                    audit(auditMessage);
                 } else {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.AUTH_FAIL,
+
+                    audit(new AuthFailEvent(
                                 ILogger.UNIDENTIFIED,
                                 ILogger.FAILURE,
                                 PASSWDUSERDB,
-                                auditUID);
-
-                    audit(auditMessage);
+                                auditUID));
                 }
 
                 throw new IOException("authentication failed");
@@ -423,25 +415,20 @@ public class AdminServlet extends HttpServlet {
                                     tuserid));
 
                     if (authType.equals("sslclientauth")) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.AUTH_FAIL,
+
+                        audit(new AuthFailEvent(
                                     ILogger.UNIDENTIFIED,
                                     ILogger.FAILURE,
                                     CERTUSERDB,
-                                    auditUID);
+                                    auditUID));
 
-                        audit(auditMessage);
                     } else {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.AUTH_FAIL,
+
+                        audit(new AuthFailEvent(
                                     ILogger.UNIDENTIFIED,
                                     ILogger.FAILURE,
                                     PASSWDUSERDB,
-                                    auditUID);
-
-                        audit(auditMessage);
+                                    auditUID));
                     }
 
                     throw new IOException("authentication failed");
@@ -459,25 +446,20 @@ public class AdminServlet extends HttpServlet {
                                     tuserid));
 
                     if (authType.equals("sslclientauth")) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.AUTH_FAIL,
+
+                        audit(new AuthFailEvent(
                                     ILogger.UNIDENTIFIED,
                                     ILogger.FAILURE,
                                     CERTUSERDB,
-                                    auditUID);
+                                    auditUID));
 
-                        audit(auditMessage);
                     } else {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.AUTH_FAIL,
+
+                        audit(new AuthFailEvent(
                                     ILogger.UNIDENTIFIED,
                                     ILogger.FAILURE,
                                     PASSWDUSERDB,
-                                    auditUID);
-
-                        audit(auditMessage);
+                                    auditUID));
                     }
 
                     throw new IOException("authentication failed");
@@ -495,25 +477,20 @@ public class AdminServlet extends HttpServlet {
                         CMS.getLogMessage("ADMIN_SRVLT_USR_GRP_ERR", e.toString()));
 
                 if (authType.equals("sslclientauth")) {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.AUTH_FAIL,
+
+                    audit(new AuthFailEvent(
                                 ILogger.UNIDENTIFIED,
                                 ILogger.FAILURE,
                                 CERTUSERDB,
-                                auditUID);
+                                auditUID));
 
-                    audit(auditMessage);
                 } else {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.AUTH_FAIL,
+
+                    audit(new AuthFailEvent(
                                 ILogger.UNIDENTIFIED,
                                 ILogger.FAILURE,
                                 PASSWDUSERDB,
-                                auditUID);
-
-                    audit(auditMessage);
+                                auditUID));
                 }
 
                 throw new IOException("authentication failed");
@@ -539,25 +516,20 @@ public class AdminServlet extends HttpServlet {
             }
         } catch (IOException eAudit1) {
             if (authType.equals("sslclientauth")) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTH_FAIL,
+
+                audit(new AuthFailEvent(
                             ILogger.UNIDENTIFIED,
                             ILogger.FAILURE,
                             CERTUSERDB,
-                            auditUID);
+                            auditUID));
 
-                audit(auditMessage);
             } else {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTH_FAIL,
+
+                audit(new AuthFailEvent(
                             ILogger.UNIDENTIFIED,
                             ILogger.FAILURE,
                             PASSWDUSERDB,
-                            auditUID);
-
-                audit(auditMessage);
+                            auditUID));
             }
 
             // rethrow the specific exception to be handled later
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
index 9168870..c23b9d1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -66,6 +66,7 @@ import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.kra.IKeyRecoveryAuthority;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.ra.IRegistrationAuthority;
 import com.netscape.certsrv.request.IRequest;
@@ -1701,7 +1702,7 @@ public abstract class CMSServlet extends HttpServlet {
      */
     public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName)
             throws EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = ILogger.UNIDENTIFIED;
         String auditAuthMgrID = ILogger.UNIDENTIFIED;
         String auditUID = ILogger.UNIDENTIFIED;
@@ -1797,14 +1798,12 @@ public abstract class CMSServlet extends HttpServlet {
 
             return authToken;
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_FAIL,
+
+            audit(new AuthFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditAuthMgrID,
-                        auditUID);
-            audit(auditMessage);
+                        auditUID));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 93d6a9a..a28bee1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -53,6 +53,7 @@ import com.netscape.certsrv.dbs.certdb.ICertRecord;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
@@ -474,7 +475,7 @@ public class CAProcessor extends Processor {
 
             String authSubjectID = auditSubjectID();
             String authMgrID = authenticator.getName();
-            String auditMessage = null;
+
             try {
                 if (isRenewal) {
                     authToken = authenticate(authenticator, request, origReq, context, credentials);
@@ -486,13 +487,12 @@ public class CAProcessor extends Processor {
                 CMS.debug("CAProcessor: authentication error: " + e);
 
                 authSubjectID += " : " + uid_cred;
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_FAIL,
+
+                audit(new AuthFailEvent(
                         authSubjectID,
                         ILogger.FAILURE,
                         authMgrID,
-                        uid_attempted_cred);
-                audit(auditMessage);
+                        uid_attempted_cred));
 
                 throw e;
 
@@ -500,13 +500,12 @@ public class CAProcessor extends Processor {
                 CMS.debug(e);
 
                 authSubjectID += " : " + uid_cred;
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTH_FAIL,
+
+                audit(new AuthFailEvent(
                         authSubjectID,
                         ILogger.FAILURE,
                         authMgrID,
-                        uid_attempted_cred);
-                audit(auditMessage);
+                        uid_attempted_cred));
 
                 throw e;
             }
@@ -565,7 +564,7 @@ public class CAProcessor extends Processor {
 
     public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName)
             throws EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = ILogger.UNIDENTIFIED;
         String auditAuthMgrID = ILogger.UNIDENTIFIED;
         String auditUID = ILogger.UNIDENTIFIED;
@@ -659,14 +658,12 @@ public class CAProcessor extends Processor {
 
             return authToken;
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTH_FAIL,
+
+            audit(new AuthFailEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
                     auditAuthMgrID,
-                    auditUID);
-            audit(auditMessage);
+                    auditUID));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
-- 
1.8.3.1


From fdcb514b0711f10eab47c81837138192207e44b4 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 16:30:18 +0200
Subject: [PATCH 26/49] Added AuthzSuccessEvent.

A new AuthzSuccessEvent class of has been added to encapsulate the
AUTHZ_SUCCESS events.

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

Change-Id: I2f45fb2c3ba8acdc82777644cf4ad0ec2eff35a5
---
 .../certsrv/logging/event/AuthzSuccessEvent.java   | 59 ++++++++++++++++++++++
 .../netscape/cms/servlet/admin/AdminServlet.java   |  9 ++--
 .../com/netscape/cms/servlet/base/CMSServlet.java  | 18 +++----
 .../cms/servlet/processors/CAProcessor.java        | 18 +++----
 .../org/dogtagpki/server/rest/ACLInterceptor.java  | 27 +++++-----
 5 files changed, 89 insertions(+), 42 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/AuthzSuccessEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/AuthzSuccessEvent.java b/base/common/src/com/netscape/certsrv/logging/event/AuthzSuccessEvent.java
new file mode 100644
index 0000000..05e505c
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/AuthzSuccessEvent.java
@@ -0,0 +1,59 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class AuthzSuccessEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public AuthzSuccessEvent(
+            String subjectID,
+            String outcome,
+            String aclResource,
+            String operation) {
+
+        super(AUTHZ_SUCCESS);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                aclResource,
+                operation
+        });
+    }
+
+    public AuthzSuccessEvent(
+            String subjectID,
+            String outcome,
+            String aclResource,
+            String operation,
+            String info) {
+
+        super(AUTHZ_SUCCESS_INFO);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                aclResource,
+                operation,
+                info
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index a715c73..adf9424 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -54,6 +54,7 @@ import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
 import com.netscape.certsrv.usrgrp.IUser;
@@ -676,15 +677,11 @@ public class AdminServlet extends HttpServlet {
             return null;
         }
 
-        // store a message in the signed audit log file
-        auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_SUCCESS,
+        audit(new AuthzSuccessEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
                     auditACLResource,
-                    auditOperation);
-
-        audit(auditMessage);
+                    auditOperation));
 
         // store a message in the signed audit log file
         auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
index c23b9d1..c70f55a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -68,6 +68,7 @@ import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.ra.IRegistrationAuthority;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestQueue;
@@ -1822,14 +1823,12 @@ public abstract class CMSServlet extends HttpServlet {
         try {
             authzToken = mAuthz.authorize(authzMgrName, authToken, exp);
             if (authzToken != null) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTHZ_SUCCESS,
+
+                audit(new AuthzSuccessEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
                             auditACLResource,
-                            auditOperation);
-
-                audit(auditMessage);
+                            auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
@@ -1955,15 +1954,12 @@ public abstract class CMSServlet extends HttpServlet {
                     operation);
 
             if (authzTok != null) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTHZ_SUCCESS,
+
+                audit(new AuthzSuccessEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
                             auditACLResource,
-                            auditOperation);
-
-                audit(auditMessage);
+                            auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index a28bee1..8760caf 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -55,6 +55,7 @@ import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileSubsystem;
@@ -707,14 +708,12 @@ public class CAProcessor extends Processor {
         try {
             authzToken = authz.authorize(authzMgrName, authToken, exp);
             if (authzToken != null) {
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_SUCCESS,
+
+                audit(new AuthzSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
                         auditACLResource,
-                        auditOperation);
-
-                audit(auditMessage);
+                        auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
@@ -839,15 +838,12 @@ public class CAProcessor extends Processor {
                     operation);
 
             if (authzTok != null) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_SUCCESS,
+
+                audit(new AuthzSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
                         auditACLResource,
-                        auditOperation);
-
-                audit(auditMessage);
+                        auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java b/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
index 331bae1..490eaed 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
@@ -47,6 +47,7 @@ import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.cms.realm.PKIPrincipal;
 
 /**
@@ -189,15 +190,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
         // If still not available, it's unprotected, allow request.
         if (!authzRequired) {
             CMS.debug("ACLInterceptor: No ACL mapping; authz not required.");
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_SUCCESS_INFO,
+
+            audit(new AuthzSuccessEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
                         null, //resource
                         null, //operation
-                        LOGGING_MISSING_ACL_MAPPING + ":" + auditInfo); //info
-            audit(auditMessage);
+                        LOGGING_MISSING_ACL_MAPPING + ":" + auditInfo)); //info
+
             return;
         }
 
@@ -230,14 +230,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
         // If no property defined, allow request.
         if (value == null) {
             CMS.debug("ACLInterceptor: No ACL configuration.");
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_SUCCESS_INFO,
+
+            audit(new AuthzSuccessEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
                     null, //resource
                     null, //operation
-                    LOGGING_NO_ACL_ACCESS_ALLOWED + ":" + auditInfo);
+                    LOGGING_NO_ACL_ACCESS_ALLOWED + ":" + auditInfo));
+
             return;
         }
 
@@ -317,15 +317,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
         }
 
         // Allow request.
-        // store a message in the signed audit log file
-        auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_SUCCESS_INFO,
+
+        audit(new AuthzSuccessEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
                     values[0], // resource
                     values[1], // operation
-                    auditInfo);
-        audit(auditMessage);
+                    auditInfo));
+
         return;
     }
 
-- 
1.8.3.1


From 30d1575046065dbd79f537e5f819c405e45af0bc Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 16:49:28 +0200
Subject: [PATCH 27/49] Added AuthzFailEvent.

A new AuthzFailEvent class of has been added to encapsulate the
AUTHZ_FAIL events.

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

Change-Id: Id4ab9bd889a1a9314264c0ef2ff7b2389aed8f9c
---
 .../certsrv/logging/event/AuthzFailEvent.java      | 59 ++++++++++++++++++++++
 .../netscape/cms/servlet/admin/AdminServlet.java   | 26 +++-------
 .../com/netscape/cms/servlet/base/CMSServlet.java  | 44 ++++++----------
 .../cms/servlet/processors/CAProcessor.java        | 35 +++++--------
 .../org/dogtagpki/server/rest/ACLInterceptor.java  | 52 ++++++++-----------
 5 files changed, 118 insertions(+), 98 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/AuthzFailEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/AuthzFailEvent.java b/base/common/src/com/netscape/certsrv/logging/event/AuthzFailEvent.java
new file mode 100644
index 0000000..1e44919
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/AuthzFailEvent.java
@@ -0,0 +1,59 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class AuthzFailEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public AuthzFailEvent(
+            String subjectID,
+            String outcome,
+            String aclResource,
+            String operation) {
+
+        super(AUTHZ_FAIL);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                aclResource,
+                operation
+        });
+    }
+
+    public AuthzFailEvent(
+            String subjectID,
+            String outcome,
+            String aclResource,
+            String operation,
+            String info) {
+
+        super(AUTHZ_FAIL_INFO);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                aclResource,
+                operation,
+                info
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index adf9424..ecc6a7d 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -54,6 +54,7 @@ import com.netscape.certsrv.logging.IAuditor;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -611,15 +612,11 @@ public class AdminServlet extends HttpServlet {
         } catch (EAuthzAccessDenied e) {
             log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
@@ -634,15 +631,11 @@ public class AdminServlet extends HttpServlet {
         } catch (EBaseException e) {
             log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString()));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
@@ -655,15 +648,12 @@ public class AdminServlet extends HttpServlet {
 
             return null;
         } catch (Exception e) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
index c70f55a..afb109a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -68,6 +68,7 @@ import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.ra.IRegistrationAuthority;
 import com.netscape.certsrv.request.IRequest;
@@ -1839,14 +1840,12 @@ public abstract class CMSServlet extends HttpServlet {
 
                 audit(auditMessage);
             } else {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTHZ_FAIL,
+
+                audit(new AuthzFailEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
                             auditACLResource,
-                            auditOperation);
-
-                audit(auditMessage);
+                            auditOperation));
 
                 auditMessage = CMS.getLogMessage(
                             AuditEvent.ROLE_ASSUME,
@@ -1858,14 +1857,12 @@ public abstract class CMSServlet extends HttpServlet {
             }
             return authzToken;
         } catch (Exception e) {
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             auditMessage = CMS.getLogMessage(
                         AuditEvent.ROLE_ASSUME,
@@ -1970,15 +1967,12 @@ public abstract class CMSServlet extends HttpServlet {
 
                 audit(auditMessage);
             } else {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTHZ_FAIL,
+
+                audit(new AuthzFailEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
                             auditACLResource,
-                            auditOperation);
-
-                audit(auditMessage);
+                            auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
@@ -1992,15 +1986,12 @@ public abstract class CMSServlet extends HttpServlet {
 
             return authzTok;
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
@@ -2013,15 +2004,12 @@ public abstract class CMSServlet extends HttpServlet {
 
             return null;
         } catch (Exception eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-            audit(auditMessage);
+                        auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 8760caf..1d04f3a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -55,6 +55,7 @@ import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
+import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
@@ -724,14 +725,12 @@ public class CAProcessor extends Processor {
 
                 audit(auditMessage);
             } else {
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+                audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-                audit(auditMessage);
+                        auditOperation));
 
                 auditMessage = CMS.getLogMessage(
                         AuditEvent.ROLE_ASSUME,
@@ -743,14 +742,12 @@ public class CAProcessor extends Processor {
             }
             return authzToken;
         } catch (EBaseException e) {
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
                     auditACLResource,
-                    auditOperation);
-
-            audit(auditMessage);
+                    auditOperation));
 
             auditMessage = CMS.getLogMessage(
                     AuditEvent.ROLE_ASSUME,
@@ -854,15 +851,12 @@ public class CAProcessor extends Processor {
 
                 audit(auditMessage);
             } else {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL,
+
+                audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditACLResource,
-                        auditOperation);
-
-                audit(auditMessage);
+                        auditOperation));
 
                 // store a message in the signed audit log file
                 auditMessage = CMS.getLogMessage(
@@ -876,15 +870,12 @@ public class CAProcessor extends Processor {
 
             return authzTok;
         } catch (Exception eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_FAIL,
+
+            audit(new AuthzFailEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
                     auditACLResource,
-                    auditOperation);
-
-            audit(auditMessage);
+                    auditOperation));
 
             // store a message in the signed audit log file
             auditMessage = CMS.getLogMessage(
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java b/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
index 490eaed..b4f75f1 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/ACLInterceptor.java
@@ -47,6 +47,7 @@ import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.ForbiddenException;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
 import com.netscape.cms.realm.PKIPrincipal;
 
@@ -108,7 +109,6 @@ public class ACLInterceptor implements ContainerRequestFilter {
         String auditInfo =  clazz.getSimpleName() + "." + method.getName();
 
         CMS.debug("ACLInterceptor: " + auditInfo + "()");
-        String auditMessage = null;
         String auditSubjectID = ILogger.UNIDENTIFIED;
 
         /*
@@ -174,14 +174,13 @@ public class ACLInterceptor implements ContainerRequestFilter {
             CMS.debug("ACLInterceptor: No authentication token present.");
             // store a message in the signed audit log file
             // although if it didn't pass authentication, it should not have gotten here
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL_INFO,
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         null, // resource
                         null, // operation
-                        LOGGING_MISSING_AUTH_TOKEN + ":" + auditInfo);
-            audit(auditMessage);
+                        LOGGING_MISSING_AUTH_TOKEN + ":" + auditInfo));
+
             throw new ForbiddenException("No authorization token present.");
         }
         if (authToken != null)
@@ -213,16 +212,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
             value = properties.getProperty(name);
 
         } catch (IOException e) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL_INFO,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         null, //resource
                         null, //operation
-                        LOGGING_ACL_PARSING_ERROR + ":" + auditInfo);
+                        LOGGING_ACL_PARSING_ERROR + ":" + auditInfo));
 
-            audit(auditMessage);
             e.printStackTrace();
             throw new Failure(e);
         }
@@ -246,16 +243,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
         // If invalid mapping, reject request.
         if (values.length != 2) {
             CMS.debug("ACLInterceptor: Invalid ACL mapping.");
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.AUTHZ_FAIL_INFO,
+
+            audit(new AuthzFailEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
                     null, //resource
                     null, //operation
-                    LOGGING_INVALID_ACL_MAPPING + ":" + auditInfo);
+                    LOGGING_INVALID_ACL_MAPPING + ":" + auditInfo));
 
-            audit(auditMessage);
             throw new ForbiddenException("Invalid ACL mapping.");
         }
 
@@ -273,15 +268,14 @@ public class ACLInterceptor implements ContainerRequestFilter {
             if (authzToken == null) {
                 String info = "No authorization token present.";
                 CMS.debug("ACLInterceptor: " + info);
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.AUTHZ_FAIL_INFO,
+
+                audit(new AuthzFailEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
                             values[0], // resource
                             values[1], // operation
-                            info);
-                audit(auditMessage);
+                            info));
+
                 throw new ForbiddenException("No authorization token present.");
             }
 
@@ -290,28 +284,26 @@ public class ACLInterceptor implements ContainerRequestFilter {
         } catch (EAuthzAccessDenied e) {
             String info = e.getMessage();
             CMS.debug("ACLInterceptor: " + info);
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL_INFO,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         values[0], // resource
                         values[1], // operation
-                        info);
-            audit(auditMessage);
+                        info));
+
             throw new ForbiddenException(e.toString());
 
         } catch (EBaseException e) {
             String info = e.getMessage();
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.AUTHZ_FAIL_INFO,
+
+            audit(new AuthzFailEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         values[0], // resource
                         values[1], // operation
-                        info);
-            audit(auditMessage);
+                        info));
+
             e.printStackTrace();
             throw new Failure(e);
         }
-- 
1.8.3.1


From aad80e8775eac61ed9eac2f3f94d2ec90207e827 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Apr 2017 10:20:06 +0200
Subject: [PATCH 28/49] Added RoleAssumeEvent.

A new RoleAssumeEvent class of has been added to encapsulate the
ROLE_ASSUME events.

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

Change-Id: I12e47ea13198b6532b1fdfee2e20765c0cab15e9
---
 .../certsrv/logging/event/RoleAssumeEvent.java     | 39 +++++++++++++++
 .../netscape/cms/servlet/admin/AdminServlet.java   | 35 ++++----------
 .../com/netscape/cms/servlet/base/CMSServlet.java  | 56 +++++++---------------
 .../servlet/csadmin/SecurityDomainProcessor.java   | 15 +++---
 .../cms/servlet/processors/CAProcessor.java        | 48 ++++++-------------
 5 files changed, 88 insertions(+), 105 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/RoleAssumeEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/RoleAssumeEvent.java b/base/common/src/com/netscape/certsrv/logging/event/RoleAssumeEvent.java
new file mode 100644
index 0000000..2715893
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/RoleAssumeEvent.java
@@ -0,0 +1,39 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class RoleAssumeEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public RoleAssumeEvent(
+            String subjectID,
+            String outcome,
+            String groups) {
+
+        super(ROLE_ASSUME);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                groups
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
index ecc6a7d..662a3e9 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/AdminServlet.java
@@ -56,6 +56,7 @@ import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
+import com.netscape.certsrv.logging.event.RoleAssumeEvent;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
 import com.netscape.certsrv.usrgrp.IUser;
@@ -573,7 +574,7 @@ public class AdminServlet extends HttpServlet {
      * @return the authorization token
      */
     protected AuthzToken authorize(HttpServletRequest req) {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
         String auditACLResource = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         String auditOperation = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
@@ -618,14 +619,10 @@ public class AdminServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                        auditGroups(auditSubjectID)));
 
             return null;
         } catch (EBaseException e) {
@@ -637,14 +634,10 @@ public class AdminServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                        auditGroups(auditSubjectID)));
 
             return null;
         } catch (Exception e) {
@@ -655,14 +648,10 @@ public class AdminServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                        auditGroups(auditSubjectID)));
 
             return null;
         }
@@ -673,14 +662,10 @@ public class AdminServlet extends HttpServlet {
                     auditACLResource,
                     auditOperation));
 
-        // store a message in the signed audit log file
-        auditMessage = CMS.getLogMessage(
-                    AuditEvent.ROLE_ASSUME,
+        audit(new RoleAssumeEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
-                    auditGroups(auditSubjectID));
-
-        audit(auditMessage);
+                    auditGroups(auditSubjectID)));
 
         return authzTok;
     }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
index afb109a..9dc7470 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -70,6 +70,7 @@ import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
+import com.netscape.certsrv.logging.event.RoleAssumeEvent;
 import com.netscape.certsrv.ra.IRegistrationAuthority;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestQueue;
@@ -1815,7 +1816,7 @@ public abstract class CMSServlet extends HttpServlet {
     public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken,
             String exp) throws EBaseException {
         AuthzToken authzToken = null;
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
         String auditGroupID = auditGroupID();
         String auditACLResource = resource;
@@ -1831,14 +1832,11 @@ public abstract class CMSServlet extends HttpServlet {
                             auditACLResource,
                             auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditGroupID);
+                            auditGroupID));
 
-                audit(auditMessage);
             } else {
 
                 audit(new AuthzFailEvent(
@@ -1847,13 +1845,10 @@ public abstract class CMSServlet extends HttpServlet {
                             auditACLResource,
                             auditOperation));
 
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditGroupID);
-
-                audit(auditMessage);
+                            auditGroupID));
             }
             return authzToken;
         } catch (Exception e) {
@@ -1864,13 +1859,11 @@ public abstract class CMSServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroupID);
+                        auditGroupID));
 
-            audit(auditMessage);
             throw new EBaseException(e.toString());
         }
     }
@@ -1900,7 +1893,7 @@ public abstract class CMSServlet extends HttpServlet {
     public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
             String resource, String operation)
             throws EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
         String auditGroupID = auditGroupID();
         String auditID = auditSubjectID;
@@ -1958,14 +1951,11 @@ public abstract class CMSServlet extends HttpServlet {
                             auditACLResource,
                             auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                             auditID,
                             ILogger.SUCCESS,
-                            auditGroups(auditSubjectID));
+                            auditGroups(auditSubjectID)));
 
-                audit(auditMessage);
             } else {
 
                 audit(new AuthzFailEvent(
@@ -1974,14 +1964,10 @@ public abstract class CMSServlet extends HttpServlet {
                             auditACLResource,
                             auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                             auditID,
                             ILogger.FAILURE,
-                            auditGroups(auditSubjectID));
-
-                audit(auditMessage);
+                            auditGroups(auditSubjectID)));
             }
 
             return authzTok;
@@ -1993,14 +1979,10 @@ public abstract class CMSServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                        auditGroups(auditSubjectID)));
 
             return null;
         } catch (Exception eAudit1) {
@@ -2011,14 +1993,10 @@ public abstract class CMSServlet extends HttpServlet {
                         auditACLResource,
                         auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                        auditGroups(auditSubjectID)));
 
             return null;
         }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
index cd769db..dc28a7c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
@@ -45,6 +45,7 @@ import com.netscape.certsrv.base.UnauthorizedException;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.RoleAssumeEvent;
 import com.netscape.certsrv.system.DomainInfo;
 import com.netscape.certsrv.system.InstallToken;
 import com.netscape.certsrv.system.SecurityDomainHost;
@@ -89,22 +90,19 @@ public class SecurityDomainProcessor extends CAProcessor {
         CMS.debug("SecurityDomainProcessor: group: " + group);
 
         if (!ugSubsystem.isMemberOf(user, group)) {
-            String message = CMS.getLogMessage(
-                    AuditEvent.ROLE_ASSUME,
+
+            audit(new RoleAssumeEvent(
                     user,
                     ILogger.FAILURE,
-                    group);
-            audit(message);
+                    group));
 
             throw new UnauthorizedException("User " + user + " is not a member of " + group + " group.");
         }
 
-        String message = CMS.getLogMessage(
-                AuditEvent.ROLE_ASSUME,
+        audit(new RoleAssumeEvent(
                 user,
                 ILogger.SUCCESS,
-                group);
-        audit(message);
+                group));
 
         String ip = "";
         try {
@@ -123,6 +121,7 @@ public class SecurityDomainProcessor extends CAProcessor {
 
         ISecurityDomainSessionTable ctable = CMS.getSecurityDomainSessionTable();
         int status = ctable.addEntry(sessionID, ip, user, group);
+        String message;
 
         if (status == ISecurityDomainSessionTable.SUCCESS) {
             message = CMS.getLogMessage(
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 1d04f3a..74f501f 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -57,6 +57,7 @@ import com.netscape.certsrv.logging.event.AuthFailEvent;
 import com.netscape.certsrv.logging.event.AuthSuccessEvent;
 import com.netscape.certsrv.logging.event.AuthzFailEvent;
 import com.netscape.certsrv.logging.event.AuthzSuccessEvent;
+import com.netscape.certsrv.logging.event.RoleAssumeEvent;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileSubsystem;
@@ -700,7 +701,7 @@ public class CAProcessor extends Processor {
     public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken,
             String exp) throws EBaseException {
         AuthzToken authzToken = null;
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
         String auditGroupID = auditGroupID();
         String auditACLResource = resource;
@@ -716,14 +717,11 @@ public class CAProcessor extends Processor {
                         auditACLResource,
                         auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
-                        auditGroupID);
+                        auditGroupID));
 
-                audit(auditMessage);
             } else {
 
                 audit(new AuthzFailEvent(
@@ -732,13 +730,10 @@ public class CAProcessor extends Processor {
                         auditACLResource,
                         auditOperation));
 
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditGroupID);
-
-                audit(auditMessage);
+                        auditGroupID));
             }
             return authzToken;
         } catch (EBaseException e) {
@@ -749,13 +744,11 @@ public class CAProcessor extends Processor {
                     auditACLResource,
                     auditOperation));
 
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
-                    auditGroupID);
+                    auditGroupID));
 
-            audit(auditMessage);
             throw e;
         }
     }
@@ -784,7 +777,7 @@ public class CAProcessor extends Processor {
      */
     public AuthzToken authorize(String authzMgrName, IAuthToken authToken,
             String resource, String operation) {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
         String auditGroupID = auditGroupID();
         String auditID = auditSubjectID;
@@ -842,14 +835,11 @@ public class CAProcessor extends Processor {
                         auditACLResource,
                         auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                         auditID,
                         ILogger.SUCCESS,
-                        auditGroups(auditSubjectID));
+                        auditGroups(auditSubjectID)));
 
-                audit(auditMessage);
             } else {
 
                 audit(new AuthzFailEvent(
@@ -858,14 +848,10 @@ public class CAProcessor extends Processor {
                         auditACLResource,
                         auditOperation));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.ROLE_ASSUME,
+                audit(new RoleAssumeEvent(
                         auditID,
                         ILogger.FAILURE,
-                        auditGroups(auditSubjectID));
-
-                audit(auditMessage);
+                        auditGroups(auditSubjectID)));
             }
 
             return authzTok;
@@ -877,14 +863,10 @@ public class CAProcessor extends Processor {
                     auditACLResource,
                     auditOperation));
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.ROLE_ASSUME,
+            audit(new RoleAssumeEvent(
                     auditID,
                     ILogger.FAILURE,
-                    auditGroups(auditSubjectID));
-
-            audit(auditMessage);
+                    auditGroups(auditSubjectID)));
 
             return null;
         }
-- 
1.8.3.1


From 3d9ef95a913af023958b79ef383853cf958757e0 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 21 Apr 2017 04:55:00 +0200
Subject: [PATCH 29/49] Added ConfigRoleEvent.

A new ConfigRoleEvent class of has been added to encapsulate the
CONFIG_ROLE events.

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

Change-Id: Ie0932131d75897f58afdd8217454c6cf6970d738
---
 .../certsrv/logging/event/ConfigRoleEvent.java     |  39 ++
 .../cms/profile/updater/SubsystemGroupUpdater.java |  37 +-
 .../cms/servlet/admin/GroupMemberProcessor.java    |  10 +-
 .../cms/servlet/admin/UsrGrpAdminServlet.java      | 500 ++++++---------------
 .../netscape/cms/servlet/csadmin/RegisterUser.java |  40 +-
 .../cms/servlet/csadmin/UpdateDomainXML.java       |  44 +-
 .../netscape/cms/servlet/processors/Processor.java |  13 -
 .../org/dogtagpki/server/rest/GroupService.java    |  10 +-
 .../src/org/dogtagpki/server/rest/UserService.java |  18 +-
 9 files changed, 264 insertions(+), 447 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ConfigRoleEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/ConfigRoleEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ConfigRoleEvent.java
new file mode 100644
index 0000000..695712b
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/ConfigRoleEvent.java
@@ -0,0 +1,39 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class ConfigRoleEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public ConfigRoleEvent(
+            String subjectID,
+            String outcome,
+            String params) {
+
+        super(CONFIG_ROLE);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                params
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
index 4ecc255..276c5b5 100644
--- a/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
+++ b/base/server/cms/src/com/netscape/cms/profile/updater/SubsystemGroupUpdater.java
@@ -28,6 +28,7 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.SessionContext;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
@@ -102,7 +103,6 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
     public void update(IRequest req, RequestStatus status)
             throws EProfileException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         CMS.debug("SubsystemGroupUpdater update starts");
@@ -163,12 +163,11 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
 
             system.addUser(user);
             CMS.debug("SubsystemGroupUpdater update: successfully add the user");
-            auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.SUCCESS,
-                               auditParams);
-            audit(auditMessage);
+                               auditParams));
 
             String b64 = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
             try {
@@ -188,12 +187,11 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
 
             system.addUserCert(user);
             CMS.debug("SubsystemGroupUpdater update: successfully add the user certificate");
-            auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.SUCCESS,
-                               auditParams);
-            audit(auditMessage);
+                               auditParams));
 
         } catch (ConflictingOperationException e) {
             CMS.debug("UpdateSubsystemGroup: update " + e.toString());
@@ -201,12 +199,12 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
 
         } catch (Exception e) {
             CMS.debug("UpdateSubsystemGroup: update addUser " + e.toString());
-            auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.FAILURE,
-                               auditParams);
-            audit(auditMessage);
+                               auditParams));
+
             throw new EProfileException(e.toString());
         }
 
@@ -232,12 +230,10 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
                 group.addMemberName(id);
                 system.modifyGroup(group);
 
-                auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.SUCCESS,
-                               auditParams);
-                audit(auditMessage);
+                               auditParams));
 
                 CMS.debug("UpdateSubsystemGroup: update: successfully added the user to the group.");
             } else {
@@ -245,12 +241,11 @@ public class SubsystemGroupUpdater implements IProfileUpdater {
             }
         } catch (Exception e) {
             CMS.debug("UpdateSubsystemGroup update: modifyGroup " + e.toString());
-            auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.FAILURE,
-                               auditParams);
-            audit(auditMessage);
+                               auditParams));
         }
     }
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
index 00f960e..c6ae5b1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/GroupMemberProcessor.java
@@ -43,9 +43,9 @@ import com.netscape.certsrv.group.GroupMemberCollection;
 import com.netscape.certsrv.group.GroupMemberData;
 import com.netscape.certsrv.group.GroupNotFoundException;
 import com.netscape.certsrv.group.GroupResource;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.usrgrp.IGroup;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
 import com.netscape.cms.servlet.processors.Processor;
@@ -388,6 +388,12 @@ public class GroupMemberProcessor extends Processor {
     }
 
     public void audit(String type, String id, Map<String, String> params, String status) {
-        audit(AuditEvent.CONFIG_ROLE, ScopeDef.SC_GROUP_MEMBERS, type, id, params, status);
+
+        if (auditor == null) return;
+
+        auditor.log(new ConfigRoleEvent(
+                auditor.getSubjectID(),
+                status,
+                auditor.getParamString(ScopeDef.SC_GROUP_MEMBERS, type, id, params)));
     }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java
index 1c38b88..183fbea 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java
@@ -31,9 +31,6 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.security.pkcs.PKCS7;
-import netscape.security.x509.X509CertImpl;
-
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.crypto.InternalCertificate;
 
@@ -48,9 +45,9 @@ import com.netscape.certsrv.common.Constants;
 import com.netscape.certsrv.common.NameValuePairs;
 import com.netscape.certsrv.common.OpDef;
 import com.netscape.certsrv.common.ScopeDef;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.password.IPasswordCheck;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IGroup;
@@ -60,6 +57,9 @@ import com.netscape.certsrv.usrgrp.IUser;
 import com.netscape.cmsutil.util.Cert;
 import com.netscape.cmsutil.util.Utils;
 
+import netscape.security.pkcs.PKCS7;
+import netscape.security.x509.X509CertImpl;
+
 /**
  * A class representing an administration servlet for
  * User/Group Manager. It communicates with client
@@ -667,7 +667,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -678,14 +677,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -697,14 +692,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 // backslashes (BS) are not allowed
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_RS_ID_BS"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_RS_ID_BS"),
@@ -716,14 +707,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 // backslashes (BS) are not allowed
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_SPECIAL_ID", id));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_SPECIAL_ID", id),
@@ -739,14 +726,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
 
                 log(ILogger.LL_FAILURE, msg);
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR, msg, null, resp);
                 return;
@@ -766,14 +749,11 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 IPasswordCheck passwdCheck = CMS.getPasswordChecker();
 
                 if (!passwdCheck.isGoodPassword(pword)) {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_ROLE,
+
+                    audit(new ConfigRoleEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
 
                     throw new EUsrGrpException(passwdCheck.getReason(pword));
 
@@ -819,14 +799,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                     } catch (Exception ex) {
                         ex.printStackTrace();
 
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_ROLE,
+                        audit(new ConfigRoleEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
 
                         sendResponse(ERROR,
                                 CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
@@ -842,14 +818,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                         } catch (Exception ex) {
                             log(ILogger.LL_FAILURE, ex.toString());
 
-                            // store a message in the signed audit log file
-                            auditMessage = CMS.getLogMessage(
-                                        AuditEvent.CONFIG_ROLE,
+                            audit(new ConfigRoleEvent(
                                         auditSubjectID,
                                         ILogger.FAILURE,
-                                        auditParams(req));
-
-                            audit(auditMessage);
+                                        auditParams(req)));
 
                             sendResponse(ERROR,
                                     CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
@@ -868,28 +840,20 @@ public class UsrGrpAdminServlet extends AdminServlet {
 
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
             } catch (EUsrGrpException e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 if (user.getUserID() == null) {
                     sendResponse(ERROR,
@@ -903,40 +867,30 @@ public class UsrGrpAdminServlet extends AdminServlet {
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp);
                 return;
             }
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -978,7 +932,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -989,14 +942,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1012,14 +961,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (certsString == null) {
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
@@ -1052,14 +997,11 @@ public class UsrGrpAdminServlet extends AdminServlet {
                     X509Certificate p7certs[] = pkcs7.getCertificates();
 
                     if (p7certs.length == 0) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_ROLE,
+
+                        audit(new ConfigRoleEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
 
                         sendResponse(ERROR,
                                 CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
@@ -1087,14 +1029,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                         // not a chain, or in random order
                         CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_BAD_CHAIN"));
 
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_ROLE,
+                        audit(new ConfigRoleEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
 
                         sendResponse(ERROR,
                                 CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
@@ -1153,14 +1091,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                     //-----
                     log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_ERROR", ex.toString()));
 
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_ROLE,
+                    audit(new ConfigRoleEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
 
                     sendResponse(ERROR,
                             CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp);
@@ -1169,14 +1103,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_O_ERROR", e.toString()));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_O_ERROR"), null, resp);
@@ -1191,14 +1121,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.addUserCert(user);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
@@ -1207,14 +1133,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_CERT_EXPIRED",
                         String.valueOf(certs[0].getSubjectDN())));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_EXPIRED"), null, resp);
@@ -1223,28 +1145,21 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_NOT_YET_VALID",
                         String.valueOf(certs[0].getSubjectDN())));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_NOT_YET_VALID"), null, resp);
                 return;
 
             } catch (ConflictingOperationException e) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_CERT_EXISTS"), null, resp);
@@ -1253,14 +1168,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
@@ -1279,14 +1190,11 @@ public class UsrGrpAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1331,7 +1239,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1342,14 +1249,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1364,14 +1267,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (certDN == null) {
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
@@ -1382,28 +1281,20 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.removeUserCert(user);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
@@ -1422,14 +1313,11 @@ public class UsrGrpAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1474,7 +1362,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1493,14 +1380,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1515,14 +1398,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             } catch (Exception ex) {
                 ex.printStackTrace();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp);
                 return;
@@ -1535,14 +1414,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                     if (mustDelete) {
                         mMgr.removeUserFromGroup(group, id);
                     } else {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_ROLE,
+                        audit(new ConfigRoleEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
 
                         sendResponse(ERROR,
                                 CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV_G"),
@@ -1557,52 +1432,39 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.removeUser(id);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
             } catch (Exception ex) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV"), null, resp);
                 return;
             }
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1644,7 +1506,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1656,14 +1517,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1694,26 +1551,19 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.addGroup(group);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
             } catch (Exception e) {
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_ADD_FAILED"),
@@ -1721,26 +1571,20 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 return;
             }
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1782,7 +1626,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1794,14 +1637,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1813,37 +1652,27 @@ public class UsrGrpAdminServlet extends AdminServlet {
             mMgr.removeGroup(id);
             NameValuePairs params = new NameValuePairs();
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.SUCCESS,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             sendResponse(SUCCESS, null, params, resp);
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1887,7 +1716,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1899,14 +1727,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -1952,14 +1776,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
                             if (!isDuplicate(groupName, memberName)) {
                                 group.addMemberName(memberName);
                             } else {
-                                // store a message in the signed audit log file
-                                auditMessage = CMS.getLogMessage(
-                                            AuditEvent.CONFIG_ROLE,
+                                audit(new ConfigRoleEvent(
                                             auditSubjectID,
                                             ILogger.FAILURE,
-                                            auditParams(req));
-
-                                audit(auditMessage);
+                                            auditParams(req)));
 
                                 throw new EBaseException(CMS.getUserMessage("CMS_BASE_DUPLICATE_ROLES", memberName));
                             }
@@ -1976,27 +1796,19 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.modifyGroup(group);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_MODIFY_FAILED"),
@@ -2004,26 +1816,20 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 return;
             }
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -2136,7 +1942,6 @@ public class UsrGrpAdminServlet extends AdminServlet {
             HttpServletResponse resp) throws ServletException,
             IOException, EBaseException {
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -2148,14 +1953,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
             if (id == null) {
                 log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID"));
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"),
@@ -2172,14 +1973,10 @@ public class UsrGrpAdminServlet extends AdminServlet {
 
                 log(ILogger.LL_FAILURE, msg);
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR, msg, null, resp);
                 return;
@@ -2197,14 +1994,11 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 IPasswordCheck passwdCheck = CMS.getPasswordChecker();
 
                 if (!passwdCheck.isGoodPassword(pword)) {
-                    // store a message in the signed audit log file
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_ROLE,
+
+                    audit(new ConfigRoleEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
 
                     throw new EUsrGrpException(passwdCheck.getReason(pword));
 
@@ -2228,54 +2022,40 @@ public class UsrGrpAdminServlet extends AdminServlet {
                 mMgr.modifyUser(user);
                 NameValuePairs params = new NameValuePairs();
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(SUCCESS, null, params, resp);
                 return;
             } catch (Exception e) {
                 log(ILogger.LL_FAILURE, e.toString());
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
 
                 sendResponse(ERROR,
                         CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp);
                 return;
             }
         } catch (EBaseException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
index 77ef4d8..f3a0164 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/RegisterUser.java
@@ -34,8 +34,8 @@ import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.authorization.EAuthzAccessDenied;
 import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.usrgrp.ICertUserLocator;
 import com.netscape.certsrv.usrgrp.IGroup;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -144,7 +144,6 @@ public class RegisterUser extends CMSServlet {
         CMS.debug("RegisterUser got name=" + name);
         CMS.debug("RegisterUser got certsString=" + certsString);
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditParams = "Scope;;users+Operation;;OP_ADD+source;;RegisterUser" +
                              "+Resource;;" + uid +
@@ -199,12 +198,11 @@ public class RegisterUser extends CMSServlet {
 
                 ugsys.addUser(user);
                 CMS.debug("RegisterUser created user " + uid);
-                auditMessage = CMS.getLogMessage(
-                              AuditEvent.CONFIG_ROLE,
+
+                audit(new ConfigRoleEvent(
                               auditSubjectID,
                               ILogger.SUCCESS,
-                              auditParams);
-                audit(auditMessage);
+                              auditParams));
             }
 
             // concatenate lines
@@ -218,23 +216,22 @@ public class RegisterUser extends CMSServlet {
             if (!foundByCert) {
                 ugsys.addUserCert(user);
                 CMS.debug("RegisterUser added user certificate");
-                auditMessage = CMS.getLogMessage(
-                              AuditEvent.CONFIG_ROLE,
+
+                audit(new ConfigRoleEvent(
                               auditSubjectID,
                               ILogger.SUCCESS,
-                              auditParams);
-                audit(auditMessage);
+                              auditParams));
+
             } else
                 CMS.debug("RegisterUser no need to add user certificate");
         } catch (Exception eee) {
             CMS.debug("RegisterUser error " + eee.toString());
-            auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams);
+                                auditParams));
 
-            audit(auditMessage);
             outputError(httpResp, "Error: Certificate malformed");
             return;
         }
@@ -261,22 +258,17 @@ public class RegisterUser extends CMSServlet {
                 ugsys.modifyGroup(group);
                 CMS.debug("RegisterUser modified group");
 
-                auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+                audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.SUCCESS,
-                               auditParams);
-
-                audit(auditMessage);
+                               auditParams));
             }
         } catch (Exception e) {
-            auditMessage = CMS.getLogMessage(
-                               AuditEvent.CONFIG_ROLE,
+
+            audit(new ConfigRoleEvent(
                                auditSubjectID,
                                ILogger.FAILURE,
-                               auditParams);
-
-            audit(auditMessage);
+                               auditParams));
         }
 
         // send success status back to the requestor
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java
index 5872ab0..91d8983 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java
@@ -28,13 +28,6 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import netscape.ldap.LDAPAttribute;
-import netscape.ldap.LDAPAttributeSet;
-import netscape.ldap.LDAPConnection;
-import netscape.ldap.LDAPEntry;
-import netscape.ldap.LDAPException;
-import netscape.ldap.LDAPModification;
-
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -49,12 +42,20 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.cms.servlet.base.CMSServlet;
 import com.netscape.cms.servlet.base.UserInfo;
 import com.netscape.cms.servlet.common.CMSRequest;
 import com.netscape.cms.servlet.common.ICMSTemplateFiller;
 import com.netscape.cmsutil.xml.XMLObject;
 
+import netscape.ldap.LDAPAttribute;
+import netscape.ldap.LDAPAttributeSet;
+import netscape.ldap.LDAPConnection;
+import netscape.ldap.LDAPEntry;
+import netscape.ldap.LDAPException;
+import netscape.ldap.LDAPModification;
+
 public class UpdateDomainXML extends CMSServlet {
 
     /**
@@ -368,12 +369,11 @@ public class UpdateDomainXML extends CMSServlet {
                     // remove the user for this subsystem's admin
                     status2 = remove_from_ldap(adminUserDN);
                     if (status2.equals(SUCCESS)) {
-                        auditMessage = CMS.getLogMessage(
-                                               AuditEvent.CONFIG_ROLE,
+
+                        audit(new ConfigRoleEvent(
                                                auditSubjectID,
                                                ILogger.SUCCESS,
-                                               userAuditParams);
-                        audit(auditMessage);
+                                               userAuditParams));
 
                         // remove this user from the subsystem group
                         userAuditParams = "Scope;;groups+Operation;;OP_DELETE_USER" +
@@ -384,26 +384,26 @@ public class UpdateDomainXML extends CMSServlet {
                                 new LDAPAttribute("uniqueMember", adminUserDN));
                         status2 = modify_ldap(dn, mod);
                         if (status2.equals(SUCCESS)) {
-                            auditMessage = CMS.getLogMessage(
-                                                   AuditEvent.CONFIG_ROLE,
+
+                            audit(new ConfigRoleEvent(
                                                    auditSubjectID,
                                                    ILogger.SUCCESS,
-                                                   userAuditParams);
+                                                   userAuditParams));
+
                         } else {
-                            auditMessage = CMS.getLogMessage(
-                                                   AuditEvent.CONFIG_ROLE,
+
+                            audit(new ConfigRoleEvent(
                                                    auditSubjectID,
                                                    ILogger.FAILURE,
-                                                   userAuditParams);
+                                                   userAuditParams));
                         }
-                        audit(auditMessage);
+
                     } else { // error deleting user
-                        auditMessage = CMS.getLogMessage(
-                                               AuditEvent.CONFIG_ROLE,
+
+                        audit(new ConfigRoleEvent(
                                                auditSubjectID,
                                                ILogger.FAILURE,
-                                               userAuditParams);
-                        audit(auditMessage);
+                                               userAuditParams));
                     }
                 }
             } else {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java
index 64344d2..ffe707c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/Processor.java
@@ -60,19 +60,6 @@ public class Processor {
         return map;
     }
 
-    public void audit(String message, String scope, String type, String id, Map<String, String> params, String status) {
-
-        if (auditor == null) return;
-
-        String auditMessage = CMS.getLogMessage(
-                message,
-                auditor.getSubjectID(),
-                status,
-                auditor.getParamString(scope, type, id, params));
-
-        auditor.log(auditMessage);
-    }
-
     public void log(int source, int level, String message) {
 
         if (logger == null) return;
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/GroupService.java b/base/server/cms/src/org/dogtagpki/server/rest/GroupService.java
index 4aa0209..6292cf8 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/GroupService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/GroupService.java
@@ -40,8 +40,8 @@ import com.netscape.certsrv.group.GroupData;
 import com.netscape.certsrv.group.GroupMemberData;
 import com.netscape.certsrv.group.GroupNotFoundException;
 import com.netscape.certsrv.group.GroupResource;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.usrgrp.IGroup;
 import com.netscape.certsrv.usrgrp.IGroupConstants;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -432,6 +432,12 @@ public class GroupService extends SubsystemService implements GroupResource {
     }
 
     public void audit(String type, String id, Map<String, String> params, String status) {
-        audit(AuditEvent.CONFIG_ROLE, ScopeDef.SC_GROUPS, type, id, params, status);
+
+        if (auditor == null) return;
+
+        auditor.log(new ConfigRoleEvent(
+                auditor.getSubjectID(),
+                status,
+                auditor.getParamString(ScopeDef.SC_GROUPS, type, id, params)));
     }
 }
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/UserService.java b/base/server/cms/src/org/dogtagpki/server/rest/UserService.java
index e10c4f5..ec690d6 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/UserService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/UserService.java
@@ -52,8 +52,8 @@ import com.netscape.certsrv.common.OpDef;
 import com.netscape.certsrv.common.ScopeDef;
 import com.netscape.certsrv.dbs.certdb.CertId;
 import com.netscape.certsrv.group.GroupMemberData;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigRoleEvent;
 import com.netscape.certsrv.password.IPasswordCheck;
 import com.netscape.certsrv.user.UserCertCollection;
 import com.netscape.certsrv.user.UserCertData;
@@ -1227,10 +1227,22 @@ public class UserService extends SubsystemService implements UserResource {
     }
 
     public void auditUser(String type, String id, Map<String, String> params, String status) {
-        audit(AuditEvent.CONFIG_ROLE, ScopeDef.SC_USERS, type, id, params, status);
+
+        if (auditor == null) return;
+
+        auditor.log(new ConfigRoleEvent(
+                auditor.getSubjectID(),
+                status,
+                auditor.getParamString(ScopeDef.SC_USERS, type, id, params)));
     }
 
     public void auditUserCert(String type, String id, Map<String, String> params, String status) {
-        audit(AuditEvent.CONFIG_ROLE, ScopeDef.SC_USER_CERTS, type, id, params, status);
+
+        if (auditor == null) return;
+
+        auditor.log(new ConfigRoleEvent(
+                auditor.getSubjectID(),
+                status,
+                auditor.getParamString(ScopeDef.SC_USER_CERTS, type, id, params)));
     }
 }
-- 
1.8.3.1


From 692b2d776397b8fd2e4dfbab3a5d2ac407c440de Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 12 Apr 2017 21:45:12 +0200
Subject: [PATCH 30/49] Added CertRequestProcessedEvent.

A new CertRequestProcessedEvent class of has been added to
encapsulate the CERT_REQUEST_PROCESSED events.

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

Change-Id: Ia79e6ae13d09a3ec6509c60435fc24d5a2fee38f
---
 .../logging/event/CertRequestProcessedEvent.java   |  43 +++++++
 .../netscape/cms/servlet/cert/CertProcessor.java   |  26 ++---
 .../netscape/cms/servlet/cert/EnrollServlet.java   |  50 +++------
 .../cms/servlet/cert/RequestProcessor.java         |  42 ++-----
 .../cms/servlet/connector/ConnectorServlet.java    |  19 ++--
 .../servlet/profile/ProfileSubmitCMCServlet.java   |  38 +++----
 .../cms/servlet/request/ProcessCertReq.java        | 125 +++++++--------------
 7 files changed, 138 insertions(+), 205 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
new file mode 100644
index 0000000..1703f65
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
@@ -0,0 +1,43 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class CertRequestProcessedEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public CertRequestProcessedEvent(
+            String subjectID,
+            String outcome,
+            String requesterID,
+            String infoName,
+            String infoValue) {
+
+        super(CERT_REQUEST_PROCESSED);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                requesterID,
+                infoName,
+                infoValue
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
index c16d8e0..2a60cb0 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -32,8 +32,8 @@ import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.cert.CertEnrollmentRequest;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.profile.EDeferException;
 import com.netscape.certsrv.profile.ERejectException;
 import com.netscape.certsrv.profile.IEnrollProfile;
@@ -217,7 +217,6 @@ public class CertProcessor extends CAProcessor {
     }
 
     protected String submitRequests(Locale locale, IProfile profile, IAuthToken authToken, IRequest[] reqs) {
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = ILogger.UNIDENTIFIED;
         String errorCode = null;
@@ -252,16 +251,13 @@ public class CertProcessor extends CAProcessor {
                 if (auditInfoCertValue != null) {
                     if (!(auditInfoCertValue.equals(
                             ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+
+                        audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue);
-
-                        audit(auditMessage);
+                                auditInfoCertValue));
                     }
                 }
             } catch (EDeferException e) {
@@ -288,16 +284,13 @@ public class CertProcessor extends CAProcessor {
                 req.setExtData(IRequest.ERROR, e.toString());
                 req.setExtData(IRequest.ERROR_CODE, errorCode);
 
-                // store a message in the signed audit log file
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.CERT_REQUEST_PROCESSED,
+                audit(new CertRequestProcessedEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditRequesterID,
                         ILogger.SIGNED_AUDIT_REJECTION,
-                        codeToReason(locale, errorCode, e.toString(), req.getRequestId()));
+                        codeToReason(locale, errorCode, e.toString(), req.getRequestId())));
 
-                audit(auditMessage);
             } catch (Throwable e) {
                 // return error to the user
                 CMS.debug(e);
@@ -307,15 +300,12 @@ public class CertProcessor extends CAProcessor {
                 req.setExtData(IRequest.ERROR, errorReason);
                 req.setExtData(IRequest.ERROR_CODE, errorCode);
 
-                auditMessage = CMS.getLogMessage(
-                        AuditEvent.CERT_REQUEST_PROCESSED,
+                audit(new CertRequestProcessedEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditRequesterID,
                         ILogger.SIGNED_AUDIT_REJECTION,
-                        errorReason);
-
-                audit(auditMessage);
+                        errorReason));
             }
 
             try {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
index 6f01d2a..cb2b76f 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
@@ -53,6 +53,7 @@ import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.RequestStatus;
 import com.netscape.certsrv.usrgrp.IGroup;
@@ -1368,29 +1369,23 @@ public class EnrollServlet extends CMSServlet {
                     for (int i = 0; i < issuedCerts.length; i++) {
                         // (automated "agent" cert request processed
                         //  - "accepted")
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue(issuedCerts[i]));
-
-                        audit(auditMessage);
+                                    auditInfoCertValue(issuedCerts[i])));
                     }
                 } catch (IOException ex) {
                     cmsReq.setStatus(ICMSRequest.ERROR);
 
                     // (automated "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_REJECTION,
-                                SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]));
                 }
 
                 return;
@@ -1402,15 +1397,12 @@ public class EnrollServlet extends CMSServlet {
 
             if (completed == false) {
                 // (automated "agent" cert request processed - "rejected")
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CERT_REQUEST_PROCESSED,
+                audit(new CertRequestProcessedEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
                             auditRequesterID,
                             ILogger.SIGNED_AUDIT_REJECTION,
-                            SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[1]);
-
-                audit(auditMessage);
+                            SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[1]));
 
                 return;
             }
@@ -1458,15 +1450,12 @@ public class EnrollServlet extends CMSServlet {
 
                 for (int i = 0; i < issuedCerts.length; i++) {
                     // (automated "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue(issuedCerts[i]));
-
-                    audit(auditMessage);
+                                auditInfoCertValue(issuedCerts[i])));
                 }
 
                 return;
@@ -1481,15 +1470,12 @@ public class EnrollServlet extends CMSServlet {
 
                 for (int i = 0; i < issuedCerts.length; i++) {
                     // (automated "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue(issuedCerts[i]));
-
-                    audit(auditMessage);
+                                auditInfoCertValue(issuedCerts[i])));
                 }
             } catch (IOException e) {
                 log(ILogger.LL_FAILURE,
@@ -1498,15 +1484,12 @@ public class EnrollServlet extends CMSServlet {
                                 e.toString()));
 
                 // (automated "agent" cert request processed - "rejected")
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CERT_REQUEST_PROCESSED,
+                audit(new CertRequestProcessedEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
                             auditRequesterID,
                             ILogger.SIGNED_AUDIT_REJECTION,
-                            SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[2]);
-
-                audit(auditMessage);
+                            SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[2]));
 
                 throw new ECMSGWException(
                         CMS.getUserMessage("CMS_GW_RETURNING_RESULT_ERROR"));
@@ -1514,15 +1497,12 @@ public class EnrollServlet extends CMSServlet {
         } catch (EBaseException eAudit1) {
             // store a message in the signed audit log file
             // (automated "agent" cert request processed - "rejected")
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CERT_REQUEST_PROCESSED,
+            audit(new CertRequestProcessedEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
                         auditRequesterID,
                         ILogger.SIGNED_AUDIT_REJECTION,
-                        SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[3]);
-
-            audit(auditMessage);
+                        SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[3]));
 
             throw eAudit1;
         }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
index 474a2e5..66fe58c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -25,8 +25,6 @@ import java.util.Locale;
 
 import javax.servlet.http.HttpServletRequest;
 
-import netscape.security.x509.X509CertImpl;
-
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
@@ -40,8 +38,8 @@ import com.netscape.certsrv.ca.AuthorityID;
 import com.netscape.certsrv.ca.CANotFoundException;
 import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.cert.CertReviewResponse;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.profile.EDeferException;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.ERejectException;
@@ -62,6 +60,8 @@ import com.netscape.certsrv.request.RequestStatus;
 import com.netscape.cms.servlet.common.CMSRequest;
 import com.netscape.cms.servlet.profile.ProfileOutputFactory;
 
+import netscape.security.x509.X509CertImpl;
+
 public class RequestProcessor extends CertProcessor {
 
     public RequestProcessor(String id, Locale locale) throws EPropertyNotFound, EBaseException {
@@ -275,23 +275,18 @@ public class RequestProcessor extends CertProcessor {
      *                occurred
      */
     private void cancelRequest(IRequest req) throws EProfileException {
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = auditRequesterID(req);
         String auditInfoValue = auditInfoValue(req);
 
         req.setRequestStatus(RequestStatus.CANCELED);
 
-        // store a message in the signed audit log file
-        auditMessage = CMS.getLogMessage(
-                AuditEvent.CERT_REQUEST_PROCESSED,
+        audit(new CertRequestProcessedEvent(
                 auditSubjectID,
                 ILogger.SUCCESS,
                 auditRequesterID,
                 ILogger.SIGNED_AUDIT_CANCELLATION,
-                auditInfoValue);
-
-        audit(auditMessage);
+                auditInfoValue));
     }
 
     /**
@@ -311,23 +306,18 @@ public class RequestProcessor extends CertProcessor {
      *                occurred
      */
     private void rejectRequest(IRequest req) throws EProfileException {
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = auditRequesterID(req);
         String auditInfoValue = auditInfoValue(req);
 
         req.setRequestStatus(RequestStatus.REJECTED);
 
-        // store a message in the signed audit log file
-        auditMessage = CMS.getLogMessage(
-                AuditEvent.CERT_REQUEST_PROCESSED,
+        audit(new CertRequestProcessedEvent(
                 auditSubjectID,
                 ILogger.SUCCESS,
                 auditRequesterID,
                 ILogger.SIGNED_AUDIT_REJECTION,
-                auditInfoValue);
-
-        audit(auditMessage);
+                auditInfoValue));
     }
 
     /**
@@ -374,7 +364,6 @@ public class RequestProcessor extends CertProcessor {
      */
     private void approveRequest(IRequest req, CertReviewResponse data, IProfile profile, Locale locale)
             throws EBaseException {
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = auditRequesterID(req);
 
@@ -398,28 +387,21 @@ public class RequestProcessor extends CertProcessor {
             X509CertImpl theCert = req.getExtDataInCert(
                     IEnrollProfile.REQUEST_ISSUED_CERT);
 
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.CERT_REQUEST_PROCESSED,
+            audit(new CertRequestProcessedEvent(
                     auditSubjectID,
                     ILogger.SUCCESS,
                     auditRequesterID,
                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                    auditInfoCertValue(theCert));
-
-            audit(auditMessage);
+                    auditInfoCertValue(theCert)));
 
         } catch (EProfileException eAudit1) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+            audit(new CertRequestProcessedEvent(
                     auditSubjectID,
                     ILogger.FAILURE,
                     auditRequesterID,
                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                    ILogger.SIGNED_AUDIT_EMPTY_VALUE);
-
-            audit(auditMessage);
+                    ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
             CMS.debug("CertRequestExecutor: about to throw EProfileException because of bad profile execute.");
             throw eAudit1;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
index 6732e92..ee60187 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -52,6 +52,7 @@ import com.netscape.certsrv.connector.IRequestEncoder;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfileSubsystem;
@@ -626,16 +627,13 @@ public class ConnectorServlet extends CMSServlet {
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
-                            // store a message in the signed audit log file
-                            auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                            audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue);
-
-                            audit(auditMessage);
+                                    auditInfoCertValue));
                         }
                     }
                 }
@@ -648,16 +646,13 @@ public class ConnectorServlet extends CMSServlet {
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
-                            // store a message in the signed audit log file
-                            auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                            audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue);
-
-                            audit(auditMessage);
+                                    auditInfoCertValue));
                         }
                     }
                 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
index c3ada9a..28f777b 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -44,8 +44,8 @@ import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.SessionContext;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.profile.EDeferException;
 import com.netscape.certsrv.profile.EProfileException;
 import com.netscape.certsrv.profile.ERejectException;
@@ -639,7 +639,6 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
             }
         } //for
 
-        String auditMessage = null;
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = ILogger.UNIDENTIFIED;
 
@@ -677,16 +676,13 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                     ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
-                            // store a message in the signed audit log file
-                            auditMessage = CMS.getLogMessage(
-                                        AuditEvent.CERT_REQUEST_PROCESSED,
+
+                            audit(new CertRequestProcessedEvent(
                                         auditSubjectID,
                                         ILogger.SUCCESS,
                                         auditRequesterID,
                                         ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                        auditInfoCertValue);
-
-                            audit(auditMessage);
+                                        auditInfoCertValue));
                         }
                     }
                 } catch (EDeferException e) {
@@ -733,31 +729,26 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
 
                 if (errorCode != null) {
                     if (errorCode.equals("1")) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_REJECTION,
-                                    errorReason);
+                                    errorReason));
 
-                        audit(auditMessage);
                     } else if (errorCode.equals("2")) {
                         // do NOT store a message in the signed audit log file
                         // as this errorCode indicates that a process has been
                         // deferred for manual acceptance/cancellation/rejection
                     } else if (errorCode.equals("3")) {
-                        // store a message in the signed audit log file
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_REJECTION,
-                                    errorReason);
-
-                        audit(auditMessage);
+                                    errorReason));
                     }
                     error_codes[k] = Integer.parseInt(errorCode);
                 } else
@@ -782,16 +773,13 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                 ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
-                            // store a message in the signed audit log file
-                            auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                            audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue);
-
-                            audit(auditMessage);
+                                    auditInfoCertValue));
                         }
                     }
                 } catch (ERejectException e) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
index 9d0da48..2bcc8ad 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
@@ -50,6 +50,7 @@ import com.netscape.certsrv.common.ICMSRequest;
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFormat;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertRequestProcessedEvent;
 import com.netscape.certsrv.publish.IPublisherProcessor;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.certsrv.request.IRequestQueue;
@@ -463,37 +464,31 @@ public class ProcessCertReq extends CMSServlet {
                         audit(auditMessage);
                     } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
                         // (manual "agent" cert request processed - "accepted")
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     auditInfoName,
-                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
-                        audit(auditMessage);
                     } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
                         // (manual "agent" cert request processed - "cancelled")
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     auditInfoName,
-                                    SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[0]);
+                                    SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[0]));
 
-                        audit(auditMessage);
                     } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
                         // (manual "agent" cert request processed - "rejected")
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CERT_REQUEST_PROCESSED,
+                        audit(new CertRequestProcessedEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     auditInfoName,
-                                    SIGNED_AUDIT_MANUAL_REJECTION_REASON[0]);
-
-                        audit(auditMessage);
+                                    SIGNED_AUDIT_MANUAL_REJECTION_REASON[0]));
                     }
 
                     return;
@@ -935,15 +930,12 @@ public class ProcessCertReq extends CMSServlet {
                                 // store a message in the signed audit log file
                                 // (one for each manual "agent"
                                 //  cert request processed - "accepted")
-                                auditMessage = CMS.getLogMessage(
-                                            AuditEvent.CERT_REQUEST_PROCESSED,
+                                audit(new CertRequestProcessedEvent(
                                             auditSubjectID,
                                             ILogger.SUCCESS,
                                             auditRequesterID,
                                             auditInfoName,
-                                            auditInfoCertValue(issuedCerts[i]));
-
-                                audit(auditMessage);
+                                            auditInfoCertValue(issuedCerts[i])));
                             }
                             header.addStringValue(
                                     "serialNumber", sbuf.toString());
@@ -979,15 +971,12 @@ public class ProcessCertReq extends CMSServlet {
                             // store a message in the signed audit log file
                             // (manual "agent" cert request processed
                             //  - "accepted")
-                            auditMessage = CMS.getLogMessage(
-                                        AuditEvent.CERT_REQUEST_PROCESSED,
+                            audit(new CertRequestProcessedEvent(
                                         auditSubjectID,
                                         ILogger.SUCCESS,
                                         auditRequesterID,
                                         auditInfoName,
-                                        ILogger.SIGNED_AUDIT_EMPTY_VALUE);
-
-                            audit(auditMessage);
+                                        ILogger.SIGNED_AUDIT_EMPTY_VALUE));
                         }
 
                         // grant trusted manager or agent privileges
@@ -1104,15 +1093,12 @@ public class ProcessCertReq extends CMSServlet {
 
                     // store a message in the signed audit log file
                     // (manual "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[1]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[1]));
 
                 } else if (toDo.equals("cancel")) {
                     mQueue.cancelRequest(r);
@@ -1166,15 +1152,12 @@ public class ProcessCertReq extends CMSServlet {
 
                     // store a message in the signed audit log file
                     // (manual "agent" cert request processed - "cancelled")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[1]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[1]));
 
                 } else if (toDo.equals("clone")) {
                     IRequest clonedRequest = mQueue.cloneAndMarkPending(r);
@@ -1277,37 +1260,30 @@ public class ProcessCertReq extends CMSServlet {
                     audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
                     // (manual "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+                                ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
                     // (manual "agent" cert request processed - "cancelled")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[2]);
+                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[2]));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
                     // (manual "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[2]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[2]));
                 }
             }
 
@@ -1330,37 +1306,30 @@ public class ProcessCertReq extends CMSServlet {
                     audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
                     // (manual "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+                                ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
                     // (manual "agent" cert request processed - "cancelled")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[3]);
+                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[3]));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
                     // (manual "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[3]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[3]));
                 }
             }
 
@@ -1384,37 +1353,30 @@ public class ProcessCertReq extends CMSServlet {
                     audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
                     // (manual "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+                                ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
                     // (manual "agent" cert request processed - "cancelled")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[4]);
+                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[4]));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
                     // (manual "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[4]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[4]));
                 }
             }
 
@@ -1438,37 +1400,30 @@ public class ProcessCertReq extends CMSServlet {
                     audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) {
                     // (manual "agent" cert request processed - "accepted")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                ILogger.SIGNED_AUDIT_EMPTY_VALUE);
+                                ILogger.SIGNED_AUDIT_EMPTY_VALUE));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) {
                     // (manual "agent" cert request processed - "cancelled")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[5]);
+                                SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[5]));
 
-                    audit(auditMessage);
                 } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) {
                     // (manual "agent" cert request processed - "rejected")
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CERT_REQUEST_PROCESSED,
+                    audit(new CertRequestProcessedEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
                                 auditRequesterID,
                                 auditInfoName,
-                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[5]);
-
-                    audit(auditMessage);
+                                SIGNED_AUDIT_MANUAL_REJECTION_REASON[5]));
                 }
             }
 
-- 
1.8.3.1


From f902b0365f2cf92f14f0a814394cd025669b3ea8 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Mon, 24 Apr 2017 20:35:50 +0200
Subject: [PATCH 31/49] Updated debug logs in SystemConfigService.

Change-Id: Id73bd6d3c0874c327bc27260318a2c671f0f0177
---
 .../src/org/dogtagpki/server/rest/SystemConfigService.java    | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java
index 27a6817..afbb24a 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/SystemConfigService.java
@@ -1008,18 +1008,25 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
 
         if (!CryptoUtil.isInternalToken(token)) {
             try {
+                CMS.debug("Logging into token " + token);
                 CryptoToken ctoken = CryptoUtil.getKeyStorageToken(token);
                 String tokenpwd = data.getTokenPassword();
                 ConfigurationUtils.loginToken(ctoken, tokenpwd);
+
             } catch (NotInitializedException e) {
+                CMS.debug(e);
                 throw new PKIException("Token is not initialized", e);
+
             } catch (NoSuchTokenException e) {
-                throw new BadRequestException("Invalid Token provided. No such token.", e);
+                CMS.debug(e);
+                throw new BadRequestException("No such key storage token: " + token, e);
+
             } catch (TokenException e) {
                 CMS.debug(e);
                 throw new PKIException("Token Exception: " + e, e);
+
             } catch (IncorrectPasswordException e) {
-                throw new BadRequestException("Incorrect Password provided for token.", e);
+                throw new BadRequestException("Incorrect password for token " + token, e);
             }
         }
     }
-- 
1.8.3.1


From 993a55fb4c883b3ca7ea0e64e24f4501909a571c Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 21 Apr 2017 05:37:05 +0200
Subject: [PATCH 32/49] Added ConfigSignedAuditEvent.

A new SignedAuditConfigRoleEvent class of has been added to
encapsulate the CONFIG_SIGNED_AUDIT events.

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

Change-Id: I95b897fa0bb73007a7cec009c43ade4cc860f0cd
---
 .../logging/event/ConfigSignedAuditEvent.java      |  39 +++
 .../cms/servlet/admin/LogAdminServlet.java         | 381 ++++++++-------------
 .../org/dogtagpki/server/rest/AuditService.java    |   9 +-
 3 files changed, 185 insertions(+), 244 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ConfigSignedAuditEvent.java

diff --git a/base/common/src/com/netscape/certsrv/logging/event/ConfigSignedAuditEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ConfigSignedAuditEvent.java
new file mode 100644
index 0000000..32de443
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/logging/event/ConfigSignedAuditEvent.java
@@ -0,0 +1,39 @@
+// --- 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) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.logging.event;
+
+import com.netscape.certsrv.logging.AuditEvent;
+
+public class ConfigSignedAuditEvent extends AuditEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public ConfigSignedAuditEvent(
+            String subjectID,
+            String outcome,
+            String params) {
+
+        super(CONFIG_SIGNED_AUDIT);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                params
+        });
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java b/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java
index c424520..1641f27 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/admin/LogAdminServlet.java
@@ -44,6 +44,7 @@ import com.netscape.certsrv.logging.ILogEventListener;
 import com.netscape.certsrv.logging.ILogSubsystem;
 import com.netscape.certsrv.logging.ILogger;
 import com.netscape.certsrv.logging.LogPlugin;
+import com.netscape.certsrv.logging.event.ConfigSignedAuditEvent;
 
 /**
  * A class representings an administration servlet for logging
@@ -414,7 +415,7 @@ public class LogAdminServlet extends AdminServlet {
     private synchronized void addLogPlugin(HttpServletRequest req,
             HttpServletResponse resp, String scope)
             throws ServletException, IOException, EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -435,13 +436,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -454,13 +453,11 @@ public class LogAdminServlet extends AdminServlet {
             if (mSys.getLogPlugins().containsKey(id)) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -475,13 +472,11 @@ public class LogAdminServlet extends AdminServlet {
             if (classPath == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -504,13 +499,11 @@ public class LogAdminServlet extends AdminServlet {
             } catch (ClassNotFoundException e) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -520,13 +513,11 @@ public class LogAdminServlet extends AdminServlet {
             } catch (IllegalArgumentException e) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -540,13 +531,11 @@ public class LogAdminServlet extends AdminServlet {
                 if (ILogEventListener.class.isAssignableFrom(newImpl) == false) {
                     // store a message in the signed audit log file
                     if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                        audit(new ConfigSignedAuditEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
                     }
 
                     sendResponse(ERROR,
@@ -557,13 +546,11 @@ public class LogAdminServlet extends AdminServlet {
             } catch (NullPointerException e) { // unlikely, only if newImpl null.
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -584,13 +571,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -608,13 +593,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             sendResponse(SUCCESS, null, params, resp);
@@ -632,14 +615,11 @@ public class LogAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_SIGNED_AUDIT,
+
+            audit(new ConfigSignedAuditEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -686,7 +666,7 @@ public class LogAdminServlet extends AdminServlet {
     private synchronized void addLogInst(HttpServletRequest req,
             HttpServletResponse resp, String scope)
             throws ServletException, IOException, EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -705,13 +685,11 @@ public class LogAdminServlet extends AdminServlet {
             if (id == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -723,13 +701,11 @@ public class LogAdminServlet extends AdminServlet {
             if (!isValidID(id)) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR, "Invalid ID '" + id + "'",
@@ -740,13 +716,11 @@ public class LogAdminServlet extends AdminServlet {
             if (mSys.getLogInsts().containsKey(id)) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -762,13 +736,11 @@ public class LogAdminServlet extends AdminServlet {
             if (implname == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -785,13 +757,11 @@ public class LogAdminServlet extends AdminServlet {
             if (plugin == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(
@@ -845,13 +815,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -864,13 +832,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -883,13 +849,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -908,13 +872,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR, e.toString(getLocale(req)), null, resp);
@@ -924,13 +886,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR, e.toString(), null, resp);
@@ -946,13 +906,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -970,13 +928,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             sendResponse(SUCCESS, null, params, resp);
@@ -994,14 +950,11 @@ public class LogAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_SIGNED_AUDIT,
+
+            audit(new ConfigSignedAuditEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1077,7 +1030,7 @@ public class LogAdminServlet extends AdminServlet {
     private synchronized void delLogInst(HttpServletRequest req,
             HttpServletResponse resp, String scope)
             throws ServletException, IOException, EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1099,13 +1052,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1118,13 +1069,11 @@ public class LogAdminServlet extends AdminServlet {
             if (mSys.getLogInsts().containsKey(id) == false) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1154,13 +1103,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1171,13 +1118,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             sendResponse(SUCCESS, null, params, resp);
@@ -1195,14 +1140,11 @@ public class LogAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_SIGNED_AUDIT,
+
+            audit(new ConfigSignedAuditEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1239,7 +1181,7 @@ public class LogAdminServlet extends AdminServlet {
     private synchronized void delLogPlugin(HttpServletRequest req,
             HttpServletResponse resp, String scope)
             throws ServletException, IOException, EBaseException {
-        String auditMessage = null;
+
         String auditSubjectID = auditSubjectID();
 
         // ensure that any low-level exceptions are reported
@@ -1261,13 +1203,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1279,13 +1219,11 @@ public class LogAdminServlet extends AdminServlet {
             if (mSys.getLogPlugins().containsKey(id) == false) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1304,13 +1242,11 @@ public class LogAdminServlet extends AdminServlet {
                 if (getLogPluginName(log) == id) {
                     // store a message in the signed audit log file
                     if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                        auditMessage = CMS.getLogMessage(
-                                    AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                        audit(new ConfigSignedAuditEvent(
                                     auditSubjectID,
                                     ILogger.FAILURE,
-                                    auditParams(req));
-
-                        audit(auditMessage);
+                                    auditParams(req)));
                     }
 
                     sendResponse(ERROR,
@@ -1335,13 +1271,11 @@ public class LogAdminServlet extends AdminServlet {
             } catch (EBaseException e) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1352,13 +1286,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             sendResponse(SUCCESS, null, params, resp);
@@ -1376,14 +1308,11 @@ public class LogAdminServlet extends AdminServlet {
             //     // rethrow the specific exception to be handled later
             //     throw eAudit1;
         } catch (IOException eAudit2) {
-            // store a message in the signed audit log file
-            auditMessage = CMS.getLogMessage(
-                        AuditEvent.CONFIG_SIGNED_AUDIT,
+
+            audit(new ConfigSignedAuditEvent(
                         auditSubjectID,
                         ILogger.FAILURE,
-                        auditParams(req));
-
-            audit(auditMessage);
+                        auditParams(req)));
 
             // rethrow the specific exception to be handled later
             throw eAudit2;
@@ -1468,13 +1397,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1487,13 +1414,11 @@ public class LogAdminServlet extends AdminServlet {
             if (!mSys.getLogInsts().containsKey(id)) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1508,13 +1433,11 @@ public class LogAdminServlet extends AdminServlet {
             if (implname == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1530,13 +1453,11 @@ public class LogAdminServlet extends AdminServlet {
             if (plugin == null) {
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(
@@ -1682,13 +1603,11 @@ public class LogAdminServlet extends AdminServlet {
                                     // store a message in the signed audit log
                                     // file
                                     if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                                        auditMessage = CMS.getLogMessage(
-                                                    AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                                        audit(new ConfigSignedAuditEvent(
                                                     auditSubjectID,
                                                     ILogger.FAILURE,
-                                                    auditParams(req));
-
-                                        audit(auditMessage);
+                                                    auditParams(req)));
                                     }
 
                                     sendResponse(ERROR,
@@ -1797,13 +1716,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1848,13 +1765,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1899,13 +1814,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -1958,13 +1871,11 @@ public class LogAdminServlet extends AdminServlet {
 
                 // store a message in the signed audit log file
                 if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                    auditMessage = CMS.getLogMessage(
-                                AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                    audit(new ConfigSignedAuditEvent(
                                 auditSubjectID,
                                 ILogger.FAILURE,
-                                auditParams(req));
-
-                    audit(auditMessage);
+                                auditParams(req)));
                 }
 
                 sendResponse(ERROR,
@@ -2017,13 +1928,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.SUCCESS,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             sendResponse(RESTART, null, params, resp);
@@ -2063,13 +1972,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             // rethrow the specific exception to be handled later
@@ -2109,13 +2016,11 @@ public class LogAdminServlet extends AdminServlet {
 
             // store a message in the signed audit log file
             if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) {
-                auditMessage = CMS.getLogMessage(
-                            AuditEvent.CONFIG_SIGNED_AUDIT,
+
+                audit(new ConfigSignedAuditEvent(
                             auditSubjectID,
                             ILogger.FAILURE,
-                            auditParams(req));
-
-                audit(auditMessage);
+                            auditParams(req)));
             }
 
             // rethrow the specific exception to be handled later
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java b/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
index 2d5b371..7c29651 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/AuditService.java
@@ -49,11 +49,11 @@ import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.base.ResourceNotFoundException;
 import com.netscape.certsrv.logging.AuditConfig;
-import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.AuditFile;
 import com.netscape.certsrv.logging.AuditFileCollection;
 import com.netscape.certsrv.logging.AuditResource;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.ConfigSignedAuditEvent;
 import com.netscape.cms.servlet.base.SubsystemService;
 
 /**
@@ -412,12 +412,9 @@ public class AuditService extends SubsystemService implements AuditResource {
      */
     public void auditTPSConfigSignedAudit(String status, Map<String, String> params) {
 
-        String msg = CMS.getLogMessage(
-                AuditEvent.CONFIG_SIGNED_AUDIT,
+        auditor.log(new ConfigSignedAuditEvent(
                 servletRequest.getUserPrincipal().getName(),
                 status,
-                auditor.getParamString(null, params));
-        auditor.log(msg);
-
+                auditor.getParamString(null, params)));
     }
 }
-- 
1.8.3.1


From 36a606e4b51de17c56da0f9ee4daab062ec4acf3 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 19 Apr 2017 23:23:39 +0200
Subject: [PATCH 33/49] Added CertRequestProcessedEvent constructor for
 X509CertImpl.

A new CertRequestProcessedEvent constructor has been added to
encapsulate CERT_REQUEST_PROCESSED events that take an X509CertImpl
object.

Copies of auditInfoCertValue() method in various classes have been
combined and moved into CertRequestProcessedEvent.

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

Change-Id: Ie234bdb9f1b52399dad4bd1e20f57dcb99d86091
---
 .../logging/event/CertRequestProcessedEvent.java   | 71 ++++++++++++++++++++++
 .../netscape/cms/servlet/cert/CertProcessor.java   |  5 +-
 .../netscape/cms/servlet/cert/EnrollServlet.java   | 61 +------------------
 .../cms/servlet/cert/RequestProcessor.java         |  2 +-
 .../cms/servlet/connector/ConnectorServlet.java    | 65 ++------------------
 .../cms/servlet/processors/CAProcessor.java        | 54 ----------------
 .../servlet/profile/ProfileSubmitCMCServlet.java   | 64 ++-----------------
 .../cms/servlet/request/ProcessCertReq.java        | 56 +----------------
 8 files changed, 91 insertions(+), 287 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
index 1703f65..3e5041d 100644
--- a/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
+++ b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
@@ -17,7 +17,13 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.certsrv.logging.event;
 
+import java.security.cert.CertificateEncodingException;
+
 import com.netscape.certsrv.logging.AuditEvent;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.cmsutil.util.Utils;
+
+import netscape.security.x509.X509CertImpl;
 
 public class CertRequestProcessedEvent extends AuditEvent {
 
@@ -40,4 +46,69 @@ public class CertRequestProcessedEvent extends AuditEvent {
                 infoValue
         });
     }
+
+    public CertRequestProcessedEvent(
+            String subjectID,
+            String outcome,
+            String requesterID,
+            String infoName,
+            X509CertImpl x509cert) {
+
+        super(CERT_REQUEST_PROCESSED);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                requesterID,
+                infoName,
+                auditInfoCertValue(x509cert)
+        });
+    }
+
+    /**
+     * Signed Audit Log Info Certificate Value
+     *
+     * This method is called to obtain the certificate from the passed in
+     * "X509CertImpl" for a signed audit log message.
+     * <P>
+     *
+     * @param x509cert an X509CertImpl
+     * @return cert string containing the certificate
+     */
+    public static String auditInfoCertValue(X509CertImpl x509cert) {
+
+        if (x509cert == null) {
+            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+        }
+
+        byte rawData[] = null;
+
+        try {
+            rawData = x509cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+        }
+
+        String cert = null;
+
+        // convert "rawData" into "base64Data"
+        if (rawData != null) {
+            String base64Data = Utils.base64encode(rawData).trim();
+
+            // concatenate lines
+            cert = base64Data.replace("\r", "").replace("\n", "");
+        }
+
+        if (cert != null) {
+            cert = cert.trim();
+
+            if (cert.equals("")) {
+                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+            } else {
+                return cert;
+            }
+        } else {
+            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+        }
+    }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
index 2a60cb0..d25d817 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertProcessor.java
@@ -246,8 +246,9 @@ public class CertProcessor extends CAProcessor {
                 req.setRequestStatus(RequestStatus.COMPLETE);
 
                 X509CertImpl x509cert = req.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
-                String auditInfoCertValue = auditInfoCertValue(x509cert);
+                String auditInfoCertValue = CertRequestProcessedEvent.auditInfoCertValue(x509cert);
 
+                // TODO: simplify this condition
                 if (auditInfoCertValue != null) {
                     if (!(auditInfoCertValue.equals(
                             ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
@@ -257,7 +258,7 @@ public class CertProcessor extends CAProcessor {
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue));
+                                x509cert));
                     }
                 }
             } catch (EDeferException e) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
index cb2b76f..43df5b6 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollServlet.java
@@ -19,7 +19,6 @@ package com.netscape.cms.servlet.cert;
 
 import java.io.IOException;
 import java.math.BigInteger;
-import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
@@ -69,7 +68,6 @@ import com.netscape.cms.servlet.processors.CRMFProcessor;
 import com.netscape.cms.servlet.processors.KeyGenProcessor;
 import com.netscape.cms.servlet.processors.PKCS10Processor;
 import com.netscape.cms.servlet.processors.PKIProcessor;
-import com.netscape.cmsutil.util.Utils;
 
 import netscape.security.pkcs.PKCS10;
 import netscape.security.x509.AlgorithmId;
@@ -1374,7 +1372,7 @@ public class EnrollServlet extends CMSServlet {
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue(issuedCerts[i])));
+                                    issuedCerts[i]));
                     }
                 } catch (IOException ex) {
                     cmsReq.setStatus(ICMSRequest.ERROR);
@@ -1455,7 +1453,7 @@ public class EnrollServlet extends CMSServlet {
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue(issuedCerts[i])));
+                                issuedCerts[i]));
                 }
 
                 return;
@@ -1475,7 +1473,7 @@ public class EnrollServlet extends CMSServlet {
                                 ILogger.SUCCESS,
                                 auditRequesterID,
                                 ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                auditInfoCertValue(issuedCerts[i])));
+                                issuedCerts[i]));
                 }
             } catch (IOException e) {
                 log(ILogger.LL_FAILURE,
@@ -1674,57 +1672,4 @@ public class EnrollServlet extends CMSServlet {
             throws EBaseException {
         mIsTestBed = config.getBoolean("isTestBed", true);
     }
-
-    /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param x509cert an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    private String auditInfoCertValue(X509CertImpl x509cert) {
-        // if no signed audit object exists, bail
-        if (mSignedAuditLogger == null) {
-            return null;
-        }
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
index 66fe58c..b66aec2 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -392,7 +392,7 @@ public class RequestProcessor extends CertProcessor {
                     ILogger.SUCCESS,
                     auditRequesterID,
                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                    auditInfoCertValue(theCert)));
+                    theCert));
 
         } catch (EProfileException eAudit1) {
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
index ee60187..b5ccdd2 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java
@@ -25,7 +25,6 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.Enumeration;
@@ -62,7 +61,6 @@ import com.netscape.certsrv.request.RequestId;
 import com.netscape.certsrv.request.RequestStatus;
 import com.netscape.cms.servlet.base.CMSServlet;
 import com.netscape.cms.servlet.common.CMSRequest;
-import com.netscape.cmsutil.util.Utils;
 
 import netscape.security.x509.CRLExtensions;
 import netscape.security.x509.CRLReasonExtension;
@@ -622,8 +620,9 @@ public class ConnectorServlet extends CMSServlet {
                 if (isProfileRequest(thisreq)) {
 
                     X509CertImpl x509cert = thisreq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
-                    String auditInfoCertValue = auditInfoCertValue(x509cert);
+                    String auditInfoCertValue = CertRequestProcessedEvent.auditInfoCertValue(x509cert);
 
+                    // TODO: simplify this condition
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
@@ -633,7 +632,7 @@ public class ConnectorServlet extends CMSServlet {
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue));
+                                    x509cert));
                         }
                     }
                 }
@@ -641,8 +640,9 @@ public class ConnectorServlet extends CMSServlet {
                 if (isProfileRequest(thisreq)) {
 
                     X509CertImpl x509cert = thisreq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
-                    String auditInfoCertValue = auditInfoCertValue(x509cert);
+                    String auditInfoCertValue = CertRequestProcessedEvent.auditInfoCertValue(x509cert);
 
+                    // TODO: simplify this condition
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                    ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
@@ -652,7 +652,7 @@ public class ConnectorServlet extends CMSServlet {
                                     ILogger.FAILURE,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue));
+                                    x509cert));
                         }
                     }
                 }
@@ -1054,57 +1054,4 @@ public class ConnectorServlet extends CMSServlet {
 
         return profileID;
     }
-
-    /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param x509cert an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    private String auditInfoCertValue(X509CertImpl x509cert) {
-        // if no signed audit object exists, bail
-        if (mSignedAuditLogger == null) {
-            return null;
-        }
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 74f501f..25f7bb3 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -71,7 +71,6 @@ import com.netscape.certsrv.util.IStatsSubsystem;
 import com.netscape.cms.servlet.common.AuthCredentials;
 import com.netscape.cms.servlet.common.CMSGateway;
 import com.netscape.cms.servlet.common.ServletUtils;
-import com.netscape.cmsutil.util.Utils;
 
 import netscape.security.x509.X509CertImpl;
 
@@ -1040,59 +1039,6 @@ public class CAProcessor extends Processor {
     }
 
     /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param x509cert an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    protected String auditInfoCertValue(X509CertImpl x509cert) {
-        // if no signed audit object exists, bail
-        if (signedAuditLogger == null) {
-            return null;
-        }
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
-
-    /**
      * Signed Audit Groups
      *
      * This method is called to extract all "groups" associated
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
index 28f777b..26ca2a4 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -19,7 +19,6 @@ package com.netscape.cms.servlet.profile;
 
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.security.cert.CertificateEncodingException;
 import java.util.Enumeration;
 import java.util.Locale;
 
@@ -671,8 +670,9 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     reqs[k].setRequestStatus(RequestStatus.COMPLETE);
 
                     X509CertImpl x509cert = reqs[k].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
-                    String auditInfoCertValue = auditInfoCertValue(x509cert);
+                    String auditInfoCertValue = CertRequestProcessedEvent.auditInfoCertValue(x509cert);
 
+                    // TODO: simplify this condition
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                     ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
@@ -682,7 +682,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                                         ILogger.SUCCESS,
                                         auditRequesterID,
                                         ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                        auditInfoCertValue));
+                                        x509cert));
                         }
                     }
                 } catch (EDeferException e) {
@@ -768,8 +768,9 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                     CMS.debug("ProfileSubmitCMCServlet: provedReq set to complete");
 
                     X509CertImpl x509cert = reqs[0].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT);
-                    String auditInfoCertValue = auditInfoCertValue(x509cert);
+                    String auditInfoCertValue = CertRequestProcessedEvent.auditInfoCertValue(x509cert);
 
+                    // TODO: simplify this condition
                     if (auditInfoCertValue != null) {
                         if (!(auditInfoCertValue.equals(
                                 ILogger.SIGNED_AUDIT_EMPTY_VALUE))) {
@@ -779,7 +780,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                                     ILogger.SUCCESS,
                                     auditRequesterID,
                                     ILogger.SIGNED_AUDIT_ACCEPTANCE,
-                                    auditInfoCertValue));
+                                    x509cert));
                         }
                     }
                 } catch (ERejectException e) {
@@ -875,57 +876,4 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
 
         return requesterID;
     }
-
-    /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param x509cert an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    private String auditInfoCertValue(X509CertImpl x509cert) {
-        // if no signed audit object exists, bail
-        if (mSignedAuditLogger == null) {
-            return null;
-        }
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
index 2bcc8ad..c229263 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/ProcessCertReq.java
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.math.BigInteger;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.util.Date;
 import java.util.Enumeration;
@@ -935,7 +934,7 @@ public class ProcessCertReq extends CMSServlet {
                                             ILogger.SUCCESS,
                                             auditRequesterID,
                                             auditInfoName,
-                                            auditInfoCertValue(issuedCerts[i])));
+                                            issuedCerts[i]));
                             }
                             header.addStringValue(
                                     "serialNumber", sbuf.toString());
@@ -1757,59 +1756,6 @@ public class ProcessCertReq extends CMSServlet {
 
         return infoName;
     }
-
-    /**
-     * Signed Audit Log Info Certificate Value
-     *
-     * This method is called to obtain the certificate from the passed in
-     * "X509CertImpl" for a signed audit log message.
-     * <P>
-     *
-     * @param x509cert an X509CertImpl
-     * @return cert string containing the certificate
-     */
-    private String auditInfoCertValue(X509CertImpl x509cert) {
-        // if no signed audit object exists, bail
-        if (mSignedAuditLogger == null) {
-            return null;
-        }
-
-        if (x509cert == null) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        byte rawData[] = null;
-
-        try {
-            rawData = x509cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-
-        String cert = null;
-
-        // convert "rawData" into "base64Data"
-        if (rawData != null) {
-            String base64Data = null;
-
-            base64Data = Utils.base64encode(rawData).trim();
-
-            // concatenate lines
-            cert = base64Data.replace("\r", "").replace("\n", "");
-        }
-
-        if (cert != null) {
-            cert = cert.trim();
-
-            if (cert.equals("")) {
-                return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-            } else {
-                return cert;
-            }
-        } else {
-            return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-        }
-    }
 }
 
 class RAReqCompletedFiller extends ImportCertsTemplateFiller {
-- 
1.8.3.1


From 6f457f2c5e0df576f067b46a78b481eb5dc197e8 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Fri, 14 Apr 2017 01:46:36 +0200
Subject: [PATCH 34/49] Added CertRequestProcessedEvent constructor for
 IRequest.

A new CertRequestProcessedEvent constructor has been added to
encapsulate CERT_REQUEST_PROCESSED events that takes an IRequest
object.

The auditInfoValue() method in CAProcessor has been moved into
CertRequestProcessedEvent.

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

Change-Id: I892f1476835b45910fdc3e64bd9f6fc9e2f016fb
---
 .../logging/event/CertRequestProcessedEvent.java   | 53 ++++++++++++++++++++++
 .../cms/servlet/cert/RequestProcessor.java         |  7 +--
 .../cms/servlet/processors/CAProcessor.java        | 39 ----------------
 3 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
index 3e5041d..777434b 100644
--- a/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
+++ b/base/common/src/com/netscape/certsrv/logging/event/CertRequestProcessedEvent.java
@@ -21,6 +21,7 @@ import java.security.cert.CertificateEncodingException;
 
 import com.netscape.certsrv.logging.AuditEvent;
 import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequest;
 import com.netscape.cmsutil.util.Utils;
 
 import netscape.security.x509.X509CertImpl;
@@ -29,6 +30,8 @@ public class CertRequestProcessedEvent extends AuditEvent {
 
     private static final long serialVersionUID = 1L;
 
+    public final static String SIGNED_AUDIT_CERT_REQUEST_REASON = "requestNotes";
+
     public CertRequestProcessedEvent(
             String subjectID,
             String outcome,
@@ -65,6 +68,24 @@ public class CertRequestProcessedEvent extends AuditEvent {
         });
     }
 
+    public CertRequestProcessedEvent(
+            String subjectID,
+            String outcome,
+            String requesterID,
+            String infoName,
+            IRequest request) {
+
+        super(CERT_REQUEST_PROCESSED);
+
+        setParameters(new Object[] {
+                subjectID,
+                outcome,
+                requesterID,
+                infoName,
+                auditInfoValue(request)
+        });
+    }
+
     /**
      * Signed Audit Log Info Certificate Value
      *
@@ -111,4 +132,36 @@ public class CertRequestProcessedEvent extends AuditEvent {
             return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
         }
     }
+
+    /**
+     * Signed Audit Log Info Value
+     *
+     * This method is called to obtain the "reason" for
+     * a signed audit log message.
+     * <P>
+     *
+     * @param request the actual request
+     * @return reason string containing the signed audit log message reason
+     */
+    String auditInfoValue(IRequest request) {
+
+        String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+
+        if (request != null) {
+            // overwrite "reason" if and only if "info" != null
+            String info =
+                    request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON);
+
+            if (info != null) {
+                reason = info.trim();
+
+                // overwrite "reason" if and only if "reason" is empty
+                if (reason.equals("")) {
+                    reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+                }
+            }
+        }
+
+        return reason;
+    }
 }
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
index b66aec2..4494d2c 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -277,8 +277,6 @@ public class RequestProcessor extends CertProcessor {
     private void cancelRequest(IRequest req) throws EProfileException {
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = auditRequesterID(req);
-        String auditInfoValue = auditInfoValue(req);
-
         req.setRequestStatus(RequestStatus.CANCELED);
 
         audit(new CertRequestProcessedEvent(
@@ -286,7 +284,7 @@ public class RequestProcessor extends CertProcessor {
                 ILogger.SUCCESS,
                 auditRequesterID,
                 ILogger.SIGNED_AUDIT_CANCELLATION,
-                auditInfoValue));
+                req));
     }
 
     /**
@@ -308,7 +306,6 @@ public class RequestProcessor extends CertProcessor {
     private void rejectRequest(IRequest req) throws EProfileException {
         String auditSubjectID = auditSubjectID();
         String auditRequesterID = auditRequesterID(req);
-        String auditInfoValue = auditInfoValue(req);
 
         req.setRequestStatus(RequestStatus.REJECTED);
 
@@ -317,7 +314,7 @@ public class RequestProcessor extends CertProcessor {
                 ILogger.SUCCESS,
                 auditRequesterID,
                 ILogger.SIGNED_AUDIT_REJECTION,
-                auditInfoValue));
+                req));
     }
 
     /**
diff --git a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
index 25f7bb3..bc5b9b5 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/processors/CAProcessor.java
@@ -120,9 +120,6 @@ public class CAProcessor extends Processor {
     public static final String ACL_INFO = "ACLinfo";
     public static final String PROFILE_SUB_ID = "profileSubId";
 
-    public final static String SIGNED_AUDIT_CERT_REQUEST_REASON =
-            "requestNotes";
-
     protected String profileID;
     protected String profileSubId;
     protected String aclMethod;
@@ -1003,42 +1000,6 @@ public class CAProcessor extends Processor {
     }
 
     /**
-     * Signed Audit Log Info Value
-     *
-     * This method is called to obtain the "reason" for
-     * a signed audit log message.
-     * <P>
-     *
-     * @param request the actual request
-     * @return reason string containing the signed audit log message reason
-     */
-    protected String auditInfoValue(IRequest request) {
-        // if no signed audit object exists, bail
-        if (signedAuditLogger == null) {
-            return null;
-        }
-
-        String reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-
-        if (request != null) {
-            // overwrite "reason" if and only if "info" != null
-            String info =
-                    request.getExtDataInString(SIGNED_AUDIT_CERT_REQUEST_REASON);
-
-            if (info != null) {
-                reason = info.trim();
-
-                // overwrite "reason" if and only if "reason" is empty
-                if (reason.equals("")) {
-                    reason = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
-                }
-            }
-        }
-
-        return reason;
-    }
-
-    /**
      * Signed Audit Groups
      *
      * This method is called to extract all "groups" associated
-- 
1.8.3.1


From 8caedd6723f4885d4aff2348aa3d9fc850627aa1 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Tue, 7 Feb 2017 17:27:06 +1000
Subject: [PATCH 35/49] LDAPProfileSubsystem: avoid duplicating logic in
 superclass

Part of: https://fedorahosted.org/pki/ticket/2588

Change-Id: I1ac9a3d89c93832ef6b6b48b89138495ef4892fb
---
 .../cmscore/profile/AbstractProfileSubsystem.java  |  7 +++-
 .../cmscore/profile/LDAPProfileSubsystem.java      | 43 ++++------------------
 2 files changed, 13 insertions(+), 37 deletions(-)

diff --git a/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
index 116b8e2..2a209ad 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
@@ -121,7 +121,7 @@ public abstract class AbstractProfileSubsystem implements IProfileSubsystem {
     /**
      * Commits a profile.
      */
-    public void commitProfile(String id)
+    public synchronized void commitProfile(String id)
             throws EProfileException {
         IConfigStore cs = mProfiles.get(id).getConfigStore();
 
@@ -157,6 +157,11 @@ public abstract class AbstractProfileSubsystem implements IProfileSubsystem {
 
         // finally commit the configStore
         //
+        commitConfigStore(id, cs);
+    }
+
+    protected void commitConfigStore(String id, IConfigStore cs)
+            throws EProfileException {
         try {
             cs.commit(false);
         } catch (EBaseException e) {
diff --git a/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java
index fff8ead..bce675e 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/profile/LDAPProfileSubsystem.java
@@ -303,43 +303,14 @@ public class LDAPProfileSubsystem
             readProfile(entry);
     }
 
+    /**
+     * Commit the configStore and track the resulting
+     * entryUSN and (in case of add) the nsUniqueId
+     */
     @Override
-    public synchronized void commitProfile(String id) throws EProfileException {
-        LDAPConfigStore cs = (LDAPConfigStore) mProfiles.get(id).getConfigStore();
-
-        // first create a *new* profile object from the configStore
-        // and initialise it with the updated configStore
-        //
-        IPluginRegistry registry = (IPluginRegistry)
-            CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
-        String classId = mProfileClassIds.get(id);
-        IPluginInfo info = registry.getPluginInfo("profile", classId);
-        String className = info.getClassName();
-        IProfile newProfile = null;
-        try {
-            newProfile = (IProfile) Class.forName(className).newInstance();
-        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
-            throw new EProfileException("Could not instantiate class '"
-                    + classId + "' for profile '" + id + "': " + e);
-        }
-        newProfile.setId(id);
-        try {
-            newProfile.init(this, cs);
-        } catch (EBaseException e) {
-            throw new EProfileException(
-                    "Failed to initialise profile '" + id + "': " + e);
-        }
-
-        // next replace the existing profile with the new profile;
-        // this is to avoid any intermediate state where the profile
-        // is not fully initialised with its inputs, outputs and
-        // policy objects.
-        //
-        mProfiles.put(id, newProfile);
-
-        // finally commit the configStore and track the resulting
-        // entryUSN and (in case of add) the nsUniqueId
-        //
+    protected void commitConfigStore(String id, IConfigStore configStore)
+            throws EProfileException {
+        LDAPConfigStore cs = (LDAPConfigStore) configStore;
         try {
             String[] attrs = {"entryUSN", "nsUniqueId"};
             LDAPEntry entry = cs.commitReturn(false, attrs);
-- 
1.8.3.1


From 6562b05a73090c0f7882a9684a8ceac2666e4401 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Tue, 7 Feb 2017 17:39:33 +1000
Subject: [PATCH 36/49] ISourceConfigStore: add clear() method to interface

The SourceConfigStore load() method does not clear the config store,
but this might be necessary to avoid stale data if wanting to
perform a complete replacement of the data (e.g. reload from file).

We should not change the behaviour of load() in case some code is
relying on the current behaviour, so add the clear() method to the
interface.

Part of: https://fedorahosted.org/pki/ticket/2588

Change-Id: Ia139a49f1a23c4f9410d7b94c9a4c8f14f29fe93
---
 base/common/src/com/netscape/certsrv/base/ISourceConfigStore.java    | 5 +++++
 .../cmscore/src/com/netscape/cmscore/base/PropConfigStore.java       | 4 ++++
 2 files changed, 9 insertions(+)

diff --git a/base/common/src/com/netscape/certsrv/base/ISourceConfigStore.java b/base/common/src/com/netscape/certsrv/base/ISourceConfigStore.java
index 42637c2..8eb86c2 100644
--- a/base/common/src/com/netscape/certsrv/base/ISourceConfigStore.java
+++ b/base/common/src/com/netscape/certsrv/base/ISourceConfigStore.java
@@ -63,6 +63,11 @@ public interface ISourceConfigStore extends Serializable {
     public Enumeration<String> keys();
 
     /**
+     * Clear the config store.
+     */
+    public void clear();
+
+    /**
      * Reads a config store from an input stream.
      *
      * @param in input stream where the properties are located
diff --git a/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java b/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java
index cc16e24..acf2844 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/base/PropConfigStore.java
@@ -223,6 +223,10 @@ public class PropConfigStore implements IConfigStore, Cloneable {
         }
     }
 
+    public synchronized void clear() {
+        mSource.clear();
+    }
+
     /**
      * Reads a config store from an input stream.
      *
-- 
1.8.3.1


From 62419afd831039e7487ba184c6bf8f876f4d21da Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Tue, 7 Feb 2017 21:12:08 +1000
Subject: [PATCH 37/49] ProfileService: clear profile attributes when modifying

When modifying a profile, attributes are not cleared.  Attributes
that were removed in the updated profile configuration are not
actually removed.

When updating a profile via PUT /ca/rest/profiles/{id}/raw, clear
the config store before loading the new configuration.

Fixes: https://fedorahosted.org/pki/ticket/2588
Change-Id: I4988315c57bb5d5a44deb04d41603adb39780f19
---
 base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java
index be61892..8666b9c 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java
@@ -718,6 +718,7 @@ public class ProfileService extends SubsystemService implements ProfileResource
             }
 
             // no error thrown, so commit updated profile config
+            profile.getConfigStore().clear();
             profile.getConfigStore().load(new ByteArrayInputStream(data));
             ps.disableProfile(profileId);
             ps.commitProfile(profileId);
-- 
1.8.3.1


From da624993c302a81a11f37f984d75c37a467dc5e5 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 6 Apr 2017 16:07:07 +1000
Subject: [PATCH 38/49] KRA: do not accumulate recovered keys in token

When using token-based unwrapping of archived keys, the key is being
stored in the token.  We do not want to accumulate the keys here;
make them temporary.

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

Change-Id: Ic12a4db7238512b4fec5d6fdb023b20195c2d438
---
 base/kra/src/com/netscape/kra/RecoveryService.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java
index fda5b80..5609b19 100644
--- a/base/kra/src/com/netscape/kra/RecoveryService.java
+++ b/base/kra/src/com/netscape/kra/RecoveryService.java
@@ -416,7 +416,7 @@ public class RecoveryService implements IService {
                 privKey = mStorageUnit.unwrap(
                         keyRecord.getPrivateKeyData(),
                         pubkey,
-                        false,
+                        true /* temporary */,
                         keyRecord.getWrappingParams(mKRA.getStorageKeyUnit().getOldWrappingParams()));
             } catch (Exception e) {
                 mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_PRIVATE_KEY_NOT_FOUND"));
-- 
1.8.3.1


From 3cc50b49e2a18344937702bd1b170b9faf738845 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Thu, 27 Apr 2017 11:10:36 -0400
Subject: [PATCH 39/49] Modify the key client to default to 3DES

When no algorithm OID is provided, we used to default to 3DES.
We need to continue to do this to not break IPA.

Change-Id: I620c3d7cec71be1a529056acc6bf3940e25f2f9d
---
 base/common/python/pki/key.py | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py
index e782d54..9313b0e 100644
--- a/base/common/python/pki/key.py
+++ b/base/common/python/pki/key.py
@@ -514,7 +514,7 @@ class KeyClient(object):
         pki.util.read_environment_files()
         client_keyset = os.getenv('KEY_WRAP_PARAMETER_SET')
         if client_keyset is not None:
-            return client_keyset
+            return int(client_keyset)
         return 0
 
     def get_server_keyset(self):
@@ -795,7 +795,7 @@ class KeyClient(object):
             data_type,
             encrypted_data,
             wrapped_session_key,
-            algorithm_oid=None,
+            algorithm_oid=self.encrypt_alg_oid,
             nonce_iv=nonce_iv,
             key_algorithm=key_algorithm,
             key_size=key_size,
@@ -850,8 +850,10 @@ class KeyClient(object):
             raise TypeError('Missing wrapped session key')
 
         if not algorithm_oid:
-            algorithm_oid = pki.crypto.AES_128_CBC_OID
-            # algorithm_oid = KeyClient.DES_EDE3_CBC_OID
+            # legacy apps like IPA call this directly without
+            # setting the algorithm_oid.  We need to keep DES
+            # for backward compatibility
+            algorithm_oid = pki.crypto.DES_EDE3_CBC_OID
 
         if not nonce_iv:
             raise TypeError('Missing nonce IV')
-- 
1.8.3.1


From b93cec621203c6fb970b57ef042636ba2f9efa3d Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 27 Apr 2017 16:01:39 +1000
Subject: [PATCH 41/49] Add upgrade script that adds KRA wrapping params

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

Change-Id: Iaa1c2c3b6f7de178bd38c2b5b8df57a2a99f64b1
---
 base/server/upgrade/10.4.2/02-AddKRAWrappingParams | 78 ++++++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100755 base/server/upgrade/10.4.2/02-AddKRAWrappingParams

diff --git a/base/server/upgrade/10.4.2/02-AddKRAWrappingParams b/base/server/upgrade/10.4.2/02-AddKRAWrappingParams
new file mode 100755
index 0000000..c95b844
--- /dev/null
+++ b/base/server/upgrade/10.4.2/02-AddKRAWrappingParams
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+# Authors:
+#     Fraser Tweedale <ftweedal@redhat.com>
+#
+# 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.
+#
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+
+from __future__ import absolute_import
+import os.path
+
+import pki
+from pki.server.upgrade import PKIServerUpgradeScriptlet
+
+proplist = [
+    ('kra.storageUnit.wrapping.0.sessionKeyLength', '168'),
+    ('kra.storageUnit.wrapping.0.sessionKeyWrapAlgorithm', 'RSA'),
+    ('kra.storageUnit.wrapping.0.payloadEncryptionPadding', 'PKCS5Padding'),
+    ('kra.storageUnit.wrapping.0.sessionKeyKeyGenAlgorithm', 'DESede'),
+    ('kra.storageUnit.wrapping.0.payloadEncryptionAlgorithm', 'DESede'),
+    ('kra.storageUnit.wrapping.0.payloadEncryptionMode', 'CBC'),
+    ('kra.storageUnit.wrapping.0.payloadEncryptionIV', 'AQEBAQEBAQE='),
+    ('kra.storageUnit.wrapping.0.payloadWrapAlgorithm', 'DES3/CBC/Pad'),
+    ('kra.storageUnit.wrapping.0.payloadWrapIV', 'AQEBAQEBAQE='),
+    ('kra.storageUnit.wrapping.0.sessionKeyType', 'DESede'),
+    ('kra.storageUnit.wrapping.1.sessionKeyLength', '128'),
+    ('kra.storageUnit.wrapping.1.sessionKeyWrapAlgorithm', 'RSA'),
+    ('kra.storageUnit.wrapping.1.payloadEncryptionPadding', 'PKCS5Padding'),
+    ('kra.storageUnit.wrapping.1.sessionKeyKeyGenAlgorithm', 'AES'),
+    ('kra.storageUnit.wrapping.1.payloadEncryptionAlgorithm', 'AES'),
+    ('kra.storageUnit.wrapping.1.payloadEncryptionMode', 'CBC'),
+    ('kra.storageUnit.wrapping.1.payloadEncryptionIVLen', '16'),
+    ('kra.storageUnit.wrapping.1.payloadWrapAlgorithm', 'AES KeyWrap/Padding'),
+    ('kra.storageUnit.wrapping.1.sessionKeyType', 'AES'),
+
+    # this upgrade script adds the config, but uses the legacy
+    # configuration so that behaviour of deployed instance does
+    # not change
+    ('kra.storageUnit.wrapping.choice', '0'),
+]
+
+
+class AddKRAWrappingParams(PKIServerUpgradeScriptlet):
+    def __init__(self):
+        super(AddKRAWrappingParams, self).__init__()
+        self.message = 'Add wrapping params to KRA CS.cfg'
+
+    def upgrade_subsystem(self, instance, subsystem):
+        if subsystem.name == 'kra':
+            self.upgrade_config(instance, subsystem)
+
+    def upgrade_config(self, instance, subsystem):  # pylint: disable=W0613
+        filename = os.path.join(subsystem.conf_dir, 'CS.cfg')
+        self.backup(filename)
+
+        properties = pki.PropertyFile(filename)
+        properties.read()
+
+        # if the property exists, leave it alone, otherwise set
+        # it to the value defined above
+        for k, v in proplist:
+            cur = properties.get(k)
+            if cur is None:
+                properties.set(k, v)
+
+        properties.write()
-- 
1.8.3.1


From 853220445eb0ce54b6ce241547891605329b7e3e Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Fri, 28 Apr 2017 00:29:45 -0400
Subject: [PATCH 42/49] Fix DES3 using python-cryptography provider

Incorrect key size lead to errors when the client side
was set to use 3DES. Also deprecate not providing an
encryption algorithm OID explcitly in
archive_encrypted_data()

Change-Id: I51e8ee2aed1d0cddd9d37d91a93c920be901fdb9
---
 base/common/python/pki/crypto.py | 7 ++++++-
 base/common/python/pki/key.py    | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/base/common/python/pki/crypto.py b/base/common/python/pki/crypto.py
index 0891acd..7f03846 100644
--- a/base/common/python/pki/crypto.py
+++ b/base/common/python/pki/crypto.py
@@ -389,9 +389,14 @@ class CryptographyCryptoProvider(CryptoProvider):
             self.encrypt_mode = modes.CBC
             self.encrypt_size = 128
         elif level == 0:
+            # note that 3DES keys are actually 192 bits long, even
+            # though only 168 bits are used internally.  See
+            # https://tools.ietf.org/html/rfc4949
+            # Using 168 here will cause python-cryptography key verification
+            # checks to fail.
             self.encrypt_alg = algorithms.TripleDES
             self.encrypt_mode = modes.CBC
-            self.encrypt_size = 168
+            self.encrypt_size = 192
 
     def generate_nonce_iv(self, mechanism='AES'):
         """ Create a random initialization vector """
diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py
index 9313b0e..d2b8297 100644
--- a/base/common/python/pki/key.py
+++ b/base/common/python/pki/key.py
@@ -28,6 +28,7 @@ from __future__ import print_function
 import base64
 import json
 import os
+import warnings
 
 from six import iteritems
 from six.moves.urllib.parse import quote  # pylint: disable=F0401,E0611
@@ -853,6 +854,8 @@ class KeyClient(object):
             # legacy apps like IPA call this directly without
             # setting the algorithm_oid.  We need to keep DES
             # for backward compatibility
+            warnings.warn("algorithm_oid=None is deprecated",
+                          DeprecationWarning)
             algorithm_oid = pki.crypto.DES_EDE3_CBC_OID
 
         if not nonce_iv:
-- 
1.8.3.1


From d98f20d33378a37898d4d6ffec80b09261504823 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-206.sjc.redhat.com>
Date: Wed, 26 Apr 2017 15:21:39 -0700
Subject: [PATCH 43/49] CA in the certificate profiles the startTime parameter
 is not working as expected.

This simple fix addresses an overflow in the "startTime" paramenter in 4 places in the code. I felt that honing in only on the startTime value was the best way to go. In some of the files other than ValidityDefault.java, there were possibly some values that could be changed from int to long. Due to the complexity of some of the calculations involved in some of those cases, it is best to fix the exact issue at hand instead of introducing some other possible side effects.
---
 .../src/com/netscape/cms/profile/def/CAValidityDefault.java  | 12 ++++++------
 .../cms/profile/def/PrivateKeyUsagePeriodExtDefault.java     |  4 ++--
 .../netscape/cms/profile/def/RandomizedValidityDefault.java  |  2 +-
 .../src/com/netscape/cms/profile/def/ValidityDefault.java    | 10 +++++-----
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java
index 2df256e..2ecd484 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CAValidityDefault.java
@@ -24,6 +24,11 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 
+import netscape.security.x509.BasicConstraintsExtension;
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.ca.ICertificateAuthority;
@@ -34,11 +39,6 @@ import com.netscape.certsrv.property.EPropertyException;
 import com.netscape.certsrv.property.IDescriptor;
 import com.netscape.certsrv.request.IRequest;
 
-import netscape.security.x509.BasicConstraintsExtension;
-import netscape.security.x509.CertificateValidity;
-import netscape.security.x509.PKIXExtensions;
-import netscape.security.x509.X509CertInfo;
-
 /**
  * This class implements a CA signing cert enrollment default policy
  * that populates a server-side configurable validity
@@ -348,7 +348,7 @@ public class CAValidityDefault extends EnrollDefault {
         if (startTimeStr == null || startTimeStr.equals("")) {
             startTimeStr = "60";
         }
-        int startTime = Integer.parseInt(startTimeStr);
+        long startTime = Long.parseLong(startTimeStr);
 
         Date notBefore = new Date(CMS.getCurrentDate().getTime() + (1000 * startTime));
         CMS.debug("CAValidityDefault: not before: " + notBefore);
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java
index 6532a13..2f05f32 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/PrivateKeyUsagePeriodExtDefault.java
@@ -296,13 +296,13 @@ public class PrivateKeyUsagePeriodExtDefault extends EnrollExtDefault {
             if (startTimeStr == null || startTimeStr.equals("")) {
                 startTimeStr = "60";
             }
-            int startTime = Integer.parseInt(startTimeStr);
+            long startTime = Long.parseLong(startTimeStr);
             Date notBefore = new Date(CMS.getCurrentDate().getTime() +
                     (1000 * startTime));
             long notAfterVal = 0;
 
             notAfterVal = notBefore.getTime() +
-                    (mDefault * Integer.parseInt(getConfig(CONFIG_DURATION)));
+                    (mDefault * Long.parseLong(getConfig(CONFIG_DURATION)));
             Date notAfter = new Date(notAfterVal);
 
             ext = new PrivateKeyUsageExtension(notBefore, notAfter);
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java
index 6308715..ce69c15 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/RandomizedValidityDefault.java
@@ -290,7 +290,7 @@ public class RandomizedValidityDefault extends EnrollDefault {
         if (startTimeStr == null || startTimeStr.equals("")) {
             startTimeStr = "60";
         }
-        int startTime = Integer.parseInt(startTimeStr);
+        long startTime = Long.parseLong(startTimeStr);
 
         String notBeforeRandomBitsStr = getConfig(CONFIG_NOT_BEFORE_RANDOM_BITS);
         if (notBeforeRandomBitsStr == null || notBeforeRandomBitsStr.length() == 0) {
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java
index 21ec8ea..a74ccdf 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/ValidityDefault.java
@@ -24,6 +24,10 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 
+import netscape.security.x509.CertificateValidity;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.ca.ICertificateAuthority;
@@ -34,10 +38,6 @@ import com.netscape.certsrv.property.EPropertyException;
 import com.netscape.certsrv.property.IDescriptor;
 import com.netscape.certsrv.request.IRequest;
 
-import netscape.security.x509.CertificateValidity;
-import netscape.security.x509.X509CertImpl;
-import netscape.security.x509.X509CertInfo;
-
 /**
  * This class implements an enrollment default policy
  * that populates a server-side configurable validity
@@ -265,7 +265,7 @@ public class ValidityDefault extends EnrollDefault {
         if (startTimeStr == null || startTimeStr.equals("")) {
             startTimeStr = "60";
         }
-        int startTime = Integer.parseInt(startTimeStr);
+        long startTime = Long.parseLong(startTimeStr);
 
         Date notBefore = new Date(CMS.getCurrentDate().getTime() + (1000 * startTime));
         CMS.debug("ValidityDefault: not before: " + notBefore);
-- 
1.8.3.1


From 9590944d5726ff32d94c6a2b2909175eae946466 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Fri, 28 Apr 2017 17:44:19 -0400
Subject: [PATCH 44/49] Fix symkey retrieval using NSS python client

This is tested using Barbican as a client.  We are simply
reverting to the same behavior we had before for the
NSS Crypto provider case.

Change-Id: I11300b3bea5670c783e1b4736d98f35f30ecf2ce
---
 base/common/python/pki/crypto.py | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/base/common/python/pki/crypto.py b/base/common/python/pki/crypto.py
index 7f03846..edb32c0 100644
--- a/base/common/python/pki/crypto.py
+++ b/base/common/python/pki/crypto.py
@@ -325,9 +325,17 @@ class NSSCryptoProvider(CryptoProvider):
         :param nonce_iv         Nonce data
         :return:                Unwrapped data
 
-        Return unwrapped data for data wrapped using AES KeyWrap
+        Return unwrapped data for data that has been keywrapped.
+        For NSS, we only support 3DES - so something that has been
+        keywrapped can be decrypted.  This is precisely what we used
+        to do before.
         """
-        raise NotImplementedError()
+        return self.symmetric_unwrap(
+            data,
+            wrapping_key,
+            mechanism=nss.CKM_DES3_CBC_PAD,
+            nonce_iv=nonce_iv
+        )
 
     def get_cert(self, cert_nick):
         """
-- 
1.8.3.1


From 3ff9de6a517d7fdcdee6c4a8c884eff052f8f824 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 28 Apr 2017 17:55:17 -0700
Subject: [PATCH 45/49] Ticket #2717 CMC user-signed enrollment request This
 patch provides implementation that allows user-signed CMC requests to be
 processed; The resulting certificate will bear the same subjectDN as that of
 the signing cert; The new uri to access is
 /ca/ee/ca/profileSubmitUserSignedCMCFull where the new profile is to be used:
 caFullCMCUserSignedCert.cfg which utilizes the new authentication plugin:
 CMCUserSignedAuth and new profile default plugin:
 CMCUserSignedSubjectNameDefault and new profile constraint plugin:
 CMCUserSignedSubjectNameConstraint

---
 base/ca/shared/conf/CS.cfg                         |    6 +-
 base/ca/shared/conf/registry.cfg                   |   10 +-
 .../shared/profiles/ca/caFullCMCUserSignedCert.cfg |   83 ++
 base/ca/shared/webapps/ca/WEB-INF/web.xml          |   28 +
 .../certsrv/authentication/IAuthManager.java       |    3 +
 .../com/netscape/certsrv/logging/AuditEvent.java   |    2 +
 .../src/com/netscape/cmstools/CRMFPopClient.java   |    2 +-
 .../cms/authentication/CMCUserSignedAuth.java      | 1140 ++++++++++++++++++++
 .../netscape/cms/profile/common/BasicProfile.java  |   28 +-
 .../netscape/cms/profile/common/EnrollProfile.java |  426 +++++---
 .../CMCUserSignedSubjectNameConstraint.java        |  141 +++
 .../def/CMCUserSignedSubjectNameDefault.java       |  159 +++
 .../netscape/cms/profile/def/EnrollDefault.java    |    5 +-
 .../cms/profile/input/CMCCertReqInput.java         |   21 +-
 .../netscape/cms/profile/input/CertReqInput.java   |   36 +-
 .../servlet/profile/ProfileSubmitCMCServlet.java   |   28 +-
 base/server/cmsbundle/src/LogMessages.properties   |    1 +
 base/server/cmsbundle/src/UserMessages.properties  |    2 +
 18 files changed, 1964 insertions(+), 157 deletions(-)
 create mode 100644 base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg
 create mode 100644 base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
 create mode 100644 base/server/cms/src/com/netscape/cms/profile/constraint/CMCUserSignedSubjectNameConstraint.java
 create mode 100644 base/server/cms/src/com/netscape/cms/profile/def/CMCUserSignedSubjectNameDefault.java

diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
index 3923319..b29802c 100644
--- a/base/ca/shared/conf/CS.cfg
+++ b/base/ca/shared/conf/CS.cfg
@@ -168,6 +168,7 @@ auths.impl._001=## authentication manager implementations
 auths.impl._002=##
 auths.impl.AgentCertAuth.class=com.netscape.cms.authentication.AgentCertAuthentication
 auths.impl.CMCAuth.class=com.netscape.cms.authentication.CMCAuth
+auths.impl.CMCUserSignedAuth.class=com.netscape.cms.authentication.CMCUserSignedAuth
 auths.impl.SSLclientCertAuth.class=com.netscape.cms.authentication.SSLclientCertAuthentication
 auths.impl.UidPwdDirAuth.class=com.netscape.cms.authentication.UidPwdDirAuthentication
 auths.impl.UidPwdPinDirAuth.class=com.netscape.cms.authentication.UidPwdPinDirAuthentication
@@ -734,6 +735,7 @@ ca.publish.rule.instance.LdapXCertRule.publisher=LdapCrossCertPairPublisher
 ca.publish.rule.instance.LdapXCertRule.type=xcert
 cmc.cert.confirmRequired=false
 cmc.lraPopWitness.verify.allow=false
+cmc.popLinkWitnessRequired=false
 cmc.revokeCert.verify=true
 cmc.revokeCert.sharedSecret.class=com.netscape.cms.authentication.SharedSecret
 cmc.sharedSecret.class=com.netscape.cms.authentication.SharedSecret
@@ -905,11 +907,11 @@ log.instance.SignedAudit._001=## Signed Audit Logging
 log.instance.SignedAudit._002=##
 log.instance.SignedAudit._003=##
 log.instance.SignedAudit._004=## Available Audit events:
-log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH_FAILURE,ACCESS_SESSION_ESTABLISH_SUCCESS,ACCESS_SESSION_TERMINATED
+log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH_FAILURE,ACCESS_SESSION_ESTABLISH_SUCCESS,ACCESS_SESSION_TERMINATED
 log.instance.SignedAudit._006=##
 log.instance.SignedAudit.bufferSize=512
 log.instance.SignedAudit.enable=true
-log.instance.SignedAudit.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH_FAILURE,ACCESS_SESSION_ESTABLISH_SUCCESS,ACCESS_SESSION_TERMINATED
+log.instance.SignedAudit.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH_FAILURE,ACCESS_SESSION_ESTABLISH_SUCCESS,ACCESS_SESSION_TERMINATED
 log.instance.SignedAudit.expirationTime=0
 log.instance.SignedAudit.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/signedAudit/ca_audit
 log.instance.SignedAudit.flushInterval=5
diff --git a/base/ca/shared/conf/registry.cfg b/base/ca/shared/conf/registry.cfg
index 2855b7a..519d854 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,validityConstraintImpl,keyUsageExtConstraintImpl,nsCertTypeExtConstraintImpl,extendedKeyUsageExtConstraintImpl,keyConstraintImpl,basicConstraintsExtConstraintImpl,extensionConstraintImpl,signingAlgConstraintImpl,uniqueKeyConstraintImpl,renewGracePeriodConstraintImpl,authzRealmConstraintImpl,externalProcessConstraintImpl
+constraintPolicy.ids=noConstraintImpl,subjectNameConstraintImpl,uniqueSubjectNameConstraintImpl,userSubjectNameConstraintImpl,cmcUserSignedSubjectNameConstraintImpl,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,6 +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.cmcUserSignedSubjectNameConstraintImpl.class=com.netscape.cms.profile.constraint.CMCUserSignedSubjectNameConstraint
+constraintPolicy.cmcUserSignedSubjectNameConstraintImpl.desc=CMC User Subject Name Constraint
+constraintPolicy.cmcUserSignedSubjectNameConstraintImpl.name=CMC User Subject Name Constraint
 constraintPolicy.validityConstraintImpl.class=com.netscape.cms.profile.constraint.ValidityConstraint
 constraintPolicy.validityConstraintImpl.desc=Validity Constraint
 constraintPolicy.validityConstraintImpl.name=Validity Constraint
@@ -48,7 +51,7 @@ constraintPolicy.uniqueKeyConstraintImpl.name=Unique Public Key Constraint
 constraintPolicy.externalProcessConstraintImpl.class=com.netscape.cms.profile.constraint.ExternalProcessConstraint
 constraintPolicy.externalProcessConstraintImpl.desc=External Process Constraint
 constraintPolicy.externalProcessConstraintImpl.name=External Process Constraint
-defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl
+defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,cmcUserSignedSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl
 defaultPolicy.autoAssignDefaultImpl.class=com.netscape.cms.profile.def.AutoAssignDefault
 defaultPolicy.autoAssignDefaultImpl.desc=Auto Request Assignment Default
 defaultPolicy.autoAssignDefaultImpl.name=Auto Request Assignment Default
@@ -67,6 +70,9 @@ defaultPolicy.authTokenSubjectNameDefaultImpl.name=Token Supplied Subject Name D
 defaultPolicy.userSubjectNameDefaultImpl.class=com.netscape.cms.profile.def.UserSubjectNameDefault
 defaultPolicy.userSubjectNameDefaultImpl.desc=User Supplied Subject Name Default
 defaultPolicy.userSubjectNameDefaultImpl.name=User Supplied Subject Name Default
+defaultPolicy.cmcUserSignedSubjectNameDefaultImpl.class=com.netscape.cms.profile.def.CMCUserSignedSubjectNameDefault
+defaultPolicy.cmcUserSignedSubjectNameDefaultImpl.desc=CMC User Signed Subject Name Default
+defaultPolicy.cmcUserSignedSubjectNameDefaultImpl.name=CMC User Signed Subject Name Default
 defaultPolicy.userKeyDefaultImpl.class=com.netscape.cms.profile.def.UserKeyDefault
 defaultPolicy.userKeyDefaultImpl.desc=User Supplied Key Default
 defaultPolicy.userKeyDefaultImpl.name=User Supplied Key Default
diff --git a/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg b/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg
new file mode 100644
index 0000000..229a3cd
--- /dev/null
+++ b/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg
@@ -0,0 +1,83 @@
+desc=This certificate profile is for enrolling user certificates by using the CMC certificate request with user CMC Signature authentication.
+enable=true
+enableBy=admin
+name=User-Signed CMC-Authenticated User Certificate Enrollment
+visible=false
+auth.instance_id=CMCUserSignedAuth
+input.list=i1,i2
+input.i1.class_id=cmcCertReqInputImpl
+input.i2.class_id=submitterInfoInputImpl
+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=cmcUserSignedSubjectNameConstraintImpl
+policyset.cmcUserCertSet.1.constraint.name=CMC User Signed Subject Name Constraint
+policyset.cmcUserCertSet.1.default.class_id=cmcUserSignedSubjectNameDefaultImpl
+policyset.cmcUserCertSet.1.default.name=User Signed 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,nistp256,nistp521
+policyset.cmcUserCertSet.3.constraint.params.keyType=-
+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=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,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/webapps/ca/WEB-INF/web.xml b/base/ca/shared/webapps/ca/WEB-INF/web.xml
index bf8aed4..dc61ab3 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/web.xml
+++ b/base/ca/shared/webapps/ca/WEB-INF/web.xml
@@ -1553,6 +1553,29 @@
    </servlet>
 
    <servlet>
+      <servlet-name>  caProfileSubmitUserSignedCMCFull  </servlet-name>
+      <servlet-class> com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet  </servlet-class>
+             <init-param><param-name>  GetClientCert  </param-name>
+                         <param-value> false       </param-value> </init-param>
+             <init-param><param-name>  cert_request_type  </param-name>
+                         <param-value> cmc         </param-value> </init-param>
+             <init-param><param-name>  profileId   </param-name>
+                         <param-value> caFullCMCUserSignedCert </param-value> </init-param>
+             <init-param><param-name>  AuthzMgr    </param-name>
+                         <param-value> BasicAclAuthz </param-value> </init-param>
+             <init-param><param-name>  authorityId  </param-name>
+                         <param-value> ca          </param-value> </init-param>
+             <init-param><param-name>  ID          </param-name>
+                         <param-value> caProfileSubmitUserSignedCMCFull </param-value> </init-param>
+             <init-param><param-name>  templatePath  </param-name>
+                         <param-value> /ee/ca/ProfileSubmit.template </param-value> </init-param>
+             <init-param><param-name>  resourceID  </param-name>
+                         <param-value> certServer.ee.profile </param-value> </init-param>
+             <init-param><param-name>  interface   </param-name>
+                         <param-value> ee          </param-value> </init-param>
+   </servlet>
+
+   <servlet>
       <servlet-name>  caProfileList  </servlet-name>
       <servlet-class> com.netscape.cms.servlet.profile.ProfileListServlet  </servlet-class>
              <init-param><param-name>  GetClientCert  </param-name>
@@ -2257,6 +2280,11 @@
    </servlet-mapping>
 
    <servlet-mapping>  
+      <servlet-name>  caProfileSubmitUserSignedCMCFull  </servlet-name>
+      <url-pattern>   /ee/ca/profileSubmitUserSignedCMCFull  </url-pattern>
+   </servlet-mapping>
+
+   <servlet-mapping>  
       <servlet-name>  caProfileList  </servlet-name>
       <url-pattern>   /ee/ca/profileList  </url-pattern>
    </servlet-mapping>
diff --git a/base/common/src/com/netscape/certsrv/authentication/IAuthManager.java b/base/common/src/com/netscape/certsrv/authentication/IAuthManager.java
index f9eddbc..21639e2 100644
--- a/base/common/src/com/netscape/certsrv/authentication/IAuthManager.java
+++ b/base/common/src/com/netscape/certsrv/authentication/IAuthManager.java
@@ -31,6 +31,9 @@ public interface IAuthManager {
     /* standard credential for client cert from ssl client auth */
     public static final String CRED_SSL_CLIENT_CERT = "sslClientCert";
 
+    /* standard credential for CMC request signing cert */
+    public static final String CRED_CMC_SIGNING_CERT = "cmcSigningCert";
+
     /**
      * Standard credential for client cert's serial number from revocation.
      */
diff --git a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
index 72c93f8..7a4aa9b 100644
--- a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
+++ b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java
@@ -145,6 +145,8 @@ public class AuditEvent implements IBundleLogEvent {
             "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE_3";
     public final static String CMC_SIGNED_REQUEST_SIG_VERIFY =
             "LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY_5";
+    public final static String CMC_USER_SIGNED_REQUEST_SIG_VERIFY =
+            "LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY_5";
 
     public final static String COMPUTE_RANDOM_DATA_REQUEST =
             "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_2";
diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
index 0168503..d0e5c27 100644
--- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java
@@ -545,7 +545,7 @@ public class CRMFPopClient {
                 pop = client.createPop(algorithm, signature);
             }
 
-            if (verbose) System.out.println("Creating CRMF requrest");
+            if (verbose) System.out.println("Creating CRMF request");
             String request = client.createCRMFRequest(certRequest, pop);
 
             StringWriter sw = new StringWriter();
diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
new file mode 100644
index 0000000..a72ce58
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
@@ -0,0 +1,1140 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+// package statement //
+///////////////////////
+
+package com.netscape.cms.authentication;
+
+///////////////////////
+// import statements //
+///////////////////////
+
+/* cert server imports */
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.PublicKey;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.INTEGER;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
+import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.asn1.SET;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.DigestAlgorithm;
+import org.mozilla.jss.crypto.PrivateKey;
+import org.mozilla.jss.pkcs10.CertificationRequest;
+import org.mozilla.jss.pkcs11.PK11ECPublicKey;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkix.cert.Certificate;
+import org.mozilla.jss.pkix.cert.CertificateInfo;
+import org.mozilla.jss.pkix.cmc.PKIData;
+import org.mozilla.jss.pkix.cmc.TaggedAttribute;
+import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest;
+import org.mozilla.jss.pkix.cmc.TaggedRequest;
+import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
+import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber;
+import org.mozilla.jss.pkix.cms.SignedData;
+import org.mozilla.jss.pkix.cms.SignerIdentifier;
+import org.mozilla.jss.pkix.crmf.CertReqMsg;
+import org.mozilla.jss.pkix.crmf.CertRequest;
+import org.mozilla.jss.pkix.crmf.CertTemplate;
+import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
+import org.mozilla.jss.pkix.primitive.Name;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthToken;
+import com.netscape.certsrv.authentication.EInvalidCredentials;
+import com.netscape.certsrv.authentication.EMissingCredential;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.IExtendedPluginInfo;
+import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.logging.AuditEvent;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.profile.IProfileAuthenticator;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cmsutil.crypto.CryptoUtil;
+import com.netscape.cmsutil.util.Utils;
+
+import netscape.security.pkcs.PKCS10;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+import netscape.security.x509.X509Key;
+
+//import com.netscape.cmscore.util.*;
+//////////////////////
+// class definition //
+//////////////////////
+
+/**
+ * User Signed CMC authentication plug-in
+ * note:
+ *  - this version differs from CMCAuth in that it allows non-agent users
+ *  to sign own cmc requests;  It is expected to be used with
+ *  CMCUserSignedSubjectNameDefault and CMCUserSignedSubjectNameConstraint
+ *  so that the resulting cert will bear the same subjectDN of that of the CMC
+ *  signing cert
+ *  - it originates from CMCAuth with modification for user-signed cmc
+ * @author cfu - user signed cmc authentication
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
+        IProfileAuthenticator {
+
+    ////////////////////////
+    // default parameters //
+    ////////////////////////
+
+    /////////////////////////////
+    // IAuthManager parameters //
+    /////////////////////////////
+
+    /* authentication plug-in configuration store */
+    private IConfigStore mConfig;
+    private static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----";
+    private static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----";
+    public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke";
+    public static final String REASON_CODE = "reasonCode";
+    /* authentication plug-in name */
+    private String mImplName = null;
+
+    /* authentication plug-in instance name */
+    private String mName = null;
+
+    /* authentication plug-in fields */
+
+    /* Holds authentication plug-in fields accepted by this implementation.
+     * This list is passed to the configuration console so configuration
+     * for instances of this implementation can be configured through the
+     * console.
+     */
+    protected static String[] mConfigParams =
+            new String[] {};
+
+    /* authentication plug-in values */
+
+    /* authentication plug-in properties */
+
+    /* required credentials to authenticate. UID and CMC are strings. */
+    public static final String CRED_CMC = "cmcRequest";
+
+    protected static String[] mRequiredCreds = {};
+
+    ////////////////////////////////////
+    // IExtendedPluginInfo parameters //
+    ////////////////////////////////////
+
+    /* Vector of extendedPluginInfo strings */
+    protected static Vector<String> mExtendedPluginInfo = null;
+    //public static final String AGENT_AUTHMGR_ID = "agentAuthMgr";
+    //public static final String AGENT_PLUGIN_ID = "agentAuthPlugin";
+
+    /* actual help messages */
+    static {
+        mExtendedPluginInfo = new Vector<String>();
+
+        mExtendedPluginInfo
+                .add(IExtendedPluginInfo.HELP_TEXT +
+                    ";Authenticate the CMC request. The \"Authentication Instance ID\" must be named \"CMCUserSignedAuth\"");
+        mExtendedPluginInfo.add(IExtendedPluginInfo.HELP_TOKEN +
+                ";configuration-authentication");
+    }
+
+    ///////////////////////
+    // Logger parameters //
+    ///////////////////////
+
+    /* the system's logger */
+    private ILogger mLogger = CMS.getLogger();
+
+    /* signed audit parameters */
+    private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+    private final static String SIGNED_AUDIT_ENROLLMENT_REQUEST_TYPE =
+            "enrollment";
+    private final static String SIGNED_AUDIT_REVOCATION_REQUEST_TYPE =
+            "revocation";
+
+    /////////////////////
+    // default methods //
+    /////////////////////
+
+    /**
+     * Default constructor, initialization must follow.
+     */
+    public CMCUserSignedAuth() {
+    }
+
+    //////////////////////////
+    // IAuthManager methods //
+    //////////////////////////
+
+    /**
+     * Initializes the CMCUserSignedAuth authentication plug-in.
+     * <p>
+     *
+     * @param name The name for this authentication plug-in instance.
+     * @param implName The name of the authentication plug-in.
+     * @param config - The configuration store for this instance.
+     * @exception EBaseException If an error occurs during initialization.
+     */
+    public void init(String name, String implName, IConfigStore config)
+            throws EBaseException {
+        mName = name;
+        mImplName = implName;
+        mConfig = config;
+
+        log(ILogger.LL_INFO, "Initialization complete!");
+    }
+
+    /**
+     * Authenticates user by their CMC;
+     * resulting AuthToken sets a TOKEN_SUBJECT for the subject name.
+     * <P>
+     *
+     * <ul>
+     * <li>signed.audit LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY used when CMC (user-pre-signed) cert
+     * requests or revocation requests are submitted and signature is verified
+     * </ul>
+     *
+     * @param authCred Authentication credentials, CRED_UID and CRED_CMC.
+     * @return an AuthToken
+     * @exception com.netscape.certsrv.authentication.EMissingCredential
+     *                If a required authentication credential is missing.
+     * @exception com.netscape.certsrv.authentication.EInvalidCredentials
+     *                If credentials failed authentication.
+     * @exception com.netscape.certsrv.base.EBaseException
+     *                If an internal error occurred.
+     * @see com.netscape.certsrv.authentication.AuthToken
+     */
+    public IAuthToken authenticate(IAuthCredentials authCred) throws EMissingCredential, EInvalidCredentials,
+            EBaseException {
+        String method = "CMCUserSignedAuth: authenticate: ";
+        CMS.debug(method + "begins");
+
+        String auditMessage = null;
+        String auditSubjectID = auditSubjectID();
+        String auditReqType = ILogger.UNIDENTIFIED;
+        String auditCertSubject = ILogger.UNIDENTIFIED;
+        String auditSignerInfo = ILogger.UNIDENTIFIED;
+
+        // ensure that any low-level exceptions are reported
+        // to the signed audit log and stored as failures
+        try {
+            // get the CMC.
+
+            Object argblock = authCred.getArgBlock();
+            Object returnVal = null;
+            if (argblock == null) {
+                returnVal = authCred.get("cert_request");
+                if (returnVal == null)
+                    returnVal = authCred.get(CRED_CMC);
+            } else {
+                returnVal = authCred.get("cert_request");
+                if (returnVal == null)
+                    returnVal = authCred.getArgBlock().get(CRED_CMC);
+            }
+            String cmc = (String) returnVal;
+            if (cmc == null) {
+                CMS.debug(method + " Authentication failed. Missing CMC.");
+
+                // store a message in the signed audit log file
+                auditMessage = CMS.getLogMessage(
+                        AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                        auditSubjectID,
+                        ILogger.FAILURE,
+                        auditReqType,
+                        auditCertSubject,
+                        auditSignerInfo);
+
+                audit(auditMessage);
+
+                throw new EMissingCredential(CMS.getUserMessage(
+                        "CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CMC));
+            }
+
+            if (cmc.equals("")) {
+                log(ILogger.LL_FAILURE,
+                        "cmc : attempted login with empty CMC.");
+
+                // store a message in the signed audit log file
+                auditMessage = CMS.getLogMessage(
+                        AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                        auditSubjectID,
+                        ILogger.FAILURE,
+                        auditReqType,
+                        auditCertSubject,
+                        auditSignerInfo);
+
+                audit(auditMessage);
+
+                throw new EInvalidCredentials(CMS.getUserMessage(
+                        "CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+            }
+
+            // authenticate by checking CMC.
+
+            // everything OK.
+            // now formulate the certificate info.
+            // set the subject name at a minimum.
+            // set anything else like version, extensions, etc.
+            // if nothing except subject name is set the rest of
+            // cert info will be filled in by policies and CA defaults.
+
+            AuthToken authToken = new AuthToken(this);
+
+            try {
+                String asciiBASE64Blob;
+
+                int startIndex = cmc.indexOf(HEADER);
+                int endIndex = cmc.indexOf(TRAILER);
+                if (startIndex != -1 && endIndex != -1) {
+                    startIndex = startIndex + HEADER.length();
+                    asciiBASE64Blob = cmc.substring(startIndex, endIndex);
+                } else
+                    asciiBASE64Blob = cmc;
+
+                byte[] cmcBlob = CMS.AtoB(asciiBASE64Blob);
+                ByteArrayInputStream cmcBlobIn = new
+                                                 ByteArrayInputStream(cmcBlob);
+
+                org.mozilla.jss.pkix.cms.ContentInfo cmcReq =
+                        (org.mozilla.jss.pkix.cms.ContentInfo)
+                        org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(
+                                cmcBlobIn);
+
+                if (!cmcReq.getContentType().equals(
+                        org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) ||
+                        !cmcReq.hasContent()) {
+                    // store a message in the signed audit log file
+                    auditMessage = CMS.getLogMessage(
+                            AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                            auditSubjectID,
+                            ILogger.FAILURE,
+                            auditReqType,
+                            auditCertSubject,
+                            auditSignerInfo);
+
+                    audit(auditMessage);
+
+                    // throw new ECMSGWException(CMSGWResources.NO_CMC_CONTENT);
+
+                    throw new EBaseException("NO_CMC_CONTENT");
+                }
+
+                SignedData cmcFullReq = (SignedData)
+                                        cmcReq.getInterpretedContent();
+
+                IConfigStore cmc_config = CMS.getConfigStore();
+                boolean checkSignerInfo =
+                        cmc_config.getBoolean("cmc.signerInfo.verify", true);
+                String userid = "defUser";
+                String uid = "defUser";
+                if (checkSignerInfo) {
+                    IAuthToken userToken = verifySignerInfo(authToken, cmcFullReq);
+                    if (userToken == null) {
+                        CMS.debug(method + " authenticate() userToken null");
+                        throw new EBaseException(method + " verifySignerInfo failure");
+                    }
+                    userid = userToken.getInString("userid");
+                    uid = userToken.getInString("cn");
+                } else {
+                    CMS.debug(method + " authenticate() signerInfo verification bypassed");
+                }
+                // reset value of auditSignerInfo
+                if (uid != null) {
+                    auditSignerInfo = uid.trim();
+                }
+
+                EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+
+                OBJECT_IDENTIFIER id = ci.getContentType();
+
+                if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) ||
+                        !ci.hasContent()) {
+                    // store a message in the signed audit log file
+                    auditMessage = CMS.getLogMessage(
+                            AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                            auditSubjectID,
+                            ILogger.FAILURE,
+                            auditReqType,
+                            auditCertSubject,
+                            auditSignerInfo);
+
+                    audit(auditMessage);
+
+                    //  throw new ECMSGWException(
+                    // CMSGWResources.NO_PKIDATA);
+
+                    throw new EBaseException("NO_PKIDATA");
+                }
+
+                OCTET_STRING content = ci.getContent();
+
+                ByteArrayInputStream s = new
+                        ByteArrayInputStream(content.toByteArray());
+                PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+                SEQUENCE reqSequence = pkiData.getReqSequence();
+
+                int numReqs = reqSequence.size();
+
+                if (numReqs == 0) {
+                    CMS.debug(method + "numReqs 0, assume revocation request");
+                    // revocation request
+
+                    // reset value of auditReqType
+                    auditReqType = SIGNED_AUDIT_REVOCATION_REQUEST_TYPE;
+
+                    SEQUENCE controlSequence = pkiData.getControlSequence();
+                    int controlSize = controlSequence.size();
+
+                    if (controlSize > 0) {
+                        for (int i = 0; i < controlSize; i++) {
+                            TaggedAttribute taggedAttribute =
+                                    (TaggedAttribute) controlSequence.elementAt(i);
+                            OBJECT_IDENTIFIER type = taggedAttribute.getType();
+
+                            if (type.equals(
+                                    OBJECT_IDENTIFIER.id_cmc_revokeRequest)) {
+/* TODO: user-signed revocation to be handled in next ticket
+                                // if( i ==1 ) {
+                                //     taggedAttribute.getType() ==
+                                //       OBJECT_IDENTIFIER.id_cmc_revokeRequest
+                                // }
+
+                                SET values = taggedAttribute.getValues();
+                                int numVals = values.size();
+                                BigInteger[] bigIntArray = null;
+
+                                bigIntArray = new BigInteger[numVals];
+                                for (int j = 0; j < numVals; j++) {
+                                    // serialNumber    INTEGER
+
+                                    // SEQUENCE RevRequest = (SEQUENCE)
+                                    //     values.elementAt(j);
+                                    byte[] encoded = ASN1Util.encode(
+                                            values.elementAt(j));
+                                    org.mozilla.jss.asn1.ASN1Template template = new
+                                            org.mozilla.jss.pkix.cmmf.RevRequest.Template();
+                                    org.mozilla.jss.pkix.cmmf.RevRequest revRequest =
+                                            (org.mozilla.jss.pkix.cmmf.RevRequest)
+                                            ASN1Util.decode(template, encoded);
+
+                                    // SEQUENCE RevRequest = (SEQUENCE)
+                                    //     ASN1Util.decode(
+                                    //         SEQUENCE.getTemplate(),
+                                    //         ASN1Util.encode(
+                                    //         values.elementAt(j)));
+
+                                    // SEQUENCE RevRequest =
+                                    //     values.elementAt(j);
+                                    // int revReqSize = RevRequest.size();
+                                    // if( revReqSize > 3 ) {
+                                    //     INTEGER serialNumber =
+                                    //         new INTEGER((long)0);
+                                    // }
+
+                                    INTEGER temp = revRequest.getSerialNumber();
+
+                                    bigIntArray[j] = temp;
+                                    authToken.set(TOKEN_CERT_SERIAL, bigIntArray);
+
+                                    long reasonCode = revRequest.getReason().getValue();
+                                    Integer IntObject = Integer.valueOf((int) reasonCode);
+                                    authToken.set(REASON_CODE, IntObject);
+
+                                    authToken.set("uid", uid);
+                                    authToken.set("userid", userid);
+                                }
+*/
+                            }
+                        }
+
+                    }
+                } else {
+                    CMS.debug(method + "numReqs not 0, assume enrollment request");
+                    // enrollment request
+
+                    // reset value of auditReqType
+                    auditReqType = SIGNED_AUDIT_ENROLLMENT_REQUEST_TYPE;
+
+                    X509CertInfo[] certInfoArray = new X509CertInfo[numReqs];
+                    String[] reqIdArray = new String[numReqs];
+
+                    for (int i = 0; i < numReqs; i++) {
+                        // decode message.
+                        TaggedRequest taggedRequest =
+                                (TaggedRequest) reqSequence.elementAt(i);
+
+                        TaggedRequest.Type type = taggedRequest.getType();
+
+                        if (type.equals(TaggedRequest.PKCS10)) {
+                            CMS.debug(method + " type is PKCS10");
+                            authToken.set("cert_request_type", "cmc-pkcs10");
+
+                            TaggedCertificationRequest tcr =
+                                    taggedRequest.getTcr();
+                            int p10Id = tcr.getBodyPartID().intValue();
+
+                            reqIdArray[i] = String.valueOf(p10Id);
+
+                            CertificationRequest p10 =
+                                    tcr.getCertificationRequest();
+
+                            // transfer to sun class
+                            ByteArrayOutputStream ostream =
+                                    new ByteArrayOutputStream();
+
+                            p10.encode(ostream);
+                            boolean sigver = true;
+                            boolean tokenSwitched = false;
+                            CryptoManager cm = null;
+                            CryptoToken signToken = null;
+                            CryptoToken savedToken = null;
+
+                            // for PKCS10, "sigver" would offer the POP
+                            sigver = CMS.getConfigStore().getBoolean("ca.requestVerify.enabled", true);
+                            try {
+                                cm = CryptoManager.getInstance();
+                                if (sigver == true) {
+                                    String tokenName =
+                                        CMS.getConfigStore().getString("ca.requestVerify.token", CryptoUtil.INTERNAL_TOKEN_NAME);
+                                    savedToken = cm.getThreadToken();
+                                    signToken = CryptoUtil.getCryptoToken(tokenName);
+                                    if (!savedToken.getName().equals(signToken.getName())) {
+                                        cm.setThreadToken(signToken);
+                                        tokenSwitched = true;
+                                    }
+                                }
+
+                                PKCS10 pkcs10 =
+                                        new PKCS10(ostream.toByteArray(), sigver);
+
+                                // xxx do we need to do anything else?
+                                X509CertInfo certInfo =
+                                        CMS.getDefaultX509CertInfo();
+
+                                // fillPKCS10(certInfo,pkcs10,authToken,null);
+
+                                // authToken.set(
+                                //     pkcs10.getSubjectPublicKeyInfo());
+
+                                X500Name tempName = pkcs10.getSubjectName();
+
+                                // reset value of auditCertSubject
+                                if (tempName != null) {
+                                    auditCertSubject =
+                                            tempName.toString().trim();
+                                    if (auditCertSubject.equals("")) {
+                                        auditCertSubject =
+                                                ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+                                    }
+                                    authToken.set(AuthToken.TOKEN_CERT_SUBJECT,
+                                              tempName.toString());
+                                }
+
+                                authToken.set("uid", uid);
+                                authToken.set("userid", userid);
+
+                                certInfoArray[i] = certInfo;
+                            } catch (Exception e) {
+                                // store a message in the signed audit log file
+                                auditMessage = CMS.getLogMessage(
+                                        AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                                        auditSubjectID,
+                                        ILogger.FAILURE,
+                                        auditReqType,
+                                        auditCertSubject,
+                                        auditSignerInfo);
+
+                                audit(auditMessage);
+
+                                //throw new ECMSGWException(
+                                //CMSGWResources.ERROR_PKCS101, e.toString());
+
+                                e.printStackTrace();
+                                throw new EBaseException(e.toString());
+                            } finally {
+                                if ((sigver == true) && (tokenSwitched == true)){
+                                    cm.setThreadToken(savedToken);
+                                }
+                             }
+                        } else if (type.equals(TaggedRequest.CRMF)) {
+
+                            CMS.debug(method + " type is CRMF");
+                            authToken.set("cert_request_type", "cmc-crmf");
+                            try {
+                                CertReqMsg crm =
+                                        taggedRequest.getCrm();
+                                CertRequest certReq = crm.getCertReq();
+                                INTEGER reqID = certReq.getCertReqId();
+                                reqIdArray[i] = reqID.toString();
+                                CertTemplate template = certReq.getCertTemplate();
+                                Name name = template.getSubject();
+
+                                // xxx do we need to do anything else?
+                                X509CertInfo certInfo =
+                                        CMS.getDefaultX509CertInfo();
+
+                                // reset value of auditCertSubject
+                                if (name != null) {
+                                    String ss = name.getRFC1485();
+
+                                    auditCertSubject = ss;
+                                    if (auditCertSubject.equals("")) {
+                                        auditCertSubject =
+                                                ILogger.SIGNED_AUDIT_EMPTY_VALUE;
+                                    }
+
+                                    authToken.set(AuthToken.TOKEN_CERT_SUBJECT, ss);
+                                    authToken.set("uid", uid);
+                                    authToken.set("userid", userid);
+                                }
+                                certInfoArray[i] = certInfo;
+                            } catch (Exception e) {
+                                // store a message in the signed audit log file
+                                auditMessage = CMS.getLogMessage(
+                                        AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                                        auditSubjectID,
+                                        ILogger.FAILURE,
+                                        auditReqType,
+                                        auditCertSubject,
+                                        auditSignerInfo);
+
+                                audit(auditMessage);
+
+                                //throw new ECMSGWException(
+                                //CMSGWResources.ERROR_PKCS101, e.toString());
+
+                                e.printStackTrace();
+                                throw new EBaseException(e.toString());
+                            }
+                        }
+
+                        // authToken.set(AgentAuthentication.CRED_CERT, new
+                        //     com.netscape.certsrv.usrgrp.Certificates(
+                        //     x509Certs));
+                    }
+                }
+            } catch (Exception e) {
+                CMS.debug(method + e);
+                // store a message in the signed audit log file
+                auditMessage = CMS.getLogMessage(
+                        AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                        auditSubjectID,
+                        ILogger.FAILURE,
+                        auditReqType,
+                        auditCertSubject,
+                        auditSignerInfo);
+
+                audit(auditMessage);
+
+                //Debug.printStackTrace(e);
+                throw new EInvalidCredentials(CMS.getUserMessage(
+                        "CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+            }
+
+            // store a message in the signed audit log file
+            auditMessage = CMS.getLogMessage(
+                    AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                    auditSubjectID,
+                    ILogger.SUCCESS,
+                    auditReqType,
+                    auditCertSubject,
+                    auditSignerInfo);
+
+            audit(auditMessage);
+
+            CMS.debug(method + "ends successfully; returning authToken");
+            return authToken;
+        } catch (EMissingCredential eAudit1) {
+            CMS.debug(method + eAudit1);
+            // store a message in the signed audit log file
+            auditMessage = CMS.getLogMessage(
+                    AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                    auditSubjectID,
+                    ILogger.FAILURE,
+                    auditReqType,
+                    auditCertSubject,
+                    auditSignerInfo);
+
+            audit(auditMessage);
+
+            // rethrow the specific exception to be handled later
+            throw eAudit1;
+        } catch (EInvalidCredentials eAudit2) {
+            CMS.debug(method + eAudit2);
+            // store a message in the signed audit log file
+            auditMessage = CMS.getLogMessage(
+                    AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                    auditSubjectID,
+                    ILogger.FAILURE,
+                    auditReqType,
+                    auditCertSubject,
+                    auditSignerInfo);
+
+            audit(auditMessage);
+
+            // rethrow the specific exception to be handled later
+            throw eAudit2;
+        } catch (EBaseException eAudit3) {
+            CMS.debug(method + eAudit3);
+            // store a message in the signed audit log file
+            auditMessage = CMS.getLogMessage(
+                    AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY,
+                    auditSubjectID,
+                    ILogger.FAILURE,
+                    auditReqType,
+                    auditCertSubject,
+                    auditSignerInfo);
+
+            audit(auditMessage);
+
+            // rethrow the specific exception to be handled later
+            throw eAudit3;
+        }
+    }
+
+    /**
+     * Returns a list of configuration parameter names.
+     * The list is passed to the configuration console so instances of
+     * this implementation can be configured through the console.
+     * <p>
+     *
+     * @return String array of configuration parameter names.
+     */
+    public String[] getConfigParams() {
+        return (mConfigParams);
+    }
+
+    /**
+     * gets the configuration substore used by this authentication
+     * plug-in
+     * <p>
+     *
+     * @return configuration store
+     */
+    public IConfigStore getConfigStore() {
+        return mConfig;
+    }
+
+    /**
+     * gets the plug-in name of this authentication plug-in.
+     */
+    public String getImplName() {
+        return mImplName;
+    }
+
+    /**
+     * gets the name of this authentication plug-in instance
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * get the list of required credentials.
+     * <p>
+     *
+     * @return list of required credentials as strings.
+     */
+    public String[] getRequiredCreds() {
+        return (mRequiredCreds);
+    }
+
+    /**
+     * prepares for shutdown.
+     */
+    public void shutdown() {
+    }
+
+    /////////////////////////////////
+    // IExtendedPluginInfo methods //
+    /////////////////////////////////
+
+    /**
+     * Activate the help system.
+     * <p>
+     *
+     * @return help messages
+     */
+    public String[] getExtendedPluginInfo() {
+        String method = "CMCUserSignedAuth: getExtendedPluginInfo: ";
+        CMS.debug(method + " begins");
+        String[] s = Utils.getStringArrayFromVector(mExtendedPluginInfo);
+
+        CMS.debug(method + " s.length = " + s.length);
+        for (int i = 0; i < s.length; i++) {
+            CMS.debug("" + i + " " + s[i]);
+        }
+        return s;
+    }
+
+    ////////////////////
+    // Logger methods //
+    ////////////////////
+
+    /**
+     * Logs a message for this class in the system log file.
+     * <p>
+     *
+     * @param level The log level.
+     * @param msg The message to log.
+     * @see com.netscape.certsrv.logging.ILogger
+     */
+    protected void log(int level, String msg) {
+        if (mLogger == null)
+            return;
+        mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHENTICATION,
+                level, "CMC User Signed Authentication: " + msg);
+    }
+
+    protected IAuthToken verifySignerInfo(AuthToken authToken, SignedData cmcFullReq) throws EBaseException {
+        String method = "CMCUserSignedAuth: verifySignerInfo: ";
+        CMS.debug(method + "begins");
+
+        EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+        OBJECT_IDENTIFIER id = ci.getContentType();
+        OCTET_STRING content = ci.getContent();
+
+        boolean tokenSwitched = false;
+        CryptoToken signToken = null;
+        CryptoToken savedToken = null;
+        CryptoManager cm = null;
+        try {
+            cm = CryptoManager.getInstance();
+            ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
+            PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+
+            SET dais = cmcFullReq.getDigestAlgorithmIdentifiers();
+            int numDig = dais.size();
+            Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>();
+
+            //if request key is used for signing, there MUST be only one signerInfo
+            //object in the signedData object.
+            for (int i = 0; i < numDig; i++) {
+                AlgorithmIdentifier dai =
+                        (AlgorithmIdentifier) dais.elementAt(i);
+                String name =
+                        DigestAlgorithm.fromOID(dai.getOID()).toString();
+
+                MessageDigest md =
+                        MessageDigest.getInstance(name);
+
+                byte[] digest = md.digest(content.toByteArray());
+
+                digs.put(name, digest);
+            }
+
+            SET sis = cmcFullReq.getSignerInfos();
+            int numSis = sis.size();
+
+            for (int i = 0; i < numSis; i++) {
+                org.mozilla.jss.pkix.cms.SignerInfo si = (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i);
+
+                String name = si.getDigestAlgorithm().toString();
+                byte[] digest = digs.get(name);
+
+                if (digest == null) {
+                    MessageDigest md = MessageDigest.getInstance(name);
+                    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+
+                    pkiData.encode(ostream);
+                    digest = md.digest(ostream.toByteArray());
+
+                }
+                // signed  by  previously certified signature key
+                SignerIdentifier sid = si.getSignerIdentifier();
+                // TODO: need to handle signing key being the matching key from
+                // the request
+                if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) {
+                    IssuerAndSerialNumber issuerAndSerialNumber = sid.getIssuerAndSerialNumber();
+                    // find from the certs in the signedData
+                    java.security.cert.X509Certificate cert = null;
+
+                    if (cmcFullReq.hasCertificates()) {
+                        SET certs = cmcFullReq.getCertificates();
+                        int numCerts = certs.size();
+                        java.security.cert.X509Certificate[] x509Certs = new java.security.cert.X509Certificate[1];
+                        byte[] certByteArray = new byte[0];
+                        for (int j = 0; j < numCerts; j++) {
+                            Certificate certJss = (Certificate) certs.elementAt(j);
+                            CertificateInfo certI = certJss.getInfo();
+                            Name issuer = certI.getIssuer();
+
+                            byte[] issuerB = ASN1Util.encode(issuer);
+CMS.debug(method + "issuer = " + new String(issuerB));
+                            INTEGER sn = certI.getSerialNumber();
+                            // if this cert is the signer cert, not a cert in the chain
+                            if (new String(issuerB).equals(new String(
+                                    ASN1Util.encode(issuerAndSerialNumber.getIssuer())))
+                                    && sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) {
+                                ByteArrayOutputStream os = new
+                                        ByteArrayOutputStream();
+
+                                certJss.encode(os);
+                                certByteArray = os.toByteArray();
+
+                                X509CertImpl tempcert = new X509CertImpl(os.toByteArray());
+
+                                cert = tempcert;
+                                x509Certs[0] = cert;
+                                // xxx validate the cert length
+
+                            }
+                        }
+                        CMS.debug(method + "start checking signature");
+                        if (cert == null) {
+                            // find from certDB
+                            CMS.debug(method + "verifying signature");
+                            si.verify(digest, id);
+                        } else {
+                            CMS.debug(method + "found signing cert... verifying");
+                            PublicKey signKey = cert.getPublicKey();
+                            PrivateKey.Type keyType = null;
+                            String alg = signKey.getAlgorithm();
+
+                            PK11PubKey pubK = null;
+                            if (alg.equals("RSA")) {
+                                CMS.debug(method + "signing key alg=RSA");
+                                keyType = PrivateKey.RSA;
+                                pubK = PK11PubKey.fromRaw(keyType, ((X509Key) signKey).getKey());
+                            } else if (alg.equals("EC")) {
+                                CMS.debug(method + "signing key alg=EC");
+                                keyType = PrivateKey.EC;
+                                byte publicKeyData[] = ((X509Key) signKey).getEncoded();
+                                pubK = PK11ECPublicKey.fromSPKI(/*keyType,*/ publicKeyData);
+                            } else {
+                                CMS.debug(method + "unsupported signature algorithm: " + alg);
+                                throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+                            }
+
+                            String tokenName =
+                                CMS.getConfigStore().getString("ca.requestVerify.token", CryptoUtil.INTERNAL_TOKEN_NAME);
+                            // by default JSS will use internal crypto token
+                            if (!CryptoUtil.isInternalToken(tokenName)) {
+                                savedToken = cm.getThreadToken();
+                                signToken = CryptoUtil.getCryptoToken(tokenName);
+                                if(signToken != null) {
+                                    cm.setThreadToken(signToken);
+                                    tokenSwitched = true;
+                                    CMS.debug(method + "verifySignerInfo token switched:"+ tokenName);
+                                } else {
+                                    CMS.debug(method + "verifySignerInfo token not found:"+ tokenName+ ", trying internal");
+                                }
+                            }
+
+                            CMS.debug(method + "verifying signature with public key");
+                            si.verify(digest, id, pubK);
+                        }
+                        CMS.debug(method + "finished checking signature");
+                        // verify signer's certificate using the revocator
+                        if (!cm.isCertValid(certByteArray, true, CryptoManager.CertUsage.SSLClient)) {
+                            CMS.debug(method + "CMC signature failed to be verified");
+                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+                        } else {
+                            CMS.debug(method + "CMC signature verified; but signer not yet;");
+                        }
+                        // At this point, the signature has been verified;
+
+                        IAuthToken tempToken = new AuthToken(null);
+                        netscape.security.x509.X500Name tempPrincipal = (X500Name) x509Certs[0].getSubjectDN();
+                        String CN = tempPrincipal.getCommonName(); //tempToken.get("userid");
+                        CMS.debug(method + " Principal name = " + CN);
+
+                        BigInteger certSerial = x509Certs[0].getSerialNumber();
+                        CMS.debug(method + " verified cert serial=" + certSerial.toString());
+                        authToken.set(IAuthManager.CRED_CMC_SIGNING_CERT, certSerial.toString());
+                        tempToken.set("cn", CN);
+
+                        return tempToken;
+
+                    }
+
+                } else {
+                    CMS.debug(method + "unsupported SignerIdentifier type");
+                }
+            }
+        } catch (InvalidBERException e) {
+            CMS.debug(method + e.toString());
+        } catch (IOException e) {
+            CMS.debug(method + e.toString());
+        } catch (NotInitializedException e) {
+            CMS.debug(method + e.toString());
+        } catch (Exception e) {
+            CMS.debug(method + e.toString());
+            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
+        } finally {
+            if ((tokenSwitched == true) && (savedToken != null)){
+                cm.setThreadToken(savedToken);
+                CMS.debug(method + "verifySignerInfo token restored");
+            }
+        }
+        return null;
+
+    }
+
+    public String[] getExtendedPluginInfo(Locale locale) {
+        return null;
+    }
+
+    // Profile-related methods
+
+    public void init(IProfile profile, IConfigStore config)
+            throws EProfileException {
+    }
+
+    /**
+     * Retrieves the localizable name of this policy.
+     */
+    public String getName(Locale locale) {
+        return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_CMS_SIGN_NAME");
+    }
+
+    /**
+     * Retrieves the localizable description of this policy.
+     */
+    public String getText(Locale locale) {
+        return CMS.getUserMessage(locale, "CMS_AUTHENTICATION_CMS_SIGN_TEXT");
+    }
+
+    /**
+     * Retrieves a list of names of the value parameter.
+     */
+    public Enumeration<String> getValueNames() {
+        Vector<String> v = new Vector<String>();
+        v.addElement("cert_request");
+        return v.elements();
+    }
+
+    public boolean isValueWriteable(String name) {
+        return false;
+    }
+
+    /**
+     * Retrieves the descriptor of the given value
+     * parameter by name.
+     */
+    public IDescriptor getValueDescriptor(Locale locale, String name) {
+        if (name.equals(CRED_CMC)) {
+            return new Descriptor(IDescriptor.STRING_LIST, null, null,
+                    "CMC request");
+        }
+        return null;
+    }
+
+    public void populate(IAuthToken token, IRequest request)
+            throws EProfileException {
+        request.setExtData(IProfileAuthenticator.AUTHENTICATED_NAME,
+                token.getInString(AuthToken.TOKEN_CERT_SUBJECT));
+    }
+
+    public boolean isSSLClientRequired() {
+        return false;
+    }
+
+    /**
+     * Signed Audit Log
+     *
+     * This method is called to store messages to the signed audit log.
+     * <P>
+     *
+     * @param msg signed audit log message
+     */
+    private void audit(String msg) {
+        // in this case, do NOT strip preceding/trailing whitespace
+        // from passed-in String parameters
+
+        if (mSignedAuditLogger == null) {
+            return;
+        }
+
+        mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+                null,
+                ILogger.S_SIGNED_AUDIT,
+                ILogger.LL_SECURITY,
+                msg);
+    }
+
+    protected void audit(AuditEvent event) {
+
+        String template = event.getMessage();
+        Object[] params = event.getParameters();
+
+        String message = CMS.getLogMessage(template, params);
+
+        audit(message);
+    }
+
+    /**
+     * Signed Audit Log Subject ID
+     *
+     * This method is called to obtain the "SubjectID" for
+     * a signed audit log message.
+     * <P>
+     *
+     * @return id string containing the signed audit log message SubjectID
+     */
+    private String auditSubjectID() {
+        // if no signed audit object exists, bail
+        if (mSignedAuditLogger == null) {
+            return null;
+        }
+
+        String subjectID = null;
+
+        // Initialize subjectID
+        SessionContext auditContext = SessionContext.getExistingContext();
+
+        if (auditContext != null) {
+            subjectID = (String)
+                    auditContext.get(SessionContext.USER_ID);
+
+            if (subjectID != null) {
+                subjectID = subjectID.trim();
+            } else {
+                subjectID = ILogger.NONROLEUSER;
+            }
+        } else {
+            subjectID = ILogger.UNIDENTIFIED;
+        }
+
+        return subjectID;
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java
index e6fc045..e47c722 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/BasicProfile.java
@@ -783,6 +783,8 @@ public abstract class BasicProfile implements IProfile {
             boolean createConfig)
             throws EProfileException {
 
+        String method = "BasicProfile: createProfilePolicy: ";
+        CMS.debug(method + "begins");
         // String setId ex: policyset.set1
         // String id    Id of policy : examples: p1,p2,p3
         // String defaultClassId : id of the default plugin ex: validityDefaultImpl
@@ -911,19 +913,18 @@ public abstract class BasicProfile implements IProfile {
                 }
             }
         }
-
         String defaultRoot = id + "." + PROP_DEFAULT;
         String constraintRoot = id + "." + PROP_CONSTRAINT;
         IPluginInfo defInfo = mRegistry.getPluginInfo("defaultPolicy",
                 defaultClassId);
 
         if (defInfo == null) {
-            CMS.debug("BasicProfile: Cannot find " + defaultClassId);
+            CMS.debug(method + " Cannot find " + defaultClassId);
             throw new EProfileException("Cannot find " + defaultClassId);
         }
         String defaultClass = defInfo.getClassName();
 
-        CMS.debug("BasicProfile: loading default class " + defaultClass);
+        CMS.debug(method + " loading default class " + defaultClass);
         IPolicyDefault def = null;
 
         try {
@@ -931,7 +932,7 @@ public abstract class BasicProfile implements IProfile {
                     Class.forName(defaultClass).newInstance();
         } catch (Exception e) {
             // throw Exception
-            CMS.debug("BasicProfile: default policy " +
+            CMS.debug(method + " default policy " +
                     defaultClass + " " + e.toString());
         }
         if (def == null) {
@@ -941,24 +942,30 @@ public abstract class BasicProfile implements IProfile {
 
             defStore = policyStore.getSubStore(defaultRoot);
             def.init(this, defStore);
+            CMS.debug(method + " default class initialized.");
         }
 
         IPluginInfo conInfo = mRegistry.getPluginInfo("constraintPolicy",
                 constraintClassId);
+        if (conInfo == null) {
+            CMS.debug(method + " Cannot find " + constraintClassId);
+            throw new EProfileException("Cannot find " + constraintClassId);
+        }
         String constraintClass = conInfo.getClassName();
-        IPolicyConstraint constraint = null;
 
+        CMS.debug(method + " loading constraint class " + constraintClass);
+        IPolicyConstraint constraint = null;
         try {
             constraint = (IPolicyConstraint)
                     Class.forName(constraintClass).newInstance();
         } catch (Exception e) {
             // throw Exception
-            CMS.debug("BasicProfile: constraint policy " +
+            CMS.debug(method + " constraint policy " +
                     constraintClass + " " + e.toString());
         }
         ProfilePolicy policy = null;
         if (constraint == null) {
-            CMS.debug("BasicProfile: failed to create " + constraintClass);
+            CMS.debug(method + " failed to create " + constraintClass);
         } else {
             IConfigStore conStore = null;
 
@@ -966,9 +973,11 @@ public abstract class BasicProfile implements IProfile {
             constraint.init(this, conStore);
             policy = new ProfilePolicy(id, def, constraint);
             policies.addElement(policy);
+            CMS.debug(method + " constraint class initialized.");
         }
 
         if (createConfig) {
+            CMS.debug(method + " createConfig true; creating...");
             String list = null;
 
             try {
@@ -996,8 +1005,10 @@ public abstract class BasicProfile implements IProfile {
                 CMS.debug("BasicProfile: commiting config store " +
                         e.toString());
             }
+            CMS.debug(method + " config created.");
         }
 
+        CMS.debug(method + "ends");
         return policy;
     }
 
@@ -1091,9 +1102,10 @@ public abstract class BasicProfile implements IProfile {
      */
     public void populate(IRequest request)
             throws EProfileException {
+        String method = "BasicProfile: populate: ";
         String setId = getPolicySetId(request);
         Vector<IProfilePolicy> policies = getPolicies(setId);
-        CMS.debug("BasicProfile: populate() policy setid =" + setId);
+        CMS.debug(method + "policy setid =" + setId);
 
         for (int i = 0; i < policies.size(); i++) {
             IProfilePolicy policy = policies.elementAt(i);
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
index 1c44e2c..57f07d1 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -71,6 +71,7 @@ import org.mozilla.jss.pkix.primitive.Name;
 import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
 
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authentication.ISharedToken;
 import com.netscape.certsrv.authority.IAuthority;
@@ -110,6 +111,7 @@ import netscape.security.x509.CertificateX509Key;
 import netscape.security.x509.Extension;
 import netscape.security.x509.Extensions;
 import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertImpl;
 import netscape.security.x509.X509CertInfo;
 import netscape.security.x509.X509Key;
 
@@ -144,7 +146,8 @@ public abstract class EnrollProfile extends BasicProfile
      */
     public IRequest[] createRequests(IProfileContext ctx, Locale locale)
             throws EProfileException {
-        String method = "EnrollProfile: createRequests";
+
+        String method = "EnrollProfile: createRequests: ";
         CMS.debug(method + "begins");
 
         // determine how many requests should be created
@@ -171,13 +174,20 @@ public abstract class EnrollProfile extends BasicProfile
         }
         TaggedRequest[] cmc_msgs = null;
         if (cert_request_type != null && cert_request_type.startsWith("cmc")) {
-            /*
-             * TODO: cfu: Phase 2: check if CMCAuth pre-signed request passed.
-             *     if not, identityProofV2 and/or identification controls
-             *     are required;
-             */
+
+            // donePOI true means Proof-Of-Identity is already done.
+            // if the auth manager is the CMCUserSignedAuth, then
+            // the new cert will eventually have the same subject as the
+            // user signing cert
+            // if the auth manager is the CMCAuth (agent pre-approved),
+            // then no changes
+            boolean donePOI = false;
+            String signingUserSerial = ctx.get(IAuthManager.CRED_CMC_SIGNING_CERT);
+            if (signingUserSerial != null) {
+                donePOI = true;
+            }
             // catch for invalid request
-            cmc_msgs = parseCMC(locale, cert_request);
+            cmc_msgs = parseCMC(locale, cert_request, donePOI);
             if (cmc_msgs == null) {
                 CMS.debug(method + "parseCMC returns cmc_msgs null");
                 return null;
@@ -209,7 +219,7 @@ public abstract class EnrollProfile extends BasicProfile
             } else {
                 result[i].setExtData(REQUEST_SEQ_NUM, Integer.valueOf(i));
                 if ((cmc_msgs != null) && (cmc_msgs[i] != null)) {
-                    CMS.debug("EnrollProfile: createRequests: setting cmc TaggedRequest in request");
+                    CMS.debug(method + "setting cmc TaggedRequest in request");
                     result[i].setExtData(
                             CTX_CERT_REQUEST,
                             ASN1Util.encode(cmc_msgs[i]));
@@ -221,9 +231,6 @@ public abstract class EnrollProfile extends BasicProfile
 
             // set requested CA
             result[i].setExtData(IRequest.AUTHORITY_ID, ctx.get(REQUEST_AUTHORITY_ID));
-
-            // set user data
-            result[i].setExtData(IRequest.USER_DATA, ctx.get(REQUEST_USER_DATA));
         }
         return result;
     }
@@ -300,7 +307,7 @@ public abstract class EnrollProfile extends BasicProfile
             req.setExtData(REQUEST_EXTENSIONS,
                     new CertificateExtensions());
 
-            CMS.debug("EnrollProfile: createRequest " +
+            CMS.debug("EnrollProfile: createEnrollmentRequest " +
                     req.getRequestId());
         } catch (EBaseException e) {
             // raise exception?
@@ -469,6 +476,7 @@ public abstract class EnrollProfile extends BasicProfile
 
         IRequestQueue queue = getRequestQueue();
         String msg = "";
+        CMS.debug(method + "begins");
 
         boolean popChallengeRequired =
                 request.getExtDataInBoolean("cmc_POPchallengeRequired", false);
@@ -485,7 +493,7 @@ public abstract class EnrollProfile extends BasicProfile
         }
 
         if (token == null){
-            CMS.debug(method + " auth token is null");
+            CMS.debug(method + " auth token is null; agent manual approval required;");
             CMS.debug(method + " validating request");
             validate(request);
             try {
@@ -500,6 +508,7 @@ public abstract class EnrollProfile extends BasicProfile
             // this is encryptedPOP case; defer to require decryptedPOP
             CMS.debug(method + " popChallengeRequired, defer to enforce decryptedPOP");
             validate(request);
+
             CMS.debug(method + " about to call setPOPchallenge");
             try {
                 setPOPchallenge(request);
@@ -521,40 +530,38 @@ public abstract class EnrollProfile extends BasicProfile
         }
     }
 
-    /*
-     * parseCMC
-     * @throws EProfileException in case of error
-     *   note: returing "null" doesn't mean failure
+    /**
+     * getPKIDataFromCMCblob
+     *
+     * @param certReqBlob cmc b64 encoded blob
+     * @return PKIData
      */
-    public TaggedRequest[] parseCMC(Locale locale, String certreq)
+    public PKIData getPKIDataFromCMCblob(Locale locale, String certReqBlob)
             throws EProfileException {
 
-        String method = "EnrollProfile: parseCMC: ";
+        String method = "EnrollProfile: getPKIDataFromCMCblob: ";
         String msg = ""; // for capturing debug and throw info
 
         /* cert request must not be null */
-        if (certreq == null) {
-            msg = method + "certreq null";
+        if (certReqBlob == null) {
+            msg = method + "certReqBlob null";
             CMS.debug(msg);
             throw new EProfileException(
                     CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") +
                             msg);
         }
-        //CMS.debug(method + " Start parseCMC(): " + certreq);
+        //CMS.debug(method + " Start: " + certReqBlob);
         CMS.debug(method + "starts");
 
-        TaggedRequest msgs[] = null;
-
-        String creq = normalizeCertReq(certreq);
+        String creq = normalizeCertReq(certReqBlob);
         try {
             byte data[] = CMS.AtoB(creq);
-            ByteArrayInputStream cmcBlobIn =
-                    new ByteArrayInputStream(data);
+            ByteArrayInputStream cmcBlobIn = new ByteArrayInputStream(data);
 
-            org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo)
-                    org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn);
-            org.mozilla.jss.pkix.cms.SignedData cmcFullReq =
-                (org.mozilla.jss.pkix.cms.SignedData) cmcReq.getInterpretedContent();
+            org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo) org.mozilla.jss.pkix.cms.ContentInfo
+                    .getTemplate().decode(cmcBlobIn);
+            org.mozilla.jss.pkix.cms.SignedData cmcFullReq = (org.mozilla.jss.pkix.cms.SignedData) cmcReq
+                    .getInterpretedContent();
             org.mozilla.jss.pkix.cms.EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
             OCTET_STRING content = ci.getContent();
 
@@ -564,6 +571,104 @@ public abstract class EnrollProfile extends BasicProfile
             mCMCData = pkiData;
             //PKIData pkiData = (PKIData)
             //    (new PKIData.Template()).decode(cmcBlobIn);
+
+            return pkiData;
+        } catch (Exception e) {
+            CMS.debug(method + e);
+            throw new EProfileException(
+                    CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"), e);
+        }
+    }
+
+    public static CertificateSubjectName getCMCSigningCertSNfromCertSerial(
+            String certSerial) throws Exception {
+        X509CertImpl userCert = getCMCSigningCertFromCertSerial(certSerial);
+
+        if (userCert != null) {
+            return userCert.getSubjectObj();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * getCMCSigningCertFromCertSerial is to be used when authentication
+     * was done with CMCUserSignedAuth where the resulting
+     * authToken contains
+     * IAuthManager.CRED_CMC_SIGNING_CERT, serial number
+     * This method takes the serial number
+     * and finds the cert from the CA's certdb
+     */
+    public static X509CertImpl getCMCSigningCertFromCertSerial(
+            String certSerial) throws Exception {
+        String method = "EnrollProfile: getCMCSigningCertFromCertSerial: ";
+        String msg = "";
+
+        X509CertImpl userCert = null;
+
+        if (certSerial == null || certSerial.equals("")) {
+            msg = method + "certSerial empty";
+            CMS.debug(msg);
+            throw new Exception(msg);
+        }
+
+        // for CMCUserSignedAuth, the signing user is the subject of
+        // the new cert
+        ICertificateAuthority authority = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+        try {
+            BigInteger serialNo = new BigInteger(certSerial);
+            userCert = authority.getCertificateRepository().getX509Certificate(serialNo);
+        } catch (NumberFormatException e) {
+            msg = method + e;
+            CMS.debug(msg);
+            throw new Exception(msg);
+        } catch (EBaseException e) {
+            msg = method + e + "; signing user cert not found: serial=" + certSerial;
+            CMS.debug(msg);
+            throw new Exception(msg);
+        }
+
+        if (userCert != null) {
+            msg = method + "signing user cert found; serial=" + certSerial;
+            CMS.debug(msg);
+        } else {
+            msg = method + "signing user cert not found: serial=" + certSerial;
+            CMS.debug(msg);
+            throw new Exception(msg);
+        }
+
+        return userCert;
+    }
+
+    /*
+     * parseCMC
+     * @throws EProfileException in case of error
+     *   note: returing "null" doesn't mean failure
+     */
+    public TaggedRequest[] parseCMC(Locale locale, String certreq)
+            throws EProfileException {
+        return parseCMC(locale, certreq, false);
+    }
+    public TaggedRequest[] parseCMC(Locale locale, String certreq, boolean donePOI)
+            throws EProfileException {
+
+        String method = "EnrollProfile: parseCMC: ";
+        String msg = ""; // for capturing debug and throw info
+        //CMS.debug(method + " Start parseCMC(): " + certreq);
+        CMS.debug(method + "starts");
+
+        /* cert request must not be null */
+        if (certreq == null) {
+            msg = method + "certreq null";
+            CMS.debug(msg);
+            throw new EProfileException(
+                    CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") +
+                            msg);
+        }
+
+        TaggedRequest msgs[] = null;
+        try {
+            PKIData pkiData = getPKIDataFromCMCblob(locale, certreq);
             SEQUENCE controlSeq = pkiData.getControlSequence();
             int numcontrols = controlSeq.size();
             SEQUENCE reqSeq = pkiData.getReqSequence();
@@ -571,6 +676,7 @@ public abstract class EnrollProfile extends BasicProfile
             UTF8String ident_s = null;
             SessionContext context = SessionContext.getContext();
             if (!context.containsKey("numOfControls")) {
+                CMS.debug(method + "numcontrols="+ numcontrols);
                 if (numcontrols > 0) {
                     context.put("numOfControls", Integer.valueOf(numcontrols));
                     TaggedAttribute[] attributes = new TaggedAttribute[numcontrols];
@@ -587,56 +693,45 @@ public abstract class EnrollProfile extends BasicProfile
                     boolean id_cmc_idPOPLinkRandom = false;
                     SET vals = null;
 
+                    /**
+                     * pre-process all controls --
+                     * the postponed processing is so that we can capture
+                     * the identification, if included
+                     */
+                    CMS.debug(method + "about to pre-process controls");
                     for (int i = 0; i < numcontrols; i++) {
                         attributes[i] = (TaggedAttribute) controlSeq.elementAt(i);
                         OBJECT_IDENTIFIER oid = attributes[i].getType();
                         if (oid.equals(OBJECT_IDENTIFIER.id_cmc_decryptedPOP)) {
-                            CMS.debug(method + " decryptedPOP found");
+                            CMS.debug(method + " id_cmc_decryptedPOP found");
                             id_cmc_decryptedPOP = true;
                             decPopVals = attributes[i].getValues();
                         } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_identification)) {
+                            CMS.debug(method + " id_cmc_identification found");
                             id_cmc_identification = true;
                             ident = attributes[i].getValues();
                         } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_identityProofV2)) {
+                            CMS.debug(method + " id_cmc_identityProofV2 found");
                             id_cmc_identityProofV2 = true;
                             attr = attributes[i];
                         } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_identityProof)) {
+                            CMS.debug(method + " id_cmc_identityProof found");
                             id_cmc_identityProof = true;
                             attr = attributes[i];
                         } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_idPOPLinkRandom)) {
-                            CMS.debug(method + "id_cmc_idPOPLinkRandom true");
+                            CMS.debug(method + "id_cmc_idPOPLinkRandom found");
                             id_cmc_idPOPLinkRandom = true;
                             vals = attributes[i].getValues();
                         } else {
+                            CMS.debug(method + "unknown control found");
                             context.put(attributes[i].getType(), attributes[i]);
                         }
                     } //for
 
                     /**
                      * now do the actual control processing
-                     * (the postponed processing is so that we can capture
-                     * the identification, if included)
                      */
-
-                    if (id_cmc_decryptedPOP) {
-                        if (decPopVals != null) {
-
-                            DecryptedPOP decPop = (DecryptedPOP) (ASN1Util.decode(DecryptedPOP.getTemplate(),
-                                    ASN1Util.encode(decPopVals.elementAt(0))));
-                            CMS.debug(method + "DecryptedPOP encoded");
-
-                            Integer reqId = verifyDecryptedPOP(locale, decPop);
-                            if (reqId != null) {
-                                context.put("decryptedPopReqId", reqId);
-                            }
-                        } else { //decPopVals == null
-                            msg = "id_cmc_decryptedPOP contains invalid DecryptedPOP";
-                            CMS.debug(method + msg);
-                            SEQUENCE bpids = getRequestBpids(reqSeq);
-                            context.put("decryptedPOP", bpids);
-                        }
-                        return null;
-                    }
+                    CMS.debug(method + "processing controls...");
 
                     if (id_cmc_identification) {
                         if (ident == null) {
@@ -666,8 +761,22 @@ public abstract class EnrollProfile extends BasicProfile
                         }
                     }
 
-                    // either V2 or not V2; can't be both
-                    if (id_cmc_identityProofV2 && (attr != null)) {
+                    // checking Proof Of Identity, if not pre-signed
+
+                    if (donePOI) {
+                        // for logging purposes
+                        if (id_cmc_identityProofV2) {
+                            CMS.debug(method
+                                    + "pre-signed CMC request, but id_cmc_identityProofV2 found...ignore; no further proof of identification check");
+                        } else if (id_cmc_identityProof) {
+                            CMS.debug(method
+                                    + "pre-signed CMC request, but id_cmc_identityProof found...ignore; no further proof of identification check");
+                        } else {
+                            CMS.debug(method + "pre-signed CMC request; no further proof of identification check");
+                        }
+                    } else if (id_cmc_identityProofV2 && (attr != null)) {
+                        // either V2 or not V2; can't be both
+                        CMS.debug(method + "not pre-signed CMC request; calling verifyIdentityProofV2;");
                         if (!id_cmc_identification) {
                             SEQUENCE bpids = getRequestBpids(reqSeq);
                             context.put("identification", bpids);
@@ -685,23 +794,57 @@ public abstract class EnrollProfile extends BasicProfile
                             SEQUENCE bpids = getRequestBpids(reqSeq);
                             context.put("identityProofV2", bpids);
 
-                            msg = " in verifyIdentityProofV2";
+                            msg = " after verifyIdentityProofV2";
                             CMS.debug(method + msg);
                             throw new EProfileException(CMS.getUserMessage(locale,
-                                    "CMS_POI_VERIFICATION_ERROR")+ msg);
+                                    "CMS_POI_VERIFICATION_ERROR") + msg);
+                        } else {
+                            CMS.debug(method + "passed verifyIdentityProofV2; Proof of Identity successful;");
                         }
                     } else if (id_cmc_identityProof && (attr != null)) {
+                        CMS.debug(method + "not pre-signed CMC request; calling verifyIdentityProof;");
                         boolean valid = verifyIdentityProof(attr,
                                 reqSeq);
                         if (!valid) {
                             SEQUENCE bpids = getRequestBpids(reqSeq);
                             context.put("identityProof", bpids);
 
-                            msg = " in verifyIdentityProof";
+                            msg = " after verifyIdentityProof";
                             CMS.debug(method + msg);
                             throw new EProfileException(CMS.getUserMessage(locale,
-                                    "CMS_POI_VERIFICATION_ERROR")+ msg);
+                                    "CMS_POI_VERIFICATION_ERROR") + msg);
+                        } else {
+                            CMS.debug(method + "passed verifyIdentityProof; Proof of Identity successful;");
                         }
+                    } else {
+                        msg = "not pre-signed CMC request; missing Proof of Identification control";
+                        CMS.debug(method + msg);
+                        throw new EProfileException(CMS.getUserMessage(locale,
+                                "CMS_POI_VERIFICATION_ERROR") + ":" + method + msg);
+                    }
+
+                    if (id_cmc_decryptedPOP) {
+                        if (decPopVals != null) {
+
+                            DecryptedPOP decPop = (DecryptedPOP) (ASN1Util.decode(DecryptedPOP.getTemplate(),
+                                    ASN1Util.encode(decPopVals.elementAt(0))));
+                            CMS.debug(method + "DecryptedPOP encoded");
+
+                            Integer reqId = verifyDecryptedPOP(locale, decPop);
+                            if (reqId != null) {
+                                context.put("cmcDecryptedPopReqId", reqId);
+                            }
+                        } else { //decPopVals == null
+                            msg = "id_cmc_decryptedPOP contains invalid DecryptedPOP";
+                            CMS.debug(method + msg);
+                            SEQUENCE bpids = getRequestBpids(reqSeq);
+                            context.put("decryptedPOP", bpids);
+                        }
+
+                        // decryptedPOP is expected to return null;
+                        // POPLinkWitnessV2 would have to be checked in
+                        // round one, if required
+                        return null;
                     }
 
                     if (id_cmc_idPOPLinkRandom && vals != null) {
@@ -725,61 +868,65 @@ public abstract class EnrollProfile extends BasicProfile
                 }
             }
 
-            int nummsgs = reqSeq.size();
-            if (nummsgs > 0) {
+            /**
+             * in CS.cfg, cmc.popLinkWitnessRequired=true
+             * will enforce popLinkWitness (or V2);
+             */
+            boolean popLinkWitnessRequired = false;
+            try {
+                String configName = "cmc.popLinkWitnessRequired";
+                CMS.debug(method + "getting :" + configName);
+                popLinkWitnessRequired = CMS.getConfigStore().getBoolean(configName, false);
+            } catch (Exception e) {
+                // unlikely to get here
+                msg = method + " Failed to retrieve cmc.popLinkWitnessRequired";
+                CMS.debug(msg);
+                throw new EProfileException(method + msg);
+            }
 
+            int nummsgs = reqSeq.size();
+            if (!popLinkWitnessRequired) {
+                CMS.debug(method + "popLinkWitnessRequired false, skip check");
+            } else if (nummsgs > 0) {
+                CMS.debug(method + "cmc.popLinkWitnessRequired is true");
+                CMS.debug(method + "nummsgs =" + nummsgs);
                 msgs = new TaggedRequest[reqSeq.size()];
                 SEQUENCE bpids = new SEQUENCE();
 
-                /* TODO: add this in CS.cfg later: cmc.popLinkWitnessRequired=true
-                // enforce popLinkWitness (or V2)
-                boolean popLinkWitnessRequired = true;
-                try {
-                    String configName = "cmc.popLinkWitnessRequired";
-                    CMS.debug(method + "getting :" + configName);
-                    popLinkWitnessRequired = CMS.getConfigStore().getBoolean(configName, true);
-                    CMS.debug(method + "cmc.popLinkWitnessRequired is " + popLinkWitnessRequired);
-                } catch (Exception e) {
-                    // unlikely to get here
-                    msg = method + " Failed to retrieve cmc.popLinkWitnessRequired";
-                    CMS.debug(msg);
-                    throw new EProfileException(method + msg);
-                }
-*/
-
                 boolean valid = true;
                 for (int i = 0; i < nummsgs; i++) {
                     msgs[i] = (TaggedRequest) reqSeq.elementAt(i);
                     if (!context.containsKey("POPLinkWitnessV2") &&
                             !context.containsKey("POPLinkWitness")) {
-                        if (randomSeed != null) {
-                            // verifyPOPLinkWitness() will determine if this is
-                            // POPLinkWitnessV2 or POPLinkWitness
-                            // If failure, context is set in verifyPOPLinkWitness
-                            valid = verifyPOPLinkWitness(ident_s, randomSeed, msgs[i], bpids, context);
-                            if (valid == false) {
-                                if (context.containsKey("POPLinkWitnessV2"))
-                                    msg = " in POPLinkWitnessV2";
-                                else if (context.containsKey("POPLinkWitness"))
-                                    msg = " in POPLinkWitness";
-                                else
-                                    msg = " unspecified failure from verifyPOPLinkWitness";
-
-                                CMS.debug(method + msg);
-                                throw new EProfileException(CMS.getUserMessage(locale,
-                                        "MS_POP_LINK_WITNESS_VERIFICATION_ERROR")+ msg);
-                            }
-                        /* TODO: for next cmc ticket, eliminate the extra trip of parseCMC if possible, or figure a way out to bypass this on 2nd trip
-                        } else if (popLinkWitnessRequired == true) {
-                            //popLinkWitnessRequired == true, must have randomSeed
-                            CMS.debug(method + "popLinkWitness(V2) required; no randomSeed found");
+                        CMS.debug(method + "popLinkWitness(V2) required");
+                        if (randomSeed == null) {
+                            CMS.debug(method + "no randomSeed found");
                             context.put("POPLinkWitnessV2", bpids);
-                            return null;*/
-                        } //randomSeed != null
+                            return null;
+                        }
+
+                        // verifyPOPLinkWitness() will determine if this is
+                        // POPLinkWitnessV2 or POPLinkWitness
+                        // If failure, context is set in verifyPOPLinkWitness
+                        valid = verifyPOPLinkWitness(ident_s, randomSeed, msgs[i], bpids, context);
+                        if (valid == false) {
+                            if (context.containsKey("POPLinkWitnessV2"))
+                                msg = " in POPLinkWitnessV2";
+                            else if (context.containsKey("POPLinkWitness"))
+                                msg = " in POPLinkWitness";
+                            else
+                                msg = " unspecified failure from verifyPOPLinkWitness";
+
+                            CMS.debug(method + msg);
+                            throw new EProfileException(CMS.getUserMessage(locale,
+                                    "CMS_POP_LINK_WITNESS_VERIFICATION_ERROR") + msg);
+                        }
                     }
-                }
-            } else
+                } //for
+            } else {
+                CMS.debug(method + "nummsgs 0; returning...");
                 return null;
+            }
 
             CMS.debug(method + "ends");
             return msgs;
@@ -1398,6 +1545,9 @@ public abstract class EnrollProfile extends BasicProfile
     public void fillTaggedRequest(Locale locale, TaggedRequest tagreq, X509CertInfo info,
             IRequest req)
             throws EProfileException {
+        String auditMessage = null;
+        String auditSubjectID = auditSubjectID();
+
         String method = "EnrollProfile: fillTaggedRequest: ";
         CMS.debug(method + "begins");
         TaggedRequest.Type type = tagreq.getType();
@@ -1409,16 +1559,19 @@ public abstract class EnrollProfile extends BasicProfile
         }
 
         if (type.equals(TaggedRequest.PKCS10)) {
-            CMS.debug(method + " TaggedRequest type == pkcs10");
+            String methodPos = method + "PKCS10: ";
+            CMS.debug(methodPos + " TaggedRequest type == pkcs10");
             boolean sigver = true;
             boolean tokenSwitched = false;
             CryptoManager cm = null;
             CryptoToken signToken = null;
             CryptoToken savedToken = null;
             try {
+                // for PKCS10, "sigver" would provide the POP
                 sigver = CMS.getConfigStore().getBoolean("ca.requestVerify.enabled", true);
                 cm = CryptoManager.getInstance();
                 if (sigver == true) {
+                    CMS.debug(methodPos + "sigver true, POP is to be verified");
                     String tokenName =
                         CMS.getConfigStore().getString("ca.requestVerify.token", CryptoUtil.INTERNAL_TOKEN_NAME);
                     savedToken = cm.getThreadToken();
@@ -1427,6 +1580,12 @@ public abstract class EnrollProfile extends BasicProfile
                         cm.setThreadToken(signToken);
                         tokenSwitched = true;
                     }
+                } else {
+                    // normally, you would not get here, as you almost always
+                    // would want to verify the PKCS10 signature when it's
+                    // already there instead of taking a 2nd trip
+                    CMS.debug(methodPos + "sigver false, POP is not to be verified now, but instead will be challenged");
+                    req.setExtData("cmc_POPchallengeRequired", "true");
                 }
 
                 TaggedCertificationRequest tcr = tagreq.getTcr();
@@ -1440,13 +1599,17 @@ public abstract class EnrollProfile extends BasicProfile
                 fillPKCS10(locale, pkcs10, info, req);
             } catch (Exception e) {
                 CMS.debug(method + e);
+                // this will throw
+                popFailed(locale, auditSubjectID, auditMessage, e);
             }  finally {
                 if ((sigver == true) && (tokenSwitched == true)){
                     cm.setThreadToken(savedToken);
                 }
             }
+            CMS.debug(methodPos + "done");
         } else if (type.equals(TaggedRequest.CRMF)) {
-            CMS.debug(method + " TaggedRequest type == crmf");
+            String methodPos = method + "CRMF: ";
+            CMS.debug(methodPos + " TaggedRequest type == crmf");
             CertReqMsg crm = tagreq.getCrm();
             SessionContext context = SessionContext.getContext();
             Integer nums = (Integer) (context.get("numOfControls"));
@@ -1454,12 +1617,12 @@ public abstract class EnrollProfile extends BasicProfile
             boolean verifyAllow = false; //disable RA by default
             try {
                 String configName = "cmc.lraPopWitness.verify.allow";
-                CMS.debug(method + "getting :" + configName);
+                CMS.debug(methodPos + "getting :" + configName);
                 verifyAllow = CMS.getConfigStore().getBoolean(configName, false);
-                CMS.debug(method + "cmc.lraPopWitness.verify.allow is " + verifyAllow);
+                CMS.debug(methodPos + "cmc.lraPopWitness.verify.allow is " + verifyAllow);
             } catch (Exception e) {
                 // unlikely to get here
-                String msg = method + " Failed to retrieve cmc.lraPopWitness.verify.allow";
+                String msg = methodPos + " Failed to retrieve cmc.lraPopWitness.verify.allow";
                 CMS.debug(msg);
                 throw new EProfileException(method + msg);
             }
@@ -1471,23 +1634,23 @@ public abstract class EnrollProfile extends BasicProfile
                         parseLRAPopWitness(locale, crm, attr);
                     } else {
                         CMS.debug(
-                                method + " verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
+                                methodPos + " verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
                         if (crm.hasPop()) {
-                            CMS.debug(method + " hasPop true");
+                            CMS.debug(methodPos + " hasPop true");
                             verifyPOP(locale, crm);
                         } else { // no signing POP, then do it the hard way
-                            CMS.debug(method + "hasPop false, need to challenge");
+                            CMS.debug(methodPos + "hasPop false, need to challenge");
                             req.setExtData("cmc_POPchallengeRequired", "true");
                         }
                     }
                 } else {
                     CMS.debug(
-                            method + " verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
+                            methodPos + " verify POP in CMC because LRA POP Witness control attribute doesnt exist in the CMC request.");
                     if (crm.hasPop()) {
-                        CMS.debug(method + " hasPop true");
+                        CMS.debug(methodPos + " hasPop true");
                         verifyPOP(locale, crm);
                     } else { // no signing POP, then do it the hard way
-                        CMS.debug(method + "hasPop false, need to challenge");
+                        CMS.debug(methodPos + "hasPop false, need to challenge");
                         req.setExtData("cmc_POPchallengeRequired", "true");
                     }
                 }
@@ -1495,10 +1658,10 @@ public abstract class EnrollProfile extends BasicProfile
             } else { //!verifyAllow
 
                 if (crm.hasPop()) {
-                    CMS.debug(method + " hasPop true");
+                    CMS.debug(methodPos + " hasPop true");
                     verifyPOP(locale, crm);
                 } else { // no signing POP, then do it the hard way
-                    CMS.debug(method + "hasPop false, need to challenge");
+                    CMS.debug(methodPos + "hasPop false, need to challenge");
                     req.setExtData("cmc_POPchallengeRequired", "true");
                 }
             }
@@ -1835,6 +1998,8 @@ public abstract class EnrollProfile extends BasicProfile
 
     public void fillPKCS10(Locale locale, PKCS10 pkcs10, X509CertInfo info, IRequest req)
             throws EProfileException {
+        String method = "EnrollProfile: fillPKCS10: ";
+        CMS.debug(method + "begins");
         X509Key key = pkcs10.getSubjectPublicKeyInfo();
 
         try {
@@ -1869,7 +2034,7 @@ public abstract class EnrollProfile extends BasicProfile
                 PKCS10Attribute p10Attr = p10Attrs.getAttribute(CertificateExtensions.NAME);
                 if (p10Attr != null && p10Attr.getAttributeId().equals(
                         PKCS9Attribute.EXTENSION_REQUEST_OID)) {
-                    CMS.debug("Found PKCS10 extension");
+                    CMS.debug(method + "Found PKCS10 extension");
                     Extensions exts0 = (Extensions)
                             (p10Attr.getAttributeValue());
                     DerOutputStream extOut = new DerOutputStream();
@@ -1879,24 +2044,22 @@ public abstract class EnrollProfile extends BasicProfile
                     DerInputStream extIn = new DerInputStream(extB);
                     CertificateExtensions exts = new CertificateExtensions(extIn);
                     if (exts != null) {
-                        CMS.debug("Set extensions " + exts);
+                        CMS.debug(method + "Set extensions " + exts);
                         // info.set(X509CertInfo.EXTENSIONS, exts);
                         req.setExtData(REQUEST_EXTENSIONS, exts);
                     }
                 } else {
-                    CMS.debug("PKCS10 extension Not Found");
+                    CMS.debug(method + "PKCS10 extension Not Found");
                 }
             }
 
-            CMS.debug("Finish parsePKCS10 - " + pkcs10.getSubjectName());
+            CMS.debug(method + "Finish parsePKCS10 - " + pkcs10.getSubjectName());
         } catch (IOException e) {
-            CMS.debug("EnrollProfile: Unable to fill PKCS #10: " + e);
-            CMS.debug(e);
+            CMS.debug(method + "Unable to fill PKCS #10: " + e);
             throw new EProfileException(
                     CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"), e);
         } catch (CertificateException e) {
-            CMS.debug("EnrollProfile: Unable to fill PKCS #10: " + e);
-            CMS.debug(e);
+            CMS.debug(method + "Unable to fill PKCS #10: " + e);
             throw new EProfileException(
                     CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"), e);
         }
@@ -2074,8 +2237,11 @@ public abstract class EnrollProfile extends BasicProfile
 
     public void populate(IRequest request)
             throws EProfileException {
-        super.populate(request);
 
+        String method = "EnrollProfile: populate: ";
+        CMS.debug(method + "begins");
+
+        super.populate(request);
     }
 
     /**
@@ -2240,7 +2406,7 @@ public abstract class EnrollProfile extends BasicProfile
     public void verifyPOP(Locale locale, CertReqMsg certReqMsg)
             throws EProfileException {
         String method = "EnrollProfile: verifyPOP: ";
-        CMS.debug(method + "for signing keys");
+        CMS.debug(method + "for signing keys begins.");
 
         String auditMessage = null;
         String auditSubjectID = auditSubjectID();
@@ -2261,10 +2427,10 @@ public abstract class EnrollProfile extends BasicProfile
             CryptoToken verifyToken = null;
             String tokenName = CMS.getConfigStore().getString("ca.requestVerify.token", CryptoUtil.INTERNAL_TOKEN_NAME);
             if (CryptoUtil.isInternalToken(tokenName)) {
-                CMS.debug("POP verification using internal token");
+                CMS.debug(method + "POP verification using internal token");
                 certReqMsg.verify();
             } else {
-                CMS.debug("POP verification using token:" + tokenName);
+                CMS.debug(method + "POP verification using token:" + tokenName);
                 verifyToken = CryptoUtil.getCryptoToken(tokenName);
                 certReqMsg.verify(verifyToken);
             }
@@ -2279,7 +2445,7 @@ public abstract class EnrollProfile extends BasicProfile
             CMS.debug(method + "Unable to verify POP: " + e);
             popFailed(locale, auditSubjectID, auditMessage, e);
         }
-        CMS.debug(method + "ends.");
+        CMS.debug(method + "done.");
     }
 
     private void popFailed(Locale locale, String auditSubjectID, String auditMessage)
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/CMCUserSignedSubjectNameConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/CMCUserSignedSubjectNameConstraint.java
new file mode 100644
index 0000000..c71b670
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/CMCUserSignedSubjectNameConstraint.java
@@ -0,0 +1,141 @@
+// --- 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.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.CMCUserSignedSubjectNameDefault;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+/**
+ * This class implements the user subject name constraint for user-signed cmc requests.
+ * It makes sure the signing cert's subjectDN and the rsulting cert match
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CMCUserSignedSubjectNameConstraint extends EnrollConstraint {
+
+    public CMCUserSignedSubjectNameConstraint() {
+    }
+
+    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 = "CMCUserSignedSubjectNameConstraint: ";
+        String msg = "";
+
+        CMS.debug(method + "validate start");
+        CertificateSubjectName infoCertSN = null;
+            CertificateSubjectName authTokenCertSN = 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());
+            String certSerial = request.getExtDataInString(IAuthManager.CRED_CMC_SIGNING_CERT);
+            if (certSerial == null) {
+                msg = method + "certSerial null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            authTokenCertSN =
+                          EnrollProfile.getCMCSigningCertSNfromCertSerial(certSerial);
+            if (authTokenCertSN == null) {
+                msg = method + "authTokenCertSN null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            X500Name infoCertName = (X500Name) infoCertSN.get(CertificateSubjectName.DN_NAME);
+            if (infoCertName == null) {
+                msg = method + "infoCertName null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            X500Name authTokenCertName = (X500Name) authTokenCertSN.get(CertificateSubjectName.DN_NAME);
+            if (authTokenCertName == null) {
+                msg = method + "authTokenCertName null";
+                CMS.debug(msg);
+                throw new Exception(msg);
+            }
+            if (infoCertName.equals(authTokenCertName)) {
+                CMS.debug(method + "names match");
+            } else {
+                msg = method + "names do not match";
+                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_USER_SIGNED_SUBJECT_NAME_TEXT");
+    }
+
+    public boolean isApplicable(IPolicyDefault def) {
+        String method = "CMCUserSignedSubjectNameConstraint: isApplicable: ";
+        if (def instanceof CMCUserSignedSubjectNameDefault) {
+            CMS.debug(method + "true");
+            return true;
+        }
+        CMS.debug(method + "false");
+        return false;
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CMCUserSignedSubjectNameDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CMCUserSignedSubjectNameDefault.java
new file mode 100644
index 0000000..a0816ea
--- /dev/null
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CMCUserSignedSubjectNameDefault.java
@@ -0,0 +1,159 @@
+// --- 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) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.profile.def;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.profile.IProfile;
+import com.netscape.certsrv.property.Descriptor;
+import com.netscape.certsrv.property.EPropertyException;
+import com.netscape.certsrv.property.IDescriptor;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.cms.profile.common.EnrollProfile;
+
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X500Name;
+import netscape.security.x509.X509CertInfo;
+
+/**
+ * This class implements an enrollment default policy
+ * that populates a CMC signing user's subject name
+ * into the certificate template.
+ *
+ * @author cfu
+ * @version $Revision$, $Date$
+ */
+public class CMCUserSignedSubjectNameDefault extends EnrollDefault {
+
+    public static final String VAL_NAME = "name";
+
+    public CMCUserSignedSubjectNameDefault() {
+        super();
+        addValueName(VAL_NAME);
+    }
+
+    public void init(IProfile profile, IConfigStore config)
+            throws EProfileException {
+        super.init(profile, config);
+    }
+
+    public IDescriptor getValueDescriptor(Locale locale, String name) {
+        if (name.equals(VAL_NAME)) {
+            return new Descriptor(IDescriptor.STRING, null, null,
+                    CMS.getUserMessage(locale, "CMS_PROFILE_SUBJECT_NAME"));
+        } else {
+            return null;
+        }
+    }
+
+    public void setValue(String name, Locale locale,
+            X509CertInfo info, String value)
+            throws EPropertyException {
+        if (name == null) {
+            throw new EPropertyException(CMS.getUserMessage(
+                        locale, "CMS_INVALID_PROPERTY", name));
+        }
+        if (name.equals(VAL_NAME)) {
+            X500Name x500name = null;
+
+            try {
+                x500name = new X500Name(value);
+            } catch (IOException e) {
+                CMS.debug(e.toString());
+                // failed to build x500 name
+            }
+            CMS.debug("SubjectNameDefault: setValue name=" + x500name);
+            try {
+                info.set(X509CertInfo.SUBJECT,
+                        new CertificateSubjectName(x500name));
+            } catch (Exception e) {
+                // failed to insert subject name
+                CMS.debug("CMCUserSignedSubjectNameDefault: setValue " + e.toString());
+                throw new EPropertyException(CMS.getUserMessage(
+                            locale, "CMS_INVALID_PROPERTY", name));
+            }
+        } else {
+            throw new EPropertyException(CMS.getUserMessage(
+                        locale, "CMS_INVALID_PROPERTY", name));
+        }
+    }
+
+    public String getValue(String name, Locale locale,
+            X509CertInfo info)
+            throws EPropertyException {
+        if (name == null) {
+            throw new EPropertyException(CMS.getUserMessage(
+                        locale, "CMS_INVALID_PROPERTY", name));
+        }
+        if (name.equals(VAL_NAME)) {
+            CertificateSubjectName sn = null;
+
+            try {
+                sn = (CertificateSubjectName)
+                        info.get(X509CertInfo.SUBJECT);
+                return sn.toString();
+            } catch (Exception e) {
+                // nothing
+            }
+            throw new EPropertyException(CMS.getUserMessage(
+                        locale, "CMS_INVALID_PROPERTY", name));
+        } else {
+            throw new EPropertyException(CMS.getUserMessage(
+                        locale, "CMS_INVALID_PROPERTY", name));
+        }
+    }
+
+    public String getText(Locale locale) {
+        return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_CMC_USER_SIGNED_SUBJECT_NAME");
+    }
+
+    /**
+     * Populates the request with this policy default.
+     */
+    public void populate(IRequest request, X509CertInfo info)
+            throws EProfileException {
+        String method = "CMCUserSignedSubjectNameDefault: populate: ";
+        String msg = "";
+        CMS.debug(method + "begins");
+
+        String signingUserSerial = request.getExtDataInString(IAuthManager.CRED_CMC_SIGNING_CERT);
+        if (info == null) {
+            msg = method + "info null";
+            CMS.debug(msg);
+            throw new EProfileException(msg);
+        }
+
+        CertificateSubjectName certSN = null;
+        try {
+            certSN = EnrollProfile.getCMCSigningCertSNfromCertSerial(signingUserSerial);
+            info.set(X509CertInfo.SUBJECT, certSN);
+            CMS.debug(method + "subjectDN set in X509CertInfo");
+        } catch (Exception e) {
+            msg = method + "exception thrown:" + e;
+            throw new EProfileException(e.toString());
+        }
+        request.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
+        CMS.debug(method + "ends");
+    }
+}
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
index 00d669e..1d5bfc4 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/EnrollDefault.java
@@ -214,17 +214,18 @@ public abstract class EnrollDefault implements IPolicyDefault, ICertInfoPolicyDe
      */
     public void populate(IRequest request)
             throws EProfileException {
+        String method = "EnrollDefault: populate: ";
         String name = getClass().getName();
 
         name = name.substring(name.lastIndexOf('.') + 1);
-        CMS.debug(name + ": populate start");
+        CMS.debug(method + name + ": start");
         X509CertInfo info =
                 request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
 
         populate(request, info);
 
         request.setExtData(IEnrollProfile.REQUEST_CERTINFO, info);
-        CMS.debug(name + ": populate end");
+        CMS.debug(method + name + ": end");
     }
 
     public void addValueName(String name) {
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java
index a62d6e9..0a9cae1 100644
--- a/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java
+++ b/base/server/cms/src/com/netscape/cms/profile/input/CMCCertReqInput.java
@@ -21,6 +21,8 @@ import java.util.Locale;
 
 import netscape.security.x509.X509CertInfo;
 
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.pkix.cmc.PKIData;
 import org.mozilla.jss.pkix.cmc.TaggedRequest;
 
 import com.netscape.certsrv.apps.CMS;
@@ -85,19 +87,32 @@ public class CMCCertReqInput extends EnrollInput implements IProfileInput {
      */
     public void populate(IProfileContext ctx, IRequest request)
             throws EProfileException {
+        String method = "CMCCertReqInput: populate: ";
+        CMS.debug(method + "begins");
+
         String cert_request = ctx.get(VAL_CERT_REQUEST);
         X509CertInfo info =
                 request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
 
         if (cert_request == null) {
-            CMS.debug("CMCCertReqInput: populate - invalid certificate request");
+            CMS.debug(method + "invalid certificate request");
             throw new EProfileException(CMS.getUserMessage(
                         getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
         }
-        TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+        // cfu: getPKIDataFromCMCblob() is extracted from parseCMC
+        // so it's less confusing
+        //TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+        PKIData pkiData = mEnrollProfile.getPKIDataFromCMCblob(getLocale(request), cert_request);
+        SEQUENCE reqSeq = pkiData.getReqSequence();
+        int nummsgs = reqSeq.size(); // for now we only handle one anyways
+        CMS.debug(method + "pkiData.getReqSequence() called; nummsgs =" + nummsgs);
+        TaggedRequest[] msgs = new TaggedRequest[reqSeq.size()];
+        for (int i = 0; i < nummsgs; i++) {
+            msgs[i] = (TaggedRequest) reqSeq.elementAt(i);
+        }
 
         if (msgs == null) {
-            CMS.debug("CMCCertReqInput: populate - parseCMC returns null TaggedRequest msgs");
+            CMS.debug(method + "TaggedRequest msgs null after getPKIDataFromCMCblob");
             return;
         }
         // This profile only handle the first request in CRMF
diff --git a/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java b/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java
index e67f5b5..fabd2aa 100644
--- a/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java
+++ b/base/server/cms/src/com/netscape/cms/profile/input/CertReqInput.java
@@ -19,10 +19,8 @@ package com.netscape.cms.profile.input;
 
 import java.util.Locale;
 
-import netscape.security.pkcs.PKCS10;
-import netscape.security.util.DerInputStream;
-import netscape.security.x509.X509CertInfo;
-
+import org.mozilla.jss.asn1.SEQUENCE;
+import org.mozilla.jss.pkix.cmc.PKIData;
 import org.mozilla.jss.pkix.cmc.TaggedRequest;
 import org.mozilla.jss.pkix.crmf.CertReqMsg;
 
@@ -37,6 +35,10 @@ import com.netscape.certsrv.property.IDescriptor;
 import com.netscape.certsrv.request.IRequest;
 import com.netscape.cms.profile.common.EnrollProfile;
 
+import netscape.security.pkcs.PKCS10;
+import netscape.security.util.DerInputStream;
+import netscape.security.x509.X509CertInfo;
+
 /**
  * This class implements the certificate request input.
  * This input populates 2 main fields to the enrollment page:
@@ -89,13 +91,16 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
      */
     public void populate(IProfileContext ctx, IRequest request)
             throws EProfileException {
+        String method = "CertReqInput: populate: ";
+        CMS.debug(method + "begins");
+
         String cert_request_type = ctx.get(VAL_CERT_REQUEST_TYPE);
         String cert_request = ctx.get(VAL_CERT_REQUEST);
         X509CertInfo info =
                 request.getExtDataInCertInfo(EnrollProfile.REQUEST_CERTINFO);
 
         if (cert_request_type == null) {
-            CMS.debug("CertReqInput: populate - invalid cert request type " +
+            CMS.debug(method + "invalid cert request type " +
                     "");
             throw new EProfileException(
                     CMS.getUserMessage(getLocale(request),
@@ -103,12 +108,14 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
                             ""));
         }
         if (cert_request == null) {
-            CMS.debug("CertReqInput: populate - invalid certificate request");
+            CMS.debug(method + "invalid certificate request");
             throw new EProfileException(CMS.getUserMessage(
                         getLocale(request), "CMS_PROFILE_NO_CERT_REQ"));
         }
 
         if (cert_request_type.equals(EnrollProfile.REQ_TYPE_PKCS10)) {
+            CMS.debug(method + "cert_request_type= REQ_TYPE_PKCS10");
+
             PKCS10 pkcs10 = mEnrollProfile.parsePKCS10(getLocale(request), cert_request);
 
             if (pkcs10 == null) {
@@ -118,6 +125,7 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
 
             mEnrollProfile.fillPKCS10(getLocale(request), pkcs10, info, request);
         } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_KEYGEN)) {
+            CMS.debug(method + "cert_request_type= REQ_TYPE_KEYGEN");
             DerInputStream keygen = mEnrollProfile.parseKeyGen(getLocale(request), cert_request);
 
             if (keygen == null) {
@@ -127,6 +135,7 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
 
             mEnrollProfile.fillKeyGen(getLocale(request), keygen, info, request);
         } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_CRMF)) {
+            CMS.debug(method + "cert_request_type= REQ_TYPE_CRMF");
             CertReqMsg msgs[] = mEnrollProfile.parseCRMF(getLocale(request), cert_request);
 
             if (msgs == null) {
@@ -142,7 +151,18 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
             mEnrollProfile.fillCertReqMsg(getLocale(request), msgs[seqNum.intValue()], info, request
                     );
         } else if (cert_request_type.startsWith(EnrollProfile.REQ_TYPE_CMC)) {
-            TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+            CMS.debug(method + "cert_request_type= REQ_TYPE_CMC");
+            // cfu: getPKIDataFromCMCblob() is extracted from parseCMC
+            // so it's less confusing
+            //TaggedRequest msgs[] = mEnrollProfile.parseCMC(getLocale(request), cert_request);
+            PKIData pkiData = mEnrollProfile.getPKIDataFromCMCblob(getLocale(request), cert_request);
+            SEQUENCE reqSeq = pkiData.getReqSequence();
+            int nummsgs = reqSeq.size(); // for now we only handle one anyways
+            CMS.debug(method + "pkiData.getReqSequence() called; nummsgs =" + nummsgs);
+            TaggedRequest[] msgs = new TaggedRequest[reqSeq.size()];
+            for (int i = 0; i < nummsgs; i++) {
+                msgs[i] = (TaggedRequest) reqSeq.elementAt(i);
+            }
 
             if (msgs == null) {
                 throw new EProfileException(CMS.getUserMessage(
@@ -159,7 +179,7 @@ public class CertReqInput extends EnrollInput implements IProfileInput {
             mEnrollProfile.fillTaggedRequest(getLocale(request), msgs[seqNum.intValue()], info, request);
         } else {
             // error
-            CMS.debug("CertReqInput: populate - invalid cert request type " +
+            CMS.debug(method + "invalid cert request type " +
                     cert_request_type);
             throw new EProfileException(
                     CMS.getUserMessage(getLocale(request),
diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
index 26ca2a4..1e128d0 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
@@ -39,6 +39,7 @@ import org.mozilla.jss.pkix.cmc.OtherInfo;
 import org.mozilla.jss.pkix.cmc.TaggedAttribute;
 
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.base.EBaseException;
@@ -443,6 +444,18 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
         ///////////////////////////////////////////////
         // create request
         ///////////////////////////////////////////////
+        String tmpCertSerialS = ctx.get(IAuthManager.CRED_CMC_SIGNING_CERT);
+        if (tmpCertSerialS != null) {
+            // unlikely to happenm, but do this just in case
+            CMS.debug("ProfileSubmitCMCServlet: found existing CRED_CMC_SIGNING_CERT in ctx for CMCUserSignedAuth:" + tmpCertSerialS);
+            CMS.debug("ProfileSubmitCMCServlet: null it out");
+            ctx.set(IAuthManager.CRED_CMC_SIGNING_CERT, "");
+        }
+        String signingCertSerialS = (String) authToken.get(IAuthManager.CRED_CMC_SIGNING_CERT);
+        if (signingCertSerialS != null) {
+            CMS.debug("ProfileSubmitCMCServlet: setting CRED_CMC_SIGNING_CERT in ctx for CMCUserSignedAuth");
+            ctx.set(IAuthManager.CRED_CMC_SIGNING_CERT, signingCertSerialS);
+        }
         try {
             reqs = profile.createRequests(ctx, locale);
         } catch (EProfileException e) {
@@ -512,7 +525,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
         IRequest provedReq = null;
         if (reqs == null) {
             // handling DecryptedPOP request here
-            Integer reqID = (Integer) context.get("decryptedPopReqId");
+            Integer reqID = (Integer) context.get("cmcDecryptedPopReqId");
             provedReq = profile.getRequestQueue().findRequest(new RequestId(reqID.toString()));
             if (provedReq == null) {
 
@@ -568,6 +581,19 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
                         }
                     }
                 }
+
+                tmpCertSerialS = reqs[k].getExtDataInString(IAuthManager.CRED_CMC_SIGNING_CERT);
+                if (tmpCertSerialS != null) {
+                    // unlikely to happenm, but do this just in case
+                    CMS.debug("ProfileSubmitCMCServlet: found existing CRED_CMC_SIGNING_CERT in request for CMCUserSignedAuth:" + tmpCertSerialS);
+                    CMS.debug("ProfileSubmitCMCServlet: null it out");
+                    reqs[k].setExtData(IAuthManager.CRED_CMC_SIGNING_CERT, "");
+                }
+                // put CMCUserSignedAuth authToken in request
+                if (signingCertSerialS != null) {
+                    CMS.debug("ProfileSubmitCMCServlet: setting CRED_CMC_SIGNING_CERT in request for CMCUserSignedAuth");
+                    reqs[k].setExtData(IAuthManager.CRED_CMC_SIGNING_CERT, signingCertSerialS);
+                }
             }
 
             // put profile framework parameters into the request
diff --git a/base/server/cmsbundle/src/LogMessages.properties b/base/server/cmsbundle/src/LogMessages.properties
index 7572db4..d3ac06a 100644
--- a/base/server/cmsbundle/src/LogMessages.properties
+++ b/base/server/cmsbundle/src/LogMessages.properties
@@ -2235,6 +2235,7 @@ LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE_3=<type=OCSP_REMOV
 # SignerInfo must be a unique String representation for the signer
 #
 LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY_5=<type=CMC_SIGNED_REQUEST_SIG_VERIFY>:[AuditEvent=CMC_SIGNED_REQUEST_SIG_VERIFY][SubjectID={0}][Outcome={1}][ReqType={2}][CertSubject={3}][SignerInfo={4}] agent pre-approved CMC request signature verification
+LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY_5=<type=CMC_USER_SIGNED_REQUEST_SIG_VERIFY>:[AuditEvent=CMC_USER_SIGNED_REQUEST_SIG_VERIFY][SubjectID={0}][Outcome={1}][ReqType={2}][CertSubject={3}][SignerInfo={4}] User signed CMC request signature verification
 
 # LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST 
 # - used for TPS to TKS to get random challenge data
diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties
index bf96f90..ff56465 100644
--- a/base/server/cmsbundle/src/UserMessages.properties
+++ b/base/server/cmsbundle/src/UserMessages.properties
@@ -951,6 +951,7 @@ CMS_PROFILE_CONSTRAINT_SIGNING_ALG_TEXT=This constraint accepts only the Signing
 CMS_PROFILE_CONSTRAINT_SUBJECT_NAME_TEXT=This constraint accepts the subject name that matches {0}
 CMS_PROFILE_CONSTRAINT_UNIQUE_SUBJECT_NAME_TEXT=This constraint accepts unique subject name only
 CMS_PROFILE_CONSTRAINT_USER_SUBJECT_NAME_TEXT=This constraint accepts user subject name only
+CMS_PROFILE_CONSTRAINT_CMC_USER_SIGNED_SUBJECT_NAME_TEXT=This constraint accepts user subject name of the CMC request siging cert only
 CMS_PROFILE_CONSTRAINT_VALIDITY_TEXT=This constraint rejects the validity that is not between {0} days.
 CMS_PROFILE_CONSTRAINT_RENEWAL_GRACE_PERIOD_TEXT=This constraint rejects the renewal requests that are outside of the grace period {0}
 CMS_PROFILE_CONSTRAINT_VALIDITY_RENEWAL_TEXT=This constraint rejects the validity that is not between {0} days. If renewal, grace period is {1} days before and {2} days after the expiration date of the original certificate.
@@ -994,6 +995,7 @@ CMS_PROFILE_DEF_USER_KEY=This default populates a User-Supplied Certificate Key
 CMS_PROFILE_DEF_USER_SIGNING_ALGORITHM=This default populates a User-Supplied Certificate Signing Algorithm to the request.
 CMS_PROFILE_DEF_AUTHZ_REALM=This default populates an authorization realm.
 CMS_PROFILE_DEF_USER_SUBJECT_NAME=This default populates a User-Supplied Certificate Subject Name to the request.
+CMS_PROFILE_DEF_CMC_USER_SIGNED_SUBJECT_NAME=This default populates a User-Supplied Certificate Subject Name to the request.
 CMS_PROFILE_DEF_USER_VALIDITY=This default populates a User-Supplied Certificate Validity to the request.
 CMS_PROFILE_DEF_VALIDITY=This default populates a Certificate Validity to the request. The default values are Range={0} in days
 CMS_PROFILE_CERTIFICATE_POLICIES_ID=Certificate Policies ID
-- 
1.8.3.1


From f31ad87440332845e7e5a1d6ea1f092fefd9eef1 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 28 Apr 2017 20:05:44 -0700
Subject: [PATCH 46/49] Ticket #2617 added the new caFullCMCUserSignedCert
 profile in CS.cfg

---
 base/ca/shared/conf/CS.cfg | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
index b29802c..078abee 100644
--- a/base/ca/shared/conf/CS.cfg
+++ b/base/ca/shared/conf/CS.cfg
@@ -970,7 +970,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=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment
+profile.list=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caFullCMCUserSignedCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,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
@@ -1015,6 +1015,8 @@ profile.caRAagentCert.class_id=caEnrollImpl
 profile.caRAagentCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caRAagentCert.cfg
 profile.caFullCMCUserCert.class_id=caEnrollImpl
 profile.caFullCMCUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caFullCMCUserCert.cfg
+profile.caFullCMCUserSignedCert.class_id=caEnrollImpl
+profile.caFullCMCUserSignedCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caFullCMCUserSignedCert.cfg
 profile.caInternalAuthOCSPCert.class_id=caEnrollImpl
 profile.caInternalAuthOCSPCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caInternalAuthOCSPCert.cfg
 profile.caInternalAuthAuditSigningCert.class_id=caEnrollImpl
-- 
1.8.3.1


From 633c7c6519c925af7e3700adff29961d72435c7f Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 23 Mar 2017 14:34:31 +1100
Subject: [PATCH 47/49] PKCS12Util: use AES to encrypt private keys

Update PKCS12Util to use AES-256-CBC to encrypt private keys.
Use JSS CryptoStore methods to ensure that all key wrapping and
unwrapping is done on the token.

Specifically, CryptoStore.getEncryptedPrivateKeyInfo replaces the
previous process where a symmetric key was generated, the private
key wrapped to the symmetric key, then decryted into Dogtag's
memory, then re-encrypted under the supplied passphrase.  Now the
key gets wrapped directly to the supplied passphrase.

Similarly, for import, the EncryptedPrivateKeyInfo was decrypted
using the supplied passphrase, then encrypted to a freshly generated
symmetric key, which was then used to unwrap the key into the token.
Now, the new JSS method CryptoStore.importEncryptedPrivateKeyInfo is
used to unwrap the EncryptedPrivateKeyInfo directly into the token,
using the supplied passphrase.

As a result, the PKCS12KeyInfo class, which previously stored
unencrypted key material (a PrivateKeyInfo object), it now only
deals with PrivateKey (an opaque handle to an PKCS #11 object)
on export and encoded (byte[]) EncryptedPrivateKeyInfo data on
import.  This split suggests that PKCS12KeyInfo should be decomposed
into two classes - one containing a PrivateKey and the other
containing a byte[] encryptedPrivateKeyInfo - but this refactoring
is left for another day.

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

Change-Id: I75d48de4d7040c9fb3a9a6d1e920c191aa757b70
(cherry picked from commit 2e198ddbe9ec5000ee7e14df0aa364b600d3aa92)
---
 .../netscape/cmstools/pkcs12/PKCS12ImportCLI.java  |   4 +-
 .../com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java |   1 -
 .../src/netscape/security/pkcs/PKCS12KeyInfo.java  |  29 +++--
 .../src/netscape/security/pkcs/PKCS12Util.java     | 122 ++++++++-------------
 4 files changed, 65 insertions(+), 91 deletions(-)

diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
index da5478c..de43284 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12ImportCLI.java
@@ -124,12 +124,12 @@ public class PKCS12ImportCLI extends CLI {
 
             if (nicknames.length == 0) {
                 // store all certificates
-                util.storeIntoNSS(pkcs12, overwrite);
+                util.storeIntoNSS(pkcs12, password, overwrite);
 
             } else {
                 // load specified certificates
                 for (String nickname : nicknames) {
-                    util.storeCertIntoNSS(pkcs12, nickname, overwrite);
+                    util.storeCertIntoNSS(pkcs12, password, nickname, overwrite);
                 }
             }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
index fbebdda..e74b63a 100644
--- a/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/pkcs12/PKCS12KeyCLI.java
@@ -38,6 +38,5 @@ public class PKCS12KeyCLI extends CLI {
 
         System.out.println("  Key ID: " + keyInfo.getID().toString(16));
         System.out.println("  Subject DN: " + keyInfo.getSubjectDN());
-        System.out.println("  Algorithm: " + keyInfo.getPrivateKeyInfo().getAlgorithm());
     }
 }
diff --git a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
index c7e84f0..f180cf2 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
@@ -19,31 +19,40 @@ package netscape.security.pkcs;
 
 import java.math.BigInteger;
 
-import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
+import org.mozilla.jss.crypto.PrivateKey;
 
 public class PKCS12KeyInfo {
 
+    private PrivateKey privateKey;
+    private byte[] epkiBytes;
     BigInteger id;
-    PrivateKeyInfo privateKeyInfo;
     String subjectDN;
 
     public PKCS12KeyInfo() {
     }
 
-    public BigInteger getID() {
-        return id;
+    public PKCS12KeyInfo(PrivateKey k) {
+        this.privateKey = k;
     }
 
-    public void setID(BigInteger id) {
-        this.id = id;
+    public PKCS12KeyInfo(byte[] epkiBytes) {
+        this.epkiBytes = epkiBytes;
+    }
+
+    public PrivateKey getPrivateKey() {
+        return this.privateKey;
     }
 
-    public PrivateKeyInfo getPrivateKeyInfo() {
-        return privateKeyInfo;
+    public byte[] getEncryptedPrivateKeyInfoBytes() {
+        return epkiBytes;
     }
 
-    public void setPrivateKeyInfo(PrivateKeyInfo privateKeyInfo) {
-        this.privateKeyInfo = privateKeyInfo;
+    public BigInteger getID() {
+        return id;
+    }
+
+    public void setID(BigInteger id) {
+        this.id = id;
     }
 
     public String getSubjectDN() {
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 0b164aa..9f9a35e 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -33,27 +33,19 @@ import java.util.Collection;
 import org.apache.commons.lang.StringUtils;
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.asn1.ANY;
-import org.mozilla.jss.asn1.ASN1Util;
 import org.mozilla.jss.asn1.ASN1Value;
 import org.mozilla.jss.asn1.BMPString;
 import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
 import org.mozilla.jss.asn1.OCTET_STRING;
 import org.mozilla.jss.asn1.SEQUENCE;
 import org.mozilla.jss.asn1.SET;
-import org.mozilla.jss.crypto.Cipher;
 import org.mozilla.jss.crypto.CryptoStore;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.EncryptionAlgorithm;
-import org.mozilla.jss.crypto.IVParameterSpec;
 import org.mozilla.jss.crypto.InternalCertificate;
-import org.mozilla.jss.crypto.KeyGenAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapAlgorithm;
-import org.mozilla.jss.crypto.KeyWrapper;
 import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
 import org.mozilla.jss.crypto.ObjectNotFoundException;
-import org.mozilla.jss.crypto.PBEAlgorithm;
 import org.mozilla.jss.crypto.PrivateKey;
-import org.mozilla.jss.crypto.SymmetricKey;
 import org.mozilla.jss.crypto.X509Certificate;
 import org.mozilla.jss.pkcs12.AuthenticatedSafes;
 import org.mozilla.jss.pkcs12.CertBag;
@@ -61,14 +53,10 @@ import org.mozilla.jss.pkcs12.PFX;
 import org.mozilla.jss.pkcs12.PasswordConverter;
 import org.mozilla.jss.pkcs12.SafeBag;
 import org.mozilla.jss.pkix.primitive.Attribute;
-import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
-import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;
 import org.mozilla.jss.util.Password;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.netscape.cmsutil.crypto.CryptoUtil;
-
 import netscape.ldap.LDAPDN;
 import netscape.ldap.util.DN;
 import netscape.security.x509.X509CertImpl;
@@ -114,41 +102,30 @@ public class PKCS12Util {
         icert.setObjectSigningTrust(PKCS12.decodeFlags(flags[2]));
     }
 
-    byte[] getEncodedKey(PrivateKey privateKey) throws Exception {
-        CryptoManager cm = CryptoManager.getInstance();
-        CryptoToken token = cm.getInternalKeyStorageToken();
-
-        byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
-        IVParameterSpec param = new IVParameterSpec(iv);
-
-        SymmetricKey sk = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, true);
-        byte[] enckey = CryptoUtil.wrapUsingSymmetricKey(
-                token,
-                sk,
-                privateKey,
-                param,
-                KeyWrapAlgorithm.DES3_CBC_PAD);
-
-        Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD);
-        c.initDecrypt(sk, param);
-        return c.doFinal(enckey);
-    }
-
     public void addKeyBag(PKCS12KeyInfo keyInfo, Password password,
             SEQUENCE encSafeContents) throws Exception {
+        PrivateKey k = keyInfo.getPrivateKey();
+        if (k == null) {
+            logger.debug("NO PRIVATE KEY for " + keyInfo.subjectDN);
+            return;
+        }
 
         logger.debug("Creating key bag for " + keyInfo.subjectDN);
 
         PasswordConverter passConverter = new PasswordConverter();
-        byte salt[] = { 0x01, 0x01, 0x01, 0x01 };
-
-        EncryptedPrivateKeyInfo encPrivateKeyInfo = EncryptedPrivateKeyInfo.createPBE(
-                PBEAlgorithm.PBE_SHA1_DES3_CBC,
-                password, salt, 1, passConverter, keyInfo.privateKeyInfo);
+        byte[] epkiBytes = CryptoManager.getInstance()
+            .getInternalKeyStorageToken()
+            .getCryptoStore()
+            .getEncryptedPrivateKeyInfo(
+                /* NSS has a bug that causes any AES CBC encryption
+                 * to use AES-256, but AlgorithmID contains chosen
+                 * alg.  To avoid mismatch, use AES_256_CBC. */
+                passConverter, password, EncryptionAlgorithm.AES_256_CBC, 0, k);
 
         SET keyAttrs = createKeyBagAttrs(keyInfo);
 
-        SafeBag safeBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, encPrivateKeyInfo, keyAttrs);
+        SafeBag safeBag = new SafeBag(
+            SafeBag.PKCS8_SHROUDED_KEY_BAG, new ANY(epkiBytes), keyAttrs);
         encSafeContents.addElement(safeBag);
     }
 
@@ -318,14 +295,10 @@ public class PKCS12Util {
             PrivateKey privateKey = cm.findPrivKeyByCert(cert);
             logger.debug("Certificate \"" + nickname + "\" has private key");
 
-            PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
+            PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(privateKey);
             keyInfo.id = id;
             keyInfo.subjectDN = cert.getSubjectDN().toString();
 
-            byte[] privateData = getEncodedKey(privateKey);
-            keyInfo.privateKeyInfo = (PrivateKeyInfo)
-                    ASN1Util.decode(PrivateKeyInfo.getTemplate(), privateData);
-
             pkcs12.addKeyInfo(keyInfo);
 
         } catch (ObjectNotFoundException e) {
@@ -375,11 +348,7 @@ public class PKCS12Util {
 
     public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception {
 
-        PKCS12KeyInfo keyInfo = new PKCS12KeyInfo();
-
-        // get private key info
-        EncryptedPrivateKeyInfo encPrivateKeyInfo = (EncryptedPrivateKeyInfo) bag.getInterpretedBagContent();
-        keyInfo.privateKeyInfo = encPrivateKeyInfo.decrypt(password, new PasswordConverter());
+        PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(bag.getBagContent().getEncoded());
 
         // get key attributes
         SET bagAttrs = bag.getBagAttributes();
@@ -491,7 +460,7 @@ public class PKCS12Util {
 
     public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception {
 
-        logger.debug("Load private keys:");
+        logger.debug("Load encrypted private keys:");
 
         AuthenticatedSafes safes = pfx.getAuthSafes();
 
@@ -590,20 +559,12 @@ public class PKCS12Util {
 
     public void importKey(
             PKCS12 pkcs12,
+            Password password,
+            String nickname,
             PKCS12KeyInfo keyInfo) throws Exception {
 
         logger.debug("Importing private key " + keyInfo.subjectDN);
 
-        byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
-        IVParameterSpec param = new IVParameterSpec(iv);
-
-        PrivateKeyInfo privateKeyInfo = keyInfo.privateKeyInfo;
-
-        // encode private key
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        privateKeyInfo.encode(bos);
-        byte[] privateKey = bos.toByteArray();
-
         PKCS12CertInfo certInfo = pkcs12.getCertInfoByID(keyInfo.getID());
         if (certInfo == null) {
             logger.debug("Private key has no certificate, ignore");
@@ -619,26 +580,29 @@ public class PKCS12Util {
         // get public key
         PublicKey publicKey = cert.getPublicKey();
 
-        // delete the cert again
+        byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes();
+        if (epkiBytes == null) {
+            logger.debug(
+                "No EncryptedPrivateKeyInfo for key '"
+                + keyInfo.subjectDN + "'; skipping key");
+        }
+        store.importEncryptedPrivateKeyInfo(
+            new PasswordConverter(), password, nickname, publicKey, epkiBytes);
+
+        // delete the cert again (it will be imported again later
+        // with the correct nickname)
         try {
             store.deleteCert(cert);
         } catch (NoSuchItemOnTokenException e) {
             // this is OK
         }
-
-        // encrypt private key
-        SymmetricKey sk = CryptoUtil.generateKey(token, KeyGenAlgorithm.DES3, 0, null, true);
-        byte[] encpkey = CryptoUtil.encryptUsingSymmetricKey(
-                token, sk, privateKey, EncryptionAlgorithm.DES3_CBC_PAD, param);
-
-        // unwrap private key to load into database
-        KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD);
-        wrapper.initUnwrap(sk, param);
-        wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publicKey), publicKey);
     }
 
-    public void storeCertIntoNSS(PKCS12 pkcs12, PKCS12CertInfo certInfo, boolean overwrite) throws Exception {
-
+    public void storeCertIntoNSS(
+            PKCS12 pkcs12, Password password,
+            PKCS12CertInfo certInfo, boolean overwrite)
+        throws Exception
+    {
         CryptoManager cm = CryptoManager.getInstance();
         CryptoToken ct = cm.getInternalKeyStorageToken();
         CryptoStore store = ct.getCryptoStore();
@@ -656,7 +620,7 @@ public class PKCS12Util {
         X509Certificate cert;
         if (keyInfo != null) { // cert has key
             logger.debug("Importing user key for " + certInfo.nickname);
-            importKey(pkcs12, keyInfo);
+            importKey(pkcs12, password, certInfo.nickname, keyInfo);
 
             logger.debug("Importing user certificate " + certInfo.nickname);
             cert = cm.importUserCACertPackage(certInfo.cert.getEncoded(), certInfo.nickname);
@@ -671,19 +635,21 @@ public class PKCS12Util {
             setTrustFlags(cert, certInfo.trustFlags);
     }
 
-    public void storeCertIntoNSS(PKCS12 pkcs12, String nickname, boolean overwrite) throws Exception {
+    public void storeCertIntoNSS(PKCS12 pkcs12, Password password, String nickname, boolean overwrite) throws Exception {
         Collection<PKCS12CertInfo> certInfos = pkcs12.getCertInfosByNickname(nickname);
         for (PKCS12CertInfo certInfo : certInfos) {
-            storeCertIntoNSS(pkcs12, certInfo, overwrite);
+            storeCertIntoNSS(pkcs12, password, certInfo, overwrite);
         }
     }
 
-    public void storeIntoNSS(PKCS12 pkcs12, boolean overwrite) throws Exception {
-
+    public void storeIntoNSS(
+            PKCS12 pkcs12, Password password, boolean overwrite)
+        throws Exception
+    {
         logger.info("Storing data into NSS database");
 
         for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
-            storeCertIntoNSS(pkcs12, certInfo, overwrite);
+            storeCertIntoNSS(pkcs12, password, certInfo, overwrite);
         }
     }
 }
-- 
1.8.3.1


From 118f648961e502f55d6997f59f6cf8f355218da5 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Fri, 28 Apr 2017 19:45:53 +1000
Subject: [PATCH 48/49] PKCS12Util: add some much-needed comments

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

Change-Id: Ic35a81c4c4dd49622bfdeb677d588641594b7ec6
(cherry picked from commit 507908d1aac8f9db6c380f5cae634521608043e8)
---
 .../src/netscape/security/pkcs/PKCS12KeyInfo.java     | 19 +++++++++++++++++++
 base/util/src/netscape/security/pkcs/PKCS12Util.java  | 17 +++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
index f180cf2..ddcc3db 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12KeyInfo.java
@@ -21,6 +21,17 @@ import java.math.BigInteger;
 
 import org.mozilla.jss.crypto.PrivateKey;
 
+/**
+ * This object is used for carrying key info around.
+ *
+ * It does not handle raw key material (but it used to).
+ *
+ * FIXME: A clear refactoring opportunity exists.  The 'privateKey'
+ * field (and associated constructor) is only used during export,
+ * and the 'epkiBytes' field (and associated constructor) is only
+ * used during import.  Therefore this should be two different
+ * types.
+ */
 public class PKCS12KeyInfo {
 
     private PrivateKey privateKey;
@@ -31,10 +42,18 @@ public class PKCS12KeyInfo {
     public PKCS12KeyInfo() {
     }
 
+    /**
+     * Construct with a PrivateKey.  This constructor is used
+     * for moving the PrivateKey handle around during export.
+     */
     public PKCS12KeyInfo(PrivateKey k) {
         this.privateKey = k;
     }
 
+    /** Construct with a (serialised) EncrypedPrivateKeyInfo.  This
+     * constructor is used for moving the EPKI data around during
+     * import.
+     */
     public PKCS12KeyInfo(byte[] epkiBytes) {
         this.epkiBytes = epkiBytes;
     }
diff --git a/base/util/src/netscape/security/pkcs/PKCS12Util.java b/base/util/src/netscape/security/pkcs/PKCS12Util.java
index 9f9a35e..31c7126 100644
--- a/base/util/src/netscape/security/pkcs/PKCS12Util.java
+++ b/base/util/src/netscape/security/pkcs/PKCS12Util.java
@@ -102,6 +102,14 @@ public class PKCS12Util {
         icert.setObjectSigningTrust(PKCS12.decodeFlags(flags[2]));
     }
 
+    /**
+     * Used during EXPORT to add a private key to the PKCS12.
+     *
+     * The private key is exported directly from the token, into
+     * an EncryptedPrivateKeyInfo value, then added as a
+     * "Shrouded Key Bag" to the PKCS #12 object.  Unencrypted
+     * key material is never seen.
+     */
     public void addKeyBag(PKCS12KeyInfo keyInfo, Password password,
             SEQUENCE encSafeContents) throws Exception {
         PrivateKey k = keyInfo.getPrivateKey();
@@ -346,6 +354,12 @@ public class PKCS12Util {
         }
     }
 
+    /**
+     * Loads key bags (for IMPORT and other operations on existing
+     * PKCS #12 files).  Does not decrypt EncryptedPrivateKeyInfo
+     * values, but stores them in PKCS12KeyInfo objects for possible
+     * later use.
+     */
     public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception {
 
         PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(bag.getBagContent().getEncoded());
@@ -598,6 +612,9 @@ public class PKCS12Util {
         }
     }
 
+    /**
+     * Store a certificate (and key, if present) in NSSDB.
+     */
     public void storeCertIntoNSS(
             PKCS12 pkcs12, Password password,
             PKCS12CertInfo certInfo, boolean overwrite)
-- 
1.8.3.1


From 012718d24aff8c37713f42f2ca69c5bd7aec97df Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Thu, 6 Apr 2017 13:27:56 +1000
Subject: [PATCH 49/49] KRA: use AES in PKCS #12 recovery for wrapped keys

The KRA has two private key recovery code paths: one dealing with
keys wrapped to the storage key, and one dealing with symmetrically
encrypted keys.  Each has a separate function for constructing a
PKCS #12 file for the recovered key.

This commit updates the PKCS #12 generation for wrapped keys to use
AES encryption.  The JSS PBE facility is not expressive enough to
handle PBES2 encryption, which is necessary for many algorithms
including AES, so we now use CryptoStore.getEncryptedPrivateKeyInfo.

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

Change-Id: Iba67f15642338316e4a6d09f78504327e8853b85
(cherry picked from commit 8e663b6270d9a9409a04bfcb445318a6d5622b52)
---
 base/kra/src/com/netscape/kra/RecoveryService.java | 24 ++++++++++++----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java
index 5609b19..eee800a 100644
--- a/base/kra/src/com/netscape/kra/RecoveryService.java
+++ b/base/kra/src/com/netscape/kra/RecoveryService.java
@@ -31,6 +31,7 @@ import java.util.Random;
 
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.asn1.ASN1Util;
+import org.mozilla.jss.asn1.ANY;
 import org.mozilla.jss.asn1.ASN1Value;
 import org.mozilla.jss.asn1.BMPString;
 import org.mozilla.jss.asn1.OCTET_STRING;
@@ -38,6 +39,7 @@ import org.mozilla.jss.asn1.SEQUENCE;
 import org.mozilla.jss.asn1.SET;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.PBEAlgorithm;
+import org.mozilla.jss.crypto.EncryptionAlgorithm;
 import org.mozilla.jss.crypto.PrivateKey;
 import org.mozilla.jss.pkcs12.AuthenticatedSafes;
 import org.mozilla.jss.pkcs12.CertBag;
@@ -484,20 +486,20 @@ public class RecoveryService implements IService {
             SEQUENCE safeContents = new SEQUENCE();
             PasswordConverter passConverter = new
                     PasswordConverter();
-            Random ran = new SecureRandom();
-            byte[] salt = new byte[20];
-            ran.nextBytes(salt);
 
-            ASN1Value key = EncryptedPrivateKeyInfo.createPBE(
-                    PBEAlgorithm.PBE_SHA1_DES3_CBC,
-                    pass, salt, 1, passConverter, priKey, ct);
-            CMS.debug("RecoverService: createPFX() EncryptedPrivateKeyInfo.createPBE() returned");
-            if (key == null) {
-                CMS.debug("RecoverService: createPFX() key null");
-                throw new EBaseException("EncryptedPrivateKeyInfo.createPBE() failed");
+            byte[] epkiBytes = ct.getCryptoStore().getEncryptedPrivateKeyInfo(
+                /* NSS has a bug that causes any AES CBC encryption
+                 * to use AES-256, but AlgorithmID contains chosen
+                 * alg.  To avoid mismatch, use AES_256_CBC. */
+                passConverter, pass, EncryptionAlgorithm.AES_256_CBC, 0, priKey);
+            CMS.debug("RecoverService: createPFX() getEncryptedPrivateKeyInfo() returned");
+            if (epkiBytes == null) {
+                CMS.debug("RecoverService: createPFX() epkiBytes null");
+                throw new EBaseException("getEncryptedPrivateKeyInfo returned null");
             } else {
-                CMS.debug("RecoverService: createPFX() key not null");
+                CMS.debug("RecoverService: createPFX() epkiBytes not null");
             }
+            ASN1Value key = new ANY(epkiBytes);
 
             SET keyAttrs = createBagAttrs(
                     x509cert.getSubjectDN().toString(),
-- 
1.8.3.1