import pki-core-10.9.4-3.module+el8.3.0+10353+73f6df5b

This commit is contained in:
CentOS Sources 2021-03-23 06:31:27 -04:00 committed by Andrew Lukoshko
parent 41013f3800
commit 4a7a035137
3 changed files with 259 additions and 1 deletions

View File

@ -0,0 +1,170 @@
From 8b3cb80954a932867c2d4d96eb1cced83fa78996 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal@redhat.com>
Date: Wed, 13 Jan 2021 18:27:46 +1100
Subject: [PATCH] Fix renewal profile approval process
Due to a recent change in PKI CLI, the CLI now passes along user
authentication with submissions to the renewal endpoint. Unlike the EE
pages, the REST API has passed along this authentication for a while.
Due to a bug in the RenewalProcessor, requests with credentials against
profiles with no authentication method and no ACLs result in the
certificiate automatically being approved. This occurs because, when
an earlier commit (cb9eb967b5e24f5fde8bbf8ae87aa615b7033db7) modified
the code to allow Light-Weight SubCAs to issue certificates, validation
wasn't done on the passed principal, to see if it was a trusted agent.
Because profiles requring Agent approval have an empty ACL list (as, no
user should be able to submit a certificate request and have it
automatically signed without agent approval), authorize allows any user
to approve this request and thus accepts the AuthToken.
Critical analysis: the RenewalProcessor code interprets (authToken
!= null) as evidence that the authenticated user is /authorized/ to
immediately issue the certificate. This mismatch of concerns (authn
vs authz) resulted in a misunderstanding of system behaviour. The
"latent" AuthToken (from the HTTP request) was assigned to authToken
without realising that authorization needed to be performed.
We fix this by splitting the logic on whether the profile defines an
authenticator. If so, we (re)authenticate and authorize the user
according to the profile configuration.
If the profile does not define an authenticator but there is a
principal in the HTTP request, if (and only if) the user has
permission to approve certificate requests *and* the requested
renewal profile is caManualRenewal (which is hardcoded to be used
for LWCA renewal), then we issue the certificate immediately. This
special case ensures that LWCA renewal keeps working.
Otherwise, if there is no principal in the HTTP request or the
principal does not have permission to approve certificate requests,
we leave the authToken unset. The resulting renewal request will be
created with status PENDING, i.e. enqueued for agent review.
Signed-off-by: Fraser Tweedale <ftweedal@redhat.com>
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
---
.../com/netscape/ca/CertificateAuthority.java | 10 +++
.../cms/servlet/cert/RenewalProcessor.java | 75 +++++++++++++++++--
2 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 07f29fead..50292201b 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -2962,6 +2962,16 @@ public class CertificateAuthority
}
ProfileSubsystem ps = engine.getProfileSubsystem();
+ /* NOTE: hard-coding the profile to use for Lightweight CA renewal
+ * might be OK, but caManualRenewal was not the right one to use.
+ * As a consequence, we have an undesirable special case in
+ * RenewalProcessor.processRenewal().
+ *
+ * We should introduce a new profile specifically for LWCA renewal,
+ * with an authenticator and ACLs to match the authz requirements
+ * for the renewAuthority REST resource itself. Then we can use
+ * it here, and remove the workaround from RenewalProcessor.
+ */
Profile profile = ps.getProfile("caManualRenewal");
CertEnrollmentRequest req = CertEnrollmentRequestFactory.create(
new ArgBlock(), profile, httpReq.getLocale());
diff --git a/base/ca/src/com/netscape/cms/servlet/cert/RenewalProcessor.java b/base/ca/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
index 917c64856..75677b5e4 100644
--- a/base/ca/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
+++ b/base/ca/src/com/netscape/cms/servlet/cert/RenewalProcessor.java
@@ -31,6 +31,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
+import org.dogtagpki.server.authorization.AuthzToken;
import org.mozilla.jss.netscape.security.x509.BasicConstraintsExtension;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
@@ -267,16 +268,78 @@ public class RenewalProcessor extends CertProcessor {
// before creating the request, authenticate the request
IAuthToken authToken = null;
- Principal principal = request.getUserPrincipal();
- if (principal instanceof PKIPrincipal)
- authToken = ((PKIPrincipal) principal).getAuthToken();
- if (authToken == null && authenticator != null) {
- authToken = authenticate(request, origReq, authenticator, context, true, credentials);
+
+ if (authenticator != null) {
+ /* The profile specifies an authenticator. Use it to
+ * authenticate the user. Ignore the "latent" session
+ * principal (if any).
+ */
+ authToken = authenticate(
+ request,
+ origReq,
+ authenticator,
+ context,
+ true /* isRenewal */,
+ credentials);
+ } else {
+ /* When authenticator is null, we expect manual agent
+ * review (leave authToken as null).
+ *
+ * But as a special case to ensure Lightweight CA (LWCA)
+ * renewal works, if there is a latent user in the HTTP
+ * request, we use that user (i.e. set authToken to the
+ * principal's IAuthToken) if and only if:
+ *
+ * - The renewal profile is caManualRenewal (LWCA renewal
+ * is hardcoded to use this profile); AND
+ *
+ * - The latent user is authorized to "execute"
+ * certificate requests (i.e. agent approval)
+ *
+ * See also CertificateAuthority.renewAuthority().
+ */
+
+ Principal principal = request.getUserPrincipal();
+ if (
+ renewProfileId.equals("caManualRenewal")
+ && principal instanceof PKIPrincipal
+ ) {
+ IAuthToken latentToken = ((PKIPrincipal) principal).getAuthToken();
+ AuthzToken authzToken = authorize(
+ "DirAclAuthz", latentToken, "certServer.ca.certrequests", "execute");
+ if (authzToken != null) {
+ // Success (no exception); user is authorized to approve
+ // cert requests. Set the authToken.
+ //
+ // NOTE: This authz does not replace or subsume the
+ // profile-specific authz check below.
+ authToken = latentToken;
+ } else {
+ // leave authToken as null to enqueue a pending request.
+ }
+ } else {
+ // not caManualRenewal or no latent principal;
+ // leave authToken as null to enqueue a pending request.
+ }
}
- // authentication success, now authorize
+ /* Authorize the request.
+ *
+ * If authToken != null, it will be checked against ACLs specified
+ * in the profile (if any). If ACLs are defined and authToken does
+ * not match, throws an authorization exception.
+ *
+ * If authToken == null, no check is performed (even if the profile
+ * defines ACLs). This is fine, because null authToken will cause
+ * the request status to be 'pending' [agent approval].
+ */
authorize(profileId, renewProfile, authToken);
+ /* At this point, the request will be created. If authToken
+ * is non-null, then the certificate will be issued
+ * immediately. Otherwise the request will be pending. */
+
+
///////////////////////////////////////////////
// create and populate requests
///////////////////////////////////////////////
--
2.29.2

View File

@ -0,0 +1,80 @@
From d17df6f22376753b5cd156f1b7f51837cae1f522 Mon Sep 17 00:00:00 2001
From: jmagne <jmagne@redhat.com>
Date: Mon, 22 Feb 2021 13:44:20 -0800
Subject: [PATCH] pkispawn fails against 389-ds 1.4.3.19 #3458 (#3465)
Add suggested patch from stanislavlevin to solve this issue.
Also add f34 to the ipa tests,this time really add the tests.
Upon further review, back out of f34 tests until the infractructure
supports it.
Also hardcode tomcat app setting in spec file for the moment to
avoid possible glitches on certain platform.
Co-authored-by: Jack Magne <jmagne@localhost.localdomain>
---
.../com/netscape/cmscore/apps/CMSEngine.java | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/base/server/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/src/com/netscape/cmscore/apps/CMSEngine.java
index 295c4d4cc..f40f99136 100644
--- a/base/server/src/com/netscape/cmscore/apps/CMSEngine.java
+++ b/base/server/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -156,9 +156,8 @@ public class CMSEngine {
private static final int PW_OK =0;
//private static final int PW_BAD_SETUP = 1;
- private static final int PW_INVALID_PASSWORD = 2;
+ private static final int PW_INVALID_CREDENTIALS = 2;
private static final int PW_CANNOT_CONNECT = 3;
- private static final int PW_NO_USER = 4;
private static final int PW_MAX_ATTEMPTS = 3;
@@ -332,16 +331,16 @@ public class CMSEngine {
}
int iteration = 0;
- int result = PW_INVALID_PASSWORD;
+ int result = PW_INVALID_CREDENTIALS;
do {
String passwd = mPasswordStore.getPassword(tag, iteration);
result = testLDAPConnection(tag, connInfo, binddn, passwd);
iteration++;
- } while ((result == PW_INVALID_PASSWORD) && (iteration < PW_MAX_ATTEMPTS));
+ } while ((result == PW_INVALID_CREDENTIALS) && (iteration < PW_MAX_ATTEMPTS));
if (result != PW_OK) {
- if ((result == PW_NO_USER) && (tag.equals("replicationdb"))) {
+ if ((result == PW_INVALID_CREDENTIALS) && (tag.equals("replicationdb"))) {
logger.warn(
"CMSEngine: password test execution failed for replicationdb " +
"with NO_SUCH_USER. This may not be a latest instance. Ignoring ..");
@@ -364,7 +363,7 @@ public class CMSEngine {
int ret = PW_OK;
if (StringUtils.isEmpty(pwd)) {
- return PW_INVALID_PASSWORD;
+ return PW_INVALID_CREDENTIALS;
}
String host = info.getHost();
@@ -383,12 +382,9 @@ public class CMSEngine {
switch (e.getLDAPResultCode()) {
case LDAPException.NO_SUCH_OBJECT:
- logger.debug("CMSEngine: user does not exist: " + binddn);
- ret = PW_NO_USER;
- break;
case LDAPException.INVALID_CREDENTIALS:
- logger.debug("CMSEngine: invalid password");
- ret = PW_INVALID_PASSWORD;
+ logger.debug("CMSEngine: invalid credentials");
+ ret = PW_INVALID_CREDENTIALS;
break;
default:
logger.debug("CMSEngine: unable to connect to " + name + ": " + e.getMessage());
--
2.29.2

View File

@ -13,7 +13,7 @@ License: GPLv2 and LGPLv2
# For development (unsupported) releases, use x.y.z-0.n.unstable with alpha/beta phase.
# For official (supported) releases, use x.y.z-r where r >=1 without alpha/beta phase.
Version: 10.9.4
Release: 1%{?_timestamp}%{?_commit_id}%{?dist}
Release: 3%{?_timestamp}%{?_commit_id}%{?dist}
#global _phase -a1
# To create a tarball from a version tag:
@ -36,6 +36,8 @@ Source: https://github.com/dogtagpki/pki/archive/v%{version}%{?_phase}/pki-%{ver
# BUILDSTDERR: Download error on https://pypi.org/simple/pytest-runner/:
# [Errno 111] Connection refused -- Some packages may not be found!
Patch1: 0001-Removed-dependency-on-pytest-runner.patch
Patch2: 0001-CVE-2021-20179-Fix-renewal-profile-approval-process.patch
Patch3: 0004-pkispawn-fails-against-389-ds-1.4.3.19-3458-3465.patch
################################################################################
# NSS
@ -1363,6 +1365,12 @@ fi
################################################################################
%changelog
* Thu Mar 11 2021 Red Hat PKI Team <rhcs-maint@redhat.com> 10.9.4-3
- Bug # 1933146 - PKI instance creation failed with new 389-ds-base build
* Thu Feb 11 2021 Red Hat PKI Team <rhcs-maint@redhat.com> 10.9.4-2
- CVE-2021-20179: Fix unprivileged users can renew any certificate
* Fri Sep 11 2020 Red Hat PKI Team <rhcs-maint@redhat.com> 10.9.4-1
- Rebased to PKI 10.9.4
- Red Hat Bugzilla #1873235 - Fix SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT in pki ca-user-cert-add