Blame SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch

bac598
From b100efbfabd96dcfb2825777b75b9a9dfaacb937 Mon Sep 17 00:00:00 2001
bac598
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
bac598
Date: Fri, 29 Jan 2021 12:41:28 +0100
bac598
Subject: [PATCH] sudo: do not search by low usn value to improve performance
bac598
bac598
This is a follow up on these two commits.
bac598
bac598
- 819d70ef6e6fa0e736ebd60a7f8a26f672927d57
bac598
- 6815844daa7701c76e31addbbdff74656cd30bea
bac598
bac598
The first one improved the search filter little bit to achieve better
bac598
performance, however it also changed the behavior: we started to search
bac598
for `usn >= 1` in the filter if no usn number was known.
bac598
bac598
This caused issues on OpenLDAP server which was fixed by the second patch.
bac598
However, the fix was wrong and searching by this meaningfully low number
bac598
can cause performance issues depending on how the filter is optimized and
bac598
evaluated on the server.
bac598
bac598
Now we omit the usn attribute from the filter if there is no meaningful value.
bac598
bac598
How to test:
bac598
1. Setup LDAP with no sudo rules defined
bac598
2. Make sure that the LDAP server does not support USN or use the following diff
bac598
   to enforce modifyTimestamp (last USN is always available from rootDSE)
bac598
```diff
bac598
bac598
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
bac598
---
bac598
 src/providers/ldap/sdap.c              |  4 ++--
bac598
 src/providers/ldap/sdap_sudo_refresh.c |  6 ++++--
bac598
 src/providers/ldap/sdap_sudo_shared.c  | 21 ++++++---------------
bac598
 3 files changed, 12 insertions(+), 19 deletions(-)
bac598
bac598
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
bac598
index 32c0144b9..c853e4dc1 100644
bac598
--- a/src/providers/ldap/sdap.c
bac598
+++ b/src/providers/ldap/sdap.c
bac598
@@ -1391,7 +1391,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
bac598
     last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
bac598
     entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
bac598
     if (rootdse) {
bac598
-        if (last_usn_name) {
bac598
+        if (false) {
bac598
             ret = sysdb_attrs_get_string(rootdse,
bac598
                                           last_usn_name, &last_usn_value);
bac598
             if (ret != EOK) {
bac598
@@ -1500,7 +1500,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
bac598
         }
bac598
     }
bac598
 
bac598
-    if (!last_usn_name) {
bac598
+    if (true) {
bac598
         DEBUG(SSSDBG_FUNC_DATA,
bac598
               "No known USN scheme is supported by this server!\n");
bac598
         if (!entry_usn_name) {
bac598
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
bac598
index ddcb23781..83f944ccf 100644
bac598
--- a/src/providers/ldap/sdap_sudo_refresh.c
bac598
+++ b/src/providers/ldap/sdap_sudo_refresh.c
bac598
@@ -181,8 +181,10 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
bac598
     state->sysdb = id_ctx->be->domain->sysdb;
bac598
 
bac598
     /* Download all rules from LDAP that are newer than usn */
bac598
-    if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
bac598
-        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
bac598
+    if (srv_opts == NULL || srv_opts->max_sudo_value == NULL
bac598
+         || strcmp(srv_opts->max_sudo_value, "0") == 0) {
bac598
+        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and "
bac598
+              "omitting it from the filter.\n");
bac598
         usn = "0";
bac598
         search_filter = talloc_asprintf(state, "(%s=%s)",
bac598
                                         map[SDAP_AT_SUDO_OC].name,
bac598
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
bac598
index 4f09957ea..75d1bc3d8 100644
bac598
--- a/src/providers/ldap/sdap_sudo_shared.c
bac598
+++ b/src/providers/ldap/sdap_sudo_shared.c
bac598
@@ -129,25 +129,17 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
bac598
 static char *
bac598
 sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
bac598
                   unsigned long usn,
bac598
-                  const char *leftover,
bac598
-                  bool supports_usn)
bac598
+                  const char *leftover)
bac598
 {
bac598
     const char *str = leftover == NULL ? "" : leftover;
bac598
     char *newusn;
bac598
 
bac598
-    /* This is a fresh start and server uses modifyTimestamp. We need to
bac598
-     * provide proper datetime value. */
bac598
-    if (!supports_usn && usn == 0) {
bac598
-        newusn = talloc_strdup(mem_ctx, "00000101000000Z");
bac598
-        if (newusn == NULL) {
bac598
-            DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
bac598
-            return NULL;
bac598
-        }
bac598
-
bac598
-        return newusn;
bac598
+    /* Current largest USN is unknown so we keep "0" to indicate it. */
bac598
+    if (usn == 0) {
bac598
+        return talloc_strdup(mem_ctx, "0");
bac598
     }
bac598
 
bac598
-    /* We increment USN number so that we can later use simplify filter
bac598
+    /* We increment USN number so that we can later use simplified filter
bac598
      * (just usn >= last+1 instead of usn >= last && usn != last).
bac598
      */
bac598
     usn++;
bac598
@@ -219,8 +211,7 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
bac598
         srv_opts->last_usn = usn_number;
bac598
     }
bac598
 
bac598
-    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone,
bac598
-                               srv_opts->supports_usn);
bac598
+    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone);
bac598
     if (newusn == NULL) {
bac598
         return;
bac598
     }
bac598
-- 
bac598
2.21.3
bac598