Blob Blame History Raw
From 73f35e5e6836c3d63cfdc4d85dfbfed99f0bcf5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 29 Jan 2021 12:41:28 +0100
Subject: [PATCH] sudo: do not search by low usn value to improve performance

This is a follow up on these two commits.

- 819d70ef6e6fa0e736ebd60a7f8a26f672927d57
- 6815844daa7701c76e31addbbdff74656cd30bea

The first one improved the search filter little bit to achieve better
performance, however it also changed the behavior: we started to search
for `usn >= 1` in the filter if no usn number was known.

This caused issues on OpenLDAP server which was fixed by the second patch.
However, the fix was wrong and searching by this meaningfully low number
can cause performance issues depending on how the filter is optimized and
evaluated on the server.

Now we omit the usn attribute from the filter if there is no meaningful value.

How to test:
1. Setup LDAP with no sudo rules defined
2. Make sure that the LDAP server does not support USN or use the following diff
   to enforce modifyTimestamp (last USN is always available from rootDSE)
```diff

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
(cherry picked from commit b100efbfabd96dcfb2825777b75b9a9dfaacb937)
---
 src/providers/ldap/sdap.c              |  4 ++--
 src/providers/ldap/sdap_sudo_refresh.c |  6 ++++--
 src/providers/ldap/sdap_sudo_shared.c  | 21 ++++++---------------
 3 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index a1a00df56..0413930bc 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -1322,7 +1322,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
     last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
     entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
     if (rootdse) {
-        if (last_usn_name) {
+        if (false) {
             ret = sysdb_attrs_get_string(rootdse,
                                           last_usn_name, &last_usn_value);
             if (ret != EOK) {
@@ -1431,7 +1431,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
         }
     }
 
-    if (!last_usn_name) {
+    if (true) {
         DEBUG(SSSDBG_FUNC_DATA,
               "No known USN scheme is supported by this server!\n");
         if (!entry_usn_name) {
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
index 5c72c6ec5..fd5deeb7a 100644
--- a/src/providers/ldap/sdap_sudo_refresh.c
+++ b/src/providers/ldap/sdap_sudo_refresh.c
@@ -181,8 +181,10 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
     state->sysdb = id_ctx->be->domain->sysdb;
 
     /* Download all rules from LDAP that are newer than usn */
-    if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
-        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
+    if (srv_opts == NULL || srv_opts->max_sudo_value == NULL
+         || strcmp(srv_opts->max_sudo_value, "0") == 0) {
+        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and "
+              "omitting it from the filter.\n");
         usn = "0";
         search_filter = talloc_asprintf(state, "(%s=%s)",
                                         map[SDAP_AT_SUDO_OC].name,
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
index bd3a24da0..5f6afb1ac 100644
--- a/src/providers/ldap/sdap_sudo_shared.c
+++ b/src/providers/ldap/sdap_sudo_shared.c
@@ -127,25 +127,17 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
 static char *
 sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
                   unsigned long usn,
-                  const char *leftover,
-                  bool supports_usn)
+                  const char *leftover)
 {
     const char *str = leftover == NULL ? "" : leftover;
     char *newusn;
 
-    /* This is a fresh start and server uses modifyTimestamp. We need to
-     * provide proper datetime value. */
-    if (!supports_usn && usn == 0) {
-        newusn = talloc_strdup(mem_ctx, "00000101000000Z");
-        if (newusn == NULL) {
-            DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
-            return NULL;
-        }
-
-        return newusn;
+    /* Current largest USN is unknown so we keep "0" to indicate it. */
+    if (usn == 0) {
+        return talloc_strdup(mem_ctx, "0");
     }
 
-    /* We increment USN number so that we can later use simplify filter
+    /* We increment USN number so that we can later use simplified filter
      * (just usn >= last+1 instead of usn >= last && usn != last).
      */
     usn++;
@@ -217,8 +209,7 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
         srv_opts->last_usn = usn_number;
     }
 
-    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone,
-                               srv_opts->supports_usn);
+    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone);
     if (newusn == NULL) {
         return;
     }
-- 
2.26.3