>From aa06df9103eadab03dd2417cda556e6b6a3f58b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 23 Oct 2012 14:09:50 +0200
Subject: [PATCH] sudo: do not fail if usn value is zero but full refresh is
 completed

https://fedorahosted.org/sssd/ticket/1596

In case that LDAP server contains zero sudo rules, the full refresh
completes succussfully and stores current USN value (= 0). But then
smart refresh will fail because it takes USN=0 as invalid value.
---
 src/providers/ldap/sdap_sudo.c | 24 +++++++++++++++++-------
 src/providers/ldap/sdap_sudo.h |  2 ++
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index d60dbd914578ac9ccabb4333e7d73ba754eaa250..ebbc95d14bfa2603806a4f42048723b3d036de2a 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -31,6 +31,7 @@
 #include "db/sysdb_sudo.h"
 
 struct sdap_sudo_full_refresh_state {
+    struct sdap_sudo_ctx *sudo_ctx;
     struct sdap_id_ctx *id_ctx;
     struct sysdb_ctx *sysdb;
     int dp_error;
@@ -128,6 +129,10 @@ int sdap_sudo_init(struct be_ctx *be_ctx,
     *ops = &sdap_sudo_ops;
     *pvt_data = sudo_ctx;
 
+    /* we didn't do any full refresh now,
+     * so we don't have current usn values available */
+    sudo_ctx->full_refresh_done = false;
+
     ret = ldap_get_sudo_options(id_ctx, be_ctx->cdb,
                                 be_ctx->conf_path, id_ctx->opts,
                                 &sudo_ctx->use_host_filter,
@@ -532,6 +537,7 @@ static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
+    state->sudo_ctx = sudo_ctx;
     state->id_ctx = id_ctx;
     state->sysdb = id_ctx->be->sysdb;
 
@@ -606,6 +612,8 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
         return;
     }
 
+    state->sudo_ctx->full_refresh_done = true;
+
     /* save the time in the sysdb */
     ret = sysdb_sudo_set_last_full_refresh(state->sysdb, time(NULL));
     if (ret != EOK) {
@@ -810,6 +818,7 @@ static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
     struct sdap_sudo_smart_refresh_state *state = NULL;
     char *ldap_filter = NULL;
     char *ldap_full_filter = NULL;
+    const char *usn;
     int ret;
 
     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
@@ -818,9 +827,11 @@ static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
-    if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
-        /* Perform full refresh */
-        DEBUG(SSSDBG_TRACE_FUNC, ("USN value is unknown!\n"));
+    if (!sudo_ctx->full_refresh_done
+            && (srv_opts == NULL || srv_opts->max_sudo_value == 0)) {
+        /* Perform full refresh first */
+        DEBUG(SSSDBG_TRACE_FUNC, ("USN value is unknown, "
+                                  "waiting for full refresh!\n"));
         ret = EINVAL;
         goto immediately;
     }
@@ -829,12 +840,11 @@ static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
     state->sysdb = id_ctx->be->sysdb;
 
     /* Download all rules from LDAP that are newer than usn */
+    usn = srv_opts->max_sudo_value == NULL ? "0" : srv_opts->max_sudo_value;
     ldap_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%s)(!(%s=%s)))",
                                   map[SDAP_OC_SUDORULE].name,
-                                  map[SDAP_AT_SUDO_USN].name,
-                                  srv_opts->max_sudo_value,
-                                  map[SDAP_AT_SUDO_USN].name,
-                                  srv_opts->max_sudo_value);
+                                  map[SDAP_AT_SUDO_USN].name, usn,
+                                  map[SDAP_AT_SUDO_USN].name, usn);
     if (ldap_filter == NULL) {
         ret = ENOMEM;
         goto immediately;
diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h
index d2c5e80f55b06529449a0e65ac9409ac98c82788..f9988d6116f048c3a698f920ed2d9baf9c06b6da 100644
--- a/src/providers/ldap/sdap_sudo.h
+++ b/src/providers/ldap/sdap_sudo.h
@@ -29,6 +29,8 @@ struct sdap_sudo_ctx {
     bool include_netgroups;
     bool include_regexp;
     bool use_host_filter;
+
+    bool full_refresh_done;
 };
 
 /* Common functions from ldap_sudo.c */
-- 
1.7.11.7

