diff --git a/.gitignore b/.gitignore index a57db63..32f3e90 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/pki-core-10.5.17.tar.gz +SOURCES/pki-core-10.5.18.tar.gz diff --git a/.pki-core.metadata b/.pki-core.metadata index 306bc26..ae103aa 100644 --- a/.pki-core.metadata +++ b/.pki-core.metadata @@ -1 +1 @@ -2debe6d869c88d4cd98de0cce80dfe8317d35dbc SOURCES/pki-core-10.5.17.tar.gz +34afe9bc29940361963772a7dc08f1d26af3db6b SOURCES/pki-core-10.5.18.tar.gz diff --git a/SOURCES/pki-core-Fix-CMCResponse-tool.patch b/SOURCES/pki-core-Fix-CMCResponse-tool.patch new file mode 100644 index 0000000..46186fc --- /dev/null +++ b/SOURCES/pki-core-Fix-CMCResponse-tool.patch @@ -0,0 +1,57 @@ +From a391af8c91b8ad108b4111c0e671bce43193bf19 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Thu, 21 May 2020 16:36:44 -0700 +Subject: [PATCH] Related: Bug 1710109 - add RSA PSS support. (#418) + +This fix is to the CMCRespone tool. + +The tool currently does not initialize the CryptoManager. +Doing so is necessary to register the JSS Provider which provides the +encoding / parsing support for the RSAPSS algorithm parameters. + +Co-authored-by: Jack Magne +(cherry picked from commit ece00d4c2cbacf187b9f44873ff70e90497e5ccd) +--- + base/java-tools/src/com/netscape/cmstools/CMCResponse.java | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/base/java-tools/src/com/netscape/cmstools/CMCResponse.java b/base/java-tools/src/com/netscape/cmstools/CMCResponse.java +index 5d4f6c6..d98ab0a 100644 +--- a/base/java-tools/src/com/netscape/cmstools/CMCResponse.java ++++ b/base/java-tools/src/com/netscape/cmstools/CMCResponse.java +@@ -53,6 +53,7 @@ import org.mozilla.jss.pkix.cmc.TaggedAttribute; + import org.mozilla.jss.pkix.cms.ContentInfo; + import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; + import org.mozilla.jss.pkix.cms.SignedData; ++import org.mozilla.jss.CryptoManager; + + import com.netscape.cmsutil.util.Utils; + import netscape.security.pkcs.PKCS7; +@@ -352,8 +353,7 @@ public class CMCResponse { + + CommandLine cmd = parser.parse(options, args, true); + +- @SuppressWarnings("unused") +- String database = cmd.getOptionValue("d"); ++ String dbdir = cmd.getOptionValue("d"); + + String input = cmd.getOptionValue("i"); + String output = cmd.getOptionValue("o"); +@@ -370,6 +370,14 @@ public class CMCResponse { + System.exit(1); + } + ++ //Intialize the crypto manager, just in case we need to use the JSS Provider to parse ++ //algorithm parameters. All we have to do is initialize the manager and be done. ++ ++ if (dbdir == null) ++ dbdir = "."; ++ ++ CryptoManager.initialize(dbdir); ++ + // load CMC response + byte[] data = Files.readAllBytes(Paths.get(input)); + +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-Fix-RSA-PSS-for-IPA-installer.patch b/SOURCES/pki-core-Fix-RSA-PSS-for-IPA-installer.patch new file mode 100644 index 0000000..fe7728f --- /dev/null +++ b/SOURCES/pki-core-Fix-RSA-PSS-for-IPA-installer.patch @@ -0,0 +1,37 @@ +From 0d68b11baa49673a8f43cf1e4f325427ab2066da Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Mon, 30 Mar 2020 20:40:50 -0400 +Subject: [PATCH] Minor fix to appease ipa install. The code in question was + getting (#364) + +an algorithmId name with trailing whitespace, which was not recognized. + +Co-authored-by: Jack Magne +(cherry picked from commit 53de751485b04fe2a1555228342ed642c9a9e347) +--- + .../cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java +index 97f221e..a0d0d33 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/SigningAlgDefault.java +@@ -119,9 +119,14 @@ public class SigningAlgDefault extends EnrollDefault { + } + if (name.equals(VAL_ALGORITHM)) { + try { ++ String newValue = value; ++ if(newValue != null) { ++ newValue = newValue.trim(); ++ } ++ CMS.debug("SigningAlgDefault: setValue value: " + newValue); + info.set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId( +- AlgorithmId.get(value))); ++ AlgorithmId.get(newValue))); + } catch (Exception e) { + CMS.debug("SigningAlgDefault: setValue " + e.toString()); + throw new EPropertyException(CMS.getUserMessage( +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-Fix-RSA-PSS-for-SHA512.patch b/SOURCES/pki-core-Fix-RSA-PSS-for-SHA512.patch new file mode 100644 index 0000000..9c5ad61 --- /dev/null +++ b/SOURCES/pki-core-Fix-RSA-PSS-for-SHA512.patch @@ -0,0 +1,30 @@ +From daf32eda6c44690391e56a92802379ae677f01fa Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Thu, 7 May 2020 13:20:02 -0400 +Subject: [PATCH] Fix to allow the SHA512withRSA/PSS algorithm to operate + properly. (#404) + +Previously signature using this alg has had the params malformed within. + +Co-authored-by: Jack Magne +(cherry picked from commit 5a3169fa6620cdebbc33c0df14e3759db4cee9ea) +--- + base/util/src/netscape/security/x509/AlgorithmId.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/util/src/netscape/security/x509/AlgorithmId.java b/base/util/src/netscape/security/x509/AlgorithmId.java +index a5e4906..54446b5 100644 +--- a/base/util/src/netscape/security/x509/AlgorithmId.java ++++ b/base/util/src/netscape/security/x509/AlgorithmId.java +@@ -763,7 +763,7 @@ public class AlgorithmId implements Serializable, DerEncoder { + } else if ("SHA384withRSA/PSS".equals(algName)) { + pssSpec = new PSSParameterSpec("SHA-384", "MGF1", MGF1ParameterSpec.SHA384, 48, 1); + +- } else if ("SHA384withRSA/PSS".equals(algName)) { ++ } else if ("SHA512withRSA/PSS".equals(algName)) { + pssSpec = new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, 1); + } + try { +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-Fixed-missing-audit-event.patch b/SOURCES/pki-core-Fixed-missing-audit-event.patch deleted file mode 100644 index 7389107..0000000 --- a/SOURCES/pki-core-Fixed-missing-audit-event.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 624dc7f769c2a7744bd390eff3e3c6cd0dbd140f Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Thu, 17 Oct 2019 16:36:05 -0700 -Subject: [PATCH] =?UTF-8?q?Bug=201523330=20-=20(addl=20fix)=20CC:=20missin?= - =?UTF-8?q?g=20audit=20event=20for=20CS=20acting=20as=20TLS=20client=20Bug?= - =?UTF-8?q?=201585722=20-=20TMS=20-=20PKISocketFactory=20=E2=80=93=20Modif?= - =?UTF-8?q?y=20Logging=20to=20Allow=20External=20Use=20of=20class=20to=20w?= - =?UTF-8?q?ork=20like=20CS8?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix in 1523330 might have broken 1585722; This patch is to put the audit -call under if (!external) so that external apps calling this class would -not reach the audit code. -I only tested to be sure that the CA continues to work; QE will need to -test both again. - -https://bugzilla.redhat.com/show_bug.cgi?id=1523330 -https://bugzilla.redhat.com/show_bug.cgi?id=1585722 -(cherry picked from commit 4dfd4893b6598d79ad5d5542795c4792091905c7) ---- - .../cmscore/ldapconn/PKISocketFactory.java | 27 ++++++++++++---------- - 1 file changed, 15 insertions(+), 12 deletions(-) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -index dc93f5d..6f5a876 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -@@ -85,12 +85,12 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - if(!external){ - IConfigStore cs = CMS.getConfigStore(); - keepAlive = cs.getBoolean("tcp.keepAlive", true); -+ sockListener = new PKIClientSocketListener(); - } else { - keepAlive = true; - } - - log(Level.INFO, "TCP Keep-Alive: " + keepAlive, null); -- sockListener = new PKIClientSocketListener(); - - } catch (Exception e) { - log(Level.SEVERE, null, e); -@@ -162,23 +162,26 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - s.setKeepAlive(keepAlive); - - } catch (Exception e) { -- // for auditing -- String localIP = "localhost"; -- try { -- localIP = InetAddress.getLocalHost().getHostAddress(); -- } catch (UnknownHostException e2) { -- // default to "localhost"; -- } -- SignedAuditEvent auditEvent; -- auditEvent = ClientAccessSessionEstablishEvent.createFailureEvent( -+ if (!external) { -+ // for auditing -+ String localIP = "localhost"; -+ try { -+ localIP = InetAddress.getLocalHost().getHostAddress(); -+ } catch (UnknownHostException e2) { -+ // default to "localhost"; -+ } -+ -+ SignedAuditEvent auditEvent; -+ auditEvent = ClientAccessSessionEstablishEvent.createFailureEvent( - localIP, - host, - Integer.toString(port), - "SYSTEM", - "connect:" +e.toString()); -- signedAuditLogger.log(auditEvent); -+ signedAuditLogger.log(auditEvent); -+ } -+ log(Level.SEVERE, null, e); - -- CMS.debug(e); - if (s != null) { - try { - s.close(); --- -1.8.3.1 - diff --git a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-alpha.patch b/SOURCES/pki-core-rhel-7-8-rhcs-9-6-alpha.patch deleted file mode 100644 index 25f39d5..0000000 --- a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-alpha.patch +++ /dev/null @@ -1,734 +0,0 @@ -From fb857eac7f74c91fda65dd9d676b28b6df2eaa78 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Thu, 3 Jan 2019 20:08:36 -0600 -Subject: [PATCH 1/7] Removed validation for token state transitions - -The TPSSubsystem has been modified to remove the validation for -tokendb.allowedTransitions property. This will allow adding new -transitions via PKI CLI or TPS Web UI. - -The TPSSubsystem will continue to validate tps.operations.allowedTransitions -as before so it will only allow transitions already defined in -the default CS.cfg. - -https://bugzilla.redhat.com/show_bug.cgi?id=1470433 -(cherry picked from commit e9079332d66f166cd89673e2160fd52dbb48728c) ---- - .../src/org/dogtagpki/server/tps/TPSSubsystem.java | 4 +- - docs/admin/TPS_Token_Lifecycle.md | 139 +++++++++++++++++++++ - 2 files changed, 141 insertions(+), 2 deletions(-) - create mode 100644 docs/admin/TPS_Token_Lifecycle.md - -diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java -index 2f43ba3..0e8f318 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java -+++ b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java -@@ -126,8 +126,8 @@ public class TPSSubsystem implements IAuthority, ISubsystem { - - FileConfigStore defaultConfig = new FileConfigStore("/usr/share/pki/tps/conf/CS.cfg"); - -- uiTransitions = loadAndValidateTokenStateTransitions( -- defaultConfig, cs, TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS); -+ uiTransitions = loadTokenStateTransitions( -+ cs, TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS); - - operationTransitions = loadAndValidateTokenStateTransitions( - defaultConfig, cs, TPSEngine.CFG_OPERATIONS_ALLOWED_TRANSITIONS); -diff --git a/docs/admin/TPS_Token_Lifecycle.md b/docs/admin/TPS_Token_Lifecycle.md -new file mode 100644 -index 0000000..194a95f ---- /dev/null -+++ b/docs/admin/TPS_Token_Lifecycle.md -@@ -0,0 +1,139 @@ -+# TPS Token Lifecycle -+ -+## Token States -+ -+Below are the supported token states in TPS: -+ -+| Code | Name | Label | -+| ---- | ----------- | ---------------------------- | -+| 0 | FORMATTED | Formatted (uninitialized) | -+| 1 | DAMAGED | Physically damaged | -+| 2 | PERM_LOST | Permanently lost | -+| 3 | SUSPENDED | Suspended (temporarily lost) | -+| 4 | ACTIVE | Active | -+| 6 | TERMINATED | Terminated | -+| 7 | UNFORMATTED | Unformatted | -+ -+In the CS.cfg the token states will be displayed by their codes. -+In PKI CLI the token states will be displayed by their names. -+In TPS Web UI the token states will be displayed by their labels. -+ -+## Token State Transitions via PKI CLI or TPS Web UI -+ -+Token state can be changed via PKI CLI or TPS Web UI. -+The transitions that can be done via PKI CLI or TPS Web UI are defined in the following property in -+/etc/pki/<instance>/tps/CS.cfg: -+ -+``` -+tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:6,4:1,4:2,4:3,4:6,6:7 -+``` -+ -+The property contains a comma-separated list of transitions. Each transition is written in this format: -+ -+ : -+ -+The above list represents the following transitions: -+ -+| Transition | Current State | Next State | Label | -+| ---------- | ------------- | ----------- | -------------------------------------------------------------- | -+| 0:1 | FORMATTED | DAMAGED | This token has been physically damaged. | -+| 0:2 | FORMATTED | PERM_LOST | This token has been permanently lost. | -+| 0:3 | FORMATTED | SUSPENDED | This token has been suspended (temporarily lost). | -+| 0:6 | FORMATTED | TERMINATED | This token has been terminated. | -+| 3:2 | SUSPENDED | TERMINATED | This suspended (temporarily lost) token has been terminated. | -+| 3:6 | SUSPENDED | PERM_LOST | This suspended (temporarily lost) has become permanently lost. | -+| 4:1 | ACTIVE | DAMAGED | This token has been physically damaged. | -+| 4:2 | ACTIVE | PERM_LOST | This token has been permanently lost. | -+| 4:3 | ACTIVE | SUSPENDED | This token has been suspended (temporarily lost). | -+| 4:6 | ACTIVE | TERMINATED | This token has been terminated. | -+| 6:7 | TERMINATED | UNFORMATTED | Reuse this token. | -+ -+The following transitions are generated automatically depending on the original state of the token. -+If a token was originally FORMATTED then became SUSPENDED, it can only return to FORMATTED state. -+If a token was originally ACTIVE then became SUSPENDED, it can only return to the ACTIVE state. -+ -+| Transition | Current State | Next State | Label | -+| ---------- | ------------- | ---------- | ------------------------------------------------------- | -+| 3:2 | SUSPENDED | FORMATTED | This suspended (temporarily lost) token has been found. | -+| 3:4 | SUSPENDED | ACTIVE | This suspended (temporarily lost) token has been found. | -+ -+To customize the tokendb.allowedTransitions property, edit the property in /etc/pki/<instance>/tps/CS.cfg, -+then restart the server. -+ -+## Token State Transitions via Token Operations -+ -+Token states can also be changed via token operations (e.g. format, enroll). -+The transitions that can be done via token operations are defined in the following property in -+/etc/pki/<instance>/tps/CS.cfg: -+ -+``` -+tps.operations.allowedTransitions=0:0,0:4,4:4,4:0,7:0 -+``` -+ -+The property contains a comma-delimited list of transitions. -+Each transition is written in this format: -+ -+ : -+ -+The above list represents the following transitions: -+ -+| Transition | Current State | Next State | Description | -+| ---------- | ------------- | ---------- | --------------------------------------------------------------------- | -+| 0:0 | FORMATTED | FORMATTED | This allows reformatting a token or upgrading applet/key in a token. | -+| 0:4 | FORMATTED | ACTIVE | This allows enrolling a token. | -+| 4:4 | ACTIVE | ACTIVE | This allows re-enrolling an active token (for external registration). | -+| 4:0 | ACTIVE | FORMATTED | This allows formatting an active token. | -+| 7:0 | UNFORMATTED | FORMATTED | This allows formatting a blank or previously used token. | -+ -+To customize the tps.operations.allowedTransitions property, edit the property in /etc/pki/<instance>/tps/CS.cfg, -+then restart the server. -+ -+This property can only be customized to remove transitions from the original list. -+New transitions cannot be added into tps.operations.allowedTransitions unless it is already defined -+in the default tps.operations.allowedTransitions in /usr/share/pki/tps/conf/CS.cfg. -+ -+## Token State and Transition Labels for TPS Web UI -+ -+The default token state and transition labels for TPS Web UI are defined in /usr/share/pki/tps/conf/token-states.properties: -+ -+``` -+# Token states -+UNFORMATTED = Unformatted -+FORMATTED = Formatted (uninitialized) -+ACTIVE = Active -+SUSPENDED = Suspended (temporarily lost) -+PERM_LOST = Permanently lost -+DAMAGED = Physically damaged -+TEMP_LOST_PERM_LOST = Temporarily lost then permanently lost -+TERMINATED = Terminated -+ -+# Token state transitions -+FORMATTED.DAMAGED = This token has been physically damaged. -+FORMATTED.PERM_LOST = This token has been permanently lost. -+FORMATTED.SUSPENDED = This token has been suspended (temporarily lost). -+FORMATTED.TERMINATED = This token has been terminated. -+SUSPENDED.ACTIVE = This suspended (temporarily lost) token has been found. -+SUSPENDED.PERM_LOST = This suspended (temporarily lost) token has become permanently lost. -+SUSPENDED.TERMINATED = This suspended (temporarily lost) token has been terminated. -+SUSPENDED.FORMATTED = This suspended (temporarily lost) token has been found. -+ACTIVE.DAMAGED = This token has been physically damaged. -+ACTIVE.PERM_LOST = This token has been permanently lost. -+ACTIVE.SUSPENDED = This token has been suspended (temporarily lost). -+ACTIVE.TERMINATED = This token has been terminated. -+TERMINATED.UNFORMATTED = Reuse this token. -+``` -+ -+To customize the labels, copy the default token-states.properties into TPS configuration folder: -+ -+``` -+$ cp /usr/share/pki/tps/conf/token-states.properties /var/lib/pki/pki-tomcat/tps/conf -+``` -+Then edit the new file. -+There is no need to restart the server, but the TPS Web UI will need to be reloaded. -+ -+To remove the customized labels simply delete the customized file: -+ -+``` -+$ rm /var/lib/pki/pki-tomcat/tps/conf/token-states.properties -+``` -+Then reload the TPS Web UI. --- -1.8.3.1 - - -From 80c61529b041dca01116726535de87f18a5d16cd Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Thu, 15 Aug 2019 12:23:57 -0400 -Subject: [PATCH 2/7] Resolve (additional patch for) Bug 1470410 - TPS doesn't - update revocation status when certificate already marked as - unformatted/terminated/damaged - -This is one of the previously missed patches. -Submited by RHCS-maint - -(cherry picked from commit e4b9e6ed3cf03bd8c026d2d944b615f9b306219a) ---- - base/ca/src/com/netscape/ca/CAService.java | 8 +++++--- - .../src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java | 3 ++- - 2 files changed, 7 insertions(+), 4 deletions(-) - -diff --git a/base/ca/src/com/netscape/ca/CAService.java b/base/ca/src/com/netscape/ca/CAService.java -index e4e4efe..4e8afac 100644 ---- a/base/ca/src/com/netscape/ca/CAService.java -+++ b/base/ca/src/com/netscape/ca/CAService.java -@@ -981,7 +981,7 @@ public class CAService implements ICAService, IService { - CRLExtensions crlentryexts = crlentry.getExtensions(); - String msg = ""; - -- CMS.debug("CAService.revokeCert: revokeCert begins"); -+ CMS.debug("CAService.revokeCert: revokeCert begins: serial:" + serialno.toString()); - - // Get the revocation reason - Enumeration enum1 = crlentryexts.getElements(); -@@ -1000,6 +1000,7 @@ public class CAService implements ICAService, IService { - CMS.getUserMessage("CMS_CA_MISSING_REV_REASON", - "0x" + serialno.toString(16))); - } -+ CMS.debug("CAService.revokeCert: revocaton request revocation reason: " + revReason.toString()); - - CertRecord certRec = (CertRecord) mCA.getCertificateRepository().readCertificateRecord(serialno); - -@@ -1026,6 +1027,7 @@ public class CAService implements ICAService, IService { - CMS.debug("CAService.revokeCert: " + msg); - throw new EBaseException(msg); - } -+ CMS.debug("CAService.revokeCert: already revoked cert with existing revocation reason:" + recRevReason.toString()); - } - - // for cert already revoked, also check whether revocation reason is changed from SUPERSEDED to KEY_COMPROMISE -@@ -1044,11 +1046,11 @@ public class CAService implements ICAService, IService { - try { - // if cert has already revoked, update the revocation info only - CMS.debug("CAService.revokeCert: about to call markAsRevoked"); -- if (certStatus.equals(ICertRecord.STATUS_REVOKED) && certRec.isCertOnHold()) { -+ if (certStatus.equals(ICertRecord.STATUS_REVOKED)) { - mCA.getCertificateRepository().markAsRevoked(serialno, - new RevocationInfo(revdate, crlentryexts), - true /*isAlreadyRevoked*/); -- CMS.debug("CAService.revokeCert: on_hold cert marked revoked"); -+ CMS.debug("CAService.revokeCert: Already-revoked cert marked revoked"); - mCA.log(ILogger.LL_INFO, - CMS.getLogMessage("CMSCORE_CA_CERT_REVO_INFO_UPDATE", - recRevReason.toString(), -diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java -index 39529c9..16ae5fd 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java -+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java -@@ -540,10 +540,11 @@ public class CARemoteRequestHandler extends RemoteRequestHandler - } else { - CMS.debug("CARemoteRequestHandler: revokeCertificate(): using default ca ID:" + connid); - } -- CMS.debug("CARemoteRequestHandler: revokeCertificate(): begins on serial#:" + serialno); -+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): begins"); - if (serialno == null || reason == null) { - throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter null."); - } -+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): revoking serial#:" + serialno + "; reason String:" + reason.toString() + "; reason code:" + reason.getCode()); - - // IConfigStore conf = CMS.getConfigStore(); - --- -1.8.3.1 - - -From aef8f648e4651f29cec0ba7e8235185d94e8f39b Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Thu, 15 Aug 2019 18:21:33 -0400 -Subject: [PATCH 3/7] Resolve (additiona patch for) Bug 1470433 - Add supported - transitions to TPS - -per suggestion in comment#4 - -Submited by RHCS-maint. - -(cherry picked from commit f9c10c352fc2129cd9f2cdf6baade6e445de5bd0) ---- - base/tps/shared/conf/CS.cfg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg -index 8a9d828..eb5b831 100644 ---- a/base/tps/shared/conf/CS.cfg -+++ b/base/tps/shared/conf/CS.cfg -@@ -2448,7 +2448,7 @@ tokendb.addConfigTemplate=addConfig.template - tokendb.addResultTemplate=addResults.template - tokendb.agentSelectConfigTemplate=agentSelectConfig.template - tokendb.agentViewConfigTemplate=agentViewConfig.template --tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:6,4:1,4:2,4:3,4:6,6:7 -+tokendb.allowedTransitions=0:1,0:2,0:3,0:6,3:2,3:6,4:1,4:2,4:3,4:6,6:7,1:2,7:1,7:2,6:1,6:2,3:1,3:4 - tokendb.auditAdminTemplate=auditAdmin.template - tokendb.auditLog=[PKI_INSTANCE_PATH]/logs/tokendb-audit.log - tokendb.baseDN=ou=Tokens,[TOKENDB_ROOT] --- -1.8.3.1 - - -From a336e4d5a27f4de9d39b4e8131e0da5889ad8dd4 Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Mon, 19 Aug 2019 21:26:23 -0400 -Subject: [PATCH 4/7] =?UTF-8?q?Resolve=20Bug=201585722=20-=20TMS=20-=20PKI?= - =?UTF-8?q?SocketFactory=20=E2=80=93=20Modify=20Logging=20to=20Allow=20Ext?= - =?UTF-8?q?ernal=20Use=20of=20class=20to=20work=20like=20CS8?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Submited by RHCS-maint. - -(cherry picked from commit 67b3b4fa936aa60618c2084dbbc15e8f9a13a699) ---- - .../cmscore/ldapconn/PKISocketFactory.java | 59 +++++++++++++++++----- - 1 file changed, 45 insertions(+), 14 deletions(-) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -index e9f28c9..00df65b 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -@@ -23,6 +23,8 @@ import java.net.Socket; - import java.net.UnknownHostException; - import java.util.Iterator; - import java.util.Vector; -+import java.util.logging.Level; -+import java.util.logging.Logger; - - import org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback; - import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; -@@ -48,6 +50,7 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - private String mClientAuthCertNickname; - private boolean mClientAuth; - private boolean keepAlive; -+ private static boolean external = false; - PKIClientSocketListener sockListener = null; - - public PKISocketFactory() { -@@ -65,22 +68,34 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - init(); - } - -+ public PKISocketFactory(String certNickname, boolean external) { -+ this.secure = true; -+ PKISocketFactory.external = external; -+ mClientAuthCertNickname = certNickname; -+ init(); -+ } -+ - public void init() { - try { -- IConfigStore cs = CMS.getConfigStore(); -- keepAlive = cs.getBoolean("tcp.keepAlive", true); -- CMS.debug("TCP Keep-Alive: " + keepAlive); -+ if(!external){ -+ IConfigStore cs = CMS.getConfigStore(); -+ keepAlive = cs.getBoolean("tcp.keepAlive", true); -+ } else { -+ keepAlive = true; -+ } -+ -+ log(Level.INFO, "TCP Keep-Alive: " + keepAlive, null); - sockListener = new PKIClientSocketListener(); - - } catch (Exception e) { -- CMS.debug(e); -+ log(Level.SEVERE, null, e); - throw new RuntimeException("Unable to read TCP configuration: " + e, e); - } - } - - public SSLSocket makeSSLSocket(String host, int port) throws UnknownHostException, IOException { - String method = "ldapconn/PKISocketFactory.makeSSLSocket: "; -- CMS.debug(method + "begins"); -+ log(Level.INFO, method + "begins", null); - - /* - * let inherit TLS range and cipher settings -@@ -115,8 +130,8 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - - if (mClientAuthCertNickname != null) { - mClientAuth = true; -- CMS.debug("LdapJssSSLSocket: set client auth cert nickname " + -- mClientAuthCertNickname); -+ log(Level.INFO, method + " set client auth cert nickname " + -+ mClientAuthCertNickname, null); - - //We have already established the manual cert selection callback - //Doing it this way will provide some debugging info on the candidate certs -@@ -127,6 +142,8 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - } - - public Socket makeSocket(String host, int port) throws LDAPException { -+ String method = "ldapconn/PKISocketFactory.makeSocket: "; -+ log(Level.INFO, method + "begins", null); - Socket s = null; - - try { -@@ -145,7 +162,7 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - try { - s.close(); - } catch (IOException e1) { -- CMS.debug(e1); -+ log(Level.SEVERE, null, e1); - } - } - throw new LDAPException("Unable to create socket: " + e); -@@ -165,6 +182,20 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - public void log(int level, String msg) { - } - -+ private static void log(Level level, String msg, Exception e) { -+ if(!external && e != null){ -+ CMS.debug(e); -+ } else if (!external) { -+ CMS.debug(msg); -+ } else { -+ if(e != null){ -+ Logger.getLogger("PKISocketFactory").log(level, e.getMessage()); -+ } else { -+ Logger.getLogger("PKISocketFactory").log(level, msg); -+ } -+ } -+ } -+ - static class ClientHandshakeCB implements SSLHandshakeCompletedListener { - Object sc; - -@@ -173,7 +204,7 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - } - - public void handshakeCompleted(SSLHandshakeCompletedEvent event) { -- CMS.debug("SSL handshake happened"); -+ log(Level.INFO, "SSL handshake happened", null); - } - } - -@@ -181,14 +212,14 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - String desiredCertName = null; - - public SSLClientCertificateSelectionCB(String clientAuthCertNickname) { -- CMS.debug("SSLClientCertificateSelectionCB: Setting desired cert nickname to: " + clientAuthCertNickname); -+ log(Level.INFO, "SSLClientCertificateSelectionCB: Setting desired cert nickname to: " + clientAuthCertNickname, null); - desiredCertName = clientAuthCertNickname; - } - - @Override - public String select(Vector certs) { - -- CMS.debug("SSLClientCertificatSelectionCB: Entering!"); -+ log(Level.INFO, "SSLClientCertificatSelectionCB: Entering!", null); - - if(desiredCertName == null) { - return null; -@@ -200,15 +231,15 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - - while(itr.hasNext()){ - String candidate = itr.next(); -- CMS.debug("Candidate cert: " + candidate); -+ log(Level.INFO, "Candidate cert: " + candidate, null); - if(desiredCertName.equalsIgnoreCase(candidate)) { - selection = candidate; -- CMS.debug("SSLClientCertificateSelectionCB: desired cert found in list: " + desiredCertName); -+ log(Level.INFO, "SSLClientCertificateSelectionCB: desired cert found in list: " + desiredCertName, null); - break; - } - } - -- CMS.debug("SSLClientCertificateSelectionCB: returning: " + selection); -+ log(Level.INFO, "SSLClientCertificateSelectionCB: returning: " + selection, null); - return selection; - - } --- -1.8.3.1 - - -From c92c65f52dcff03f47fc7f05efa427ee9166c2e6 Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Mon, 26 Aug 2019 18:47:02 -0400 -Subject: [PATCH 5/7] =?UTF-8?q?Resolve=20(addition=20issues=20for)=20Bug?= - =?UTF-8?q?=201642577=20-=20TPS=20=E2=80=93=20Revoked=20Encryption=20Certi?= - =?UTF-8?q?ficates=20Marked=20as=20Active=20in=20TPS=20Cert=20LDAP=20Durin?= - =?UTF-8?q?g=20Token=20Key=20Recovery?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch addresses the following: -* in TokenKeyRecoveryService.java, unwrap should be with temperatory true -* in CS.cfg, auths.instance.ldap1.ldapStringAttributes and auths.instance.ldap1.externalReg.attributes are expanded to include additional elements -* in CS.cfg registrationTypeAttributeName is added as original submitter suggested -* TPSEnrollProcessor.java, additional error checkings -* TPSProcessor.java, addresses case sensitive nature of List "contains" method - -(cherry picked from commit 24bdc1e39a5bad6b944f6f5571bf48e7e2af52f6) ---- - .../com/netscape/kra/TokenKeyRecoveryService.java | 2 +- - base/tps/shared/conf/CS.cfg | 4 ++- - .../server/tps/processor/TPSEnrollProcessor.java | 2 +- - .../server/tps/processor/TPSProcessor.java | 34 ++++++++++++++++++---- - 4 files changed, 34 insertions(+), 8 deletions(-) - -diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java -index dcccc78..e95945a 100644 ---- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java -+++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java -@@ -678,7 +678,7 @@ public class TokenKeyRecoveryService implements IService { - privKey = mStorageUnit.unwrap( - keyRecord.getPrivateKeyData(), - pubkey, -- false, -+ true, - keyRecord.getWrappingParams(mStorageUnit.getOldWrappingParams())); - } catch (Exception e) { - CMS.debug("TokenKeyRecoveryService: recoverKey() - recovery failure"); -diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg -index eb5b831..4bd4bb7 100644 ---- a/base/tps/shared/conf/CS.cfg -+++ b/base/tps/shared/conf/CS.cfg -@@ -61,10 +61,12 @@ auths.instance.ldap1.ldapStringAttributes._003=# $$ - auths.instance.ldap1.ldapStringAttributes._004=# attributes example: - auths.instance.ldap1.ldapStringAttributes._005=#mail,cn,uid,edipi,pcc,firstname,lastname,exec-edipi,exec-pcc,exec-mail,certsToAdd,tokenCUID,tokenType - auths.instance.ldap1.ldapStringAttributes._006=################################# --auths.instance.ldap1.ldapStringAttributes=mail,cn,uid -+auths.instance.ldap1.ldapStringAttributes=mail,cn,uid,enrollmenttype,certsToAdd,tokenCUID,registrationtype,tokenType,firstname,lastname,exec-edipi,exec-mail - auths.instance.ldap1.ldap.basedn=[LDAP_ROOT] -+auths.instance.ldap1.externalReg.attributes=certsToAdd,tokenCUID,enrollmenttype,registrationtype,tokenType - auths.instance.ldap1.externalReg.certs.recoverAttributeName=certsToAdd - auths.instance.ldap1.externalReg.cuidAttributeName=tokenCUID -+auths.instance.ldap1.externalReg.registrationTypeAttributeName=registrationtype - auths.instance.ldap1.externalReg.tokenTypeAttributeName=tokenType - auths.instance.ldap1.ldap.maxConns=15 - auths.instance.ldap1.ldap.minConns=3 -diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java -index 77b320c..f1e773a 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java -+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java -@@ -200,7 +200,7 @@ public class TPSEnrollProcessor extends TPSProcessor { - // Check if the external reg parameter registrationType matches currentTokenOperation, - // otherwise stop the operation. - CMS.debug(method + " checking if record registrationtype matches currentTokenOperation."); -- if(erAttrs.getRegistrationType() != null) { -+ if(erAttrs.getRegistrationType() != null && erAttrs.getRegistrationType().length() > 0) { - if(!erAttrs.getRegistrationType().equalsIgnoreCase(currentTokenOperation)) { - CMS.debug( - method + " Error: registrationType " + -diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -index ec069b1..61da1d6 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -@@ -1294,12 +1294,12 @@ public class TPSProcessor { - throws EBaseException, TPSException { - - String logMsg = null; -- CMS.debug("TPSProcessor.authenticateUser"); - if (op.isEmpty() || userAuth == null || userCred == null) { - logMsg = "TPSProcessor.authenticateUser: missing parameter(s): op, userAuth, or userCred"; - CMS.debug(logMsg); - throw new EBaseException(logMsg); - } -+ CMS.debug("TPSProcessor.authenticateUser: op: " + op); - IAuthManager auth = userAuth.getAuthManager(); - - try { -@@ -1311,6 +1311,12 @@ public class TPSProcessor { - while (n.hasMoreElements()) { - String name = n.nextElement(); - CMS.debug("TPSProcessor.authenticateUser: got authToken val name:" + name); -+ /* debugging authToken content vals -+ String[] vals = authToken.getInStringArray(name); -+ if (vals != null) { -+ CMS.debug("TPSProcessor.authenticateUser: got authToken val :" + vals[0]); -+ } -+ */ - } - return authToken; - } else { -@@ -1811,6 +1817,21 @@ public class TPSProcessor { - return ret; - } - -+ /* -+ * listCaseInsensitiveContains - case insensitive contain check -+ * @param s the string checked if contained in list -+ * @param list the list -+ * @returns true if list contains s; false otherwise -+ */ -+ public boolean listCaseInsensitiveContains(String s, List list){ -+ for (String element : list){ -+ if (element.equalsIgnoreCase(s)){ -+ return true; -+ } -+ } -+ return false; -+ } -+ - /* - * processExternalRegAttrs : - * - retrieve from authToken relevant attributes for externalReg -@@ -1836,7 +1857,7 @@ public class TPSProcessor { - if(attributesToProcess == null) - return erAttrs; - -- if(attributesToProcess.contains(erAttrs.ldapAttrNameTokenType)) { -+ if(listCaseInsensitiveContains(erAttrs.ldapAttrNameTokenType, attributesToProcess)) { - CMS.debug(method + ": getting from authToken:" - + erAttrs.ldapAttrNameTokenType); - vals = authToken.getInStringArray(erAttrs.ldapAttrNameTokenType); -@@ -1852,17 +1873,20 @@ public class TPSProcessor { - erAttrs.setTokenType(vals[0]); - } - } -- if(attributesToProcess.contains(erAttrs.ldapAttrNameTokenCUID)) { -+ if(listCaseInsensitiveContains(erAttrs.ldapAttrNameTokenCUID, attributesToProcess)) { - CMS.debug(method + ": getting from authToken:" - + erAttrs.ldapAttrNameTokenCUID); - vals = authToken.getInStringArray(erAttrs.ldapAttrNameTokenCUID); - if (vals != null) { - CMS.debug(method + ": retrieved cuid:" + vals[0]); - erAttrs.setTokenCUID(vals[0]); -+ } else { -+ CMS.debug(method + ": " + erAttrs.ldapAttrNameTokenCUID + -+ " attribute not found"); - } - } - -- if(attributesToProcess.contains(erAttrs.ldapAttrNameRegistrationType)) { -+ if(listCaseInsensitiveContains(erAttrs.ldapAttrNameRegistrationType, attributesToProcess)) { - CMS.debug(method + ": getting from authToken:" - + erAttrs.ldapAttrNameRegistrationType); - vals = authToken.getInStringArray(erAttrs.ldapAttrNameRegistrationType); -@@ -1876,7 +1900,7 @@ public class TPSProcessor { - - } - -- if(attributesToProcess.contains(erAttrs.ldapAttrNameCertsToRecover)) { -+ if(listCaseInsensitiveContains(erAttrs.ldapAttrNameCertsToRecover, attributesToProcess)) { - /* - * certs to be recovered for this user - * - multi-valued --- -1.8.3.1 - - -From 74c7c1133fd8d2f216eb1330147e870632ded68f Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Wed, 28 Aug 2019 18:11:36 -0400 -Subject: [PATCH 6/7] simple typo fix in a debug line. - -(cherry picked from commit 272b785d20bc807406bc1e89a52c0fc142e25e72) ---- - base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -index 61da1d6..baf0671 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java -@@ -4172,7 +4172,7 @@ public class TPSProcessor { - - keyInfo = tokenRecord.getKeyInfo(); - -- CMS.debug("TPProcessor.getKeyInfioFromTokenDB: returning: " + keyInfo); -+ CMS.debug("TPProcessor.getKeyInfoFromTokenDB: returning: " + keyInfo); - - return keyInfo; - --- -1.8.3.1 - - -From ce90aeab54f0a33d1c59bd5a95852ea2c62541e9 Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Fri, 6 Sep 2019 16:49:00 -0400 -Subject: [PATCH 7/7] Bug 1523330 - CC: missing audit event for CS acting as - TLS client - -This patch adds failed CLIENT_ACCESS_SESSION_ESTABLISH audit event for the case -when internal ldap server goes down - -fixes https://bugzilla.redhat.com/show_bug.cgi?id=1523330 - -(cherry picked from commit 10d52dd0d6b562edc9e32c543017c67c1c0212a8) ---- - .../netscape/cmscore/ldapconn/PKISocketFactory.java | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -index 00df65b..dc93f5d 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/PKISocketFactory.java -@@ -33,6 +33,9 @@ import org.mozilla.jss.ssl.SSLSocket; - - import com.netscape.certsrv.apps.CMS; - import com.netscape.certsrv.base.IConfigStore; -+import com.netscape.certsrv.logging.event.ClientAccessSessionEstablishEvent; -+import com.netscape.certsrv.logging.SignedAuditEvent; -+import com.netscape.cms.logging.SignedAuditLogger; - - import netscape.ldap.LDAPException; - import netscape.ldap.LDAPSSLSocketFactoryExt; -@@ -46,6 +49,8 @@ import org.dogtagpki.server.PKIClientSocketListener; - */ - public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - -+ private static SignedAuditLogger signedAuditLogger = SignedAuditLogger.getLogger(); -+ - private boolean secure; - private String mClientAuthCertNickname; - private boolean mClientAuth; -@@ -157,6 +162,22 @@ public class PKISocketFactory implements LDAPSSLSocketFactoryExt { - s.setKeepAlive(keepAlive); - - } catch (Exception e) { -+ // for auditing -+ String localIP = "localhost"; -+ try { -+ localIP = InetAddress.getLocalHost().getHostAddress(); -+ } catch (UnknownHostException e2) { -+ // default to "localhost"; -+ } -+ SignedAuditEvent auditEvent; -+ auditEvent = ClientAccessSessionEstablishEvent.createFailureEvent( -+ localIP, -+ host, -+ Integer.toString(port), -+ "SYSTEM", -+ "connect:" +e.toString()); -+ signedAuditLogger.log(auditEvent); -+ - CMS.debug(e); - if (s != null) { - try { --- -1.8.3.1 - diff --git a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-beta.patch b/SOURCES/pki-core-rhel-7-8-rhcs-9-6-beta.patch deleted file mode 100644 index 091a1d9..0000000 --- a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-beta.patch +++ /dev/null @@ -1,1642 +0,0 @@ -From 696422ef74f9e143684d6a79769217a32811ec16 Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Mon, 9 Sep 2019 20:36:26 -0400 -Subject: [PATCH 01/14] Bug 1638891 - TPS - (addl fix) Add External - Registration Support to PIN Reset - -This small patch fixes a critical typo (during patch merge) that causes KeySet - to be accidentally written to token Type instead. - -(cherry picked from commit 78c86e6cf33e85a23e666e06708441ac58b46a75) ---- - .../src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java -index a8589fe..de5c634 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java -+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java -@@ -209,7 +209,7 @@ public class TPSPinResetProcessor extends TPSProcessor { - BaseMappingResolver resolverInst = - subsystem.getMappingResolverManager().getResolverInstance(resolverInstName); - String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet"); -- setSelectedTokenType(keySet); -+ setSelectedKeySet(keySet); - CMS.debug(method + " resolved keySet: " + keySet); - } - } catch (TPSException e) { --- -1.8.3.1 - - -From eee11e26487e7993d4923df4c30d72b667a14a2b Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Tue, 10 Sep 2019 15:50:38 -0500 -Subject: [PATCH 02/14] Fixed TPSTokendb.tdbFindTokenRecordsByUID() - -The TPSTokendb.tdbFindTokenRecordsByUID() has been modified such -that it uses (tokenUserID=) filter to find tokens with exact -owner UID instead of filter with wildcards. - -https://bugzilla.redhat.com/show_bug.cgi?id=1520258 -(cherry picked from commit e8c81c59f03a3db5886924e4e7ec272bc864d953) ---- - .../src/com/netscape/cmscore/dbs/LDAPDatabase.java | 23 +++++++++++++++++++--- - .../src/org/dogtagpki/server/tps/TPSTokendb.java | 22 ++++++++++++--------- - .../dogtagpki/server/tps/dbs/TokenDatabase.java | 1 + - 3 files changed, 34 insertions(+), 12 deletions(-) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java -index 8773423..8e7f1f3 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/LDAPDatabase.java -@@ -108,12 +108,22 @@ public abstract class LDAPDatabase extends Database { - // if no attributes specified, don't change filter - if (attributes == null || attributes.isEmpty()) return; - -- // wrap current filter with attribute matching filter -- sb.insert(0, "(&"); -+ // count filter components -+ int components = 0; -+ if (sb.length() > 0) components++; // count original filter -+ components += attributes.size(); // count attribute filters -+ -+ // concatenate the original filter and attribute filters: -+ // (=)...(=) - for (Map.Entry entry : attributes.entrySet()) { - sb.append("(" + entry.getKey() + "=" + LDAPUtil.escapeFilter(entry.getValue()) + ")"); - } -- sb.append(")"); -+ -+ // if there are multiple filter components, join with AND operator -+ if (components > 1) { -+ sb.insert(0, "(&"); -+ sb.append(")"); -+ } - } - - @Override -@@ -121,13 +131,20 @@ public abstract class LDAPDatabase extends Database { - return findRecords(keyword, null); - } - -+ /** -+ * Search for LDAP records with the specified keyword and attributes. -+ * The keyword parameter will be used to search with wildcards on certain attributes. -+ * The attributes parameter will be used to find exact matches of the specified attributes. -+ */ - public Collection findRecords(String keyword, Map attributes) throws Exception { - - CMS.debug("LDAPDatabase: findRecords()"); - - try (IDBSSession session = dbSubsystem.createSession()) { - Collection list = new ArrayList(); -+ - String ldapFilter = createFilter(keyword, attributes); -+ - CMS.debug("LDAPDatabase: searching " + baseDN + " with filter " + ldapFilter); - IDBSearchResults results = session.search(baseDN, ldapFilter); - -diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -index 80c9bb1..da0b51d 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -@@ -23,6 +23,7 @@ import java.util.Collection; - import java.util.Date; - import java.util.HashMap; - import java.util.Iterator; -+import java.util.LinkedHashMap; - import java.util.Map; - - import org.dogtagpki.server.tps.cms.CARemoteRequestHandler; -@@ -141,17 +142,20 @@ public class TPSTokendb { - */ - public ArrayList tdbFindTokenRecordsByUID(String uid) - throws Exception { -- ArrayList tokenRecords = new ArrayList(); -- String filter = uid; -- Iterator records = null; -- records = tps.tokenDatabase.findRecords(filter).iterator(); - -- while (records.hasNext()) { -- TokenRecord tokenRecord = records.next(); -- tokenRecords.add(tokenRecord); -- } -+ // search for tokens with (tokenUserID=) -+ Map attributes = new LinkedHashMap<>(); -+ attributes.put("tokenUserID", uid); -+ -+ Iterator records = tps.tokenDatabase.findRecords(null, attributes).iterator(); -+ -+ ArrayList tokenRecords = new ArrayList(); -+ while (records.hasNext()) { -+ TokenRecord tokenRecord = records.next(); -+ tokenRecords.add(tokenRecord); -+ } - -- return tokenRecords; -+ return tokenRecords; - } - - public void tdbHasActiveToken(String userid) -diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java -index 9235e78..b349cb2 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java -+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java -@@ -60,6 +60,7 @@ public class TokenDatabase extends LDAPDatabase { - StringBuilder sb = new StringBuilder(); - - if (keyword != null) { -+ // if keyword is specified, generate filter with wildcards - keyword = LDAPUtil.escapeFilter(keyword); - sb.append("(|(id=*" + keyword + "*)(userID=*" + keyword + "*))"); - } --- -1.8.3.1 - - -From 3cc98ae77dff2351c1ea6af0086d4d0daeb28497 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Fri, 13 Sep 2019 17:31:21 -0500 -Subject: [PATCH 03/14] Fixed TPSTokendb.tdbFindTokenRecordsByUID() (part 2) - -The TPSTokendb.tdbFindTokenRecordsByUID() has been modified to -construct (userID=) filter which will be translated into -(tokenUserID=) LDAP filter as defined in TokenRecord. - -https://bugzilla.redhat.com/show_bug.cgi?id=1520258 -(cherry picked from commit def3453308c68493f7417e485a1db14419187af0) ---- - base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -index da0b51d..49bfb7f 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java -@@ -143,9 +143,11 @@ public class TPSTokendb { - public ArrayList tdbFindTokenRecordsByUID(String uid) - throws Exception { - -- // search for tokens with (tokenUserID=) -+ // search for tokens with (userID=) filter which will be -+ // translated into (tokenUserID=) LDAP filter as defined -+ // in TokenRecord - Map attributes = new LinkedHashMap<>(); -- attributes.put("tokenUserID", uid); -+ attributes.put("userID", uid); - - Iterator records = tps.tokenDatabase.findRecords(null, attributes).iterator(); - --- -1.8.3.1 - - -From 53766e02131741dc0cb6434755b3ba488f0bd927 Mon Sep 17 00:00:00 2001 -From: Dinesh Prasanth M K -Date: Wed, 18 Sep 2019 15:36:51 -0400 -Subject: [PATCH 04/14] Update KRATool to support netkeyKeyRecovery entries - (#248) - -The `netkeyKeyRecovery` request entries are generated when -the TPS retrieves encryption cert onto tokens. - -The attributes processed by KRATool include: -* requestId -* dn -* dateOfModify -* cn -* extdata-requestid -* extdata-request-notes (creates, if it doesn't exist) - -Resolves: BZ#1445479 - -Signed-off-by: Dinesh Prasanth M K - -(cherry picked from commit b02bc04fe16c59aec28d90323e7c9e31dbd7261f) ---- - base/java-tools/man/man1/KRATool.1 | 44 +- - .../src/com/netscape/cmstools/KRATool.cfg | 21 + - .../src/com/netscape/cmstools/KRATool.java | 460 ++++++++++++++++++++- - 3 files changed, 506 insertions(+), 19 deletions(-) - -diff --git a/base/java-tools/man/man1/KRATool.1 b/base/java-tools/man/man1/KRATool.1 -index b04cd2b..1e2fe99 100644 ---- a/base/java-tools/man/man1/KRATool.1 -+++ b/base/java-tools/man/man1/KRATool.1 -@@ -1,7 +1,7 @@ - .\" First parameter, NAME, should be all caps - .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection - .\" other parameters are allowed: see man(7), man(1) --.TH KRATool 1 "July 18, 2016" "version 10.3" "PKI Key Recovery Authority (KRA) Tool" Dogtag Team -+.TH KRATool 1 "Sep 11, 2019" "version 10.5" "PKI Key Recovery Authority (KRA) Tool" Dogtag Team - .\" Please adjust this date whenever revising the man page. - .\" - .\" Some roff macros, for reference: -@@ -33,6 +33,8 @@ The syntax for rewrapping keys: - [-source_pki_security_database_pwdfile ]] - [-source_kra_naming_context -target_kra_naming_context ] - [-process_requests_and_key_records_only] -+ [-unwrap_algorithm AES|DES3] -+ - .fi - .PP - The syntax for renumbering keys: -@@ -130,6 +132,12 @@ Gives the path and filename to a password file that contains only the password f - - This argument is optional when other rewrap parameters are used. If this argument is not used, then the script prompts for the password. - -+.TP -+.B -unwrap_algorithm -+Specifies the symmetric key algorithm used by source KRA. Available options include \fBDES3\fP and \fBAES\fP -+ -+This argument is optional and defaults to \fBDES3\fP if unspecified. -+ - .PP - The following parameters are optional for renumbering keys: - -@@ -147,13 +155,14 @@ If \fB-remove_id_offset\fP is used, then do not use the \fB-append_id_offset\fP - - .SH Configuration File (.cfg) - .PP --The required configuration file instructs the KRATool how to process attributes in the key archival and key request entries in the LDIF file. There are six types of entries: -+The required configuration file instructs the KRATool how to process attributes in the key archival and key request entries in the LDIF file. There are seven types of entries: - .IP - * CA enrollment requests - * TPS enrollment requests - * CA key records - * TPS key records - * CA and TPS recovery requests (which are treated the same in the KRA) -+* TPS token key recovery requests - .PP - Each key and key request has an LDAP entry with attributes that are specific to that kind of record. For example, for a recovery request: - .IP -@@ -198,7 +207,7 @@ nsUniqueId: b2891805-1dd111b2-a6d7e85f-2c2f0000 - .PP - Much of that information passes through the script processing unchanged, so it is entered into the new, target KRA just the same. However, some of those attributes can and should be edited, like the Common Name (CN) and DN being changed to match the new KRA instance. The fields which can safely be changed are listed in the configuration file for each type of key entry. (Any attribute not listed is not touched by the tool under any circumstances.) - .PP --If a field /fIshould/fP be edited — meaning, the tool can update the record ID number or rename the entry — then the value is set to true in the configuration file. For example, this configuration updates the CN, DN, ID number, last modified date, and associated entry notes for all CA enrollment requests: -+If a field \fIshould\fP be edited — meaning, the tool can update the record ID number or rename the entry — then the value is set to true in the configuration file. For example, this configuration updates the CN, DN, ID number, last modified date, and associated entry notes for all CA enrollment requests: - .IP - .nf - kratool.ldif.caEnrollmentRequest.cn=true -@@ -324,9 +333,9 @@ kratool.ldif.namingContext._037=## uid ## - kratool.ldif.namingContext._038=## uniqueMember ## - kratool.ldif.namingContext._039=## ## - kratool.ldif.namingContext._040=## If '-source_naming_context ## --kratool.ldif.namingContext._041=## original source KRA naming context' ## -+kratool.ldif.namingContext._041=## ' ## - kratool.ldif.namingContext._042=## and '-target_naming_context ## --kratool.ldif.namingContext._043=## renamed target KRA naming context' ## -+kratool.ldif.namingContext._043=## ' ## - kratool.ldif.namingContext._044=## options are specified, ALWAYS ## - kratool.ldif.namingContext._045=## require 'KRATOOL' to change the ## - kratool.ldif.namingContext._046=## KRA 'naming context' data in ALL of ## -@@ -355,6 +364,10 @@ kratool.ldif.namingContext._068=## tpsNetkeyKeygenRequest: ## - kratool.ldif.namingContext._069=## ## - kratool.ldif.namingContext._070=## dn ## - kratool.ldif.namingContext._071=## ## -+kratool.ldif.namingContext._072=## tpsNetkeyKeyRecoveryRequest: ## -+kratool.ldif.namingContext._073=## ## -+kratool.ldif.namingContext._074=## dn ## -+kratool.ldif.namingContext._075=## ## - kratool.ldif.namingContext._072=############################################ - kratool.ldif.recoveryRequest._000=##################################### - kratool.ldif.recoveryRequest._001=## KRA CA / TPS Recovery Request ## -@@ -401,6 +414,23 @@ kratool.ldif.tpsNetkeyKeygenRequest.extdata.keyRecord=true - kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestId=true - kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestNotes=true - kratool.ldif.tpsNetkeyKeygenRequest.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._000=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._001=## KRA TPS Netkey Keyrecovery Request ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._002=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._003=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._004=## NEVER allow 'KRATOOL' the ability ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._005=## to change the TPS 'naming context'## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._006=## data in the following fields: ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._007=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._008=## extdata-updatedby ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._009=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._010=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.cn=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dn=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dateOfModify=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestNotes=true - .if - - .SH EXAMPLES -@@ -448,10 +478,10 @@ KRATool -kratool_config_file "/usr/share/pki/java-tools/KRATool.cfg" -source_ldi - .if - - .SH AUTHORS --Matthew Harmsen . -+Matthew Harmsen and Dinesh Prasanth M K - - .SH COPYRIGHT --Copyright (c) 2016 Red Hat, Inc. This is licensed under the GNU General Public -+Copyright (c) 2019 Red Hat, Inc. This is licensed under the GNU General Public - License, version 2 (GPLv2). A copy of this license is available at - http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - -diff --git a/base/java-tools/src/com/netscape/cmstools/KRATool.cfg b/base/java-tools/src/com/netscape/cmstools/KRATool.cfg -index cad2bf4..b2a4892 100644 ---- a/base/java-tools/src/com/netscape/cmstools/KRATool.cfg -+++ b/base/java-tools/src/com/netscape/cmstools/KRATool.cfg -@@ -111,6 +111,10 @@ kratool.ldif.namingContext._068=## tpsNetkeyKeygenRequest: ## - kratool.ldif.namingContext._069=## ## - kratool.ldif.namingContext._070=## dn ## - kratool.ldif.namingContext._071=## ## -+kratool.ldif.namingContext._072=## tpsNetkeyKeyRecoveryRequest: ## -+kratool.ldif.namingContext._073=## ## -+kratool.ldif.namingContext._074=## dn ## -+kratool.ldif.namingContext._075=## ## - kratool.ldif.namingContext._072=############################################ - kratool.ldif.recoveryRequest._000=##################################### - kratool.ldif.recoveryRequest._001=## KRA CA / TPS Recovery Request ## -@@ -157,4 +161,21 @@ kratool.ldif.tpsNetkeyKeygenRequest.extdata.keyRecord=true - kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestId=true - kratool.ldif.tpsNetkeyKeygenRequest.extdata.requestNotes=true - kratool.ldif.tpsNetkeyKeygenRequest.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._000=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._001=## KRA TPS Netkey Keyrecovery Request ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._002=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._003=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._004=## NEVER allow 'KRATOOL' the ability ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._005=## to change the TPS 'naming context'## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._006=## data in the following fields: ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._007=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._008=## extdata-updatedby ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._009=## ## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest._010=######################################## -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.cn=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dn=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.dateOfModify=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestId=true -+kratool.ldif.tpsNetkeyKeyRecoveryRequest.extdata.requestNotes=true - -diff --git a/base/java-tools/src/com/netscape/cmstools/KRATool.java b/base/java-tools/src/com/netscape/cmstools/KRATool.java -index 74e5a6a..e4b9ae8 100644 ---- a/base/java-tools/src/com/netscape/cmstools/KRATool.java -+++ b/base/java-tools/src/com/netscape/cmstools/KRATool.java -@@ -699,6 +699,7 @@ public class KRATool { - private static final String KRATOOL_CFG_RECOVERY = "recoveryRequest"; - private static final String KRATOOL_CFG_TPS_KEY_RECORD = "tpsKeyRecord"; - private static final String KRATOOL_CFG_KEYGEN = "tpsNetkeyKeygenRequest"; -+ private static final String KRATOOL_CFG_KEYRECOVERY = "tpsNetkeyKeyRecoveryRequest"; - - // Constants: KRATOOL Config File (KRA CA Enrollment Request Fields) - private static final String KRATOOL_CFG_ENROLLMENT_CN = KRATOOL_CFG_PREFIX -@@ -860,6 +861,42 @@ public class KRATool { - + DOT - + "requestId"; - -+ private static final String KRATOOL_CFG_KEYRECOVERY_REQUEST_ID = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "requestId"; -+ -+ private static final String KRATOOL_CFG_KEYRECOVERY_DN = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "dn"; -+ -+ private static final String KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "dateOfModify"; -+ -+ private static final String KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "extdata.requestId"; -+ -+ private static final String KRATOOL_CFG_KEYRECOVERY_CN = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "cn"; -+ -+ private static final String KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES = KRATOOL_CFG_PREFIX -+ + DOT -+ + KRATOOL_CFG_KEYRECOVERY -+ + DOT -+ + "extdata.requestNotes"; -+ - // Constants: Target Certificate Information - private static final String HEADER = "-----BEGIN"; - private static final String TRAILER = "-----END"; -@@ -892,6 +929,7 @@ public class KRATool { - private static final String KRA_LDIF_KEYGEN = "netkeyKeygen"; - private static final String KRA_LDIF_RECOVERY = "recovery"; - private static final String KRA_LDIF_TPS_KEY_RECORD = "TPS"; -+ private static final String KRA_LDIF_KEYRECOVERY = "netkeyKeyRecovery"; - - // Constants: KRA LDIF Record Messages - private static final String KRA_LDIF_REWRAP_MESSAGE = "REWRAPPED the '" -@@ -2334,6 +2372,15 @@ public class KRATool { - } else { - output = line; - } -+ } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if( kratoolCfg.get(KRATOOL_CFG_KEYRECOVERY_CN ) ) { -+ output = compose_numeric_line(KRA_LDIF_CN, -+ SPACE, -+ line, -+ false ); -+ } else { -+ output = line; -+ } - } else if (record_type.equals(KRA_LDIF_RECORD)) { - // Non-Request / Non-Key Record: - // Pass through the original -@@ -2439,6 +2486,21 @@ public class KRATool { - } else { - output = line; - } -+ } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY ) ) { -+ output = KRA_LDIF_DATE_OF_MODIFY -+ + SPACE -+ + mDateOfModify; -+ -+ log( "Changed '" -+ + line -+ + "' to '" -+ + output -+ + "'." -+ + NEWLINE, false ); -+ } else { -+ output = line; -+ } - } else { - log("ERROR: Mismatched record field='" - + KRA_LDIF_DATE_OF_MODIFY -@@ -2657,6 +2719,44 @@ public class KRATool { - } else { - output = line; - } -+ } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_DN ) ) { -+ // First check for an embedded "cn=" -+ // name-value pair -+ if( line.startsWith( KRA_LDIF_DN_EMBEDDED_CN_DATA ) ) { -+ // At this point, always extract -+ // the embedded "cn=" name-value pair -+ // which will ALWAYS be the first -+ // portion of the "dn: " attribute -+ embedded_cn_data = line.split( COMMA, 2 ); -+ -+ embedded_cn_output = compose_numeric_line( -+ KRA_LDIF_DN_EMBEDDED_CN_DATA, -+ EQUAL_SIGN, -+ embedded_cn_data[0], -+ false ); -+ -+ input = embedded_cn_output -+ + COMMA -+ + embedded_cn_data[1]; -+ } else { -+ input = line; -+ } -+ -+ // Since "-source_kra_naming_context", and -+ // "-target_kra_naming_context" are OPTIONAL -+ // parameters, ONLY process this portion of the field -+ // if both of these options have been selected -+ if( mKraNamingContextsFlag ) { -+ output = input.replace( mSourceKraNamingContext, -+ mTargetKraNamingContext ); -+ } else { -+ output = input; -+ } -+ -+ } else { -+ output = line; -+ } - } else if (record_type.equals(KRA_LDIF_RECORD)) { - // Non-Request / Non-Key Record: - // Pass through the original -@@ -2771,6 +2871,15 @@ public class KRATool { - } else { - output = line; - } -+ } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if( kratoolCfg.get(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID ) ) { -+ output = compose_numeric_line(KRA_LDIF_EXTDATA_REQUEST_ID, -+ SPACE, -+ line, -+ false ); -+ } else { -+ output = line; -+ } - } else { - log("ERROR: Mismatched record field='" - + KRA_LDIF_EXTDATA_REQUEST_ID -@@ -3307,6 +3416,167 @@ public class KRATool { - } else { - output = line; - } -+ } else if (record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES ) ) { -+ // write out a revised 'extdata-requestnotes' line -+ if( mRewrapFlag && mAppendIdOffsetFlag ) { -+ data = input -+ + SPACE -+ + LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + SPACE -+ + PLUS + SPACE -+ + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mAppendIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRewrapFlag && mRemoveIdOffsetFlag ) { -+ data = input -+ + SPACE -+ + LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + SPACE -+ + PLUS + SPACE -+ + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mRemoveIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRewrapFlag ) { -+ data = input -+ + SPACE -+ + LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mAppendIdOffsetFlag ) { -+ data = input -+ + SPACE -+ + LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mAppendIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRemoveIdOffsetFlag ) { -+ data = input -+ + SPACE -+ + LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mRemoveIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } -+ -+ // log this information -+ log( "Changed:" -+ + NEWLINE -+ + TIC -+ + KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ input.toString() ) -+ + TIC -+ + NEWLINE -+ + "--->" -+ + NEWLINE -+ + TIC -+ + output -+ + TIC -+ + NEWLINE, false ); -+ } else { -+ output = line; -+ } - } else { - log("ERROR: Mismatched record field='" - + KRA_LDIF_EXTDATA_REQUEST_NOTES -@@ -3634,6 +3904,153 @@ public class KRATool { - System.out.print("."); - } - } -+ } else if (record_type.equals(KRA_LDIF_KEYRECOVERY)) { -+ if( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES ) ) { -+ if(!previous_line.startsWith( KRA_LDIF_EXTDATA_REQUEST_NOTES)) { -+ // write out the missing 'extdata-requestnotes' line -+ if( mRewrapFlag && mAppendIdOffsetFlag ) { -+ data = LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + SPACE -+ + PLUS + SPACE -+ + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mAppendIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRewrapFlag && mRemoveIdOffsetFlag ) { -+ data = LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + SPACE -+ + PLUS + SPACE -+ + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mRemoveIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRewrapFlag ) { -+ data = LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REWRAP_MESSAGE -+ + mPublicKeySize -+ + KRA_LDIF_RSA_MESSAGE -+ + mSourcePKISecurityDatabasePwdfileMessage -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mAppendIdOffsetFlag ) { -+ data = LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_APPENDED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mAppendIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } else if( mRemoveIdOffsetFlag ) { -+ data = LEFT_BRACE -+ + mDateOfModify -+ + RIGHT_BRACE -+ + COLON + SPACE -+ + KRA_LDIF_REMOVED_ID_OFFSET_MESSAGE -+ + SPACE -+ + TIC -+ + mRemoveIdOffset.toString() -+ + TIC -+ + mKraNamingContextMessage -+ + mProcessRequestsAndKeyRecordsOnlyMessage; -+ -+ // Unformat the data -+ unformatted_data = stripEOL( data ); -+ -+ // Format the unformatted_data -+ // to match the desired LDIF format -+ output = KRA_LDIF_EXTDATA_REQUEST_NOTES -+ + SPACE -+ + format_ldif_data( -+ EXTDATA_REQUEST_NOTES_FIRST_LINE_DATA_LENGTH, -+ unformatted_data ); -+ } -+ -+ // log this information -+ log( "Created:" -+ + NEWLINE -+ + TIC -+ + output -+ + TIC -+ + NEWLINE, false ); -+ -+ // Write out this revised line -+ // and flush the buffer -+ writer.write( output + NEWLINE ); -+ writer.flush(); -+ System.out.print( "." ); -+ } -+ } - } - } - -@@ -3897,6 +4314,15 @@ public class KRATool { - } else { - output = line; - } -+ } else if ( record_type.equals( KRA_LDIF_KEYRECOVERY ) ) { -+ if ( kratoolCfg.get( KRATOOL_CFG_KEYRECOVERY_REQUEST_ID ) ) { -+ output = compose_numeric_line(KRA_LDIF_REQUEST_ID, -+ SPACE, -+ line, -+ true); -+ } else { -+ output = line; -+ } - } else { - log("ERROR: Mismatched record field='" - + KRA_LDIF_REQUEST_ID -@@ -4115,7 +4541,8 @@ public class KRATool { - ).trim(); - if (!record_type.equals(KRA_LDIF_ENROLLMENT) && - !record_type.equals(KRA_LDIF_KEYGEN) && -- !record_type.equals(KRA_LDIF_RECOVERY)) { -+ !record_type.equals(KRA_LDIF_RECOVERY) && -+ !record_type.equals( KRA_LDIF_KEYRECOVERY)) { - log("ERROR: Unknown LDIF record type='" - + record_type - + "'!" -@@ -4398,7 +4825,13 @@ public class KRATool { - || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_KEY_RECORD) - || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_REQUEST_ID) - || name.equals(KRATOOL_CFG_KEYGEN_EXTDATA_REQUEST_NOTES) -- || name.equals(KRATOOL_CFG_KEYGEN_REQUEST_ID)) { -+ || name.equals(KRATOOL_CFG_KEYGEN_REQUEST_ID) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_REQUEST_ID ) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_DN ) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_DATE_OF_MODIFY) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_ID) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_CN) -+ || name.equals(KRATOOL_CFG_KEYRECOVERY_EXTDATA_REQUEST_NOTES) ) { - kratoolCfg.put(name, value); - System.out.print("."); - } -@@ -4496,6 +4929,7 @@ public class KRATool { - (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 5)) && - (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 6)) && - (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 7)) && -+ (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 8)) && - (args.length != (REWRAP_AND_ID_OFFSET_ARGS + 9))) { - System.err.println("ERROR: Incorrect number of arguments!" - + NEWLINE); -@@ -4892,16 +5326,18 @@ public class KRATool { - } - - // Check for the Key Unwrap Algorithm provided by user. -- // If unprovided, choose DES3 as the default (to maintain consistency with old code) -- if (keyUnwrapAlgorithmName.equalsIgnoreCase("DES3")) { -- keyUnwrapAlgorithm = SymmetricKey.DES3; -- } else if (keyUnwrapAlgorithmName.equalsIgnoreCase("AES")) { -- keyUnwrapAlgorithm = SymmetricKey.AES; -- } else { -- System.err.println("ERROR: Unsupported key unwrap algorithm '" -- + keyUnwrapAlgorithmName + "'" -- + NEWLINE); -- System.exit(1); -+ // If unprovided, DES3 is chosen as the default (to maintain consistency with old code) -+ if (keyUnwrapAlgorithmName != null) { -+ if (keyUnwrapAlgorithmName.equalsIgnoreCase("DES3")) { -+ keyUnwrapAlgorithm = SymmetricKey.DES3; -+ } else if (keyUnwrapAlgorithmName.equalsIgnoreCase("AES")) { -+ keyUnwrapAlgorithm = SymmetricKey.AES; -+ } else { -+ System.err.println("ERROR: Unsupported key unwrap algorithm '" -+ + keyUnwrapAlgorithmName + "'" -+ + NEWLINE); -+ System.exit(1); -+ } - } - - // Check for OPTIONAL "Process Requests and Key Records ONLY" option --- -1.8.3.1 - - -From b8f619e12ac90aab1ad845bffbdefffcb1e9229d Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 19 Sep 2019 15:41:40 +1000 -Subject: [PATCH 05/14] SecurityDataProcess.archive: log decryption failure - -(cherry picked from commit df26b7e86b3341c2cc7c0d5d9c3d9f680496a071) ---- - base/kra/src/com/netscape/kra/SecurityDataProcessor.java | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java -index 5a64530..05e73ce 100644 ---- a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java -+++ b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java -@@ -208,6 +208,8 @@ public class SecurityDataProcessor { - KeyRequestService.SYMKEY_TYPES.get(algorithm), - strength); - } catch (Exception e) { -+ CMS.debug("Can't decrypt symmetric key:"); -+ CMS.debug(e); - throw new EBaseException("Can't decrypt symmetric key.", e); - } - } -@@ -222,6 +224,8 @@ public class SecurityDataProcessor { - secdata, - null); - } catch (Exception e) { -+ CMS.debug("Can't decrypt passphrase."); -+ CMS.debug(e); - throw new EBaseException("Can't decrypt passphrase.", e); - } - --- -1.8.3.1 - - -From 38a8d9d7fb4e18027c763a553c5ab20cfe709a76 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 19 Sep 2019 17:17:24 +1000 -Subject: [PATCH 06/14] CryptoUtil: include OID in NoSuchAlgorithmException - -(cherry picked from commit c08b0cdbf069033d7ddc4e769890bf6281200659) ---- - base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -index 083b9f2..e9bc0dd 100644 ---- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -@@ -3114,7 +3114,7 @@ public class CryptoUtil { - if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID)) - return KeyWrapAlgorithm.DES3_CBC_PAD; - -- throw new NoSuchAlgorithmException(); -+ throw new NoSuchAlgorithmException(wrapOID); - } - - } --- -1.8.3.1 - - -From 4ade0812dac8bebb81500ea74641f3bf79548f42 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 19 Sep 2019 20:54:17 +1000 -Subject: [PATCH 07/14] CryptoUtil.getKeywrapAlgorithmFromOID: Fix DES-EDE3-CBC - selection - -Commit dbd2d9b587f46b8af2f78b73d62715c1fd3344fc contained the edit: - -- if (oid.equals(KW_DES_CBC_PAD)) -+ if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID)) - -KW_DES_CBC_PAD was 1.2.840.113549.3.7 (DES-EDE3-CBC; this definition -was removed in the same commit). But -KeyWrapAlgorithm.DES_CBC_PAD_OID is 1.3.14.3.2.7. This is a -behaviour change that breaks KRA archival (possibly recovery too). - -Test equality to KeyWrapAlgorithm.DES3_CBC_PAD_OID to restore the -correct behaviour. Also fix a similar error in WrappingParams.java. - -Related: https://bugzilla.redhat.com/show_bug.cgi?id=1709585 -(cherry picked from commit 4d9b4f23d761621073eb7f858e654fc7aceb406d) ---- - base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java | 2 +- - base/util/src/netscape/security/util/WrappingParams.java | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -index e9bc0dd..3d85a14 100644 ---- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java -@@ -3111,7 +3111,7 @@ public class CryptoUtil { - if (oid.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID)) - return KeyWrapAlgorithm.AES_CBC_PAD; - -- if (oid.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID)) -+ if (oid.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID)) - return KeyWrapAlgorithm.DES3_CBC_PAD; - - throw new NoSuchAlgorithmException(wrapOID); -diff --git a/base/util/src/netscape/security/util/WrappingParams.java b/base/util/src/netscape/security/util/WrappingParams.java -index f1ebc95..b0d4600 100644 ---- a/base/util/src/netscape/security/util/WrappingParams.java -+++ b/base/util/src/netscape/security/util/WrappingParams.java -@@ -67,7 +67,7 @@ public class WrappingParams { - // New clients set this correctly. - // We'll assume the old DES3 wrapping here. - encrypt = EncryptionAlgorithm.DES_CBC_PAD; -- } else if (encryptOID.equals(KeyWrapAlgorithm.DES_CBC_PAD_OID.toString())) { -+ } else if (encryptOID.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID.toString())) { - encrypt = EncryptionAlgorithm.DES3_CBC_PAD; - } else if (encryptOID.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID.toString())) { - encrypt = EncryptionAlgorithm.AES_128_CBC_PAD; --- -1.8.3.1 - - -From 78c8448064afddeefea8938f01100a03f6a10d2d Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 29 Aug 2018 16:55:31 +1000 -Subject: [PATCH 08/14] getTheSerialNumber: only return null if next range not - available - -When cloning, if the master's current number range has been depleted -due to a previous UpdateNumberRange request, -Repository.getTheSerialNumber() returns null because the next serial -number is out of the current range, but the next range has not been -activated yet. NullPointerException ensues. - -Update getTheSerialNumber() to return the next serial number even -when it exceeds the current number range, as long as there is a next -range. If there is no next range, return null (as before). It is -assumed that the next range is non-empty - -Also do a couple of drive-by method extractions to improve -readability. - -Part of: https://pagure.io/dogtagpki/issue/3055 - -(cherry picked from commit f1615df509053a8f474b82ea6a2fa0883ab06d09) ---- - .../src/com/netscape/cmscore/dbs/Repository.java | 61 ++++++++++++++++------ - 1 file changed, 44 insertions(+), 17 deletions(-) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -index afe9013..c5120c4 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -@@ -317,7 +317,15 @@ public abstract class Repository implements IRepository { - } - - /** -- * get the next serial number in cache -+ * Peek at the next serial number in cache (does not consume the -+ * number). -+ * -+ * The returned number is not necessarily the previously emitted -+ * serial number plus one, i.e. if we are going to roll into the -+ * next range. This method does not actually switch the range. -+ * -+ * Returns null if the next number exceeds the current range and -+ * there is not a next range. - */ - public BigInteger getTheSerialNumber() throws EBaseException { - -@@ -327,7 +335,7 @@ public abstract class Repository implements IRepository { - BigInteger serial = mLastSerialNo.add(BigInteger.ONE); - - if (mMaxSerialNo != null && serial.compareTo(mMaxSerialNo) > 0) -- return null; -+ return hasNextRange() ? mNextMinSerialNo : null; - else - return serial; - } -@@ -390,9 +398,13 @@ public abstract class Repository implements IRepository { - } - - /** -- * Checks to see if range needs to be switched. -+ * Checks if the given number is in the current range. -+ * If it does not exceed the current range, return cleanly. -+ * If it exceeds the given range, and there is a next range, switch the range. -+ * If it exceeds the given range, and there is not a next range, throw EDBException. - * -- * @exception EBaseException thrown when next range is not allocated -+ * @exception EDBException thrown when range switch is needed -+ * but next range is not allocated - */ - protected void checkRange() throws EBaseException - { -@@ -413,7 +425,7 @@ public abstract class Repository implements IRepository { - - if (mDB.getEnableSerialMgmt()) { - CMS.debug("Reached the end of the range. Attempting to move to next range"); -- if ((mNextMinSerialNo == null) || (mNextMaxSerialNo == null)) { -+ if (!hasNextRange()) { - if (rangeLength != null && mCounter.compareTo(rangeLength) < 0) { - return; - } else { -@@ -421,18 +433,7 @@ public abstract class Repository implements IRepository { - mLastSerialNo.toString())); - } - } -- mMinSerialNo = mNextMinSerialNo; -- mMaxSerialNo = mNextMaxSerialNo; -- mLastSerialNo = mMinSerialNo; -- mNextMinSerialNo = null; -- mNextMaxSerialNo = null; -- mCounter = BigInteger.ZERO; -- -- // persist the changes -- mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix)); -- mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix)); -- mDB.setNextMinSerialConfig(mRepo, null); -- mDB.setNextMaxSerialConfig(mRepo, null); -+ switchToNextRange(); - } else { - throw new EDBException(CMS.getUserMessage("CMS_DBS_LIMIT_REACHED", - mLastSerialNo.toString())); -@@ -441,6 +442,32 @@ public abstract class Repository implements IRepository { - } - - /** -+ * Return true iff there is a next range ready to go. -+ */ -+ private boolean hasNextRange() { -+ return (mNextMinSerialNo != null) && (mNextMaxSerialNo != null); -+ } -+ -+ /** -+ * Switch to the next range and persist the changes. -+ */ -+ private void switchToNextRange() -+ throws EBaseException { -+ mMinSerialNo = mNextMinSerialNo; -+ mMaxSerialNo = mNextMaxSerialNo; -+ mLastSerialNo = mMinSerialNo; -+ mNextMinSerialNo = null; -+ mNextMaxSerialNo = null; -+ mCounter = BigInteger.ZERO; -+ -+ // persist the changes -+ mDB.setMinSerialConfig(mRepo, mMinSerialNo.toString(mRadix)); -+ mDB.setMaxSerialConfig(mRepo, mMaxSerialNo.toString(mRadix)); -+ mDB.setNextMinSerialConfig(mRepo, null); -+ mDB.setNextMaxSerialConfig(mRepo, null); -+ } -+ -+ /** - * Checks to see if a new range is needed, or if we have reached the end of the - * current range, or if a range conflict has occurred. - * --- -1.8.3.1 - - -From 30fa68e6241763c5c117014e9e5cacc410cc3a56 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Mon, 3 Sep 2018 15:55:35 +1000 -Subject: [PATCH 09/14] Repository: handle depleted range in initCache() - -Repository.initCache() does not handle the case where the current -range has been fully depleted, but the switch to the next range has -not occurred yet. This situation arises when the range has been -fully depleted by servicing UpdateNumberRange requests for clones. - -Detect this situation and handle it by switching to the next range -(when available). - -Part of: https://pagure.io/dogtagpki/issue/3055 - -(cherry picked from commit 2fb3611db5145dbdd5e7e14daaad1470691494f0) ---- - .../src/com/netscape/cmscore/dbs/Repository.java | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -index c5120c4..828217c 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -@@ -298,6 +298,25 @@ public abstract class Repository implements IRepository { - BigInteger theSerialNo = null; - theSerialNo = getLastSerialNumberInRange(mMinSerialNo, mMaxSerialNo); - -+ if (theSerialNo == null) { -+ // This arises when range has been depleted by servicing -+ // UpdateNumberRange requests for clones. Attempt to -+ // move to next range. -+ CMS.debug( -+ "Repository: failed to get last serial number in range " -+ + mMinSerialNo + ".." + mMaxSerialNo); -+ -+ if (hasNextRange()) { -+ CMS.debug("Repository: switching to next range."); -+ switchToNextRange(); -+ CMS.debug("Repository: new range: " + mMinSerialNo + ".." + mMaxSerialNo); -+ // try again with updated range -+ theSerialNo = getLastSerialNumberInRange(mMinSerialNo, mMaxSerialNo); -+ } else { -+ CMS.debug("Repository: next range not available."); -+ } -+ } -+ - if (theSerialNo != null) { - - mLastSerialNo = new BigInteger(theSerialNo.toString()); --- -1.8.3.1 - - -From 920187e48e4971069ac114a3a41a5be79578f17c Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 29 Aug 2018 17:31:34 +1000 -Subject: [PATCH 10/14] rename method getTheSerialNumber -> - peekNextSerialNumber - -Rename Repository.getTheSerialNumber -> peekNextSerialNumber to more -accurately reflect what it does: peek at the next serial number -without actually consuming it. - -Part of: https://pagure.io/dogtagpki/issue/3055 - -(cherry picked from commit 85e356580f64f87c0b01736b71dc3d385db0bcba) ---- - base/ca/src/com/netscape/ca/CertificateAuthority.java | 2 +- - base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java | 2 +- - .../cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java | 2 +- - base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java -index 0281db0..f414628 100644 ---- a/base/ca/src/com/netscape/ca/CertificateAuthority.java -+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java -@@ -1077,7 +1077,7 @@ public class CertificateAuthority - public String getStartSerial() { - try { - BigInteger serial = -- mCertRepot.getTheSerialNumber(); -+ mCertRepot.peekNextSerialNumber(); - - if (serial == null) - return ""; -diff --git a/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java b/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java -index 39744ac..d0b6135 100644 ---- a/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java -+++ b/base/common/src/com/netscape/certsrv/dbs/repository/IRepository.java -@@ -50,7 +50,7 @@ public interface IRepository { - * @return serial number - * @exception EBaseException failed to retrieve next serial number - */ -- public BigInteger getTheSerialNumber() throws EBaseException; -+ public BigInteger peekNextSerialNumber() throws EBaseException; - - /** - * Set the maximum serial number. -diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -index 2586da2..e5b5168 100644 ---- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -@@ -187,7 +187,7 @@ public class UpdateNumberRange extends CMSServlet { - BigInteger decrement = new BigInteger(decrementStr, radix); - beginNum = endNum.subtract(decrement).add(oneNum); - -- if (beginNum.compareTo(repo.getTheSerialNumber()) < 0) { -+ if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) { - String nextEndNumStr = cs.getString(nextEndConfig, ""); - BigInteger endNum2 = new BigInteger(nextEndNumStr, radix); - CMS.debug("Transferring from the end of on-deck range"); -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -index 828217c..55068ea 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -@@ -346,7 +346,7 @@ public abstract class Repository implements IRepository { - * Returns null if the next number exceeds the current range and - * there is not a next range. - */ -- public BigInteger getTheSerialNumber() throws EBaseException { -+ public BigInteger peekNextSerialNumber() throws EBaseException { - - CMS.debug("Repository:In getTheSerialNumber "); - if (mLastSerialNo == null) --- -1.8.3.1 - - -From 60e78b19edb91b5d7130f591dec5232f30877871 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 29 Aug 2018 21:42:40 +1000 -Subject: [PATCH 11/14] checkRange: small refactor and add commentary - -Add some commentary about the behaviour and proper usage of -Repository.checkRange(). Also perform a small refactor, avoiding -a redundant stringify and parse. - -Part of: https://pagure.io/dogtagpki/issue/3055 - -(cherry picked from commit 5a606e83719272fb488047b28a9ca7d5ce2ea30b) ---- - .../src/com/netscape/cmscore/dbs/Repository.java | 19 +++++++++++++++---- - 1 file changed, 15 insertions(+), 4 deletions(-) - -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -index 55068ea..9bc7e2a 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -@@ -406,14 +406,17 @@ public abstract class Repository implements IRepository { - throw new EBaseException("mLastSerialNo is null"); - } - -+ /* Advance the serial number. checkRange() will check if it exceeds -+ * the current range and, if so, rolls to the next range and resets -+ * mLastSerialNo to the start of the new range. Hence we return -+ * mLastSerialNo below, after the call to checkRange(). -+ */ - mLastSerialNo = mLastSerialNo.add(BigInteger.ONE); - - checkRange(); - -- BigInteger retSerial = new BigInteger(mLastSerialNo.toString()); -- -- CMS.debug("Repository: getNextSerialNumber: returning retSerial " + retSerial); -- return retSerial; -+ CMS.debug("Repository: getNextSerialNumber: returning " + mLastSerialNo); -+ return mLastSerialNo; - } - - /** -@@ -422,6 +425,14 @@ public abstract class Repository implements IRepository { - * If it exceeds the given range, and there is a next range, switch the range. - * If it exceeds the given range, and there is not a next range, throw EDBException. - * -+ * Precondition: the serial number should already have been advanced. -+ * This method will detect that and switch to the next range, including -+ * resetting mLastSerialNo to the start of the new (now current) range. -+ * -+ * Postcondition: the caller should again read mLastSerialNo after -+ * calling checkRange(), in case checkRange switched the range and the -+ * new range is not adjacent to the current range. -+ * - * @exception EDBException thrown when range switch is needed - * but next range is not allocated - */ --- -1.8.3.1 - - -From a2c05cef94753ee1914aeb9c1b88789a322d4015 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 29 Aug 2018 22:22:10 +1000 -Subject: [PATCH 12/14] Add missing synchronisation for range management - -Several methods in Repository (and CertificateRepository) need -synchronisation on the intrisic lock. Make these methods -synchronised. - -Also take the lock in UpdateNumberRange so that no serial numbers -can be handed out in other threads between peekNextSerialNumber() -and set(Next)?MaxSerial(). Without this synchronisation, it is -possible that the master instance will use some of the serial -numbers it transfers to the clone. - -Fixes: https://pagure.io/dogtagpki/issue/3055 -(cherry picked from commit 851a0bdd79c12c627a04cfc376338c1727cd50d9) ---- - .../cms/servlet/csadmin/UpdateNumberRange.java | 35 +++++++----- - .../cmscore/dbs/CertificateRepository.java | 62 ++++++++++------------ - .../src/com/netscape/cmscore/dbs/Repository.java | 6 +-- - 3 files changed, 53 insertions(+), 50 deletions(-) - -diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -index e5b5168..c2ff7ed 100644 ---- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java -@@ -187,20 +187,27 @@ public class UpdateNumberRange extends CMSServlet { - BigInteger decrement = new BigInteger(decrementStr, radix); - beginNum = endNum.subtract(decrement).add(oneNum); - -- if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) { -- String nextEndNumStr = cs.getString(nextEndConfig, ""); -- BigInteger endNum2 = new BigInteger(nextEndNumStr, radix); -- CMS.debug("Transferring from the end of on-deck range"); -- String newValStr = endNum2.subtract(decrement).toString(radix); -- repo.setNextMaxSerial(newValStr); -- cs.putString(nextEndConfig, newValStr); -- beginNum = endNum2.subtract(decrement).add(oneNum); -- endNum = endNum2; -- } else { -- CMS.debug("Transferring from the end of the current range"); -- String newValStr = beginNum.subtract(oneNum).toString(radix); -- repo.setMaxSerial(newValStr); -- cs.putString(endNumConfig, newValStr); -+ /* We need to synchronise on repo because we peek the next -+ * serial number, then set the max serial of the current or -+ * next range. If we don't synchronize, we could end up -+ * using serial numbers that were transferred. -+ */ -+ synchronized (repo) { -+ if (beginNum.compareTo(repo.peekNextSerialNumber()) < 0) { -+ String nextEndNumStr = cs.getString(nextEndConfig, ""); -+ BigInteger endNum2 = new BigInteger(nextEndNumStr, radix); -+ CMS.debug("Transferring from the end of on-deck range"); -+ String newValStr = endNum2.subtract(decrement).toString(radix); -+ repo.setNextMaxSerial(newValStr); -+ cs.putString(nextEndConfig, newValStr); -+ beginNum = endNum2.subtract(decrement).add(oneNum); -+ endNum = endNum2; -+ } else { -+ CMS.debug("Transferring from the end of the current range"); -+ String newValStr = beginNum.subtract(oneNum).toString(radix); -+ repo.setMaxSerial(newValStr); -+ cs.putString(endNumConfig, newValStr); -+ } - } - - if (beginNum == null) { -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java -index 367917f..94087c8 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CertificateRepository.java -@@ -251,49 +251,45 @@ public class CertificateRepository extends Repository - return nextSerialNumber; - } - -- private Object nextSerialNumberMonitor = new Object(); -- -- public BigInteger getNextSerialNumber() throws -+ public synchronized BigInteger getNextSerialNumber() throws - EBaseException { - - BigInteger nextSerialNumber = null; - BigInteger randomNumber = null; - -- synchronized (nextSerialNumberMonitor) { -- super.initCacheIfNeeded(); -- CMS.debug("CertificateRepository: getNextSerialNumber mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers); -+ super.initCacheIfNeeded(); -+ CMS.debug("CertificateRepository: getNextSerialNumber mEnableRandomSerialNumbers="+mEnableRandomSerialNumbers); - -- if (mEnableRandomSerialNumbers) { -- int i = 0; -- do { -- if (i > 0) { -- CMS.debug("CertificateRepository: getNextSerialNumber regenerating serial number"); -- } -- randomNumber = getRandomNumber(); -- nextSerialNumber = getRandomSerialNumber(randomNumber); -- nextSerialNumber = checkSerialNumbers(randomNumber, nextSerialNumber); -- i++; -- } while (nextSerialNumber == null && i < mMaxCollisionRecoveryRegenerations); -- -- if (nextSerialNumber == null) { -- CMS.debug("CertificateRepository: in getNextSerialNumber nextSerialNumber is null"); -- throw new EBaseException( "nextSerialNumber is null" ); -+ if (mEnableRandomSerialNumbers) { -+ int i = 0; -+ do { -+ if (i > 0) { -+ CMS.debug("CertificateRepository: getNextSerialNumber regenerating serial number"); - } -+ randomNumber = getRandomNumber(); -+ nextSerialNumber = getRandomSerialNumber(randomNumber); -+ nextSerialNumber = checkSerialNumbers(randomNumber, nextSerialNumber); -+ i++; -+ } while (nextSerialNumber == null && i < mMaxCollisionRecoveryRegenerations); - -- if (mCounter.compareTo(BigInteger.ZERO) >= 0 && -- mMinSerialNo != null && mMaxSerialNo != null && -- nextSerialNumber != null && -- nextSerialNumber.compareTo(mMinSerialNo) >= 0 && -- nextSerialNumber.compareTo(mMaxSerialNo) <= 0) { -- mCounter = mCounter.add(BigInteger.ONE); -- } -- CMS.debug("CertificateRepository: getNextSerialNumber nextSerialNumber="+ -- nextSerialNumber+" mCounter="+mCounter); -+ if (nextSerialNumber == null) { -+ CMS.debug("CertificateRepository: in getNextSerialNumber nextSerialNumber is null"); -+ throw new EBaseException( "nextSerialNumber is null" ); -+ } - -- super.checkRange(); -- } else { -- nextSerialNumber = super.getNextSerialNumber(); -+ if (mCounter.compareTo(BigInteger.ZERO) >= 0 && -+ mMinSerialNo != null && mMaxSerialNo != null && -+ nextSerialNumber != null && -+ nextSerialNumber.compareTo(mMinSerialNo) >= 0 && -+ nextSerialNumber.compareTo(mMaxSerialNo) <= 0) { -+ mCounter = mCounter.add(BigInteger.ONE); - } -+ CMS.debug("CertificateRepository: getNextSerialNumber nextSerialNumber="+ -+ nextSerialNumber+" mCounter="+mCounter); -+ -+ super.checkRange(); -+ } else { -+ nextSerialNumber = super.getNextSerialNumber(); - } - - return nextSerialNumber; -diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -index 9bc7e2a..c31d376 100644 ---- a/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/Repository.java -@@ -185,7 +185,7 @@ public abstract class Repository implements IRepository { - * @param serial maximum number - * @exception EBaseException failed to set maximum serial number - */ -- public void setMaxSerial(String serial) throws EBaseException { -+ public synchronized void setMaxSerial(String serial) throws EBaseException { - BigInteger maxSerial = null; - CMS.debug("Repository:setMaxSerial " + serial); - -@@ -211,7 +211,7 @@ public abstract class Repository implements IRepository { - * @param serial maximum number in next range - * @exception EBaseException failed to set maximum serial number in next range - */ -- public void setNextMaxSerial(String serial) throws EBaseException { -+ public synchronized void setNextMaxSerial(String serial) throws EBaseException { - BigInteger maxSerial = null; - CMS.debug("Repository:setNextMaxSerial " + serial); - -@@ -346,7 +346,7 @@ public abstract class Repository implements IRepository { - * Returns null if the next number exceeds the current range and - * there is not a next range. - */ -- public BigInteger peekNextSerialNumber() throws EBaseException { -+ public synchronized BigInteger peekNextSerialNumber() throws EBaseException { - - CMS.debug("Repository:In getTheSerialNumber "); - if (mLastSerialNo == null) --- -1.8.3.1 - - -From 2fb237853c3f730f4f96141d9710d1394de5649d Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Fri, 20 Sep 2019 10:59:07 -0500 -Subject: [PATCH 13/14] Replaced "Advanced Search" with "Filter" in TPS UI - -(cherry picked from commit df3ece37320c2de7db025aa172c2344b07a55483) ---- - base/tps/shared/webapps/tps/ui/tokens.html | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/tps/shared/webapps/tps/ui/tokens.html b/base/tps/shared/webapps/tps/ui/tokens.html -index c2f6227..41d8d94 100644 ---- a/base/tps/shared/webapps/tps/ui/tokens.html -+++ b/base/tps/shared/webapps/tps/ui/tokens.html -@@ -30,7 +30,7 @@ - - - -- Advanced Search -+ Filter - - - --- -1.8.3.1 - - -From f2186a497978b778a808e6ad892bfd4180acf8a6 Mon Sep 17 00:00:00 2001 -From: Jack Magne -Date: Fri, 20 Sep 2019 20:20:13 -0400 -Subject: [PATCH 14/14] Fix Bug 1534013 - Attempting to add new keys using a - PUT KEY APDU to a token that is loaded only with the default/factory keys - (Key Version Number 0xFF) returns an APDU with error code 0x6A88. - -The token returns 0x6A88 (Referenced data not found) because sending it a key version number of 1, implies that the token already has a key with key version 1. In the case of a token with only default/factory keys with version 0xFF, the key with version #1 is not present. - -Giving zero as the key version number in the APDU specifically tells the token to add a new key, with a new key version number. A non-zero key version number instructs the card to replace an existing key. If the existing key is not present then an error occurs. - -(cherry picked from commit 19bb64a98881e4651126bcdc544e3fa04ea989ea) ---- - base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java -index cb08970..7369e58 100644 ---- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java -+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java -@@ -1558,8 +1558,8 @@ public class SecureChannel { - byte keyVersion = curVersion; - - if (curVersion == (byte) 0xff) { -- CMS.debug("Setting keyVersion to 1"); -- keyVersion = 0x1; -+ CMS.debug("Setting keyVersion to 0"); -+ keyVersion = 0x0; - } - - CMS.debug("keyVersion now set to: " + keyVersion); --- -1.8.3.1 - diff --git a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-snapshot-2.patch b/SOURCES/pki-core-rhel-7-8-rhcs-9-6-snapshot-2.patch deleted file mode 100644 index 0b1ac4b..0000000 --- a/SOURCES/pki-core-rhel-7-8-rhcs-9-6-snapshot-2.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 6c199b8882fa1b2cb07f911d29d2a7eccf7e99c7 Mon Sep 17 00:00:00 2001 -From: Christina Fu -Date: Fri, 22 Nov 2019 13:03:18 -0500 -Subject: [PATCH 1/2] Bug 1723008 - ECC Key recovery failure with - CKR_TEMPLATE_INCONSISTENT - -The current settings irt key wrapping parameters were depending on the -expection that the revised sw version for the nCipher HSM would be capable -of handling the key wrapping/unwrapping algorithm "AES KeyWrap/Padding"; -As it turned out it did not completely do that. -This patch changes the default setting in the KRA CS.cfg as well as -CRMFPopClient to that of a supported wrapping algorithm: AES/CBC/PKCS5Padding - -Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1723008 - -(cherry picked from commit 06fdf41b2f5947f90d84b3fc32def4c8346c9601) ---- - base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java | 6 +++--- - base/kra/shared/conf/CS.cfg | 3 ++- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java -index 72eca3e..4caf92f 100644 ---- a/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java -+++ b/base/java-tools/src/com/netscape/cmstools/CRMFPopClient.java -@@ -224,8 +224,8 @@ public class CRMFPopClient { - System.out.println(" - POP_SUCCESS: with valid POP"); - System.out.println(" - POP_FAIL: with invalid POP (for testing)"); - System.out.println(" -w Algorithm to use for key wrapping"); -- System.out.println(" - default: \"AES KeyWrap/Padding\""); -- System.out.println(" - \"AES/CBC/PKCS5Padding\""); -+ System.out.println(" - default: \"AES/CBC/PKCS5Padding\""); -+ System.out.println(" - \"AES KeyWrap/Padding\""); - System.out.println(" - \"DES3/CBC/Pad\""); - System.out.println(" -b PEM transport certificate (default: transport.txt)"); - System.out.println(" -v, --verbose Run in verbose mode."); -@@ -324,7 +324,7 @@ public class CRMFPopClient { - - // get the keywrap algorithm - KeyWrapAlgorithm keyWrapAlgorithm = null; -- String kwAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD.toString(); -+ String kwAlg = KeyWrapAlgorithm.AES_CBC_PAD.toString(); - if (cmd.hasOption("w")) { - kwAlg = cmd.getOptionValue("w"); - } else { -diff --git a/base/kra/shared/conf/CS.cfg b/base/kra/shared/conf/CS.cfg -index f21f305..9f54c40 100644 ---- a/base/kra/shared/conf/CS.cfg -+++ b/base/kra/shared/conf/CS.cfg -@@ -286,7 +286,8 @@ kra.storageUnit.wrapping.1.sessionKeyKeyGenAlgorithm=AES - kra.storageUnit.wrapping.1.payloadEncryptionAlgorithm=AES - kra.storageUnit.wrapping.1.payloadEncryptionMode=CBC - kra.storageUnit.wrapping.1.payloadEncryptionIVLen=16 --kra.storageUnit.wrapping.1.payloadWrapAlgorithm=AES KeyWrap/Padding -+kra.storageUnit.wrapping.1.payloadWrapAlgorithm=AES/CBC/PKCS5Padding -+kra.storageUnit.wrapping.1.payloadWrapIVLen=16 - kra.storageUnit.wrapping.1.sessionKeyType=AES - kra.storageUnit.wrapping.choice=1 - kra.storageUnit.nickName=storageCert cert-[PKI_INSTANCE_NAME] --- -1.8.3.1 - - -From 90105b85df48b2035e8c5fa1f0982f631964b011 Mon Sep 17 00:00:00 2001 -From: Alexander Scheel -Date: Wed, 20 Nov 2019 09:10:02 -0500 -Subject: [PATCH 2/2] Remove non-breaking space from pki-server-nuxwdog - -In pki-server-nuxwdog, we had a non-breaking space at the end of a -quoted string, causing the resulting directory to end with a -non-breaking space. - -This results in paths with incorrect names: - -/var/log/pki/$INSTANCE/pids / - -instead of - -/var/log/pki/$INSTANCE/pids/ - -Resolves: rhbz#1774282 - -Signed-off-by: Alexander Scheel -(cherry picked from commit 4f2b8aaf13b488558b7718d7967d42db4d23d172) ---- - base/server/sbin/pki-server-nuxwdog | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/base/server/sbin/pki-server-nuxwdog b/base/server/sbin/pki-server-nuxwdog -index ffdbc33..5244d57 100755 ---- a/base/server/sbin/pki-server-nuxwdog -+++ b/base/server/sbin/pki-server-nuxwdog -@@ -43,7 +43,7 @@ chown ${TOMCAT_USER}: ${nux_fname} - - echo "ExeFile ${JAVA_HOME}/bin/java" > $nux_fname - echo "ExeArgs ${JAVA_HOME}/bin/java ${JAVACMD_OPTS} ${FLAGS} -classpath ${CLASSPATH} ${OPTIONS} ${MAIN_CLASS} start" >> $nux_fname --echo "TmpDir ${CATALINA_BASE}/logs/pids" >> $nux_fname -+echo "TmpDir ${CATALINA_BASE}/logs/pids" >> $nux_fname - echo "ChildSecurity 1" >> $nux_fname - echo "ExeOut ${CATALINA_BASE}/logs/catalina.out" >> $nux_fname - echo "ExeErr ${CATALINA_BASE}/logs/catalina.out" >> $nux_fname --- -1.8.3.1 - diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-beta.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-beta.patch new file mode 100644 index 0000000..c812a8f --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-beta.patch @@ -0,0 +1,3686 @@ +From a4f203666bc157bc2bcc09c7f1abd19d987d77ec Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Thu, 16 Apr 2020 10:23:08 -0700 +Subject: [PATCH 1/6] Fix Bug 1809273 - CRL generation performs an unindexed + search. (#378) + +This fix right now will take care of new installations only. + +Co-authored-by: Jack Magne +(cherry picked from commit e587f9557620a737fea3f3e1b14ec58e2957edb5) +--- + base/ca/shared/conf/CS.cfg | 2 +- + base/ca/shared/conf/crlcaissuer.ldif | 15 +++++++++++++++ + base/ca/shared/conf/crlcaissuertasks.ldif | 7 +++++++ + .../netscape/cms/servlet/csadmin/ConfigurationUtils.java | 11 +++++++++++ + 4 files changed, 34 insertions(+), 1 deletion(-) + create mode 100644 base/ca/shared/conf/crlcaissuer.ldif + create mode 100644 base/ca/shared/conf/crlcaissuertasks.ldif + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index ce76cff..741d4aa 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -830,7 +830,7 @@ preop.internaldb.ldif=/usr/share/pki/server/conf/database.ldif + preop.internaldb.data_ldif=/usr/share/pki/ca/conf/db.ldif,/usr/share/pki/ca/conf/acl.ldif + preop.internaldb.index_ldif=/usr/share/pki/ca/conf/index.ldif + preop.internaldb.manager_ldif=/usr/share/pki/server/conf/manager.ldif +-preop.internaldb.post_ldif=/usr/share/pki/ca/conf/vlv.ldif,/usr/share/pki/ca/conf/vlvtasks.ldif ++preop.internaldb.post_ldif=/usr/share/pki/ca/conf/vlv.ldif,/usr/share/pki/ca/conf/vlvtasks.ldif,/usr/share/pki/ca/conf/crlcaissuer.ldif,/usr/share/pki/ca/conf/crlcaissuertasks.ldif + preop.internaldb.wait_dn=cn=index1160589769, cn=index, cn=tasks, cn=config + preop.internaldb.index_task_ldif=/usr/share/pki/ca/conf/indextasks.ldif + preop.internaldb.index_wait_dn=cn=index1160589770,cn=index,cn=tasks,cn=config +diff --git a/base/ca/shared/conf/crlcaissuer.ldif b/base/ca/shared/conf/crlcaissuer.ldif +new file mode 100644 +index 0000000..2fec1a0 +--- /dev/null ++++ b/base/ca/shared/conf/crlcaissuer.ldif +@@ -0,0 +1,15 @@ ++dn: cn=allRevokedCertsByIssuer-{instanceId}, cn={database}, cn=ldbm database, cn=plugins, cn=config ++objectClass: top ++objectClass: vlvSearch ++cn: allRevokedCertsByIssuer-{instanceId} ++vlvBase: ou=certificateRepository,ou=ca,{rootSuffix} ++vlvScope: 1 ++vlvFilter: (&(certStatus=REVOKED)(|(!(issuerName=*))(issuerName={caIssuerDN}))) ++ ++dn: cn=allRevokedCertsByIssuer-{instanceId}Index, cn=allRevokedCerts-{instanceId}, cn={database}, cn=ldbm database, cn=plugins, cn=config ++objectClass: top ++objectClass: vlvIndex ++cn: allRevokedCertsByIssuer-{instanceId}Index ++vlvSort: serialno ++vlvEnabled: 0 ++vlvUses: 0 +diff --git a/base/ca/shared/conf/crlcaissuertasks.ldif b/base/ca/shared/conf/crlcaissuertasks.ldif +new file mode 100644 +index 0000000..888e113 +--- /dev/null ++++ b/base/ca/shared/conf/crlcaissuertasks.ldif +@@ -0,0 +1,7 @@ ++dn: cn=index1160589779, cn=index, cn=tasks, cn=config ++objectclass: top ++objectclass: extensibleObject ++cn: index1160589779 ++ttl: 10 ++nsinstance: {database} ++nsindexVLVAttribute: allRevokedCertsByIssuer-{instanceId} +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +index aca4827..2510191 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +@@ -1701,6 +1701,8 @@ public class ConfigurationUtils { + EBaseException { + IConfigStore cs = CMS.getConfigStore(); + ++ String caIssuerName = null; ++ + CMS.debug("importLDIFS: param=" + param); + String v = cs.getString(param); + +@@ -1712,6 +1714,11 @@ public class ConfigurationUtils { + String dbuser = cs.getString("preop.internaldb.dbuser", + "uid=" + DBUSER + ",ou=people," + baseDN); + ++ if("ca".equalsIgnoreCase(cstype)) { ++ caIssuerName = cs.getString("preop.cert.signing.dn", null); ++ CMS.debug("importLDIFS(): ca issuer name = " + caIssuerName); ++ } ++ + String configDir = instancePath + File.separator + cstype.toLowerCase() + File.separator + "conf"; + + StringTokenizer tokenizer = new StringTokenizer(v, ","); +@@ -1755,6 +1762,10 @@ public class ConfigurationUtils { + ps.print(database); + } else if (tok.equals("dbuser")) { + ps.print(dbuser); ++ } else if (tok.equals("caIssuerDN") ) { ++ if(caIssuerName != null) { ++ ps.print(caIssuerName); ++ } + } + if ((s.length() + 1) == n1) { + endOfline = true; +-- +1.8.3.1 + + +From 944862c63e3f8fb4647b4728d9006e795c6ddc8d Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Fri, 17 Apr 2020 10:46:43 -0400 +Subject: [PATCH 2/6] Add TPS Auditor group + +Resolves: bz#1549307 + +Signed-off-by: Alexander Scheel +(cherry picked from commit b27cdf487b4dcbc9d16275f1b911643f3b03de57) +--- + base/tps/shared/conf/db.ldif | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/base/tps/shared/conf/db.ldif b/base/tps/shared/conf/db.ldif +index a88e66b..6661d8b 100644 +--- a/base/tps/shared/conf/db.ldif ++++ b/base/tps/shared/conf/db.ldif +@@ -41,6 +41,12 @@ objectClass: groupOfUniqueNames + cn: Administrators + description: Administrators for TPS + ++dn: cn=Auditors,ou=Groups,{rootSuffix} ++objectClass: top ++objectClass: groupOfUniqueNames ++cn: Auditors ++description: People who can read the signed audit logs for TPS ++ + dn: cn=TPS Operators,ou=Groups,{rootSuffix} + objectClass: top + objectClass: groupOfUniqueNames +-- +1.8.3.1 + + +From b3d46362c83ff2aa8447aa579722d0be209ab590 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Fri, 20 Mar 2020 18:58:26 -0400 +Subject: [PATCH 3/6] Bug 1794213 Server-Side Kyegen Enrollment + +This patch contains the code that provides the Server-Side Keygen Enrollment feature. + +Some limitations for this release: + - It currently only supports RSA keys. + - You need to import the KRA's transport cert into CA's nssdb with the nickname + "KRA Transport Certificate" + then restart the CA. + - Currently, the UI (Javascript) keyType and keySize pulldown menu needs some work + (ProfileSelect.template) + - Some more error checking and cleanup needed (will be done before actual push) + +----- +This patch contains mainly the following pieces: + +input: + The new input plugin ServerKeygenInput.java, which is supposed +to work with the modification in ProfileSelect.template to + - accept the p12 passwd that will be used to compose the p12 once the keys are generated on KRA and cert issued by the CA. + - accept the keyType: RSA/ECC + - accept the keySize: RSA key sizes or ECC curves + +Profile: + - The new default plugin: ServerKeygenUserKeyDefault.java, which inserts temporary fake keys so code won't blow up down the road; Such fake key will be replaced later when KRA generates the new keys + - The new caServerKeygen_UserCert.cfg profile which utilizes the new input and output + +output: + The new output plugin PKCS12Output.java, which contains the p12 to be sent +back to the browser when the request has been approved. + +What's expected: + Once working, if you go to EE and click on (currently) the first profile: +"Manual User Dual-User Certificate Enrollment using server-side key generation", +one should expect to be able to specify the p12 password, p12 password +again (verified by the Javascript), the key type (RSA/ECC), key size/curve, +the subject name info, and the requestor info. + Once filled out and submit, the request should go into the request queue +waiting to be approved. +During approval, the keys should be generated on KRA, archived, and pkcs#12 returned. + +Finally: +Server-side key generation for enrollment is not intended to be a solution +for all. It's mainly for encryption keys, unless the site administrator + doesn't care about archiving signing keys. + +https://bugzilla.redhat.com/show_bug.cgi?id=1794213 +(cherry picked from commit 3e38d8cfae018a2a2ad69247c9d1b3e347b21ee0) +--- + base/ca/shared/conf/CS.cfg | 4 +- + base/ca/shared/conf/registry.cfg | 15 +- + .../shared/profiles/ca/caServerKeygen_UserCert.cfg | 103 ++++++ + .../shared/webapps/ca/ee/ca/ProfileSelect.template | 25 +- + base/common/src/com/netscape/certsrv/apps/CMS.java | 1 + + .../certsrv/cert/CertEnrollmentRequest.java | 15 + + .../netscape/certsrv/profile/IEnrollProfile.java | 6 + + .../com/netscape/certsrv/profile/ProfileData.java | 3 +- + .../com/netscape/certsrv/property/IDescriptor.java | 2 + + .../src/com/netscape/certsrv/request/IRequest.java | 6 + + .../src/com/netscape/kra/AsymKeyGenService.java | 69 ++++ + base/kra/src/com/netscape/kra/KRAService.java | 2 +- + base/kra/src/com/netscape/kra/RecoveryService.java | 84 ++++- + .../cms/profile/common/CAEnrollProfile.java | 171 ++++++++- + .../profile/def/ServerKeygenUserKeyDefault.java | 385 +++++++++++++++++++++ + .../cms/profile/input/ServerKeygenInput.java | 115 ++++++ + .../netscape/cms/profile/output/PKCS12Output.java | 110 ++++++ + .../com/netscape/cms/servlet/base/CMSServlet.java | 4 + + .../cms/servlet/connector/ConnectorServlet.java | 48 ++- + .../cms/servlet/profile/ProfileProcessServlet.java | 31 +- + base/server/cmsbundle/src/UserMessages.properties | 13 +- + .../netscape/cmscore/connector/HttpPKIMessage.java | 5 + + .../cmscore/connector/RequestTransfer.java | 4 +- + 23 files changed, 1198 insertions(+), 23 deletions(-) + create mode 100644 base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg + create mode 100644 base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java + create mode 100644 base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java + create mode 100644 base/server/cms/src/com/netscape/cms/profile/output/PKCS12Output.java + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 741d4aa..004efdc 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -976,7 +976,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=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSharedTokenCert,caECFullCMCSharedTokenCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment ++profile.list=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caServerKeygen_UserCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSharedTokenCert,caECFullCMCSharedTokenCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,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 +@@ -1131,6 +1131,8 @@ profile.caStorageCert.class_id=caEnrollImpl + profile.caStorageCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caStorageCert.cfg + profile.caTransportCert.class_id=caEnrollImpl + profile.caTransportCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caTransportCert.cfg ++profile.caServerKeygen_UserCert.class_id=caEnrollImpl ++profile.caServerKeygen_UserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caServerKeygen_UserCert.cfg + profile.caUserCert.class_id=caEnrollImpl + profile.caUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caUserCert.cfg + profile.caECUserCert.class_id=caEnrollImpl +diff --git a/base/ca/shared/conf/registry.cfg b/base/ca/shared/conf/registry.cfg +index a78af86..66348a6 100644 +--- a/base/ca/shared/conf/registry.cfg ++++ b/base/ca/shared/conf/registry.cfg +@@ -57,7 +57,7 @@ constraintPolicy.uniqueKeyConstraintImpl.name=Unique Public Key Constraint + constraintPolicy.externalProcessConstraintImpl.class=com.netscape.cms.profile.constraint.ExternalProcessConstraint + constraintPolicy.externalProcessConstraintImpl.desc=External Process Constraint + constraintPolicy.externalProcessConstraintImpl.name=External Process Constraint +-defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,cmcUserSignedSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl ++defaultPolicy.ids=noDefaultImpl,genericExtDefaultImpl,autoAssignDefaultImpl,subjectNameDefaultImpl,validityDefaultImpl,randomizedValidityDefaultImpl,caValidityDefaultImpl,subjectKeyIdentifierExtDefaultImpl,authorityKeyIdentifierExtDefaultImpl,basicConstraintsExtDefaultImpl,keyUsageExtDefaultImpl,nsCertTypeExtDefaultImpl,extendedKeyUsageExtDefaultImpl,ocspNoCheckExtDefaultImpl,issuerAltNameExtDefaultImpl,subjectAltNameExtDefaultImpl,userSubjectNameDefaultImpl,cmcUserSignedSubjectNameDefaultImpl,signingAlgDefaultImpl,userKeyDefaultImpl,userValidityDefaultImpl,userExtensionDefaultImpl,userSigningAlgDefaultImpl,authTokenSubjectNameDefaultImpl,subjectInfoAccessExtDefaultImpl,authInfoAccessExtDefaultImpl,nscCommentExtDefaultImpl,freshestCRLExtDefaultImpl,crlDistributionPointsExtDefaultImpl,policyConstraintsExtDefaultImpl,policyMappingsExtDefaultImpl,nameConstraintsExtDefaultImpl,certificateVersionDefaultImpl,certificatePoliciesExtDefaultImpl,subjectDirAttributesExtDefaultImpl,privateKeyPeriodExtDefaultImpl,inhibitAnyPolicyExtDefaultImpl,imageDefaultImpl,nsTokenDeviceKeySubjectNameDefaultImpl,nsTokenUserKeySubjectNameDefaultImpl,authzRealmDefaultImpl,commonNameToSANDefaultImpl,serverKeygenUserKeyDefaultImpl + defaultPolicy.autoAssignDefaultImpl.class=com.netscape.cms.profile.def.AutoAssignDefault + defaultPolicy.autoAssignDefaultImpl.desc=Auto Request Assignment Default + defaultPolicy.autoAssignDefaultImpl.name=Auto Request Assignment Default +@@ -82,6 +82,9 @@ defaultPolicy.cmcUserSignedSubjectNameDefaultImpl.name=CMC User Signed Subject N + defaultPolicy.userKeyDefaultImpl.class=com.netscape.cms.profile.def.UserKeyDefault + defaultPolicy.userKeyDefaultImpl.desc=User Supplied Key Default + defaultPolicy.userKeyDefaultImpl.name=User Supplied Key Default ++defaultPolicy.serverKeygenUserKeyDefaultImpl.class=com.netscape.cms.profile.def.ServerKeygenUserKeyDefault ++defaultPolicy.serverKeygenUserKeyDefaultImpl.desc=Server-Side Keygen Default ++defaultPolicy.serverKeygenUserKeyDefaultImpl.name=Server-Side Keygen Default + defaultPolicy.userValidityDefaultImpl.class=com.netscape.cms.profile.def.UserValidityDefault + defaultPolicy.userValidityDefaultImpl.desc=User Supplied Validity Default + defaultPolicy.userValidityDefaultImpl.name=User Supplied Validity Default +@@ -197,7 +200,10 @@ profile.caServerCertEnrollImpl.name=Server Certificate Enrollment Profile + profile.caUserCertEnrollImpl.class=com.netscape.cms.profile.common.UserCertCAEnrollProfile + profile.caUserCertEnrollImpl.desc=Certificate Authority User Certificate Enrollment Profile + profile.caUserCertEnrollImpl.name=User Certificate Enrollment Profile +-profileInput.ids=cmcCertReqInputImpl,certReqInputImpl,keyGenInputImpl,encKeyGenInputImpl,signKeyGenInputImpl,dualKeyGenInputImpl,subjectNameInputImpl,submitterInfoInputImpl,genericInputImpl,fileSigningInputImpl,imageInputImpl,subjectDNInputImpl,nsNKeyCertReqInputImpl,nsHKeyCertReqInputImpl,serialNumRenewInputImpl,subjectAltNameExtInputImpl ++profileInput.ids=cmcCertReqInputImpl,certReqInputImpl,keyGenInputImpl,encKeyGenInputImpl,signKeyGenInputImpl,dualKeyGenInputImpl,subjectNameInputImpl,submitterInfoInputImpl,genericInputImpl,fileSigningInputImpl,imageInputImpl,subjectDNInputImpl,nsNKeyCertReqInputImpl,nsHKeyCertReqInputImpl,serialNumRenewInputImpl,subjectAltNameExtInputImpl,serverKeygenInputImpl ++profileInput.serverKeygenInputImpl.class=com.netscape.cms.profile.input.ServerKeygenInput ++profileInput.serverKeygenInputImpl.desc=Server-Side Keygen Input ++profileInput.serverKeygenInputImpl.name=Server-Side Keygen Input + profileInput.subjectAltNameExtInputImpl.class=com.netscape.cms.profile.input.SubjectAltNameExtInput + profileInput.subjectAltNameExtInputImpl.desc=SAN Input + profileInput.subjectAltNameExtInputImpl.name=SAN Input +@@ -246,7 +252,7 @@ profileInput.subjectDNInputImpl.name=Subject DN Input + profileInput.subjectNameInputImpl.class=com.netscape.cms.profile.input.SubjectNameInput + profileInput.subjectNameInputImpl.desc=Subject Name Input + profileInput.subjectNameInputImpl.name=Subject Name Input +-profileOutput.ids=certOutputImpl,cmmfOutputImpl,pkcs7OutputImpl,nsNKeyOutputImpl ++profileOutput.ids=certOutputImpl,cmmfOutputImpl,pkcs7OutputImpl,nsNKeyOutputImpl,pkcs12OutputImpl + profileOutput.certOutputImpl.class=com.netscape.cms.profile.output.CertOutput + profileOutput.certOutputImpl.desc=Certificate Output + profileOutput.certOutputImpl.name=Certificate Output +@@ -259,6 +265,9 @@ profileOutput.nsNKeyOutputImpl.name=nsNKeyOutputImpl + profileOutput.pkcs7OutputImpl.class=com.netscape.cms.profile.output.PKCS7Output + profileOutput.pkcs7OutputImpl.desc=PKCS7 Output + profileOutput.pkcs7OutputImpl.name=PKCS7 Output ++profileOutput.pkcs12OutputImpl.class=com.netscape.cms.profile.output.PKCS12Output ++profileOutput.pkcs12OutputImpl.desc=PKCS12 Output ++profileOutput.pkcs12OutputImpl.name=PKCS12 Output + profileUpdater.ids=subsystemGroupUpdaterImpl + profileUpdater.subsystemGroupUpdaterImpl.class=com.netscape.cms.profile.updater.SubsystemGroupUpdater + profileUpdater.subsystemGroupUpdaterImpl.desc=Updater for Subsystem Group +diff --git a/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +new file mode 100644 +index 0000000..0f2b3dc +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +@@ -0,0 +1,103 @@ ++desc=This certificate profile is for enrolling user certificates using server-side Key generation. ++visible=true ++enable=true ++enableBy=admin ++name=Manual User Dual-Use Certificate Enrollment using server-side Key generation ++auth.class_id= ++input.list=i1,i2,i3 ++input.i1.class_id=serverKeygenInputImpl ++input.i2.class_id=subjectNameInputImpl ++input.i3.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=pkcs12OutputImpl ++policyset.list=userCertSet ++policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9 ++policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.userCertSet.1.constraint.name=Subject Name Constraint ++policyset.userCertSet.1.constraint.params.pattern=UID=.* ++policyset.userCertSet.1.constraint.params.accept=true ++policyset.userCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.userCertSet.1.default.name=Subject Name Default ++policyset.userCertSet.1.default.params.name= ++policyset.userCertSet.10.constraint.class_id=renewGracePeriodConstraintImpl ++policyset.userCertSet.10.constraint.name=Renewal Grace Period Constraint ++policyset.userCertSet.10.constraint.params.renewal.graceBefore=30 ++policyset.userCertSet.10.constraint.params.renewal.graceAfter=30 ++policyset.userCertSet.10.default.class_id=noDefaultImpl ++policyset.userCertSet.10.default.name=No Default ++policyset.userCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.userCertSet.2.constraint.name=Validity Constraint ++policyset.userCertSet.2.constraint.params.range=365 ++policyset.userCertSet.2.constraint.params.notBeforeCheck=false ++policyset.userCertSet.2.constraint.params.notAfterCheck=false ++policyset.userCertSet.2.default.class_id=validityDefaultImpl ++policyset.userCertSet.2.default.name=Validity Default ++policyset.userCertSet.2.default.params.range=180 ++policyset.userCertSet.2.default.params.startTime=0 ++policyset.userCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.userCertSet.3.constraint.name=Key Constraint ++policyset.userCertSet.3.constraint.params.keyType=RSA ++policyset.userCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.userCertSet.3.default.class_id=serverKeygenUserKeyDefaultImpl ++policyset.userCertSet.3.default.name=Server-Side Keygen Default ++policyset.userCertSet.3.default.params.keyType=RSA ++policyset.userCertSet.3.default.params.keySize=2048 ++policyset.userCertSet.4.constraint.class_id=noConstraintImpl ++policyset.userCertSet.4.constraint.name=No Constraint ++policyset.userCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.userCertSet.4.default.name=Authority Key Identifier Default ++policyset.userCertSet.5.constraint.class_id=noConstraintImpl ++policyset.userCertSet.5.constraint.name=No Constraint ++policyset.userCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.userCertSet.5.default.name=AIA Extension Default ++policyset.userCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.userCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.userCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.userCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.userCertSet.5.default.params.authInfoAccessCritical=false ++policyset.userCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.userCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.userCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.userCertSet.6.constraint.params.keyUsageCritical=true ++policyset.userCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.userCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.userCertSet.6.constraint.params.keyUsageDataEncipherment=false ++policyset.userCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.userCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.userCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.userCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.userCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.userCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.userCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.userCertSet.6.default.name=Key Usage Default ++policyset.userCertSet.6.default.params.keyUsageCritical=true ++policyset.userCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.userCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.userCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.userCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.userCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.userCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.userCertSet.6.default.params.keyUsageCrlSign=false ++policyset.userCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.userCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.userCertSet.7.constraint.class_id=noConstraintImpl ++policyset.userCertSet.7.constraint.name=No Constraint ++policyset.userCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.userCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.userCertSet.7.default.params.exKeyUsageCritical=false ++policyset.userCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4 ++policyset.userCertSet.8.constraint.class_id=noConstraintImpl ++policyset.userCertSet.8.constraint.name=No Constraint ++policyset.userCertSet.8.default.class_id=subjectAltNameExtDefaultImpl ++policyset.userCertSet.8.default.name=Subject Alt Name Constraint ++policyset.userCertSet.8.default.params.subjAltNameExtCritical=false ++policyset.userCertSet.8.default.params.subjAltExtType_0=RFC822Name ++policyset.userCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$ ++policyset.userCertSet.8.default.params.subjAltExtGNEnable_0=true ++policyset.userCertSet.8.default.params.subjAltNameNumGNs=1 ++policyset.userCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.userCertSet.9.constraint.name=No Constraint ++policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.userCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.userCertSet.9.default.name=Signing Alg ++policyset.userCertSet.9.default.params.signingAlg=- +diff --git a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template +index 666d20f..350cb9b 100644 +--- a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template ++++ b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template +@@ -109,6 +109,15 @@ if (isNaN(majorVersion)) { + majorVersion = parseInt(navigator.appVersion, 10); + } + ++function passwdValidate() ++{ ++ ++ if (document.forms[0].serverSideKeygenP12Passwd.value != document.forms[0].p12PasswordAgain.value) { ++ alert("Passwords do not match"); ++ return false; ++ } ++ return true; ++} + + function isIE() { + if ( "ActiveXObject" in window ) { +@@ -535,7 +544,7 @@ function setCRMFRequest() + } else if (typeof(crypto) != "undefined" && typeof(crypto.version) != "undefined") { + document.writeln('
'); + } else { +- document.writeln(''); ++ document.writeln(''); + } + + +@@ -741,6 +750,20 @@ for (var m = 0; m < inputPluginListSet.length; m++) { + document.writeln(''); + if (inputListSet[n].inputSyntax == 'string') { + document.writeln(''); ++ } else if (inputListSet[n].inputSyntax == 'server_side_keygen_request_type') { ++ // get PKCS#12 password ++ document.writeln(''); ++ document.write('PKCS #12 Password:'); ++ document.write(''); ++ document.writeln(''); ++ ++ document.writeln(''); ++ document.write('PKCS #12 Password again:'); ++ document.write(''); ++ document.writeln('  '); ++ document.writeln('  '); ++ document.writeln(''); ++ + } else if (inputListSet[n].inputSyntax == 'cert_request') { + document.writeln(''); + } else if (inputListSet[n].inputSyntax == 'cert_request_type') { +diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java +index 8efa3b7..1dace42 100644 +--- a/base/common/src/com/netscape/certsrv/apps/CMS.java ++++ b/base/common/src/com/netscape/certsrv/apps/CMS.java +@@ -1550,6 +1550,7 @@ public final class CMS { + name.equalsIgnoreCase("uPasswd") || + name.equalsIgnoreCase("PASSWORD_CACHE_ADD") || + name.startsWith("p12Password") || ++ name.startsWith("serverSideKeygenP12Passwd") || + name.equalsIgnoreCase("host_challenge") || + name.equalsIgnoreCase("card_challenge") || + name.equalsIgnoreCase("card_cryptogram") || +diff --git a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java +index e3ea69c..00d1040 100644 +--- a/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java ++++ b/base/common/src/com/netscape/certsrv/cert/CertEnrollmentRequest.java +@@ -57,10 +57,14 @@ public class CertEnrollmentRequest extends ResourceMessage { + private static final String PROFILE_ID = "profileId"; + private static final String RENEWAL = "renewal"; + private static final String SERIAL_NUM = "serial_num"; ++ private static final String SERVERSIDE_KEYGEN_P12_PASSWD = "serverSideKeygenP12Passwd"; + + @XmlElement(name="ProfileID") + protected String profileId; + ++ @XmlElement(name="ServerSideKeygenP12Passwd") ++ protected String serverSideKeygenP12Passwd; ++ + @XmlElement(name="Renewal") + protected boolean renewal; + +@@ -89,6 +93,8 @@ public class CertEnrollmentRequest extends ResourceMessage { + String renewalStr = form.getFirst(RENEWAL); + serialNum = new CertId(form.getFirst(SERIAL_NUM)); + renewal = new Boolean(renewalStr); ++ ++ serverSideKeygenP12Passwd = form.getFirst(SERVERSIDE_KEYGEN_P12_PASSWD); + } + + /** +@@ -213,6 +219,7 @@ public class CertEnrollmentRequest extends ResourceMessage { + if (serialNum != null) ret.put(SERIAL_NUM, serialNum.toHexString()); + if (remoteHost != null) ret.put("remoteHost", remoteHost); + if (remoteAddr != null) ret.put("remoteAddr", remoteAddr); ++ if (serverSideKeygenP12Passwd != null) ret.put(SERVERSIDE_KEYGEN_P12_PASSWD, serverSideKeygenP12Passwd); + + for (ProfileInput input: inputs) { + for (ProfileAttribute attr : input.getAttributes()) { +@@ -299,6 +306,9 @@ public class CertEnrollmentRequest extends ResourceMessage { + result = prime * result + ((remoteHost == null) ? 0 : remoteHost.hashCode()); + result = prime * result + (renewal ? 1231 : 1237); + result = prime * result + ((serialNum == null) ? 0 : serialNum.hashCode()); ++ ++//cfu? ++ result = prime * result + ((serverSideKeygenP12Passwd == null) ? 0 : serverSideKeygenP12Passwd.hashCode()); + return result; + } + +@@ -343,6 +353,11 @@ public class CertEnrollmentRequest extends ResourceMessage { + return false; + } else if (!serialNum.equals(other.serialNum)) + return false; ++ if (serverSideKeygenP12Passwd == null) { ++ if (other.serverSideKeygenP12Passwd != null) ++ return false; ++ } else if (!serverSideKeygenP12Passwd.equals(other.serverSideKeygenP12Passwd)) ++ return false; + return true; + } + +diff --git a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java +index 34543cb..8002540 100644 +--- a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java ++++ b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java +@@ -148,6 +148,12 @@ public interface IEnrollProfile extends IProfile { + public static final String REQUEST_ISSUED_CERT = "req_issued_cert"; + + /** ++ * Name of request attribute that stores the issued P12 from server-side keygen. ++ *

++ */ ++ public static final String REQUEST_ISSUED_P12 = "req_issued_p12"; ++ ++ /** + * Name of request attribute that stores the transport certificate. + *

+ * The value is of type String including base64 encoded certificate. +diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileData.java b/base/common/src/com/netscape/certsrv/profile/ProfileData.java +index 4b35fee..7d3623a 100644 +--- a/base/common/src/com/netscape/certsrv/profile/ProfileData.java ++++ b/base/common/src/com/netscape/certsrv/profile/ProfileData.java +@@ -313,4 +313,5 @@ public class ProfileData { + data.setXMLOutput(false); + } + +-} +\ No newline at end of file ++} ++ +diff --git a/base/common/src/com/netscape/certsrv/property/IDescriptor.java b/base/common/src/com/netscape/certsrv/property/IDescriptor.java +index 830ecdb..4de6bb3 100644 +--- a/base/common/src/com/netscape/certsrv/property/IDescriptor.java ++++ b/base/common/src/com/netscape/certsrv/property/IDescriptor.java +@@ -45,6 +45,8 @@ public interface IDescriptor { + public static String DUAL_KEYGEN_REQUEST_TYPE = "dual_keygen_request_type"; + public static String CERT_REQUEST = "cert_request"; + public static String CERT_REQUEST_TYPE = "cert_request_type"; ++ public static String SERVER_SIDE_KEYGEN_REQUEST_TYPE = "server_side_keygen_request_type"; ++ public static String SERVER_SIDE_KEYGEN_PKCS12 = "server_side_keygen_p12"; + public static String CHOICE = "choice"; // choice of strings + public static String DN = "dn"; + public static String IP = "ip"; +diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java +index cfc4ca0..47dde82 100644 +--- a/base/common/src/com/netscape/certsrv/request/IRequest.java ++++ b/base/common/src/com/netscape/certsrv/request/IRequest.java +@@ -197,6 +197,12 @@ public interface IRequest extends Serializable { + public static final String KEY_GEN_USAGES = "keyGenUsages"; + public static final String KEY_GEN_TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + ++ // Server-side Keygen enrollment ++ //public static final String SERVER_SIDE_KEYGEN_ENROLL = "serverSideKeygenEnroll"; ++ public static final String SSK_STAGE = "serverSideKeygenStage"; ++ public static final String SSK_STAGE_KEYGEN = "serverSideKeygenStage_keygen"; ++ public static final String SSK_STAGE_KEY_RETRIEVE = "serverSideKeygenStage_key_retrieve"; ++ + // requestor type values. + public static final String REQUESTOR_EE = "EE"; + public static final String REQUESTOR_RA = "RA"; +diff --git a/base/kra/src/com/netscape/kra/AsymKeyGenService.java b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +index 6571044..dca6ebc 100644 +--- a/base/kra/src/com/netscape/kra/AsymKeyGenService.java ++++ b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +@@ -19,6 +19,7 @@ package com.netscape.kra; + + import java.math.BigInteger; + import java.security.KeyPair; ++import java.util.Enumeration; + + import org.mozilla.jss.crypto.KeyPairGeneratorSpi; + import org.mozilla.jss.crypto.PrivateKey; +@@ -42,6 +43,7 @@ import com.netscape.certsrv.security.IStorageKeyUnit; + import com.netscape.cms.logging.Logger; + import com.netscape.cms.logging.SignedAuditLogger; + import com.netscape.cmscore.dbs.KeyRecord; ++import com.netscape.cmsutil.crypto.CryptoUtil; + + import netscape.security.util.WrappingParams; + +@@ -72,8 +74,24 @@ public class AsymKeyGenService implements IService { + + @Override + public boolean serviceRequest(IRequest request) throws EBaseException { ++ String method = "AsymKeyGenService:serviceRequest: "; + IConfigStore configStore = CMS.getConfigStore(); ++ ++ boolean isSSKeygen = false; ++ String isSSKeygenStr = request.getExtDataInString("isServerSideKeygen"); ++ if ((isSSKeygenStr != null) && isSSKeygenStr.equalsIgnoreCase("true")) { ++ CMS.debug(method + "isServerSideKeygen = true"); ++ isSSKeygen = true; ++ } else { ++ CMS.debug(method + "isServerSideKeygen = false"); ++ } ++ + String clientKeyId = request.getExtDataInString(IRequest.SECURITY_DATA_CLIENT_KEY_ID); ++ if (clientKeyId != null) ++ CMS.debug(method + "clientKeyId = " + clientKeyId); ++ else ++ CMS.debug(method + "clientKeyId not found"); ++ + String algorithm = request.getExtDataInString(IRequest.KEY_GEN_ALGORITHM); + + String keySizeStr = request.getExtDataInString(IRequest.KEY_GEN_SIZE); +@@ -159,6 +177,35 @@ public class AsymKeyGenService implements IService { + throw new EBaseException("Failed to generate asymmetric key!"); + } + ++ if (isSSKeygen) { ++ byte[] publicKeyData = null; ++ String pubKeyStr = ""; ++ try { ++ publicKeyData = kp.getPublic().getEncoded(); ++ if (publicKeyData == null) { ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ CMS.debug(method + " failed getting publickey encoded"); ++ return false; ++ } else { ++ //CMS.debug(method + "public key binary length ="+ publicKeyData.length); ++ if (algorithm.equals("EC")) { ++ /* url encode */ ++ pubKeyStr = com.netscape.cmsutil.util.Utils.SpecialEncode(publicKeyData); ++ CMS.debug(method + " EC pubKeyStr special encoded"); ++ } else { ++ pubKeyStr = CryptoUtil.base64Encode(publicKeyData); ++ } ++ ++ //CMS.debug(method + "public key length =" + pubKeyStr.length()); ++ request.setExtData("public_key", pubKeyStr); ++ } ++ } catch (Exception e) { ++ CMS.debug(method + e); ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ return false; ++ } ++ } ++ + byte[] privateSecurityData = null; + WrappingParams params = null; + +@@ -194,6 +241,7 @@ public class AsymKeyGenService implements IService { + record.set(KeyRecord.ATTR_STATUS, STATUS_ACTIVE); + record.set(KeyRecord.ATTR_KEY_SIZE, keySize); + request.setExtData(ATTR_KEY_RECORD, serialNo); ++ request.setExtData("serialNumber", serialNo); + + if (realm != null) { + record.set(KeyRecord.ATTR_REALM, realm); +@@ -212,7 +260,28 @@ public class AsymKeyGenService implements IService { + auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.SUCCESS, request.getRequestId(), + clientKeyId, new KeyId(serialNo), "None"); + request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS); ++ ++ if (isSSKeygen) { ++ ++ Enumeration ereq = request.getExtDataKeys(); ++ ++ /* cfu ++ CMS.debug(method + "let's find out what's in the request"); ++ while (ereq.hasMoreElements()) { ++ String reqKey = ereq.nextElement(); ++ String reqVal = request.getExtDataInString(reqKey); ++ if (reqVal != null) { ++ CMS.debug(method + reqKey + ": " + reqVal); ++ } else { ++ CMS.debug(method + reqKey + ": no value"); ++ } ++ } ++ */ ++ ++ request.setExtData("delayLDAPCommit", "false"); ++ } + kra.getRequestQueue().updateRequest(request); ++ + return true; + } + +diff --git a/base/kra/src/com/netscape/kra/KRAService.java b/base/kra/src/com/netscape/kra/KRAService.java +index f57b293..91ee5f9 100644 +--- a/base/kra/src/com/netscape/kra/KRAService.java ++++ b/base/kra/src/com/netscape/kra/KRAService.java +@@ -50,7 +50,7 @@ public class KRAService implements IService { + public final static String SECURITY_DATA_RECOVERY = IRequest.SECURITY_DATA_RECOVERY_REQUEST; + public final static String SYMKEY_GENERATION = IRequest.SYMKEY_GENERATION_REQUEST; + public final static String ASYMKEY_GENERATION = IRequest.ASYMKEY_GENERATION_REQUEST; +- ++ //public final static String SERVER_SIDE_KEYGEN_ENROLL = IRequest.SERVER_SIDE_KEYGEN_ENROLL; + + // private variables + private IKeyRecoveryAuthority mKRA = null; +diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java +index 96ee73b..4f2add9 100644 +--- a/base/kra/src/com/netscape/kra/RecoveryService.java ++++ b/base/kra/src/com/netscape/kra/RecoveryService.java +@@ -38,8 +38,12 @@ import org.mozilla.jss.asn1.SEQUENCE; + import org.mozilla.jss.asn1.SET; + import org.mozilla.jss.crypto.CryptoToken; + import org.mozilla.jss.crypto.EncryptionAlgorithm; ++import org.mozilla.jss.crypto.IVParameterSpec; ++import org.mozilla.jss.crypto.KeyWrapAlgorithm; ++import org.mozilla.jss.crypto.KeyWrapper; + import org.mozilla.jss.crypto.PBEAlgorithm; + import org.mozilla.jss.crypto.PrivateKey; ++import org.mozilla.jss.crypto.SymmetricKey; + import org.mozilla.jss.pkcs12.AuthenticatedSafes; + import org.mozilla.jss.pkcs12.CertBag; + import org.mozilla.jss.pkcs12.PFX; +@@ -85,8 +89,7 @@ import netscape.security.x509.X509Key; + * End Entity recovery will send RA or CA a response where stores the recovered key. + * + * @author thomask (original) +- * @author cfu (non-RSA keys; private keys secure handling); +- * @version $Revision$, $Date$ ++ * @author cfu (non-RSA keys; private keys secure handling; server-side keygen enrollment); + */ + public class RecoveryService implements IService { + +@@ -139,15 +142,69 @@ public class RecoveryService implements IService { + String tokName = ""; + CryptoToken ct = null; + Boolean allowEncDecrypt_recovery = false; ++ boolean isSSKeygen = false; ++ String serverKeygenP12Pass = null; + ++ X509Certificate transportCert = ++ request.getExtDataInCert(ATTR_TRANSPORT_CERT); ++ String transportCertNick = null; + try { + cm = CryptoManager.getInstance(); + config = CMS.getConfigStore(); + tokName = config.getString("kra.storageUnit.hardware", CryptoUtil.INTERNAL_TOKEN_NAME); ++ ++ // default to "KRA transport certificate" would require one to ++ // change the nickname for existing KRA transport cert ++ transportCertNick = config.getString("kra.cert.transport.nickname", "KRA transport certificate"); ++ CMS.debug("RecoveryService: serviceRequest: KRA transport cert nickname: " + transportCertNick); + CMS.debug("RecoveryService: serviceRequest: token: " + tokName); + ct = CryptoUtil.getCryptoToken(tokName); + + allowEncDecrypt_recovery = config.getBoolean("kra.allowEncDecrypt.recovery", false); ++ ++ String isSSKeygenStr = request.getExtDataInString("isServerSideKeygen"); ++ if (isSSKeygenStr != null && isSSKeygenStr.equalsIgnoreCase("true")) { ++ CMS.debug("RecoveryService: serviceRequest: isSSKengen=" + isSSKeygenStr); ++ isSSKeygen = true; ++ CryptoToken token = CryptoUtil.getKeyStorageToken("internal"); ++ ++ // serverKeygenP12Pass = request.getExtDataInString("serverSideKeygenP12Passwd"); ++ byte[] sessionWrappedPassphrase = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdEnc"); ++ byte[] transWrappedSessionKey = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdTransSession"); ++ ++ // unwrap session key ++ /* TODO: get nickname from config */ ++ org.mozilla.jss.crypto.X509Certificate transCert = ++ cm.findCertByNickname(transportCertNick); ++ PrivateKey transPrivateKey = ++ (org.mozilla.jss.crypto.PrivateKey) cm.findPrivKeyByCert(transCert); ++ if (transPrivateKey != null) ++ CMS.debug("RecoveryService: serviceRequest: found private key"); ++ ++ // key size and alg must match with serverKeygenUserKeyDefault.java ++ ++ SymmetricKey unwrappedSessionKey = ++ CryptoUtil.unwrap(token, SymmetricKey.AES, 128, ++ SymmetricKey.Usage.UNWRAP, ++ transPrivateKey, ++ transWrappedSessionKey, ++ KeyWrapAlgorithm.RSA); ++ ++ if (unwrappedSessionKey == null) ++ CMS.debug("RecoveryService: serviceRequest: unwrappedSessionKey null"); ++ ++ // decrypt p12 passphrase ++ EncryptionAlgorithm encryptAlgorithm = ++ EncryptionAlgorithm.AES_128_CBC_PAD; ++ byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; ++ IVParameterSpec ivps = new IVParameterSpec(iv); ++ byte[] passphrase = CryptoUtil.decryptUsingSymmetricKey(token, ++ ivps, sessionWrappedPassphrase, unwrappedSessionKey, ++ encryptAlgorithm); ++ serverKeygenP12Pass = new String(passphrase, "UTF-8"); ++ // TODO: do this after it's done being used later: ++ // CryptoUtil.obscureBytes(serverKeygenP12Pass, "random"); ++ } + } catch (Exception e) { + CMS.debug("RecoveryService exception: use internal token :" + + e.toString()); +@@ -173,8 +230,14 @@ public class RecoveryService implements IService { + request.getRequestId()); + + if (params == null) { +- // possibly we are in recovery mode +- return true; ++ //cfu ++ if (isSSKeygen) { ++ params = new Hashtable(); ++ params.put(RecoveryService.ATTR_TRANSPORT_PWD, serverKeygenP12Pass); ++ } else { ++ // possibly we are in recovery mode ++ return true; ++ } + } + + // retrieve based on serial no +@@ -185,6 +248,7 @@ public class RecoveryService implements IService { + statsSub.startTiming("get_key"); + } + KeyRecord keyRecord = (KeyRecord) mStorage.readKeyRecord(serialno); ++ + if (statsSub != null) { + statsSub.endTiming("get_key"); + } +@@ -221,8 +285,6 @@ public class RecoveryService implements IService { + + // Unwrap the archived private key + byte privateKeyData[] = null; +- X509Certificate transportCert = +- request.getExtDataInCert(ATTR_TRANSPORT_CERT); + + if (transportCert == null) { + if (statsSub != null) { +@@ -314,6 +376,14 @@ public class RecoveryService implements IService { + mKRA.getStorageKeyUnit().logout(); + } + } ++ ++ // cfu ++ if (isSSKeygen) { ++ CMS.debug("RecoveryService: putting p12 in request"); ++ byte[] p12b = (byte[])params.get(ATTR_PKCS12); ++ // IEnrollProfile.REQUEST_ISSUED_P12 ++ request.setExtData("req_issued_p12" /*ATTR_PKCS12*/, p12b); ++ } + mKRA.log(ILogger.LL_INFO, "key " + + serialno.toString() + + " recovered"); +@@ -540,7 +610,7 @@ public class RecoveryService implements IService { + pass, + /* NSS has a bug that causes any AES CBC encryption + * to use AES-256, but AlgorithmID contains chosen +- * alg. To avoid mismatch, use AES_256_CBC. */ ++ * alg. To avoid mismatch, use AES_128_CBC. */ + EncryptionAlgorithm.AES_256_CBC, + 0 /* iterations (use default) */, + priKey); +diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +index 6e1981f..2c539f0 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java ++++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +@@ -17,6 +17,9 @@ + // --- END COPYRIGHT BLOCK --- + package com.netscape.cms.profile.common; + ++import java.io.ByteArrayInputStream; ++import java.io.IOException; ++import java.security.cert.CertificateException; + import java.util.Enumeration; + + import org.mozilla.jss.pkix.crmf.PKIArchiveOptions; +@@ -40,7 +43,9 @@ import com.netscape.certsrv.request.RequestId; + import com.netscape.certsrv.request.RequestStatus; + import com.netscape.cms.logging.Logger; + import com.netscape.cms.logging.SignedAuditLogger; ++import com.netscape.cmsutil.crypto.CryptoUtil; + ++import netscape.security.x509.CertificateX509Key; + import netscape.security.x509.X500Name; + import netscape.security.x509.X509CertImpl; + import netscape.security.x509.X509CertInfo; +@@ -49,7 +54,7 @@ import netscape.security.x509.X509CertInfo; + * This class implements a Certificate Manager enrollment + * profile. + * +- * @version $Revision$, $Date$ ++ * @author cfu - Server-Side Keygen Enrollment implementation + */ + public class CAEnrollProfile extends EnrollProfile { + +@@ -77,7 +82,7 @@ public class CAEnrollProfile extends EnrollProfile { + + public void execute(IRequest request) + throws EProfileException, ERejectException { +- ++ String method = "CAEnrollProfile: execute: "; + long startTime = CMS.getCurrentDate().getTime(); + + if (!isEnable()) { +@@ -99,12 +104,78 @@ public class CAEnrollProfile extends EnrollProfile { + throw new EProfileException("No CA Service"); + } + ++ //cfu: if isServerSideKeygen, send keygen request to KRA ++ boolean isSSKeygen = false; ++ String isSSKeygenStr = request.getExtDataInString("isServerSideKeygen"); ++ if (isSSKeygenStr != null && isSSKeygenStr.equalsIgnoreCase("true")) { ++ CMS.debug(method + "isServerSideKeygen = true"); ++ isSSKeygen = true; ++ } else { ++ CMS.debug(method + "isServerSideKeygen = false"); ++ } ++ + // if PKI Archive Option present, send this request + // to DRM + byte optionsData[] = request.getExtDataInByteArray(REQUEST_ARCHIVE_OPTIONS); ++ if (isSSKeygen) { // cfu ++ request.setExtData(IRequest.SSK_STAGE, IRequest.SSK_STAGE_KEYGEN); ++ try { ++ IConnector kraConnector = caService.getKRAConnector(); ++ ++ if (kraConnector == null) { ++ String message = "KRA connector not configured"; ++ CMS.debug(method + message); ++ } else { ++ CMS.debug(method + "request"); ++ kraConnector.send(request); ++ ++ // check response ++ if (!request.isSuccess()) { ++ String message = "serverSide Keygen request failed"; ++ CMS.debug(method + message); ++ ++ if (getLocale(request) != null && ++ request.getError(getLocale(request)) != null) { ++ ++ if ((request.getError(getLocale(request))).equals(CMS.getUserMessage("CMS_KRA_INVALID_TRANSPORT_CERT"))) { //Todo ++ CMS.debug(method + "set request status: REJECTED"); ++ request.setRequestStatus(RequestStatus.REJECTED); ++ ca.getRequestQueue().updateRequest(request); ++ } ++ throw new ERejectException( ++ request.getError(getLocale(request))); ++ } else { ++ throw new ERejectException(CMS.getUserMessage("CMS_CA_SEND_KRA_REQUEST")+ " check KRA log for detail"); ++ } ++ } ++/* ++ signedAuditLogger.log(SecurityDataArchivalRequestEvent.createSuccessEvent( ++ auditSubjectID, ++ auditRequesterID, ++ requestId, ++ null)); ++*/ ++ } ++ } catch (Exception e) { ++ ++ CMS.debug(method + e); ++ ++/* ++ signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( ++ auditSubjectID, ++ auditRequesterID, ++ requestId, ++ null, ++ e)); ++*/ + +- // do not archive keys for renewal requests +- if ((optionsData != null) && (!request.getRequestType().equals(IRequest.RENEWAL_REQUEST))) { ++ if (e instanceof ERejectException) { ++ throw (ERejectException) e; ++ } ++ throw new EProfileException(e); ++ } ++ } else if ((optionsData != null) && (!request.getRequestType().equals(IRequest.RENEWAL_REQUEST))) { ++ // do not archive keys for renewal requests + PKIArchiveOptions options = toPKIArchiveOptions(optionsData); + + if (options != null) { +@@ -184,6 +255,29 @@ public class CAEnrollProfile extends EnrollProfile { + + // process certificate issuance + X509CertInfo info = request.getExtDataInCertInfo(REQUEST_CERTINFO); ++ ++ if (isSSKeygen) { // cfu ++ try { ++ String pubKeyStr = request.getExtDataInString("public_key"); ++ CMS.debug(method + "pubKeyStr = " + pubKeyStr); ++ byte[] pubKeyB = CryptoUtil.base64Decode(pubKeyStr); ++ CertificateX509Key certKey = new CertificateX509Key( ++ new ByteArrayInputStream(pubKeyB)); ++ Object oj = info.get(X509CertInfo.KEY); ++ if (oj != null) { ++ info.delete(X509CertInfo.KEY); ++ CMS.debug(method + " fake key deleted"); ++ } ++ info.set(X509CertInfo.KEY, certKey); ++ } catch (IOException e) { ++ CMS.debug(method + e); ++ throw new EProfileException(e); ++ } catch (CertificateException e) { ++ CMS.debug(method + e); ++ throw new EProfileException(e); ++ } ++ } ++ + // #615460 - added audit log (transaction) + SessionContext sc = SessionContext.getExistingContext(); + sc.put("profileId", getId()); +@@ -209,6 +303,75 @@ public class CAEnrollProfile extends EnrollProfile { + + request.setExtData(REQUEST_ISSUED_CERT, theCert); + ++ //cfu: cert issued, now retrieve p12 ++ if (isSSKeygen) { ++ CMS.debug(method + "onto SSK_STAGE_KEY_RETRIEVE"); ++ request.setExtData(IRequest.SSK_STAGE, IRequest.SSK_STAGE_KEY_RETRIEVE); ++ request.setExtData("requestType", "recovery"); ++ request.setExtData("cert", theCert); //recognized by kra ++ try { ++ IConnector kraConnector = caService.getKRAConnector(); ++ ++ if (kraConnector == null) { ++ String message = "KRA connector not configured"; ++ CMS.debug(method + message); ++ } else { ++ CMS.debug(method + "request"); ++ kraConnector.send(request); ++ ++ // check response ++ if (!request.isSuccess()) { ++ String message = "serverSide Keygen request failed"; ++ CMS.debug(method + message); ++ ++ if (getLocale(request) != null && ++ request.getError(getLocale(request)) != null) { ++ ++ if ((request.getError(getLocale(request))).equals(CMS.getUserMessage("CMS_KRA_INVALID_TRANSPORT_CERT"))) { //Todo ++ CMS.debug(method + "set request status: REJECTED"); ++ request.setRequestStatus(RequestStatus.REJECTED); ++ ca.getRequestQueue().updateRequest(request); ++ } ++ throw new ERejectException( ++ request.getError(getLocale(request))); ++ } else { ++ throw new ERejectException(CMS.getUserMessage("CMS_CA_SEND_KRA_REQUEST")+ " check KRA log for detail"); ++ } ++ } ++/* ++ signedAuditLogger.log(SecurityDataArchivalRequestEvent.createSuccessEvent( ++ auditSubjectID, ++ auditRequesterID, ++ requestId, ++ null)); ++*/ ++ } ++ } catch (Exception e) { ++ ++ CMS.debug(method + e); ++/* ++ signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( ++ auditSubjectID, ++ auditRequesterID, ++ requestId, ++ null, ++ e)); ++*/ ++ ++ if (e instanceof ERejectException) { ++ throw (ERejectException) e; ++ } ++ throw new EProfileException(e); ++ } ++ CMS.debug(method + "isSSKeygen: response received from KRA"); ++ byte p12bytes[] = request.getExtDataInByteArray("pkcs12"); ++ if (p12bytes != null) { ++ CMS.debug(method + "p12bytes not null"); ++ } else { ++ CMS.debug(method + "p12bytes null"); ++ } ++ } ++ + long endTime = CMS.getCurrentDate().getTime(); + + String initiative = AuditFormat.FROMAGENT +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +new file mode 100644 +index 0000000..e82ee24 +--- /dev/null ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +@@ -0,0 +1,385 @@ ++// --- 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) 2007 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.cms.profile.def; ++ ++import java.io.ByteArrayInputStream; ++import java.math.BigInteger; ++import java.security.interfaces.DSAParams; ++import java.util.Locale; ++import java.util.Vector; ++import java.security.KeyPair; ++import java.security.PublicKey; ++ ++import netscape.security.provider.DSAPublicKey; ++import netscape.security.provider.RSAPublicKey; ++import netscape.security.x509.AlgorithmId; ++import netscape.security.x509.CertificateX509Key; ++import netscape.security.x509.X509CertImpl; ++import netscape.security.x509.X509CertInfo; ++import netscape.security.x509.X509Key; ++ ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.IConfigStore; ++import com.netscape.certsrv.profile.EProfileException; ++import com.netscape.certsrv.profile.IEnrollProfile; ++import com.netscape.certsrv.profile.IProfile; ++import com.netscape.certsrv.property.Descriptor; ++import com.netscape.certsrv.property.EPropertyException; ++import com.netscape.certsrv.property.IDescriptor; ++import com.netscape.certsrv.request.IRequest; ++import com.netscape.cmsutil.crypto.CryptoUtil; ++import com.netscape.cmsutil.util.Utils; ++ ++import org.mozilla.jss.CryptoManager; ++import org.mozilla.jss.crypto.CryptoToken; ++import org.mozilla.jss.crypto.EncryptionAlgorithm; ++import org.mozilla.jss.crypto.IVParameterSpec; ++import org.mozilla.jss.crypto.KeyGenAlgorithm; ++import org.mozilla.jss.crypto.KeyWrapAlgorithm; ++import org.mozilla.jss.crypto.SymmetricKey; ++import org.mozilla.jss.crypto.X509Certificate; ++ ++/** ++ * This class implements an enrollment default policy ++ * for Server-Side keygen enrollment. ++ * It accepts usre-supplied key type and size to be passed onto KRA ++ * ++ * @author Christina Fu ++ */ ++public class ServerKeygenUserKeyDefault extends EnrollDefault { ++ ++ public static final String CONFIG_LEN = "keySize"; ++ public static final String CONFIG_TYPE = "keyType"; ++ public static final String VAL_LEN = "LEN"; ++ public static final String VAL_TYPE = "TYPE"; ++ ++ private static final String TEMP_PUBKEY_1024 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBz6H2rT2r1RpHdr3JyYr7thSjfwWPbIJ6U09NziHSekLsNZQKsjdLS/LPCfe/aXkhpzPztlx++tkPucpt/xT0exp08feAPIE+Y6gVoyXzEw+Ztz+Zez9Y1cQWxAyp7z11flytjL+4zBGDXmEoe3ZlQvij9DGypPjBC9PhWm0lBwIDAQAB"; ++ private static final String TEMP_PUBKEY_2048 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4Ha+CxWDPAHEl9+u57U3UCw8bfG/ZN3cVTrQgj/p8ak12NYUWt0ZI/xCcLj7gKwFPbNMTDwzizRPZuxKJT7fHgW8a1BQDUL2VGfx7O0A7KlLqcpVc6VKsQx5caP3hrB38Q5xnTKeVee9cBrd8An+veZ2QV6mHLEU8iMCN2No/t1oO+aYje42XloNRblXVQAOYW+3aMCam2kIKWUqLvA3Sbf2BPR2x5SSZRPHJt3hQCheara5j+nHLQ8paRvVlT+ghgyX5N3BwiPmvC+e9iUaaofj+DxrGX3cTo5hehG2b71sY3xdC5OIhEGRfkAqIAEw6eaU6a/ymNsByRgVByfQaQIDAQAB"; ++ private static final String TEMP_PUBKEY_3072 = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAm0yQ0y+8YOTWkye5qFuqNI/qC4wtjEjNnoZaqSZUOJLg6ZRDlsZoOiblJpw65rPjaPcSp/inqYfCCA5mISYaqfcoB80LCnw1+DAv8tcvwUtytQYXHVj2gbyuVHaBgD4n4j/wFV80sF3OTQcPKYmeTfWRtv2xZQMK9rYfa8Le+DAZyOWPk4+RtTIRPa5R9arLqE+ONgUcrD3NvewOdsCrT7flJnFdx8TGl5ftxVWYlHRSg+wEB8pQZlw0BSDlQGHXIRjBKT2+iCkYzuKPWpMbu42PnBaQTcvjD3cl8MjLQcZp6v39bU1Du0C0LYunhvIWidwKnCOGOYu+a0VKuHxH8odjFdPoWGmP+orllkwSZzhWayYJxGpJJQlWcM05uD6qDF67WQnuYsliVH4LNiSjf/iPSpr0tzDXOtdeVsiQgO9wYYlnooBtd1xfTmkILwt3j9ZXeBtmt4lLYxbLo2ZCzkFqCCdu5FfcFgxjPaRaW0bQHKuP1woGk0rDUUbuqr+PAgMBAAE="; ++ private static final String TEMP_PUBKEY_4096 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs3xoddtoCQrDpPK/45DpN/wPHO/6qrsbEDnwEnSkcLz51WHb7+CEUP9oxuE8vPn9JXcLdZkgPcmfMVibSUEJVUCXPibGTqAJ/7RAAm+/FhdL02N57hpgLzbIPbIaTP00z/jbTqR4a0uV49fnEPqrhA/KoUmOn3eoiAPAB5xNSauFOmMZXv2gr4akNxvSiZ/59ddYF+DBEFSs4ufCqIqBWYAMMo78eskgm/ZUyv7OZzG+8c1nncdnrNk/JtXauANu8NUQXX2qllmEOioY6gnalpR26fwOscjkvHDTvRQmSIqceWdd5P6OMHJwzTVG8d4b0f150o1RTzU3gvg9/qXvbOGcnH2TXZjYi02mhyXgPrimZepKyDr2LjeAEZbfAAXecaMhjrDZEkDZNFWe4eoG2JuE34TODeiCLMBql6VTgOvCFW3to32aBwNLpCV4hi5rKLnPMlf8Tz0zYvGqDeCp4zzy6C9tosiYfHIkVU/AVqK9PoY0RsLnBzHOV7Jl2VgHr8Ro+C66+leajssAemK8swcj2AZEOuVLlsdCvguUn6XUyDqI3tIfnoLK690hG1znuIWzFZzzivZ5ZwgfxguCly9zDArc7i6YHxOR2lcUrM0VfHmyHpE9JNfarEgAPS59ASG7y14LOvp4yYKNz10TtetwkSfpcjqiuWHtIDi9sjMCAwEAAQ=="; ++ ++ public ServerKeygenUserKeyDefault() { ++ super(); ++ addConfigName(CONFIG_TYPE); ++ addConfigName(CONFIG_LEN); ++ addValueName(VAL_TYPE); ++ addValueName(VAL_LEN); ++ } ++ ++ public void init(IProfile profile, IConfigStore config) ++ throws EProfileException { ++ super.init(profile, config); ++ } ++ ++/* ++ public void setConfig(String name, String value) ++ throws EPropertyException { ++ super.setConfig(name, value); ++ } ++*/ ++ ++ public IDescriptor getConfigDescriptor(Locale locale, String name) { ++ if (name.equals(CONFIG_TYPE)) { ++ return new Descriptor(IDescriptor.STRING, ++ null, ++ "RSA", ++ CMS.getUserMessage(locale, ++ "CMS_PROFILE_SERVER_KEYGEN_KEYTYPE")); ++ } else if (name.equals(CONFIG_LEN)) { ++ return new Descriptor(IDescriptor.STRING, ++ null, ++ "2048", ++ CMS.getUserMessage(locale, ++ "CMS_PROFILE_SERVER_KEYGEN_KEYSIZE")); ++ } else { ++ return null; ++ } ++ } ++ ++ public IDescriptor getValueDescriptor(Locale locale, String name) { ++ if (name.equals(VAL_LEN)) { ++ return new Descriptor(IDescriptor.STRING, ++ IDescriptor.READONLY, ++ null, ++ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_LEN")); ++ } else if (name.equals(VAL_TYPE)) { ++ return new Descriptor(IDescriptor.STRING, ++ IDescriptor.READONLY, ++ null, ++ CMS.getUserMessage(locale, "CMS_PROFILE_KEY_TYPE")); ++ } else { ++ return null; ++ } ++ } ++ ++ public void setValue(String name, Locale locale, ++ X509CertInfo info, String value) ++ throws EPropertyException { ++ // this default rule is readonly ++ } ++ ++ public String getValue(String name, Locale locale, ++ X509CertInfo info) ++ throws EPropertyException { ++ CMS.debug("ServerKeygenUserKeyDefault: getValue name=" + name); ++ if (name == null) { ++ throw new EPropertyException(CMS.getUserMessage( ++ locale, "CMS_INVALID_PROPERTY", name)); ++ } ++ ++ if (name.equals(VAL_LEN)) { ++ CertificateX509Key ck = null; ++ ++ try { ++ ck = (CertificateX509Key) ++ info.get(X509CertInfo.KEY); ++ } catch (Exception e) { ++ // nothing ++ } ++ X509Key k = null; ++ ++ try { ++ k = (X509Key) ++ ck.get(CertificateX509Key.KEY); ++ } catch (Exception e) { ++ // nothing ++ } ++ if (k == null) { ++ throw new EPropertyException(CMS.getUserMessage( ++ locale, "CMS_PROFILE_KEY_NOT_FOUND")); ++ } ++ try { ++ if (k.getAlgorithm().equals("RSA")) { ++ return Integer.toString(getRSAKeyLen(k)); ++ } else if (k.getAlgorithm().equals("EC")) { ++ Vector vect = CryptoUtil.getECKeyCurve(k); ++ if (vect != null) ++ return vect.toString(); ++ else ++ return null; ++ } else { ++ return Integer.toString(getDSAKeyLen(k)); ++ } ++ } catch (Exception e) { ++ CMS.debug("ServerKeygenUserKeyDefault: getValue " + e.toString()); ++ throw new EPropertyException(CMS.getUserMessage( ++ locale, "CMS_INVALID_PROPERTY", name)); ++ } ++ } else if (name.equals(VAL_TYPE)) { ++ CertificateX509Key ck = null; ++ ++ try { ++ ck = (CertificateX509Key) ++ info.get(X509CertInfo.KEY); ++ } catch (Exception e) { ++ // nothing ++ } ++ X509Key k = null; ++ ++ try { ++ k = (X509Key) ++ ck.get(CertificateX509Key.KEY); ++ } catch (Exception e) { ++ // nothing ++ } ++ if (k == null) { ++ throw new EPropertyException(CMS.getUserMessage( ++ locale, "CMS_PROFILE_KEY_NOT_FOUND")); ++ } ++ return k.getAlgorithm() + " - " + ++ k.getAlgorithmId().getOID().toString(); ++ } else { ++ throw new EPropertyException(CMS.getUserMessage( ++ locale, "CMS_INVALID_PROPERTY", name)); ++ } ++ } ++ ++ public String getText(Locale locale) { ++ String params[] = { ++ getConfig(CONFIG_TYPE), ++ getConfig(CONFIG_LEN) ++ }; ++ CMS.debug("ServerKeygenUserKeyDefault: getText "); ++ if (locale == null) ++ CMS.debug("ServerKeygenUserKeyDefault: getText: locale null "); ++ ++ return CMS.getUserMessage(locale, "CMS_PROFILE_DEF_SERVER_KEYGEN_USER_KEY_INFO", params); ++ } ++ ++ public int getRSAKeyLen(X509Key key) throws Exception { ++ X509Key newkey = null; ++ ++ try { ++ newkey = new X509Key(AlgorithmId.get("RSA"), ++ key.getKey()); ++ } catch (Exception e) { ++ CMS.debug("ServerKeygenUserKeyDefault: getRSAKey " + e.toString()); ++ throw e; ++ } ++ RSAPublicKey rsaKey = new RSAPublicKey(newkey.getEncoded()); ++ ++ return rsaKey.getKeySize(); ++ } ++ ++ public int getDSAKeyLen(X509Key key) throws Exception { ++ // Check DSAKey parameters. ++ // size refers to the p parameter. ++ DSAPublicKey dsaKey = new DSAPublicKey(key.getEncoded()); ++ DSAParams keyParams = dsaKey.getParams(); ++ BigInteger p = keyParams.getP(); ++ int len = p.bitLength(); ++ ++ return len; ++ } ++ ++ /** ++ * Populates the request with this policy default. ++ */ ++ public void populate(IRequest request, X509CertInfo info) ++ throws EProfileException { ++ CertificateX509Key certKey = null; ++ String method = "ServerKeygenUserKeyDefault: populate: "; ++ CMS.debug(method + "in here"); ++ ++ // trigger serverSide keygen enrollment ++ try { ++ // Todo: remove debug test print; encrypt the passwd ++ String p12passwd = request.getExtDataInString("serverSideKeygenP12Passwd"); ++ if (p12passwd == null || p12passwd.length() == 0) { ++ CMS.debug(method + "p12passwd not found"); ++ throw new EPropertyException(CMS.getUserMessage("CMS_PASSWORD_EMPTY_PASSWORD")); ++ } ++ ++ // Encrypt the password before putting it back in ++ String transportCertStr = null; ++ CryptoManager cm = CryptoManager.getInstance(); ++ org.mozilla.jss.crypto.X509Certificate transCert = null; ++ try { ++ transCert = cm.findCertByNickname("KRA Transport Certificate"); ++ } catch (Exception e) { ++ CMS.debug(method + "'KRA transport certificate' not found in nssdb; need to be manually setup for Server-Side keygen enrollment"); ++ throw new EPropertyException(CMS.getUserMessage("CMS_MISSING_KRA_TRANSPORT_CERT_IN_CA_NSSDB")); ++ ++ /* future; cert nickname can't be controlled yet at import in jss ++ CMS.debug(method + "KRA transport certificate not found in nssdb; getting from CS.cfg"); ++ transportCertStr = CMS.getConfigStore().getString("ca.connector.KRA.transportCert", ""); ++ CMS.debug(method + "transportCert found in CS.cfg: " + transportCertStr); ++ ++ byte[] transportCertB = Utils.base64decode(transportCertStr); ++ CMS.debug(method + "transportCertB.length=" + transportCertB.length); ++ // hmmm, can't yet control the nickname ++ transCert = cm.importCACertPackage(transportCertB); ++ CMS.debug(method + "KRA transport certificate imported"); ++ */ ++ } ++ ++ { ++ // todo: make things configurable in CS.cfg or profile ++ CryptoToken ct = ++ CryptoUtil.getCryptoToken(CryptoUtil.INTERNAL_TOKEN_NAME); ++ if (ct == null) ++ CMS.debug(method + "crypto token null"); ++ ++ EncryptionAlgorithm encryptAlgorithm = ++ EncryptionAlgorithm.AES_128_CBC_PAD; ++ KeyWrapAlgorithm wrapAlgorithm = KeyWrapAlgorithm.RSA; ++ ++ SymmetricKey sessionKey = CryptoUtil.generateKey( ++ ct, ++ KeyGenAlgorithm.AES, ++ 128, ++ null, ++ true); ++ ++ byte[] iv = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; ++ byte[] sessionWrappedPassphrase = CryptoUtil.encryptUsingSymmetricKey( ++ ct, ++ sessionKey, ++ p12passwd.getBytes("UTF-8"), ++ encryptAlgorithm, ++ new IVParameterSpec(iv)); ++ ++ CMS.debug(method + "sessionWrappedPassphrase.length=" + sessionWrappedPassphrase.length); ++ ++ byte[] transWrappedSessionKey = CryptoUtil.wrapUsingPublicKey( ++ ct, ++ transCert.getPublicKey(), ++ sessionKey, ++ wrapAlgorithm); ++ CMS.debug(method + " transWrappedSessionKey.length =" +transWrappedSessionKey.length); ++ ++ // store in request to pass to kra ++ request.setExtData("serverSideKeygenP12PasswdEnc", ++ sessionWrappedPassphrase); ++ request.setExtData("serverSideKeygenP12PasswdTransSession", ++ transWrappedSessionKey); ++ // delete the plain text one ++ request.deleteExtData("serverSideKeygenP12Passwd"); ++ } ++ ++ // ++ request.setExtData("isServerSideKeygen", "true"); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ ++ String keySizeStr = request.getExtDataInString("keySize"); ++ int keySize = 1024; ++ if (keySizeStr != null) { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request: " + keySizeStr); ++ keySize = Integer.parseInt(keySizeStr); ++ } else { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request null; default to 2048"); ++ } ++ request.setExtData(IRequest.KEY_GEN_ALGORITHM, "RSA"); ++ request.setExtData(IRequest.KEY_GEN_SIZE, keySize); ++ ++ /* ++ * it is necessary to put in a static fake key here to prevent ++ * issue; The fake key will be replaced later once KRA generates ++ * the real keys ++ */ ++ String pubKeyStr = ""; ++ switch (keySize) { ++ case 1024: ++ pubKeyStr = TEMP_PUBKEY_1024; ++ break; ++ case 2048: ++ pubKeyStr = TEMP_PUBKEY_2048; ++ break; ++ case 3072: ++ pubKeyStr = TEMP_PUBKEY_3072; ++ break; ++ case 4096: ++ pubKeyStr = TEMP_PUBKEY_4096; ++ break; ++ default: ++ CMS.debug("ServerKeygenUserKeyDefault: populate: unsupported keySize: " + keySize); ++ break; ++ } ++ byte[] certKeyData = CryptoUtil.base64Decode(pubKeyStr); ++ if (certKeyData != null) { ++ certKey = new CertificateX509Key( ++ new ByteArrayInputStream(certKeyData)); ++ } else { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: serverKeygen to be implemented "); ++ } ++ info.set(X509CertInfo.KEY, certKey); ++ } catch (Exception e) { ++ CMS.debug("ServerKeygenUserKeyDefault: populate " + e.toString()); ++ } ++ } ++} +diff --git a/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java +new file mode 100644 +index 0000000..fb460d0 +--- /dev/null ++++ b/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java +@@ -0,0 +1,115 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.cms.profile.input; ++ ++import java.util.Locale; ++import java.util.Map; ++ ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.IConfigStore; ++import com.netscape.certsrv.profile.EProfileException; ++import com.netscape.certsrv.property.Descriptor; ++import com.netscape.certsrv.property.IDescriptor; ++import com.netscape.certsrv.request.IRequest; ++import com.netscape.certsrv.profile.IProfile; ++import com.netscape.certsrv.profile.IProfileContext; ++import com.netscape.certsrv.profile.IProfileInput; ++ ++/** ++ * This class implements input for the Server-Side Keygen Enrollment ++ *

++ * ++ * @author Christina Fu ++ */ ++public class ServerKeygenInput extends EnrollInput implements IProfileInput { ++ ++ public static final String P12PASSWORD = "serverSideKeygenP12Passwd"; ++/* ++ public static final String KEY_TYPE = "keyType"; ++ public static final String KEY_SIZE = "keySize"; ++*/ ++ ++ public ServerKeygenInput() { ++ addValueName(P12PASSWORD); ++/* ++ addValueName(KEY_TYPE); ++ addValueName(KEY_SIZE); ++*/ ++ } ++ ++ /** ++ * Initializes this default policy. ++ */ ++ public void init(IProfile profile, IConfigStore config) ++ throws EProfileException { ++ super.init(profile, config); ++ } ++ ++ /** ++ * Retrieves the localizable name of this policy. ++ */ ++ public String getName(Locale locale) { ++ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERVER_KEYGEN_NAME"); ++ } ++ ++ /** ++ * Retrieves the localizable description of this policy. ++ */ ++ public String getText(Locale locale) { ++ return CMS.getUserMessage(locale, "CMS_PROFILE_INPUT_SERVER_KEYGEN_TEXT"); ++ } ++ ++ public String getConfig(String name) { ++ String config = super.getConfig(name); ++ if (config == null || config.equals("")) ++ return "true"; ++ return config; ++ } ++ ++ /** ++ * Populates the request with this policy default. ++ */ ++ public void populate(IProfileContext ctx, IRequest request) ++ throws EProfileException { ++ // ++ CMS.debug("ServerKeygenP12PasswordInput:populate: cfu"); ++ } ++ ++ /** ++ * Retrieves the descriptor of the given value ++ * parameter by name. ++ */ ++ public IDescriptor getValueDescriptor(Locale locale, String name) { ++ if (name.equals(P12PASSWORD)) { ++ return new Descriptor(IDescriptor.SERVER_SIDE_KEYGEN_REQUEST_TYPE, null, ++ null, ++ CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_P12PASSWD")); ++/* ++ } else if (name.equals(KEY_TYPE)) { ++ return new Descriptor(IDescriptor.STRING, null, ++ null, ++ CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_KEY_TYPE")); ++ } else if (name.equals(KEY_SIZE)) { ++ return new Descriptor(IDescriptor.STRING, null, ++ null, ++ CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_KEY_SIZE")); ++*/ ++ } ++ return null; ++ } ++} +diff --git a/base/server/cms/src/com/netscape/cms/profile/output/PKCS12Output.java b/base/server/cms/src/com/netscape/cms/profile/output/PKCS12Output.java +new file mode 100644 +index 0000000..837fdc9 +--- /dev/null ++++ b/base/server/cms/src/com/netscape/cms/profile/output/PKCS12Output.java +@@ -0,0 +1,110 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.cms.profile.output; ++ ++import java.io.ByteArrayOutputStream; ++import java.security.cert.X509Certificate; ++import java.util.Locale; ++import java.util.Map; ++ ++import org.mozilla.jss.asn1.INTEGER; ++import org.mozilla.jss.netscape.security.util.Utils; ++import org.mozilla.jss.netscape.security.x509.CertificateChain; ++import org.mozilla.jss.netscape.security.x509.X509CertImpl; ++ ++import com.netscape.certsrv.ca.ICertificateAuthority; ++import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.profile.EProfileException; ++import com.netscape.certsrv.profile.IProfile; ++import com.netscape.certsrv.profile.IProfileContext; ++import com.netscape.certsrv.profile.IProfileOutput; ++import com.netscape.certsrv.property.Descriptor; ++import com.netscape.certsrv.property.IDescriptor; ++import com.netscape.certsrv.request.IRequest; ++import com.netscape.cms.profile.common.EnrollProfile; ++import com.netscape.cmsutil.crypto.CryptoUtil; ++ ++/** ++ * This class implements the output plugin that outputs ++ * PKCS12 response for the issued certificate for Server-side keygen enrollment. ++ * ++ * Christina Fu ++ */ ++public class PKCS12Output extends EnrollOutput { ++ ++ public static final String VAL_P12_RESPONSE = "p12_response"; ++ ++ public PKCS12Output() { ++ addValueName(VAL_P12_RESPONSE); ++ } ++ ++ /** ++ * Retrieves the localizable name of this policy. ++ */ ++ public String getName(Locale locale) { ++ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_PKCS12"); ++ } ++ ++ /** ++ * Retrieves the localizable description of this policy. ++ */ ++ public String getText(Locale locale) { ++ return CMS.getUserMessage(locale, "CMS_PROFILE_OUTPUT_PKCS12_TEXT"); ++ } ++ ++ /** ++ * Populates the request with this policy default. ++ */ ++ public void populate(IProfileContext ctx, IRequest request) ++ throws EProfileException { ++ } ++ ++ /** ++ * Retrieves the descriptor of the given value ++ * parameter by name. ++ */ ++ public IDescriptor getValueDescriptor(Locale locale, String name) { ++ if (name.equals(VAL_P12_RESPONSE)) { ++ return new Descriptor(IDescriptor.SERVER_SIDE_KEYGEN_PKCS12, null, ++ null, ++ CMS.getUserMessage(locale, ++ "CMS_PROFILE_OUTPUT_PKCS12")); ++ } ++ return null; ++ } ++ ++ public String getValue(String name, Locale locale, IRequest request) ++ throws EProfileException { ++ ++ if (name.equals(VAL_P12_RESPONSE)) { ++ try { ++ byte pkcs12[] = request.getExtDataInByteArray( ++ EnrollProfile.REQUEST_ISSUED_P12); ++ if (pkcs12 != null) { ++ CMS.debug("PKCS12Output:getValue: found p12"); ++ String pkcs12Str = Utils.base64encodeSingleLine(pkcs12); ++ return pkcs12Str; ++ } ++ } catch (Exception e) { ++ return null; ++ } ++ } ++ return null; ++ } ++ ++} +diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java +index 0c65702..145fd5f 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java +@@ -573,6 +573,7 @@ public abstract class CMSServlet extends HttpServlet { + + protected void outputArgBlockAsXML(XMLObject xmlObj, Node parent, + String argBlockName, IArgBlock argBlock) { ++ CMS.debug("CMSServlet:outputArgBlockAsXML: begins"); + Node argBlockContainer = xmlObj.createContainer(parent, argBlockName); + + if (argBlock != null) { +@@ -584,9 +585,11 @@ public abstract class CMSServlet extends HttpServlet { + xmlObj.addItemToContainer(argBlockContainer, name, val); + } + } ++ CMS.debug("CMSServlet:outputArgBlockAsXML: ends"); + } + + protected void outputXML(HttpServletResponse httpResp, CMSTemplateParams params) { ++ CMS.debug("CMSServlet:outputXML: begins"); + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); +@@ -613,6 +616,7 @@ public abstract class CMSServlet extends HttpServlet { + } catch (Exception e) { + CMS.debug("failed in outputing XML " + e); + } ++ CMS.debug("CMSServlet:outputXML: ends"); + } + + protected void renderTemplate( +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +index 8741a75..b369fc8 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +@@ -28,6 +28,7 @@ import java.security.cert.Certificate; + import java.security.cert.CertificateException; + import java.security.cert.X509Certificate; + import java.util.Enumeration; ++import java.util.Hashtable; + + import javax.servlet.ServletConfig; + import javax.servlet.ServletException; +@@ -62,6 +63,7 @@ import com.netscape.certsrv.request.RequestId; + import com.netscape.certsrv.request.RequestStatus; + import com.netscape.cms.servlet.base.CMSServlet; + import com.netscape.cms.servlet.common.CMSRequest; ++//import com.netscape.kra.RecoveryService; + + import netscape.security.x509.CRLExtensions; + import netscape.security.x509.CRLReasonExtension; +@@ -81,7 +83,7 @@ import netscape.security.x509.X509CertInfo; + * process requests from remote authority - + * service request or return status. + * +- * @version $Revision$, $Date$ ++ * @author cfu - Server-Side Keygen Enrollment implementation + */ + public class ConnectorServlet extends CMSServlet { + +@@ -506,8 +508,27 @@ public class ConnectorServlet extends CMSServlet { + } + } + +- // if not found process request. ++/* ++ // cfu: let's find out what's in the request ++ Enumeration ereq = thisreq.getExtDataKeys(); ++ ++ while (ereq.hasMoreElements()) { ++ String reqKey = ereq.nextElement(); ++ String reqVal = thisreq.getExtDataInString(reqKey); ++ if (reqVal != null) { ++ CMS.debug("ConnectorServlet: - " + reqKey + ": " + reqVal); ++ } else { ++ CMS.debug("ConnectorServlet: - " + reqKey + ": no value"); ++ } ++ } ++*/ ++ + thisreq = queue.newRequest(msg.getReqType()); ++ // if not found process request. ++/*cfu ++ CMS.debug("ConnectorServlet: created reqType=" +msg.getReqType()+ ++ " requestId=" + thisreq.getRequestId().toString() + " requestStatus=" + thisreq.getRequestStatus().toString()); ++*/ + CMS.debug("ConnectorServlet: created requestId=" + + thisreq.getRequestId().toString()); + thisreq.setSourceId(srcid); +@@ -520,6 +541,29 @@ public class ConnectorServlet extends CMSServlet { + // own special try/catch block. + msg.toRequest(thisreq); + ++ boolean isSSKeygen = false; ++ String isSSKeygenStr = thisreq.getExtDataInString("isServerSideKeygen"); ++ if ((isSSKeygenStr != null) && isSSKeygenStr.equalsIgnoreCase("true")) { ++ String method = "ConnectorServlet:isServerSideKeygen: "; ++ CMS.debug("ConnectorServlet:isServerSideKeygen = true"); ++ isSSKeygen = true; ++ String sskKeygenStage = thisreq.getExtDataInString(IRequest.SSK_STAGE); ++ if (sskKeygenStage!= null && sskKeygenStage.equalsIgnoreCase(IRequest.SSK_STAGE_KEYGEN)) { ++ CMS.debug(method + "Stage=" + sskKeygenStage); ++ thisreq.setRequestType("asymkeyGenRequest"); //IRequest.ASYMKEY_GENERATION_REQUEST ++ } else if (sskKeygenStage.equalsIgnoreCase(IRequest.SSK_STAGE_KEY_RETRIEVE)) { ++ CMS.debug(method + "Stage=" + sskKeygenStage); ++ thisreq.setRequestType("recovery"); //IRequest.KEYRECOVERY_REQUEST ++ } ++ String clientKeyId = thisreq.getExtDataInString(IRequest.SECURITY_DATA_CLIENT_KEY_ID); ++ if (clientKeyId != null) ++ CMS.debug(method + "clientKeyId = " + clientKeyId); ++ else ++ CMS.debug(method + "clientKeyId not found"); ++ } else { ++ CMS.debug("ConnectorServlet:isServerSideKeygen = false"); ++ } ++ + if (isProfileRequest(thisreq)) { + X509CertInfo info = + thisreq.getExtDataInCertInfo( +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +index 00fcbb3..ea2183f 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +@@ -18,6 +18,8 @@ + package com.netscape.cms.servlet.profile; + + import java.util.Locale; ++import java.io.IOException; ++import java.io.OutputStream; + + import javax.servlet.ServletConfig; + import javax.servlet.ServletException; +@@ -47,6 +49,8 @@ import com.netscape.cms.servlet.cert.RequestProcessor; + import com.netscape.cms.servlet.common.CMSRequest; + import com.netscape.cms.servlet.common.CMSTemplate; + ++import org.mozilla.jss.netscape.security.util.Utils; ++ + /** + * This servlet approves profile-based request. + * +@@ -170,7 +174,32 @@ public class ProfileProcessServlet extends ProfileServlet { + args.set(ARG_OUTPUT_LIST, outputlist); + } + +- outputTemplate(request, response, args); ++ try { //cfu ++ CMS.debug("ProfileProcessServlet:cfu: p12 output process begins"); ++ String p12Str = req.getExtDataInString("req_issued_p12"); ++ if (p12Str == null) { ++ // not server-side keygen ++ CMS.debug("ProfileProcessServlet:cfu: no p12; not server-side keygen"); ++ outputTemplate(request, response, args); ++ } else { ++ // found pkcs12 blob ++ byte[] p12blob = null; ++ HttpServletResponse p12_response = cmsReq.getHttpResp(); ++ CMS.debug("ProfileProcessServlet:cfu: found p12 =" + ++ p12Str/*ing.toString()*/); ++ p12blob = Utils.base64decode(p12Str/*ing.toString()*/); ++ OutputStream bos = p12_response.getOutputStream(); ++ p12_response.setContentType("application/x-pkcs12"); ++ p12_response.setContentLength(p12blob.length); ++ bos.write(p12blob); ++ bos.flush(); ++ bos.close(); ++ } ++ } catch (IOException e) { ++ CMS.debug(e); ++ setError(args, e.getMessage(), request, response); ++ return; ++ } + } + + private void setError(ArgSet args, String reason, HttpServletRequest request, HttpServletResponse response) +diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties +index e5e6ecc..608d29a 100644 +--- a/base/server/cmsbundle/src/UserMessages.properties ++++ b/base/server/cmsbundle/src/UserMessages.properties +@@ -79,6 +79,7 @@ CMS_BASE_INVALID_PROPERTY=Cannot convert property {0} + CMS_BASE_INVALID_PROPERTY_1=Cannot convert value of property {0} to a {1}. Expected format is {2} + CMS_BASE_LOAD_FAILED=Failed to load {0} + CMS_BASE_LOAD_FAILED_1=Failed to load {0}. Error {1} ++CMS_MISSING_KRA_TRANSPORT_CERT_IN_CA_NSSDB=KRA Transport Certificate needs to be imported into the CA nssdb for Server-Side Kegen Enrollment + CMS_BASE_PERMISSION_DENIED=Permission denied + CMS_BASE_INVALID_ATTRIBUTE=Invalid attribute {0} + CMS_BASE_REQUEST_IN_BAD_STATE=Request is in a bad state +@@ -843,6 +844,8 @@ CMS_PROFILE_VALIDITY_NOT_BEFORE_GRACE_PERIOD=Grace period for Not Before being s + CMS_PROFILE_VALIDITY_RANGE=Validity Range + CMS_PROFILE_VALIDITY_RANGE_UNIT=Validity Range Unit: year, month, day (default), hour, minute + CMS_PROFILE_VALIDITY_START_TIME=Relative Start Time (in seconds) ++CMS_PROFILE_SERVER_KEYGEN_KEYTYPE=Server-side keygen key type ++CMS_PROFILE_SERVER_KEYGEN_KEYSIZE=Server-side keygen key size + CMS_PROFILE_NOT_BEFORE_RANDOM_BITS=Not Before Random Bits + CMS_PROFILE_NOT_AFTER_RANDOM_BITS=Not After Random Bits + CMS_PROFILE_BYPASS_CA_NOTAFTER=Bypass CA notAfter constraint +@@ -998,6 +1001,7 @@ CMS_PROFILE_DEF_INHIBIT_ANY_POLICY_EXT=This default populates an Inhibit Any-Pol + CMS_PROFILE_INHIBIT_ANY_POLICY_WRONG_SKIP_CERTS=The value for skipped certificates must be an integer. + CMS_PROFILE_DEF_USER_EXT=This default populates a User-Supplied Extension ({0}) to the request. + CMS_PROFILE_DEF_USER_KEY=This default populates a User-Supplied Certificate Key to the request. ++CMS_PROFILE_DEF_SERVER_KEYGEN_USER_KEY_INFO=This default triggers server-side keygen and then populates the Certificate Key to the request. + CMS_PROFILE_DEF_USER_SIGNING_ALGORITHM=This default populates a User-Supplied Certificate Signing Algorithm to the request. + CMS_PROFILE_DEF_AUTHZ_REALM=This default populates an authorization realm. + CMS_PROFILE_DEF_USER_SUBJECT_NAME=This default populates a User-Supplied Certificate Subject Name to the request. +@@ -1028,6 +1032,7 @@ CMS_PROFILE_REQUESTOR_EMAIL=Requestor Email + CMS_PROFILE_REQUESTOR_PHONE=Requestor Phone + CMS_PROFILE_REQ_SAN_TYPE=Request Subject Alternative Name Extension Type + CMS_PROFILE_REQ_SAN_PATTERN=Request Subject Alternative Name Extension Pattern ++CMS_PROFILE_SERVER_KEYGEN_P12PASSWORD=Server-Side Key Generation PKCS#12 Password + CMS_PROFILE_SN_UID=UID + CMS_PROFILE_SN_EMAIL=Email + CMS_PROFILE_SN_CN=Common Name +@@ -1043,9 +1048,13 @@ CMS_PROFILE_INPUT_CERT_REQ=Certificate Request + CMS_PROFILE_INPUT_KEYGEN_REQ=Key Generation Request + CMS_PROFILE_INPUT_KEYGEN_REQ_TYPE=Key Generation Request Type + CMS_PROFILE_INPUT_FILE_SIGNING_NAME=File Signing Input +-CMS_PROFILE_INPUT_FILE_SIGNING_TEXT=File Signing Input + CMS_PROFILE_INPUT_FILE_SIGNING_URL=URL Of File Being Signed + CMS_PROFILE_INPUT_FILE_SIGNING_TEXT=Text Being Signed ++CMS_PROFILE_INPUT_SERVER_KEYGEN_NAME=Server-Side Key Generation ++CMS_PROFILE_INPUT_SERVER_KEYGEN_TEXT=Server-Side Key Generation ++CMS_PROFILE_SERVER_KEYGEN_P12PASSWD=Server-Side Key Generation P12 Password ++CMS_PROFILE_SERVER_KEYGEN_KEY_TYPE=Server-Side Key Generation KEY TYPE ++CMS_PROFILE_SERVER_KEYGEN_KEY_SIZE=Server-Side Key Generation KEY SIZE + CMS_PROFILE_INPUT_SUBJECT_ALT_NAME_EXT_NAME=Subject Alternative Name Extension Information + CMS_PROFILE_INPUT_SUBJECT_ALT_NAME_EXT_TEXT=Subject Alternative Name Extension Information + CMS_PROFILE_IMAGE=Image +@@ -1094,6 +1103,8 @@ CMS_PROFILE_OUTPUT_CERT_B64=Certificate Base-64 Encoded + CMS_PROFILE_OUTPUT_CMMF_B64=CMMF Base-64 Encoded + CMS_PROFILE_OUTPUT_PKCS7_B64=PKCS #7 Base-64 Encoded + CMS_PROFILE_OUTPUT_DER_B64=DER Base 64 Encoded ++CMS_PROFILE_OUTPUT_PKCS12=PKCS#12 ++CMS_PROFILE_OUTPUT_PKCS12_TEXT=PKCS#12 + ####################################################### + # Self Tests + # +diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java +index ac780b4..b73230a 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpPKIMessage.java +@@ -75,6 +75,11 @@ public class HttpPKIMessage implements IHttpPKIMessage { + reqStatus = r.getRequestStatus().toString(); + reqRealm = r.getRealm(); + ++/* ++ CMS.debug("HttpPKIMessage.fromRequest:" + "requestType= " + reqType + ++ " requestId=" + r.getRequestId().toString() + ++ " requestStatus=" + reqStatus + " instance=" + r); ++*/ + CMS.debug("HttpPKIMessage.fromRequest: requestId=" + + r.getRequestId().toString() + " requestStatus=" + reqStatus + " instance=" + r); + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java b/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java +index 9f77920..a533527 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/connector/RequestTransfer.java +@@ -83,15 +83,17 @@ public class RequestTransfer { + if (k.equals("AUTH_TOKEN")) + continue; + //CMS.debug("RequestTransfer: attribute=" + k); +- if (k.equals("requestStatus")) { ++ if (k.equalsIgnoreCase("requestStatus")) { + CMS.debug("RequestTransfer : requestStatus=" + + r.getExtDataInString("requestStatus")); + } ++ //CMS.debug("RequestTransfer: profile request; transfer name:"+k); + v.addElement(k); + } + CMS.debug("RequestTransfer: attribute size=" + v.size()); + return v.toArray(new String[v.size()]); + } else { ++ //CMS.debug("RequestTransfer: not profile request; returning default transferAttributes"); + return transferAttributes; + } + } +-- +1.8.3.1 + + +From f963ff3ce187c5607dd2507a8ecf0d89a9356766 Mon Sep 17 00:00:00 2001 +From: Dinesh Prasanth M K +Date: Thu, 16 Apr 2020 21:14:48 -0400 +Subject: [PATCH 4/6] Fix Javascript and backend to populate the WebUI for + ServerSideKeygen + +This patch: + +- Uses javascript to fill up the web UI request for ServerSide Keygen request profile + +- Provides 2 drop down boxes: KeyType and Keysize. KeySize autoupdates based on + the KeyType selected. Example: RSA -> 1024, 2048,.. ; ECC -> nistp521, nistp256 + +- The keyType and keySize are read from the profile's attr: + policyset.userCertSet.3.constraint.params.keyParameters + +File wise changes: + +- ServerKeygenInput.java sends 2 new fields (keyType and keyRequest) to the request, to be + displayed on the webUI + +- ProfileSelect.template carries the javascript changes. Note that there are 2 new if + conditions included: "server_side_keygen_key_type" and "server_side_keygen_key_size". + This ensures that it doesn't meddle with other profile web UIs + +- IDescriptor.java and UserMessages.properties carry the appropriate String values to + be displayed/requested from user. + +Signed-off-by: Dinesh Prasanth M K +(cherry picked from commit 3fa7a49aee3afda2ac1bb077e4062bfd57e96f44) +--- + .../shared/webapps/ca/ee/ca/ProfileSelect.template | 33 ++++++++++--- + .../com/netscape/certsrv/property/IDescriptor.java | 2 + + .../profile/def/ServerKeygenUserKeyDefault.java | 55 ++++++++++++++++++---- + .../cms/profile/input/ServerKeygenInput.java | 14 +++--- + base/server/cmsbundle/src/UserMessages.properties | 4 +- + 5 files changed, 83 insertions(+), 25 deletions(-) + +diff --git a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template +index 350cb9b..be2caef 100644 +--- a/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template ++++ b/base/ca/shared/webapps/ca/ee/ca/ProfileSelect.template +@@ -315,6 +315,10 @@ function keyLengthsCurvesOptions (keyPurpose) + if (keyPurpose.length == 0 || (keyPurpose.length > 0 && policySetListSet[i].setId.indexOf(keyPurpose) > -1)) { + keyType = policySetListSet[i].policySet[j].constraintSet[k].value; + } ++ } else { ++ if (document.getElementById("keyTypeId").value != "undefined") { ++ keyType = document.getElementById("keyTypeId").value; ++ } + } + } + +@@ -346,6 +350,8 @@ function keyLengthsCurvesOptions (keyPurpose) + value != "nistp256" && value != "nistp384" && value != "nistp521" && + value != "ECDSA_P256" && value != "ECDSA_P384" && value != "ECDSA_P521") { + included = false; ++ } else if (keyType == "EC" && isNumeric(value)) { ++ included = false; + } + + if (included) { +@@ -377,6 +383,18 @@ function keyLengthsCurvesOptions (keyPurpose) + return options; + } + ++function updateKeyLengthsCurvesOptions() { ++ // get the keySize select element via its known id ++ var cSelect = document.getElementById("keySizeId"); ++ ++ // remove the current options from the select tag ++ var len=cSelect.options.length; ++ while (cSelect.options.length > 0) { ++ cSelect.remove(0); ++ } ++ cSelect.innerHTML = keyLengthsCurvesOptions(""); ++} ++ + function isNumeric(sText) + { + var validChars = "0123456789"; +@@ -753,17 +771,18 @@ for (var m = 0; m < inputPluginListSet.length; m++) { + } else if (inputListSet[n].inputSyntax == 'server_side_keygen_request_type') { + // get PKCS#12 password + document.writeln(''); +- document.write('PKCS #12 Password:'); +- document.write(''); ++ document.writeln('PKCS #12 Password:'); ++ document.writeln(''); + document.writeln(''); + + document.writeln(''); +- document.write('PKCS #12 Password again:'); +- document.write(''); +- document.writeln('  '); +- document.writeln('  '); ++ document.writeln('PKCS #12 Password again:'); ++ document.writeln(''); + document.writeln(''); +- ++ } else if (inputListSet[n].inputSyntax == 'server_side_keygen_key_type') { ++ document.writeln(' '); ++ } else if (inputListSet[n].inputSyntax == 'server_side_keygen_key_size') { ++ document.writeln(' '); + } else if (inputListSet[n].inputSyntax == 'cert_request') { + document.writeln(''); + } else if (inputListSet[n].inputSyntax == 'cert_request_type') { +diff --git a/base/common/src/com/netscape/certsrv/property/IDescriptor.java b/base/common/src/com/netscape/certsrv/property/IDescriptor.java +index 4de6bb3..8eed7ae 100644 +--- a/base/common/src/com/netscape/certsrv/property/IDescriptor.java ++++ b/base/common/src/com/netscape/certsrv/property/IDescriptor.java +@@ -47,6 +47,8 @@ public interface IDescriptor { + public static String CERT_REQUEST_TYPE = "cert_request_type"; + public static String SERVER_SIDE_KEYGEN_REQUEST_TYPE = "server_side_keygen_request_type"; + public static String SERVER_SIDE_KEYGEN_PKCS12 = "server_side_keygen_p12"; ++ public static String SERVER_SIDE_KEYGEN_KEY_TYPE = "server_side_keygen_key_type"; ++ public static String SERVER_SIDE_KEYGEN_KEY_SIZE = "server_side_keygen_key_size"; + public static String CHOICE = "choice"; // choice of strings + public static String DN = "dn"; + public static String IP = "ip"; +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +index e82ee24..13a8dec 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +@@ -336,22 +336,61 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + request.setExtData("isServerSideKeygen", "true"); + CryptoToken token = cm.getInternalKeyStorageToken(); + +- String keySizeStr = request.getExtDataInString("keySize"); +- int keySize = 1024; +- if (keySizeStr != null) { +- CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request: " + keySizeStr); +- keySize = Integer.parseInt(keySizeStr); ++ String keyTypeStr = request.getExtDataInString("keyType"); ++ String keyType = "RSA"; ++ int keySize = 2048; ++ String curveName = "nistp521"; ++ ++ // Populate the keyType and keySize/keyCurve ++ ++ if (keyTypeStr != null && !keyTypeStr.isEmpty()) { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keyType in request: " + keyTypeStr); ++ keyType = keyTypeStr; + } else { +- CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request null; default to 2048"); ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keyType in request null; default to RSA"); ++ } ++ ++ String keySizeCurveStr = request.getExtDataInString("keySize"); ++ ++ if (keyType.contentEquals("RSA")) { ++ if (keySizeCurveStr != null && !keySizeCurveStr.isEmpty()) { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request: " + keySizeCurveStr); ++ keySize = Integer.parseInt(keySizeCurveStr); ++ } else { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request null; default to" + keySize); ++ } ++ // Do things when RSA is selected ++ } else if (keyType.contentEquals("EC")) { ++ // TODO: dmoluguw: Fix the following to generate right Key ECC keys ++ ++ if (keySizeCurveStr != null && !keySizeCurveStr.isEmpty()) { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keyCurve in request: " + keySizeCurveStr); ++ curveName = keySizeCurveStr; ++ } else { ++ CMS.debug("ServerKeygenUserKeyDefault: populate: keySize in request null; default to" + curveName); ++ } ++ // Do things when EC is selected ++ } else { ++ throw new Exception("Unsupported keyType: " + keyType); ++ } ++ request.setExtData(IRequest.KEY_GEN_ALGORITHM, keyType); ++ if(keyType.contentEquals("RSA")) { ++ request.setExtData(IRequest.KEY_GEN_SIZE, keySize); ++ } ++ else if (keyType.contentEquals("EC")) { ++ // TODO: Check whether IRequest.KEY_GEN_SIZE can accept string value ++ request.setExtData(IRequest.KEY_GEN_SIZE, curveName); + } +- request.setExtData(IRequest.KEY_GEN_ALGORITHM, "RSA"); +- request.setExtData(IRequest.KEY_GEN_SIZE, keySize); + + /* + * it is necessary to put in a static fake key here to prevent + * issue; The fake key will be replaced later once KRA generates + * the real keys + */ ++ ++ // dmoluguw: TODO: The below values seem to be for development purposes, ++ // and will probably work only with keyType="RSA" ++ + String pubKeyStr = ""; + switch (keySize) { + case 1024: +diff --git a/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java b/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java +index fb460d0..29890f4 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java ++++ b/base/server/cms/src/com/netscape/cms/profile/input/ServerKeygenInput.java +@@ -39,17 +39,17 @@ import com.netscape.certsrv.profile.IProfileInput; + public class ServerKeygenInput extends EnrollInput implements IProfileInput { + + public static final String P12PASSWORD = "serverSideKeygenP12Passwd"; +-/* ++ + public static final String KEY_TYPE = "keyType"; + public static final String KEY_SIZE = "keySize"; +-*/ ++ + + public ServerKeygenInput() { + addValueName(P12PASSWORD); +-/* ++ + addValueName(KEY_TYPE); + addValueName(KEY_SIZE); +-*/ ++ + } + + /** +@@ -99,16 +99,14 @@ public class ServerKeygenInput extends EnrollInput implements IProfileInput { + return new Descriptor(IDescriptor.SERVER_SIDE_KEYGEN_REQUEST_TYPE, null, + null, + CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_P12PASSWD")); +-/* + } else if (name.equals(KEY_TYPE)) { +- return new Descriptor(IDescriptor.STRING, null, ++ return new Descriptor(IDescriptor.SERVER_SIDE_KEYGEN_KEY_TYPE, null, + null, + CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_KEY_TYPE")); + } else if (name.equals(KEY_SIZE)) { +- return new Descriptor(IDescriptor.STRING, null, ++ return new Descriptor(IDescriptor.SERVER_SIDE_KEYGEN_KEY_SIZE, null, + null, + CMS.getUserMessage(locale, "CMS_PROFILE_SERVER_KEYGEN_KEY_SIZE")); +-*/ + } + return null; + } +diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties +index 608d29a..2c57c59 100644 +--- a/base/server/cmsbundle/src/UserMessages.properties ++++ b/base/server/cmsbundle/src/UserMessages.properties +@@ -1053,8 +1053,8 @@ CMS_PROFILE_INPUT_FILE_SIGNING_TEXT=Text Being Signed + CMS_PROFILE_INPUT_SERVER_KEYGEN_NAME=Server-Side Key Generation + CMS_PROFILE_INPUT_SERVER_KEYGEN_TEXT=Server-Side Key Generation + CMS_PROFILE_SERVER_KEYGEN_P12PASSWD=Server-Side Key Generation P12 Password +-CMS_PROFILE_SERVER_KEYGEN_KEY_TYPE=Server-Side Key Generation KEY TYPE +-CMS_PROFILE_SERVER_KEYGEN_KEY_SIZE=Server-Side Key Generation KEY SIZE ++CMS_PROFILE_SERVER_KEYGEN_KEY_TYPE=Server-Side Key Generation Key Type ++CMS_PROFILE_SERVER_KEYGEN_KEY_SIZE=Server-Side Key Generation Key Size + CMS_PROFILE_INPUT_SUBJECT_ALT_NAME_EXT_NAME=Subject Alternative Name Extension Information + CMS_PROFILE_INPUT_SUBJECT_ALT_NAME_EXT_TEXT=Subject Alternative Name Extension Information + CMS_PROFILE_IMAGE=Image +-- +1.8.3.1 + + +From 92b79cf422ab780edb65b28e0e77e13037f60fd6 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Fri, 17 Apr 2020 18:05:14 -0400 +Subject: [PATCH 5/6] Bug 1794213- change p12 filename & transport cert + nickname for Server-Side Kyegen Enrollment This patch provides the following + fixes: - changes the p12 filename from "profileProcess" to + "serverKeyGenCert.p12" - transport cert nickname config + +https://bugzilla.redhat.com/show_bug.cgi?id=1794213 +(cherry picked from commit a7b6d8e834f95f16478f6ae7b30b964f28693361) +--- + .../src/com/netscape/certsrv/system/KRAConnectorInfo.java | 14 ++++++++++++++ + .../org/dogtagpki/server/kra/rest/KRAInstallerService.java | 5 ++++- + .../netscape/cms/servlet/admin/KRAConnectorProcessor.java | 3 +++ + .../com/netscape/cms/servlet/csadmin/UpdateConnector.java | 1 + + .../cms/servlet/profile/ProfileProcessServlet.java | 1 + + 5 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java +index a8caca6..b22909c 100644 +--- a/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java ++++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java +@@ -36,6 +36,7 @@ public class KRAConnectorInfo { + private static final String HOST = "host"; + private static final String PORT = "port"; + private static final String TRANSPORT_CERT= "transportCert"; ++ private static final String TRANSPORT_CERT_NICKNAME="transportCertNickname"; + private static final String URI = "uri"; + private static final String TIMEOUT = "timeout"; + private static final String LOCAL = "local"; +@@ -51,6 +52,9 @@ public class KRAConnectorInfo { + String transportCert; + + @XmlElement ++ String transportCertNickname; ++ ++ @XmlElement + String uri; + + @XmlElement +@@ -74,6 +78,7 @@ public class KRAConnectorInfo { + timeout = form.getFirst(TIMEOUT); + local = form.getFirst(LOCAL); + enable = form.getFirst(ENABLE); ++ transportCertNickname = form.getFirst(TRANSPORT_CERT_NICKNAME); + } + + public String getHost() { +@@ -100,6 +105,14 @@ public class KRAConnectorInfo { + this.transportCert = transportCert; + } + ++ public void setTransportCertNickname(String transportCertNickname) { ++ this.transportCertNickname = transportCertNickname; ++ } ++ ++ public String getTransportCertNickname() { ++ return transportCertNickname; ++ } ++ + public String getUri() { + return uri; + } +@@ -156,6 +169,7 @@ public class KRAConnectorInfo { + info.setPort("8443"); + info.setTimeout("30"); + info.setUri(""); ++ info.setTransportCertNickname("KRA Transport Certificate"); + info.setTransportCert( + "MIIDnDCCAoSgAwIBAgIBDzANBgkqhkiG9w0BAQsFADBGMSMwIQYDVQQKExpyZWRo" + + "YXQuY29tIFNlY3VyaXR5IERvbWFpbjEfMB0GA1UEAxMWQ0EgU2lnbmluZyBDZXJ0" + +diff --git a/base/kra/src/org/dogtagpki/server/kra/rest/KRAInstallerService.java b/base/kra/src/org/dogtagpki/server/kra/rest/KRAInstallerService.java +index 7759dcc..35ae7b8 100644 +--- a/base/kra/src/org/dogtagpki/server/kra/rest/KRAInstallerService.java ++++ b/base/kra/src/org/dogtagpki/server/kra/rest/KRAInstallerService.java +@@ -93,7 +93,8 @@ public class KRAInstallerService extends SystemConfigService { + String kraPort = CMS.getAgentPort(); + String transportCert = cs.getString("kra.transport.cert", ""); + String sessionId = CMS.getConfigSDSessionId(); +- ++ String transportCertNickname = cs.getString("kra.cert.transport.nickname"); ++ CMS.debug("KRAInstallerService: transportCert nickname: " + transportCertNickname); + MultivaluedMap content = new MultivaluedHashMap(); + content.putSingle("ca.connector.KRA.enable", "true"); + content.putSingle("ca.connector.KRA.local", "false"); +@@ -102,8 +103,10 @@ public class KRAInstallerService extends SystemConfigService { + content.putSingle("ca.connector.KRA.host", kraHost); + content.putSingle("ca.connector.KRA.port", kraPort); + content.putSingle("ca.connector.KRA.transportCert", transportCert); ++ content.putSingle("ca.connector.KRA.transportCertNickname",transportCertNickname); + content.putSingle("sessionID", sessionId); + ++ CMS.debug("KRAnstallerService: content: " + content); + String c = ConfigurationUtils.post(caHost, caPort, true, "/ca/admin/ca/updateConnector", content, null, null); + if (c == null || c.equals("")) { + CMS.debug("KRAInstallerService: Unable to configure KRA connector: No response from CA"); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java +index 2fd5d53..46d4324 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java +@@ -183,6 +183,7 @@ public class KRAConnectorProcessor extends CAProcessor { + } + } + ++ CMS.debug("KRAConnectorInfo: " + info); + // connector does not exist, or existing connector is the same host/port and we are replacing it + cs.putString(PREFIX + ".host", info.getHost()); + cs.putString(PREFIX + ".port", info.getPort()); +@@ -191,6 +192,7 @@ public class KRAConnectorProcessor extends CAProcessor { + cs.putString(PREFIX + ".timeout", info.getTimeout() != null ? info.getTimeout() : "30"); + cs.putString(PREFIX + ".uri", info.getUri() != null ? info.getUri() : "/kra/agent/kra/connector"); + cs.putString(PREFIX + ".transportCert", info.getTransportCert()); ++ cs.putString(PREFIX + ".transportCertNickname", info.getTransportCertNickname()); + + String nickname = cs.getString("ca.subsystem.nickname", ""); + String tokenname = cs.getString("ca.subsystem.tokenname", ""); +@@ -219,6 +221,7 @@ public class KRAConnectorProcessor extends CAProcessor { + info.setTimeout(cs.getString(PREFIX + ".timeout")); + info.setUri(cs.getString(PREFIX + ".uri")); + info.setTransportCert(cs.getString(PREFIX + ".transportCert")); ++ info.setTransportCertNickname(cs.getString(PREFIX + ".transportCertNickname")); + + return info; + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java +index b2d081f..6a2c25f 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java +@@ -71,6 +71,7 @@ public class UpdateConnector extends CMSServlet { + info.setPort(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".port")); + info.setTimeout(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".timeout")); + info.setTransportCert(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".transportCert")); ++ info.setTransportCertNickname(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".transportCertNickname")); + info.setUri(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".uri")); + info.setLocal(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".local")); + info.setEnable(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".enable")); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +index ea2183f..f71d754 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +@@ -191,6 +191,7 @@ public class ProfileProcessServlet extends ProfileServlet { + OutputStream bos = p12_response.getOutputStream(); + p12_response.setContentType("application/x-pkcs12"); + p12_response.setContentLength(p12blob.length); ++ p12_response.setHeader("Content-disposition", "attachment; filename="+ "serverKeyGenCert.p12"); + bos.write(p12blob); + bos.flush(); + bos.close(); +-- +1.8.3.1 + + +From e7e1cea36fb616a5f5059453c53d30678e813622 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Fri, 17 Apr 2020 17:43:53 -0700 +Subject: [PATCH 6/6] Bug 1794213 adds EC Support and audit for Server-Side + Kyegen Enrollment + +This patch + - adds EC support for the Server-Side Kyegen Enrollment feature. + - adds auditng + - fixes key record so that Archiver and Owner Name are not null. + - fixes missing request records + +Note: the new audit events implemented are + - SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST + - SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST_PROCESSED + - SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST + - SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST_PROCESSED +where SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST_PROCESSED is not yet added + +https://bugzilla.redhat.com/show_bug.cgi?id=1794213 +(cherry picked from commit 3649e4b3143a35a51c367c71b31d2aa8d9b4e507) +--- + .../shared/profiles/ca/caServerKeygen_UserCert.cfg | 6 +- + .../certsrv/kra/IKeyRecoveryAuthority.java | 2 + + .../ServerSideKeygenEnrollKeyRetrievalEvent.java | 43 +++++ + ...SideKeygenEnrollKeyRetrievalProcessedEvent.java | 46 ++++++ + .../event/ServerSideKeygenEnrollKeygenEvent.java | 43 +++++ + ...ServerSideKeygenEnrollKeygenProcessedEvent.java | 47 ++++++ + .../src/com/netscape/kra/AsymKeyGenService.java | 183 +++++++++++++++------ + .../src/com/netscape/kra/KeyRecoveryAuthority.java | 15 +- + base/kra/src/com/netscape/kra/RecoveryService.java | 21 ++- + .../cms/profile/common/CAEnrollProfile.java | 80 +++++---- + .../profile/def/ServerKeygenUserKeyDefault.java | 77 ++++++--- + .../com/netscape/cms/servlet/base/CMSServlet.java | 4 - + .../cms/servlet/connector/ConnectorServlet.java | 49 ++++-- + .../cms/servlet/profile/ProfileProcessServlet.java | 7 +- + base/server/cmsbundle/src/audit-events.properties | 53 ++++++ + .../netscape/cmscore/request/ARequestQueue.java | 4 +- + 16 files changed, 548 insertions(+), 132 deletions(-) + create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalEvent.java + create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalProcessedEvent.java + create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenEvent.java + create mode 100644 base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenProcessedEvent.java + +diff --git a/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +index 0f2b3dc..b449163 100644 +--- a/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg ++++ b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +@@ -36,8 +36,8 @@ policyset.userCertSet.2.default.params.range=180 + policyset.userCertSet.2.default.params.startTime=0 + policyset.userCertSet.3.constraint.class_id=keyConstraintImpl + policyset.userCertSet.3.constraint.name=Key Constraint +-policyset.userCertSet.3.constraint.params.keyType=RSA +-policyset.userCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 ++policyset.userCertSet.3.constraint.params.keyType=- ++policyset.userCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 + policyset.userCertSet.3.default.class_id=serverKeygenUserKeyDefaultImpl + policyset.userCertSet.3.default.name=Server-Side Keygen Default + policyset.userCertSet.3.default.params.keyType=RSA +@@ -97,7 +97,7 @@ policyset.userCertSet.8.default.params.subjAltExtGNEnable_0=true + policyset.userCertSet.8.default.params.subjAltNameNumGNs=1 + policyset.userCertSet.9.constraint.class_id=signingAlgConstraintImpl + policyset.userCertSet.9.constraint.name=No Constraint +-policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC ++policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC,SHA256withRSA/PSS,SHA384withRSA/PSS,SHA512withRSA/PSS + policyset.userCertSet.9.default.class_id=signingAlgDefaultImpl + policyset.userCertSet.9.default.name=Signing Alg + policyset.userCertSet.9.default.params.signingAlg=- +diff --git a/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java b/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java +index 4f709e9..97c65eb 100644 +--- a/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java ++++ b/base/common/src/com/netscape/certsrv/kra/IKeyRecoveryAuthority.java +@@ -354,4 +354,6 @@ public interface IKeyRecoveryAuthority extends ISubsystem { + */ + public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, + PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList) throws EBaseException; ++ public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, ++ PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList, boolean temporary) throws EBaseException; + } +diff --git a/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalEvent.java +new file mode 100644 +index 0000000..59534e3 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalEvent.java +@@ -0,0 +1,43 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.logging.event; ++ ++import com.netscape.certsrv.logging.SignedAuditEvent; ++import com.netscape.certsrv.request.RequestId; ++ ++public class ServerSideKeygenEnrollKeyRetrievalEvent extends SignedAuditEvent { ++ ++ private static final long serialVersionUID = 1L; ++ ++ private static final String LOGGING_PROPERTY = ++ "LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST"; ++ ++ public ServerSideKeygenEnrollKeyRetrievalEvent( ++ String subjectID, ++ String outcome, ++ RequestId requestID, ++ String clientID) { ++ ++ super(LOGGING_PROPERTY); ++ ++ setAttribute("SubjectID", subjectID); ++ setAttribute("Outcome", outcome); ++ setAttribute("RequestID", requestID); ++ setAttribute("ClientID", clientID); ++ } ++} +diff --git a/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalProcessedEvent.java +new file mode 100644 +index 0000000..603ed74 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeyRetrievalProcessedEvent.java +@@ -0,0 +1,46 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.logging.event; ++ ++import com.netscape.certsrv.logging.SignedAuditEvent; ++import com.netscape.certsrv.request.RequestId; ++ ++public class ServerSideKeygenEnrollKeyRetrievalProcessedEvent extends SignedAuditEvent { ++ ++ private static final long serialVersionUID = 1L; ++ ++ private static final String LOGGING_PROPERTY = ++ "LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST_PROCESSED"; ++ ++ public ServerSideKeygenEnrollKeyRetrievalProcessedEvent( ++ String subjectID, ++ String outcome, ++ RequestId requestID, ++ String clientID, ++ String failureReason) { ++ ++ super(LOGGING_PROPERTY); ++ ++ setAttribute("SubjectID", subjectID); ++ setAttribute("Outcome", outcome); ++ setAttribute("RequestID", requestID); ++ setAttribute("ClientID", clientID); ++ setAttribute("FailureReason", failureReason); ++ } ++} ++ +diff --git a/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenEvent.java +new file mode 100644 +index 0000000..90e8330 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenEvent.java +@@ -0,0 +1,43 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.logging.event; ++ ++import com.netscape.certsrv.logging.SignedAuditEvent; ++import com.netscape.certsrv.request.RequestId; ++ ++public class ServerSideKeygenEnrollKeygenEvent extends SignedAuditEvent { ++ ++ private static final long serialVersionUID = 1L; ++ ++ private static final String LOGGING_PROPERTY = ++ "LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST"; ++ ++ public ServerSideKeygenEnrollKeygenEvent( ++ String subjectID, ++ String outcome, ++ RequestId requestID, ++ String clientKeyID) { ++ ++ super(LOGGING_PROPERTY); ++ ++ setAttribute("SubjectID", subjectID); ++ setAttribute("Outcome", outcome); ++ setAttribute("RequestID", requestID); ++ setAttribute("ClientKeyID", clientKeyID); ++ } ++} +diff --git a/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenProcessedEvent.java +new file mode 100644 +index 0000000..13adb32 +--- /dev/null ++++ b/base/common/src/com/netscape/certsrv/logging/event/ServerSideKeygenEnrollKeygenProcessedEvent.java +@@ -0,0 +1,47 @@ ++// --- 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) 2020 Red Hat, Inc. ++// All rights reserved. ++// --- END COPYRIGHT BLOCK --- ++package com.netscape.certsrv.logging.event; ++ ++import com.netscape.certsrv.dbs.keydb.KeyId; ++import com.netscape.certsrv.logging.SignedAuditEvent; ++import com.netscape.certsrv.request.RequestId; ++ ++public class ServerSideKeygenEnrollKeygenProcessedEvent extends SignedAuditEvent { ++ ++ private static final long serialVersionUID = 1L; ++ ++ private static final String LOGGING_PROPERTY = ++ "LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST_PROCESSED"; ++ ++ public ServerSideKeygenEnrollKeygenProcessedEvent( ++ String subjectID, ++ String outcome, ++ RequestId requestID, ++ String clientID, ++ String failureReason) { ++ ++ super(LOGGING_PROPERTY); ++ ++ setAttribute("SubjectID", subjectID); ++ setAttribute("Outcome", outcome); ++ setAttribute("RequestID", requestID); ++ setAttribute("ClientID", clientID); ++ setAttribute("FailureReason", failureReason); ++ } ++} ++ +diff --git a/base/kra/src/com/netscape/kra/AsymKeyGenService.java b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +index dca6ebc..61f86ff 100644 +--- a/base/kra/src/com/netscape/kra/AsymKeyGenService.java ++++ b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +@@ -36,6 +36,7 @@ import com.netscape.certsrv.kra.IKeyRecoveryAuthority; + import com.netscape.certsrv.logging.ILogger; + import com.netscape.certsrv.logging.LogEvent; + import com.netscape.certsrv.logging.event.AsymKeyGenerationProcessedEvent; ++import com.netscape.certsrv.logging.event.ServerSideKeygenEnrollKeygenProcessedEvent; + import com.netscape.certsrv.request.IRequest; + import com.netscape.certsrv.request.IService; + import com.netscape.certsrv.request.RequestId; +@@ -55,6 +56,7 @@ import netscape.security.util.WrappingParams; + * The public key is stored in the publicKeyData attribute of the record. + * + * @author akoneru ++ * @author cfu Server-Side Keygen Enrollment support + * + */ + public class AsymKeyGenService implements IService { +@@ -77,6 +79,8 @@ public class AsymKeyGenService implements IService { + String method = "AsymKeyGenService:serviceRequest: "; + IConfigStore configStore = CMS.getConfigStore(); + ++ String owner = request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER); ++ String auditSubjectID = owner; + boolean isSSKeygen = false; + String isSSKeygenStr = request.getExtDataInString("isServerSideKeygen"); + if ((isSSKeygenStr != null) && isSSKeygenStr.equalsIgnoreCase("true")) { +@@ -93,9 +97,37 @@ public class AsymKeyGenService implements IService { + CMS.debug(method + "clientKeyId not found"); + + String algorithm = request.getExtDataInString(IRequest.KEY_GEN_ALGORITHM); +- + String keySizeStr = request.getExtDataInString(IRequest.KEY_GEN_SIZE); +- int keySize = Integer.valueOf(keySizeStr); ++ int keySize = 2048; ++ boolean isEC = false; ++ String errmsg =""; ++ ++ if (algorithm.toUpperCase().equals("RSA")) ++ keySize = Integer.valueOf(keySizeStr); ++ else { ++ isEC = true; ++ switch (keySizeStr) { ++ case "nistp256": ++ keySize = 256; ++ break; ++ case "nistp384": ++ keySize = 384; ++ break; ++ case "nistp521": ++ keySize = 521; ++ break; ++ default: ++ CMS.debug(method + "unknown EC key curve name: " + keySizeStr); ++ errmsg = "unknown EC key curve name: " + keySizeStr; ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ errmsg)); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + errmsg); ++ } ++ } + + String realm = request.getRealm(); + +@@ -149,8 +181,6 @@ public class AsymKeyGenService implements IService { + CMS.debug("AsymKeyGenService.serviceRequest. Request id: " + request.getRequestId()); + CMS.debug("AsymKeyGenService.serviceRequest algorithm: " + algorithm); + +- String owner = request.getExtDataInString(IRequest.ATTR_REQUEST_OWNER); +- String auditSubjectID = owner; + + // Generating the asymmetric keys + KeyPair kp = null; +@@ -159,22 +189,44 @@ public class AsymKeyGenService implements IService { + kp = kra.generateKeyPair( + algorithm.toUpperCase(), + keySize, +- null, // keyCurve for ECC, not yet supported ++ isEC? keySizeStr:null, // keyCurve for ECC + null, // PQG not yet supported +- usageList ++ usageList, ++ true /* temporary */ + ); + + } catch (EBaseException e) { + CMS.debugStackTrace(); +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), +- clientKeyId, null, "Failed to generate asymmetric key: " + e.getMessage()); +- throw new EBaseException("Errors in generating Asymmetric key: " + e, e); ++ if (isSSKeygen) { ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ e.getMessage())); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + e, e); ++ } else { ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), ++ clientKeyId, null, "Failed to generate asymmetric key: " + e.getMessage()); ++ throw new EBaseException("Errors in generating Asymmetric key: " + e, e); ++ } + } + + if (kp == null) { +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), +- clientKeyId, null, "Failed to generate asymmetric key"); +- throw new EBaseException("Failed to generate asymmetric key!"); ++ if (isSSKeygen) { ++ errmsg = "key generation failure"; ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ errmsg)); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: "+ errmsg); ++ } else { ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), ++ clientKeyId, null, "Failed to generate asymmetric key"); ++ throw new EBaseException("Failed to generate asymmetric key!"); ++ } + } + + if (isSSKeygen) { +@@ -184,17 +236,18 @@ public class AsymKeyGenService implements IService { + publicKeyData = kp.getPublic().getEncoded(); + if (publicKeyData == null) { + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); +- CMS.debug(method + " failed getting publickey encoded"); +- return false; ++ errmsg = " failed getting publickey encoded"; ++ CMS.debug(method + errmsg); ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ errmsg)); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: "+ errmsg); + } else { + //CMS.debug(method + "public key binary length ="+ publicKeyData.length); +- if (algorithm.equals("EC")) { +- /* url encode */ +- pubKeyStr = com.netscape.cmsutil.util.Utils.SpecialEncode(publicKeyData); +- CMS.debug(method + " EC pubKeyStr special encoded"); +- } else { +- pubKeyStr = CryptoUtil.base64Encode(publicKeyData); +- } ++ pubKeyStr = CryptoUtil.base64Encode(publicKeyData); + + //CMS.debug(method + "public key length =" + pubKeyStr.length()); + request.setExtData("public_key", pubKeyStr); +@@ -202,7 +255,13 @@ public class AsymKeyGenService implements IService { + } catch (Exception e) { + CMS.debug(method + e); + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); +- return false; ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ e.getMessage())); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + e, e); + } + } + +@@ -214,23 +273,46 @@ public class AsymKeyGenService implements IService { + privateSecurityData = storageUnit.wrap((PrivateKey) kp.getPrivate(), params); + } catch (Exception e) { + CMS.debug("Failed to generate security data to archive: " + e); +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), ++ if (isSSKeygen) { ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ e.getMessage())); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + e, e); ++ } else { ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), + clientKeyId, null, CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY")); +- throw new EBaseException("Failed to generate security data to archive!", e); ++ throw new EBaseException("Failed to generate security data to archive!", e); ++ } + } + ++ if (owner == null) ++ owner = request.getExtDataInString("auth_token-userdn"); + KeyRecord record = new KeyRecord(null, kp.getPublic().getEncoded(), privateSecurityData, +- owner, algorithm, owner); ++ isSSKeygen? clientKeyId:owner, algorithm, owner); + + IKeyRepository storage = kra.getKeyRepository(); + BigInteger serialNo = storage.getNextSerialNumber(); + + if (serialNo == null) { +- kra.log(ILogger.LL_FAILURE, ++ if (isSSKeygen) { ++ errmsg = "Failed to get next Key ID"; ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ errmsg)); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: "+ errmsg); ++ } else { ++ kra.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_KRA_GET_NEXT_SERIAL")); +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), + clientKeyId, null, "Failed to get next Key ID"); +- throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); ++ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); ++ } + } + + // Storing the public key and private key. +@@ -250,36 +332,37 @@ public class AsymKeyGenService implements IService { + try { + record.setWrappingParams(params, allowEncDecrypt_archival); + } catch (Exception e) { +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), ++ if (isSSKeygen) { ++ errmsg = "Failed to store wrapping params"; ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Failure", ++ request.getRequestId(), ++ clientKeyId, ++ e.getMessage() + errmsg)); ++ throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + errmsg, e); ++ } else { ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.FAILURE, request.getRequestId(), + clientKeyId, null, "Failed to store wrapping params"); +- throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); ++ throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); ++ } + } + + storage.addKeyRecord(record); + +- auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.SUCCESS, request.getRequestId(), ++ if (isSSKeygen) { ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenProcessedEvent( ++ auditSubjectID, ++ "Success", ++ request.getRequestId(), ++ clientKeyId, ++ null)); ++ } else { ++ auditAsymKeyGenRequestProcessed(auditSubjectID, ILogger.SUCCESS, request.getRequestId(), + clientKeyId, new KeyId(serialNo), "None"); ++ } + request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS); + +- if (isSSKeygen) { +- +- Enumeration ereq = request.getExtDataKeys(); +- +- /* cfu +- CMS.debug(method + "let's find out what's in the request"); +- while (ereq.hasMoreElements()) { +- String reqKey = ereq.nextElement(); +- String reqVal = request.getExtDataInString(reqKey); +- if (reqVal != null) { +- CMS.debug(method + reqKey + ": " + reqVal); +- } else { +- CMS.debug(method + reqKey + ": no value"); +- } +- } +- */ +- +- request.setExtData("delayLDAPCommit", "false"); +- } + kra.getRequestQueue().updateRequest(request); + + return true; +diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java +index 05c7e71..34e329b 100644 +--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java ++++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java +@@ -1728,6 +1728,10 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove + + public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, + PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList) throws EBaseException { ++ return generateKeyPair(alg, keySize, keyCurve, pqg, usageList, false); ++ } ++ public KeyPair generateKeyPair(String alg, int keySize, String keyCurve, ++ PQGParams pqg, KeyPairGeneratorSpi.Usage[] usageList, boolean temp) throws EBaseException { + KeyPairAlgorithm kpAlg = null; + + if (alg.equals("RSA")) +@@ -1738,7 +1742,7 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove + kpAlg = KeyPairAlgorithm.DSA; + + try { +- KeyPair kp = generateKeyPair(kpAlg, keySize, keyCurve, pqg, usageList); ++ KeyPair kp = generateKeyPair(kpAlg, keySize, keyCurve, pqg, usageList, temp); + + return kp; + } catch (InvalidParameterException e) { +@@ -1761,6 +1765,13 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove + KeyPairGeneratorSpi.Usage[] usageList ) + throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, + InvalidParameterException, PQGParamGenException { ++ return generateKeyPair(kpAlg, keySize, keyCurve, pqg, usageList, true); ++ } ++ public KeyPair generateKeyPair( ++ KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg, ++ KeyPairGeneratorSpi.Usage[] usageList, boolean temp) ++ throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, ++ InvalidParameterException, PQGParamGenException { + + CryptoToken token = getKeygenToken(); + +@@ -1780,7 +1791,7 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove + KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg); + IConfigStore config = CMS.getConfigStore(); + IConfigStore kgConfig = config.getSubStore("kra.keygen"); +- boolean tp = false; ++ boolean tp = temp; + boolean sp = false; + boolean ep = false; + if ((kgConfig != null) && (!kgConfig.equals(""))) { +diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java +index 4f2add9..fc6edeb 100644 +--- a/base/kra/src/com/netscape/kra/RecoveryService.java ++++ b/base/kra/src/com/netscape/kra/RecoveryService.java +@@ -170,7 +170,13 @@ public class RecoveryService implements IService { + + // serverKeygenP12Pass = request.getExtDataInString("serverSideKeygenP12Passwd"); + byte[] sessionWrappedPassphrase = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdEnc"); ++ if (sessionWrappedPassphrase == null) { ++ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR" + "Server-Side Keygen Enroll Key Retrieval: sessionWrappedPassphrase not found in Request")); ++ } + byte[] transWrappedSessionKey = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdTransSession"); ++ if (transWrappedSessionKey == null) { ++ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR" + "Server-Side Keygen Enroll Key Retrieval: transWrappedSessionKey not found in Request")); ++ } + + // unwrap session key + /* TODO: get nickname from config */ +@@ -190,8 +196,10 @@ public class RecoveryService implements IService { + transWrappedSessionKey, + KeyWrapAlgorithm.RSA); + +- if (unwrappedSessionKey == null) ++ if (unwrappedSessionKey == null) { + CMS.debug("RecoveryService: serviceRequest: unwrappedSessionKey null"); ++ throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR" + "Server-Side Keygen Enroll Key Retrieval: CryptoUtil.unwrap failed on unwrappedSessionKey")); ++ } + + // decrypt p12 passphrase + EncryptionAlgorithm encryptAlgorithm = +@@ -230,7 +238,6 @@ public class RecoveryService implements IService { + request.getRequestId()); + + if (params == null) { +- //cfu + if (isSSKeygen) { + params = new Hashtable(); + params.put(RecoveryService.ATTR_TRANSPORT_PWD, serverKeygenP12Pass); +@@ -671,6 +678,16 @@ public class RecoveryService implements IService { + } + } + ++ /* TODO ++ if (isSSKeygen) { ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeyRetrievalProcessedEvent( ++ auditSubjectID, ++ "Success", ++ request.getRequestId(), ++ clientKeyId, ++ null)); ++ } ++ */ + // update request + mKRA.getRequestQueue().updateRequest(request); + } +diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +index 2c539f0..138a2ec 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java ++++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +@@ -35,6 +35,9 @@ import com.netscape.certsrv.connector.IConnector; + import com.netscape.certsrv.logging.AuditFormat; + import com.netscape.certsrv.logging.ILogger; + import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; ++import com.netscape.certsrv.logging.event.ServerSideKeygenEnrollKeygenEvent; ++import com.netscape.certsrv.logging.event.ServerSideKeygenEnrollKeyRetrievalEvent; ++import com.netscape.certsrv.profile.IEnrollProfile; + import com.netscape.certsrv.profile.EProfileException; + import com.netscape.certsrv.profile.ERejectException; + import com.netscape.certsrv.profile.IProfileUpdater; +@@ -45,6 +48,7 @@ import com.netscape.cms.logging.Logger; + import com.netscape.cms.logging.SignedAuditLogger; + import com.netscape.cmsutil.crypto.CryptoUtil; + ++import netscape.security.x509.CertificateSubjectName; + import netscape.security.x509.CertificateX509Key; + import netscape.security.x509.X500Name; + import netscape.security.x509.X509CertImpl; +@@ -104,7 +108,7 @@ public class CAEnrollProfile extends EnrollProfile { + throw new EProfileException("No CA Service"); + } + +- //cfu: if isServerSideKeygen, send keygen request to KRA ++ // if isServerSideKeygen, send keygen request to KRA + boolean isSSKeygen = false; + String isSSKeygenStr = request.getExtDataInString("isServerSideKeygen"); + if (isSSKeygenStr != null && isSSKeygenStr.equalsIgnoreCase("true")) { +@@ -114,10 +118,20 @@ public class CAEnrollProfile extends EnrollProfile { + CMS.debug(method + "isServerSideKeygen = false"); + } + ++ // prepare for auditing ++ CertificateSubjectName reqSubj = ++ request.getExtDataInCertSubjectName(IEnrollProfile.REQUEST_SUBJECT_NAME); ++ String clientId = "unknown serverKeyGenUser"; ++ if (reqSubj != null) { ++ X500Name xN = reqSubj.getX500Name(); ++ clientId = xN.toString(); ++ CMS.debug(method + "clientId = " + clientId); ++ } ++ + // if PKI Archive Option present, send this request + // to DRM + byte optionsData[] = request.getExtDataInByteArray(REQUEST_ARCHIVE_OPTIONS); +- if (isSSKeygen) { // cfu ++ if (isSSKeygen) { // Server-Side Keygen enrollment + request.setExtData(IRequest.SSK_STAGE, IRequest.SSK_STAGE_KEYGEN); + try { + IConnector kraConnector = caService.getKRAConnector(); +@@ -148,26 +162,23 @@ public class CAEnrollProfile extends EnrollProfile { + throw new ERejectException(CMS.getUserMessage("CMS_CA_SEND_KRA_REQUEST")+ " check KRA log for detail"); + } + } +-/* +- signedAuditLogger.log(SecurityDataArchivalRequestEvent.createSuccessEvent( +- auditSubjectID, +- auditRequesterID, +- requestId, +- null)); +-*/ ++ // TODO: perhaps have Server-Side Keygen enrollment audit ++ // event, or expand AsymKeyGenerationEvent ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenEvent( ++ auditSubjectID, ++ "Success", ++ requestId, ++ clientId)); + } + } catch (Exception e) { + + CMS.debug(method + e); + +-/* +- signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeygenEvent( + auditSubjectID, +- auditRequesterID, ++ "Failure", + requestId, +- null, +- e)); +-*/ ++ clientId)); + + if (e instanceof ERejectException) { + throw (ERejectException) e; +@@ -256,17 +267,22 @@ public class CAEnrollProfile extends EnrollProfile { + // process certificate issuance + X509CertInfo info = request.getExtDataInCertInfo(REQUEST_CERTINFO); + +- if (isSSKeygen) { // cfu ++ if (isSSKeygen) { + try { + String pubKeyStr = request.getExtDataInString("public_key"); +- CMS.debug(method + "pubKeyStr = " + pubKeyStr); ++ if (pubKeyStr == null) { ++ throw new EProfileException("Server-Side Keygen enrollment failed to retrieve public_key from KRA"); ++ } ++ //CMS.debug(method + "pubKeyStr = " + pubKeyStr); + byte[] pubKeyB = CryptoUtil.base64Decode(pubKeyStr); + CertificateX509Key certKey = new CertificateX509Key( + new ByteArrayInputStream(pubKeyB)); + Object oj = info.get(X509CertInfo.KEY); + if (oj != null) { ++ // a placeholder temporary fake key was put in ++ // ServerKeygenUserKeyDefault + info.delete(X509CertInfo.KEY); +- CMS.debug(method + " fake key deleted"); ++ //CMS.debug(method + " fake key deleted"); + } + info.set(X509CertInfo.KEY, certKey); + } catch (IOException e) { +@@ -303,10 +319,11 @@ public class CAEnrollProfile extends EnrollProfile { + + request.setExtData(REQUEST_ISSUED_CERT, theCert); + +- //cfu: cert issued, now retrieve p12 ++ // cert issued, now retrieve p12 + if (isSSKeygen) { + CMS.debug(method + "onto SSK_STAGE_KEY_RETRIEVE"); + request.setExtData(IRequest.SSK_STAGE, IRequest.SSK_STAGE_KEY_RETRIEVE); ++ request.setExtData(IRequest.REQ_STATUS, "begin"); + request.setExtData("requestType", "recovery"); + request.setExtData("cert", theCert); //recognized by kra + try { +@@ -338,25 +355,22 @@ public class CAEnrollProfile extends EnrollProfile { + throw new ERejectException(CMS.getUserMessage("CMS_CA_SEND_KRA_REQUEST")+ " check KRA log for detail"); + } + } +-/* +- signedAuditLogger.log(SecurityDataArchivalRequestEvent.createSuccessEvent( ++ ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeyRetrievalEvent( + auditSubjectID, +- auditRequesterID, ++ "Success", + requestId, +- null)); +-*/ ++ clientId)); + } + } catch (Exception e) { + + CMS.debug(method + e); +-/* +- signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( ++ ++ signedAuditLogger.log(new ServerSideKeygenEnrollKeyRetrievalEvent( + auditSubjectID, +- auditRequesterID, ++ "Failure", + requestId, +- null, +- e)); +-*/ ++ clientId)); + + if (e instanceof ERejectException) { + throw (ERejectException) e; +@@ -364,12 +378,6 @@ public class CAEnrollProfile extends EnrollProfile { + throw new EProfileException(e); + } + CMS.debug(method + "isSSKeygen: response received from KRA"); +- byte p12bytes[] = request.getExtDataInByteArray("pkcs12"); +- if (p12bytes != null) { +- CMS.debug(method + "p12bytes not null"); +- } else { +- CMS.debug(method + "p12bytes null"); +- } + } + + long endTime = CMS.getCurrentDate().getTime(); +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +index 13a8dec..1e2a787 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +@@ -20,6 +20,7 @@ package com.netscape.cms.profile.def; + import java.io.ByteArrayInputStream; + import java.math.BigInteger; + import java.security.interfaces.DSAParams; ++import java.util.Enumeration; + import java.util.Locale; + import java.util.Vector; + import java.security.KeyPair; +@@ -29,6 +30,8 @@ import netscape.security.provider.DSAPublicKey; + import netscape.security.provider.RSAPublicKey; + import netscape.security.x509.AlgorithmId; + import netscape.security.x509.CertificateX509Key; ++import netscape.security.x509.CertificateSubjectName; ++import netscape.security.x509.X500Name; + import netscape.security.x509.X509CertImpl; + import netscape.security.x509.X509CertInfo; + import netscape.security.x509.X509Key; +@@ -54,6 +57,8 @@ import org.mozilla.jss.crypto.KeyWrapAlgorithm; + import org.mozilla.jss.crypto.SymmetricKey; + import org.mozilla.jss.crypto.X509Certificate; + ++import com.netscape.certsrv.logging.ILogger; ++ + /** + * This class implements an enrollment default policy + * for Server-Side keygen enrollment. +@@ -68,10 +73,14 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + public static final String VAL_LEN = "LEN"; + public static final String VAL_TYPE = "TYPE"; + +- private static final String TEMP_PUBKEY_1024 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBz6H2rT2r1RpHdr3JyYr7thSjfwWPbIJ6U09NziHSekLsNZQKsjdLS/LPCfe/aXkhpzPztlx++tkPucpt/xT0exp08feAPIE+Y6gVoyXzEw+Ztz+Zez9Y1cQWxAyp7z11flytjL+4zBGDXmEoe3ZlQvij9DGypPjBC9PhWm0lBwIDAQAB"; +- private static final String TEMP_PUBKEY_2048 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4Ha+CxWDPAHEl9+u57U3UCw8bfG/ZN3cVTrQgj/p8ak12NYUWt0ZI/xCcLj7gKwFPbNMTDwzizRPZuxKJT7fHgW8a1BQDUL2VGfx7O0A7KlLqcpVc6VKsQx5caP3hrB38Q5xnTKeVee9cBrd8An+veZ2QV6mHLEU8iMCN2No/t1oO+aYje42XloNRblXVQAOYW+3aMCam2kIKWUqLvA3Sbf2BPR2x5SSZRPHJt3hQCheara5j+nHLQ8paRvVlT+ghgyX5N3BwiPmvC+e9iUaaofj+DxrGX3cTo5hehG2b71sY3xdC5OIhEGRfkAqIAEw6eaU6a/ymNsByRgVByfQaQIDAQAB"; +- private static final String TEMP_PUBKEY_3072 = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAm0yQ0y+8YOTWkye5qFuqNI/qC4wtjEjNnoZaqSZUOJLg6ZRDlsZoOiblJpw65rPjaPcSp/inqYfCCA5mISYaqfcoB80LCnw1+DAv8tcvwUtytQYXHVj2gbyuVHaBgD4n4j/wFV80sF3OTQcPKYmeTfWRtv2xZQMK9rYfa8Le+DAZyOWPk4+RtTIRPa5R9arLqE+ONgUcrD3NvewOdsCrT7flJnFdx8TGl5ftxVWYlHRSg+wEB8pQZlw0BSDlQGHXIRjBKT2+iCkYzuKPWpMbu42PnBaQTcvjD3cl8MjLQcZp6v39bU1Du0C0LYunhvIWidwKnCOGOYu+a0VKuHxH8odjFdPoWGmP+orllkwSZzhWayYJxGpJJQlWcM05uD6qDF67WQnuYsliVH4LNiSjf/iPSpr0tzDXOtdeVsiQgO9wYYlnooBtd1xfTmkILwt3j9ZXeBtmt4lLYxbLo2ZCzkFqCCdu5FfcFgxjPaRaW0bQHKuP1woGk0rDUUbuqr+PAgMBAAE="; +- private static final String TEMP_PUBKEY_4096 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs3xoddtoCQrDpPK/45DpN/wPHO/6qrsbEDnwEnSkcLz51WHb7+CEUP9oxuE8vPn9JXcLdZkgPcmfMVibSUEJVUCXPibGTqAJ/7RAAm+/FhdL02N57hpgLzbIPbIaTP00z/jbTqR4a0uV49fnEPqrhA/KoUmOn3eoiAPAB5xNSauFOmMZXv2gr4akNxvSiZ/59ddYF+DBEFSs4ufCqIqBWYAMMo78eskgm/ZUyv7OZzG+8c1nncdnrNk/JtXauANu8NUQXX2qllmEOioY6gnalpR26fwOscjkvHDTvRQmSIqceWdd5P6OMHJwzTVG8d4b0f150o1RTzU3gvg9/qXvbOGcnH2TXZjYi02mhyXgPrimZepKyDr2LjeAEZbfAAXecaMhjrDZEkDZNFWe4eoG2JuE34TODeiCLMBql6VTgOvCFW3to32aBwNLpCV4hi5rKLnPMlf8Tz0zYvGqDeCp4zzy6C9tosiYfHIkVU/AVqK9PoY0RsLnBzHOV7Jl2VgHr8Ro+C66+leajssAemK8swcj2AZEOuVLlsdCvguUn6XUyDqI3tIfnoLK690hG1znuIWzFZzzivZ5ZwgfxguCly9zDArc7i6YHxOR2lcUrM0VfHmyHpE9JNfarEgAPS59ASG7y14LOvp4yYKNz10TtetwkSfpcjqiuWHtIDi9sjMCAwEAAQ=="; ++ // DO NOT REMOVE ++ private static final String TEMP_PUBKEY_RSA_1024 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBz6H2rT2r1RpHdr3JyYr7thSjfwWPbIJ6U09NziHSekLsNZQKsjdLS/LPCfe/aXkhpzPztlx++tkPucpt/xT0exp08feAPIE+Y6gVoyXzEw+Ztz+Zez9Y1cQWxAyp7z11flytjL+4zBGDXmEoe3ZlQvij9DGypPjBC9PhWm0lBwIDAQAB"; ++ private static final String TEMP_PUBKEY_RSA_2048 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4Ha+CxWDPAHEl9+u57U3UCw8bfG/ZN3cVTrQgj/p8ak12NYUWt0ZI/xCcLj7gKwFPbNMTDwzizRPZuxKJT7fHgW8a1BQDUL2VGfx7O0A7KlLqcpVc6VKsQx5caP3hrB38Q5xnTKeVee9cBrd8An+veZ2QV6mHLEU8iMCN2No/t1oO+aYje42XloNRblXVQAOYW+3aMCam2kIKWUqLvA3Sbf2BPR2x5SSZRPHJt3hQCheara5j+nHLQ8paRvVlT+ghgyX5N3BwiPmvC+e9iUaaofj+DxrGX3cTo5hehG2b71sY3xdC5OIhEGRfkAqIAEw6eaU6a/ymNsByRgVByfQaQIDAQAB"; ++ private static final String TEMP_PUBKEY_RSA_3072 = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAm0yQ0y+8YOTWkye5qFuqNI/qC4wtjEjNnoZaqSZUOJLg6ZRDlsZoOiblJpw65rPjaPcSp/inqYfCCA5mISYaqfcoB80LCnw1+DAv8tcvwUtytQYXHVj2gbyuVHaBgD4n4j/wFV80sF3OTQcPKYmeTfWRtv2xZQMK9rYfa8Le+DAZyOWPk4+RtTIRPa5R9arLqE+ONgUcrD3NvewOdsCrT7flJnFdx8TGl5ftxVWYlHRSg+wEB8pQZlw0BSDlQGHXIRjBKT2+iCkYzuKPWpMbu42PnBaQTcvjD3cl8MjLQcZp6v39bU1Du0C0LYunhvIWidwKnCOGOYu+a0VKuHxH8odjFdPoWGmP+orllkwSZzhWayYJxGpJJQlWcM05uD6qDF67WQnuYsliVH4LNiSjf/iPSpr0tzDXOtdeVsiQgO9wYYlnooBtd1xfTmkILwt3j9ZXeBtmt4lLYxbLo2ZCzkFqCCdu5FfcFgxjPaRaW0bQHKuP1woGk0rDUUbuqr+PAgMBAAE="; ++ private static final String TEMP_PUBKEY_RSA_4096 = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs3xoddtoCQrDpPK/45DpN/wPHO/6qrsbEDnwEnSkcLz51WHb7+CEUP9oxuE8vPn9JXcLdZkgPcmfMVibSUEJVUCXPibGTqAJ/7RAAm+/FhdL02N57hpgLzbIPbIaTP00z/jbTqR4a0uV49fnEPqrhA/KoUmOn3eoiAPAB5xNSauFOmMZXv2gr4akNxvSiZ/59ddYF+DBEFSs4ufCqIqBWYAMMo78eskgm/ZUyv7OZzG+8c1nncdnrNk/JtXauANu8NUQXX2qllmEOioY6gnalpR26fwOscjkvHDTvRQmSIqceWdd5P6OMHJwzTVG8d4b0f150o1RTzU3gvg9/qXvbOGcnH2TXZjYi02mhyXgPrimZepKyDr2LjeAEZbfAAXecaMhjrDZEkDZNFWe4eoG2JuE34TODeiCLMBql6VTgOvCFW3to32aBwNLpCV4hi5rKLnPMlf8Tz0zYvGqDeCp4zzy6C9tosiYfHIkVU/AVqK9PoY0RsLnBzHOV7Jl2VgHr8Ro+C66+leajssAemK8swcj2AZEOuVLlsdCvguUn6XUyDqI3tIfnoLK690hG1znuIWzFZzzivZ5ZwgfxguCly9zDArc7i6YHxOR2lcUrM0VfHmyHpE9JNfarEgAPS59ASG7y14LOvp4yYKNz10TtetwkSfpcjqiuWHtIDi9sjMCAwEAAQ=="; ++ private static final String TEMP_PUBKEY_EC_NISTP256 = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEw67JdXDj1J3wwvLTYtzpyUArev/Ra2QEsHo+q5P3VcDrr0HqJGXsj5/vH7bPe4WG5OkgxmL5BiBpKpTmJMxNLg=="; ++ private static final String TEMP_PUBKEY_EC_NISTP384 = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEdjuCVoP3qykxs97Wjk2k/cEE6fza0N0Y8JRzLYNrFtOti4zKNpvYcteaYTWLKYGOUEgGuOBV9lWjEbZSH5n+AqKf+JLaTu+Qytsr9OnBu3L4r18yNdWQQo/LlaLkr5on"; ++ private static final String TEMP_PUBKEY_EC_NISTP521 = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAnGS6GRhXMwgKu+0G7BHWbu99h4KoZi4vzKvJ+QmoApZbaU0A83ayHhKp6c5mubgZY7Vq1/msGxju89QqOf25nNwBOl9Y0IYG+/LMSjtSR1rU+MI00iyrjx3GgnC0lbxZD6KiPqMNlx5h4oyiy6d+xYfIweSF+QYVm53s4Q4OWVEhz54="; + + public ServerKeygenUserKeyDefault() { + super(); +@@ -254,11 +263,10 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + throws EProfileException { + CertificateX509Key certKey = null; + String method = "ServerKeygenUserKeyDefault: populate: "; +- CMS.debug(method + "in here"); ++ CMS.debug(method + "begins"); + + // trigger serverSide keygen enrollment + try { +- // Todo: remove debug test print; encrypt the passwd + String p12passwd = request.getExtDataInString("serverSideKeygenP12Passwd"); + if (p12passwd == null || p12passwd.length() == 0) { + CMS.debug(method + "p12passwd not found"); +@@ -270,7 +278,8 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + CryptoManager cm = CryptoManager.getInstance(); + org.mozilla.jss.crypto.X509Certificate transCert = null; + try { +- transCert = cm.findCertByNickname("KRA Transport Certificate"); ++ String transportNickname = CMS.getConfigStore().getString("ca.connector.KRA.transportCertNickname", "KRA Transport Certificate"); ++ transCert = cm.findCertByNickname(transportNickname); + } catch (Exception e) { + CMS.debug(method + "'KRA transport certificate' not found in nssdb; need to be manually setup for Server-Side keygen enrollment"); + throw new EPropertyException(CMS.getUserMessage("CMS_MISSING_KRA_TRANSPORT_CERT_IN_CA_NSSDB")); +@@ -323,7 +332,17 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + wrapAlgorithm); + CMS.debug(method + " transWrappedSessionKey.length =" +transWrappedSessionKey.length); + ++ CertificateSubjectName reqSubj = ++ request.getExtDataInCertSubjectName(IEnrollProfile.REQUEST_SUBJECT_NAME); ++ String subj = "unknown serverKeyGenUser"; ++ if (reqSubj != null) { ++ X500Name xN = reqSubj.getX500Name(); ++ subj = xN.toString(); ++ CMS.debug(method + "subj = " + subj); ++ } + // store in request to pass to kra ++ request.setExtData(IRequest.SECURITY_DATA_CLIENT_KEY_ID, ++ subj); + request.setExtData("serverSideKeygenP12PasswdEnc", + sessionWrappedPassphrase); + request.setExtData("serverSideKeygenP12PasswdTransSession", +@@ -339,7 +358,7 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + String keyTypeStr = request.getExtDataInString("keyType"); + String keyType = "RSA"; + int keySize = 2048; +- String curveName = "nistp521"; ++ String curveName = "nistp256"; + + // Populate the keyType and keySize/keyCurve + +@@ -350,6 +369,7 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + CMS.debug("ServerKeygenUserKeyDefault: populate: keyType in request null; default to RSA"); + } + ++ boolean isEC = false; + String keySizeCurveStr = request.getExtDataInString("keySize"); + + if (keyType.contentEquals("RSA")) { +@@ -361,6 +381,7 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + } + // Do things when RSA is selected + } else if (keyType.contentEquals("EC")) { ++ isEC = true; + // TODO: dmoluguw: Fix the following to generate right Key ECC keys + + if (keySizeCurveStr != null && !keySizeCurveStr.isEmpty()) { +@@ -383,31 +404,49 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + } + + /* +- * it is necessary to put in a static fake key here to prevent +- * issue; The fake key will be replaced later once KRA generates +- * the real keys ++ * DO NOT REMOVE ++ * currently, it is necessary to put in a static placeholder fake ++ * key here to prevent issue; The fake key will be replaced later ++ * once KRA generates the real keys ++ * ++ * TODO: perhaps find out how to get around not breaking ++ * the code without fake keys + */ + +- // dmoluguw: TODO: The below values seem to be for development purposes, +- // and will probably work only with keyType="RSA" +- + String pubKeyStr = ""; +- switch (keySize) { ++ if (!isEC) { ++ switch (keySize) { + case 1024: +- pubKeyStr = TEMP_PUBKEY_1024; ++ pubKeyStr = TEMP_PUBKEY_RSA_1024; + break; + case 2048: +- pubKeyStr = TEMP_PUBKEY_2048; ++ pubKeyStr = TEMP_PUBKEY_RSA_2048; + break; + case 3072: +- pubKeyStr = TEMP_PUBKEY_3072; ++ pubKeyStr = TEMP_PUBKEY_RSA_3072; + break; + case 4096: +- pubKeyStr = TEMP_PUBKEY_4096; ++ pubKeyStr = TEMP_PUBKEY_RSA_4096; + break; + default: + CMS.debug("ServerKeygenUserKeyDefault: populate: unsupported keySize: " + keySize); + break; ++ } ++ } else { ++ switch (curveName) { ++ case "nistp256": ++ pubKeyStr = TEMP_PUBKEY_EC_NISTP256; ++ break; ++ case "nistp384": ++ pubKeyStr = TEMP_PUBKEY_EC_NISTP384; ++ break; ++ case "nistp521": ++ pubKeyStr = TEMP_PUBKEY_EC_NISTP521; ++ break; ++ default: ++ CMS.debug("ServerKeygenUserKeyDefault: populate: unsupported cureveName: " + curveName); ++ break; ++ } + } + byte[] certKeyData = CryptoUtil.base64Decode(pubKeyStr); + if (certKeyData != null) { +diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java +index 145fd5f..0c65702 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/base/CMSServlet.java +@@ -573,7 +573,6 @@ public abstract class CMSServlet extends HttpServlet { + + protected void outputArgBlockAsXML(XMLObject xmlObj, Node parent, + String argBlockName, IArgBlock argBlock) { +- CMS.debug("CMSServlet:outputArgBlockAsXML: begins"); + Node argBlockContainer = xmlObj.createContainer(parent, argBlockName); + + if (argBlock != null) { +@@ -585,11 +584,9 @@ public abstract class CMSServlet extends HttpServlet { + xmlObj.addItemToContainer(argBlockContainer, name, val); + } + } +- CMS.debug("CMSServlet:outputArgBlockAsXML: ends"); + } + + protected void outputXML(HttpServletResponse httpResp, CMSTemplateParams params) { +- CMS.debug("CMSServlet:outputXML: begins"); + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); +@@ -616,7 +613,6 @@ public abstract class CMSServlet extends HttpServlet { + } catch (Exception e) { + CMS.debug("failed in outputing XML " + e); + } +- CMS.debug("CMSServlet:outputXML: ends"); + } + + protected void renderTemplate( +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +index b369fc8..5d39f24 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +@@ -450,17 +450,20 @@ public class ConnectorServlet extends CMSServlet { + try { + IRequestQueue queue = mAuthority.getRequestQueue(); + String srcid = source + ":" + msg.getReqId(); ++ CMS.debug("ConnectorServlet:processRequest: srcid =" + srcid); + + // find request in request queue and return result. + RequestId thisreqid = queue.findRequestBySourceId(srcid); + IRequest thisreq = null; + + if (thisreqid != null) { ++ CMS.debug("ConnectorServlet:processRequest: thisreqid not null:" + thisreqid); + thisreq = queue.findRequest(thisreqid); + if (thisreq == null) { + // strange case. + String errormsg = "Cannot find request in request queue " + + thisreqid; ++ CMS.debug("ConnectorServlet:processRequest: " + errormsg); + + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage( +@@ -484,8 +487,18 @@ public class ConnectorServlet extends CMSServlet { + + throw new EBaseException(errormsg); + } else { +- mAuthority.log(ILogger.LL_INFO, +- "Found request " + thisreqid + " for " + srcid); ++ String errormsg = "Found request " + thisreqid + " for " + srcid; ++ // for Server-Side Keygen, it could be the 2nd trip ++ // where stage was Request.SSK_STAGE_KEYGEN going on ++ // IRequest.SSK_STAGE_KEY_RETRIEVE ++ String sskKeygenStage = thisreq.getExtDataInString(IRequest.SSK_STAGE); ++ if (sskKeygenStage!= null && sskKeygenStage.equalsIgnoreCase(IRequest.SSK_STAGE_KEYGEN)) { ++ CMS.debug("ConnectorServlet:processRequest: Stage=" + sskKeygenStage); ++ } else { ++ ++ mAuthority.log(ILogger.LL_INFO, errormsg); ++ CMS.debug("ConnectorServlet:processRequest: " + errormsg); ++ + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + +@@ -505,13 +518,14 @@ public class ConnectorServlet extends CMSServlet { + // does not yet matter at this point! + + return replymsg; ++ } + } + } + +-/* +- // cfu: let's find out what's in the request ++ thisreq = queue.newRequest(msg.getReqType()); ++ /* cfu: let's find out what's in the request ++ CMS.debug("ConnectorServlet: cfu see what's in request"); + Enumeration ereq = thisreq.getExtDataKeys(); +- + while (ereq.hasMoreElements()) { + String reqKey = ereq.nextElement(); + String reqVal = thisreq.getExtDataInString(reqKey); +@@ -521,14 +535,9 @@ public class ConnectorServlet extends CMSServlet { + CMS.debug("ConnectorServlet: - " + reqKey + ": no value"); + } + } +-*/ ++ */ + +- thisreq = queue.newRequest(msg.getReqType()); + // if not found process request. +-/*cfu +- CMS.debug("ConnectorServlet: created reqType=" +msg.getReqType()+ +- " requestId=" + thisreq.getRequestId().toString() + " requestStatus=" + thisreq.getRequestStatus().toString()); +-*/ + CMS.debug("ConnectorServlet: created requestId=" + + thisreq.getRequestId().toString()); + thisreq.setSourceId(srcid); +@@ -540,6 +549,24 @@ public class ConnectorServlet extends CMSServlet { + // then this code does NOT need to be contained within its + // own special try/catch block. + msg.toRequest(thisreq); ++ // reset CA's request dbStatus and requestStatus got inadvertantly ++ // transferred over ++ thisreq.setExtData("dbStatus", "NOT_UPDATED"); ++ thisreq.setExtData(IRequest.REQ_STATUS, "begin"); ++ ++ /* cfu: let's find out what's in the request again ++ CMS.debug("ConnectorServlet: cfu see again what's in request"); ++ ereq = thisreq.getExtDataKeys(); ++ while (ereq.hasMoreElements()) { ++ String reqKey = ereq.nextElement(); ++ String reqVal = thisreq.getExtDataInString(reqKey); ++ if (reqVal != null) { ++ CMS.debug("ConnectorServlet: - " + reqKey + ": " + reqVal); ++ } else { ++ CMS.debug("ConnectorServlet: - " + reqKey + ": no value"); ++ } ++ } ++ */ + + boolean isSSKeygen = false; + String isSSKeygenStr = thisreq.getExtDataInString("isServerSideKeygen"); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +index f71d754..3bc1853 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +@@ -179,15 +179,14 @@ public class ProfileProcessServlet extends ProfileServlet { + String p12Str = req.getExtDataInString("req_issued_p12"); + if (p12Str == null) { + // not server-side keygen +- CMS.debug("ProfileProcessServlet:cfu: no p12; not server-side keygen"); ++ // CMS.debug("ProfileProcessServlet:cfu: no p12; not server-side keygen"); + outputTemplate(request, response, args); + } else { + // found pkcs12 blob ++ CMS.debug("ProfileProcessServlet: found p12 " /* + p12Str*/); + byte[] p12blob = null; + HttpServletResponse p12_response = cmsReq.getHttpResp(); +- CMS.debug("ProfileProcessServlet:cfu: found p12 =" + +- p12Str/*ing.toString()*/); +- p12blob = Utils.base64decode(p12Str/*ing.toString()*/); ++ p12blob = Utils.base64decode(p12Str); + OutputStream bos = p12_response.getOutputStream(); + p12_response.setContentType("application/x-pkcs12"); + p12_response.setContentLength(p12blob.length); +diff --git a/base/server/cmsbundle/src/audit-events.properties b/base/server/cmsbundle/src/audit-events.properties +index 0ff7b4e..d3ac517 100644 +--- a/base/server/cmsbundle/src/audit-events.properties ++++ b/base/server/cmsbundle/src/audit-events.properties +@@ -633,6 +633,59 @@ LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION_2=:[AuditEven + # Available Audit Events - Enabled by default: Yes + ######################################################################### + # ++# Event: SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST ++# Description: This event is used when Server-Side Keygen enrollment keygen request is made. ++# Applicable subsystems: CA ++# Enabled by default: Yes ++# Fields: ++# - SubjectID: ++# - Outcome: ++# - RequestID: ++# - ClientID: ++# ++LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST=:[AuditEvent=SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST]{0} Server-Side Keygen enrollment keygen request made ++# ++# Event: SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST_PROCESSED ++# Description: This event is used when a request to do Server-Side Keygen enrollment keygen has been processed ++# is processed. ++# Applicable subsystems: KRA ++# Enabled by default: Yes ++# Fields: ++# - SubjectID: ++# - Outcome: ++# - RequestID: ++# - ClientID: ++# - FailureReason: ++# ++LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST_PROCESSED=:[AuditEvent=SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST_PROCESSED]{0} Server-Side Keygen enrollment keygen request processed ++# ++# Event: SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST ++# Description: This event is used when Server-Side Keygen enrollment key retrieval request is made. ++# Applicable subsystems: CA ++# Enabled by default: Yes ++# Fields: ++# - SubjectID: ++# - Outcome: ++# - RequestID: ++# - ClientID: ++# ++LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST=:[AuditEvent=SERVER_SIDE_KEYGEN_ENROLL_KEYGEN_REQUEST]{0} Server-Side Keygen enrollment retrieval request made ++# ++# Event: SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST_PROCESSED ++# Description: This event is used when a request to do Server-Side Keygen enrollment retrieval has been processed ++# is processed. ++# Applicable subsystems: KRA ++# Enabled by default: Yes ++# Fields: ++# - SubjectID: ++# - Outcome: ++# - RequestID: ++# - ClientID: ++# - FailureReason: ++# ++LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_ENROLL_KEY_RETRIEVAL_REQUEST_PROCESSED=:[AuditEvent=SERVER_SIDE_KEYGEN_ENROLL_RETRIEVAL_REQUEST_PROCESSED]{0} Server-Side Keygen enrollment retrieval request processed ++######### ++# + # Event: ASYMKEY_GENERATION_REQUEST + # Description: This event is used when asymmetric key generation request is made. + # Applicable subsystems: KRA +diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java +index 0851826..24c2f77 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java +@@ -568,10 +568,12 @@ public abstract class ARequestQueue + + // by default, write request to LDAP + if (delayLDAPCommit == null || !delayLDAPCommit.equals("true")) { ++ CMS.debug("ARequestQueue: updateRequest(): delayLDAPCommit is false"); + // TODO: use a state flag to determine whether to call + // addRequest or modifyRequest (see newRequest as well) + modifyRequest(r); +- } // else: delay the write to ldap ++ } else //: delay the write to ldap ++ CMS.debug("ARequestQueue: updateRequest(): delayLDAPCommit is true"); + } + + // PRIVATE functions +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta-2.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta-2.patch new file mode 100644 index 0000000..40ee11f --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta-2.patch @@ -0,0 +1,326 @@ +From d98aed0cbb25deaa954289e7f870c10edde688dd Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Mon, 18 May 2020 19:14:41 -0400 +Subject: [PATCH 1/2] Bug 1794213 Add Directory-based-auth profile for + SeverSide Keygen + +This patch adds caServerKeygen_DirUserCert.cfg, which is a profile using +directory-based authentication for severSide Keygen enrollment. +One is required to set up UserDirEnrollment in CS.cfg. + +It also contains some misc cleanup such as removal of unneeded imports +and debugs, as well as perfecting a couple error handling stemmed from +upstream review. + +https://bugzilla.redhat.com/show_bug.cgi?id=1794213 +(cherry picked from commit 9e2bb93bb435e658a15ab8572a61d6481bb4fed8) +--- + base/ca/shared/conf/CS.cfg | 4 +- + .../profiles/ca/caServerKeygen_DirUserCert.cfg | 104 +++++++++++++++++++++ + base/kra/src/com/netscape/kra/RecoveryService.java | 2 +- + .../cms/profile/common/CAEnrollProfile.java | 2 + + .../profile/def/ServerKeygenUserKeyDefault.java | 12 ++- + .../cms/servlet/connector/ConnectorServlet.java | 1 - + .../netscape/cmscore/request/ARequestQueue.java | 5 +- + 7 files changed, 119 insertions(+), 11 deletions(-) + create mode 100644 base/ca/shared/profiles/ca/caServerKeygen_DirUserCert.cfg + +diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg +index 004efdc..2c50831 100644 +--- a/base/ca/shared/conf/CS.cfg ++++ b/base/ca/shared/conf/CS.cfg +@@ -976,7 +976,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=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caServerKeygen_UserCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSharedTokenCert,caECFullCMCSharedTokenCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,caTokenUserDelegateAuthKeyEnrollment,caTokenUserDelegateSigningKeyEnrollment ++profile.list=caCMCserverCert,caCMCECserverCert,caCMCECsubsystemCert,caCMCsubsystemCert,caCMCauditSigningCert,caCMCcaCert,caCMCocspCert,caCMCkraTransportCert,caCMCkraStorageCert,caServerKeygen_UserCert,caServerKeygen_DirUserCert,caUserCert,caECUserCert,caUserSMIMEcapCert,caDualCert,caDirBasedDualCert,AdminCert,ECAdminCert,caSignedLogCert,caTPSCert,caRARouterCert,caRouterCert,caServerCert,caECServerCert,caSubsystemCert,caECSubsystemCert,caOtherCert,caCACert,caCMCcaCert,caCrossSignedCACert,caInstallCACert,caRACert,caOCSPCert,caStorageCert,caTransportCert,caDirPinUserCert,caECDirPinUserCert,caDirUserCert,caECDirUserCert,caAgentServerCert,caECAgentServerCert,caAgentFileSigning,caCMCUserCert,caCMCECUserCert,caFullCMCUserCert,caECFullCMCUserCert,caFullCMCUserSignedCert,caECFullCMCUserSignedCert,caFullCMCSharedTokenCert,caECFullCMCSharedTokenCert,caSimpleCMCUserCert,caECSimpleCMCUserCert,caTokenDeviceKeyEnrollment,caTokenUserEncryptionKeyEnrollment,caTokenUserSigningKeyEnrollment,caTempTokenDeviceKeyEnrollment,caTempTokenUserEncryptionKeyEnrollment,caTempTokenUserSigningKeyEnrollment,caAdminCert,caECAdminCert,caInternalAuthServerCert,caECInternalAuthServerCert,caInternalAuthTransportCert,caInternalAuthDRMstorageCert,caInternalAuthSubsystemCert,caECInternalAuthSubsystemCert,caInternalAuthOCSPCert,caInternalAuthAuditSigningCert,DomainController,caDualRAuserCert,caRAagentCert,caRAserverCert,caUUIDdeviceCert,caSSLClientSelfRenewal,caDirUserRenewal,caManualRenewal,caTokenMSLoginEnrollment,caTokenUserSigningKeyRenewal,caTokenUserEncryptionKeyRenewal,caTokenUserAuthKeyRenewal,caJarSigningCert,caIPAserviceCert,caEncUserCert,caSigningUserCert,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 +@@ -1133,6 +1133,8 @@ profile.caTransportCert.class_id=caEnrollImpl + profile.caTransportCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caTransportCert.cfg + profile.caServerKeygen_UserCert.class_id=caEnrollImpl + profile.caServerKeygen_UserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caServerKeygen_UserCert.cfg ++profile.caServerKeygen_DirUserCert.class_id=caEnrollImpl ++profile.caServerKeygen_DirUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caServerKeygen_DirUserCert.cfg + profile.caUserCert.class_id=caEnrollImpl + profile.caUserCert.config=[PKI_INSTANCE_PATH]/[PKI_SUBSYSTEM_TYPE]/profiles/ca/caUserCert.cfg + profile.caECUserCert.class_id=caEnrollImpl +diff --git a/base/ca/shared/profiles/ca/caServerKeygen_DirUserCert.cfg b/base/ca/shared/profiles/ca/caServerKeygen_DirUserCert.cfg +new file mode 100644 +index 0000000..ea1acfb +--- /dev/null ++++ b/base/ca/shared/profiles/ca/caServerKeygen_DirUserCert.cfg +@@ -0,0 +1,104 @@ ++desc=This certificate profile is for enrolling user certificates using server-side Key generation with Directory-based authentication. ++visible=true ++enable=true ++enableBy=admin ++name=Directory-authenticated User Dual-Use Certificate Enrollment using server-side Key generation ++auth.instance_id=UserDirEnrollment ++input.list=i1,i2,i3 ++input.i1.class_id=serverKeygenInputImpl ++input.i2.class_id=subjectNameInputImpl ++input.i3.class_id=submitterInfoInputImpl ++output.list=o1 ++output.o1.class_id=pkcs12OutputImpl ++policyset.list=userCertSet ++policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9 ++policyset.userCertSet.1.constraint.class_id=subjectNameConstraintImpl ++policyset.userCertSet.1.constraint.name=Subject Name Constraint ++policyset.userCertSet.1.constraint.params.pattern=UID=.* ++policyset.userCertSet.1.constraint.params.accept=true ++policyset.userCertSet.1.default.class_id=userSubjectNameDefaultImpl ++policyset.userCertSet.1.default.name=Subject Name Default ++policyset.userCertSet.1.default.params.name= ++policyset.userCertSet.10.constraint.class_id=renewGracePeriodConstraintImpl ++policyset.userCertSet.10.constraint.name=Renewal Grace Period Constraint ++policyset.userCertSet.10.constraint.params.renewal.graceBefore=30 ++policyset.userCertSet.10.constraint.params.renewal.graceAfter=30 ++policyset.userCertSet.10.default.class_id=noDefaultImpl ++policyset.userCertSet.10.default.name=No Default ++policyset.userCertSet.2.constraint.class_id=validityConstraintImpl ++policyset.userCertSet.2.constraint.name=Validity Constraint ++policyset.userCertSet.2.constraint.params.range=365 ++policyset.userCertSet.2.constraint.params.notBeforeCheck=false ++policyset.userCertSet.2.constraint.params.notAfterCheck=false ++policyset.userCertSet.2.default.class_id=validityDefaultImpl ++policyset.userCertSet.2.default.name=Validity Default ++policyset.userCertSet.2.default.params.range=180 ++policyset.userCertSet.2.default.params.startTime=0 ++policyset.userCertSet.3.constraint.class_id=keyConstraintImpl ++policyset.userCertSet.3.constraint.name=Key Constraint ++policyset.userCertSet.3.constraint.params.keyType=- ++policyset.userCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096,nistp256,nistp384,nistp521 ++policyset.userCertSet.3.default.class_id=serverKeygenUserKeyDefaultImpl ++policyset.userCertSet.3.default.name=Server-Side Keygen Default ++policyset.userCertSet.3.default.params.keyType=RSA ++policyset.userCertSet.3.default.params.keySize=2048 ++policyset.userCertSet.3.default.params.enableArchival=true ++policyset.userCertSet.4.constraint.class_id=noConstraintImpl ++policyset.userCertSet.4.constraint.name=No Constraint ++policyset.userCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl ++policyset.userCertSet.4.default.name=Authority Key Identifier Default ++policyset.userCertSet.5.constraint.class_id=noConstraintImpl ++policyset.userCertSet.5.constraint.name=No Constraint ++policyset.userCertSet.5.default.class_id=authInfoAccessExtDefaultImpl ++policyset.userCertSet.5.default.name=AIA Extension Default ++policyset.userCertSet.5.default.params.authInfoAccessADEnable_0=true ++policyset.userCertSet.5.default.params.authInfoAccessADLocationType_0=URIName ++policyset.userCertSet.5.default.params.authInfoAccessADLocation_0= ++policyset.userCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 ++policyset.userCertSet.5.default.params.authInfoAccessCritical=false ++policyset.userCertSet.5.default.params.authInfoAccessNumADs=1 ++policyset.userCertSet.6.constraint.class_id=keyUsageExtConstraintImpl ++policyset.userCertSet.6.constraint.name=Key Usage Extension Constraint ++policyset.userCertSet.6.constraint.params.keyUsageCritical=true ++policyset.userCertSet.6.constraint.params.keyUsageDigitalSignature=true ++policyset.userCertSet.6.constraint.params.keyUsageNonRepudiation=true ++policyset.userCertSet.6.constraint.params.keyUsageDataEncipherment=false ++policyset.userCertSet.6.constraint.params.keyUsageKeyEncipherment=true ++policyset.userCertSet.6.constraint.params.keyUsageKeyAgreement=false ++policyset.userCertSet.6.constraint.params.keyUsageKeyCertSign=false ++policyset.userCertSet.6.constraint.params.keyUsageCrlSign=false ++policyset.userCertSet.6.constraint.params.keyUsageEncipherOnly=false ++policyset.userCertSet.6.constraint.params.keyUsageDecipherOnly=false ++policyset.userCertSet.6.default.class_id=keyUsageExtDefaultImpl ++policyset.userCertSet.6.default.name=Key Usage Default ++policyset.userCertSet.6.default.params.keyUsageCritical=true ++policyset.userCertSet.6.default.params.keyUsageDigitalSignature=true ++policyset.userCertSet.6.default.params.keyUsageNonRepudiation=true ++policyset.userCertSet.6.default.params.keyUsageDataEncipherment=false ++policyset.userCertSet.6.default.params.keyUsageKeyEncipherment=true ++policyset.userCertSet.6.default.params.keyUsageKeyAgreement=false ++policyset.userCertSet.6.default.params.keyUsageKeyCertSign=false ++policyset.userCertSet.6.default.params.keyUsageCrlSign=false ++policyset.userCertSet.6.default.params.keyUsageEncipherOnly=false ++policyset.userCertSet.6.default.params.keyUsageDecipherOnly=false ++policyset.userCertSet.7.constraint.class_id=noConstraintImpl ++policyset.userCertSet.7.constraint.name=No Constraint ++policyset.userCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl ++policyset.userCertSet.7.default.name=Extended Key Usage Extension Default ++policyset.userCertSet.7.default.params.exKeyUsageCritical=false ++policyset.userCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.4 ++policyset.userCertSet.8.constraint.class_id=noConstraintImpl ++policyset.userCertSet.8.constraint.name=No Constraint ++policyset.userCertSet.8.default.class_id=subjectAltNameExtDefaultImpl ++policyset.userCertSet.8.default.name=Subject Alt Name Constraint ++policyset.userCertSet.8.default.params.subjAltNameExtCritical=false ++policyset.userCertSet.8.default.params.subjAltExtType_0=RFC822Name ++policyset.userCertSet.8.default.params.subjAltExtPattern_0=$request.requestor_email$ ++policyset.userCertSet.8.default.params.subjAltExtGNEnable_0=true ++policyset.userCertSet.8.default.params.subjAltNameNumGNs=1 ++policyset.userCertSet.9.constraint.class_id=signingAlgConstraintImpl ++policyset.userCertSet.9.constraint.name=No Constraint ++policyset.userCertSet.9.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withEC,SHA256withEC,SHA384withRSA,SHA384withEC,SHA512withEC,SHA256withRSA/PSS,SHA384withRSA/PSS,SHA512withRSA/PSS ++policyset.userCertSet.9.default.class_id=signingAlgDefaultImpl ++policyset.userCertSet.9.default.name=Signing Alg ++policyset.userCertSet.9.default.params.signingAlg=- +diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java +index c5229ea..529cb57 100644 +--- a/base/kra/src/com/netscape/kra/RecoveryService.java ++++ b/base/kra/src/com/netscape/kra/RecoveryService.java +@@ -637,7 +637,7 @@ public class RecoveryService implements IService { + pass, + /* NSS has a bug that causes any AES CBC encryption + * to use AES-256, but AlgorithmID contains chosen +- * alg. To avoid mismatch, use AES_128_CBC. */ ++ * alg. To avoid mismatch, use AES_256_CBC. */ + EncryptionAlgorithm.AES_256_CBC, + 0 /* iterations (use default) */, + priKey); +diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +index f8b547d..b0dd773 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java ++++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +@@ -156,6 +156,8 @@ public class CAEnrollProfile extends EnrollProfile { + if (kraConnector == null) { + String message = "KRA connector not configured"; + CMS.debug(method + message); ++ ++ throw new EProfileException(message); + } else { + CMS.debug(method + "request"); + kraConnector.send(request); +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +index b1eb58e..3c4e3d0 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +@@ -20,7 +20,6 @@ package com.netscape.cms.profile.def; + import java.io.ByteArrayInputStream; + import java.math.BigInteger; + import java.security.interfaces.DSAParams; +-import java.util.Enumeration; + import java.util.Locale; + import java.util.Vector; + import java.security.KeyPair; +@@ -271,6 +270,7 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + CertificateX509Key certKey = null; + String method = "ServerKeygenUserKeyDefault: populate: "; + CMS.debug(method + "begins"); ++ String errmsg = ""; + + // trigger serverSide keygen enrollment + try { +@@ -439,8 +439,9 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + pubKeyStr = TEMP_PUBKEY_RSA_4096; + break; + default: +- CMS.debug("ServerKeygenUserKeyDefault: populate: unsupported keySize: " + keySize); +- break; ++ errmsg = "unsupported keySize: " + keySize; ++ CMS.debug("ServerKeygenUserKeyDefault: populate: " + errmsg); ++ throw new EProfileException(errmsg); + } + } else { + switch (curveName) { +@@ -454,8 +455,9 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + pubKeyStr = TEMP_PUBKEY_EC_NISTP521; + break; + default: +- CMS.debug("ServerKeygenUserKeyDefault: populate: unsupported cureveName: " + curveName); +- break; ++ errmsg = "unsupported curveName: " + curveName; ++ CMS.debug("ServerKeygenUserKeyDefault: populate: " + errmsg); ++ throw new EProfileException(errmsg); + } + } + byte[] certKeyData = CryptoUtil.base64Decode(pubKeyStr); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +index fb9ed65..0e72559 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +@@ -28,7 +28,6 @@ import java.security.cert.Certificate; + import java.security.cert.CertificateException; + import java.security.cert.X509Certificate; + import java.util.Enumeration; +-import java.util.Hashtable; + + import javax.servlet.ServletConfig; + import javax.servlet.ServletException; +diff --git a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java +index 24c2f77..3941fa0 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/request/ARequestQueue.java +@@ -568,12 +568,11 @@ public abstract class ARequestQueue + + // by default, write request to LDAP + if (delayLDAPCommit == null || !delayLDAPCommit.equals("true")) { +- CMS.debug("ARequestQueue: updateRequest(): delayLDAPCommit is false"); ++ // CMS.debug("ARequestQueue: updateRequest(): delayLDAPCommit is false"); + // TODO: use a state flag to determine whether to call + // addRequest or modifyRequest (see newRequest as well) + modifyRequest(r); +- } else //: delay the write to ldap +- CMS.debug("ARequestQueue: updateRequest(): delayLDAPCommit is true"); ++ } + } + + // PRIVATE functions +-- +1.8.3.1 + + +From b12e75b4314c9d017763130683b99008d7fc22ca Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Mon, 18 May 2020 20:35:31 -0400 +Subject: [PATCH 2/2] Additional fix Bug# 1710109 - add RSA PSS support. (#414) + +Remove minor log message which was causing problems. +Fix a typo in the pkispawn code that detects PSS signing algorithms. + +Co-authored-by: Jack Magne +(cherry picked from commit f30d2a26d6484cd85415b338fd721efc6499a937) +--- + base/server/python/pki/server/deployment/pkihelper.py | 2 +- + base/util/src/netscape/security/x509/X509CertInfo.java | 6 ------ + 2 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 8c7ef51..214c9ae 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -4596,7 +4596,7 @@ class ConfigClient: + if ('pki_subsystem_signing_algorithm' in self.mdict): + if ('RSA' in self.mdict['pki_subsystem_signing_algorithm'] and + 'PSS' not in self.mdict['pki_subsystem_signing_algorithm']): +- self.mdict[''] = \ ++ self.mdict['pki_subsystem_signing_algorithm'] = \ + self.mdict['pki_subsystem_signing_algorithm'] + '/PSS' + + +diff --git a/base/util/src/netscape/security/x509/X509CertInfo.java b/base/util/src/netscape/security/x509/X509CertInfo.java +index 93377f4..083ec41 100644 +--- a/base/util/src/netscape/security/x509/X509CertInfo.java ++++ b/base/util/src/netscape/security/x509/X509CertInfo.java +@@ -34,9 +34,6 @@ import netscape.security.util.DerInputStream; + import netscape.security.util.DerOutputStream; + import netscape.security.util.DerValue; + +-import org.slf4j.Logger; +-import org.slf4j.LoggerFactory; +- + /** + * The X509CertInfo class represents X.509 certificate information. + * +@@ -75,8 +72,6 @@ public class X509CertInfo implements CertAttrSet, Serializable { + * get, set, delete methods of Certificate, x509 type. + */ + +- private static Logger logger = LoggerFactory.getLogger(X509CertInfo.class); +- + public static final String IDENT = "x509.info"; + // Certificate attribute names + public static final String NAME = "info"; +@@ -621,7 +616,6 @@ public class X509CertInfo implements CertAttrSet, Serializable { + return (serialNum.get(attrName.getSuffix())); + } + case (ATTR_ALGORITHM): +- logger.warn("X509CertInfo.get(alg): " + this.toString()); + if (attrName.getSuffix() == null) { + return (algId); + } else { +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta.patch new file mode 100644 index 0000000..9de03c8 --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-post-beta.patch @@ -0,0 +1,530 @@ +From cc6d37299e5f1158c7a579c963b1ecf350948d9e Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Fri, 24 Apr 2020 15:18:29 -0700 +Subject: [PATCH 1/2] My 10.5 (#389) + +* Add AlgorithmId.toStringWithParams, fix toString + + PKI's usage of AlgorithmId.toString() doesn't handle having the + parameters encoded in the toString() representation of the id. + Move toString() back to only having the contents of algName, and + move parameters to a separate method. + + Fix courtesy ascheel. + +* Apply contributed patch - TPS - Searching the certificate DB for a brand new token takes too long. Bad search filter + +Resolves: +Bug #1710975 - TPS - Searching the certificate DB for a band new token takes too long. Bad search filter. +Submited by RHCS-maint. + +Co-authored-by: Jack Magne +(cherry picked from commit c02de65c98232a848bbeed67c872fd57f51a49fe) +--- + .../tps/src/org/dogtagpki/server/tps/TPSTokendb.java | 14 ++++++++++---- + .../util/src/netscape/security/x509/AlgorithmId.java | 20 +++++++++++++++++--- + 2 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java +index 49bfb7f..446fa3f 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java ++++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java +@@ -370,7 +370,10 @@ public class TPSTokendb { + private boolean isCertOnToken(TPSCertRecord cert, String cuid) { + String method = "TPSTokendb: isCertOnToken: "; + boolean result = false; +- String filter = cuid; ++ ++ Map attributes = new HashMap(); ++ attributes.put("tokenID", cuid); ++ + Iterator records; + if (cert == null) { + CMS.debug(method + "input param cert null"); +@@ -385,7 +388,7 @@ public class TPSTokendb { + "cert serial = " + cert.getSerialNumber() + + "; token cuid = " + cuid); + try { +- records = tps.certDatabase.findRecords(filter).iterator(); ++ records = tps.certDatabase.findRecords(null, attributes).iterator(); + } catch (Exception e) { + CMS.debug(method + ":" + e); + return false; +@@ -430,10 +433,13 @@ public class TPSTokendb { + throw new Exception(method + ": cuid null"); + + CMS.debug(method + ":" + " begins for cuid =" + cuid); +- String filter = cuid; ++ ++ Map attributes = new HashMap(); ++ attributes.put("tokenID", cuid); ++ + Iterator records; + try { +- records = tps.certDatabase.findRecords(filter).iterator(); ++ records = tps.certDatabase.findRecords(null, attributes).iterator(); + } catch (Exception e) { + CMS.debug(method + ":" + e); + throw new Exception(method + ":" + e); +diff --git a/base/util/src/netscape/security/x509/AlgorithmId.java b/base/util/src/netscape/security/x509/AlgorithmId.java +index 6ce30e9..a5e4906 100644 +--- a/base/util/src/netscape/security/x509/AlgorithmId.java ++++ b/base/util/src/netscape/security/x509/AlgorithmId.java +@@ -624,10 +624,24 @@ public class AlgorithmId implements Serializable, DerEncoder { + } + + /** +- * Returns a string describing the algorithm and its parameters. ++ * Returns a string describing only the algorithm without parameters. ++ * ++ * Use toStringWithParams() for algorithm name and paramaters, or ++ * paramsToString() for just parameters. + */ + public String toString() { +- return (algName() + " " + paramsToString()); ++ return algName(); ++ } ++ ++ /** ++ * Returns a string describing the algorithm and its parameters. ++ */ ++ public String toStringWithParams() { ++ if (params == null) { ++ return algName(); ++ } ++ ++ return algName() + " " + paramsToString(); + } + + /** +@@ -1030,7 +1044,7 @@ public class AlgorithmId implements Serializable, DerEncoder { + */ + public static final String[] ALL_SIGNING_ALGORITHMS = new String[] + { +- "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withRSA","SHA256withRSA/PSS","SHA384withRSA/PSS","SHA5121withRSA/PSS", ++ "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withRSA","SHA256withRSA/PSS","SHA384withRSA/PSS","SHA512withRSA/PSS", + "SHA256withEC", "SHA384withEC", "SHA512withEC", "SHA1withEC" }; + + public static void dumpBytes(byte[] data) +-- +1.8.3.1 + + +From 5cfb515d0ab1a32a1dafa1c12088e52c21569bd8 Mon Sep 17 00:00:00 2001 +From: Christina Fu +Date: Mon, 4 May 2020 09:43:30 -0700 +Subject: [PATCH 2/2] Bug 1794213 Additional Server-Side Kyegen Enrollment + support and touch-up + +This patch + - adds support for automatic approval (e.g. UidPwdDirAuth) + - adds support for the "enableArchival" parameter for ServerKeygenUserKeyDefault per profile + - fixes the accidental disablement of DSA key generation in AsymKeyGenService.java + - Clears some of the unneeded items in the request + - zeroize password in memory + +https://bugzilla.redhat.com/show_bug.cgi?id=1794213 +(cherry picked from commit 9ab687e9a5104b260c958e59b3ca87e753b2fd73) +--- + .../shared/profiles/ca/caServerKeygen_UserCert.cfg | 1 + + .../src/com/netscape/certsrv/request/IRequest.java | 1 + + .../src/com/netscape/kra/AsymKeyGenService.java | 6 ++-- + base/kra/src/com/netscape/kra/RecoveryService.java | 30 +++++++++++++++--- + .../cms/profile/common/CAEnrollProfile.java | 28 ++++++++++++++++ + .../profile/def/ServerKeygenUserKeyDefault.java | 25 ++++++++++++--- + .../cms/servlet/connector/ConnectorServlet.java | 14 -------- + .../cms/servlet/profile/ProfileProcessServlet.java | 8 ++--- + .../cms/servlet/profile/ProfileSubmitServlet.java | 37 +++++++++++++++++++++- + base/server/cmsbundle/src/UserMessages.properties | 6 ++-- + 10 files changed, 123 insertions(+), 33 deletions(-) + +diff --git a/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +index b449163..b8c3e10 100644 +--- a/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg ++++ b/base/ca/shared/profiles/ca/caServerKeygen_UserCert.cfg +@@ -42,6 +42,7 @@ policyset.userCertSet.3.default.class_id=serverKeygenUserKeyDefaultImpl + policyset.userCertSet.3.default.name=Server-Side Keygen Default + policyset.userCertSet.3.default.params.keyType=RSA + policyset.userCertSet.3.default.params.keySize=2048 ++policyset.userCertSet.3.default.params.enableArchival=true + policyset.userCertSet.4.constraint.class_id=noConstraintImpl + policyset.userCertSet.4.constraint.name=No Constraint + policyset.userCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl +diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java +index 47dde82..7193791 100644 +--- a/base/common/src/com/netscape/certsrv/request/IRequest.java ++++ b/base/common/src/com/netscape/certsrv/request/IRequest.java +@@ -199,6 +199,7 @@ public interface IRequest extends Serializable { + + // Server-side Keygen enrollment + //public static final String SERVER_SIDE_KEYGEN_ENROLL = "serverSideKeygenEnroll"; ++ public static final String SERVER_SIDE_KEYGEN_ENROLL_ENABLE_ARCHIVAL = "serverSideKeygenEnrollEnableArchival"; + public static final String SSK_STAGE = "serverSideKeygenStage"; + public static final String SSK_STAGE_KEYGEN = "serverSideKeygenStage_keygen"; + public static final String SSK_STAGE_KEY_RETRIEVE = "serverSideKeygenStage_key_retrieve"; +diff --git a/base/kra/src/com/netscape/kra/AsymKeyGenService.java b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +index 61f86ff..0aa0862 100644 +--- a/base/kra/src/com/netscape/kra/AsymKeyGenService.java ++++ b/base/kra/src/com/netscape/kra/AsymKeyGenService.java +@@ -102,9 +102,7 @@ public class AsymKeyGenService implements IService { + boolean isEC = false; + String errmsg =""; + +- if (algorithm.toUpperCase().equals("RSA")) +- keySize = Integer.valueOf(keySizeStr); +- else { ++ if (algorithm.toUpperCase().equals("EC")) { + isEC = true; + switch (keySizeStr) { + case "nistp256": +@@ -127,6 +125,8 @@ public class AsymKeyGenService implements IService { + errmsg)); + throw new EBaseException("Errors in ServerSideKeygenEnroll generating Asymmetric key: " + errmsg); + } ++ } else { ++ keySize = Integer.valueOf(keySizeStr); + } + + String realm = request.getRealm(); +diff --git a/base/kra/src/com/netscape/kra/RecoveryService.java b/base/kra/src/com/netscape/kra/RecoveryService.java +index fc6edeb..c5229ea 100644 +--- a/base/kra/src/com/netscape/kra/RecoveryService.java ++++ b/base/kra/src/com/netscape/kra/RecoveryService.java +@@ -168,7 +168,6 @@ public class RecoveryService implements IService { + isSSKeygen = true; + CryptoToken token = CryptoUtil.getKeyStorageToken("internal"); + +- // serverKeygenP12Pass = request.getExtDataInString("serverSideKeygenP12Passwd"); + byte[] sessionWrappedPassphrase = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdEnc"); + if (sessionWrappedPassphrase == null) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR" + "Server-Side Keygen Enroll Key Retrieval: sessionWrappedPassphrase not found in Request")); +@@ -210,16 +209,21 @@ public class RecoveryService implements IService { + ivps, sessionWrappedPassphrase, unwrappedSessionKey, + encryptAlgorithm); + serverKeygenP12Pass = new String(passphrase, "UTF-8"); +- // TODO: do this after it's done being used later: +- // CryptoUtil.obscureBytes(serverKeygenP12Pass, "random"); ++ CryptoUtil.obscureBytes(passphrase, "random"); + } + } catch (Exception e) { + CMS.debug("RecoveryService exception: use internal token :" + + e.toString()); + ct = cm.getInternalCryptoToken(); ++ } finally { ++ // delete SSK items from request ++ request.setExtData("serverSideKeygenP12PasswdTransSession", ""); ++ request.setExtData("serverSideKeygenP12PasswdEnc", ""); ++ request.deleteExtData("serverSideKeygenP12PasswdTransSession"); ++ request.deleteExtData("serverSideKeygenP12PasswdEnc"); + } + if (ct == null) { +- throw new EBaseException(CMS.getUserMessage("CMS_BASE_CERT_ERROR" + "cannot get crypto token")); ++ throw new EBaseException(CMS.getUserMessage("CMS_BASE_TOKEN_NOT_FOUND" + "cannot get crypto token")); + } + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); +@@ -349,6 +353,7 @@ public class RecoveryService implements IService { + //We don't need this data any more + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); + jssSubsystem.obscureBytes(privateKeyData); ++ + } + + if (statsSub != null) { +@@ -384,13 +389,28 @@ public class RecoveryService implements IService { + } + } + +- // cfu + if (isSSKeygen) { + CMS.debug("RecoveryService: putting p12 in request"); + byte[] p12b = (byte[])params.get(ATTR_PKCS12); + // IEnrollProfile.REQUEST_ISSUED_P12 + request.setExtData("req_issued_p12" /*ATTR_PKCS12*/, p12b); ++ ++ // if key archival is not enabled, delete the key record. ++ // for Server-Side keygen enrollment, key archival is determined ++ // by the enableArchival parameter in the enrollment profiile: ++ // e.g. ++ // policyset.userCertSet.3.default.params.enableArchival ++ // Note that if the enableArchival parameter does not exist in ++ // the profile, the default value to that is set to *false* ++ // in the request in ServerKeygenUserKeyDefault ++ boolean isArchival = request.getExtDataInBoolean(IRequest.SERVER_SIDE_KEYGEN_ENROLL_ENABLE_ARCHIVAL, true); ++ if (isArchival) { ++ CMS.debug("RecoveryService: serviceRequest: Server-Side Keygen isArchival true, key record kept"); ++ } else ++ mStorage.deleteKeyRecord(serialno); ++ CMS.debug("RecoveryService: serviceRequest: Server-Side Keygen isArchival false, key record not kept"); + } ++ + mKRA.log(ILogger.LL_INFO, "key " + + serialno.toString() + + " recovered"); +diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +index 138a2ec..f8b547d 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java ++++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java +@@ -131,8 +131,25 @@ public class CAEnrollProfile extends EnrollProfile { + // if PKI Archive Option present, send this request + // to DRM + byte optionsData[] = request.getExtDataInByteArray(REQUEST_ARCHIVE_OPTIONS); ++ byte[] transWrappedSessionKey = null; ++ byte[] sessionWrappedPassphrase = null; + if (isSSKeygen) { // Server-Side Keygen enrollment + request.setExtData(IRequest.SSK_STAGE, IRequest.SSK_STAGE_KEYGEN); ++ ++ /* ++ * temporarily remove the items not needed for SSK_STAGE_KEYGEN ++ * so not to pass them to KRA. ++ * They will be put back at SSK_STAGE_KEY_RETRIEVE below ++ */ ++ transWrappedSessionKey = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdTransSession"); ++ ++ sessionWrappedPassphrase = (byte[]) request.getExtDataInByteArray("serverSideKeygenP12PasswdEnc"); ++ ++ request.setExtData("serverSideKeygenP12PasswdTransSession", ""); ++ request.deleteExtData("serverSideKeygenP12PasswdTransSession"); ++ request.setExtData("serverSideKeygenP12PasswdEnc", ""); ++ request.deleteExtData("serverSideKeygenP12PasswdEnc"); ++ + try { + IConnector kraConnector = caService.getKRAConnector(); + +@@ -326,6 +343,11 @@ public class CAEnrollProfile extends EnrollProfile { + request.setExtData(IRequest.REQ_STATUS, "begin"); + request.setExtData("requestType", "recovery"); + request.setExtData("cert", theCert); //recognized by kra ++ ++ // putting them back ++ request.setExtData("serverSideKeygenP12PasswdEnc", sessionWrappedPassphrase); ++ request.setExtData("serverSideKeygenP12PasswdTransSession", transWrappedSessionKey); ++ + try { + IConnector kraConnector = caService.getKRAConnector(); + +@@ -376,6 +398,12 @@ public class CAEnrollProfile extends EnrollProfile { + throw (ERejectException) e; + } + throw new EProfileException(e); ++ } finally { ++ // cfu TODO: clean them ++ request.setExtData("serverSideKeygenP12PasswdTransSession", ""); ++ request.deleteExtData("serverSideKeygenP12PasswdTransSession"); ++ request.setExtData("serverSideKeygenP12PasswdEnc", ""); ++ request.deleteExtData("serverSideKeygenP12PasswdEnc"); + } + CMS.debug(method + "isSSKeygen: response received from KRA"); + } +diff --git a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +index 1e2a787..b1eb58e 100644 +--- a/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java ++++ b/base/server/cms/src/com/netscape/cms/profile/def/ServerKeygenUserKeyDefault.java +@@ -68,6 +68,7 @@ import com.netscape.certsrv.logging.ILogger; + */ + public class ServerKeygenUserKeyDefault extends EnrollDefault { + ++ public static final String CONFIG_ENABLE_ARCHIVAL = "enableArchival"; + public static final String CONFIG_LEN = "keySize"; + public static final String CONFIG_TYPE = "keyType"; + public static final String VAL_LEN = "LEN"; +@@ -84,6 +85,7 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + + public ServerKeygenUserKeyDefault() { + super(); ++ addConfigName(CONFIG_ENABLE_ARCHIVAL); + addConfigName(CONFIG_TYPE); + addConfigName(CONFIG_LEN); + addValueName(VAL_TYPE); +@@ -103,18 +105,23 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + */ + + public IDescriptor getConfigDescriptor(Locale locale, String name) { +- if (name.equals(CONFIG_TYPE)) { ++ if (name.equals(CONFIG_ENABLE_ARCHIVAL)) { ++ return new Descriptor(IDescriptor.BOOLEAN, null, ++ "false", ++ CMS.getUserMessage(locale, ++ "CMS_PROFILE_SERVER_SIDE_KEYGEN_ENABLE_ARCHIVAL")); ++ } else if (name.equals(CONFIG_TYPE)) { + return new Descriptor(IDescriptor.STRING, + null, + "RSA", + CMS.getUserMessage(locale, +- "CMS_PROFILE_SERVER_KEYGEN_KEYTYPE")); ++ "CMS_PROFILE_SERVER_SIDE_KEYGEN_KEYTYPE")); + } else if (name.equals(CONFIG_LEN)) { + return new Descriptor(IDescriptor.STRING, + null, + "2048", + CMS.getUserMessage(locale, +- "CMS_PROFILE_SERVER_KEYGEN_KEYSIZE")); ++ "CMS_PROFILE_SERVER_SIDE_KEYGEN_KEYSIZE")); + } else { + return null; + } +@@ -343,11 +350,14 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + // store in request to pass to kra + request.setExtData(IRequest.SECURITY_DATA_CLIENT_KEY_ID, + subj); ++ + request.setExtData("serverSideKeygenP12PasswdEnc", + sessionWrappedPassphrase); + request.setExtData("serverSideKeygenP12PasswdTransSession", + transWrappedSessionKey); +- // delete the plain text one ++ ++ // delete ++ request.setExtData("serverSideKeygenP12Passwd", ""); + request.deleteExtData("serverSideKeygenP12Passwd"); + } + +@@ -455,6 +465,13 @@ public class ServerKeygenUserKeyDefault extends EnrollDefault { + } else { + CMS.debug("ServerKeygenUserKeyDefault: populate: serverKeygen to be implemented "); + } ++ ++ // the param "enableArchival" allows the profile to decide whether ++ // to archive the keys or not; By default, it is *false* ++ boolean enableArchival = getConfigBoolean(CONFIG_ENABLE_ARCHIVAL); ++ //CMS.debug(method + "archival enabled: " + enableArchival); ++ request.setExtData(IRequest.SERVER_SIDE_KEYGEN_ENROLL_ENABLE_ARCHIVAL, enableArchival? "true":"false"); ++ + info.set(X509CertInfo.KEY, certKey); + } catch (Exception e) { + CMS.debug("ServerKeygenUserKeyDefault: populate " + e.toString()); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +index 5d39f24..fb9ed65 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/ConnectorServlet.java +@@ -554,20 +554,6 @@ public class ConnectorServlet extends CMSServlet { + thisreq.setExtData("dbStatus", "NOT_UPDATED"); + thisreq.setExtData(IRequest.REQ_STATUS, "begin"); + +- /* cfu: let's find out what's in the request again +- CMS.debug("ConnectorServlet: cfu see again what's in request"); +- ereq = thisreq.getExtDataKeys(); +- while (ereq.hasMoreElements()) { +- String reqKey = ereq.nextElement(); +- String reqVal = thisreq.getExtDataInString(reqKey); +- if (reqVal != null) { +- CMS.debug("ConnectorServlet: - " + reqKey + ": " + reqVal); +- } else { +- CMS.debug("ConnectorServlet: - " + reqKey + ": no value"); +- } +- } +- */ +- + boolean isSSKeygen = false; + String isSSKeygenStr = thisreq.getExtDataInString("isServerSideKeygen"); + if ((isSSKeygenStr != null) && isSSKeygenStr.equalsIgnoreCase("true")) { +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +index 3bc1853..3c1c439 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java +@@ -174,16 +174,16 @@ public class ProfileProcessServlet extends ProfileServlet { + args.set(ARG_OUTPUT_LIST, outputlist); + } + +- try { //cfu +- CMS.debug("ProfileProcessServlet:cfu: p12 output process begins"); ++ try { ++ //CMS.debug("ProfileProcessServlet: p12 output process begins"); + String p12Str = req.getExtDataInString("req_issued_p12"); + if (p12Str == null) { + // not server-side keygen +- // CMS.debug("ProfileProcessServlet:cfu: no p12; not server-side keygen"); ++ // CMS.debug("ProfileProcessServlet: no p12; not server-side keygen"); + outputTemplate(request, response, args); + } else { + // found pkcs12 blob +- CMS.debug("ProfileProcessServlet: found p12 " /* + p12Str*/); ++ //CMS.debug("ProfileProcessServlet: found p12 " /* + p12Str*/); + byte[] p12blob = null; + HttpServletResponse p12_response = cmsReq.getHttpResp(); + p12blob = Utils.base64decode(p12Str); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java +index b18e407..ec13aa2 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java +@@ -20,6 +20,8 @@ package com.netscape.cms.servlet.profile; + import java.util.Enumeration; + import java.util.HashMap; + import java.util.Locale; ++import java.io.IOException; ++import java.io.OutputStream; + + import javax.servlet.ServletConfig; + import javax.servlet.ServletException; +@@ -202,10 +204,43 @@ public class ProfileSubmitServlet extends ProfileServlet { + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + +- outputTemplate(request, response, args); ++ //outputTemplate(request, response, args); ++ try { ++ //CMS.debug("ProfileSubmitServlet: p12 output process begins"); ++ String p12Str = reqs[0].getExtDataInString("req_issued_p12"); ++ if (p12Str == null) { ++ // not server-side keygen ++ // CMS.debug("ProfileProcessServlet:cfu: no p12; not server-side keygen"); ++ outputTemplate(request, response, args); ++ } else { ++ // found pkcs12 blob ++ //CMS.debug("ProfileProcessServlet: found p12 " /* + p12Str*/); ++ byte[] p12blob = null; ++ HttpServletResponse p12_response = cmsReq.getHttpResp(); ++ p12blob = Utils.base64decode(p12Str); ++ OutputStream bos = p12_response.getOutputStream(); ++ p12_response.setContentType("application/x-pkcs12"); ++ p12_response.setContentLength(p12blob.length); ++ p12_response.setHeader("Content-disposition", "attachment; filename="+ "serverKeyGenCert.p12"); ++ bos.write(p12blob); ++ bos.flush(); ++ bos.close(); ++ } ++ } catch (IOException e) { ++ CMS.debug(e); ++ setError(args, e.getMessage(), request, response); ++ return; ++ } + } + } + ++ private void setError(ArgSet args, String reason, HttpServletRequest request, HttpServletResponse response) ++ throws EBaseException { ++ args.set(ARG_ERROR_CODE, "1"); ++ args.set(ARG_ERROR_REASON, reason); ++ outputTemplate(request, response, args); ++ } ++ + public HashMap processEnrollment(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest request = cmsReq.getHttpReq(); +diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties +index 2c57c59..78687a6 100644 +--- a/base/server/cmsbundle/src/UserMessages.properties ++++ b/base/server/cmsbundle/src/UserMessages.properties +@@ -844,8 +844,9 @@ CMS_PROFILE_VALIDITY_NOT_BEFORE_GRACE_PERIOD=Grace period for Not Before being s + CMS_PROFILE_VALIDITY_RANGE=Validity Range + CMS_PROFILE_VALIDITY_RANGE_UNIT=Validity Range Unit: year, month, day (default), hour, minute + CMS_PROFILE_VALIDITY_START_TIME=Relative Start Time (in seconds) +-CMS_PROFILE_SERVER_KEYGEN_KEYTYPE=Server-side keygen key type +-CMS_PROFILE_SERVER_KEYGEN_KEYSIZE=Server-side keygen key size ++CMS_PROFILE_SERVER_SIDE_KEYGEN_KEYTYPE=Server-side keygen key type: RSA or EC ++CMS_PROFILE_SERVER_SIDE_KEYGEN_KEYSIZE=Server-side keygen key size. For RSA: 1024,2048,3072,or 4096; for EC: nistp256,nistp384,or nistp521 ++CMS_PROFILE_SERVER_SIDE_KEYGEN_ENABLE_ARCHIVAL=Server-side keygen enable key archival + CMS_PROFILE_NOT_BEFORE_RANDOM_BITS=Not Before Random Bits + CMS_PROFILE_NOT_AFTER_RANDOM_BITS=Not After Random Bits + CMS_PROFILE_BYPASS_CA_NOTAFTER=Bypass CA notAfter constraint +@@ -919,6 +920,7 @@ CMS_PROFILE_EXT_VALUE=Extension Value + CMS_PROFILE_KEY=Key + CMS_PROFILE_KEY_LEN=Key Length + CMS_PROFILE_KEY_TYPE=Key Type ++CMS_PROFILE_ENABLE_ARCHIVAL=Enable Archival + CMS_PROFILE_KEY_MIN_LEN=Min Key Length + CMS_PROFILE_KEY_MAX_LEN=Max Key Length + CMS_PROFILE_KEY_PARAMETERS=Key Lengths or Curves. For EC use comma separated list of curves, otherise use list of key sizes. Ex: 1024,2048,4096,8192 or: nistp256,nistp384,nistp521,sect163k1,nistk163 for EC. +-- +1.8.3.1 + diff --git a/SPECS/pki-core.spec b/SPECS/pki-core.spec index b413d4c..67e317a 100644 --- a/SPECS/pki-core.spec +++ b/SPECS/pki-core.spec @@ -13,7 +13,7 @@ %global package_rhel_packages 1 # Package RHCS-specific RPMS Only %global package_rhcs_packages 0 -%define pki_core_rhel_version 10.5.17 +%define pki_core_rhel_version 10.5.18 %else # Fedora always packages all RPMS %global package_fedora_packages 1 @@ -64,14 +64,14 @@ Name: pki-core %if 0%{?rhel} -Version: 10.5.17 -%define redhat_release 6 +Version: 10.5.18 +%define redhat_release 7 %define redhat_stage 0 #%define default_release %{redhat_release}.%{redhat_stage} %define default_release %{redhat_release} %else -Version: 10.5.17 -%define fedora_release 6 +Version: 10.5.18 +%define fedora_release 7 %define fedora_stage 0 #%define default_release %{fedora_release}.%{fedora_stage} %define default_release %{fedora_release} @@ -166,7 +166,7 @@ BuildRequires: policycoreutils-python-utils BuildRequires: python-ldap BuildRequires: junit BuildRequires: jpackage-utils >= 0:1.7.5-10 -BuildRequires: jss >= 4.4.7-1 +BuildRequires: jss >= 4.4.9-3 %if 0%{?rhel} && 0%{?rhel} <= 7 BuildRequires: tomcatjss >= 7.2.5-1 %else @@ -206,10 +206,12 @@ Source0: http://pki.fedoraproject.org/pki/sources/%{name}/%{version}/%{ Source0: http://pki.fedoraproject.org/pki/sources/%{name}/%{version}/%{release}/%{name}-%{version}%{?prerel}.tar.gz %endif -Patch0: pki-core-rhel-7-8-rhcs-9-6-alpha.patch -Patch1: pki-core-rhel-7-8-rhcs-9-6-beta.patch -Patch2: pki-core-Fixed-missing-audit-event.patch -Patch3: pki-core-rhel-7-8-rhcs-9-6-snapshot-2.patch +Patch0: pki-core-Fix-RSA-PSS-for-IPA-installer.patch +Patch1: pki-core-rhel-7-9-rhcs-9-7-beta.patch +Patch2: pki-core-rhel-7-9-rhcs-9-7-post-beta.patch +Patch3: pki-core-Fix-RSA-PSS-for-SHA512.patch +Patch4: pki-core-rhel-7-9-rhcs-9-7-post-beta-2.patch +Patch5: pki-core-Fix-CMCResponse-tool.patch # Obtain version phase number (e. g. - used by "alpha", "beta", etc.) # @@ -309,7 +311,7 @@ Group: System Environment/Libraries Requires: java-1.8.0-openjdk-headless Requires: jpackage-utils >= 0:1.7.5-10 -Requires: jss >= 4.4.7-1 +Requires: jss >= 4.4.9-3 Requires: nss >= 3.28.3 Provides: symkey = %{version}-%{release} @@ -388,7 +390,7 @@ Requires: slf4j-jdk14 %endif Requires: javassist Requires: jpackage-utils >= 0:1.7.5-10 -Requires: jss >= 4.4.7-1 +Requires: jss >= 4.4.9-3 Requires: ldapjdk >= 4.19-5 Requires: pki-base = %{version}-%{release} @@ -807,6 +809,8 @@ This package is a part of the PKI Core used by the Certificate System. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 %clean %{__rm} -rf %{buildroot} @@ -1344,6 +1348,69 @@ fi %endif # %{with server} %changelog +* Wed May 27 2020 Dogtag Team 10.5.18-7 +- Patch for CMCResponse tool +- Bugzilla Bug #1710109 - add RSA PSS support - fix CMCResponse tool (jmagne) + +* Tue May 19 2020 Dogtag Team 10.5.18-6 +- Patch for CMC Credential Error, RSA PSS typo, and new profile + for directory-authentication-based Server-Side keygen +- ########################################################################## +- # RHEL 7.9: +- ########################################################################## +- Bugzilla Bug #1710109 - add RSA PSS support (jmagne) +- Bugzilla Bug #1794213 - Server-Side keygen Enrollment for EE (cfu) +- ########################################################################## +- # RHCS 9.7: +- ########################################################################## +- # Bugzilla Bug #1733588 - Rebase redhat-pki, redhat-pki-theme, pki-core, and + # pki-console to 10.5.18 in RHCS 9.7 + +* Thu May 7 2020 Dogtag Team 10.5.18-5 +- Updated jss dependencies +- Bugzilla Bug #1710109 - add RSA PSS support - fix SHA512 (jmagne) + +* Tue May 5 2020 Dogtag Team 10.5.18-4 +- ########################################################################## +- # RHEL 7.9: +- ########################################################################## +- Bugzilla Bug #1794213 - Server-Side keygen Enrollment for EE + additional support and touch-up (cfu) +- ########################################################################## +- # RHCS 9.7: +- ########################################################################## +- # Bugzilla Bug #1710975 - TPS - Searching the certificate DB for a brand new + # token takes too long. Bad search filter (rhcs-maint, ascheel, jmagne) + +* Sun Apr 19 2020 Dogtag Team 10.5.18-3 +- Updated jss dependencies +- ########################################################################## +- # RHEL 7.9: +- ########################################################################## +- Bugzilla Bug #1794213 - Server-Side keygen Enrollment for EE (cfu) +- Bugzilla Bug #1809273 - CRL generation performs an unindexed search (jmagne) +- ########################################################################## +- # RHCS 9.7: +- ########################################################################## +- # Bugzilla Bug #1549307 - No default TPS Auditor group (ascheel) + +* Mon Mar 30 2020 Dogtag Team 10.5.18-2 +- Bugzilla Bug #1710109 - add RSA PSS support - fix IPA installer (jmagne) + +* Sun Mar 29 2020 Dogtag Team 10.5.18-1 +- Updated jss dependencies +- ########################################################################## +- # RHEL 7.9: +- ########################################################################## +- Bugzilla Bug #1774174 - Rebase pki-core from 10.5.17 to 10.5.18 (RHEL) +- ########################################################################## +- # RHCS 9.7: +- ########################################################################## +- # Bugzilla Bug #1774177 - Rebase redhat-pki, redhat-pki-theme, pki-core, and + # pki-console to 10.5.18 in RHCS 9.7 +- # Bugzilla Bug #1774181 - Update RHCS version of CA, KRA, OCSP, and TKS so + # that it can be identified using a browser [RHCS] + * Mon Dec 2 2019 Dogtag Team 10.5.17-6 - ########################################################################## - # RHEL 7.8: