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