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

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