summaryrefslogtreecommitdiffstats
path: root/base/server/cms/src/com/netscape
diff options
context:
space:
mode:
authorChristina Fu <cfu@redhat.com>2017-05-30 14:12:06 -0700
committerChristina Fu <cfu@redhat.com>2017-06-08 18:07:49 -0700
commit698192f4f62c55142a557f6489ed2323e17401b0 (patch)
tree6be820d18391cddac9d2de50e2917bb2e9e3a1da /base/server/cms/src/com/netscape
parent5bf30f2f6a52b7164ba31ab12ed2317b2c572610 (diff)
downloadpki-698192f4f62c55142a557f6489ed2323e17401b0.tar.gz
pki-698192f4f62c55142a557f6489ed2323e17401b0.tar.xz
pki-698192f4f62c55142a557f6489ed2323e17401b0.zip
Ticket #2619 Allow CA to process user-signed CMC revocation requests
First of all, the original CMC revocation only supports agent-signed CMC revocation requests from the UI where CMCRevReqServlet handles it with CMCAuth. It is in violation with https://tools.ietf.org/html/rfc5273 CMC Transport Protocols, as for HTTP/HTTPS, the body of the message is the binary value of the BER encoding of the PKI Request or Response,so HTML is not an approved method.The other way is through profileSubmitCMCFullServlet (or maybe not, as it was completely broken). One thing that's much less crucial, but goes along with rfc update is the name of the revocation request ASN1 structure. In the new rfc5272, it is now called RevokeRequest insead of RevRequest. This patch revamped the CMC revocation provision and fixing what's broken and adding what's missing. On the client side: CMCRequest - Commented out the code where it made an assumption to use OtherMsg for the signer information. This makes no sense as the outer layer SignedData would have the same information when signing happens. - removed the revRequest.nickname parameter from the configuration. From the code it seems like it expects the certificate to be revoked to exist in the user database, and it uses the same certificate to sign the revocation request. The RFC does allow for self-signed revocation, but it also allows for signing with another certificate provided that it has same subject. By removing the revRequest.nickname parameter, I am using the "nickname" parameter as the signer cert, which may or may not be the same certificate specified in revRequest.serial. It is less confusing. The change also eliminate the need for the cert to be revoked to be present in the db. In addition, revRequest.issuer only needs to be specified if revRequest.sharedSecret is used. The code will extract the issuer info from the signing cert. - added support for unsigned data in support of shared secret in both CMCRequest and server; The original code assumed that a cmc revocation request that relies on shared secret still requires agent signing. CMCRevoke - The original code assumed that the nss db password is the same as Shared Secret (!!). This patch added a "-t" to accept shred secret, and keep the -p for the nss db password. - The original code printed out b64 encoded request to the screen output as well as the file CMCRevoke.out. Both are unusable directly. This patch fixes it so that the output to the screen can be directly copied and pasted into the CMC revocate ui at ee (processed by CMCRevReqServlet); Again, this is not RFC conforming, but I fixed it anyways; - The output to the file CMCRevoke.out has been fixed so that it is the BER encoding of the request, which can be fed directly into the updated server that now conforms to the RFC (see below) - This code still requires the signer certificate nickname to run, making the shared secret method moot. Since CMCRequest has been updated to work properly, we can leave this for now. On the server side. CMCUserSignedAuth has been updated to handle unsigned DATA; Recall that the original CMC revocation only handled SIGNED_DATA (making assumption that agent always signs the requests). This addition is important to support shared secrets properly. Another thing that's important change on the server side is that it now checks the revoking cert's subject against the signer's subject, if authenticated by CMCUserSignedAuth. The original code did not do that, I think it is because it always checks if it's an agent or not. Something that could be improved on is to have its own servlet. However, due to the time restriction, I only updated existing EnrollProfile, ProfileSubmitCMCServlet, and CMCOutputTemplate to handle the rfc conforming cmc revocation requests. The shared secret handling is left in the CMCOutputTemplate for now. Logically it would make sense to go into CMCUserSignedAuth. This could be left as a possible later ticket for improvement. Shared Token plugin implementation will be added in later ticket as well. Previously missed signing cert validation is also added for more complete check. Some SHA1 are turned into SHA2 Finally, some auditing are added, but it is not finalized. It will be done in the next ticket(s).
Diffstat (limited to 'base/server/cms/src/com/netscape')
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java19
-rw-r--r--base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java198
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java80
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java4
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java10
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java407
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java15
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java12
8 files changed, 468 insertions, 277 deletions
diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
index b8983531a..94411671b 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java
@@ -237,6 +237,9 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
*/
public IAuthToken authenticate(IAuthCredentials authCred) throws EMissingCredential, EInvalidCredentials,
EBaseException {
+ String method = "CMCAuth: authenticate: ";
+ String msg = "";
+
String auditMessage = null;
String auditSubjectID = auditSubjectID();
String auditReqType = ILogger.UNIDENTIFIED;
@@ -261,7 +264,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
}
String cmc = (String) returnVal;
if (cmc == null) {
- CMS.debug("CMCAuth: Authentication failed. Missing CMC.");
+ CMS.debug(method + "Authentication failed. Missing CMC.");
// store a message in the signed audit log file
auditMessage = CMS.getLogMessage(
@@ -279,8 +282,9 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
}
if (cmc.equals("")) {
- log(ILogger.LL_FAILURE,
- "cmc : attempted login with empty CMC.");
+ msg = "attempted login with empty CMC";
+ CMS.debug(method + msg);
+ log(ILogger.LL_FAILURE, method + msg);
// store a message in the signed audit log file
auditMessage = CMS.getLogMessage(
@@ -331,6 +335,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
if (!cmcReq.getContentType().equals(
org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) ||
!cmcReq.hasContent()) {
+ CMS.debug(method + "malformed cmc: either not ContentInfo.SIGNED_DATA or cmcReq has no content");
// store a message in the signed audit log file
auditMessage = CMS.getLogMessage(
AuditEvent.CMC_SIGNED_REQUEST_SIG_VERIFY,
@@ -358,13 +363,13 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
if (checkSignerInfo) {
IAuthToken agentToken = verifySignerInfo(authToken, cmcFullReq);
if (agentToken == null) {
- CMS.debug("CMCAuth: authenticate() agentToken null");
+ CMS.debug(method + "agentToken null");
throw new EBaseException("CMCAuth: agent verifySignerInfo failure");
}
userid = agentToken.getInString("userid");
uid = agentToken.getInString("cn");
} else {
- CMS.debug("CMCAuth: authenticate() signerInfo verification bypassed");
+ CMS.debug(method + "signerInfo verification bypassed");
}
// reset value of auditSignerInfo
if (uid != null) {
@@ -377,6 +382,8 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) ||
!ci.hasContent()) {
+ msg = "request EncapsulatedContentInfo content type not OBJECT_IDENTIFIER.id_cct_PKIData";
+ CMS.debug( method + msg);
// store a message in the signed audit log file
auditMessage = CMS.getLogMessage(
AuditEvent.CMC_SIGNED_REQUEST_SIG_VERIFY,
@@ -406,6 +413,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
if (numReqs == 0) {
// revocation request
+ CMS.debug(method + "numReqs 0, assume revocation request");
// reset value of auditReqType
auditReqType = SIGNED_AUDIT_REVOCATION_REQUEST_TYPE;
@@ -476,6 +484,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo,
}
} else {
// enrollment request
+ CMS.debug(method + "numReqs not 0, assume enrollment request");
// reset value of auditReqType
auditReqType = SIGNED_AUDIT_ENROLLMENT_REQUEST_TYPE;
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 a18c25ee3..2e4d6dccc 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java
@@ -29,9 +29,9 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
-import java.security.cert.CertificateExpiredException;
import java.security.MessageDigest;
import java.security.PublicKey;
+import java.security.cert.CertificateExpiredException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
@@ -323,85 +323,90 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
byte[] cmcBlob = CMS.AtoB(asciiBASE64Blob);
ByteArrayInputStream cmcBlobIn = new ByteArrayInputStream(cmcBlob);
- org.mozilla.jss.pkix.cms.ContentInfo cmcReq =
- (org.mozilla.jss.pkix.cms.ContentInfo) org.mozilla.jss.pkix.cms.ContentInfo
+ org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo) org.mozilla.jss.pkix.cms.ContentInfo
.getTemplate().decode(
cmcBlobIn);
- if (!cmcReq.getContentType().equals(
- org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) ||
- !cmcReq.hasContent()) {
-
- cmcBlobIn.close();
- msg = "cmc rquest content type is not ContentInfo.SIGNED_DATA";
- CMS.debug(msg);
- throw new EBaseException(msg);
- }
-
- SignedData cmcFullReq = (SignedData) cmcReq.getInterpretedContent();
-
String userid = ILogger.UNIDENTIFIED;
String uid = ILogger.UNIDENTIFIED;
- IConfigStore cmc_config = CMS.getConfigStore();
- boolean checkSignerInfo = cmc_config.getBoolean("cmc.signerInfo.verify", true);
- if (checkSignerInfo) {
- // selfSigned will be set in verifySignerInfo if applicable
- IAuthToken userToken = verifySignerInfo(auditContext, authToken, cmcFullReq);
- if (userToken == null) {
- msg = "userToken null; verifySignerInfo failure";
- CMS.debug(method + msg);
- throw new EBaseException(msg);
- } else {
- if (selfSigned) {
- CMS.debug(method
- + " self-signed cmc request will not have user identification info at this point.");
- auditSignerInfo = "selfSigned";
+ SignedData cmcFullReq = null;
+ OCTET_STRING content = null;
+ OBJECT_IDENTIFIER id = null;
+ org.mozilla.jss.pkix.cms.SignerInfo selfsign_signerInfo = null;
+ if (cmcReq.getContentType().equals(
+ org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA)) {
+ CMS.debug(method + "cmc request content is signed data");
+ cmcFullReq = (SignedData) cmcReq.getInterpretedContent();
+
+ IConfigStore cmc_config = CMS.getConfigStore();
+ boolean checkSignerInfo = cmc_config.getBoolean("cmc.signerInfo.verify", true);
+ if (checkSignerInfo) {
+ // selfSigned will be set in verifySignerInfo if applicable
+ IAuthToken userToken = verifySignerInfo(auditContext, authToken, cmcFullReq);
+ if (userToken == null) {
+ msg = "userToken null; verifySignerInfo failure";
+ CMS.debug(method + msg);
+ throw new EBaseException(msg);
} else {
- CMS.debug(method + "signed with user cert");
- userid = userToken.getInString("userid");
- uid = userToken.getInString("cn");
- if (userid == null && uid == null) {
- msg = " verifySignerInfo failure... missing userid and cn";
- CMS.debug(method + msg);
- throw new EBaseException(msg);
- }
- // reset value of auditSignerInfo
- if (uid != null && !uid.equals(ILogger.UNIDENTIFIED)) {
- 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();
- auditSubjectID = userid.trim();
- authToken.set(IAuthToken.USER_ID, auditSubjectID);
+ if (selfSigned) {
+ CMS.debug(method
+ + " self-signed cmc request will not have user identification info at this point.");
+ auditSignerInfo = "selfSigned";
+ } else {
+ CMS.debug(method + "signed with user cert");
+ userid = userToken.getInString("userid");
+ uid = userToken.getInString("cn");
+ if (userid == null && uid == null) {
+ msg = " verifySignerInfo failure... missing userid and cn";
+ CMS.debug(method + msg);
+ throw new EBaseException(msg);
+ }
+ // reset value of auditSignerInfo
+ if (uid != null && !uid.equals(ILogger.UNIDENTIFIED)) {
+ 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();
+ auditSubjectID = userid.trim();
+ authToken.set(IAuthToken.USER_ID, auditSubjectID);
+ }
}
}
+ } else {
+ CMS.debug(method + " signerInfo verification bypassed");
}
- } else {
- CMS.debug(method + " signerInfo verification bypassed");
- }
- EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
- SET sis = cmcFullReq.getSignerInfos();
- // only one SignerInfo for selfSigned
- org.mozilla.jss.pkix.cms.SignerInfo selfsign_signerInfo =
- (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(0);
+ EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+ SET sis = cmcFullReq.getSignerInfos();
+ // only one SignerInfo for selfSigned
+ selfsign_signerInfo = (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(0);
- OBJECT_IDENTIFIER id = ci.getContentType();
+ id = ci.getContentType();
- if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) ||
- !ci.hasContent()) {
- msg = "request EncapsulatedContentInfo content type not OBJECT_IDENTIFIER.id_cct_PKIData";
- CMS.debug(method + msg);
+ if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) ||
+ !ci.hasContent()) {
+ msg = "request EncapsulatedContentInfo content type not OBJECT_IDENTIFIER.id_cct_PKIData";
+ CMS.debug(method + msg);
+
+ throw new EBaseException(msg);
+ }
+ content = ci.getContent();
+ } else if (cmcReq.getContentType().equals( //unsigned
+ org.mozilla.jss.pkix.cms.ContentInfo.DATA)) {
+ CMS.debug(method + "cmc request content is unsigned data...verifySignerInfo will not be called;");
+ content = (OCTET_STRING) cmcReq.getInterpretedContent();
+ } else {
+ cmcBlobIn.close();
+ msg = "unsupported cmc rquest content type; must be either ContentInfo.SIGNED_DATA or ContentInfo.DATA;";
+ CMS.debug(msg);
throw new EBaseException(msg);
}
- OCTET_STRING content = ci.getContent();
-
ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
@@ -426,7 +431,8 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
if (type.equals(
OBJECT_IDENTIFIER.id_cmc_revokeRequest)) {
- /* TODO: user-signed revocation to be handled in next ticket
+ //further checks and actual revocation happen in CMCOutputTemplate
+
// if( i ==1 ) {
// taggedAttribute.getType() ==
// OBJECT_IDENTIFIER.id_cmc_revokeRequest
@@ -440,25 +446,23 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
for (int j = 0; j < numVals; j++) {
// serialNumber INTEGER
- // SEQUENCE RevRequest = (SEQUENCE)
+ // SEQUENCE RevokeRequest = (SEQUENCE)
// values.elementAt(j);
byte[] encoded = ASN1Util.encode(
values.elementAt(j));
- org.mozilla.jss.asn1.ASN1Template template = new
- org.mozilla.jss.pkix.cmmf.RevRequest.Template();
- org.mozilla.jss.pkix.cmmf.RevRequest revRequest =
- (org.mozilla.jss.pkix.cmmf.RevRequest)
- ASN1Util.decode(template, encoded);
+ org.mozilla.jss.asn1.ASN1Template template = new org.mozilla.jss.pkix.cmc.RevokeRequest.Template();
+ org.mozilla.jss.pkix.cmc.RevokeRequest revRequest = (org.mozilla.jss.pkix.cmc.RevokeRequest) ASN1Util
+ .decode(template, encoded);
- // SEQUENCE RevRequest = (SEQUENCE)
+ // SEQUENCE RevokeRequest = (SEQUENCE)
// ASN1Util.decode(
// SEQUENCE.getTemplate(),
// ASN1Util.encode(
// values.elementAt(j)));
- // SEQUENCE RevRequest =
+ // SEQUENCE RevokeRequest =
// values.elementAt(j);
- // int revReqSize = RevRequest.size();
+ // int revReqSize = RevokeRequest.size();
// if( revReqSize > 3 ) {
// INTEGER serialNumber =
// new INTEGER((long)0);
@@ -473,13 +477,10 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
Integer IntObject = Integer.valueOf((int) reasonCode);
authToken.set(REASON_CODE, IntObject);
-
//authToken.set("uid", uid);
//authToken.set("userid", userid);
}
- */
-
}
}
@@ -648,8 +649,7 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
certInfoArray[i] = certInfo;
if (selfSigned) {
- selfsign_skiExtn =
- (SubjectKeyIdentifierExtension) CryptoUtil
+ selfsign_skiExtn = (SubjectKeyIdentifierExtension) CryptoUtil
.getExtensionFromCertTemplate(template, PKIXExtensions.SubjectKey_Id);
if (selfsign_skiExtn != null) {
CMS.debug(method +
@@ -702,16 +702,24 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
throw new EInvalidCredentials(e.toString());
}
- // store a message in the signed audit log file
- auditMessage = CMS.getLogMessage(
- AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS,
- auditSubjectID,
- ILogger.SUCCESS,
- auditReqType,
- auditCertSubject,
- auditSignerInfo);
-
- audit(auditMessage);
+ // For accuracy, make sure revocation by shared secret doesn't
+ // log CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS
+ if (authToken.get(IAuthManager.CRED_CMC_SIGNING_CERT) != null ||
+ authToken.get(IAuthManager.CRED_CMC_SELF_SIGNED) != null) {
+ // store a message in the signed audit log file
+ auditMessage = CMS.getLogMessage(
+ AuditEvent.CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS,
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditReqType,
+ auditCertSubject,
+ auditSignerInfo);
+
+ audit(auditMessage);
+ } else {
+ CMS.debug(method
+ + "audit event CMC_USER_SIGNED_REQUEST_SIG_VERIFY_SUCCESS not logged due to unsigned data for revocation with shared secret.");
+ }
CMS.debug(method + "ends successfully; returning authToken");
return authToken;
@@ -1029,10 +1037,15 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo,
} else {
CMS.debug(method + "found signing cert... verifying");
- //capture auditSubjectID first in case of failure
- netscape.security.x509.X500Name tempPrincipal =
+ // capture auditSubjectID first in case of failure
+ netscape.security.x509.X500Name principal =
(X500Name) x509Certs[0].getSubjectDN();
- CN = tempPrincipal.getCommonName(); //tempToken.get("userid");
+
+ // 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);
@@ -1093,15 +1106,18 @@ 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");
+ s.close();
throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
}
try { //do this again anyways
cert.checkValidity();
} catch (CertificateExpiredException e) {
CMS.debug(method + "CMC signing cert is an expired certificate");
+ s.close();
throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
} catch (Exception e) {
CMS.debug(method + e.toString());
+ s.close();
throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
}
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
index 2591acefa..74da8e75f 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -588,16 +588,25 @@ public abstract class EnrollProfile extends BasicProfile
try {
byte data[] = CMS.AtoB(creq);
ByteArrayInputStream cmcBlobIn = new ByteArrayInputStream(data);
+ PKIData pkiData = null;
org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo) org.mozilla.jss.pkix.cms.ContentInfo
.getTemplate().decode(cmcBlobIn);
- org.mozilla.jss.pkix.cms.SignedData cmcFullReq = (org.mozilla.jss.pkix.cms.SignedData) cmcReq
- .getInterpretedContent();
- org.mozilla.jss.pkix.cms.EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
- OCTET_STRING content = ci.getContent();
-
+ OCTET_STRING content = null;
+ if (cmcReq.getContentType().equals(
+ org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA)) {
+ CMS.debug(method + "cmc request content is signed data");
+ org.mozilla.jss.pkix.cms.SignedData cmcFullReq = (org.mozilla.jss.pkix.cms.SignedData) cmcReq
+ .getInterpretedContent();
+ org.mozilla.jss.pkix.cms.EncapsulatedContentInfo ci = cmcFullReq.getContentInfo();
+ content = ci.getContent();
+
+ } else { // for unsigned revocation requests (using shared secret)
+ CMS.debug(method + "cmc request content is unsigned data");
+ content = (OCTET_STRING) cmcReq.getInterpretedContent();
+ }
ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
- PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s);
+ pkiData = (PKIData) (new PKIData.Template()).decode(s);
mCMCData = pkiData;
//PKIData pkiData = (PKIData)
@@ -708,6 +717,8 @@ public abstract class EnrollProfile extends BasicProfile
byte randomSeed[] = null;
UTF8String ident_s = null;
SessionContext context = SessionContext.getContext();
+
+ boolean id_cmc_revokeRequest = false;
if (!context.containsKey("numOfControls")) {
CMS.debug(method + "numcontrols="+ numcontrols);
if (numcontrols > 0) {
@@ -735,7 +746,13 @@ public abstract class EnrollProfile extends BasicProfile
for (int i = 0; i < numcontrols; i++) {
attributes[i] = (TaggedAttribute) controlSeq.elementAt(i);
OBJECT_IDENTIFIER oid = attributes[i].getType();
- if (oid.equals(OBJECT_IDENTIFIER.id_cmc_decryptedPOP)) {
+ if (oid.equals(OBJECT_IDENTIFIER.id_cmc_revokeRequest)) {
+ id_cmc_revokeRequest = true;
+ // put in context for processing in
+ // CMCOutputTemplate.java later
+ context.put(OBJECT_IDENTIFIER.id_cmc_revokeRequest,
+ attributes[i]);
+ } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_decryptedPOP)) {
CMS.debug(method + " id_cmc_decryptedPOP found");
id_cmc_decryptedPOP = true;
decPopVals = attributes[i].getValues();
@@ -766,6 +783,10 @@ public abstract class EnrollProfile extends BasicProfile
*/
CMS.debug(method + "processing controls...");
+ if (id_cmc_revokeRequest) {
+ CMS.debug(method + "revocation control");
+ }
+
if (id_cmc_identification) {
if (ident == null) {
msg = "id_cmc_identification contains null attribute value";
@@ -801,7 +822,7 @@ public abstract class EnrollProfile extends BasicProfile
// checking Proof Of Identity, if not pre-signed
- if (donePOI) {
+ if (donePOI || id_cmc_revokeRequest) {
// for logging purposes
if (id_cmc_identityProofV2) {
CMS.debug(method
@@ -921,6 +942,7 @@ public abstract class EnrollProfile extends BasicProfile
SEQUENCE otherMsgSeq = pkiData.getOtherMsgSequence();
int numOtherMsgs = otherMsgSeq.size();
if (!context.containsKey("numOfOtherMsgs")) {
+ CMS.debug(method + "found numOfOtherMsgs: " + numOtherMsgs);
context.put("numOfOtherMsgs", Integer.valueOf(numOtherMsgs));
for (int i = 0; i < numOtherMsgs; i++) {
OtherMsg omsg = (OtherMsg) (ASN1Util.decode(OtherMsg.getTemplate(),
@@ -959,6 +981,8 @@ public abstract class EnrollProfile extends BasicProfile
boolean valid = true;
for (int i = 0; i < nummsgs; i++) {
msgs[i] = (TaggedRequest) reqSeq.elementAt(i);
+ if (id_cmc_revokeRequest)
+ continue;
if (popLinkWitnessRequired &&
!context.containsKey("POPLinkWitnessV2") &&
!context.containsKey("POPLinkWitness")) {
@@ -1271,7 +1295,7 @@ public abstract class EnrollProfile extends BasicProfile
boolean sharedSecretFound = true;
String configName = "cmc.sharedSecret.class";
String sharedSecret = null;
- ISharedToken tokenClass = getSharedTokenClass(configName);
+ ISharedToken tokenClass = CMS.getSharedTokenClass(configName);
if (tokenClass == null) {
CMS.debug(method + " Failed to retrieve shared secret plugin class");
sharedSecretFound = false;
@@ -1498,40 +1522,6 @@ public abstract class EnrollProfile extends BasicProfile
return bpids;
}
-
- ISharedToken getSharedTokenClass(String configName) {
- String method = "EnrollProfile: getSharedTokenClass: ";
- ISharedToken tokenClass = null;
-
- String name = null;
- try {
- CMS.debug(method + "getting :" + configName);
- name = CMS.getConfigStore().getString(configName);
- CMS.debug(method + "Shared Secret plugin class name retrieved:" +
- name);
- } catch (Exception e) {
- CMS.debug(method + " Failed to retrieve shared secret plugin class name");
- return null;
- }
-
- try {
- tokenClass = (ISharedToken) Class.forName(name).newInstance();
- CMS.debug(method + "Shared Secret plugin class retrieved");
- } catch (ClassNotFoundException e) {
- CMS.debug(method + " Failed to find class name: " + name);
- return null;
- } catch (InstantiationException e) {
- CMS.debug("EnrollProfile: Failed to instantiate class: " + name);
- return null;
- } catch (IllegalAccessException e) {
- CMS.debug(method + " Illegal access: " + name);
- return null;
- }
-
- return tokenClass;
- }
-
-
/**
* verifyIdentityProofV2 handles IdentityProofV2 as defined by RFC5272
*
@@ -1577,7 +1567,7 @@ public abstract class EnrollProfile extends BasicProfile
}
String configName = "cmc.sharedSecret.class";
- ISharedToken tokenClass = getSharedTokenClass(configName);
+ ISharedToken tokenClass = CMS.getSharedTokenClass(configName);
if (tokenClass == null) {
msg = " Failed to retrieve shared secret plugin class";
@@ -1681,7 +1671,7 @@ public abstract class EnrollProfile extends BasicProfile
return false;
String configName = "cmc.sharedSecret.class";
- ISharedToken tokenClass = getSharedTokenClass(configName);
+ ISharedToken tokenClass = CMS.getSharedTokenClass(configName);
if (tokenClass == null) {
CMS.debug(method + " Failed to retrieve shared secret plugin class");
return false;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java
index 24ba49473..a66cd9574 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java
@@ -142,6 +142,8 @@ public class CMCRevReqServlet extends CMSServlet {
* @param cmsReq the object holding the request and response information
*/
protected void process(CMSRequest cmsReq) throws EBaseException {
+ String method = "CMCRevReqServlet: process: ";
+ CMS.debug(method + "begins");
String cmcAgentSerialNumber = null;
IArgBlock httpParams = cmsReq.getHttpParams();
@@ -151,7 +153,7 @@ public class CMCRevReqServlet extends CMSServlet {
CMSTemplate form = null;
Locale[] locale = new Locale[1];
- CMS.debug("**** mFormPath = " + mFormPath);
+ CMS.debug(method + "**** mFormPath = " + mFormPath);
try {
form = getTemplate(mFormPath, req, locale);
} catch (IOException e) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
index 3794f109f..01c4b6aca 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
@@ -461,11 +461,11 @@ public class ListCerts extends CMSServlet {
ICertRecord rec = e.nextElement();
if (rec == null) {
- CMS.debug("ListCerts: * record " + count + " is null");
+ //CMS.debug("ListCerts: * record " + count + " is null");
break;
}
curSerial = rec.getSerialNumber();
- CMS.debug("ListCerts: * record " + count + ": " + curSerial);
+ //CMS.debug("ListCerts: * record " + count + ": " + curSerial);
if (count == 0) {
firstSerial = curSerial;
@@ -493,11 +493,11 @@ public class ListCerts extends CMSServlet {
}
if (mReverse) {
- CMS.debug("ListCerts: returning with rcount: " + rcount);
+ //CMS.debug("ListCerts: returning with rcount: " + rcount);
recs[rcount++] = rec;
} else {
- CMS.debug("ListCerts: returning with arg block");
+ //CMS.debug("ListCerts: returning with arg block");
IArgBlock rarg = CMS.createArgBlock();
fillRecordIntoArg(rec, rarg);
argSet.addRepeatRecord(rarg);
@@ -514,7 +514,7 @@ public class ListCerts extends CMSServlet {
CMS.debug("ListCerts: fill records into arg block and argSet");
for (int ii = rcount - 1; ii >= 0; ii--) {
if (recs[ii] != null) {
- CMS.debug("ListCerts: processing recs[" + ii + "]");
+ //CMS.debug("ListCerts: processing recs[" + ii + "]");
IArgBlock rarg = CMS.createArgBlock();
// CMS.debug("item " + ii + " is serial #" + recs[ii].getSerialNumber());
fillRecordIntoArg(recs[ii], rarg);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
index 8d6c37f2c..067dce76b 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java
@@ -25,6 +25,7 @@ import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
+import java.security.cert.CertificateExpiredException;
import java.util.Date;
import java.util.Hashtable;
@@ -55,9 +56,9 @@ import org.mozilla.jss.pkix.cmc.OtherInfo;
import org.mozilla.jss.pkix.cmc.OtherMsg;
import org.mozilla.jss.pkix.cmc.PendInfo;
import org.mozilla.jss.pkix.cmc.ResponseBody;
+import org.mozilla.jss.pkix.cmc.RevokeRequest;
import org.mozilla.jss.pkix.cmc.TaggedAttribute;
import org.mozilla.jss.pkix.cmc.TaggedRequest;
-import org.mozilla.jss.pkix.cmmf.RevRequest;
import org.mozilla.jss.pkix.cms.ContentInfo;
import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo;
import org.mozilla.jss.pkix.cms.EnvelopedData;
@@ -76,8 +77,10 @@ import com.netscape.certsrv.base.SessionContext;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
+import com.netscape.certsrv.logging.AuditEvent;
import com.netscape.certsrv.logging.AuditFormat;
import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.logging.event.CertStatusChangeRequestProcessedEvent;
import com.netscape.certsrv.profile.IEnrollProfile;
import com.netscape.certsrv.request.IRequest;
import com.netscape.certsrv.request.IRequestQueue;
@@ -101,6 +104,8 @@ import netscape.security.x509.X509Key;
* @version $ $, $Date$
*/
public class CMCOutputTemplate {
+ protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger();
+
public CMCOutputTemplate() {
}
@@ -212,14 +217,12 @@ public class CMCOutputTemplate {
}
}
} else {
- CMS.debug(method + " reqs null. why?");
+ CMS.debug(method + " reqs null. could be revocation");
}
TaggedAttribute tagattr = null;
CMCStatusInfo cmcStatusInfo = null;
-//cfu
-
SEQUENCE decryptedPOPBpids = (SEQUENCE) context.get("decryptedPOP");
if (decryptedPOPBpids != null && decryptedPOPBpids.size() > 0) {
OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
@@ -880,8 +883,8 @@ public class CMCOutputTemplate {
String salt = "lala123" + date.toString();
byte[] dig;
try {
- MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
- dig = SHA1Digest.digest(salt.getBytes());
+ MessageDigest SHA2Digest = MessageDigest.getInstance("SHA256");
+ dig = SHA2Digest.digest(salt.getBytes());
} catch (NoSuchAlgorithmException ex) {
dig = salt.getBytes();
}
@@ -920,22 +923,59 @@ public class CMCOutputTemplate {
private int processRevokeRequestControl(TaggedAttribute attr,
SEQUENCE controlSeq, int bpid) throws InvalidBERException, EBaseException,
IOException {
+ String method = "CMCOutputTemplate: processRevokeRequestControl: ";
+ String msg = "";
+ CMS.debug(method + "begins");
boolean revoke = false;
SessionContext context = SessionContext.getContext();
+ String authManagerId = (String) context.get(SessionContext.AUTH_MANAGER_ID);
+ if (authManagerId == null) {
+ CMS.debug(method + "authManagerId null.????");
+ //unlikely, but...
+ authManagerId = "none";
+ } else {
+ CMS.debug(method + "authManagerId =" + authManagerId);
+ }
+
+ // in case of CMCUserSignedAuth,
+ // for matching signer and revoked cert principal
+ X500Name signerPrincipal = null;
+
+ // for auditing
+ String auditRequesterID = null;
+ auditRequesterID = (String) context.get(SessionContext.USER_ID);
+
+ if (auditRequesterID != null) {
+ auditRequesterID = auditRequesterID.trim();
+ } else {
+ auditRequesterID = ILogger.NONROLEUSER;
+ }
+ signerPrincipal = (X500Name) context.get(SessionContext.CMC_SIGNER_PRINCIPAL);
+ String auditSubjectID = null;
+ String auditRequestType = "revoke";
+ String auditSerialNumber = null;
+ String auditReasonNum = null;
+ RequestStatus auditApprovalStatus = RequestStatus.REJECTED;
+
if (attr != null) {
INTEGER attrbpid = attr.getBodyPartID();
CMCStatusInfo cmcStatusInfo = null;
SET vals = attr.getValues();
if (vals.size() > 0) {
- RevRequest revRequest =
- (RevRequest) (ASN1Util.decode(new RevRequest.Template(),
- ASN1Util.encode(vals.elementAt(0))));
- OCTET_STRING str = revRequest.getSharedSecret();
+ RevokeRequest revRequest = (RevokeRequest) (ASN1Util.decode(new RevokeRequest.Template(),
+ ASN1Util.encode(vals.elementAt(0))));
+ OCTET_STRING reqSecret = revRequest.getSharedSecret();
INTEGER pid = attr.getBodyPartID();
TaggedAttribute tagattr = null;
INTEGER revokeCertSerial = revRequest.getSerialNumber();
+ ENUMERATED n = revRequest.getReason();
+ RevocationReason reason = toRevocationReason(n);
+ auditReasonNum = reason.toString();
BigInteger revokeSerial = new BigInteger(revokeCertSerial.toByteArray());
- if (str == null) {
+ auditSerialNumber = revokeSerial.toString();
+
+ if (reqSecret == null) {
+ CMS.debug(method + "no shared secret in request; Checking signature;");
boolean needVerify = true;
try {
needVerify = CMS.getConfigStore().getBoolean("cmc.revokeCert.verify", true);
@@ -943,67 +983,75 @@ public class CMCOutputTemplate {
}
if (needVerify) {
- Integer num1 = (Integer) context.get("numOfOtherMsgs");
- int num = num1.intValue();
- for (int i = 0; i < num; i++) {
- OtherMsg data = (OtherMsg) context.get("otherMsg" + i);
- INTEGER dpid = data.getBodyPartID();
- if (pid.longValue() == dpid.longValue()) {
- ANY msgValue = data.getOtherMsgValue();
- SignedData msgData =
- (SignedData) msgValue.decodeWith(SignedData.getTemplate());
- if (!verifyRevRequestSignature(msgData)) {
- OtherInfo otherInfo =
- new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK),
- null);
- SEQUENCE failed_bpids = new SEQUENCE();
- failed_bpids.addElement(attrbpid);
- cmcStatusInfo =
- new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null,
- otherInfo);
- tagattr = new TaggedAttribute(
- new INTEGER(bpid++),
- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
- controlSeq.addElement(tagattr);
- return bpid;
+ if (authManagerId.equals("CMCUserSignedAuth")) {
+ if (signerPrincipal == null) {
+ CMS.debug(method + "missing CMC signer principal");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_MESSAGE_CHECK),
+ null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null,
+ otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ } else { // !CMCUserSignedAuth
+
+ // this code is making the assumption that OtherMsg
+ // is used for signer info in signed cmc revocation,
+ // when in fact the signer info is
+ // in the outer layer and should have already been
+ // verified in the auth manager;
+ // Left here for possible legacy client(s)
+
+ Integer num1 = (Integer) context.get("numOfOtherMsgs");
+ CMS.debug(method + "found numOfOtherMsgs =" + num1.toString());
+ int num = num1.intValue();
+ for (int i = 0; i < num; i++) {
+ OtherMsg data = (OtherMsg) context.get("otherMsg" + i);
+ INTEGER dpid = data.getBodyPartID();
+ if (pid.longValue() == dpid.longValue()) {
+ CMS.debug(method + "body part id match;");
+ ANY msgValue = data.getOtherMsgValue();
+ SignedData msgData = (SignedData) msgValue.decodeWith(SignedData.getTemplate());
+ if (!verifyRevRequestSignature(msgData)) {
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL,
+ new INTEGER(OtherInfo.BAD_MESSAGE_CHECK),
+ null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids,
+ (String) null,
+ otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+ return bpid;
+ }
+ } else {
+ CMS.debug(method + "body part id do not match;");
}
}
}
}
revoke = true;
+ } else { //use shared secret; request unsigned
+ CMS.debug(method + "checking shared secret");
// check shared secret
- } else {
- ISharedToken tokenClass = null;
- boolean sharedSecretFound = true;
- String name = null;
- try {
- name = CMS.getConfigStore().getString("cmc.revokeCert.sharedSecret.class");
- } catch (EPropertyNotFound e) {
- CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
- sharedSecretFound = false;
- } catch (EBaseException e) {
- CMS.debug("EnrollProfile: Failed to find the token class in the configuration file.");
- sharedSecretFound = false;
- }
-
- try {
- tokenClass = (ISharedToken) Class.forName(name).newInstance();
- } catch (ClassNotFoundException e) {
- CMS.debug("EnrollProfile: Failed to find class name: " + name);
- sharedSecretFound = false;
- } catch (InstantiationException e) {
- CMS.debug("EnrollProfile: Failed to instantiate class: " + name);
- sharedSecretFound = false;
- } catch (IllegalAccessException e) {
- CMS.debug("EnrollProfile: Illegal access: " + name);
- sharedSecretFound = false;
- }
-
- if (!sharedSecretFound) {
- CMS.debug("CMCOutputTemplate: class for shared secret was not found.");
- OtherInfo otherInfo =
- new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null);
+ //TODO: remember to provide one-time-use when working
+ // on shared token
+ ISharedToken tokenClass =
+ CMS.getSharedTokenClass("cmc.revokeCert.sharedSecret.class");
+ if (tokenClass == null) {
+ CMS.debug(method + " Failed to retrieve shared secret plugin class");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR),
+ null);
SEQUENCE failed_bpids = new SEQUENCE();
failed_bpids.addElement(attrbpid);
cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
@@ -1014,15 +1062,13 @@ public class CMCOutputTemplate {
return bpid;
}
- String sharedSecret = null;
- if (tokenClass != null) {
- sharedSecret = tokenClass.getSharedToken(revokeSerial);
- }
+ String sharedSecret =
+ sharedSecret = tokenClass.getSharedToken(revokeSerial);
if (sharedSecret == null) {
- CMS.debug("CMCOutputTemplate: class for shared secret was not found.");
- OtherInfo otherInfo =
- new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null);
+ CMS.debug("CMCOutputTemplate: shared secret not found.");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR),
+ null);
SEQUENCE failed_bpids = new SEQUENCE();
failed_bpids.addElement(attrbpid);
cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
@@ -1033,15 +1079,17 @@ public class CMCOutputTemplate {
return bpid;
}
- byte[] strb = str.toByteArray();
- String clientSC = new String(strb);
+ byte[] reqSecretb = reqSecret.toByteArray();
+ String clientSC = new String(reqSecretb);
if (clientSC.equals(sharedSecret)) {
- CMS.debug("CMCOutputTemplate: Both client and server shared secret are the same, can go ahead to revoke certificate.");
+ CMS.debug(method
+ + " Client and server shared secret are the same, can go ahead and revoke certificate.");
revoke = true;
} else {
- CMS.debug("CMCOutputTemplate: Both client and server shared secret are not the same, cant revoke certificate.");
- OtherInfo otherInfo =
- new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null);
+ CMS.debug(method
+ + " Client and server shared secret are not the same, cannot revoke certificate.");
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK),
+ null);
SEQUENCE failed_bpids = new SEQUENCE();
failed_bpids.addElement(attrbpid);
cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
@@ -1049,6 +1097,16 @@ public class CMCOutputTemplate {
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
controlSeq.addElement(tagattr);
+
+ audit(new CertStatusChangeRequestProcessedEvent(
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus));
+
return bpid;
}
}
@@ -1060,11 +1118,11 @@ public class CMCOutputTemplate {
try {
record = repository.readCertificateRecord(revokeSerial);
} catch (EBaseException ee) {
- CMS.debug("CMCOutputTemplate: Exception: " + ee.toString());
+ CMS.debug(method + "Exception: " + ee.toString());
}
if (record == null) {
- CMS.debug("CMCOutputTemplate: The certificate is not found");
+ CMS.debug(method + " The certificate is not found");
OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null);
SEQUENCE failed_bpids = new SEQUENCE();
failed_bpids.addElement(attrbpid);
@@ -1088,11 +1146,46 @@ public class CMCOutputTemplate {
controlSeq.addElement(tagattr);
return bpid;
}
+
X509CertImpl impl = record.getCertificate();
+
+ X500Name certPrincipal = (X500Name) impl.getSubjectDN();
+ auditSubjectID = certPrincipal.getCommonName();
+
+ // in case of user-signed request, check if signer
+ // principal matches that of the revoking cert
+ if ((reqSecret == null) && authManagerId.equals("CMCUserSignedAuth")) {
+ if (!certPrincipal.equals(signerPrincipal)) {
+ msg = "certificate principal and signer do not match";
+ CMS.debug(method + msg);
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY),
+ null);
+ SEQUENCE failed_bpids = new SEQUENCE();
+ failed_bpids.addElement(attrbpid);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, msg,
+ otherInfo);
+ tagattr = new TaggedAttribute(
+ new INTEGER(bpid++),
+ OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
+ controlSeq.addElement(tagattr);
+
+ audit(new CertStatusChangeRequestProcessedEvent(
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus));
+
+ return bpid;
+ } else {
+ CMS.debug(method + "certificate principal and signer match");
+ }
+ }
+
X509CertImpl[] impls = new X509CertImpl[1];
impls[0] = impl;
- ENUMERATED n = revRequest.getReason();
- RevocationReason reason = toRevocationReason(n);
CRLReasonExtension crlReasonExtn = new CRLReasonExtension(reason);
CRLExtensions entryExtn = new CRLExtensions();
GeneralizedTime t = revRequest.getInvalidityDate();
@@ -1105,8 +1198,8 @@ public class CMCOutputTemplate {
entryExtn.set(crlReasonExtn.getName(), crlReasonExtn);
}
- RevokedCertImpl revCertImpl =
- new RevokedCertImpl(impl.getSerialNumber(), CMS.getCurrentDate(), entryExtn);
+ RevokedCertImpl revCertImpl = new RevokedCertImpl(impl.getSerialNumber(), CMS.getCurrentDate(),
+ entryExtn);
RevokedCertImpl[] revCertImpls = new RevokedCertImpl[1];
revCertImpls[0] = revCertImpl;
IRequestQueue queue = ca.getRequestQueue();
@@ -1122,20 +1215,30 @@ public class CMCOutputTemplate {
RequestStatus stat = revReq.getRequestStatus();
if (stat == RequestStatus.COMPLETE) {
Integer result = revReq.getExtDataInInteger(IRequest.RESULT);
- CMS.debug("CMCOutputTemplate: revReq result = " + result);
+ CMS.debug(method + " revReq result = " + result);
if (result.equals(IRequest.RES_ERROR)) {
CMS.debug("CMCOutputTemplate: revReq exception: " +
revReq.getExtDataInString(IRequest.ERROR));
- OtherInfo otherInfo =
- new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null);
+ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST),
+ null);
SEQUENCE failed_bpids = new SEQUENCE();
failed_bpids.addElement(attrbpid);
- cmcStatusInfo =
- new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo);
+ cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null,
+ otherInfo);
tagattr = new TaggedAttribute(
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
controlSeq.addElement(tagattr);
+
+ audit(new CertStatusChangeRequestProcessedEvent(
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus));
+
return bpid;
}
}
@@ -1148,7 +1251,7 @@ public class CMCOutputTemplate {
impl.getSubjectDN(),
impl.getSerialNumber().toString(16),
reason.toString() });
- CMS.debug("CMCOutputTemplate: Certificate get revoked.");
+ CMS.debug(method + " Certificate revoked.");
SEQUENCE success_bpids = new SEQUENCE();
success_bpids.addElement(attrbpid);
cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS,
@@ -1157,6 +1260,16 @@ public class CMCOutputTemplate {
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
controlSeq.addElement(tagattr);
+
+ auditApprovalStatus = RequestStatus.COMPLETE;
+ audit(new CertStatusChangeRequestProcessedEvent(
+ auditSubjectID,
+ ILogger.SUCCESS,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus));
return bpid;
} else {
OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null);
@@ -1167,6 +1280,16 @@ public class CMCOutputTemplate {
new INTEGER(bpid++),
OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo);
controlSeq.addElement(tagattr);
+
+ audit(new CertStatusChangeRequestProcessedEvent(
+ auditSubjectID,
+ ILogger.FAILURE,
+ auditRequesterID,
+ auditSerialNumber,
+ auditRequestType,
+ auditReasonNum,
+ auditApprovalStatus));
+
return bpid;
}
}
@@ -1175,54 +1298,81 @@ public class CMCOutputTemplate {
return bpid;
}
+ protected void audit(AuditEvent event) {
+
+ String template = event.getMessage();
+ Object[] params = event.getParameters();
+
+ String message = CMS.getLogMessage(template, params);
+
+ audit(message);
+ }
+
+ protected void audit(String msg) {
+ // in this case, do NOT strip preceding/trailing whitespace
+ // from passed-in String parameters
+
+ if (mSignedAuditLogger == null) {
+ return;
+ }
+
+ mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT,
+ null,
+ ILogger.S_SIGNED_AUDIT,
+ ILogger.LL_SECURITY,
+ msg);
+ }
+
private RevocationReason toRevocationReason(ENUMERATED n) {
long code = n.getValue();
- if (code == RevRequest.aACompromise.getValue())
+ if (code == RevokeRequest.aACompromise.getValue())
return RevocationReason.UNSPECIFIED;
- else if (code == RevRequest.affiliationChanged.getValue())
+ else if (code == RevokeRequest.affiliationChanged.getValue())
return RevocationReason.AFFILIATION_CHANGED;
- else if (code == RevRequest.cACompromise.getValue())
+ else if (code == RevokeRequest.cACompromise.getValue())
return RevocationReason.CA_COMPROMISE;
- else if (code == RevRequest.certificateHold.getValue())
+ else if (code == RevokeRequest.certificateHold.getValue())
return RevocationReason.CERTIFICATE_HOLD;
- else if (code == RevRequest.cessationOfOperation.getValue())
+ else if (code == RevokeRequest.cessationOfOperation.getValue())
return RevocationReason.CESSATION_OF_OPERATION;
- else if (code == RevRequest.keyCompromise.getValue())
+ else if (code == RevokeRequest.keyCompromise.getValue())
return RevocationReason.KEY_COMPROMISE;
- else if (code == RevRequest.privilegeWithdrawn.getValue())
+ else if (code == RevokeRequest.privilegeWithdrawn.getValue())
return RevocationReason.UNSPECIFIED;
- else if (code == RevRequest.removeFromCRL.getValue())
+ else if (code == RevokeRequest.removeFromCRL.getValue())
return RevocationReason.REMOVE_FROM_CRL;
- else if (code == RevRequest.superseded.getValue())
+ else if (code == RevokeRequest.superseded.getValue())
return RevocationReason.SUPERSEDED;
- else if (code == RevRequest.unspecified.getValue())
+ else if (code == RevokeRequest.unspecified.getValue())
return RevocationReason.UNSPECIFIED;
return RevocationReason.UNSPECIFIED;
}
private boolean verifyRevRequestSignature(SignedData msgData) {
+ String method = "CMCOutputTemplate: verifyRevRequestSignature: ";
+ CMS.debug(method + "begins");
try {
EncapsulatedContentInfo ci = msgData.getContentInfo();
OCTET_STRING content = ci.getContent();
ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray());
TaggedAttribute tattr = (TaggedAttribute) (new TaggedAttribute.Template()).decode(s);
SET values = tattr.getValues();
- RevRequest revRequest = null;
- if (values != null && values.size() > 0)
- revRequest =
- (RevRequest) (ASN1Util.decode(new RevRequest.Template(),
- ASN1Util.encode(values.elementAt(0))));
+ RevokeRequest revRequest = null;
+ if (values != null && values.size() > 0) {
+ revRequest = (RevokeRequest) (ASN1Util.decode(new RevokeRequest.Template(),
+ ASN1Util.encode(values.elementAt(0))));
+ } else {
+ CMS.debug(method + "attribute null");
+ return false;
+ }
SET dias = msgData.getDigestAlgorithmIdentifiers();
int numDig = dias.size();
Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>();
for (int i = 0; i < numDig; i++) {
- AlgorithmIdentifier dai =
- (AlgorithmIdentifier) dias.elementAt(i);
- String name =
- DigestAlgorithm.fromOID(dai.getOID()).toString();
- MessageDigest md =
- MessageDigest.getInstance(name);
+ AlgorithmIdentifier dai = (AlgorithmIdentifier) dias.elementAt(i);
+ String name = DigestAlgorithm.fromOID(dai.getOID()).toString();
+ MessageDigest md = MessageDigest.getInstance(name);
byte[] digest = md.digest(content.toByteArray());
digs.put(name, digest);
}
@@ -1230,8 +1380,7 @@ public class CMCOutputTemplate {
SET sis = msgData.getSignerInfos();
int numSis = sis.size();
for (int i = 0; i < numSis; i++) {
- org.mozilla.jss.pkix.cms.SignerInfo si =
- (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i);
+ org.mozilla.jss.pkix.cms.SignerInfo si = (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i);
String name = si.getDigestAlgorithm().toString();
byte[] digest = digs.get(name);
if (digest == null) {
@@ -1242,17 +1391,15 @@ public class CMCOutputTemplate {
}
SignerIdentifier sid = si.getSignerIdentifier();
if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) {
- org.mozilla.jss.pkix.cms.IssuerAndSerialNumber issuerAndSerialNumber =
- sid.getIssuerAndSerialNumber();
+ org.mozilla.jss.pkix.cms.IssuerAndSerialNumber issuerAndSerialNumber = sid
+ .getIssuerAndSerialNumber();
java.security.cert.X509Certificate cert = null;
if (msgData.hasCertificates()) {
SET certs = msgData.getCertificates();
int numCerts = certs.size();
for (int j = 0; j < numCerts; j++) {
- org.mozilla.jss.pkix.cert.Certificate certJss =
- (Certificate) certs.elementAt(j);
- org.mozilla.jss.pkix.cert.CertificateInfo certI =
- certJss.getInfo();
+ org.mozilla.jss.pkix.cert.Certificate certJss = (Certificate) certs.elementAt(j);
+ org.mozilla.jss.pkix.cert.CertificateInfo certI = certJss.getInfo();
Name issuer = certI.getIssuer();
byte[] issuerB = ASN1Util.encode(issuer);
INTEGER sn = certI.getSerialNumber();
@@ -1268,11 +1415,33 @@ public class CMCOutputTemplate {
}
if (cert != null) {
+ CMS.debug(method + "found cert");
PublicKey pbKey = cert.getPublicKey();
PK11PubKey pubK = PK11PubKey.fromSPKI(((X509Key) pbKey).getKey());
si.verify(digest, ci.getContentType(), pubK);
+
+ // now check validity of the cert
+ java.security.cert.X509Certificate[] x509Certs = new java.security.cert.X509Certificate[1];
+ x509Certs[0] = cert;
+ if (CMS.isRevoked(x509Certs)) {
+ CMS.debug(method + "CMC signing cert is a revoked certificate");
+ return false;
+ }
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException e) {
+ CMS.debug(method + "CMC signing cert is an expired certificate");
+ return false;
+ } catch (Exception e) {
+ return false;
+ }
+
return true;
+ } else {
+ CMS.debug(method + "cert not found");
}
+ } else {
+ CMS.debug(method + "unsupported SignerIdentifier for CMC revocation");
}
}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java b/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java
index 83a2d8cf0..4578a988a 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java
@@ -158,9 +158,9 @@ public class GenPendingTemplateFiller implements ICMSTemplateFiller {
byte[] dig;
try {
- MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1");
+ MessageDigest SHA2Digest = MessageDigest.getInstance("SHA256");
- dig = SHA1Digest.digest(salt.getBytes());
+ dig = SHA2Digest.digest(salt.getBytes());
} catch (NoSuchAlgorithmException ex) {
dig = salt.getBytes();
}
@@ -199,16 +199,15 @@ public class GenPendingTemplateFiller implements ICMSTemplateFiller {
SignerIdentifier si = new
SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null);
- // SHA1 is the default digest Alg for now.
DigestAlgorithm digestAlg = null;
SignatureAlgorithm signAlg = null;
org.mozilla.jss.crypto.PrivateKey privKey = CryptoManager.getInstance().findPrivKeyByCert(x509cert);
org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType();
if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA)) {
- signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest;
- } else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA)) {
- signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest;
+ signAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest;
+ } else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.EC)) {
+ signAlg = SignatureAlgorithm.ECSignatureWithSHA256Digest;
} else {
CMS.debug("GenPendingTemplateFiller::getTemplateParams() - "
+ "keyType " + keyType.toString()
@@ -220,8 +219,8 @@ public class GenPendingTemplateFiller implements ICMSTemplateFiller {
byte[] digest = null;
try {
- SHADigest = MessageDigest.getInstance("SHA1");
- digestAlg = DigestAlgorithm.SHA1;
+ SHADigest = MessageDigest.getInstance("SHA256");
+ digestAlg = DigestAlgorithm.SHA256;
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
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 93039a486..330b5ff66 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
@@ -413,7 +413,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
}
setInputsIntoContext(request, profile, ctx);
- CMS.debug("ProfileSubmistServlet: set Inputs into Context");
+ CMS.debug("ProfileSubmitCMCServlet: set Inputs into Context");
// before creating the request, authenticate the request
@@ -560,9 +560,14 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
// In case of decryptedPOP, request already exists, find it and
// put in provedReq.
IRequest provedReq = null;
+ boolean isRevoke = false;
if (reqs == null) {
// handling DecryptedPOP request here
Integer reqID = (Integer) context.get("cmcDecryptedPopReqId");
+ if (reqID == null) {
+ CMS.debug("ProfileSubmitCMCServlet: revocation request");
+ isRevoke = true;
+ } else {
provedReq = profile.getRequestQueue().findRequest(new RequestId(reqID.toString()));
if (provedReq == null) {
@@ -584,6 +589,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
} else {
CMS.debug("ProfileSubmitCMCServlet: provedReq not null");
}
+ }
}
String errorCode = null;
@@ -592,7 +598,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
///////////////////////////////////////////////
// populate request
///////////////////////////////////////////////
- for (int k = 0; (provedReq == null) &&(k < reqs.length); k++) {
+ for (int k = 0; (!isRevoke) && (provedReq == null) &&(k < reqs.length); k++) {
// adding parameters to request
setInputsIntoRequest(request, profile, reqs[k]);
@@ -712,7 +718,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet {
if (reqs != null && reqs.length > 0)
error_codes = new int[reqs.length];
- for (int k = 0; (provedReq == null) && (k < reqs.length); k++) {
+ for (int k = 0; (!isRevoke) && (provedReq == null) && (k < reqs.length); k++) {
try {
// reset the "auditRequesterID"
auditRequesterID = auditRequesterID(reqs[k]);