diff --git a/SOURCES/pki-core-CMC-id-cmc-statusInfoV2.patch b/SOURCES/pki-core-CMC-id-cmc-statusInfoV2.patch new file mode 100644 index 0000000..25d8f46 --- /dev/null +++ b/SOURCES/pki-core-CMC-id-cmc-statusInfoV2.patch @@ -0,0 +1,1927 @@ +From 724b91a4688ca73a07c6c225e0e61e0a79073f42 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Fri, 16 Jun 2017 18:20:38 -0700 +Subject: [PATCH] Ticket #2616 CMC: id-cmc-statusInfo ==> id-cmc-statusInfoV2 + +This patch contains the following update: +* Structurely, CMCStatusInfo to CMCStatusInfoV2 update; no extendedFailInfo has been added at this point +* In case of EncryptedPOP, instead of returning with CMCStatus pending where + PendInfo contains the requestID, it now returns CMCStatus failed whith + responseInfo control contains the requestID. On the client side, CMCRequest + now processes the responseInfo and returns the DecryptedPOP with requestID in + the regInfo control. CMCResponse has been updated to handle the new controls + as well. +* A number of fail info codes are now being supported by the server to add + clarity to CMC failed status, including: + badMessageCheck, badRequest, unsuportedExt, badIdentity, popRequired, and popFailed. + +(cherry picked from commit 6273907e0ca36425fa30c106b7fdd28c510b1162) +--- + .../certsrv/profile/ECMCBadIdentityException.java | 54 ++++++ + .../profile/ECMCBadMessageCheckException.java | 54 ++++++ + .../certsrv/profile/ECMCBadRequestException.java | 53 +++++ + .../certsrv/profile/ECMCPopFailedException.java | 53 +++++ + .../certsrv/profile/ECMCPopRequiredException.java | 59 ++++++ + .../profile/ECMCUnsupportedExtException.java | 53 +++++ + .../src/com/netscape/cmstools/CMCRequest.java | 69 +++++-- + .../src/com/netscape/cmstools/CMCResponse.java | 36 +++- + .../netscape/cms/profile/common/EnrollProfile.java | 195 ++++++++++++------- + .../cms/servlet/common/CMCOutputTemplate.java | 216 ++++++++++++--------- + .../servlet/common/GenPendingTemplateFiller.java | 10 +- + .../servlet/profile/ProfileSubmitCMCServlet.java | 96 ++++++++- + .../netscape/cms/servlet/request/CheckRequest.java | 8 +- + base/server/cmsbundle/src/UserMessages.properties | 1 + + 14 files changed, 747 insertions(+), 210 deletions(-) + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCBadIdentityException.java + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCBadMessageCheckException.java + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCBadRequestException.java + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCPopFailedException.java + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCPopRequiredException.java + create mode 100644 base/common/src/com/netscape/certsrv/profile/ECMCUnsupportedExtException.java + +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCBadIdentityException.java b/base/common/src/com/netscape/certsrv/profile/ECMCBadIdentityException.java +new file mode 100644 +index 0000000..118a8ee +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCBadIdentityException.java +@@ -0,0 +1,54 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC badIdentity condition. ++ * The framework raises this exception when a request fails identity ++ * checks ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCBadIdentityException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = -89147145684990870L; ++ ++ /** ++ * Creates an exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. ++ */ ++ public ECMCBadIdentityException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCBadIdentityException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++ ++ public ECMCBadIdentityException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++} +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCBadMessageCheckException.java b/base/common/src/com/netscape/certsrv/profile/ECMCBadMessageCheckException.java +new file mode 100644 +index 0000000..fb56eb4 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCBadMessageCheckException.java +@@ -0,0 +1,54 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC badMessageCheck condition. ++ * The framework raises this exception when a request fails various ++ * checks ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCBadMessageCheckException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = 1353005739159030604L; ++ ++ /** ++ * Creates an exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. ++ */ ++ public ECMCBadMessageCheckException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCBadMessageCheckException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++ public ECMCBadMessageCheckException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++ ++} +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCBadRequestException.java b/base/common/src/com/netscape/certsrv/profile/ECMCBadRequestException.java +new file mode 100644 +index 0000000..dc4a107 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCBadRequestException.java +@@ -0,0 +1,53 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC badRequest condition. ++ * The framework raises this exception when a request fails ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCBadRequestException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = -957171725482446695L; ++ ++ /** ++ * Creates an exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. ++ */ ++ public ECMCBadRequestException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCBadRequestException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++ public ECMCBadRequestException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++ ++} +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCPopFailedException.java b/base/common/src/com/netscape/certsrv/profile/ECMCPopFailedException.java +new file mode 100644 +index 0000000..cc87434 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCPopFailedException.java +@@ -0,0 +1,53 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC popFailed condition. ++ * The framework raises this exception when a request fails POP ++ * (Proof Of Possession) check ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCPopFailedException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = -3098694565652563197L; ++ ++ /** ++ * Creates an exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. ++ */ ++ public ECMCPopFailedException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCPopFailedException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++ public ECMCPopFailedException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++} +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCPopRequiredException.java b/base/common/src/com/netscape/certsrv/profile/ECMCPopRequiredException.java +new file mode 100644 +index 0000000..25a7bc0 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCPopRequiredException.java +@@ -0,0 +1,59 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC popRequired condition. ++ * The framework raises this exception when a request is missing POP ++ * (Proof Of Possession) ++ *

++ * A CMC request with missing POP will not be processed immediately. ++ * Round trip is required to return with CMC direct POP (DecryptedPOP) ++ * for processing the request again. ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCPopRequiredException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = 8328983412028345364L; ++ ++ /** ++ * Creates a defer exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. This message ++ * should indicate the reason why a request ++ * is deferred. ++ */ ++ public ECMCPopRequiredException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCPopRequiredException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++ public ECMCPopRequiredException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++} +diff --git a/base/common/src/com/netscape/certsrv/profile/ECMCUnsupportedExtException.java b/base/common/src/com/netscape/certsrv/profile/ECMCUnsupportedExtException.java +new file mode 100644 +index 0000000..b33c58a +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/profile/ECMCUnsupportedExtException.java +@@ -0,0 +1,53 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.profile; ++ ++/** ++ * This represents a profile specific exception for handling ++ * CMC unsupportedExt condition. ++ * The framework raises this exception when a request contains extensions ++ * that's not supported ++ *

++ * ++ * @version $Revision$, $Date$ ++ */ ++public class ECMCUnsupportedExtException extends EProfileException { ++ ++ /** ++ * ++ */ ++ private static final long serialVersionUID = -2065658791983639446L; ++ ++ /** ++ * Creates an exception. ++ * ++ * @param msg localized message that will be ++ * displayed to end user. ++ */ ++ public ECMCUnsupportedExtException(String msg) { ++ super(msg); ++ } ++ ++ public ECMCUnsupportedExtException(String msg, Throwable cause) { ++ super(msg, cause); ++ } ++ ++ public ECMCUnsupportedExtException(Throwable cause) { ++ super(cause.getMessage(), cause); ++ } ++} +diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java +index 00e03a7..fd59aa1 100644 +--- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java ++++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java +@@ -65,7 +65,7 @@ import org.mozilla.jss.crypto.X509Certificate; + import org.mozilla.jss.pkcs10.CertificationRequest; + import org.mozilla.jss.pkcs10.CertificationRequestInfo; + import org.mozilla.jss.pkix.cmc.CMCCertId; +-import org.mozilla.jss.pkix.cmc.CMCStatusInfo; ++import org.mozilla.jss.pkix.cmc.CMCStatusInfoV2; + import org.mozilla.jss.pkix.cmc.DecryptedPOP; + import org.mozilla.jss.pkix.cmc.EncryptedPOP; + import org.mozilla.jss.pkix.cmc.GetCert; +@@ -1609,14 +1609,15 @@ public class CMCRequest { + * + * @param prevResponse file + * @param privKey +- * @return encryptedPop and reqIdString in Object[] ++ * @return encryptedPop and reqIdOS (requestID in Octet String in Object[] + * @author cfu + */ + private static Object[] processEncryptedPopResponse( + String prevResponse) { + // the values to be returned + EncryptedPOP encryptedPop = null; +- String reqIdString = null; // capture the requestId; ++ String reqIdString = null; ++ OCTET_STRING reqIdOS = null; // capture the requestId; + + String method = "processEncryptedPopResponse: "; + System.out.println(method + " begins."); +@@ -1661,13 +1662,13 @@ public class CMCRequest { + TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i); + OBJECT_IDENTIFIER type = taggedAttr.getType(); + +- if (type.equals(OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo)) { +- System.out.println(method + "Control #" + i + ": CMCStatusInfo"); ++ if (type.equals(OBJECT_IDENTIFIER.id_cmc_statusInfoV2)) { ++ System.out.println(method + "Control #" + i + ": CMCStatusInfoV2"); + System.out.println(method + " OID: " + type.toString()); + SET sts = taggedAttr.getValues(); + int numSts = sts.size(); + for (int j = 0; j < numSts; j++) { +- CMCStatusInfo cst = (CMCStatusInfo) ASN1Util.decode(CMCStatusInfo.getTemplate(), ++ CMCStatusInfoV2 cst = (CMCStatusInfoV2) ASN1Util.decode(CMCStatusInfoV2.getTemplate(), + ASN1Util.encode(sts.elementAt(j))); + SEQUENCE seq = cst.getBodyList(); + StringBuilder s = new StringBuilder(" BodyList: "); +@@ -1677,7 +1678,7 @@ public class CMCRequest { + } + System.out.println(method + s); + int st = cst.getStatus(); +- if (st != CMCStatusInfo.SUCCESS && st != CMCStatusInfo.CONFIRM_REQUIRED) { ++ if (st != CMCStatusInfoV2.SUCCESS && st != CMCStatusInfoV2.CONFIRM_REQUIRED) { + String stString = cst.getStatusString(); + if (stString != null) + System.out.println(method + " Status String: " + stString); +@@ -1685,9 +1686,22 @@ public class CMCRequest { + OtherInfo.Type t = oi.getType(); + if (t == OtherInfo.FAIL) { + System.out.println(method + " OtherInfo type: FAIL"); +- System.out.println(method +- + " not what we expected, because encryptedPOP.enable is true!!!! exit now"); +- System.exit(1); ++ INTEGER failInfo = oi.getFailInfo(); ++ if (failInfo == null) { ++ System.out.println(method + "failInfo null...skipping"); ++ continue; ++ } ++ ++ if (failInfo.intValue() == OtherInfo.POP_REQUIRED) { ++ System.out.println(method + " failInfo=" + ++ OtherInfo.FAIL_INFO[failInfo.intValue()]); ++ System.out.println(method + " what we expected, as decryptedPOP.enable is true;"); ++ } else { ++ System.out.println(method + "failInfo=" + ++ OtherInfo.FAIL_INFO[failInfo.intValue()]); ++ System.out.println(method + " not what we expected when encryptedPOP.enable is true;"); ++ System.exit(1); ++ } + } else if (t == OtherInfo.PEND) { + System.out.println(method + " OtherInfo type: PEND"); + PendInfo pi = oi.getPendInfo(); +@@ -1711,9 +1725,8 @@ public class CMCRequest { + System.out.println(method + "missing pendToken in response"); + System.exit(1); + } +- System.out.println(method + " what we expected, as encryptedPOP.enable is true;"); + } +- } else if (st == CMCStatusInfo.SUCCESS) { ++ } else if (st == CMCStatusInfoV2.SUCCESS) { + System.out.println(method + " Status: SUCCESS"); + System.out.println( + method + " not what we expected, because encryptedPOP.enable is true!!!! exit now"); +@@ -1728,8 +1741,18 @@ public class CMCRequest { + + encryptedPop = (EncryptedPOP) (ASN1Util.decode(EncryptedPOP.getTemplate(), + ASN1Util.encode(encryptedPOPvals.elementAt(0)))); +- System.out.println(method + "encryptedPOP decoded successfully"); +- ++ System.out.println(method + " encryptedPOP decoded successfully"); ++ ++ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_responseInfo)) { ++ System.out.println(method + "Control #" + i + ": CMC ResponseInfo"); ++ SET riVals = taggedAttr.getValues(); ++ reqIdOS = (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), ++ ASN1Util.encode(riVals.elementAt(0)))); ++ byte[] reqIdBA = reqIdOS.toByteArray(); ++ BigInteger reqIdBI = new BigInteger(reqIdBA); ++ ++ System.out.println(method + " requestID: " + reqIdBI.toString()); ++ + } // we don't expect any other controls + } //for + } catch (Exception e) { +@@ -1738,13 +1761,13 @@ public class CMCRequest { + } + + System.out.println(method + "ends"); +- return new Object[] { encryptedPop, reqIdString }; ++ return new Object[] { encryptedPop, reqIdOS }; + } + + /** + * constructDecryptedPopRequest constructs request PKIData for DecryptedPOP + * +- * @param encryptedPopInfo {EncryptedPOP, reqIdString} ++ * @param encryptedPopInfo {EncryptedPOP, reqIdOS} + * @param privKey + * @return request PKIData + * @author cfu +@@ -1764,8 +1787,8 @@ public class CMCRequest { + } + + EncryptedPOP encryptedPop = (EncryptedPOP) encryptedPopInfo[0]; +- String reqIdString = (String) encryptedPopInfo[1]; +- if ((encryptedPop == null) || (reqIdString == null)) { ++ OCTET_STRING reqIdOS = (OCTET_STRING) encryptedPopInfo[1]; ++ if ((encryptedPop == null) || (reqIdOS == null)) { + System.out.println(method + "encryptedPopInfo content encryptedPop and reqIdString cannot be null"); + System.exit(1); + } +@@ -1851,7 +1874,8 @@ public class CMCRequest { + int bpid = 1; + // now construct DecryptedPOP + System.out.println(method + "constructing DecryptedPOP..."); +- decryptedPop = new DecryptedPOP(new INTEGER(reqIdString), thePOPAlgID, new OCTET_STRING(popProofValue)); ++ ++ decryptedPop = new DecryptedPOP(new INTEGER(bpid++), thePOPAlgID, new OCTET_STRING(popProofValue)); + System.out.println(method + "DecryptedPOP constructed successfully"); + System.out.println(method + "adding decryptedPop control"); + TaggedAttribute decPop = new TaggedAttribute(new INTEGER(bpid++), +@@ -1865,6 +1889,13 @@ public class CMCRequest { + controlSeq.addElement(decPop); + System.out.println(method + "decryptedPop control added"); + ++ TaggedAttribute reqIdTA = ++ new TaggedAttribute(new INTEGER(bpid++), ++ OBJECT_IDENTIFIER.id_cmc_regInfo, ++ reqIdOS); ++ controlSeq.addElement(reqIdTA); ++ System.out.println(method + "regInfo control added"); ++ + SEQUENCE otherMsgSeq = new SEQUENCE(); + + pkidata = new PKIData(controlSeq, reqSequence, new SEQUENCE(), otherMsgSeq); +diff --git a/base/java-tools/src/com/netscape/cmstools/CMCResponse.java b/base/java-tools/src/com/netscape/cmstools/CMCResponse.java +index 4c74934..5224de8 100644 +--- a/base/java-tools/src/com/netscape/cmstools/CMCResponse.java ++++ b/base/java-tools/src/com/netscape/cmstools/CMCResponse.java +@@ -19,6 +19,7 @@ package com.netscape.cmstools; + + import java.io.ByteArrayInputStream; + import java.io.FileInputStream; ++import java.math.BigInteger; + import java.text.SimpleDateFormat; + import java.util.Date; + import java.util.Locale; +@@ -33,7 +34,7 @@ import org.mozilla.jss.asn1.OCTET_STRING; + import org.mozilla.jss.asn1.SEQUENCE; + import org.mozilla.jss.asn1.SET; + import org.mozilla.jss.pkix.cert.Certificate; +-import org.mozilla.jss.pkix.cmc.CMCStatusInfo; ++import org.mozilla.jss.pkix.cmc.CMCStatusInfoV2; + import org.mozilla.jss.pkix.cmc.EncryptedPOP; + import org.mozilla.jss.pkix.cmc.OtherInfo; + import org.mozilla.jss.pkix.cmc.PendInfo; +@@ -113,13 +114,13 @@ public class CMCResponse { + TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i); + OBJECT_IDENTIFIER type = taggedAttr.getType(); + +- if (type.equals(OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo)) { +- System.out.println("Control #" + i + ": CMCStatusInfo"); ++ if (type.equals(OBJECT_IDENTIFIER.id_cmc_statusInfoV2)) { ++ System.out.println("Control #" + i + ": CMCStatusInfoV2"); + System.out.println(" OID: " + type.toString()); + SET sts = taggedAttr.getValues(); + int numSts = sts.size(); + for (int j = 0; j < numSts; j++) { +- CMCStatusInfo cst = (CMCStatusInfo) ASN1Util.decode(CMCStatusInfo.getTemplate(), ++ CMCStatusInfoV2 cst = (CMCStatusInfoV2) ASN1Util.decode(CMCStatusInfoV2.getTemplate(), + ASN1Util.encode(sts.elementAt(j))); + SEQUENCE seq = cst.getBodyList(); + +@@ -130,15 +131,23 @@ public class CMCResponse { + } + System.out.println(s); + int st = cst.getStatus(); +- if (st != CMCStatusInfo.SUCCESS && st != CMCStatusInfo.CONFIRM_REQUIRED) { ++ if (st != CMCStatusInfoV2.SUCCESS && st != CMCStatusInfoV2.CONFIRM_REQUIRED) { + String stString = cst.getStatusString(); + if (stString != null) + System.out.println(" Status String: " + stString); + OtherInfo oi = cst.getOtherInfo(); + OtherInfo.Type t = oi.getType(); +- if (t == OtherInfo.FAIL) ++ if (t == OtherInfo.FAIL) { + System.out.println(" OtherInfo type: FAIL"); +- else if (t == OtherInfo.PEND) { ++ INTEGER failInfo = oi.getFailInfo(); ++ if (failInfo == null) { ++ System.out.println("failInfo null...skipping"); ++ continue; ++ } ++ ++ System.out.println(" failInfo=" + ++ OtherInfo.FAIL_INFO[failInfo.intValue()]); ++ } else if (t == OtherInfo.PEND) { + System.out.println(" OtherInfo type: PEND"); + PendInfo pi = oi.getPendInfo(); + if (pi == null) { +@@ -163,7 +172,7 @@ public class CMCResponse { + } + + } +- } else if (st == CMCStatusInfo.SUCCESS) { ++ } else if (st == CMCStatusInfoV2.SUCCESS) { + System.out.println(" Status: SUCCESS"); + } + } +@@ -224,8 +233,17 @@ public class CMCResponse { + EncryptedPOP encryptedPOP = + (EncryptedPOP) (ASN1Util.decode(EncryptedPOP.getTemplate(), + ASN1Util.encode(encryptedPOPvals.elementAt(0)))); +- System.out.println("after encryptedPOP encode"); ++ System.out.println(" encryptedPOP decoded"); ++ ++ } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_responseInfo)) { ++ System.out.println("Control #" + i + ": CMC ResponseInfo"); ++ SET riVals = taggedAttr.getValues(); ++ OCTET_STRING reqIdOS = (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), ++ ASN1Util.encode(riVals.elementAt(0)))); ++ byte[] reqIdBA = reqIdOS.toByteArray(); ++ BigInteger reqIdBI = new BigInteger(reqIdBA); + ++ System.out.println(" requestID: " + reqIdBI.toString()); + } + } + } catch (Exception e) { +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 74da8e7..8f3e986 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 +@@ -84,6 +84,12 @@ import com.netscape.certsrv.base.SessionContext; + import com.netscape.certsrv.ca.ICertificateAuthority; + import com.netscape.certsrv.logging.AuditEvent; + import com.netscape.certsrv.logging.ILogger; ++import com.netscape.certsrv.profile.ECMCBadIdentityException; ++import com.netscape.certsrv.profile.ECMCBadMessageCheckException; ++import com.netscape.certsrv.profile.ECMCBadRequestException; ++import com.netscape.certsrv.profile.ECMCPopFailedException; ++import com.netscape.certsrv.profile.ECMCPopRequiredException; ++import com.netscape.certsrv.profile.ECMCUnsupportedExtException; + import com.netscape.certsrv.profile.EDeferException; + import com.netscape.certsrv.profile.EProfileException; + import com.netscape.certsrv.profile.ERejectException; +@@ -550,7 +556,7 @@ public abstract class EnrollProfile extends BasicProfile + throw new EProfileException(msg); + } + +- throw new EDeferException("EnrollProfile: submit: encryptedPOP defer request"); ++ throw new ECMCPopRequiredException(" Return with DecryptedPOP to complete"); + + } else { + // this profile executes request that is authenticated +@@ -726,6 +732,8 @@ public abstract class EnrollProfile extends BasicProfile + TaggedAttribute[] attributes = new TaggedAttribute[numcontrols]; + boolean id_cmc_decryptedPOP = false; + SET decPopVals = null; ++ boolean id_cmc_regInfo = false; ++ SET reqIdVals = null; + + boolean id_cmc_identification = false; + SET ident = null; +@@ -756,6 +764,10 @@ public abstract class EnrollProfile extends BasicProfile + CMS.debug(method + " id_cmc_decryptedPOP found"); + id_cmc_decryptedPOP = true; + decPopVals = attributes[i].getValues(); ++ } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_regInfo)) { ++ CMS.debug(method + "id_cmc_regInfo found"); ++ id_cmc_regInfo = true; ++ reqIdVals = attributes[i].getValues(); + } else if (oid.equals(OBJECT_IDENTIFIER.id_cmc_identification)) { + CMS.debug(method + " id_cmc_identification found"); + id_cmc_identification = true; +@@ -796,11 +808,10 @@ public abstract class EnrollProfile extends BasicProfile + + msg = " id_cmc_identification attribute value not found in"; + CMS.debug(method + msg); +-/* +- throw new EProfileException( +- CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ++ ++ throw new ECMCBadRequestException( ++ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ":" + + msg); +-*/ + } else { + ident_s = (UTF8String) (ASN1Util.decode(UTF8String.getTemplate(), + ASN1Util.encode(ident.elementAt(0)))); +@@ -812,11 +823,11 @@ public abstract class EnrollProfile extends BasicProfile + context.put("identification", bpids); + + CMS.debug(method + msg); +-/* +- throw new EProfileException( +- CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ++ ++ throw new ECMCBadRequestException( ++ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ":" + + msg); +-*/ ++ + } + } + +@@ -850,8 +861,8 @@ public abstract class EnrollProfile extends BasicProfile + method + msg); + audit(auditMessage); + +- throw new EProfileException( +- CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ++ throw new ECMCBadIdentityException( ++ CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + ":" + + msg); + } + +@@ -863,7 +874,7 @@ public abstract class EnrollProfile extends BasicProfile + + msg = " after verifyIdentityProofV2"; + CMS.debug(method + msg); +- throw new EProfileException(CMS.getUserMessage(locale, ++ throw new ECMCBadIdentityException(CMS.getUserMessage(locale, + "CMS_POI_VERIFICATION_ERROR") + msg); + } else { + CMS.debug(method + "passed verifyIdentityProofV2; Proof of Identity successful;"); +@@ -878,7 +889,7 @@ public abstract class EnrollProfile extends BasicProfile + + msg = " after verifyIdentityProof"; + CMS.debug(method + msg); +- throw new EProfileException(CMS.getUserMessage(locale, ++ throw new ECMCBadIdentityException(CMS.getUserMessage(locale, + "CMS_POI_VERIFICATION_ERROR") + msg); + } else { + CMS.debug(method + "passed verifyIdentityProof; Proof of Identity successful;"); +@@ -894,20 +905,53 @@ public abstract class EnrollProfile extends BasicProfile + ILogger.FAILURE, + method + msg); + audit(auditMessage); +- throw new EProfileException(CMS.getUserMessage(locale, +- "CMS_POI_VERIFICATION_ERROR") + ":" + method + msg); ++ throw new ECMCBadRequestException(CMS.getUserMessage(locale, ++ "CMS_POI_VERIFICATION_ERROR") + ":" + msg); + } + + if (id_cmc_decryptedPOP) { + if (decPopVals != null) { ++ if (!id_cmc_regInfo) { ++ msg = "id_cmc_decryptedPOP must be accompanied by id_cmc_regInfo for request id per server/client agreement"; ++ CMS.debug(method + msg); ++ auditMessage = CMS.getLogMessage( ++ AuditEvent.PROOF_OF_POSSESSION, ++ auditSubjectID, ++ ILogger.FAILURE, ++ method + msg); ++ audit(auditMessage); ++ ++ SEQUENCE bpids = getRequestBpids(reqSeq); ++ context.put("decryptedPOP", bpids); ++ throw new ECMCPopFailedException(CMS.getUserMessage(locale, ++ "CMS_POP_VERIFICATION_ERROR") + ":" + msg); ++ } ++ ++ OCTET_STRING reqIdOS = ++ (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), ++ ASN1Util.encode(reqIdVals.elementAt(0)))); + + DecryptedPOP decPop = (DecryptedPOP) (ASN1Util.decode(DecryptedPOP.getTemplate(), + ASN1Util.encode(decPopVals.elementAt(0)))); + CMS.debug(method + "DecryptedPOP encoded"); + +- Integer reqId = verifyDecryptedPOP(locale, decPop); ++ BigInteger reqId = verifyDecryptedPOP(locale, decPop, reqIdOS); + if (reqId != null) { + context.put("cmcDecryptedPopReqId", reqId); ++ } else { ++ msg = "DecryptedPOP failed to verify"; ++ CMS.debug(method + msg); ++ auditMessage = CMS.getLogMessage( ++ AuditEvent.PROOF_OF_POSSESSION, ++ auditSubjectID, ++ ILogger.FAILURE, ++ method + msg); ++ audit(auditMessage); ++ ++ SEQUENCE bpids = getRequestBpids(reqSeq); ++ context.put("decryptedPOP", bpids); ++ throw new ECMCPopFailedException(CMS.getUserMessage(locale, ++ "CMS_POP_VERIFICATION_ERROR") + ":" + msg); + } + } else { //decPopVals == null + msg = "id_cmc_decryptedPOP contains invalid DecryptedPOP"; +@@ -915,12 +959,14 @@ public abstract class EnrollProfile extends BasicProfile + auditMessage = CMS.getLogMessage( + AuditEvent.PROOF_OF_POSSESSION, + auditSubjectID, +- ILogger.SUCCESS, ++ ILogger.FAILURE, + method + msg); + audit(auditMessage); + + SEQUENCE bpids = getRequestBpids(reqSeq); + context.put("decryptedPOP", bpids); ++ throw new ECMCPopFailedException(CMS.getUserMessage(locale, ++ "CMS_POP_VERIFICATION_ERROR") + ":" + msg); + } + + // decryptedPOP is expected to return null; +@@ -967,9 +1013,9 @@ public abstract class EnrollProfile extends BasicProfile + } + } catch (Exception e) { + // unlikely to get here +- msg = method + " Failed to retrieve cmc.popLinkWitnessRequired"; +- CMS.debug(msg); +- throw new EProfileException(method + msg); ++ msg = " Failed to retrieve cmc.popLinkWitnessRequired"; ++ CMS.debug(method + msg); ++ throw new EProfileException( msg); + } + + int nummsgs = reqSeq.size(); +@@ -988,7 +1034,7 @@ public abstract class EnrollProfile extends BasicProfile + !context.containsKey("POPLinkWitness")) { + CMS.debug(method + "popLinkWitness(V2) required"); + if (randomSeed == null || ident_s == null) { +- msg = "no randomSeed or identification found needed for popLinkWitness(V2)"; ++ msg = "missing needed randomSeed or identification for popLinkWitness(V2)"; + CMS.debug(method + msg); + auditMessage = CMS.getLogMessage( + AuditEvent.CMC_ID_POP_LINK_WITNESS, +@@ -998,7 +1044,8 @@ public abstract class EnrollProfile extends BasicProfile + audit(auditMessage); + + context.put("POPLinkWitnessV2", bpids); +- return null; ++ throw new ECMCBadRequestException(CMS.getUserMessage(locale, ++ "CMS_POP_LINK_WITNESS_VERIFICATION_ERROR") + ":" + msg); + } + + // verifyPOPLinkWitness() will determine if this is +@@ -1021,8 +1068,8 @@ public abstract class EnrollProfile extends BasicProfile + ILogger.FAILURE, + method + msg); + audit(auditMessage); +- throw new EProfileException(CMS.getUserMessage(locale, +- "CMS_POP_LINK_WITNESS_VERIFICATION_ERROR") + msg); ++ throw new ECMCBadRequestException(CMS.getUserMessage(locale, ++ "CMS_POP_LINK_WITNESS_VERIFICATION_ERROR") + ":" + msg); + } else { + msg = ": ident_s=" + ident_s; + auditMessage = CMS.getLogMessage( +@@ -1041,6 +1088,14 @@ public abstract class EnrollProfile extends BasicProfile + + CMS.debug(method + "ends"); + return msgs; ++ } catch (ECMCBadMessageCheckException e) { ++ throw new ECMCBadMessageCheckException(e); ++ } catch (ECMCBadIdentityException e) { ++ throw new ECMCBadIdentityException(e); ++ } catch (ECMCPopFailedException e) { ++ throw new ECMCPopFailedException(e); ++ } catch (ECMCBadRequestException e) { ++ throw new ECMCBadRequestException(e); + } catch (EProfileException e) { + throw new EProfileException(e); + } catch (Exception e) { +@@ -1056,34 +1111,28 @@ public abstract class EnrollProfile extends BasicProfile + * + * @author cfu + */ +- private Integer verifyDecryptedPOP(Locale locale, DecryptedPOP decPop) +- throws EProfileException { ++ private BigInteger verifyDecryptedPOP(Locale locale, ++ DecryptedPOP decPop, ++ OCTET_STRING reqIdOS) ++ throws EProfileException, ECMCPopFailedException { + String method = "EnrollProfile: verifyDecryptedPOP: "; + CMS.debug(method + "begins"); + String msg = ""; + +- if (decPop == null) { ++ if (decPop == null || reqIdOS == null) { + CMS.debug(method + "method parameters cannot be null"); + return null; + } + +- // iBody contains the request id +- INTEGER iBody = decPop.getBodyPartID(); +- if (iBody == null) { +- msg = method + "iBody null after decPop.getBodyPartID"; +- CMS.debug(msg); +- return null; +- } +- CMS.debug(method + "request id from decryptedPOP =" + +- iBody.toString()); +- Integer reqId = new Integer(iBody.toString()); ++ byte[] reqIdBA = reqIdOS.toByteArray(); ++ BigInteger reqIdBI = new BigInteger(reqIdBA); + + OCTET_STRING witness_os = decPop.getWitness(); + + IRequestQueue reqQueue = getRequestQueue(); + IRequest req = null; + try { +- req = reqQueue.findRequest(new RequestId(reqId)); ++ req = reqQueue.findRequest(new RequestId(reqIdBI)); + } catch (Exception e) { + msg = method + "after findRequest: " + e; + CMS.debug(msg); +@@ -1095,7 +1144,7 @@ public abstract class EnrollProfile extends BasicProfile + if (pop_encryptedData == null) { + msg = method + + "pop_encryptedData not found in request:" + +- reqId.toString(); ++ reqIdBI.toString(); + CMS.debug(msg); + return null; + } +@@ -1104,7 +1153,7 @@ public abstract class EnrollProfile extends BasicProfile + if (pop_sysPubEncryptedSession == null) { + msg = method + + "pop_sysPubEncryptedSession not found in request:" + +- reqId.toString(); ++ reqIdBI.toString(); + CMS.debug(msg); + return null; + } +@@ -1113,7 +1162,7 @@ public abstract class EnrollProfile extends BasicProfile + if (cmc_msg == null) { + msg = method + + "cmc_msg not found in request:" + +- reqId.toString(); ++ reqIdBI.toString(); + CMS.debug(msg); + return null; + } +@@ -1185,8 +1234,8 @@ public abstract class EnrollProfile extends BasicProfile + return null; + } + } catch (Exception e) { +- msg = method + e; +- CMS.debug(msg); ++ msg = e.toString(); ++ CMS.debug(method + msg); + throw new EProfileException( + CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST") + + e); +@@ -1198,7 +1247,7 @@ public abstract class EnrollProfile extends BasicProfile + CMS.debug(method + "cmc_POPchallengeRequired set back to false"); + CMS.debug(method + "ends"); + +- return reqId; ++ return reqIdBI; + } + + /** +@@ -1645,7 +1694,9 @@ public abstract class EnrollProfile extends BasicProfile + "method=" + method); + audit(auditMessage); + } else { +- throw new EBaseException("failed to verify"); ++ msg = "IdentityProofV2 failed to verify"; ++ CMS.debug(method + msg); ++ throw new EBaseException(msg); + } + return verified; + } catch (Exception e) { +@@ -1677,28 +1728,28 @@ public abstract class EnrollProfile extends BasicProfile + return false; + } + +- String token = tokenClass.getSharedToken(mCMCData); +- OCTET_STRING ostr = null; +- try { +- ostr = (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), +- ASN1Util.encode(vals.elementAt(0)))); +- } catch (InvalidBERException e) { +- CMS.debug(method + "Failed to decode the byte value."); +- return false; +- } +- byte[] b = ostr.toByteArray(); +- byte[] text = ASN1Util.encode(reqSeq); ++ String token = tokenClass.getSharedToken(mCMCData); ++ OCTET_STRING ostr = null; ++ try { ++ ostr = (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), ++ ASN1Util.encode(vals.elementAt(0)))); ++ } catch (InvalidBERException e) { ++ CMS.debug(method + "Failed to decode the byte value."); ++ return false; ++ } ++ byte[] b = ostr.toByteArray(); ++ byte[] text = ASN1Util.encode(reqSeq); + +- verified = verifyDigest(token.getBytes(), text, b); +- if (verified) {// update auditSubjectID +- //placeholder. Should probably just disable this v1 method +- } +- return verified; ++ verified = verifyDigest(token.getBytes(), text, b); ++ if (verified) {// update auditSubjectID ++ //placeholder. Should probably just disable this v1 method ++ } ++ return verified; + } + + public void fillTaggedRequest(Locale locale, TaggedRequest tagreq, X509CertInfo info, + IRequest req) +- throws EProfileException { ++ throws EProfileException, ECMCPopFailedException, ECMCBadRequestException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + +@@ -1832,7 +1883,7 @@ public abstract class EnrollProfile extends BasicProfile + fillCertReqMsg(locale, crm, info, req); + } else { + CMS.debug(method + " unsupported type (not CRMF or PKCS10)"); +- throw new EProfileException( ++ throw new ECMCBadRequestException( + CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST")); + } + } +@@ -1951,7 +2002,7 @@ public abstract class EnrollProfile extends BasicProfile + + public void fillCertReqMsg(Locale locale, CertReqMsg certReqMsg, X509CertInfo info, + IRequest req) +- throws EProfileException { ++ throws EProfileException, ECMCUnsupportedExtException { + String method = "EnrollProfile: fillCertReqMsg: "; + try { + CMS.debug(method + "Start parseCertReqMsg "); +@@ -2111,7 +2162,7 @@ public abstract class EnrollProfile extends BasicProfile + } catch (IOException e) { + CMS.debug("EnrollProfile: Unable to fill certificate request message: " + e); + CMS.debug(e); +- throw new EProfileException( ++ throw new ECMCUnsupportedExtException( + CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"), e); + } catch (InvalidKeyException e) { + CMS.debug("EnrollProfile: Unable to fill certificate request message: " + e); +@@ -2175,7 +2226,7 @@ public abstract class EnrollProfile extends BasicProfile + } + + public void fillPKCS10(Locale locale, PKCS10 pkcs10, X509CertInfo info, IRequest req) +- throws EProfileException { ++ throws EProfileException, ECMCUnsupportedExtException { + String method = "EnrollProfile: fillPKCS10: "; + CMS.debug(method + "begins"); + X509Key key = pkcs10.getSubjectPublicKeyInfo(); +@@ -2234,7 +2285,7 @@ public abstract class EnrollProfile extends BasicProfile + CMS.debug(method + "Finish parsePKCS10 - " + pkcs10.getSubjectName()); + } catch (IOException e) { + CMS.debug(method + "Unable to fill PKCS #10: " + e); +- throw new EProfileException( ++ throw new ECMCUnsupportedExtException( + CMS.getUserMessage(locale, "CMS_PROFILE_INVALID_REQUEST"), e); + } catch (CertificateException e) { + CMS.debug(method + "Unable to fill PKCS #10: " + e); +@@ -2582,7 +2633,7 @@ public abstract class EnrollProfile extends BasicProfile + * verifyPOP - CRMF POP verification for signing keys + */ + public void verifyPOP(Locale locale, CertReqMsg certReqMsg) +- throws EProfileException { ++ throws EProfileException, ECMCPopFailedException { + String method = "EnrollProfile: verifyPOP: "; + CMS.debug(method + "for signing keys begins."); + +@@ -2628,11 +2679,11 @@ public abstract class EnrollProfile extends BasicProfile + } + + private void popFailed(Locale locale, String auditSubjectID, String msg) +- throws EProfileException { ++ throws EProfileException, ECMCPopFailedException { + popFailed(locale, auditSubjectID, msg, null); + } + private void popFailed(Locale locale, String auditSubjectID, String msg, Exception e) +- throws EProfileException { ++ throws EProfileException, ECMCPopFailedException { + + if (e != null) + msg = msg + e.toString(); +@@ -2645,10 +2696,10 @@ public abstract class EnrollProfile extends BasicProfile + audit(auditMessage); + + if (e != null) { +- throw new EProfileException(CMS.getUserMessage(locale, ++ throw new ECMCPopFailedException(CMS.getUserMessage(locale, + "CMS_POP_VERIFICATION_ERROR"), e); + } else { +- throw new EProfileException(CMS.getUserMessage(locale, ++ throw new ECMCPopFailedException(CMS.getUserMessage(locale, + "CMS_POP_VERIFICATION_ERROR")); + } + } +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 067dce7..1e509d3 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 +@@ -49,7 +49,7 @@ import org.mozilla.jss.crypto.SignatureAlgorithm; + import org.mozilla.jss.pkcs11.PK11PubKey; + import org.mozilla.jss.pkix.cert.Certificate; + import org.mozilla.jss.pkix.cmc.CMCCertId; +-import org.mozilla.jss.pkix.cmc.CMCStatusInfo; ++import org.mozilla.jss.pkix.cmc.CMCStatusInfoV2; + import org.mozilla.jss.pkix.cmc.EncryptedPOP; + import org.mozilla.jss.pkix.cmc.GetCert; + import org.mozilla.jss.pkix.cmc.OtherInfo; +@@ -117,13 +117,13 @@ public class CMCOutputTemplate { + + int bpid = 1; + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(code), null); +- CMCStatusInfo cmcStatusInfo = new CMCStatusInfo( +- new INTEGER(CMCStatusInfo.FAILED), ++ new INTEGER(code), null, null); ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2( ++ new INTEGER(CMCStatusInfoV2.FAILED), + bpids, s, otherInfo); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + try { +@@ -166,6 +166,7 @@ public class CMCOutputTemplate { + // in rfc 2797: body list value is 1 + int bpid = 1; + SEQUENCE pending_bpids = null; ++ SEQUENCE popRequired_bpids = null; + SEQUENCE success_bpids = null; + SEQUENCE failed_bpids = null; + if (cert_request_type.equals("crmf") || +@@ -175,23 +176,24 @@ public class CMCOutputTemplate { + if (error_codes[0] == 2) { + PendInfo pendInfo = new PendInfo(reqId, new Date()); + otherInfo = new OtherInfo(OtherInfo.PEND, null, +- pendInfo); ++ pendInfo, null); + } else { + otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_REQUEST), null); ++ new INTEGER(OtherInfo.BAD_REQUEST), null, null); + } + + SEQUENCE bpids = new SEQUENCE(); + bpids.addElement(new INTEGER(1)); +- CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.PENDING, + bpids, (String) null, otherInfo); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } else if (cert_request_type.equals("cmc")) { + CMS.debug(method + " processing cmc"); + pending_bpids = new SEQUENCE(); ++ popRequired_bpids = new SEQUENCE(); + success_bpids = new SEQUENCE(); + failed_bpids = new SEQUENCE(); + EncryptedPOP encPop = null; +@@ -205,11 +207,15 @@ public class CMCOutputTemplate { + } else if (error_codes[i] == 2) { + pending_bpids.addElement(new INTEGER( + reqs[i].getExtDataInBigInteger("bodyPartId"))); ++ } else if (error_codes[i] == 4) { ++ popRequired_bpids.addElement(new INTEGER( ++ reqs[i].getExtDataInBigInteger("bodyPartId"))); + try { + encPop = constructEncryptedPop(reqs[i]); + } catch (Exception e) { + CMS.debug(method + e); +- return; ++ failed_bpids.addElement(new INTEGER( ++ reqs[i].getExtDataInBigInteger("bodyPartId"))); + } + } else { + failed_bpids.addElement(new INTEGER( +@@ -221,41 +227,41 @@ public class CMCOutputTemplate { + } + + TaggedAttribute tagattr = null; +- CMCStatusInfo cmcStatusInfo = null; ++ CMCStatusInfoV2 cmcStatusInfoV2 = null; + + SEQUENCE decryptedPOPBpids = (SEQUENCE) context.get("decryptedPOP"); + if (decryptedPOPBpids != null && decryptedPOPBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.POP_FAILED), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.POP_FAILED), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + decryptedPOPBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + SEQUENCE identificationBpids = (SEQUENCE) context.get("identification"); + if (identificationBpids != null && identificationBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_IDENTITY), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_IDENTITY), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + identificationBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + SEQUENCE identityV2Bpids = (SEQUENCE) context.get("identityProofV2"); + if (identityV2Bpids != null && identityV2Bpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_IDENTITY), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_IDENTITY), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + identityV2Bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + +@@ -263,41 +269,41 @@ public class CMCOutputTemplate { + SEQUENCE identityBpids = (SEQUENCE) context.get("identityProof"); + if (identityBpids != null && identityBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_IDENTITY), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_IDENTITY), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + identityBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + SEQUENCE POPLinkWitnessV2Bpids = (SEQUENCE) context.get("POPLinkWitnessV2"); + if (POPLinkWitnessV2Bpids != null && POPLinkWitnessV2Bpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_REQUEST), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_REQUEST), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + POPLinkWitnessV2Bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + SEQUENCE POPLinkWitnessBpids = (SEQUENCE) context.get("POPLinkWitness"); + if (POPLinkWitnessBpids != null && POPLinkWitnessBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_REQUEST), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_REQUEST), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + POPLinkWitnessBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + +- if (pending_bpids.size() > 0) { +- // handle encryptedPOP control first ++ if (popRequired_bpids.size() > 0) { ++ // handle encryptedPOP control + + if (encPop != null) { + CMS.debug(method + "adding encPop"); +@@ -309,17 +315,35 @@ public class CMCOutputTemplate { + CMS.debug(method + "encPop added"); + } + ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, ++ new INTEGER(OtherInfo.POP_REQUIRED), null, null); ++ cmcStatusInfoV2 = ++ new CMCStatusInfoV2(CMCStatusInfoV2.POP_REQUIRED, ++ popRequired_bpids, (String) null, otherInfo); ++ tagattr = new TaggedAttribute( ++ new INTEGER(bpid++), ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); ++ controlSeq.addElement(tagattr); ++ ++ // add request id ++ byte[] reqId = reqs[0].getRequestId().toBigInteger().toByteArray(); ++ TaggedAttribute reqIdTA = ++ new TaggedAttribute(new INTEGER(bpid++), ++ OBJECT_IDENTIFIER.id_cmc_responseInfo, ++ new OCTET_STRING(reqId)); ++ controlSeq.addElement(reqIdTA); ++ } ++ ++ if (pending_bpids.size() > 0) { + String reqId = reqs[0].getRequestId().toString(); +- OtherInfo otherInfo = null; + PendInfo pendInfo = new PendInfo(reqId, new Date()); +- otherInfo = new OtherInfo(OtherInfo.PEND, null, +- pendInfo); +- // cfu: inject POP_REQUIRED when working on V2 status +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.PEND, null, ++ pendInfo, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.PENDING, + pending_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + +@@ -333,27 +357,27 @@ public class CMCOutputTemplate { + } + if (confirmRequired) { + CMS.debug(method + " confirmRequired in the request"); +- cmcStatusInfo = +- new CMCStatusInfo(CMCStatusInfo.CONFIRM_REQUIRED, ++ cmcStatusInfoV2 = ++ new CMCStatusInfoV2(CMCStatusInfoV2.CONFIRM_REQUIRED, + success_bpids, (String) null, null); + } else { +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, + success_bpids, (String) null, null); + } + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + if (failed_bpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_REQUEST), null); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ new INTEGER(OtherInfo.BAD_REQUEST), null, null); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + } +@@ -373,15 +397,15 @@ public class CMCOutputTemplate { + } catch (EBaseException ee) { + CMS.debug(method + ee.toString()); + OtherInfo otherInfo1 = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_CERT_ID), null); ++ new INTEGER(OtherInfo.BAD_CERT_ID), null, null); + SEQUENCE bpids1 = new SEQUENCE(); + bpids1.addElement(attr.getBodyPartID()); +- CMCStatusInfo cmcStatusInfo1 = new CMCStatusInfo( +- new INTEGER(CMCStatusInfo.FAILED), ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2( ++ new INTEGER(CMCStatusInfoV2.FAILED), + bpids1, null, otherInfo1); + TaggedAttribute tagattr1 = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo1); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr1); + } + } +@@ -537,7 +561,7 @@ public class CMCOutputTemplate { + } + + } else { +- msg = "popChallengeRequired required, but one more more of the pop_ data not found in request"; ++ msg = "popChallengeRequired, but one or more of the pop_ data not found in request"; + CMS.debug(method + msg); + throw new EBaseException(method + msg); + } +@@ -734,23 +758,23 @@ public class CMCOutputTemplate { + CMS.debug("CMCOutputTemplate: Certificate in the confirm acceptance control was not found"); + } + } +- CMCStatusInfo cmcStatusInfo = null; ++ CMCStatusInfoV2 cmcStatusInfoV2 = null; + if (confirmAccepted) { + CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate exists in the certificate repository."); +- cmcStatusInfo = +- new CMCStatusInfo(CMCStatusInfo.SUCCESS, seq, ++ cmcStatusInfoV2 = ++ new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, seq, + (String) null, null); + } else { + CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate does not exist in the certificate repository."); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, +- new INTEGER(OtherInfo.BAD_CERT_ID), null); +- cmcStatusInfo = +- new CMCStatusInfo(CMCStatusInfo.FAILED, seq, ++ new INTEGER(OtherInfo.BAD_CERT_ID), null, null); ++ cmcStatusInfoV2 = ++ new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, seq, + (String) null, otherInfo); + } + TaggedAttribute statustagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(statustagattr); + } catch (Exception e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); +@@ -825,28 +849,28 @@ public class CMCOutputTemplate { + } + + if (pending_bpids.size() > 0) { +- CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.PENDING, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + if (success_bpids.size() > 0) { +- CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + + if (failed_bpids.size() > 0) { +- CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, ++ CMCStatusInfoV2 cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + } + +@@ -959,7 +983,7 @@ public class CMCOutputTemplate { + + if (attr != null) { + INTEGER attrbpid = attr.getBodyPartID(); +- CMCStatusInfo cmcStatusInfo = null; ++ CMCStatusInfoV2 cmcStatusInfoV2 = null; + SET vals = attr.getValues(); + if (vals.size() > 0) { + RevokeRequest revRequest = (RevokeRequest) (ASN1Util.decode(new RevokeRequest.Template(), +@@ -988,14 +1012,14 @@ public class CMCOutputTemplate { + CMS.debug(method + "missing CMC signer principal"); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), +- null); ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1021,15 +1045,15 @@ public class CMCOutputTemplate { + if (!verifyRevRequestSignature(msgData)) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), +- null); ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, + (String) null, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1051,13 +1075,13 @@ public class CMCOutputTemplate { + 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); ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1067,14 +1091,14 @@ public class CMCOutputTemplate { + + if (sharedSecret == null) { + CMS.debug("CMCOutputTemplate: shared secret not found."); +- OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), +- null); ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1088,14 +1112,14 @@ public class CMCOutputTemplate { + } else { + 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); ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + audit(new CertStatusChangeRequestProcessedEvent( +@@ -1123,13 +1147,13 @@ public class CMCOutputTemplate { + + if (record == null) { + CMS.debug(method + " The certificate is not found"); +- OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null); ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1138,11 +1162,11 @@ public class CMCOutputTemplate { + CMS.debug("CMCOutputTemplate: The certificate is already revoked."); + SEQUENCE success_bpids = new SEQUENCE(); + success_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, + success_bpids, (String) null, null); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + return bpid; + } +@@ -1159,14 +1183,14 @@ public class CMCOutputTemplate { + msg = "certificate principal and signer do not match"; + CMS.debug(method + msg); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), +- null); ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, msg, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, msg, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + audit(new CertStatusChangeRequestProcessedEvent( +@@ -1220,14 +1244,14 @@ public class CMCOutputTemplate { + CMS.debug("CMCOutputTemplate: revReq exception: " + + revReq.getExtDataInString(IRequest.ERROR)); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), +- null); ++ null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + audit(new CertStatusChangeRequestProcessedEvent( +@@ -1254,11 +1278,11 @@ public class CMCOutputTemplate { + CMS.debug(method + " Certificate revoked."); + SEQUENCE success_bpids = new SEQUENCE(); + success_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, + success_bpids, (String) null, null); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + auditApprovalStatus = RequestStatus.COMPLETE; +@@ -1272,13 +1296,13 @@ public class CMCOutputTemplate { + auditApprovalStatus)); + return bpid; + } else { +- OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null); ++ OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); +- cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); ++ cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + audit(new CertStatusChangeRequestProcessedEvent( +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 4578a98..cfd42ad 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 +@@ -35,7 +35,7 @@ import org.mozilla.jss.asn1.SEQUENCE; + import org.mozilla.jss.asn1.SET; + import org.mozilla.jss.crypto.DigestAlgorithm; + import org.mozilla.jss.crypto.SignatureAlgorithm; +-import org.mozilla.jss.pkix.cmc.CMCStatusInfo; ++import org.mozilla.jss.pkix.cmc.CMCStatusInfoV2; + import org.mozilla.jss.pkix.cmc.OtherInfo; + import org.mozilla.jss.pkix.cmc.PendInfo; + import org.mozilla.jss.pkix.cmc.ResponseBody; +@@ -98,7 +98,7 @@ public class GenPendingTemplateFiller implements ICMSTemplateFiller { + RequestId reqId = req.getRequestId(); + + fixed.set(ICMSTemplateFiller.REQUEST_ID, reqId); +- // set pendInfo, CMCStatusInfo ++ // set pendInfo, CMCStatusInfoV2 + IArgBlock httpParams = cmsReq.getHttpParams(); + + if (doFullResponse(httpParams)) { +@@ -115,12 +115,12 @@ public class GenPendingTemplateFiller implements ICMSTemplateFiller { + for (int i = 0; i < reqIdArray.length; i++) { + bpids.addElement(new INTEGER(reqIdArray[i])); + } +- CMCStatusInfo cmcStatusInfo = new +- CMCStatusInfo(CMCStatusInfo.PENDING, bpids, ++ CMCStatusInfoV2 cmcStatusInfo = new ++ CMCStatusInfoV2(CMCStatusInfoV2.PENDING, bpids, + (String) null, otherInfo); + TaggedAttribute ta = new TaggedAttribute(new + INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, + cmcStatusInfo); + + controlSeq.addElement(ta); +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 73195e9..d087162 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.math.BigInteger; + import java.security.cert.X509Certificate; + import java.util.Enumeration; + import java.util.Locale; +@@ -51,6 +52,11 @@ import com.netscape.certsrv.logging.ILogger; + import com.netscape.certsrv.logging.event.AuthFailEvent; + import com.netscape.certsrv.logging.event.AuthSuccessEvent; + import com.netscape.certsrv.logging.event.CertRequestProcessedEvent; ++import com.netscape.certsrv.profile.ECMCBadIdentityException; ++import com.netscape.certsrv.profile.ECMCBadMessageCheckException; ++import com.netscape.certsrv.profile.ECMCBadRequestException; ++import com.netscape.certsrv.profile.ECMCPopFailedException; ++import com.netscape.certsrv.profile.ECMCPopRequiredException; + import com.netscape.certsrv.profile.EDeferException; + import com.netscape.certsrv.profile.EProfileException; + import com.netscape.certsrv.profile.ERejectException; +@@ -502,8 +508,60 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + } + try { + reqs = profile.createRequests(ctx, locale); ++ } catch (ECMCBadMessageCheckException e) { ++ CMS.debug("ProfileSubmitCMCServlet: after createRequests - " + e.toString()); ++ CMCOutputTemplate template = new CMCOutputTemplate(); ++ SEQUENCE seq = new SEQUENCE(); ++ seq.addElement(new INTEGER(0)); ++ UTF8String s = null; ++ try { ++ s = new UTF8String(e.toString()); ++ } catch (Exception ee) { ++ } ++ template.createFullResponseWithFailedStatus(response, seq, ++ OtherInfo.BAD_MESSAGE_CHECK, s); ++ return; ++ } catch (ECMCBadIdentityException e) { ++ CMS.debug("ProfileSubmitCMCServlet: after createRequests - " + e.toString()); ++ CMCOutputTemplate template = new CMCOutputTemplate(); ++ SEQUENCE seq = new SEQUENCE(); ++ seq.addElement(new INTEGER(0)); ++ UTF8String s = null; ++ try { ++ s = new UTF8String(e.toString()); ++ } catch (Exception ee) { ++ } ++ template.createFullResponseWithFailedStatus(response, seq, ++ OtherInfo.BAD_IDENTITY, s); ++ return; ++ } catch (ECMCPopFailedException e) { ++ CMS.debug("ProfileSubmitCMCServlet: after createRequests - " + e.toString()); ++ CMCOutputTemplate template = new CMCOutputTemplate(); ++ SEQUENCE seq = new SEQUENCE(); ++ seq.addElement(new INTEGER(0)); ++ UTF8String s = null; ++ try { ++ s = new UTF8String(e.toString()); ++ } catch (Exception ee) { ++ } ++ template.createFullResponseWithFailedStatus(response, seq, ++ OtherInfo.POP_FAILED, s); ++ return; ++ } catch (ECMCBadRequestException e) { ++ CMS.debug("ProfileSubmitCMCServlet: after createRequests - " + e.toString()); ++ CMCOutputTemplate template = new CMCOutputTemplate(); ++ SEQUENCE seq = new SEQUENCE(); ++ seq.addElement(new INTEGER(0)); ++ UTF8String s = null; ++ try { ++ s = new UTF8String(e.toString()); ++ } catch (Exception ee) { ++ } ++ template.createFullResponseWithFailedStatus(response, seq, ++ OtherInfo.BAD_REQUEST, s); ++ return; + } catch (EProfileException e) { +- CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString()); ++ CMS.debug("ProfileSubmitCMCServlet: after createRequests - " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); +@@ -516,7 +574,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } catch (Throwable e) { +- CMS.debug("ProfileSubmitCMCServlet: createRequests " + e.toString()); ++ CMS.debug("ProfileSubmitCMCServlet: createRequests - " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); +@@ -570,7 +628,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + boolean isRevoke = false; + if (reqs == null) { + // handling DecryptedPOP request here +- Integer reqID = (Integer) context.get("cmcDecryptedPopReqId"); ++ BigInteger reqID = (BigInteger) context.get("cmcDecryptedPopReqId"); + if (reqID == null) { + CMS.debug("ProfileSubmitCMCServlet: revocation request"); + isRevoke = true; +@@ -683,8 +741,21 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + } + profile.populateInput(ctx, reqs[k]); + profile.populate(reqs[k]); ++ } catch (ECMCPopFailedException e) { ++ CMS.debug("ProfileSubmitCMCServlet: after populate - " + e.toString()); ++ CMCOutputTemplate template = new CMCOutputTemplate(); ++ SEQUENCE seq = new SEQUENCE(); ++ seq.addElement(new INTEGER(0)); ++ UTF8String s = null; ++ try { ++ s = new UTF8String(e.toString()); ++ } catch (Exception ee) { ++ } ++ template.createFullResponseWithFailedStatus(response, seq, ++ OtherInfo.POP_FAILED, s); ++ return; + } catch (EProfileException e) { +- CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString()); ++ CMS.debug("ProfileSubmitCMCServlet: after populate - " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); +@@ -697,7 +768,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + OtherInfo.BAD_REQUEST, s); + return; + } catch (Throwable e) { +- CMS.debug("ProfileSubmitCMCServlet: populate " + e.toString()); ++ CMS.debug("ProfileSubmitCMCServlet: after populate - " + e.toString()); + // throw new IOException("Profile " + profileId + + // " cannot populate"); + CMCOutputTemplate template = new CMCOutputTemplate(); +@@ -780,6 +851,21 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + errorReason = CMS.getUserMessage(locale, + "CMS_PROFILE_REJECTED", + e.toString()); ++ } catch (ECMCPopRequiredException e) { ++ // return popRequired message to the user ++ CMS.debug("ProfileSubmitCMCServlet: popRequired; set request to PENDING"); ++ reqs[k].setRequestStatus(RequestStatus.PENDING); ++ // need to notify ++ INotify notify = profile.getRequestQueue().getPendingNotify(); ++ if (notify != null) { ++ notify.notify(reqs[k]); ++ } ++ ++ CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString()); ++ errorCode = "4"; ++ errorReason = CMS.getUserMessage(locale, ++ "CMS_PROFILE_CMC_POP_REQUIRED", ++ e.toString()); + } catch (Throwable e) { + // return error to the user + CMS.debug("ProfileSubmitCMCServlet: submit " + e.toString()); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java b/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java +index 76700fe..5666c13 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/request/CheckRequest.java +@@ -48,7 +48,7 @@ import org.mozilla.jss.asn1.SEQUENCE; + import org.mozilla.jss.asn1.SET; + import org.mozilla.jss.crypto.DigestAlgorithm; + import org.mozilla.jss.crypto.SignatureAlgorithm; +-import org.mozilla.jss.pkix.cmc.CMCStatusInfo; ++import org.mozilla.jss.pkix.cmc.CMCStatusInfoV2; + import org.mozilla.jss.pkix.cmc.PKIData; + import org.mozilla.jss.pkix.cmc.ResponseBody; + import org.mozilla.jss.pkix.cmc.TaggedAttribute; +@@ -431,11 +431,11 @@ public class CheckRequest extends CMSServlet { + + if (bodyPartId != null) + bpids.addElement(bodyPartId); +- CMCStatusInfo cmcStatusInfo = new +- CMCStatusInfo(CMCStatusInfo.SUCCESS, bpids); ++ CMCStatusInfoV2 cmcStatusInfo = new ++ CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, bpids); + TaggedAttribute ta = new TaggedAttribute(new + INTEGER(bpid++), +- OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, ++ OBJECT_IDENTIFIER.id_cmc_statusInfoV2, + cmcStatusInfo); + + controlSeq.addElement(ta); +diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties +index ff56465..ed2a620 100644 +--- a/base/server/cmsbundle/src/UserMessages.properties ++++ b/base/server/cmsbundle/src/UserMessages.properties +@@ -801,6 +801,7 @@ CMS_PROFILE_SUBJDIR_EMPTY_ATTRVAL=Attribute value should not be empty + CMS_PROFILE_CRL_DISTRIBUTION_POINTS=CRL Distribution Points + CMS_PROFILE_REJECTED=Request {0} Rejected - {1} + CMS_PROFILE_DEFERRED=Request Deferred - {0} ++CMS_PROFILE_CMC_POP_REQUIRED=Request Deferred due to missing POP - {0} + CMS_PROFILE_INTERNAL_ERROR=Request {0} - Server Internal Error + CMS_PROFILE_KEY_ID=Key ID + CMS_PROFILE_NOT_OWNER=Not Profile Owner +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-HSM-key-changeover-SCP03-support.patch b/SOURCES/pki-core-HSM-key-changeover-SCP03-support.patch new file mode 100644 index 0000000..5d839da --- /dev/null +++ b/SOURCES/pki-core-HSM-key-changeover-SCP03-support.patch @@ -0,0 +1,97 @@ +From af96c3fc7cb41cbe6c14722418e132f5eadd93e1 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Thu, 29 Jun 2017 14:23:47 -0700 +Subject: [PATCH] SCP03 support: fix Key Changeover with HSM (RHCS) + +Ticket #2764. + +This relatively simple fix involves making sure the correct crypto token is being used to search for the master key int the case of symmetric key changover where the master key resides on an HSM. + +(cherry picked from commit 7eb8ac9abb06d5a21c9d81d3f7fd08391a2a745e) +--- + .../cms/servlet/tks/SecureChannelProtocol.java | 29 ++++++++++++++-------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index 0542470..c3b3952 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -25,12 +25,12 @@ import org.mozilla.jss.crypto.SymmetricKey.NotExtractableException; + import org.mozilla.jss.crypto.SymmetricKeyDeriver; + import org.mozilla.jss.crypto.TokenException; + ++import sun.security.pkcs11.wrapper.PKCS11Constants; ++ + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.cmsutil.crypto.CryptoUtil; + +-import sun.security.pkcs11.wrapper.PKCS11Constants; +- + public class SecureChannelProtocol { + + static String sharedSecretKeyName = null; +@@ -1874,13 +1874,13 @@ public class SecureChannelProtocol { + kekKey = returnDeveloperSymKey(newToken, SecureChannelProtocol.kekType, keySet, null,"DES3"); + } else if (protocol == PROTOCOL_THREE) { + CMS.debug(method + " Special case or returning to the dev key set (or ver 1) for DiversifyKey, protocol 3!"); +- encKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo, ++ encKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, newKeyInfo, + SecureChannelProtocol.encType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); +- macKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo, ++ macKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, newKeyInfo, + SecureChannelProtocol.macType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); +- kekKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, newKeyInfo, ++ kekKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, newKeyInfo, + SecureChannelProtocol.kekType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); + } +@@ -1916,13 +1916,14 @@ public class SecureChannelProtocol { + } else { // protocol 3 + + CMS.debug(method + " Generating new card keys to upgrade to, protocol 3."); +- encKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo, ++ CMS.debug("tokenName: " + tokenName + " newTokenName: " + newTokenName); ++ encKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, oldKeyInfo, + SecureChannelProtocol.encType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); +- macKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo, ++ macKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, oldKeyInfo, + SecureChannelProtocol.macType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); +- kekKey = this.computeSessionKey_SCP03(tokenName, newMasterKeyName, oldKeyInfo, ++ kekKey = this.computeSessionKey_SCP03(newTokenName, newMasterKeyName, oldKeyInfo, + SecureChannelProtocol.kekType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); + +@@ -1931,6 +1932,7 @@ public class SecureChannelProtocol { + old_kek_sym_key = this.computeSessionKey_SCP03(tokenName, oldMasterKeyName, oldKeyInfo, + SecureChannelProtocol.kekType, kekKeyArray, + keySet, CUIDValue, KDD, null, null, transportKeyName, params); ++ + } + + if (encKey == null || macKey == null || kekKey == null) { +@@ -2076,9 +2078,14 @@ public class SecureChannelProtocol { + encrypted_mac_key = this.wrapSessionKey(tokenName, macKey, wrappingKey); + encrypted_kek_key = this.wrapSessionKey(tokenName, kekKey, wrappingKey); + +- keycheck_enc_key = this.computeKeyCheck_SCP03(encKey, tokenName); +- keycheck_mac_key = this.computeKeyCheck_SCP03(macKey, tokenName); +- keycheck_kek_key = this.computeKeyCheck_SCP03(kekKey, tokenName); ++ try { ++ keycheck_enc_key = this.computeKeyCheck_SCP03(encKey, encKey.getOwningToken().getName()); ++ keycheck_mac_key = this.computeKeyCheck_SCP03(macKey, macKey.getOwningToken().getName()); ++ keycheck_kek_key = this.computeKeyCheck_SCP03(kekKey, kekKey.getOwningToken().getName()); ++ } catch (TokenException e) { ++ throw new EBaseException(method + e); ++ } ++ + + } else { + throw new EBaseException(method + " Invalid SCP version requested!"); +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-cmc-plugin-default-change.patch b/SOURCES/pki-core-cmc-plugin-default-change.patch new file mode 100644 index 0000000..2a9b5aa --- /dev/null +++ b/SOURCES/pki-core-cmc-plugin-default-change.patch @@ -0,0 +1,28 @@ +From 7c075ba00c81dd01ebdb3ee455a07a2fe1256f13 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Thu, 29 Jun 2017 15:44:13 -0700 +Subject: [PATCH] Ticket #2779 cmc plugin default change + +(cherry picked from commit 876d13c6d20e7e1235b9efbd601b47315debb492) +--- + base/ca/shared/conf/CS.cfg | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 4da7429..5a244d7 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -735,8 +735,8 @@ ca.publish.rule.instance.LdapXCertRule.predicate= + ca.publish.rule.instance.LdapXCertRule.publisher=LdapCrossCertPairPublisher + ca.publish.rule.instance.LdapXCertRule.type=xcert + cmc.popLinkWitnessRequired=false +-cmc.revokeCert.sharedSecret.class=com.netscape.cms.authentication.SharedSecret +-cmc.sharedSecret.class=com.netscape.cms.authentication.SharedSecret ++#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 +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-platform-dependent-python-import.patch b/SOURCES/pki-core-platform-dependent-python-import.patch new file mode 100644 index 0000000..c36bd3a --- /dev/null +++ b/SOURCES/pki-core-platform-dependent-python-import.patch @@ -0,0 +1,30 @@ +From dfbd7c8d54dc27957438a722bc43e37b1b2057b6 Mon Sep 17 00:00:00 2001 +From: Matthew Harmsen +Date: Thu, 22 Jun 2017 12:50:21 -0600 +Subject: [PATCH] dogtagpki Pagure Issue #2745 - Platform Dependent Python + Import + +(cherry picked from commit 9d63a7a6b1abb42595b6a24296a39a79441ba8df) +--- + base/common/python/pki/client.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/base/common/python/pki/client.py b/base/common/python/pki/client.py +index 805d0fa..e1a4d3f 100644 +--- a/base/common/python/pki/client.py ++++ b/base/common/python/pki/client.py +@@ -25,7 +25,10 @@ import functools + import warnings + + import requests +-from requests.packages.urllib3.exceptions import InsecureRequestWarning ++try: ++ from requests.packages.urllib3.exceptions import InsecureRequestWarning ++except ImportError: ++ from urllib3.exceptions import InsecureRequestWarning + + + def catch_insecure_warning(func): +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-pre-signed-CMC-renewal-UniqueKeyConstraint.patch b/SOURCES/pki-core-pre-signed-CMC-renewal-UniqueKeyConstraint.patch new file mode 100644 index 0000000..9d3f9c7 --- /dev/null +++ b/SOURCES/pki-core-pre-signed-CMC-renewal-UniqueKeyConstraint.patch @@ -0,0 +1,30 @@ +From 7f29261148fa4a27824cb2006c515d376288ec64 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Tue, 20 Jun 2017 15:04:12 -0700 +Subject: [PATCH] Ticket #2618 UniqueKeyConstraint fix on subjectDN comparison + +(cherry picked from commit 2d69d9332eea7ddc5205dc9e44d15452be4be61f) +--- + .../com/netscape/cms/profile/constraint/UniqueKeyConstraint.java | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +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 030995a..2614576 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 +@@ -240,11 +240,7 @@ public class UniqueKeyConstraint extends EnrollConstraint { + } + // only VALID or EXPIRED certs could have reached here + X509CertImpl origCert = rec.getCertificate(); +- String certDN = +- origCert.getSubjectDN().toString(); +- CMS.debug(method + " cert retrieved from ldap has subject DN =" + certDN); +- +- sjname_in_db = new X500Name(certDN); ++ sjname_in_db = (X500Name) origCert.getSubjectDN(); + + if (sjname_in_db.equals(sjname_in_req) == false) { + msg = msg + "subject name not match in same key renewal;"; +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-server-access-banner-retrieval-validation.patch b/SOURCES/pki-core-server-access-banner-retrieval-validation.patch new file mode 100644 index 0000000..a4a20d7 --- /dev/null +++ b/SOURCES/pki-core-server-access-banner-retrieval-validation.patch @@ -0,0 +1,81 @@ +From 384cd35c5298010386047b62d6db64916dd6689c Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Fri, 18 Aug 2017 23:05:24 +0200 +Subject: [PATCH] Added banner validation in InfoService. + +Previously banner was only validated during server startup. Since +banner can be modified anytime, the InfoService has been changed +such that it validates the banner on each banner retrieval. + +https://pagure.io/dogtagpki/issue/2671 + +Change-Id: I208f4c5b4ce2ce594e92acd4792aa03c729fa2cf +(cherry picked from commit 889a9c9efce62488f098fb96fcf4a1454c0b3bc2) +--- + .../src/org/dogtagpki/server/rest/InfoService.java | 27 +++++++++++++++++++++- + 1 file changed, 26 insertions(+), 1 deletion(-) + +diff --git a/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java b/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java +index 13581dd..5467bda 100644 +--- a/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java ++++ b/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java +@@ -20,12 +20,15 @@ package org.dogtagpki.server.rest; + + import javax.servlet.http.HttpSession; + import javax.ws.rs.core.Response; ++import javax.xml.bind.UnmarshalException; + + import org.dogtagpki.common.Info; + import org.dogtagpki.common.InfoResource; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; ++import org.xml.sax.SAXParseException; + ++import com.netscape.certsrv.base.PKIException; + import com.netscape.cms.servlet.base.PKIService; + + /** +@@ -42,17 +45,39 @@ public class InfoService extends PKIService implements InfoResource { + logger.debug("InfoService.getInfo(): session: " + session.getId()); + + Info info = new Info(); +- info.setVersion(getVersion()); + + boolean bannerDisplayed = session.getAttribute("bannerDisplayed") != null; + boolean bannerEnabled = isBannerEnabled(); + + // if banner not yet displayed in this session and it's enabled, return banner + if (!bannerDisplayed && bannerEnabled) { ++ + String banner = getBanner(); + info.setBanner(banner); ++ ++ // validate banner ++ try { ++ // converting Info object into XML ++ String xmlInfo = info.toString(); ++ ++ // and parse it back into Info object ++ info = Info.valueOf(xmlInfo); ++ ++ } catch (UnmarshalException e) { ++ Throwable cause = e.getCause(); ++ logger.error("InfoService: Invalid access banner: " + cause, e); ++ ++ if (cause instanceof SAXParseException) { ++ throw new PKIException("Banner contains invalid character(s)", e); ++ } else { ++ throw new PKIException("Invalid access banner: " + cause, e); ++ } ++ } + } + ++ // add other info attributes after banner validation ++ info.setVersion(getVersion()); ++ + return createOKResponse(info); + } + } +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-server-access-banner-validation.patch b/SOURCES/pki-core-server-access-banner-validation.patch new file mode 100644 index 0000000..ac95f33 --- /dev/null +++ b/SOURCES/pki-core-server-access-banner-validation.patch @@ -0,0 +1,523 @@ +From 9c8a4d2543e215f388e95e30f727a35eb9a7f778 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Mon, 5 Jun 2017 21:50:00 +0200 +Subject: [PATCH 1/4] Fixed access banner normalization. + +The PKIService has been modified to trim whitespaces in access +banner before returning the value to the client. The clients +have been modified to no longer trim the banner. + +https://pagure.io/dogtagpki/issue/2671 + +Change-Id: I51c5e78d11c89c711e369328def27bb352aa49e6 +(cherry picked from commit 5e0dcb69a734c9f52cca673a7a5189d31fb15774) +--- + base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java | 2 +- + base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java | 2 +- + base/server/share/webapps/pki/js/pki-banner.js | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +index 51861b5..8f91f32 100644 +--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java ++++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +@@ -571,7 +571,7 @@ public class MainCLI extends CLI { + + if (banner != null) { + +- System.out.println(banner.trim()); ++ System.out.println(banner); + System.out.println(); + System.out.print("Do you want to proceed (y/N)? "); + System.out.flush(); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java +index e023aa6..3273477 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java +@@ -98,7 +98,7 @@ public class PKIService { + } + + public static String getBanner() throws IOException { +- return new String(Files.readAllBytes(bannerFile)); ++ return new String(Files.readAllBytes(bannerFile)).trim(); + } + + public static MediaType resolveFormat(MediaType format) { +diff --git a/base/server/share/webapps/pki/js/pki-banner.js b/base/server/share/webapps/pki/js/pki-banner.js +index e88220e..ff64092 100644 +--- a/base/server/share/webapps/pki/js/pki-banner.js ++++ b/base/server/share/webapps/pki/js/pki-banner.js +@@ -37,7 +37,7 @@ if (location.protocol == "https:" && !sessionStorage.bannerLock) { + } + + // display the banner and ask for confirmation +- var message = $.trim(data.Banner) + "\n\nDo you want to proceed?"; ++ var message = banner + "\n\nDo you want to proceed?"; + + // if banner accepted + if (confirm(message)) { +-- +1.8.3.1 + + +From 00b439b9056baef2b40a16cba2b3e46d1365ce62 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Tue, 13 Jun 2017 21:09:52 +0200 +Subject: [PATCH 2/4] Fixed access banner encoding. + +The Info service and client have been modified to transmit access +banner in Base64-encoded form. The PKI UI has been modified to +decode the access banner properly. + +https://pagure.io/dogtagpki/issue/2671 + +Change-Id: Ic8526bac4c4d6b99e627aced64ab24cf675f5d50 +(cherry picked from commit e5f6ed7be301a3531b871ef3b0ce64bea0fe1973) +--- + .../src/org/dogtagpki/common/Base64Adapter.java | 34 ++++++++++++++++++++++ + base/common/src/org/dogtagpki/common/Info.java | 2 ++ + base/server/share/webapps/pki/js/pki-banner.js | 3 ++ + 3 files changed, 39 insertions(+) + create mode 100644 base/common/src/org/dogtagpki/common/Base64Adapter.java + +diff --git a/base/common/src/org/dogtagpki/common/Base64Adapter.java b/base/common/src/org/dogtagpki/common/Base64Adapter.java +new file mode 100644 +index 0000000..f777745 +--- /dev/null ++++ b/base/common/src/org/dogtagpki/common/Base64Adapter.java +@@ -0,0 +1,34 @@ ++// --- BEGIN COPYRIGHT BLOCK --- ++// This program is free software; you can redistribute it and/or modify ++// it under the terms of the GNU General Public License as published by ++// the Free Software Foundation; version 2 of the License. ++// ++// This program is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++// ++// You should have received a copy of the GNU General Public License along ++// with this program; if not, write to the Free Software Foundation, Inc., ++// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++// ++// (C) 2017 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++ ++package org.dogtagpki.common; ++ ++import javax.xml.bind.annotation.adapters.XmlAdapter; ++ ++public class Base64Adapter extends XmlAdapter { ++ ++ @Override ++ public String unmarshal(byte[] bytes) throws Exception { ++ return new String(bytes); ++ } ++ ++ @Override ++ public byte[] marshal(String string) throws Exception { ++ return string.getBytes(); ++ } ++} +diff --git a/base/common/src/org/dogtagpki/common/Info.java b/base/common/src/org/dogtagpki/common/Info.java +index 0a216f4..7ea3fd7 100644 +--- a/base/common/src/org/dogtagpki/common/Info.java ++++ b/base/common/src/org/dogtagpki/common/Info.java +@@ -26,6 +26,7 @@ import javax.xml.bind.Marshaller; + import javax.xml.bind.Unmarshaller; + import javax.xml.bind.annotation.XmlElement; + import javax.xml.bind.annotation.XmlRootElement; ++import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; +@@ -66,6 +67,7 @@ public class Info extends ResourceMessage { + } + + @XmlElement(name="Banner") ++ @XmlJavaTypeAdapter(Base64Adapter.class) + public String getBanner() { + return banner; + } +diff --git a/base/server/share/webapps/pki/js/pki-banner.js b/base/server/share/webapps/pki/js/pki-banner.js +index ff64092..05b5f01 100644 +--- a/base/server/share/webapps/pki/js/pki-banner.js ++++ b/base/server/share/webapps/pki/js/pki-banner.js +@@ -36,6 +36,9 @@ if (location.protocol == "https:" && !sessionStorage.bannerLock) { + return; + } + ++ // decode Base64-encoded UTF-8 banner ++ var banner = decodeURIComponent(escape(atob(data.Banner))); ++ + // display the banner and ask for confirmation + var message = banner + "\n\nDo you want to proceed?"; + +-- +1.8.3.1 + + +From b5085492242307d669fb331dead66f331a07c09e Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 14 Jun 2017 03:40:43 +0200 +Subject: [PATCH 3/4] Fixed access banner encoding (part 2). + +The code that reads the access banner from file has been modified +to explicitly use UTF-8 encoding. + +The Info class and the PKI UI have been modified not to encode the +access banner in Base64 since it is not necessary. + +https://pagure.io/dogtagpki/issue/2671 + +Change-Id: I5f41a8ebac0bc91623b27f14608bca294bc9bc38 +(cherry picked from commit 4a8e1703603ab348b24d4f010e3587c340e1a032) +--- + base/common/src/org/dogtagpki/common/Info.java | 2 -- + base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java | 2 +- + base/server/share/webapps/pki/js/pki-banner.js | 5 +---- + 3 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/base/common/src/org/dogtagpki/common/Info.java b/base/common/src/org/dogtagpki/common/Info.java +index 7ea3fd7..0a216f4 100644 +--- a/base/common/src/org/dogtagpki/common/Info.java ++++ b/base/common/src/org/dogtagpki/common/Info.java +@@ -26,7 +26,6 @@ import javax.xml.bind.Marshaller; + import javax.xml.bind.Unmarshaller; + import javax.xml.bind.annotation.XmlElement; + import javax.xml.bind.annotation.XmlRootElement; +-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; +@@ -67,7 +66,6 @@ public class Info extends ResourceMessage { + } + + @XmlElement(name="Banner") +- @XmlJavaTypeAdapter(Base64Adapter.class) + public String getBanner() { + return banner; + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java +index 3273477..7a4727b 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java +@@ -98,7 +98,7 @@ public class PKIService { + } + + public static String getBanner() throws IOException { +- return new String(Files.readAllBytes(bannerFile)).trim(); ++ return new String(Files.readAllBytes(bannerFile), "UTF-8").trim(); + } + + public static MediaType resolveFormat(MediaType format) { +diff --git a/base/server/share/webapps/pki/js/pki-banner.js b/base/server/share/webapps/pki/js/pki-banner.js +index 05b5f01..2bb2792 100644 +--- a/base/server/share/webapps/pki/js/pki-banner.js ++++ b/base/server/share/webapps/pki/js/pki-banner.js +@@ -36,11 +36,8 @@ if (location.protocol == "https:" && !sessionStorage.bannerLock) { + return; + } + +- // decode Base64-encoded UTF-8 banner +- var banner = decodeURIComponent(escape(atob(data.Banner))); +- + // display the banner and ask for confirmation +- var message = banner + "\n\nDo you want to proceed?"; ++ var message = data.Banner + "\n\nDo you want to proceed?"; + + // if banner accepted + if (confirm(message)) { +-- +1.8.3.1 + + +From 6449371ab6cb95a10ce0ad37d4a303709e356973 Mon Sep 17 00:00:00 2001 +From: "Endi S. Dewata" +Date: Wed, 14 Jun 2017 23:08:29 +0200 +Subject: [PATCH 4/4] Added banner validation during server startup. + +Some pki-server CLIs have been added to inspect and validate the +content of the banner file. + +The PKI server startup script has been modified to validate the +content of the banner file using the new CLI. + +https://pagure.io/dogtagpki/issue/2671 + +Change-Id: Ibc51afee184d0a720cc0d2961af08ef75d2b54c4 +(cherry picked from commit d2e247798a36225880ef6050716cc7576fe2ad7f) +--- + base/server/python/pki/server/__init__.py | 8 ++ + base/server/python/pki/server/cli/banner.py | 186 ++++++++++++++++++++++++++++ + base/server/sbin/pki-server | 2 + + base/server/scripts/operations | 6 + + 4 files changed, 202 insertions(+) + create mode 100644 base/server/python/pki/server/cli/banner.py + +diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py +index 46c6711..0852b12 100644 +--- a/base/server/python/pki/server/__init__.py ++++ b/base/server/python/pki/server/__init__.py +@@ -19,6 +19,7 @@ + # + + from __future__ import absolute_import ++import codecs + from lxml import etree + import functools + import getpass +@@ -501,6 +502,7 @@ class PKIInstance(object): + self.conf_dir = os.path.join(CONFIG_BASE_DIR, name) + self.log_dir = os.path.join(LOG_BASE_DIR, name) + ++ self.banner_file = os.path.join(self.conf_dir, 'banner.txt') + self.password_conf = os.path.join(self.conf_dir, 'password.conf') + self.external_certs_conf = os.path.join( + self.conf_dir, 'external_certs.conf') +@@ -792,6 +794,12 @@ class PKIInstance(object): + self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') + os.remove(context_xml) + ++ def banner_installed(self): ++ return os.path.exists(self.banner_file) ++ ++ def get_banner(self): ++ return codecs.open(self.banner_file, "UTF-8").read().strip() ++ + def __repr__(self): + if self.type == 9: + return "Dogtag 9 " + self.name +diff --git a/base/server/python/pki/server/cli/banner.py b/base/server/python/pki/server/cli/banner.py +new file mode 100644 +index 0000000..98f8f16 +--- /dev/null ++++ b/base/server/python/pki/server/cli/banner.py +@@ -0,0 +1,186 @@ ++# Authors: ++# Endi S. Dewata ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; version 2 of the License. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License along ++# with this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++# ++# Copyright (C) 2017 Red Hat, Inc. ++# All rights reserved. ++# ++ ++from __future__ import absolute_import ++from __future__ import print_function ++import codecs ++import getopt ++from lxml import etree ++import sys ++import traceback ++ ++import pki.cli ++ ++ ++class BannerCLI(pki.cli.CLI): ++ ++ def __init__(self): ++ super(BannerCLI, self).__init__('banner', ++ 'Banner management commands') ++ ++ self.add_module(BannerShowCLI()) ++ self.add_module(BannerValidateCLI()) ++ ++ ++class BannerShowCLI(pki.cli.CLI): ++ ++ def __init__(self): ++ super(BannerShowCLI, self).__init__('show', 'Show banner') ++ ++ def usage(self): ++ print('Usage: pki-server banner-show [OPTIONS]') ++ print() ++ print(' -i, --instance Instance ID (default: pki-tomcat).') ++ print(' -v, --verbose Run in verbose mode.') ++ print(' --help Show help message.') ++ print() ++ ++ def execute(self, argv): ++ ++ try: ++ opts, _ = getopt.gnu_getopt(argv, 'i:v', [ ++ 'instance=', ++ 'verbose', 'help']) ++ ++ except getopt.GetoptError as e: ++ print('ERROR: ' + str(e)) ++ self.usage() ++ sys.exit(1) ++ ++ instance_name = 'pki-tomcat' ++ ++ for o, a in opts: ++ if o in ('-i', '--instance'): ++ instance_name = a ++ ++ elif o in ('-v', '--verbose'): ++ self.set_verbose(True) ++ ++ elif o == '--help': ++ self.usage() ++ sys.exit() ++ ++ else: ++ print('ERROR: unknown option ' + o) ++ self.usage() ++ sys.exit(1) ++ ++ instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ ++ instance.load() ++ ++ if not instance.banner_installed(): ++ print('ERROR: Banner is not installed') ++ sys.exit(1) ++ ++ print(instance.get_banner()) ++ ++ ++class BannerValidateCLI(pki.cli.CLI): ++ ++ def __init__(self): ++ super(BannerValidateCLI, self).__init__('validate', 'Validate banner') ++ ++ def usage(self): ++ print('Usage: pki-server banner-validate [OPTIONS]') ++ print() ++ print(' -i, --instance Instance ID (default: pki-tomcat).') ++ print(' --file Validate specified banner file.') ++ print(' -v, --verbose Run in verbose mode.') ++ print(' --help Show help message.') ++ print() ++ ++ def execute(self, argv): ++ ++ try: ++ opts, _ = getopt.gnu_getopt(argv, 'i:v', [ ++ 'instance=', 'file=', ++ 'verbose', 'help']) ++ ++ except getopt.GetoptError as e: ++ print('ERROR: ' + str(e)) ++ self.usage() ++ sys.exit(1) ++ ++ instance_name = 'pki-tomcat' ++ banner_file = None ++ ++ for o, a in opts: ++ if o in ('-i', '--instance'): ++ instance_name = a ++ ++ elif o == '--file': ++ banner_file = a ++ ++ elif o in ('-v', '--verbose'): ++ self.set_verbose(True) ++ ++ elif o == '--help': ++ self.usage() ++ sys.exit() ++ ++ else: ++ print('ERROR: unknown option ' + o) ++ self.usage() ++ sys.exit(1) ++ ++ if banner_file: ++ ++ # load banner from file ++ banner = codecs.open(banner_file, "UTF-8").read().strip() ++ ++ else: ++ ++ # load banner from instance ++ instance = pki.server.PKIInstance(instance_name) ++ ++ if not instance.is_valid(): ++ print('ERROR: Invalid instance %s.' % instance_name) ++ sys.exit(1) ++ ++ instance.load() ++ ++ if not instance.banner_installed(): ++ self.print_message('Banner is not installed') ++ return ++ ++ banner = instance.get_banner() ++ ++ if not banner: ++ print('ERROR: Banner is empty') ++ sys.exit(1) ++ ++ xml_banner = "" + banner + "" ++ ++ try: ++ parser = etree.XMLParser() ++ etree.fromstring(xml_banner, parser) ++ ++ self.print_message('Banner is valid') ++ ++ except etree.XMLSyntaxError as e: ++ if self.verbose: ++ traceback.print_exc() ++ print('ERROR: Banner contains invalid character(s)') ++ sys.exit(1) +diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server +index 6df70dc..ce06e28 100644 +--- a/base/server/sbin/pki-server ++++ b/base/server/sbin/pki-server +@@ -32,6 +32,7 @@ import pki.server.cli.kra + import pki.server.cli.ocsp + import pki.server.cli.tks + import pki.server.cli.tps ++import pki.server.cli.banner + import pki.server.cli.db + import pki.server.cli.instance + import pki.server.cli.subsystem +@@ -52,6 +53,7 @@ class PKIServerCLI(pki.cli.CLI): + self.add_module(pki.server.cli.tks.TKSCLI()) + self.add_module(pki.server.cli.tps.TPSCLI()) + ++ self.add_module(pki.server.cli.banner.BannerCLI()) + self.add_module(pki.server.cli.db.DBCLI()) + self.add_module(pki.server.cli.instance.InstanceCLI()) + self.add_module(pki.server.cli.subsystem.SubsystemCLI()) +diff --git a/base/server/scripts/operations b/base/server/scripts/operations +index 907dd0e..908c952 100644 +--- a/base/server/scripts/operations ++++ b/base/server/scripts/operations +@@ -1297,6 +1297,12 @@ EOF + /var/lib/pki/$PKI_INSTANCE_NAME/conf/custom.policy > \ + /var/lib/pki/$PKI_INSTANCE_NAME/conf/catalina.policy + ++ pki-server banner-validate -i "$PKI_INSTANCE_NAME" ++ rv=$? ++ if [ $rv -ne 0 ]; then ++ return $rv ++ fi ++ + if [ "${PKI_SERVER_AUTO_ENABLE_SUBSYSTEMS}" = "true" ] ; then + # enable all subsystems + pki-server subsystem-enable -i "$PKI_INSTANCE_NAME" --all +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-subsystem-cert-update-CLI-cert-option.patch b/SOURCES/pki-core-subsystem-cert-update-CLI-cert-option.patch new file mode 100644 index 0000000..78c3b8a --- /dev/null +++ b/SOURCES/pki-core-subsystem-cert-update-CLI-cert-option.patch @@ -0,0 +1,90 @@ +From c5312d0b44b5f58ba5b92aba85b89e405213e8a8 Mon Sep 17 00:00:00 2001 +From: Dinesh Prasanth M K +Date: Fri, 23 Jun 2017 15:57:29 -0400 +Subject: [PATCH] Patch for "pki-server subsystem-cert-update" command + +Currently, the --cert option has not been implemented for +`pki-server subsystem-cert-update` command. The --cert takes +certificate name that needs to be added to the NSS database +and replaces the existing certificate (if exists) in the +database + +https://pagure.io/dogtagpki/issue/2756 + +Change-Id: If8be9edd55a673230f86e213fc803be365e55a92 +(cherry picked from commit d762073c4b5bcd4f9f30e3b8439983a497a77c97) +--- + base/server/python/pki/server/cli/subsystem.py | 29 +++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py +index 10af8ca..a9857ba 100644 +--- a/base/server/python/pki/server/cli/subsystem.py ++++ b/base/server/python/pki/server/cli/subsystem.py +@@ -741,6 +741,7 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + print(' -i, --instance Instance ID (default: pki-tomcat).') + print(' -v, --verbose Run in verbose mode.') + print(' --help Show help message.') ++ print(' --cert New certificate to be added') + print() + + def execute(self, argv): +@@ -748,7 +749,8 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + try: + opts, args = getopt.gnu_getopt(argv, 'i:v', [ + 'instance=', +- 'verbose', 'help']) ++ 'verbose', 'help', ++ 'cert=']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) +@@ -756,6 +758,7 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + sys.exit(1) + + instance_name = 'pki-tomcat' ++ cert_file = None + + for o, a in opts: + if o in ('-i', '--instance'): +@@ -768,6 +771,9 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + self.usage() + sys.exit() + ++ elif o == '--cert': ++ cert_file = a ++ + else: + print('ERROR: unknown option ' + o) + self.usage() +@@ -807,6 +813,27 @@ class SubsystemCertUpdateCLI(pki.cli.CLI): + + token = subsystem_cert['token'] + nssdb = instance.open_nssdb(token) ++ ++ if cert_file: ++ if not os.path.isfile(cert_file): ++ print('ERROR: %s certificate does not exist.' % cert_file) ++ self.usage() ++ sys.exit(1) ++ ++ data = nssdb.get_cert( ++ nickname=subsystem_cert['nickname'], ++ output_format='base64') ++ ++ if data: ++ if self.verbose: ++ print('Removing old %s certificate from database.' % subsystem_cert['nickname']) ++ nssdb.remove_cert(nickname=subsystem_cert['nickname']) ++ if self.verbose: ++ print('Adding new %s certificate into database.' % subsystem_cert['nickname']) ++ nssdb.add_cert( ++ nickname=subsystem_cert['nickname'], ++ cert_file=cert_file) ++ + data = nssdb.get_cert( + nickname=subsystem_cert['nickname'], + output_format='base64') +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-system-cert-CMC-enroll-profile.patch b/SOURCES/pki-core-system-cert-CMC-enroll-profile.patch new file mode 100644 index 0000000..0417ac6 --- /dev/null +++ b/SOURCES/pki-core-system-cert-CMC-enroll-profile.patch @@ -0,0 +1,1132 @@ +From f10ba33f3d6f9cbd31831d0fb571e15b818e9990 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Mon, 26 Jun 2017 18:09:55 -0700 +Subject: [PATCH] Ticket #2757 CMC enrollment profiles for system certificates + +This patch supports CMC-based system certificate requests. + +This patch contains the following: +* The code in CMCAuth (agent-based) to check ssl client auth cert against the CMC signing cert +* The cmc-based system enrollment profiles: +caCMCauditSigningCert.cfg +caCMCcaCert.cfg +caCMCkraStorageCert.cfg +caCMCkraTransportCert.cfg +caCMCocspCert.cfg +caCMCserverCert.cfg +caCMCsubsystemCert.cfg +* new URI's in web.xml as new access points + +Usage example can be found here: +http://pki.fedoraproject.org/wiki/PKI_10.4_CMC_Feature_Update_(RFC5272)#Examples_.28System_Certificates.29 + +(cherry picked from commit 65b1242cd139e6306fb3e039193a3a6b223ea9b1) +--- + base/ca/shared/conf/CS.cfg | 20 ++- + .../shared/profiles/ca/caCMCauditSigningCert.cfg | 80 +++++++++ + base/ca/shared/profiles/ca/caCMCcaCert.cfg | 96 ++++++++++ + base/ca/shared/profiles/ca/caCMCkraStorageCert.cfg | 86 +++++++++ + .../shared/profiles/ca/caCMCkraTransportCert.cfg | 86 +++++++++ + base/ca/shared/profiles/ca/caCMCocspCert.cfg | 71 ++++++++ + base/ca/shared/profiles/ca/caCMCserverCert.cfg | 90 ++++++++++ + base/ca/shared/profiles/ca/caCMCsubsystemCert.cfg | 86 +++++++++ + base/ca/shared/profiles/ca/caFullCMCUserCert.cfg | 4 +- + .../shared/profiles/ca/caFullCMCUserSignedCert.cfg | 2 +- + base/ca/shared/webapps/ca/WEB-INF/web.xml | 196 +++++++++++++++++++++ + .../src/com/netscape/cmstools/CMCRequest.java | 2 +- + .../com/netscape/cms/authentication/CMCAuth.java | 48 ++++- + .../cms/authentication/CMCUserSignedAuth.java | 2 + + .../netscape/cms/profile/common/EnrollProfile.java | 12 ++ + .../servlet/profile/ProfileSubmitCMCServlet.java | 2 +- + 16 files changed, 872 insertions(+), 11 deletions(-) + create mode 100644 base/ca/shared/profiles/ca/caCMCauditSigningCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCcaCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCkraStorageCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCkraTransportCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCocspCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCserverCert.cfg + create mode 100644 base/ca/shared/profiles/ca/caCMCsubsystemCert.cfg + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 5a244d7..8976575 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -969,7 +969,7 @@ oidmap.pse.oid=2.16.840.1.113730.1.18 + oidmap.subject_info_access.class=netscape.security.extensions.SubjectInfoAccessExtension + oidmap.subject_info_access.oid=1.3.6.1.5.5.7.1.11 + os.userid=nobody +-profile.list=caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caFullCMCUserSignedCert,caFullCMCSelfSignedCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment ++profile.list=caCMCserverCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,caECDualCert,AdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caAgentFileSigning,caCMCUserCert,caFullCMCUserCert,caFullCMCUserSignedCert,caFullCMCSelfSignedCert,caSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caSigningECUserCert,caEncECUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment + profile.caUUIDdeviceCert.class_id=caEnrollImpl + profile.caUUIDdeviceCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caUUIDdeviceCert.cfg + profile.caManualRenewal.class_id=caEnrollImpl +@@ -988,12 +988,26 @@ profile.caAgentServerCert.class_id=caEnrollImpl + profile.caAgentServerCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caAgentServerCert.cfg + profile.caRAserverCert.class_id=caEnrollImpl + profile.caRAserverCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caRAserverCert.cfg ++profile.caCMCUserCert.class_id=caEnrollImpl ++profile.caCMCUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCUserCert.cfg ++profile.caCMCauditSigningCert.class_id=caEnrollImpl ++profile.caCMCauditSigningCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCauditSigningCert.cfg ++profile.caCMCcaCert.class_id=caEnrollImpl ++profile.caCMCcaCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCcaCert.cfg ++profile.caCMCkraStorageCert.class_id=caEnrollImpl ++profile.caCMCkraStorageCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCkraStorageCert.cfg ++profile.caCMCkraTransportCert.class_id=caEnrollImpl ++profile.caCMCkraTransportCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCkraTransportCert.cfg ++profile.caCMCocspCert.class_id=caEnrollImpl ++profile.caCMCocspCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCocspCert.cfg ++profile.caCMCserverCert.class_id=caEnrollImpl ++profile.caCMCserverCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCserverCert.cfg ++profile.caCMCsubsystemCert.class_id=caEnrollImpl ++profile.caCMCsubsystemCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCsubsystemCert.cfg + profile.caCACert.class_id=caEnrollImpl + profile.caCACert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCACert.cfg + profile.caInstallCACert.class_id=caEnrollImpl + profile.caInstallCACert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caInstallCACert.cfg +-profile.caCMCUserCert.class_id=caEnrollImpl +-profile.caCMCUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCMCUserCert.cfg + profile.caCrossSignedCACert.class_id=caEnrollImpl + profile.caCrossSignedCACert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caCrossSignedCACert.cfg + profile.caDirBasedDualCert.class_id=caEnrollImpl +diff --git a/base/ca/shared/profiles/ca/caCMCauditSigningCert.cfg b/base/ca/shared/profiles/ca/caCMCauditSigningCert.cfg +new file mode 100644 +index 0000000..ed5a1b2 +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCauditSigningCert.cfg +@@ -0,0 +1,80 @@ ++desc=This certificate profile is for enrolling audit signing certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=Audit Signing Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=auditSigningCertSet ++policyset.auditSigningCertSet.list=1,2,3,4,5,6,9 ++policyset.auditSigningCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.auditSigningCertSet.1.constraint.name=Subject Name Constraint ++policyset.auditSigningCertSet.1.constraint.params.pattern=CN=.* ++policyset.auditSigningCertSet.1.constraint.params.accept=true ++policyset.auditSigningCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.auditSigningCertSet.1.default.name=Subject Name Default ++policyset.auditSigningCertSet.1.default.params.name= ++policyset.auditSigningCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.auditSigningCertSet.2.constraint.name=Validity Constraint ++policyset.auditSigningCertSet.2.constraint.params.range=720 ++policyset.auditSigningCertSet.2.constraint.params.notBeforeCheck=false ++policyset.auditSigningCertSet.2.constraint.params.notAfterCheck=false ++policyset.auditSigningCertSet.2.default.class_id=validityDefaultImpl ++policyset.auditSigningCertSet.2.default.name=Validity Default ++policyset.auditSigningCertSet.2.default.params.range=720 ++policyset.auditSigningCertSet.2.default.params.startTime=0 ++policyset.auditSigningCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.auditSigningCertSet.3.constraint.name=Key Constraint ++policyset.auditSigningCertSet.3.constraint.params.keyType=RSA ++policyset.auditSigningCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.auditSigningCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.auditSigningCertSet.3.default.name=Key Default ++policyset.auditSigningCertSet.4.constraint.class_id=noConstraintImpl ++policyset.auditSigningCertSet.4.constraint.name=No Constraint ++policyset.auditSigningCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.auditSigningCertSet.4.default.name=Authority Key Identifier Default ++policyset.auditSigningCertSet.5.constraint.class_id=noConstraintImpl ++policyset.auditSigningCertSet.5.constraint.name=No Constraint ++policyset.auditSigningCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.auditSigningCertSet.5.default.name=AIA Extension Default ++policyset.auditSigningCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.auditSigningCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.auditSigningCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.auditSigningCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.auditSigningCertSet.5.default.params.authInfoAccessCritical=false ++policyset.auditSigningCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.auditSigningCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.auditSigningCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.auditSigningCertSet.6.constraint.params.keyUsageCritical=true ++policyset.auditSigningCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.auditSigningCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.auditSigningCertSet.6.constraint.params.keyUsageDataEncipherment=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyEncipherment=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.auditSigningCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.auditSigningCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.auditSigningCertSet.6.default.name=Key Usage Default ++policyset.auditSigningCertSet.6.default.params.keyUsageCritical=true ++policyset.auditSigningCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.auditSigningCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.auditSigningCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.auditSigningCertSet.6.default.params.keyUsageKeyEncipherment=false ++policyset.auditSigningCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.auditSigningCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.auditSigningCertSet.6.default.params.keyUsageCrlSign=false ++policyset.auditSigningCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.auditSigningCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.auditSigningCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.auditSigningCertSet.9.constraint.name=No Constraint ++policyset.auditSigningCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.auditSigningCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.auditSigningCertSet.9.default.name=Signing Alg ++policyset.auditSigningCertSet.9.default.params.signingAlg=- +diff --git a/base/ca/shared/profiles/ca/caCMCcaCert.cfg b/base/ca/shared/profiles/ca/caCMCcaCert.cfg +new file mode 100644 +index 0000000..f6df36f +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCcaCert.cfg +@@ -0,0 +1,96 @@ ++desc=This certificate profile is for enrolling Certificate Authority certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=Certificate Manager Signing Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=caCertSet ++policyset.caCertSet.list=1,2,3,4,5,6,8,9,10 ++policyset.caCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.caCertSet.1.constraint.name=Subject Name Constraint ++policyset.caCertSet.1.constraint.params.pattern=CN=.* ++policyset.caCertSet.1.constraint.params.accept=true ++policyset.caCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.caCertSet.1.default.name=Subject Name Default ++policyset.caCertSet.1.default.params.name= ++policyset.caCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.caCertSet.2.constraint.name=Validity Constraint ++policyset.caCertSet.2.constraint.params.range=7305 ++policyset.caCertSet.2.constraint.params.notBeforeCheck=false ++policyset.caCertSet.2.constraint.params.notAfterCheck=false ++policyset.caCertSet.2.default.class_id=caValidityDefaultImpl ++policyset.caCertSet.2.default.name=CA Certificate Validity Default ++policyset.caCertSet.2.default.params.range=7305 ++policyset.caCertSet.2.default.params.startTime=0 ++policyset.caCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.caCertSet.3.constraint.name=Key Constraint ++policyset.caCertSet.3.constraint.params.keyType=- ++policyset.caCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 ++policyset.caCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.caCertSet.3.default.name=Key Default ++policyset.caCertSet.4.constraint.class_id=noConstraintImpl ++policyset.caCertSet.4.constraint.name=No Constraint ++policyset.caCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.caCertSet.4.default.name=Authority Key Identifier Default ++policyset.caCertSet.5.constraint.class_id=basicConstraintsExtConstraintImpl ++policyset.caCertSet.5.constraint.name=Basic Constraint Extension Constraint ++policyset.caCertSet.5.constraint.params.basicConstraintsCritical=true ++policyset.caCertSet.5.constraint.params.basicConstraintsIsCA=true ++policyset.caCertSet.5.constraint.params.basicConstraintsMinPathLen=-1 ++policyset.caCertSet.5.constraint.params.basicConstraintsMaxPathLen=-1 ++policyset.caCertSet.5.default.class_id=basicConstraintsExtDefaultImpl ++policyset.caCertSet.5.default.name=Basic Constraints Extension Default ++policyset.caCertSet.5.default.params.basicConstraintsCritical=true ++policyset.caCertSet.5.default.params.basicConstraintsIsCA=true ++policyset.caCertSet.5.default.params.basicConstraintsPathLen=-1 ++policyset.caCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.caCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.caCertSet.6.constraint.params.keyUsageCritical=true ++policyset.caCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.caCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.caCertSet.6.constraint.params.keyUsageDataEncipherment=false ++policyset.caCertSet.6.constraint.params.keyUsageKeyEncipherment=false ++policyset.caCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.caCertSet.6.constraint.params.keyUsageKeyCertSign=true ++policyset.caCertSet.6.constraint.params.keyUsageCrlSign=true ++policyset.caCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.caCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.caCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.caCertSet.6.default.name=Key Usage Default ++policyset.caCertSet.6.default.params.keyUsageCritical=true ++policyset.caCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.caCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.caCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.caCertSet.6.default.params.keyUsageKeyEncipherment=false ++policyset.caCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.caCertSet.6.default.params.keyUsageKeyCertSign=true ++policyset.caCertSet.6.default.params.keyUsageCrlSign=true ++policyset.caCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.caCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.caCertSet.8.constraint.class_id=noConstraintImpl ++policyset.caCertSet.8.constraint.name=No Constraint ++policyset.caCertSet.8.default.class_id=subjectKeyIdentifierExtDefaultImpl ++policyset.caCertSet.8.default.name=Subject Key Identifier Extension Default ++policyset.caCertSet.8.default.params.critical=false ++policyset.caCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.caCertSet.9.constraint.name=No Constraint ++policyset.caCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.caCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.caCertSet.9.default.name=Signing Alg ++policyset.caCertSet.9.default.params.signingAlg=- ++policyset.caCertSet.10.constraint.class_id=noConstraintImpl ++policyset.caCertSet.10.constraint.name=No Constraint ++policyset.caCertSet.10.default.class_id=authInfoAccessExtDefaultImpl ++policyset.caCertSet.10.default.name=AIA Extension Default ++policyset.caCertSet.10.default.params.authInfoAccessADEnable_0=true ++policyset.caCertSet.10.default.params.authInfoAccessADLocationType_0=URIName ++policyset.caCertSet.10.default.params.authInfoAccessADLocation_0= ++policyset.caCertSet.10.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.caCertSet.10.default.params.authInfoAccessCritical=false ++policyset.caCertSet.10.default.params.authInfoAccessNumADs=1 +diff --git a/base/ca/shared/profiles/ca/caCMCkraStorageCert.cfg b/base/ca/shared/profiles/ca/caCMCkraStorageCert.cfg +new file mode 100644 +index 0000000..259430b +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCkraStorageCert.cfg +@@ -0,0 +1,86 @@ ++desc=This certificate profile is for enrolling KRA storage certificates using CMC ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=KRA storage Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=drmStorageCertSet ++policyset.drmStorageCertSet.list=1,2,3,4,5,6,7,9 ++policyset.drmStorageCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.drmStorageCertSet.1.constraint.name=Subject Name Constraint ++policyset.drmStorageCertSet.1.constraint.params.pattern=CN=.* ++policyset.drmStorageCertSet.1.constraint.params.accept=true ++policyset.drmStorageCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.drmStorageCertSet.1.default.name=Subject Name Default ++policyset.drmStorageCertSet.1.default.params.name= ++policyset.drmStorageCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.drmStorageCertSet.2.constraint.name=Validity Constraint ++policyset.drmStorageCertSet.2.constraint.params.range=720 ++policyset.drmStorageCertSet.2.constraint.params.notBeforeCheck=false ++policyset.drmStorageCertSet.2.constraint.params.notAfterCheck=false ++policyset.drmStorageCertSet.2.default.class_id=validityDefaultImpl ++policyset.drmStorageCertSet.2.default.name=Validity Default ++policyset.drmStorageCertSet.2.default.params.range=720 ++policyset.drmStorageCertSet.2.default.params.startTime=0 ++policyset.drmStorageCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.drmStorageCertSet.3.constraint.name=Key Constraint ++policyset.drmStorageCertSet.3.constraint.params.keyType=RSA ++policyset.drmStorageCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.drmStorageCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.drmStorageCertSet.3.default.name=Key Default ++policyset.drmStorageCertSet.4.constraint.class_id=noConstraintImpl ++policyset.drmStorageCertSet.4.constraint.name=No Constraint ++policyset.drmStorageCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.drmStorageCertSet.4.default.name=Authority Key Identifier Default ++policyset.drmStorageCertSet.5.constraint.class_id=noConstraintImpl ++policyset.drmStorageCertSet.5.constraint.name=No Constraint ++policyset.drmStorageCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.drmStorageCertSet.5.default.name=AIA Extension Default ++policyset.drmStorageCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.drmStorageCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.drmStorageCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.drmStorageCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.drmStorageCertSet.5.default.params.authInfoAccessCritical=false ++policyset.drmStorageCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.drmStorageCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.drmStorageCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.drmStorageCertSet.6.constraint.params.keyUsageCritical=true ++policyset.drmStorageCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.drmStorageCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.drmStorageCertSet.6.constraint.params.keyUsageDataEncipherment=true ++policyset.drmStorageCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.drmStorageCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.drmStorageCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.drmStorageCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.drmStorageCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.drmStorageCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.drmStorageCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.drmStorageCertSet.6.default.name=Key Usage Default ++policyset.drmStorageCertSet.6.default.params.keyUsageCritical=true ++policyset.drmStorageCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.drmStorageCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.drmStorageCertSet.6.default.params.keyUsageDataEncipherment=true ++policyset.drmStorageCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.drmStorageCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.drmStorageCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.drmStorageCertSet.6.default.params.keyUsageCrlSign=false ++policyset.drmStorageCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.drmStorageCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.drmStorageCertSet.7.constraint.class_id=noConstraintImpl ++policyset.drmStorageCertSet.7.constraint.name=No Constraint ++policyset.drmStorageCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.drmStorageCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.drmStorageCertSet.7.default.params.exKeyUsageCritical=false ++policyset.drmStorageCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2 ++policyset.drmStorageCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.drmStorageCertSet.9.constraint.name=No Constraint ++policyset.drmStorageCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.drmStorageCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.drmStorageCertSet.9.default.name=Signing Alg ++policyset.drmStorageCertSet.9.default.params.signingAlg=- +diff --git a/base/ca/shared/profiles/ca/caCMCkraTransportCert.cfg b/base/ca/shared/profiles/ca/caCMCkraTransportCert.cfg +new file mode 100644 +index 0000000..ec54f9c +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCkraTransportCert.cfg +@@ -0,0 +1,86 @@ ++desc=This certificate profile is for enrolling Key Archival Authority transport certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=Key Archival Authority Transport Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=transportCertSet ++policyset.transportCertSet.list=1,2,3,4,5,6,7,8 ++policyset.transportCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.transportCertSet.1.constraint.name=Subject Name Constraint ++policyset.transportCertSet.1.constraint.params.pattern=CN=.* ++policyset.transportCertSet.1.constraint.params.accept=true ++policyset.transportCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.transportCertSet.1.default.name=Subject Name Default ++policyset.transportCertSet.1.default.params.name= ++policyset.transportCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.transportCertSet.2.constraint.name=Validity Constraint ++policyset.transportCertSet.2.constraint.params.range=720 ++policyset.transportCertSet.2.constraint.params.notBeforeCheck=false ++policyset.transportCertSet.2.constraint.params.notAfterCheck=false ++policyset.transportCertSet.2.default.class_id=validityDefaultImpl ++policyset.transportCertSet.2.default.name=Validity Default ++policyset.transportCertSet.2.default.params.range=720 ++policyset.transportCertSet.2.default.params.startTime=0 ++policyset.transportCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.transportCertSet.3.constraint.name=Key Constraint ++policyset.transportCertSet.3.constraint.params.keyType=RSA ++policyset.transportCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.transportCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.transportCertSet.3.default.name=Key Default ++policyset.transportCertSet.4.constraint.class_id=noConstraintImpl ++policyset.transportCertSet.4.constraint.name=No Constraint ++policyset.transportCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.transportCertSet.4.default.name=Authority Key Identifier Default ++policyset.transportCertSet.5.constraint.class_id=noConstraintImpl ++policyset.transportCertSet.5.constraint.name=No Constraint ++policyset.transportCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.transportCertSet.5.default.name=AIA Extension Default ++policyset.transportCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.transportCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.transportCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.transportCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.transportCertSet.5.default.params.authInfoAccessCritical=false ++policyset.transportCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.transportCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.transportCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.transportCertSet.6.constraint.params.keyUsageCritical=true ++policyset.transportCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.transportCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.transportCertSet.6.constraint.params.keyUsageDataEncipherment=true ++policyset.transportCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.transportCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.transportCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.transportCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.transportCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.transportCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.transportCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.transportCertSet.6.default.name=Key Usage Default ++policyset.transportCertSet.6.default.params.keyUsageCritical=true ++policyset.transportCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.transportCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.transportCertSet.6.default.params.keyUsageDataEncipherment=true ++policyset.transportCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.transportCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.transportCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.transportCertSet.6.default.params.keyUsageCrlSign=false ++policyset.transportCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.transportCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.transportCertSet.7.constraint.class_id=noConstraintImpl ++policyset.transportCertSet.7.constraint.name=No Constraint ++policyset.transportCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.transportCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.transportCertSet.7.default.params.exKeyUsageCritical=false ++policyset.transportCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2 ++policyset.transportCertSet.8.constraint.class_id=signingAlgConstraintImpl ++policyset.transportCertSet.8.constraint.name=No Constraint ++policyset.transportCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.transportCertSet.8.default.class_id=signingAlgDefaultImpl ++policyset.transportCertSet.8.default.name=Signing Alg ++policyset.transportCertSet.8.default.params.signingAlg=- +diff --git a/base/ca/shared/profiles/ca/caCMCocspCert.cfg b/base/ca/shared/profiles/ca/caCMCocspCert.cfg +new file mode 100644 +index 0000000..8afbd46 +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCocspCert.cfg +@@ -0,0 +1,71 @@ ++desc=This certificate profile is for enrolling OCSP Responder signing certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=OCSP Responder Signing Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=ocspCertSet ++policyset.ocspCertSet.list=1,2,3,4,5,6,8,9 ++policyset.ocspCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.ocspCertSet.1.constraint.name=Subject Name Constraint ++policyset.ocspCertSet.1.constraint.params.pattern=CN=.* ++policyset.ocspCertSet.1.constraint.params.accept=true ++policyset.ocspCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.ocspCertSet.1.default.name=Subject Name Default ++policyset.ocspCertSet.1.default.params.name= ++policyset.ocspCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.ocspCertSet.2.constraint.name=Validity Constraint ++policyset.ocspCertSet.2.constraint.params.range=720 ++policyset.ocspCertSet.2.constraint.params.notBeforeCheck=false ++policyset.ocspCertSet.2.constraint.params.notAfterCheck=false ++policyset.ocspCertSet.2.default.class_id=validityDefaultImpl ++policyset.ocspCertSet.2.default.name=Validity Default ++policyset.ocspCertSet.2.default.params.range=720 ++policyset.ocspCertSet.2.default.params.startTime=0 ++policyset.ocspCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.ocspCertSet.3.constraint.name=Key Constraint ++policyset.ocspCertSet.3.constraint.params.keyType=- ++policyset.ocspCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 ++policyset.ocspCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.ocspCertSet.3.default.name=Key Default ++policyset.ocspCertSet.4.constraint.class_id=noConstraintImpl ++policyset.ocspCertSet.4.constraint.name=No Constraint ++policyset.ocspCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.ocspCertSet.4.default.name=Authority Key Identifier Default ++policyset.ocspCertSet.5.constraint.class_id=noConstraintImpl ++policyset.ocspCertSet.5.constraint.name=No Constraint ++policyset.ocspCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.ocspCertSet.5.default.name=AIA Extension Default ++policyset.ocspCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.ocspCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.ocspCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.ocspCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.ocspCertSet.5.default.params.authInfoAccessCritical=false ++policyset.ocspCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.ocspCertSet.6.constraint.class_id=extendedKeyUsageExtConstraintImpl ++policyset.ocspCertSet.6.constraint.name=Extended Key Usage Extension ++policyset.ocspCertSet.6.constraint.params.exKeyUsageCritical=false ++policyset.ocspCertSet.6.constraint.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.9 ++policyset.ocspCertSet.6.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.ocspCertSet.6.default.name=Extended Key Usage Default ++policyset.ocspCertSet.6.default.params.exKeyUsageCritical=false ++policyset.ocspCertSet.6.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.9 ++policyset.ocspCertSet.8.constraint.class_id=extensionConstraintImpl ++policyset.ocspCertSet.8.constraint.name=No Constraint ++policyset.ocspCertSet.8.constraint.params.extCritical=false ++policyset.ocspCertSet.8.constraint.params.extOID=1.3.6.1.5.5.7.48.1.5 ++policyset.ocspCertSet.8.default.class_id=ocspNoCheckExtDefaultImpl ++policyset.ocspCertSet.8.default.name=OCSP No Check Extension ++policyset.ocspCertSet.8.default.params.ocspNoCheckCritical=false ++policyset.ocspCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.ocspCertSet.9.constraint.name=No Constraint ++policyset.ocspCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.ocspCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.ocspCertSet.9.default.name=Signing Alg ++policyset.ocspCertSet.9.default.params.signingAlg=- +diff --git a/base/ca/shared/profiles/ca/caCMCserverCert.cfg b/base/ca/shared/profiles/ca/caCMCserverCert.cfg +new file mode 100644 +index 0000000..8215d65 +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCserverCert.cfg +@@ -0,0 +1,90 @@ ++desc=This certificate profile is for enrolling server certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=Server Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=serverCertSet ++policyset.serverCertSet.list=1,2,3,4,5,6,7,8,9 ++policyset.serverCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.serverCertSet.1.constraint.name=Subject Name Constraint ++policyset.serverCertSet.1.constraint.params.pattern=.*CN=.* ++policyset.serverCertSet.1.constraint.params.accept=true ++policyset.serverCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.serverCertSet.1.default.name=Subject Name Default ++policyset.serverCertSet.1.default.params.name= ++policyset.serverCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.serverCertSet.2.constraint.name=Validity Constraint ++policyset.serverCertSet.2.constraint.params.range=720 ++policyset.serverCertSet.2.constraint.params.notBeforeCheck=false ++policyset.serverCertSet.2.constraint.params.notAfterCheck=false ++policyset.serverCertSet.2.default.class_id=validityDefaultImpl ++policyset.serverCertSet.2.default.name=Validity Default ++policyset.serverCertSet.2.default.params.range=720 ++policyset.serverCertSet.2.default.params.startTime=0 ++policyset.serverCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.serverCertSet.3.constraint.name=Key Constraint ++policyset.serverCertSet.3.constraint.params.keyType=- ++policyset.serverCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 ++policyset.serverCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.serverCertSet.3.default.name=Key Default ++policyset.serverCertSet.4.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.4.constraint.name=No Constraint ++policyset.serverCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.serverCertSet.4.default.name=Authority Key Identifier Default ++policyset.serverCertSet.5.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.5.constraint.name=No Constraint ++policyset.serverCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.serverCertSet.5.default.name=AIA Extension Default ++policyset.serverCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.serverCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.serverCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.serverCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.serverCertSet.5.default.params.authInfoAccessCritical=false ++policyset.serverCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.serverCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.serverCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.serverCertSet.6.constraint.params.keyUsageCritical=true ++policyset.serverCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.serverCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.serverCertSet.6.constraint.params.keyUsageDataEncipherment=true ++policyset.serverCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.serverCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.serverCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.serverCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.serverCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.serverCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.serverCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.serverCertSet.6.default.name=Key Usage Default ++policyset.serverCertSet.6.default.params.keyUsageCritical=true ++policyset.serverCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.serverCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.serverCertSet.6.default.params.keyUsageDataEncipherment=true ++policyset.serverCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.serverCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.serverCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.serverCertSet.6.default.params.keyUsageCrlSign=false ++policyset.serverCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.serverCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.serverCertSet.7.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.7.constraint.name=No Constraint ++policyset.serverCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.serverCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.serverCertSet.7.default.params.exKeyUsageCritical=false ++policyset.serverCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 ++policyset.serverCertSet.8.constraint.class_id=signingAlgConstraintImpl ++policyset.serverCertSet.8.constraint.name=No Constraint ++policyset.serverCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.serverCertSet.8.default.class_id=signingAlgDefaultImpl ++policyset.serverCertSet.8.default.name=Signing Alg ++policyset.serverCertSet.8.default.params.signingAlg=- ++policyset.serverCertSet.9.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.9.constraint.name=No Constraint ++policyset.serverCertSet.9.default.class_id=commonNameToSANDefaultImpl ++policyset.serverCertSet.9.default.name=copy CN to SAN Default +diff --git a/base/ca/shared/profiles/ca/caCMCsubsystemCert.cfg b/base/ca/shared/profiles/ca/caCMCsubsystemCert.cfg +new file mode 100644 +index 0000000..f473f98 +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caCMCsubsystemCert.cfg +@@ -0,0 +1,86 @@ ++desc=This certificate profile is for enrolling subsystem certificates using CMC. ++visible=false ++enable=true ++enableBy=admin ++auth.instance_id=CMCAuth ++authz.acl=group="Certificate Manager Agents" ++name=Subsystem Certificate Enrollment using CMC ++input.list=i1,i2 ++input.i1.class_id=certReqInputImpl ++input.i2.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=certOutputImpl ++policyset.list=serverCertSet ++policyset.serverCertSet.list=1,2,3,4,5,6,7,8 ++policyset.serverCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.serverCertSet.1.constraint.name=Subject Name Constraint ++policyset.serverCertSet.1.constraint.params.pattern=CN=.* ++policyset.serverCertSet.1.constraint.params.accept=true ++policyset.serverCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.serverCertSet.1.default.name=Subject Name Default ++policyset.serverCertSet.1.default.params.name= ++policyset.serverCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.serverCertSet.2.constraint.name=Validity Constraint ++policyset.serverCertSet.2.constraint.params.range=720 ++policyset.serverCertSet.2.constraint.params.notBeforeCheck=false ++policyset.serverCertSet.2.constraint.params.notAfterCheck=false ++policyset.serverCertSet.2.default.class_id=validityDefaultImpl ++policyset.serverCertSet.2.default.name=Validity Default ++policyset.serverCertSet.2.default.params.range=720 ++policyset.serverCertSet.2.default.params.startTime=0 ++policyset.serverCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.serverCertSet.3.constraint.name=Key Constraint ++policyset.serverCertSet.3.constraint.params.keyType=- ++policyset.serverCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 ++policyset.serverCertSet.3.default.class_id=userKeyDefaultImpl ++policyset.serverCertSet.3.default.name=Key Default ++policyset.serverCertSet.4.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.4.constraint.name=No Constraint ++policyset.serverCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.serverCertSet.4.default.name=Authority Key Identifier Default ++policyset.serverCertSet.5.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.5.constraint.name=No Constraint ++policyset.serverCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.serverCertSet.5.default.name=AIA Extension Default ++policyset.serverCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.serverCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.serverCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.serverCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.serverCertSet.5.default.params.authInfoAccessCritical=false ++policyset.serverCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.serverCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.serverCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.serverCertSet.6.constraint.params.keyUsageCritical=true ++policyset.serverCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.serverCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.serverCertSet.6.constraint.params.keyUsageDataEncipherment=true ++policyset.serverCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.serverCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.serverCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.serverCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.serverCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.serverCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.serverCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.serverCertSet.6.default.name=Key Usage Default ++policyset.serverCertSet.6.default.params.keyUsageCritical=true ++policyset.serverCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.serverCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.serverCertSet.6.default.params.keyUsageDataEncipherment=true ++policyset.serverCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.serverCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.serverCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.serverCertSet.6.default.params.keyUsageCrlSign=false ++policyset.serverCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.serverCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.serverCertSet.7.constraint.class_id=noConstraintImpl ++policyset.serverCertSet.7.constraint.name=No Constraint ++policyset.serverCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.serverCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.serverCertSet.7.default.params.exKeyUsageCritical=false ++policyset.serverCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2 ++policyset.serverCertSet.8.constraint.class_id=signingAlgConstraintImpl ++policyset.serverCertSet.8.constraint.name=No Constraint ++policyset.serverCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.serverCertSet.8.default.class_id=signingAlgDefaultImpl ++policyset.serverCertSet.8.default.name=Signing Alg ++policyset.serverCertSet.8.default.params.signingAlg=- +diff --git a/base/ca/shared/profiles/ca/caFullCMCUserCert.cfg b/base/ca/shared/profiles/ca/caFullCMCUserCert.cfg +index 29baeed..90cb424 100644 +--- a/base/ca/shared/profiles/ca/caFullCMCUserCert.cfg ++++ b/base/ca/shared/profiles/ca/caFullCMCUserCert.cfg +@@ -1,7 +1,7 @@ +-desc=This certificate profile is for enrolling user certificates by using the CMC certificate request with CMC Signature authentication. ++desc=This certificate profile is for enrolling user certificates by using the agent-signed CMC certificate request with CMC Signature authentication. + enable=true + enableBy=admin +-name=Signed CMC-Authenticated User Certificate Enrollment ++name=Agent-Signed CMC-Authenticated User Certificate Enrollment + visible=false + auth.instance_id=CMCAuth + input.list=i1,i2 +diff --git a/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg b/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg +index 63a4bca..7bfad9c 100644 +--- a/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg ++++ b/base/ca/shared/profiles/ca/caFullCMCUserSignedCert.cfg +@@ -1,4 +1,4 @@ +-desc=This certificate profile is for enrolling user certificates by using the CMC certificate request with user CMC Signature authentication. ++desc=This certificate profile is for enrolling user certificates by using the CMC certificate request with non-agent user CMC authentication. + enable=true + enableBy=admin + name=User-Signed CMC-Authenticated User Certificate Enrollment +diff --git a/base/ca/shared/webapps/ca/WEB-INF/web.xml b/base/ca/shared/webapps/ca/WEB-INF/web.xml +index a550142..2666049 100644 +--- a/base/ca/shared/webapps/ca/WEB-INF/web.xml ++++ b/base/ca/shared/webapps/ca/WEB-INF/web.xml +@@ -1553,6 +1553,167 @@ + + + ++ caProfileSubmitCMCFullCACert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCcaCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullServerCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCserverCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullOCSPCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCocspCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullSubsystemCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCsubsystemCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullAuditSigningCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCauditSigningCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullKRATransportCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCkraTransportCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ ++ caProfileSubmitCMCFullKRAstorageCert ++ com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet ++ GetClientCert ++ false ++ cert_request_type ++ cmc ++ profileId ++ caCMCkraStorageCert ++ AuthzMgr ++ BasicAclAuthz ++ authorityId ++ ca ++ ID ++ caProfileSubmitCMCFull ++ templatePath ++ /ee/ca/ProfileSubmit.template ++ resourceID ++ certServer.ee.profile ++ interface ++ ee ++ ++ ++ + caProfileSubmitUserSignedCMCFull + com.netscape.cms.servlet.profile.ProfileSubmitCMCServlet + GetClientCert +@@ -2303,6 +2464,41 @@ + + + ++ caProfileSubmitCMCFullCACert ++ /ee/ca/profileSubmitCMCFullCACert ++ ++ ++ ++ caProfileSubmitCMCFullServerCert ++ /ee/ca/profileSubmitCMCFullServerCert ++ ++ ++ ++ caProfileSubmitCMCFullOCSPCert ++ /ee/ca/profileSubmitCMCFullOCSPCert ++ ++ ++ ++ caProfileSubmitCMCFullSubsystemCert ++ /ee/ca/profileSubmitCMCFullSubsystemCert ++ ++ ++ ++ caProfileSubmitCMCFullAuditSigningCert ++ /ee/ca/profileSubmitCMCFullAuditSigningCert ++ ++ ++ ++ caProfileSubmitCMCFullKRATransportCert ++ /ee/ca/profileSubmitCMCFullKRAtransportCert ++ ++ ++ ++ caProfileSubmitCMCFullKRAstorageCert ++ /ee/ca/profileSubmitCMCFullKRAstorageCert ++ ++ ++ + caProfileSubmitUserSignedCMCFull + /ee/ca/profileSubmitUserSignedCMCFull + +diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java +index fd59aa1..9fcb8db 100644 +--- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java ++++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java +@@ -2393,7 +2393,7 @@ public class CMCRequest { + System.out.println(""); + System.out.println(""); + System.out.println("The CMC enrollment request in binary format is stored in " + +- ofilename + "."); ++ ofilename); + } catch (IOException e) { + System.out.println("CMCRequest: unable to open file " + ofilename + + " for writing:\n" + e); +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 9441167..459c7c6 100644 +--- a/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java ++++ b/base/server/cms/src/com/netscape/cms/authentication/CMCAuth.java +@@ -29,6 +29,7 @@ import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; + import java.io.IOException; + import java.math.BigInteger; ++import java.security.cert.X509Certificate; + import java.security.MessageDigest; + import java.security.PublicKey; + import java.util.Enumeration; +@@ -246,6 +247,10 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo, + String auditCertSubject = ILogger.UNIDENTIFIED; + String auditSignerInfo = ILogger.UNIDENTIFIED; + ++ SessionContext auditContext = SessionContext.getExistingContext(); ++ X509Certificate clientCert = ++ (X509Certificate) auditContext.get(SessionContext.SSL_CLIENT_CERT); ++ + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { +@@ -361,7 +366,7 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo, + String userid = "defUser"; + String uid = "defUser"; + if (checkSignerInfo) { +- IAuthToken agentToken = verifySignerInfo(authToken, cmcFullReq); ++ IAuthToken agentToken = verifySignerInfo(auditContext, authToken, cmcFullReq); + if (agentToken == null) { + CMS.debug(method + "agentToken null"); + throw new EBaseException("CMCAuth: agent verifySignerInfo failure"); +@@ -812,8 +817,12 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo, + level, "CMC Authentication: " + msg); + } + +- protected IAuthToken verifySignerInfo(AuthToken authToken, SignedData cmcFullReq) throws EBaseException { +- ++ protected IAuthToken verifySignerInfo( ++ SessionContext auditContext, ++ AuthToken authToken, ++ SignedData cmcFullReq) throws EBaseException { ++ String method = "CMCAuth: verifySignerInfo: "; ++ String msg = ""; + EncapsulatedContentInfo ci = cmcFullReq.getContentInfo(); + OBJECT_IDENTIFIER id = ci.getContentType(); + OCTET_STRING content = ci.getContent(); +@@ -822,6 +831,11 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo, + CryptoToken signToken = null; + CryptoToken savedToken = null; + CryptoManager cm = null; ++ ++ if (auditContext == null) { ++ CMS.debug(method + " auditConext can't be null"); ++ return null; ++ } + try { + cm = CryptoManager.getInstance(); + ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray()); +@@ -909,6 +923,34 @@ public class CMCAuth implements IAuthManager, IExtendedPluginInfo, + si.verify(digest, id); + } else { + CMS.debug("CMCAuth: found signing cert... verifying"); ++ ++ X509Certificate clientCert = ++ (X509Certificate) auditContext.get(SessionContext.SSL_CLIENT_CERT); ++ 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(); ++ ++ netscape.security.x509.X500Name cmcPrincipal = ++ (X500Name) x509Certs[0].getSubjectDN(); ++ ++ // 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); ++ } else { ++ CMS.debug(method + "ssl client cert principal and cmc signer principal match"); ++ } ++ + PublicKey signKey = cert.getPublicKey(); + PrivateKey.Type keyType = null; + String alg = signKey.getAlgorithm(); +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 6c3ee8f..e11a344 100644 +--- a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java ++++ b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java +@@ -1078,6 +1078,8 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo, + s.close(); + throw new EInvalidCredentials( + CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL") + ":" + msg); ++ } else { ++ CMS.debug(method + "ssl client cert principal and cmc signer principal match"); + } + + PublicKey signKey = cert.getPublicKey(); +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 8f3e986..1356035 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 +@@ -198,6 +198,7 @@ public abstract class EnrollProfile extends BasicProfile + if (signingUserSerial != null) { + donePOI = true; + } ++ + // catch for invalid request + cmc_msgs = parseCMC(locale, cert_request, donePOI); + if (cmc_msgs == null) { +@@ -723,6 +724,17 @@ public abstract class EnrollProfile extends BasicProfile + byte randomSeed[] = null; + UTF8String ident_s = null; + 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); ++ } ++ if(authManagerId.equals("CMCAuth")) { ++ donePOI = true; ++ } + + boolean id_cmc_revokeRequest = false; + if (!context.containsKey("numOfControls")) { +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 d087162..f7a6470 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 +@@ -496,7 +496,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { + /////////////////////////////////////////////// + String tmpCertSerialS = ctx.get(IAuthManager.CRED_CMC_SIGNING_CERT); + if (tmpCertSerialS != null) { +- // unlikely to happenm, but do this just in case ++ // unlikely to happen, but do this just in case + CMS.debug("ProfileSubmitCMCServlet: found existing CRED_CMC_SIGNING_CERT in ctx for CMCUserSignedAuth:" + tmpCertSerialS); + CMS.debug("ProfileSubmitCMCServlet: null it out"); + ctx.set(IAuthManager.CRED_CMC_SIGNING_CERT, ""); +-- +1.8.3.1 + diff --git a/SPECS/pki-core.spec b/SPECS/pki-core.spec index 2537c92..dc582cc 100644 --- a/SPECS/pki-core.spec +++ b/SPECS/pki-core.spec @@ -66,7 +66,8 @@ Name: pki-core %if 0%{?rhel} Version: 10.4.1 -Release: 10%{?dist} +#Release: 13%{?dist} +Release: 13.el7_4 %else Version: 10.4.8 Release: 1%{?dist} @@ -275,6 +276,24 @@ Patch9: pki-core-Fix-3DES-archival.patch Patch10: pki-core-Fix-token-enrollment-and-recovery-ivs.patch Patch11: pki-core-CMC-check-HTTPS-client-authentication-cert.patch Patch12: pki-core-Fix-regression-in-pkcs12-key-bag-creation.patch +####################### +## pki-core-10.4.1-11 +####################### +Patch13: pki-core-cmc-plugin-default-change.patch +####################### +## pki-core-10.4.1-12 +####################### +Patch14: pki-core-server-access-banner-validation.patch +Patch15: pki-core-pre-signed-CMC-renewal-UniqueKeyConstraint.patch +Patch16: pki-core-platform-dependent-python-import.patch +Patch17: pki-core-CMC-id-cmc-statusInfoV2.patch +Patch18: pki-core-subsystem-cert-update-CLI-cert-option.patch +Patch19: pki-core-HSM-key-changeover-SCP03-support.patch +Patch20: pki-core-system-cert-CMC-enroll-profile.patch +####################### +## pki-core-10.4.1-13 +####################### +Patch21: pki-core-server-access-banner-retrieval-validation.patch @@ -954,6 +973,15 @@ This package is a part of the PKI Core used by the Certificate System. %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 %clean %{__rm} -rf %{buildroot} @@ -1479,6 +1507,59 @@ fi %endif # %{with server} %changelog +* Mon Aug 21 2017 Dogtag Team 10.4.1-13 +- Resolves: rhbz #1463350 +- ########################################################################## +- RHEL 7.4: +- ########################################################################## +- Bugzilla Bug #1463350 - Access banner validation (edewata) + [pki-core-server-access-banner-retrieval-validation.patch] + +* Wed Jul 19 2017 Dogtag Team 10.4.1-12 +- Resolves: rhbz #1472615,1472617,1469447,1463350,1469449,1472619,1464970,1469437,1469439,1469446 +- ########################################################################## +- RHEL 7.4: +- ########################################################################## +- Bugzilla Bug #1472615 - CC: allow CA to process pre-signed CMC non-signing + certificate requests (cfu) + [PREVIOUS PATCH: pki-core-beta.patch] + [PREVIOUS PATCH: pki-core-snapshot-4.patch] +- Bugzilla Bug #1472617 - CMC: cmc.popLinkWitnessRequired=false would cause + error (cfu) + [PREVIOUS PATCH: pki-core-post-beta.patch] +- Bugzilla Bug #1469447 - CC: CMC: check HTTPS client authentication cert + against CMC signer (cfu) + [PREVIOUS PATCH: pki-core-CMC-check-HTTPS-client-authentication-cert.patch] +- Bugzilla Bug #1463350 - Access banner validation (edewata) + [pki-core-server-access-banner-validation.patch] +- Bugzilla Bug #1469449 - CC: allow CA to process pre-signed CMC renewal + non-signing cert requests (cfu) + [PREVIOUS PATCH: pki-core-snapshot-1.patch] + [pki-core-pre-signed-CMC-renewal-UniqueKeyConstraint.patch] +- Bugzilla Bug #1472619 - Platform Dependent Python Import (mharmsen) + [pki-core-platform-dependent-python-import.patch] +- Bugzilla Bug #1464970 - CC: CMC: replace id-cmc-statusInfo with + id-cmc-statusInfoV2 (cfu) + [pki-core-CMC-id-cmc-statusInfoV2.patch] +- Bugzilla Bug #1469437 - subsystem-cert-update command lacks --cert option + (dmoluguw) + [pki-core-subsystem-cert-update-CLI-cert-option.patch] +- Bugzilla Bug #1469439 - Fix Key Changeover with HSM to support SCP03 + (jmagne) + [pki-core-HSM-key-changeover-SCP03-support.patch] +- Bugzilla Bug #1469446 - CC: need CMC enrollment profiles for system + certificates (cfu) + [pki-core-system-cert-CMC-enroll-profile.patch] + +* Mon Jul 17 2017 Dogtag Team 10.4.1-11 +- Resolves: rhbz #1469432 +- ########################################################################## +- RHEL 7.4: +- ########################################################################## +- Bugzilla Bug #1469432 - CMC plugin default change +- Resolves CVE-2017-7537 +- Fixes BZ #1470948 + * Mon Jun 19 2017 Dogtag Team 10.4.1-10 - ########################################################################## - RHEL 7.4: