Blame SOURCES/0013-ipaldap_invalid_modlist_when_attribute_encoding_can_vary_rhbz#1658302.patch

b01884
From 9e7e9c1014c10f838b341a45436aba0840ad5b07 Mon Sep 17 00:00:00 2001
b01884
From: Fraser Tweedale <ftweedal@redhat.com>
b01884
Date: Nov 07 2018 13:51:59 +0000
b01884
Subject: ipaldap: avoid invalid modlist when attribute encoding differs
b01884
b01884
b01884
ipaldap does not take into account the possibility of the attribute
b01884
encoding returned by python-ldap differing from the attribute
b01884
encoding produced by FreeIPA.  In particular this can occur with DNs
b01884
with special characters that require escaping.  For example,
b01884
python-ldap (or the underlying LDAP library) escapes special
b01884
characters using hex encoding:
b01884
b01884
  CN=Test Sub-CA 201604041620,OU=ftweedal,O=Red Hat\2C Inc.,L=Brisbane,C=AU
b01884
b01884
Whereas FreeIPA, when encoding the DN, escapes the character
b01884
directly:
b01884
b01884
  CN=Test Sub-CA 201604041620,OU=ftweedal,O=Red Hat\, Inc.,L=Brisbane,C=AU
b01884
b01884
Therefore it is possible to generate an invalid modlist. For
b01884
example, during external CA certificate renewal, if the issuer DN
b01884
includes a comma in one of the attribute values (as above), an
b01884
invalid modlist will be generated:
b01884
b01884
  [ (ldap.MOD_ADD, 'ipacaissuerdn',
b01884
      [b'CN=Test Sub-CA 201604041620,OU=ftweedal,O=Red Hat\, Inc.,L=Brisbane,C=AU'])
b01884
  , (ldap.MOD_DELETE, 'ipacaissuerdn',
b01884
      [b'CN=Test Sub-CA 201604041620,OU=ftweedal,O=Red Hat\2C Inc.,L=Brisbane,C=AU'])
b01884
  ]
b01884
b01884
Although encoded differently, these are the same value.  If this
b01884
modification is applied to the object, attributeOrValueExists (error
b01884
20) occurs.
b01884
b01884
To avoid the issue, put deletes before adds in the modlist.  If a
b01884
value is present (with different encodings) as both an addition and
b01884
a deletion, it must be because the original object contained the
b01884
value with a different encoding.  Therefore it is safe to delete it,
b01884
then add it back.
b01884
b01884
Note that the modlist is not optimal.  In the simplest case (like
b01884
above example), there should be no modification to perform.  It is
b01884
considerably more complex (and more computation) to implement this
b01884
because the raw attribute values must be decoded before comparison.
b01884
b01884
Fixes: https://pagure.io/freeipa/issue/7750
b01884
Reviewed-By: Christian Heimes <cheimes@redhat.com>
b01884
b01884
---
b01884
b01884
diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
b01884
index fbc824e..cf1e60b 100644
b01884
--- a/ipapython/ipaldap.py
b01884
+++ b/ipapython/ipaldap.py
b01884
@@ -565,10 +565,13 @@ class LDAPEntry(MutableMapping):
b01884
                     raise errors.OnlyOneValueAllowed(attr=name)
b01884
                 modlist.append((ldap.MOD_REPLACE, name, adds))
b01884
             else:
b01884
-                if adds:
b01884
-                    modlist.append((ldap.MOD_ADD, name, adds))
b01884
+                # dels before adds, in case the same value occurs in
b01884
+                # both due to encoding differences
b01884
+                # (https://pagure.io/freeipa/issue/7750)
b01884
                 if dels:
b01884
                     modlist.append((ldap.MOD_DELETE, name, dels))
b01884
+                if adds:
b01884
+                    modlist.append((ldap.MOD_ADD, name, adds))
b01884
 
b01884
         # Usually the modlist order does not matter.
b01884
         # However, for schema updates, we want 'attributetypes' before
b01884