|
|
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 |
|