From 4d1eb84ed956e59ef1bf9d4b01114fef15d49fd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 23 Apr 2019 13:37:01 +0200
Subject: [PATCH 1/3] sudo: always use server highest known usn for smart
 refresh

The sudo attributes may not be indexed on the server, therefore if
smart refresh filter is run on the server it may first search using
the indexed entryusn attribute and run the rest of the filter on
non-sudo objects. The number of objects that are filtered may increased
dramatically if sudo rules are not changed for a long time (and thus
keeping smaller and smaller last sudo usn number).

This patch makes sure that highest sudo usn number is always set to
the highest server usn number known by SSSD after each refresh.

Resolves:
https://pagure.io/SSSD/sssd/issue/3997
---
 src/providers/ldap/sdap_sudo_shared.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
index 66b788702f..d2f24ed6e2 100644
--- a/src/providers/ldap/sdap_sudo_shared.c
+++ b/src/providers/ldap/sdap_sudo_shared.c
@@ -174,28 +174,17 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
         return;
     }
 
-    if (usn_number == 0) {
-        /* Zero means that there were no rules on the server, so we have
-         * nothing to store. */
-        DEBUG(SSSDBG_TRACE_FUNC, "SUDO USN value is empty.\n");
-        return;
+    if (usn_number > srv_opts->last_usn) {
+        srv_opts->last_usn = usn_number;
     }
 
-    newusn = sdap_sudo_new_usn(srv_opts, usn_number, endptr);
+    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, endptr);
     if (newusn == NULL) {
         return;
     }
 
-    if (sysdb_compare_usn(newusn, srv_opts->max_sudo_value) > 0) {
-        talloc_zfree(srv_opts->max_sudo_value);
-        srv_opts->max_sudo_value = newusn;
-    } else {
-        talloc_zfree(newusn);
-    }
-
-    if (usn_number > srv_opts->last_usn) {
-        srv_opts->last_usn = usn_number;
-    }
+    talloc_zfree(srv_opts->max_sudo_value);
+    srv_opts->max_sudo_value = newusn;
 
     DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
                              srv_opts->max_sudo_value);

From 45e7301eac8ccdcfbdbb47ff9f73fbf4f76091ee Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 7 May 2019 11:19:02 +0200
Subject: [PATCH 2/3] sdap: update last_usn on reconnect

If we are reconnecting to the same server it makes sense the keep the
stored maximum USN values for the different object classes. But since
the highest USN is already read from the rootDSE during the reconnect it
make sense to keep this value to be able to update the maximum USN
values even of no new object where found during the related searches.
---
 src/providers/ldap/sdap.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index e81aaf4a7d..4a3670e72f 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -1460,8 +1460,9 @@ void sdap_steal_server_opts(struct sdap_id_ctx *id_ctx,
     }
 
     /* discard if same as previous so we do not reset max usn values
-     * unnecessarily */
+     * unnecessarily, only update last_usn. */
     if (strcmp(id_ctx->srv_opts->server_id, (*srv_opts)->server_id) == 0) {
+        id_ctx->srv_opts->last_usn = (*srv_opts)->last_usn;
         talloc_zfree(*srv_opts);
         return;
     }

From b17949acd195b5f6c54518e3274beb8722753002 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 21 May 2019 10:25:45 +0200
Subject: [PATCH 3/3] man: update sudo smart refresh documentation to reflect
 new USN behavior

Resolves:
https://pagure.io/SSSD/sssd/issue/3997
---
 src/man/sssd-ldap.5.xml | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index b30a54f19e..5c50130364 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -2537,13 +2537,24 @@ ldap_access_filter = (employeeType=admin)
                         <para>
                             How many seconds SSSD has to wait before executing
                             a smart refresh of sudo rules (which downloads all
-                            rules that have USN higher than the highest USN of
-                            cached rules).
+                            rules that have USN higher than the highest server
+                            USN value that is currently known by SSSD).
                         </para>
                         <para>
                             If USN attributes are not supported by the server,
                             the modifyTimestamp attribute is used instead.
                         </para>
+                        <para>
+                            <emphasis>Note:</emphasis> the highest USN value
+                            can be updated by three tasks:
+                            1) By sudo full and smart refresh (if updated rules
+                            are found),
+                            2) by enumeration of users and groups (if enabled
+                            and updated users or groups are found) and
+                            3) by reconnecting to the server
+                            (by default every 15 minutes, see
+                            <emphasis>ldap_connection_expire_timeout</emphasis>).
+                        </para>
                         <para>
                             Default: 900 (15 minutes)
                         </para>
