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

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