Blame SOURCES/0001-Issue-4383-Do-not-normalize-escaped-spaces-in-a-DN.patch

be9751
From 81dcaf1c37c2de24c46672df8d4f968c2fb40a6e Mon Sep 17 00:00:00 2001
be9751
From: Mark Reynolds <mreynolds@redhat.com>
be9751
Date: Wed, 11 Nov 2020 08:59:18 -0500
be9751
Subject: [PATCH 1/3] Issue 4383 - Do not normalize escaped spaces in a DN
be9751
be9751
Bug Description:  Adding an entry with an escaped leading space leads to many
be9751
                  problems.  Mainly id2entry can get corrupted during an
be9751
                  import of such an entry, and the entryrdn index is not
be9751
                  updated correctly
be9751
be9751
Fix Description:  In slapi_dn_normalize_ext() leave an escaped space intact.
be9751
be9751
Relates: https://github.com/389ds/389-ds-base/issues/4383
be9751
be9751
Reviewed by: firstyear, progier, and tbordaz (Thanks!!!)
be9751
---
be9751
 .../tests/suites/syntax/acceptance_test.py    | 75 ++++++++++++++++++-
be9751
 ldap/servers/slapd/dn.c                       |  8 +-
be9751
 2 files changed, 77 insertions(+), 6 deletions(-)
be9751
be9751
diff --git a/dirsrvtests/tests/suites/syntax/acceptance_test.py b/dirsrvtests/tests/suites/syntax/acceptance_test.py
be9751
index 543718689..7939a99a7 100644
be9751
--- a/dirsrvtests/tests/suites/syntax/acceptance_test.py
be9751
+++ b/dirsrvtests/tests/suites/syntax/acceptance_test.py
be9751
@@ -1,5 +1,5 @@
be9751
 # --- BEGIN COPYRIGHT BLOCK ---
be9751
-# Copyright (C) 2019 Red Hat, Inc.
be9751
+# Copyright (C) 2020 Red Hat, Inc.
be9751
 # All rights reserved.
be9751
 #
be9751
 # License: GPL (version 3 or any later version).
be9751
@@ -7,13 +7,12 @@
be9751
 # --- END COPYRIGHT BLOCK ---
be9751
 
be9751
 import ldap
be9751
-import logging
be9751
 import pytest
be9751
 import os
be9751
 from lib389.schema import Schema
be9751
 from lib389.config import Config
be9751
 from lib389.idm.user import UserAccounts
be9751
-from lib389.idm.group import Groups
be9751
+from lib389.idm.group import Group, Groups
be9751
 from lib389._constants import DEFAULT_SUFFIX
be9751
 from lib389.topologies import log, topology_st as topo
be9751
 
be9751
@@ -127,7 +126,7 @@ def test_invalid_dn_syntax_crash(topo):
be9751
         4. Success
be9751
     """
be9751
 
be9751
-    # Create group
be9751
+        # Create group
be9751
     groups = Groups(topo.standalone, DEFAULT_SUFFIX)
be9751
     group = groups.create(properties={'cn': ' test'})
be9751
 
be9751
@@ -145,6 +144,74 @@ def test_invalid_dn_syntax_crash(topo):
be9751
     groups.list()
be9751
 
be9751
 
be9751
+@pytest.mark.parametrize("props, rawdn", [
be9751
+                         ({'cn': ' leadingSpace'}, "cn=\\20leadingSpace,ou=Groups,dc=example,dc=com"),
be9751
+                         ({'cn': 'trailingSpace '}, "cn=trailingSpace\\20,ou=Groups,dc=example,dc=com")])
be9751
+def test_dn_syntax_spaces_delete(topo,  props,  rawdn):
be9751
+    """Test that an entry with a space as the first character in the DN can be
be9751
+    deleted without error.  We also want to make sure the indexes are properly
be9751
+    updated by repeatedly adding and deleting the entry, and that the entry cache
be9751
+    is properly maintained.
be9751
+
be9751
+    :id: b993f37c-c2b0-4312-992c-a9048ff98965
be9751
+    :parametrized: yes
be9751
+    :setup: Standalone Instance
be9751
+    :steps:
be9751
+        1. Create a group with a DN that has a space as the first/last
be9751
+           character.
be9751
+        2. Delete group
be9751
+        3. Add group
be9751
+        4. Modify group
be9751
+        5. Restart server and modify entry
be9751
+        6. Delete group
be9751
+        7. Add group back
be9751
+        8. Delete group using specific DN
be9751
+    :expectedresults:
be9751
+        1. Success
be9751
+        2. Success
be9751
+        3. Success
be9751
+        4. Success
be9751
+        5. Success
be9751
+        6. Success
be9751
+        7. Success
be9751
+        8. Success
be9751
+    """
be9751
+
be9751
+    # Create group
be9751
+    groups = Groups(topo.standalone, DEFAULT_SUFFIX)
be9751
+    group = groups.create(properties=props.copy())
be9751
+
be9751
+    # Delete group (verifies DN/RDN parsing works and cache is correct)
be9751
+    group.delete()
be9751
+
be9751
+    # Add group again (verifies entryrdn index was properly updated)
be9751
+    groups = Groups(topo.standalone, DEFAULT_SUFFIX)
be9751
+    group = groups.create(properties=props.copy())
be9751
+
be9751
+    # Modify the group (verifies dn/rdn parsing is correct)
be9751
+    group.replace('description', 'escaped space group')
be9751
+
be9751
+    # Restart the server.  This will pull the entry from the database and
be9751
+    # convert it into a cache entry, which is different than how a client
be9751
+    # first adds an entry and is put into the cache before being written to
be9751
+    # disk.
be9751
+    topo.standalone.restart()
be9751
+
be9751
+    # Make sure we can modify the entry (verifies cache entry was created
be9751
+    # correctly)
be9751
+    group.replace('description', 'escaped space group after restart')
be9751
+
be9751
+    # Make sure it can still be deleted (verifies cache again).
be9751
+    group.delete()
be9751
+
be9751
+    # Add it back so we can delete it using a specific DN (sanity test to verify
be9751
+    # another DN/RDN parsing variation).
be9751
+    groups = Groups(topo.standalone, DEFAULT_SUFFIX)
be9751
+    group = groups.create(properties=props.copy())
be9751
+    group = Group(topo.standalone, dn=rawdn)
be9751
+    group.delete()
be9751
+
be9751
+
be9751
 if __name__ == '__main__':
be9751
     # Run isolated
be9751
     # -s for DEBUG mode
be9751
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
be9751
index 2af3f38fc..3980b897f 100644
be9751
--- a/ldap/servers/slapd/dn.c
be9751
+++ b/ldap/servers/slapd/dn.c
be9751
@@ -894,8 +894,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
be9751
                             s++;
be9751
                         }
be9751
                     }
be9751
-                } else if (s + 2 < ends &&
be9751
-                           isxdigit(*(s + 1)) && isxdigit(*(s + 2))) {
be9751
+                } else if (s + 2 < ends && isxdigit(*(s + 1)) && isxdigit(*(s + 2))) {
be9751
                     /* esc hexpair ==> real character */
be9751
                     int n = slapi_hexchar2int(*(s + 1));
be9751
                     int n2 = slapi_hexchar2int(*(s + 2));
be9751
@@ -903,6 +902,11 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
be9751
                     if (n == 0) { /* don't change \00 */
be9751
                         *d++ = *++s;
be9751
                         *d++ = *++s;
be9751
+                    } else if (n == 32) { /* leave \20 (space) intact */
be9751
+                        *d++ = *s;
be9751
+                        *d++ = *++s;
be9751
+                        *d++ = *++s;
be9751
+                        s++;
be9751
                     } else {
be9751
                         *d++ = n;
be9751
                         s += 3;
be9751
-- 
be9751
2.26.2
be9751