Blame SOURCES/pki-core-CMC-check-HTTPS-client-authentication-cert.patch

b80204
From 32cf3850935590f7f4cd457b824cc296b6af44b9 Mon Sep 17 00:00:00 2001
b80204
From: Christina Fu <cfu@redhat.com>
b80204
Date: Wed, 14 Jun 2017 14:57:10 -0700
b80204
Subject: [PATCH 2/4] Ticket#2737 CMC: check HTTPS client authentication cert
b80204
 against CMC signer
b80204
b80204
This patch adds enforcement in CMCUserSignedAuth to make sure SSL client authentication is performed and the authenticated cert matches that of the CMC signing cert.
b80204
Some auditing adjustments are also done.
b80204
b80204
(cherry picked from commit 63c9582009b3858a6878863b9658d04c9aad45c1)
b80204
---
b80204
 base/ca/shared/conf/CS.cfg                         |   3 +-
b80204
 .../com/netscape/certsrv/base/SessionContext.java  |   7 +
b80204
 .../cms/authentication/CMCUserSignedAuth.java      | 220 ++++++++++++++-------
b80204
 .../profile/constraint/UniqueKeyConstraint.java    |   8 +-
b80204
 .../com/netscape/cms/servlet/base/CMSServlet.java  |  10 +-
b80204
 .../servlet/profile/ProfileSubmitCMCServlet.java   |   7 +
b80204
 base/server/cmsbundle/src/LogMessages.properties   |   4 +-
b80204
 7 files changed, 175 insertions(+), 84 deletions(-)
b80204
b80204
diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg
b80204
index d1bf7db..4da7429 100644
b80204
--- a/base/ca/shared/conf/CS.cfg
b80204
+++ b/base/ca/shared/conf/CS.cfg
b80204
@@ -734,11 +734,10 @@ ca.publish.rule.instance.LdapXCertRule.pluginName=Rule
b80204
 ca.publish.rule.instance.LdapXCertRule.predicate=
b80204
 ca.publish.rule.instance.LdapXCertRule.publisher=LdapCrossCertPairPublisher
b80204
 ca.publish.rule.instance.LdapXCertRule.type=xcert
b80204
-cmc.cert.confirmRequired=false
b80204
 cmc.popLinkWitnessRequired=false
b80204
-cmc.revokeCert.verify=true
b80204
 cmc.revokeCert.sharedSecret.class=com.netscape.cms.authentication.SharedSecret
b80204
 cmc.sharedSecret.class=com.netscape.cms.authentication.SharedSecret
b80204
+cmc.token=internal
b80204
 cms.passwordlist=internaldb,replicationdb
b80204
 cms.password.ignore.publishing.failure=true
b80204
 cms.version=@APPLICATION_VERSION_MAJOR@.@APPLICATION_VERSION_MINOR@
b80204
diff --git a/base/common/src/com/netscape/certsrv/base/SessionContext.java b/base/common/src/com/netscape/certsrv/base/SessionContext.java
b80204
index 8bcb3c1..9323e6e 100644
b80204
--- a/base/common/src/com/netscape/certsrv/base/SessionContext.java
b80204
+++ b/base/common/src/com/netscape/certsrv/base/SessionContext.java
b80204
@@ -56,6 +56,13 @@ public class SessionContext extends Hashtable<Object, Object> {
b80204
      * Principal name object of the signed CMC request
b80204
      */
b80204
     public static final String CMC_SIGNER_PRINCIPAL = "cmcSignerPrincipal";
b80204
+    public static final String CMC_SIGNER_INFO = "cmcSignerInfo";
b80204
+    public static final String CMC_REQUEST_CERT_SUBJECT = "cmcRequestCertSubject";
b80204
+
b80204
+   /**
b80204
+    * authenticated SSL client certificate
b80204
+    */
b80204
+    public static final String SSL_CLIENT_CERT = "sslClientCert";
b80204
 
b80204
     /**
b80204
      * User object of the authenticated user in the current thread.
b80204
diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
b80204
index 2e4d6dc..6c3ee8f 100644
b80204
--- a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
b80204
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
b80204
@@ -28,6 +28,7 @@ package com.netscape.cms.authentication;
b80204
 import java.io.ByteArrayInputStream;
b80204
 import java.io.ByteArrayOutputStream;
b80204
 import java.io.IOException;
b80204
+import java.security.cert.X509Certificate;
b80204
 import java.math.BigInteger;
b80204
 import java.security.MessageDigest;
b80204
 import java.security.PublicKey;
b80204
@@ -260,11 +261,27 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
         CMS.debug(method + "begins");
b80204
 
b80204
         String auditMessage = null;
b80204
-        String auditSubjectID = auditSubjectID();
b80204
+        String auditSubjectID = getAuditSubjectID();
b80204
         String auditReqType = ILogger.UNIDENTIFIED;
b80204
-        String auditCertSubject = ILogger.UNIDENTIFIED;
b80204
+        String requestCertSubject = ILogger.UNIDENTIFIED;
b80204
         String auditSignerInfo = ILogger.UNIDENTIFIED;
b80204
 
b80204
+        SessionContext auditContext = SessionContext.getExistingContext();
b80204
+
b80204
+        // create audit context if clientCert exists
b80204
+        X509Certificate clientCert =
b80204
+               (X509Certificate) auditContext.get(SessionContext.SSL_CLIENT_CERT);
b80204
+        // null is okay, as it is not required in case of self-sign;
b80204
+        // will be checked later
b80204
+        if (clientCert != null) {
b80204
+            try {
b80204
+                createAuditSubjectFromCert(auditContext, clientCert);
b80204
+            } catch (IOException e) { 
b80204
+               //unlikely, and not necessarily required at this point
b80204
+               CMS.debug("CMSUserSignedAuth: authenticate: after createAuditSubjectFromCert call; " + e);
b80204
+            }
b80204
+        }
b80204
+
b80204
         // ensure that any low-level exceptions are reported
b80204
         // to the signed audit log and stored as failures
b80204
         try {
b80204
@@ -296,8 +313,6 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                 throw new EInvalidCredentials(msg);
b80204
             }
b80204
 
b80204
-            SessionContext auditContext = SessionContext.getExistingContext();
b80204
-
b80204
             // authenticate by checking CMC.
b80204
 
b80204
             // everything OK.
b80204
@@ -364,13 +379,13 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                                 }
b80204
                                 // reset value of auditSignerInfo
b80204
                                 if (uid != null && !uid.equals(ILogger.UNIDENTIFIED)) {
b80204
-                                    CMS.debug(method + "setting auditSignerInfo to uid:" + uid.trim());
b80204
-                                    auditSignerInfo = uid.trim();
b80204
+                                    //CMS.debug(method + "setting auditSignerInfo to uid:" + uid.trim());
b80204
+                                    //auditSignerInfo = uid.trim();
b80204
                                     auditSubjectID = uid.trim();
b80204
                                     authToken.set(IAuthToken.USER_ID, auditSubjectID);
b80204
                                 } else if (userid != null && !userid.equals(ILogger.UNIDENTIFIED)) {
b80204
-                                    CMS.debug(method + "setting auditSignerInfo to userid:" + userid);
b80204
-                                    auditSignerInfo = userid.trim();
b80204
+                                    //CMS.debug(method + "setting auditSignerInfo to userid:" + userid);
b80204
+                                    //auditSignerInfo = userid.trim();
b80204
                                     auditSubjectID = userid.trim();
b80204
                                     authToken.set(IAuthToken.USER_ID, auditSubjectID);
b80204
                                 }
b80204
@@ -538,16 +553,17 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                                 }
b80204
 
b80204
                                 PKCS10 pkcs10 = new PKCS10(ostream.toByteArray(), sigver);
b80204
-                                // reset value of auditCertSubject
b80204
+                                // reset value of requestCertSubject
b80204
                                 X500Name tempName = pkcs10.getSubjectName();
b80204
                                 CMS.debug(method + "request subject name=" + tempName.toString());
b80204
                                 if (tempName != null) {
b80204
-                                    auditCertSubject = tempName.toString().trim();
b80204
-                                    if (auditCertSubject.equals("")) {
b80204
-                                        auditCertSubject = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
b80204
+                                    requestCertSubject = tempName.toString().trim();
b80204
+                                    if (requestCertSubject.equals("")) {
b80204
+                                        requestCertSubject = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
b80204
                                     }
b80204
                                     authToken.set(AuthToken.TOKEN_CERT_SUBJECT,
b80204
-                                            auditCertSubject/*tempName.toString()*/);
b80204
+                                            requestCertSubject/*tempName.toString()*/);
b80204
+                                    auditContext.put(SessionContext.CMC_REQUEST_CERT_SUBJECT, requestCertSubject);
b80204
                                 }
b80204
 
b80204
                                 if (selfSigned) {
b80204
@@ -632,17 +648,18 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                                 // xxx do we need to do anything else?
b80204
                                 X509CertInfo certInfo = CMS.getDefaultX509CertInfo();
b80204
 
b80204
-                                // reset value of auditCertSubject
b80204
+                                // reset value of requestCertSubject
b80204
                                 if (name != null) {
b80204
                                     String ss = name.getRFC1485();
b80204
 
b80204
-                                    CMS.debug(method + "setting auditCertSubject to: " + ss);
b80204
-                                    auditCertSubject = ss;
b80204
-                                    if (auditCertSubject.equals("")) {
b80204
-                                        auditCertSubject = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
b80204
+                                    CMS.debug(method + "setting requestCertSubject to: " + ss);
b80204
+                                    requestCertSubject = ss;
b80204
+                                    if (requestCertSubject.equals("")) {
b80204
+                                        requestCertSubject = ILogger.SIGNED_AUDIT_EMPTY_VALUE;
b80204
                                     }
b80204
 
b80204
                                     authToken.set(AuthToken.TOKEN_CERT_SUBJECT, ss);
b80204
+                                    auditContext.put(SessionContext.CMC_REQUEST_CERT_SUBJECT, requestCertSubject);
b80204
                                     //authToken.set("uid", uid);
b80204
                                     //authToken.set("userid", userid);
b80204
                                 }
b80204
@@ -696,10 +713,15 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
 
b80204
                 authToken.set("uid", uid);
b80204
                 authToken.set("userid", userid);
b80204
+            } catch (EMissingCredential e) {
b80204
+                throw e;
b80204
+            } catch (EInvalidCredentials e) {
b80204
+                throw e;
b80204
             } catch (Exception e) {
b80204
-                CMS.debug(method + e);
b80204
+                //CMS.debug(method + e);
b80204
                 //Debug.printStackTrace(e);
b80204
-                throw new EInvalidCredentials(e.toString());
b80204
+                //throw new EInvalidCredentials(e.toString());
b80204
+                throw e;
b80204
             }
b80204
 
b80204
             // For accuracy, make sure revocation by shared secret doesn't
b80204
@@ -709,11 +731,11 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                 // store a message in the signed audit log file
b80204
                 auditMessage = CMS.getLogMessage(
b80204
                         AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS,
b80204
-                        auditSubjectID,
b80204
+                        getAuditSubjectID(),
b80204
                         ILogger.SUCCESS,
b80204
                         auditReqType,
b80204
-                        auditCertSubject,
b80204
-                        auditSignerInfo);
b80204
+                        getRequestCertSubject(auditContext),
b80204
+                        getAuditSignerInfo(auditContext));
b80204
 
b80204
                 audit(auditMessage);
b80204
             } else {
b80204
@@ -725,17 +747,6 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
             return authToken;
b80204
         } catch (EMissingCredential eAudit1) {
b80204
             CMS.debug(method + eAudit1);
b80204
-            // store a message in the signed audit log file
b80204
-            auditMessage = CMS.getLogMessage(
b80204
-                    AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE,
b80204
-                    auditSubjectID,
b80204
-                    ILogger.FAILURE,
b80204
-                    auditReqType,
b80204
-                    auditCertSubject,
b80204
-                    auditSignerInfo,
b80204
-                    eAudit1.toString());
b80204
-
b80204
-            audit(auditMessage);
b80204
 
b80204
             // rethrow the specific exception to be handled later
b80204
             throw eAudit1;
b80204
@@ -744,11 +755,11 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
             // store a message in the signed audit log file
b80204
             auditMessage = CMS.getLogMessage(
b80204
                     AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE,
b80204
-                    auditSubjectID,
b80204
+                    getAuditSubjectID(),
b80204
                     ILogger.FAILURE,
b80204
                     auditReqType,
b80204
-                    auditCertSubject,
b80204
-                    auditSignerInfo,
b80204
+                    getRequestCertSubject(auditContext),
b80204
+                    getAuditSignerInfo(auditContext),
b80204
                     eAudit2.toString());
b80204
 
b80204
             audit(auditMessage);
b80204
@@ -760,11 +771,11 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
             // store a message in the signed audit log file
b80204
             auditMessage = CMS.getLogMessage(
b80204
                     AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE,
b80204
-                    auditSubjectID,
b80204
+                    getAuditSubjectID(),
b80204
                     ILogger.FAILURE,
b80204
                     auditReqType,
b80204
-                    auditCertSubject,
b80204
-                    auditSignerInfo,
b80204
+                    getRequestCertSubject(auditContext),
b80204
+                    getAuditSignerInfo(auditContext),
b80204
                     eAudit3.toString());
b80204
 
b80204
             audit(auditMessage);
b80204
@@ -776,17 +787,17 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
             // store a message in the signed audit log file
b80204
             auditMessage = CMS.getLogMessage(
b80204
                     AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE,
b80204
-                    auditSubjectID,
b80204
+                    getAuditSubjectID(),
b80204
                     ILogger.FAILURE,
b80204
                     auditReqType,
b80204
-                    auditCertSubject,
b80204
-                    auditSignerInfo,
b80204
+                    getRequestCertSubject(auditContext),
b80204
+                    getAuditSignerInfo(auditContext),
b80204
                     eAudit4.toString());
b80204
 
b80204
             audit(auditMessage);
b80204
 
b80204
-            // rethrow the specific exception to be handled later
b80204
-            throw eAudit4;
b80204
+            // rethrow the exception to be handled later
b80204
+            throw new EBaseException(eAudit4);
b80204
         }
b80204
     }
b80204
 
b80204
@@ -935,8 +946,9 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
             SessionContext auditContext, // to capture info in case of failure
b80204
             AuthToken authToken,
b80204
             SignedData cmcFullReq)
b80204
-            throws EBaseException {
b80204
+            throws EBaseException, EInvalidCredentials, EMissingCredential {
b80204
         String method = "CMCUserSignedAuth: verifySignerInfo: ";
b80204
+        String msg = "";
b80204
         CMS.debug(method + "begins");
b80204
         EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
b80204
         OBJECT_IDENTIFIER id = ci.getContentType();
b80204
@@ -1001,7 +1013,7 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                     if (cmcFullReq.hasCertificates()) {
b80204
                         SET certs = cmcFullReq.getCertificates();
b80204
                         int numCerts = certs.size();
b80204
-                        java.security.cert.X509Certificate[] x509Certs = new java.security.cert.X509Certificate[1];
b80204
+                        X509Certificate[] x509Certs = new X509Certificate[1];
b80204
                         byte[] certByteArray = new byte[0];
b80204
                         for (int j = 0; j < numCerts; j++) {
b80204
                             Certificate certJss = (Certificate) certs.elementAt(j);
b80204
@@ -1029,25 +1041,44 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                         }
b80204
 
b80204
                         CMS.debug(method + "start checking signature");
b80204
-                        String CN = null;
b80204
                         if (cert == null) {
b80204
                             // find from certDB
b80204
                             CMS.debug(method + "verifying signature");
b80204
                             si.verify(digest, id);
b80204
                         } else {
b80204
-                            CMS.debug(method + "found signing cert... verifying");
b80204
+                            CMS.debug(method + "found CMC signing cert... verifying");
b80204
+
b80204
+                            X509Certificate clientCert =
b80204
+                                    (X509Certificate) auditContext.get(SessionContext.SSL_CLIENT_CERT);
b80204
+                            // user-signed case requires ssl client authentication
b80204
+                            if (clientCert == null) {
b80204
+                                createAuditSubjectFromCert(auditContext, x509Certs[0]);
b80204
+                                msg = "missing SSL client authentication certificate;";
b80204
+                                CMS.debug(method + msg);
b80204
+                                s.close();
b80204
+                                throw new EMissingCredential(
b80204
+                                        CMS.getUserMessage("CMS_AUTHENTICATION_NO_CERT"));
b80204
+                            }
b80204
+                            netscape.security.x509.X500Name clientPrincipal =
b80204
+                                    (X500Name) clientCert.getSubjectDN();
b80204
 
b80204
-                            // capture auditSubjectID first in case of failure
b80204
-                            netscape.security.x509.X500Name principal =
b80204
+                            netscape.security.x509.X500Name cmcPrincipal =
b80204
                                     (X500Name) x509Certs[0].getSubjectDN();
b80204
 
b80204
                             // capture signer principal to be checked against
b80204
                             // cert subject principal later in CMCOutputTemplate
b80204
                             // in case of user signed revocation
b80204
-                            auditContext.put(SessionContext.CMC_SIGNER_PRINCIPAL, principal);
b80204
-                            CN = principal.getCommonName(); //tempToken.get("userid");
b80204
-                            CMS.debug(method + " Principal name = " + CN);
b80204
-                            auditContext.put(SessionContext.USER_ID, CN);
b80204
+                            auditContext.put(SessionContext.CMC_SIGNER_PRINCIPAL, cmcPrincipal);
b80204
+                            auditContext.put(SessionContext.CMC_SIGNER_INFO, cmcPrincipal.getCommonName());
b80204
+
b80204
+                            // check ssl client cert against cmc signer
b80204
+                            if (!clientPrincipal.equals(cmcPrincipal)) {
b80204
+                                msg = "SSL client authentication certificate and CMC signer do not match";
b80204
+                                CMS.debug(method + msg);
b80204
+                                s.close();
b80204
+                                throw new EInvalidCredentials(
b80204
+                                        CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
+                            }
b80204
 
b80204
                             PublicKey signKey = cert.getPublicKey();
b80204
                             PrivateKey.Type keyType = null;
b80204
@@ -1064,10 +1095,11 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                                 byte publicKeyData[] = ((X509Key) signKey).getEncoded();
b80204
                                 pubK = PK11ECPublicKey.fromSPKI(/*keyType,*/ publicKeyData);
b80204
                             } else {
b80204
-                                CMS.debug(method + "unsupported signature algorithm: " + alg);
b80204
+                                msg = "unsupported signature algorithm: " + alg;
b80204
+                                CMS.debug(method +  msg);
b80204
                                 s.close();
b80204
                                 throw new EInvalidCredentials(
b80204
-                                        CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+                                        CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
                             }
b80204
 
b80204
                             String tokenName = CMS.getConfigStore().getString("ca.requestVerify.token",
b80204
@@ -1095,9 +1127,10 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                         // ...or not;  I think it just checks usage and
b80204
                         // validity, but not revocation status
b80204
                         if (!cm.isCertValid(certByteArray, true, CryptoManager.CertUsage.SSLClient)) {
b80204
-                            CMS.debug(method + "CMC signature failed to be verified");
b80204
+                            msg = "CMC signing cert is invalid";
b80204
+                            CMS.debug(method + msg);
b80204
                             s.close();
b80204
-                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
                         } else {
b80204
                             CMS.debug(method + "CMC signature verified; but signer not yet;");
b80204
                         }
b80204
@@ -1105,28 +1138,28 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
 
b80204
                         // now check revocation status of the cert
b80204
                         if (CMS.isRevoked(x509Certs)) {
b80204
-                            CMS.debug(method + "CMC signing cert is a revoked certificate");
b80204
+                            msg = "CMC signing cert is a revoked certificate";
b80204
+                            CMS.debug(method + msg);
b80204
                             s.close();
b80204
-                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
                         }
b80204
                         try { //do this again anyways
b80204
                             cert.checkValidity();
b80204
                         } catch (CertificateExpiredException e) {
b80204
-                            CMS.debug(method + "CMC signing cert is an expired certificate");
b80204
+                            msg = "CMC signing cert is an expired certificate";
b80204
+                            CMS.debug(method + msg);
b80204
                             s.close();
b80204
-                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
                         } catch (Exception e) {
b80204
                             CMS.debug(method + e.toString());
b80204
                             s.close();
b80204
-                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+                            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + e.toString());
b80204
                         }
b80204
 
b80204
                         IAuthToken tempToken = new AuthToken(null);
b80204
-/*
b80204
                         netscape.security.x509.X500Name tempPrincipal = (X500Name) x509Certs[0].getSubjectDN();
b80204
                         String CN = tempPrincipal.getCommonName(); //tempToken.get("userid");
b80204
                         CMS.debug(method + " Principal name = " + CN);
b80204
-*/
b80204
 
b80204
                         BigInteger certSerial = x509Certs[0].getSerialNumber();
b80204
                         CMS.debug(method + " verified cert serial=" + certSerial.toString());
b80204
@@ -1137,7 +1170,9 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                         return tempToken;
b80204
 
b80204
                     } else {
b80204
-                        CMS.debug(method + "no certificate found in cmcFullReq");
b80204
+                        msg = "no certificate found in cmcFullReq";
b80204
+                        CMS.debug(method + msg);
b80204
+                        throw new EMissingCredential(msg);
b80204
                     }
b80204
                 } else if (sid.getType().equals(SignerIdentifier.SUBJECT_KEY_IDENTIFIER)) {
b80204
                     CMS.debug(method + "SignerIdentifier type: SUBJECT_KEY_IDENTIFIER");
b80204
@@ -1150,19 +1185,20 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
                     s.close();
b80204
                     return tempToken;
b80204
                 } else {
b80204
-                    CMS.debug(method + "unsupported SignerIdentifier type");
b80204
+                    msg = "unsupported SignerIdentifier type";
b80204
+                    CMS.debug(method + msg);
b80204
+                    throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg);
b80204
                 }
b80204
             } //for
b80204
 
b80204
+        } catch (EMissingCredential e) {
b80204
+            throw e;
b80204
+        } catch (EInvalidCredentials e) {
b80204
+            throw e;
b80204
         } catch (InvalidBERException e) {
b80204
-            CMS.debug(method + e.toString());
b80204
-        } catch (IOException e) {
b80204
-            CMS.debug(method + e.toString());
b80204
-        } catch (NotInitializedException e) {
b80204
-            CMS.debug(method + e.toString());
b80204
+            CMS.debug(method + e);
b80204
         } catch (Exception e) {
b80204
-            CMS.debug(method + e.toString());
b80204
-            throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
b80204
+            CMS.debug(method + e);
b80204
         } finally {
b80204
             if ((tokenSwitched == true) && (savedToken != null)) {
b80204
                 cm.setThreadToken(savedToken);
b80204
@@ -1173,6 +1209,21 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
 
b80204
     }
b80204
 
b80204
+    private void createAuditSubjectFromCert (
b80204
+            SessionContext auditContext,
b80204
+            X509Certificate cert)
b80204
+            throws IOException {
b80204
+        String method = "CMCUserSignedAuth:createAuditSubjectFromCert: ";
b80204
+
b80204
+        // capture auditSubjectID first in case of failure
b80204
+        netscape.security.x509.X500Name principal =
b80204
+                (X500Name) cert.getSubjectDN();
b80204
+
b80204
+        String CN = principal.getCommonName();
b80204
+        CMS.debug(method + " Principal name = " + CN);
b80204
+        auditContext.put(SessionContext.USER_ID, CN);
b80204
+    }
b80204
+
b80204
     public String[] getExtendedPluginInfo(Locale locale) {
b80204
         return null;
b80204
     }
b80204
@@ -1274,7 +1325,7 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
      *
b80204
      * @return id string containing the signed audit log message SubjectID
b80204
      */
b80204
-    private String auditSubjectID() {
b80204
+    private String getAuditSubjectID() {
b80204
         // if no signed audit object exists, bail
b80204
         if (mSignedAuditLogger == null) {
b80204
             return null;
b80204
@@ -1299,4 +1350,21 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
b80204
 
b80204
         return subjectID;
b80204
     }
b80204
+
b80204
+    private String getAuditSignerInfo(SessionContext auditContext) {
b80204
+        String signerSubject = (String)auditContext.get(SessionContext.CMC_SIGNER_INFO);
b80204
+        if (signerSubject == null)
b80204
+            signerSubject = "$Unidentified$";
b80204
+
b80204
+        return signerSubject;
b80204
+    }
b80204
+
b80204
+    private String getRequestCertSubject(SessionContext auditContext) {
b80204
+        String certSubject = (String)auditContext.get(SessionContext.CMC_REQUEST_CERT_SUBJECT);
b80204
+        if (certSubject == null)
b80204
+            certSubject = "$Unidentified$";
b80204
+
b80204
+        return certSubject;
b80204
+    }
b80204
+
b80204
 }
b80204
diff --git a/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java
b80204
index 33cc7a9..030995a 100644
b80204
--- a/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java
b80204
+++ b/base/server/cms/src/com/netscape/cms/profile/constraint/UniqueKeyConstraint.java
b80204
@@ -219,12 +219,14 @@ public class UniqueKeyConstraint extends EnrollConstraint {
b80204
                         Date origNotAfter = null;
b80204
                         boolean first = true;
b80204
                         while (e != null && e.hasMoreElements()) {
b80204
+                            CMS.debug(method +  msg);
b80204
                             ICertRecord rec = e.nextElement();
b80204
                             BigInteger serial = rec.getSerialNumber();
b80204
+                            msg = msg + "existing cert with same key found: " + serial.toString() + ";";
b80204
 
b80204
                             if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)
b80204
                                     || rec.getStatus().equals(ICertRecord.STATUS_REVOKED_EXPIRED)) {
b80204
-                                msg = msg + "revoked cert cannot be renewed: serial=" + serial.toString() + ";";
b80204
+                                msg = msg + "revoked cert cannot be renewed;";
b80204
                                 CMS.debug(method + msg);
b80204
                                 rejected = true;
b80204
                                 // this has to break
b80204
@@ -232,7 +234,7 @@ public class UniqueKeyConstraint extends EnrollConstraint {
b80204
                             }
b80204
                             if (!rec.getStatus().equals(ICertRecord.STATUS_VALID)
b80204
                                     && !rec.getStatus().equals(ICertRecord.STATUS_EXPIRED)) {
b80204
-                                CMS.debug(method + "invalid cert cannot be renewed; continue:" + serial.toString());
b80204
+                                CMS.debug(method + "invalid cert cannot be renewed; continue;" + serial.toString());
b80204
                                 // can still find another one to renew
b80204
                                 continue;
b80204
                             }
b80204
@@ -297,7 +299,7 @@ public class UniqueKeyConstraint extends EnrollConstraint {
b80204
         } // (size > 0)
b80204
 
b80204
         if (rejected == true) {
b80204
-            CMS.debug(method + " rejected");
b80204
+            CMS.debug(method + " rejected: " + msg);
b80204
             throw new ERejectException(msg);
b80204
         } else {
b80204
             CMS.debug(method + " approved");
b80204
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
b80204
index 9dc7470..65dc06a 100644
b80204
--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
b80204
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java
b80204
@@ -843,6 +843,10 @@ public abstract class CMSServlet extends HttpServlet {
b80204
      * get ssl client authenticated certificate
b80204
      */
b80204
     protected X509Certificate getSSLClientCertificate(HttpServletRequest httpReq) throws EBaseException {
b80204
+        return getSSLClientCertificate(httpReq, true);
b80204
+    }
b80204
+
b80204
+    protected X509Certificate getSSLClientCertificate(HttpServletRequest httpReq, boolean clientCertRequired) throws EBaseException {
b80204
 
b80204
         X509Certificate cert = null;
b80204
 
b80204
@@ -855,7 +859,11 @@ public abstract class CMSServlet extends HttpServlet {
b80204
         X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR);
b80204
 
b80204
         if (allCerts == null || allCerts.length == 0) {
b80204
-            throw new EBaseException("You did not provide a valid certificate for this operation");
b80204
+            if (!clientCertRequired) {
b80204
+                return null;
b80204
+            } else {
b80204
+                throw new EBaseException("You did not provide a valid certificate for this operation");
b80204
+            }
b80204
         }
b80204
 
b80204
         cert = allCerts[0];
b80204
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
b80204
index 330b5ff..73195e9 100644
b80204
--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
b80204
+++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java
b80204
@@ -19,6 +19,7 @@ package com.netscape.cms.servlet.profile;
b80204
 
b80204
 import java.io.InputStream;
b80204
 import java.io.OutputStream;
b80204
+import java.security.cert.X509Certificate;
b80204
 import java.util.Enumeration;
b80204
 import java.util.Locale;
b80204
 
b80204
@@ -169,6 +170,12 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
b80204
         String authMgrID = authenticator.getName();
b80204
         SessionContext sc = SessionContext.getContext();
b80204
 
b80204
+        X509Certificate clientCert =
b80204
+                getSSLClientCertificate(request, false /*cert may not be required*/);
b80204
+        if (clientCert != null) {
b80204
+           sc.put(SessionContext.SSL_CLIENT_CERT, clientCert);
b80204
+        }
b80204
+
b80204
         try {
b80204
             authToken = authenticator.authenticate(credentials);
b80204
             if (sc != null) {
b80204
diff --git a/base/server/cmsbundle/src/LogMessages.properties b/base/server/cmsbundle/src/LogMessages.properties
b80204
index 9490098..5e51440 100644
b80204
--- a/base/server/cmsbundle/src/LogMessages.properties
b80204
+++ b/base/server/cmsbundle/src/LogMessages.properties
b80204
@@ -2208,10 +2208,10 @@ LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY_5=
b80204
 #   are submitted and signature is verified
b80204
 # ReqType must be the request type (enrollment, or revocation)
b80204
 # CertSubject must be the certificate subject name of the certificate request
b80204
-# SignerInfo must be a unique String representation for the signer
b80204
+# CMCSignerInfo must be a unique String representation for the CMC request signer
b80204
 #
b80204
 LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS_5=<type=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS>:[AuditEvent=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS][SubjectID={0}][Outcome={1}][ReqType={2}][CertSubject={3}][SignerInfo={4}] User signed CMC request signature verification success
b80204
-LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE_6=<type=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE>:[AuditEvent=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE][SubjectID={0}][Outcome={1}][ReqType={2}][CertSubject={3}][SignerInfo={4}][info={5}] User signed CMC request signature verification failure
b80204
+LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE_6=<type=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE>:[AuditEvent=CMC_USER_SIGNED_REQUEST_SIG_VERIFY_FAILURE][SubjectID={0}][Outcome={1}][ReqType={2}][CertSubject={3}][CMCSignerInfo={4}][info={5}] User signed CMC request signature verification failure
b80204
 
b80204
 # LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST 
b80204
 # - used for TPS to TKS to get random challenge data
b80204
-- 
b80204
1.8.3.1
b80204