From b395cdfc455c54461bb6fb3cacab34912e6ec585 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Thu, 16 Jun 2016 15:44:58 -0700
Subject: [PATCH] Ticket #2298 exclude some ldap record attributes with key
 archival This is part 2 of: https://fedorahosted.org/pki/ticket/2298 [non-TMS]
 for key archival/recovery, not to record certain data in ldap and logs

This patch allows one to exclude certain ldap attributes from the enrollment records for crmf requests
(both CRMF, and CMC CRMF).  The following are the highlights:
* CRMF Manual approval profile is disabled: caDualCert.cfg
  - If excludedLdapAttrs.enabled is true, then this profile will not work, as the crmf requests (by default it is false)
    are not written to ldap record for agents to act on
* excludedLdapAttrs.attrs can be used to configure the attribute list to be excluded
* a new CRMF "auto approval" (directory based, needs to be setup) is provided
* if excludedLdapAttrs.enabled is true (in both ca and kra), the following fields are not written to the ldap record in case of CRMF:
(note: the code deliberately use literal strings on purpose for the reason that the exact literal strings need to be spelled out
in excludedLdapAttrs.attrs if the admin chooses to override the default)
           "req_x509info",
           "publickey",
            "req_extensions",
            "cert_request",
            "req_archive_options",
            "req_key"
* a sleepOneMinute() method is added for debugging purpose.  It is not called in the final code, but is left there for future debugging purpose
* code was fixed so that in KRA request will display subject name even though the x509info is missing from request
* cmc requests did not have request type in records, so they had to be added for differentiation

The following have been tested:
* CRMF auto enroll
* CRMF manual enroll/approval
* CMC-CRMF enroll
* both CA and KRA internal ldap are examined for correct data exclusion

Note: CRMF could potentially not include key archival option, however, I am not going to differentiate them at the moment.  An earlier prototype I had built attempted to do that and the signing cert's record isn't excluded for attrs write while it's CRMF request is the same as that of its encryption cert counterpart within the same request.  Due to this factor (multiple cert reqs with the same request blob), I am treating them the same for exclusion.
---
 base/ca/shared/conf/CS.cfg                         |   4 +-
 base/ca/shared/profiles/ca/caDirBasedDualCert.cfg  | 168 +++++++++++++++++++++
 base/common/src/com/netscape/certsrv/apps/CMS.java |  13 ++
 .../src/com/netscape/certsrv/apps/ICMSEngine.java  |   6 +
 .../com/netscape/cms/authentication/CMCAuth.java   |   3 +
 .../def/AuthorityKeyIdentifierExtDefault.java      |   4 +
 .../netscape/cms/profile/def/ValidityDefault.java  |   2 +-
 .../cms/servlet/request/CertReqParser.java         |  95 ++++++++----
 .../src/com/netscape/cmscore/apps/CMSEngine.java   |  76 ++++++++++
 .../netscape/cmscore/request/RequestRecord.java    |  35 ++++-
 .../netscape/cmscore/app/CMSEngineDefaultStub.java |  14 ++
 11 files changed, 388 insertions(+), 32 deletions(-)
 create mode 100644 base/ca/shared/profiles/ca/caDirBasedDualCert.cfg

diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
index 989a3221f256a010f9f6225d5caf3eaed0d0385c..3634ba5b16ca35b0b1482f6d456bad88e18457e3 100644
--- a/base/ca/shared/conf/CS.cfg
+++ b/base/ca/shared/conf/CS.cfg
@@ -967,7 +967,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,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,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,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,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
@@ -994,6 +994,8 @@ profile.caCMCUserCert.class_id=caEnrollImpl
 profile.caCMCUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCUserCert.cfg
 profile.caCrossSignedCACert.class_id=caEnrollImpl
 profile.caCrossSignedCACert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCrossSignedCACert.cfg
+profile.caDirBasedDualCert.class_id=caEnrollImpl
+profile.caDirBasedDualCert.config=/var/lib/pki/pki-tomcat/ca/profiles/ca/caDirBasedDualCert.cfg
 profile.caDirPinUserCert.class_id=caEnrollImpl
 profile.caDirPinUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caDirPinUserCert.cfg
 profile.caDirUserCert.class_id=caEnrollImpl
diff --git a/base/ca/shared/profiles/ca/caDirBasedDualCert.cfg b/base/ca/shared/profiles/ca/caDirBasedDualCert.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..884fef8f53ccf2a27154bda97c862b7f9dd722bb
--- /dev/null
+++ b/base/ca/shared/profiles/ca/caDirBasedDualCert.cfg
@@ -0,0 +1,168 @@
+desc=This certificate profile is for enrolling dual user certificates. It works only with Netscape 7.0 or later.
+visible=true
+enable=true
+enableBy=admin
+name=Directory-authenticated User Signing & Encryption Certificates Enrollment
+auth.instance_id=UserDirEnrollment
+input.list=i1,i2,i3
+input.i1.class_id=dualKeyGenInputImpl
+input.i2.class_id=subjectNameInputImpl
+input.i3.class_id=submitterInfoInputImpl
+output.list=o1
+output.o1.class_id=certOutputImpl
+policyset.list=encryptionCertSet,signingCertSet
+policyset.encryptionCertSet.list=1,2,3,4,5,6,7,8,9
+policyset.encryptionCertSet.1.constraint.class_id=subjectNameConstraintImpl
+policyset.encryptionCertSet.1.constraint.name=Subject Name Constraint
+policyset.encryptionCertSet.1.constraint.params.pattern=UID=.*
+policyset.encryptionCertSet.1.constraint.params.accept=true
+policyset.encryptionCertSet.1.default.class_id=userSubjectNameDefaultImpl
+policyset.encryptionCertSet.1.default.name=Subject Name Default
+policyset.encryptionCertSet.1.default.params.name=
+policyset.encryptionCertSet.2.constraint.class_id=validityConstraintImpl
+policyset.encryptionCertSet.2.constraint.name=Validity Constraint
+policyset.encryptionCertSet.2.constraint.params.range=365
+policyset.encryptionCertSet.2.constraint.params.notBeforeCheck=false
+policyset.encryptionCertSet.2.constraint.params.notAfterCheck=false
+policyset.encryptionCertSet.2.default.class_id=validityDefaultImpl
+policyset.encryptionCertSet.2.default.name=Validity Default
+policyset.encryptionCertSet.2.default.params.range=180
+policyset.encryptionCertSet.2.default.params.startTime=0
+policyset.encryptionCertSet.3.constraint.class_id=keyConstraintImpl
+policyset.encryptionCertSet.3.constraint.name=Key Constraint
+policyset.encryptionCertSet.3.constraint.params.keyType=RSA
+policyset.encryptionCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096
+policyset.encryptionCertSet.3.default.class_id=userKeyDefaultImpl
+policyset.encryptionCertSet.3.default.name=Key Default
+policyset.encryptionCertSet.4.constraint.class_id=noConstraintImpl
+policyset.encryptionCertSet.4.constraint.name=No Constraint
+policyset.encryptionCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
+policyset.encryptionCertSet.4.default.name=Authority Key Identifier Default
+policyset.encryptionCertSet.5.constraint.class_id=noConstraintImpl
+policyset.encryptionCertSet.5.constraint.name=No Constraint
+policyset.encryptionCertSet.5.default.class_id=authInfoAccessExtDefaultImpl
+policyset.encryptionCertSet.5.default.name=AIA Extension Default
+policyset.encryptionCertSet.5.default.params.authInfoAccessADEnable_0=true
+policyset.encryptionCertSet.5.default.params.authInfoAccessADLocationType_0=URIName
+policyset.encryptionCertSet.5.default.params.authInfoAccessADLocation_0=
+policyset.encryptionCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1
+policyset.encryptionCertSet.5.default.params.authInfoAccessCritical=false
+policyset.encryptionCertSet.5.default.params.authInfoAccessNumADs=1
+policyset.encryptionCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
+policyset.encryptionCertSet.6.constraint.name=Key Usage Extension Constraint
+policyset.encryptionCertSet.6.constraint.params.keyUsageCritical=true
+policyset.encryptionCertSet.6.constraint.params.keyUsageDigitalSignature=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageNonRepudiation=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageDataEncipherment=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageKeyEncipherment=true
+policyset.encryptionCertSet.6.constraint.params.keyUsageKeyAgreement=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageKeyCertSign=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageCrlSign=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageEncipherOnly=false
+policyset.encryptionCertSet.6.constraint.params.keyUsageDecipherOnly=false
+policyset.encryptionCertSet.6.default.class_id=keyUsageExtDefaultImpl
+policyset.encryptionCertSet.6.default.name=Key Usage Default
+policyset.encryptionCertSet.6.default.params.keyUsageCritical=true
+policyset.encryptionCertSet.6.default.params.keyUsageDigitalSignature=false
+policyset.encryptionCertSet.6.default.params.keyUsageNonRepudiation=false
+policyset.encryptionCertSet.6.default.params.keyUsageDataEncipherment=false
+policyset.encryptionCertSet.6.default.params.keyUsageKeyEncipherment=true
+policyset.encryptionCertSet.6.default.params.keyUsageKeyAgreement=false
+policyset.encryptionCertSet.6.default.params.keyUsageKeyCertSign=false
+policyset.encryptionCertSet.6.default.params.keyUsageCrlSign=false
+policyset.encryptionCertSet.6.default.params.keyUsageEncipherOnly=false
+policyset.encryptionCertSet.6.default.params.keyUsageDecipherOnly=false
+policyset.encryptionCertSet.7.constraint.class_id=noConstraintImpl
+policyset.encryptionCertSet.7.constraint.name=No Constraint
+policyset.encryptionCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
+policyset.encryptionCertSet.7.default.name=Extended Key Usage Extension Default
+policyset.encryptionCertSet.7.default.params.exKeyUsageCritical=false
+policyset.encryptionCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
+policyset.encryptionCertSet.8.constraint.class_id=noConstraintImpl
+policyset.encryptionCertSet.8.constraint.name=No Constraint
+policyset.encryptionCertSet.8.default.class_id=subjectAltNameExtDefaultImpl
+policyset.encryptionCertSet.8.default.name=Subject Alt Name Constraint
+policyset.encryptionCertSet.8.default.params.subjAltNameExtCritical=false
+policyset.encryptionCertSet.8.default.params.subjAltExtType_0=RFC822Name
+policyset.encryptionCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$
+policyset.encryptionCertSet.8.default.params.subjAltExtGNEnable_0=true
+policyset.encryptionCertSet.8.default.params.subjAltNameNumGNs=1
+policyset.encryptionCertSet.9.constraint.class_id=signingAlgConstraintImpl
+policyset.encryptionCertSet.9.constraint.name=No Constraint
+policyset.encryptionCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC
+policyset.encryptionCertSet.9.default.class_id=signingAlgDefaultImpl
+policyset.encryptionCertSet.9.default.name=Signing Alg
+policyset.encryptionCertSet.9.default.params.signingAlg=-
+policyset.signingCertSet.list=1,2,3,4,6,7,8,9
+policyset.signingCertSet.1.constraint.class_id=subjectNameConstraintImpl
+policyset.signingCertSet.1.constraint.name=Subject Name Constraint
+policyset.signingCertSet.1.constraint.params.pattern=UID=.*
+policyset.signingCertSet.1.constraint.params.accept=true
+policyset.signingCertSet.1.default.class_id=userSubjectNameDefaultImpl
+policyset.signingCertSet.1.default.name=Subject Name Default
+policyset.signingCertSet.1.default.params.name=
+policyset.signingCertSet.2.constraint.class_id=validityConstraintImpl
+policyset.signingCertSet.2.constraint.name=Validity Constraint
+policyset.signingCertSet.2.constraint.params.range=365
+policyset.signingCertSet.2.constraint.params.notBeforeCheck=false
+policyset.signingCertSet.2.constraint.params.notAfterCheck=false
+policyset.signingCertSet.2.default.class_id=validityDefaultImpl
+policyset.signingCertSet.2.default.name=Validity Default
+policyset.signingCertSet.2.default.params.range=180
+policyset.signingCertSet.2.default.params.startTime=0
+policyset.signingCertSet.3.constraint.class_id=keyConstraintImpl
+policyset.signingCertSet.3.constraint.name=Key Constraint
+policyset.signingCertSet.3.constraint.params.keyType=RSA
+policyset.signingCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096
+policyset.signingCertSet.3.default.class_id=userKeyDefaultImpl
+policyset.signingCertSet.3.default.name=Key Default
+policyset.signingCertSet.4.constraint.class_id=noConstraintImpl
+policyset.signingCertSet.4.constraint.name=No Constraint
+policyset.signingCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl
+policyset.signingCertSet.4.default.name=Authority Key Identifier Default
+policyset.signingCertSet.6.constraint.class_id=keyUsageExtConstraintImpl
+policyset.signingCertSet.6.constraint.name=Key Usage Extension Constraint
+policyset.signingCertSet.6.constraint.params.keyUsageCritical=true
+policyset.signingCertSet.6.constraint.params.keyUsageDigitalSignature=true
+policyset.signingCertSet.6.constraint.params.keyUsageNonRepudiation=true
+policyset.signingCertSet.6.constraint.params.keyUsageDataEncipherment=false
+policyset.signingCertSet.6.constraint.params.keyUsageKeyEncipherment=false
+policyset.signingCertSet.6.constraint.params.keyUsageKeyAgreement=false
+policyset.signingCertSet.6.constraint.params.keyUsageKeyCertSign=false
+policyset.signingCertSet.6.constraint.params.keyUsageCrlSign=false
+policyset.signingCertSet.6.constraint.params.keyUsageEncipherOnly=false
+policyset.signingCertSet.6.constraint.params.keyUsageDecipherOnly=false
+policyset.signingCertSet.6.default.class_id=keyUsageExtDefaultImpl
+policyset.signingCertSet.6.default.name=Key Usage Default
+policyset.signingCertSet.6.default.params.keyUsageCritical=true
+policyset.signingCertSet.6.default.params.keyUsageDigitalSignature=true
+policyset.signingCertSet.6.default.params.keyUsageNonRepudiation=true
+policyset.signingCertSet.6.default.params.keyUsageDataEncipherment=false
+policyset.signingCertSet.6.default.params.keyUsageKeyEncipherment=false
+policyset.signingCertSet.6.default.params.keyUsageKeyAgreement=false
+policyset.signingCertSet.6.default.params.keyUsageKeyCertSign=false
+policyset.signingCertSet.6.default.params.keyUsageCrlSign=false
+policyset.signingCertSet.6.default.params.keyUsageEncipherOnly=false
+policyset.signingCertSet.6.default.params.keyUsageDecipherOnly=false
+policyset.signingCertSet.7.constraint.class_id=noConstraintImpl
+policyset.signingCertSet.7.constraint.name=No Constraint
+policyset.signingCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl
+policyset.signingCertSet.7.default.name=Extended Key Usage Extension Default
+policyset.signingCertSet.7.default.params.exKeyUsageCritical=false
+policyset.signingCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4
+policyset.signingCertSet.8.constraint.class_id=noConstraintImpl
+policyset.signingCertSet.8.constraint.name=No Constraint
+policyset.signingCertSet.8.default.class_id=subjectAltNameExtDefaultImpl
+policyset.signingCertSet.8.default.name=Subject Alt Name Constraint
+policyset.signingCertSet.8.default.params.subjAltNameExtCritical=false
+policyset.signingCertSet.8.default.params.subjAltExtType_0=RFC822Name
+policyset.signingCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$
+policyset.signingCertSet.8.default.params.subjAltExtGNEnable_0=true
+policyset.signingCertSet.8.default.params.subjAltNameNumGNs=1
+policyset.signingCertSet.9.constraint.class_id=signingAlgConstraintImpl
+policyset.signingCertSet.9.constraint.name=No Constraint
+policyset.signingCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC
+policyset.signingCertSet.9.default.class_id=signingAlgDefaultImpl
+policyset.signingCertSet.9.default.name=Signing Alg
+policyset.signingCertSet.9.default.params.signingAlg=-
+policyset.signingCertSet.9.default.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC
diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java
index 9bfa608f2b5fa843a8c5d099e9383df89f7390e6..bc82a986089e932604f860f067b46593bc17ab2c 100644
--- a/base/common/src/com/netscape/certsrv/apps/CMS.java
+++ b/base/common/src/com/netscape/certsrv/apps/CMS.java
@@ -1670,6 +1670,19 @@ public final class CMS {
         return _engine.getServerStatus();
     }
 
+    // for debug only
+    public static void sleepOneMinute() {
+        _engine.sleepOneMinute();
+    }
+
+    public static boolean isExcludedLdapAttrsEnabled() {
+        return _engine.isExcludedLdapAttrsEnabled();
+    }
+
+    public static boolean isExcludedLdapAttr(String key) {
+        return _engine.isExcludedLdapAttr(key);
+    }
+
     /**
      * Main driver to start CMS.
      */
diff --git a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
index aa6b9e32e26edec3e9c34d23f84db1684f31ebbd..f781c41301360692431969987cb754ba7a6ce5f4 100644
--- a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
+++ b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
@@ -1167,4 +1167,10 @@ public interface ICMSEngine extends ISubsystem {
     public String getConfigSDSessionId();
 
     public String getServerStatus();
+
+    public void sleepOneMinute(); // for debug only
+
+    public boolean isExcludedLdapAttrsEnabled();
+
+    public boolean isExcludedLdapAttr(String key);
 }
diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
index f2bf402417961ebae442dc6019d13a8381f3352e..67938af5d1820c7403221af9fc832f8bc61da785 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
@@ -489,6 +489,8 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
 
                         if (type.equals(TaggedRequest.PKCS10)) {
                             CMS.debug("CMCAuth: type is PKCS10");
+                            authToken.set("cert_request_type", "cmc-pkcs10");
+
                             TaggedCertificationRequest tcr =
                                     taggedRequest.getTcr();
                             int p10Id = tcr.getBodyPartID().intValue();
@@ -581,6 +583,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
                         } else if (type.equals(TaggedRequest.CRMF)) {
 
                             CMS.debug("CMCAuth: type is CRMF");
+                            authToken.set("cert_request_type", "cmc-crmf");
                             try {
                                 CertReqMsg crm =
                                         taggedRequest.getCrm();
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
index e2208aba7c51a4ffd5914e039c38fee43343383e..9aaa29d7a417739c62c9c46968933253dbcddd89 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
@@ -100,6 +100,10 @@ public class AuthorityKeyIdentifierExtDefault extends CAEnrollDefault {
             throw new EPropertyException(CMS.getUserMessage(
                         locale, "CMS_INVALID_PROPERTY", name));
         }
+        if (info == null) {
+            // info is null; possibly strippedldapRecords enabled
+            return null;
+        }
 
         AuthorityKeyIdentifierExtension ext =
                 (AuthorityKeyIdentifierExtension) getExtension(
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 ad4281b808f0a8ab1250717a74256a42b4527b4f..634d0709328d4157bbb7ff4cfa683d09a5bd0291 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
@@ -195,7 +195,7 @@ public class ValidityDefault extends EnrollDefault {
             } catch (Exception e) {
                 CMS.debug("ValidityDefault: getValue " + e.toString());
             }
-            throw new EPropertyException("Invalid valie");
+            throw new EPropertyException("Invalid value");
         } else if (name.equals(VAL_NOT_AFTER)) {
             SimpleDateFormat formatter =
                     new SimpleDateFormat(DATE_FORMAT);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java b/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java
index 03975ac4f081a0a0506d199b72e20fddce4620c6..64adebf6844303b28783617583b00a50cb12f111 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/request/CertReqParser.java
@@ -30,6 +30,19 @@ import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Vector;
 
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IArgBlock;
+import com.netscape.certsrv.base.IPrettyPrintFormat;
+import com.netscape.certsrv.profile.IEnrollProfile;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.RequestStatus;
+import com.netscape.cms.servlet.common.CMSTemplate;
+import com.netscape.cms.servlet.common.CMSTemplateParams;
+import com.netscape.cms.servlet.common.RawJS;
+import com.netscape.cmsutil.util.Utils;
+
 import netscape.security.extensions.NSCertTypeExtension;
 import netscape.security.x509.AlgorithmId;
 import netscape.security.x509.BasicConstraintsExtension;
@@ -44,23 +57,11 @@ import netscape.security.x509.CertificateX509Key;
 import netscape.security.x509.Extension;
 import netscape.security.x509.RevocationReason;
 import netscape.security.x509.RevokedCertImpl;
+import netscape.security.x509.X500Name;
 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.IAuthToken;
-import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.base.IArgBlock;
-import com.netscape.certsrv.base.IPrettyPrintFormat;
-import com.netscape.certsrv.profile.IEnrollProfile;
-import com.netscape.certsrv.request.IRequest;
-import com.netscape.certsrv.request.RequestStatus;
-import com.netscape.cms.servlet.common.CMSTemplate;
-import com.netscape.cms.servlet.common.CMSTemplateParams;
-import com.netscape.cms.servlet.common.RawJS;
-import com.netscape.cmsutil.util.Utils;
-
 /**
  * Output a 'pretty print' of a certificate request
  *
@@ -102,6 +103,26 @@ public class CertReqParser extends ReqParser {
      */
     public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg)
             throws EBaseException {
+
+        // in case x509CertInfo is missing, at least add the subject for display
+        if (req.getExtDataInCertInfo("req_x509info"/*IRequest.CERT_INFO*/) == null
+                && req.getExtDataInCertInfo(IRequest.CERT_INFO) == null
+                && arg.getValueAsString("subject", "").equals("")) {
+            //CMS.debug("CertReqParser.fillRequestIntoArg: filling subject due to missing x509CertInfo in request");
+            try {
+                String subjectnamevalue = req.getExtDataInString("req_subject_name");
+                if (subjectnamevalue != null && !subjectnamevalue.equals("")) {
+                    X500Name name = new X500Name(Utils.base64decode(subjectnamevalue));
+                    CertificateSubjectName sbjName = new CertificateSubjectName(name);
+                    if (sbjName != null) {
+                        arg.addStringValue("subject", sbjName.toString());
+                    }
+                }
+            } catch (Exception ee) {
+                CMS.debug("CertReqParser.fillRequestIntoArg: Exception:" + ee.toString());
+            }
+        }
+
         if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) {
             fillX509RequestIntoArg(l, req, argSet, arg);
         } else if (req.getExtDataInRevokedCertArray(IRequest.CERT_INFO) != null) {
@@ -609,9 +630,36 @@ public class CertReqParser extends ReqParser {
                 CMSTemplate.escapeJavaScriptStringHTML(v.toString()) + "\"";
     }
 
+    public String getCertSubjectDN(IRequest request) {
+        try {
+            String cert = request.getExtDataInString("cert");
+            if (cert == null) {
+                cert = request.getExtDataInString("req_issued_cert");
+            }
+
+            if (cert != null) {
+
+                X509CertImpl theCert = null;
+                try {
+                    theCert = new X509CertImpl(Utils.base64decode(cert));
+                } catch (CertificateException e) {
+                }
+
+                if (theCert != null) {
+                    String subject = theCert.getSubjectDN().toString();
+                    return subject;
+                }
+            }
+        } catch (Exception e) {
+            CMS.debug("CertReqParser: getCertSubjectDN " + e.toString());
+        }
+        return null;
+    }
+
     public String getRequestorDN(IRequest request) {
         try {
             X509CertInfo info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO);
+            if (info == null) return null;
             // retrieve the subject name
             CertificateSubjectName sn = (CertificateSubjectName)
                     info.get(X509CertInfo.SUBJECT);
@@ -661,28 +709,17 @@ public class CertReqParser extends ReqParser {
         if (profile != null) {
             arg.addStringValue("profile", profile);
             String requestorDN = getRequestorDN(req);
+            if (requestorDN == null) {
+                requestorDN = getCertSubjectDN(req);
+            }
 
             if (requestorDN != null) {
                 arg.addStringValue("subject", requestorDN);
             }
         } else if (IRequest.KEYRECOVERY_REQUEST.equals(reqType)) {
             arg.addStringValue("profile", "false");
-
-            String cert = req.getExtDataInString("cert");
-
-            if (cert != null) {
-
-                X509CertImpl theCert = null;
-                try {
-                    theCert = new X509CertImpl(Utils.base64decode(cert));
-                } catch (CertificateException e) {
-                }
-
-                if (theCert != null) {
-                    String subject = theCert.getSubjectDN().toString();
-                    arg.addStringValue("subject", subject);
-                }
-            }
+            String subjectDN = getCertSubjectDN(req);
+            arg.addStringValue("subject", subjectDN);
 
         } else { //TMS
             arg.addStringValue("profile", "false");
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 d68290195a92c90b0bb960b64a5f0bfc160ef0a7..c9295caae6fed9651e19bd01479bf9651dbc849f 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -31,9 +31,11 @@ import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.StringTokenizer;
@@ -207,6 +209,7 @@ public class CMSEngine implements ICMSEngine {
     private CryptoManager mManager = null;
 
     private IConfigStore mConfig = null;
+    private boolean mExcludedLdapAttrsEnabled = false;
     // AutoSD : AutoShutdown
     private String mAutoSD_CrumbFile = null;
     private boolean mAutoSD_Restart = false;
@@ -1246,8 +1249,62 @@ public class CMSEngine implements ICMSEngine {
                 }
             }
         }
+
+        if (id.equals("ca") || id.equals("kra")) {
+
+            /*
+              figure out if any ldap attributes need exclusion in enrollment records
+              Default config:
+                excludedLdapAttrs.enabled=false;
+                (excludedLdapAttrs.attrs unspecified to take default)
+             */
+            mExcludedLdapAttrsEnabled = mConfig.getBoolean("excludedLdapAttrs.enabled", false);
+            if (mExcludedLdapAttrsEnabled == true) {
+                CMS.debug("CMSEngine: initSubsystem: excludedLdapAttrs.enabled: true");
+                excludedLdapAttrsList = Arrays.asList(excludedLdapAttrs);
+                String unparsedExcludedLdapAttrs = "";
+                try {
+                    unparsedExcludedLdapAttrs = mConfig.getString("excludedLdapAttrs.attrs");
+                    CMS.debug("CMSEngine: initSubsystem: excludedLdapAttrs.attrs =" + unparsedExcludedLdapAttrs);
+                } catch (Exception e) {
+                    CMS.debug("CMSEngine: initSubsystem: excludedLdapAttrs.attrs unspecified, taking default");
+                }
+                if (!unparsedExcludedLdapAttrs.equals("")) {
+                    excludedLdapAttrsList = Arrays.asList(unparsedExcludedLdapAttrs.split(","));
+                    // overwrites the default
+                    //excludedLdapAttrSet = new HashSet(excludedLdapAttrsList);
+                }
+            } else {
+                CMS.debug("CMSEngine: initSubsystem: excludedLdapAttrs.enabled: false");
+            }
+        }
     }
 
+    public boolean isExcludedLdapAttrsEnabled() {
+        return mExcludedLdapAttrsEnabled;
+    }
+
+    public boolean isExcludedLdapAttr(String key) {
+        if (isExcludedLdapAttrsEnabled()) {
+            return excludedLdapAttrsList.contains(key);
+        } else {
+            return false;
+        }
+    }
+
+    // default for excludedLdapAttrs.enabled == false
+    // can be overwritten with excludedLdapAttrs.attrs
+    public List<String> excludedLdapAttrsList = null;
+
+    public static String excludedLdapAttrs[] = {
+            "req_x509info",
+            "publickey",
+            "req_extensions",
+            "cert_request",
+            "req_archive_options",
+            "req_key"
+    };
+
     /**
      * sign some known data to determine if signing key is botched;
      * if so, proceed to graceful shutdown
@@ -2299,6 +2356,25 @@ public class CMSEngine implements ICMSEngine {
     public String getServerStatus() {
         return serverStatus;
     }
+
+    // for debug only
+    public void sleepOneMinute() {
+        boolean debugSleep = false;
+        try {
+            debugSleep = mConfig.getBoolean("debug.sleepOneMinute", false);
+        } catch (Exception e) {
+        }
+
+        /* debugSleep: sleep for one minute to check request on ldap*/
+        if (debugSleep == true) {
+            CMS.debug("debugSleep: about to sleep for one minute; check ldap");
+            try {
+                Thread.sleep(60000);
+            } catch (InterruptedException e) {
+                CMS.debug("debugSleep: sleep out:" + e.toString());
+            }
+        }
+    }
 }
 
 class WarningListener implements ILogEventListener {
diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java
index a6e454dd1787f5f254f5304489f7e53fe4eced8e..8e01290cfa871aefeb076c258333762276879b8b 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/request/RequestRecord.java
@@ -49,6 +49,8 @@ import com.netscape.cmscore.dbs.BigIntegerMapper;
 import com.netscape.cmscore.dbs.DateMapper;
 import com.netscape.cmscore.dbs.StringMapper;
 import com.netscape.cmscore.util.Debug;
+import netscape.security.x509.CertificateSubjectName;
+import netscape.security.x509.X509CertInfo;
 
 import netscape.ldap.LDAPAttribute;
 import netscape.ldap.LDAPAttributeSet;
@@ -243,11 +245,42 @@ public class RequestRecord
 
     protected static Hashtable<String, Object> loadExtDataFromRequest(IRequest r) throws EBaseException {
         Hashtable<String, Object> h = new Hashtable<String, Object>();
-
+        String reqType = r.getExtDataInString("cert_request_type");
+        if (reqType == null || reqType.equals("")) {
+            // where CMC puts it
+            reqType = r.getExtDataInString("auth_token.cert_request_type");
+        }
         Enumeration<String> e = r.getExtDataKeys();
         while (e.hasMoreElements()) {
             String key = e.nextElement();
             if (r.isSimpleExtDataValue(key)) {
+                if (key.equals("req_x509info")) {
+                    // extract subjectName if possible here
+                    // if already there, skip it
+                    String subjectName = r.getExtDataInString("req_subject_name");
+                    if (subjectName == null || subjectName.equals("")) {
+                        X509CertInfo info = r.getExtDataInCertInfo(IRequest.CERT_INFO);
+                        CMS.debug("RequestRecord.loadExtDataFromRequest: missing subject name. Processing extracting subjectName from req_x509info");
+                        try {
+                            CertificateSubjectName subjName = (CertificateSubjectName) info.get(X509CertInfo.SUBJECT);
+                            if (subjName != null) {
+                                CMS.debug("RequestRecord.loadExtDataFromRequest: got subjName");
+                                h.put("req_subject_name", subjName.toString());
+                            }
+                        } catch (Exception es) {
+                          //if failed, then no other way to get subject name.
+                          //so be it
+                        }
+                    }/* else { //this is the common case
+                        CMS.debug("RequestRecord.loadExtDataFromRequest: subject name already exists, no action needed");
+                    }*/
+                }
+                if (reqType != null &&
+                    (reqType.equals("crmf") || reqType.equals("cmc-crmf")) &&
+                        CMS.isExcludedLdapAttr(key)) {
+                    //CMS.debug("RequestRecord.loadExtDataFromRequest: found excluded attr; key=" + key);
+                    continue;
+                }
                 h.put(key, r.getExtDataInString(key));
             } else {
                 h.put(key, r.getExtDataInHashtable(key));
diff --git a/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java b/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java
index 2b85eacacd688d744099189dabed02d91f1b9933..d2b7fe8b730df76ea20b3868b1ee4181b5dc4e6f 100644
--- a/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java
+++ b/base/server/test/com/netscape/cmscore/app/CMSEngineDefaultStub.java
@@ -639,4 +639,18 @@ public class CMSEngineDefaultStub implements ICMSEngine {
     public String getServerStatus() {
         return null;
     }
+
+    @Override
+    public void sleepOneMinute() {
+    }
+
+    @Override
+    public boolean isExcludedLdapAttrsEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isExcludedLdapAttr(String key) {
+        return false;
+    }
 }
-- 
2.4.3

