Blame SOURCES/0013-Don-t-store-entries-with-a-usercertificate-in-the-LD_rhbz#1999893.patch

b39a24
From be1e3bbfc13aff9a583108376f245b81cc3666fb Mon Sep 17 00:00:00 2001
b39a24
From: Rob Crittenden <rcritten@redhat.com>
b39a24
Date: Thu, 9 Sep 2021 15:26:55 -0400
b39a24
Subject: [PATCH] Don't store entries with a usercertificate in the LDAP cache
b39a24
b39a24
usercertificate often has a subclass and both the plain and
b39a24
subclassed (binary) values are queried. I'm concerned that
b39a24
they are used more or less interchangably in places so not
b39a24
caching these entries is the safest path forward for now until
b39a24
we can dedicate the time to find all usages, determine their
b39a24
safety and/or perhaps handle this gracefully within the cache
b39a24
now.
b39a24
b39a24
What we see in this bug is that usercertificate;binary holds the
b39a24
first certificate value but a user-mod is done with
b39a24
setattr usercertificate=<new_cert>. Since there is no
b39a24
usercertificate value (remember, it's usercertificate;binary)
b39a24
a replace is done and 389-ds wipes the existing value as we've
b39a24
asked it to.
b39a24
b39a24
I'm not comfortable with simply treating them the same because
b39a24
in LDAP they are not.
b39a24
b39a24
https://pagure.io/freeipa/issue/8986
b39a24
b39a24
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
b39a24
Reviewed-By: Francois Cami <fcami@redhat.com>
b39a24
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
b39a24
---
b39a24
 ipapython/ipaldap.py | 14 +++++++++++---
b39a24
 1 file changed, 11 insertions(+), 3 deletions(-)
b39a24
b39a24
diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
b39a24
index f94b784d6..ced8f1bd6 100644
b39a24
--- a/ipapython/ipaldap.py
b39a24
+++ b/ipapython/ipaldap.py
b39a24
@@ -1821,9 +1821,17 @@ class LDAPCache(LDAPClient):
b39a24
                         entry=None, exception=None):
b39a24
         # idnsname - caching prevents delete when mod value to None
b39a24
         # cospriority - in a Class of Service object, uncacheable
b39a24
-        # TODO - usercertificate was banned at one point and I don't remember
b39a24
-        #        why...
b39a24
-        BANNED_ATTRS = {'idnsname', 'cospriority'}
b39a24
+        # usercertificate* - caching subtypes is tricky, trade less
b39a24
+        #                    complexity for performance
b39a24
+        #
b39a24
+        # TODO: teach the cache about subtypes
b39a24
+
b39a24
+        BANNED_ATTRS = {
b39a24
+            'idnsname',
b39a24
+            'cospriority',
b39a24
+            'usercertificate',
b39a24
+            'usercertificate;binary'
b39a24
+        }
b39a24
         if not self._enable_cache:
b39a24
             return
b39a24
 
b39a24
-- 
b39a24
2.31.1
b39a24
b39a24
From 86588640137562b2016fdb0f91142d00bc38e54a Mon Sep 17 00:00:00 2001
b39a24
From: Rob Crittenden <rcritten@redhat.com>
b39a24
Date: Fri, 10 Sep 2021 09:01:48 -0400
b39a24
Subject: [PATCH] ipatests: Test that a user can be issued multiple
b39a24
 certificates
b39a24
b39a24
Prevent regressions in the LDAP cache layer that caused newly
b39a24
issued certificates to overwrite existing ones.
b39a24
b39a24
https://pagure.io/freeipa/issue/8986
b39a24
b39a24
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
b39a24
Reviewed-By: Francois Cami <fcami@redhat.com>
b39a24
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
b39a24
---
b39a24
 ipatests/test_integration/test_cert.py | 29 ++++++++++++++++++++++++++
b39a24
 1 file changed, 29 insertions(+)
b39a24
b39a24
diff --git a/ipatests/test_integration/test_cert.py b/ipatests/test_integration/test_cert.py
b39a24
index 7d51b76ee..b4e85eadc 100644
b39a24
--- a/ipatests/test_integration/test_cert.py
b39a24
+++ b/ipatests/test_integration/test_cert.py
b39a24
@@ -16,6 +16,7 @@ import string
b39a24
 import time
b39a24
 
b39a24
 from ipaplatform.paths import paths
b39a24
+from ipapython.dn import DN
b39a24
 from cryptography import x509
b39a24
 from cryptography.x509.oid import ExtensionOID
b39a24
 from cryptography.hazmat.backends import default_backend
b39a24
@@ -183,6 +184,34 @@ class TestInstallMasterClient(IntegrationTest):
b39a24
         )
b39a24
         assert "profile: caServerCert" in result.stdout_text
b39a24
 
b39a24
+    def test_multiple_user_certificates(self):
b39a24
+        """Test that a user may be issued multiple certificates"""
b39a24
+        ldap = self.master.ldap_connect()
b39a24
+
b39a24
+        user = 'user1'
b39a24
+
b39a24
+        tasks.kinit_admin(self.master)
b39a24
+        tasks.user_add(self.master, user)
b39a24
+
b39a24
+        for id in (0,1):
b39a24
+            csr_file = f'{id}.csr'
b39a24
+            key_file = f'{id}.key'
b39a24
+            cert_file = f'{id}.crt'
b39a24
+            openssl_cmd = [
b39a24
+                'openssl', 'req', '-newkey', 'rsa:2048', '-keyout', key_file,
b39a24
+                '-nodes', '-out', csr_file, '-subj', '/CN=' + user]
b39a24
+            self.master.run_command(openssl_cmd)
b39a24
+
b39a24
+            cmd_args = ['ipa', 'cert-request', '--principal', user,
b39a24
+                        '--certificate-out', cert_file, csr_file]
b39a24
+            self.master.run_command(cmd_args)
b39a24
+
b39a24
+        # easier to count by pulling the LDAP entry
b39a24
+        entry = ldap.get_entry(DN(('uid', user), ('cn', 'users'),
b39a24
+                               ('cn', 'accounts'), self.master.domain.basedn))
b39a24
+
b39a24
+        assert len(entry.get('usercertificate')) == 2
b39a24
+
b39a24
     @pytest.fixture
b39a24
     def test_subca_certs(self):
b39a24
         """
b39a24
-- 
b39a24
2.31.1
b39a24