d3b35fd
From 154d886c35318cabfb174e6791d3361ce760cdcd Mon Sep 17 00:00:00 2001
d3b35fd
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
d3b35fd
Date: Wed, 16 Dec 2015 14:42:04 +0100
d3b35fd
Subject: [PATCH 16/49] SUDO: make sudo sysdb interface more reusable
d3b35fd
d3b35fd
Reviewed-by: Sumit Bose <sbose@redhat.com>
d3b35fd
(cherry picked from commit 68abbe716bed7c8d6790d9bec168ef44469306a1)
d3b35fd
---
d3b35fd
 Makefile.am                          |   2 -
d3b35fd
 src/db/sysdb.c                       |  98 ++++++++++++
d3b35fd
 src/db/sysdb.h                       |   7 +
d3b35fd
 src/db/sysdb_sudo.c                  | 286 +++++++++++++++++++++++++++--------
d3b35fd
 src/db/sysdb_sudo.h                  |  17 +--
d3b35fd
 src/providers/ldap/sdap_async_sudo.c | 121 ++-------------
d3b35fd
 src/providers/ldap/sdap_sudo.c       |   1 -
d3b35fd
 src/providers/ldap/sdap_sudo_cache.c | 183 ----------------------
d3b35fd
 src/providers/ldap/sdap_sudo_cache.h |  37 -----
d3b35fd
 9 files changed, 354 insertions(+), 398 deletions(-)
d3b35fd
 delete mode 100644 src/providers/ldap/sdap_sudo_cache.c
d3b35fd
 delete mode 100644 src/providers/ldap/sdap_sudo_cache.h
d3b35fd
d3b35fd
diff --git a/Makefile.am b/Makefile.am
d3b35fd
index 095b1cfd62f49d266df278e1736d48ed5ef4fa7a..29dd73edf3e6770e4280945f69c9d266f3d8c4c4 100644
d3b35fd
--- a/Makefile.am
d3b35fd
+++ b/Makefile.am
d3b35fd
@@ -618,7 +618,6 @@ dist_noinst_HEADERS = \
d3b35fd
     src/providers/ldap/sdap_access.h \
d3b35fd
     src/providers/ldap/sdap_async.h \
d3b35fd
     src/providers/ldap/sdap_async_private.h \
d3b35fd
-    src/providers/ldap/sdap_sudo_cache.h \
d3b35fd
     src/providers/ldap/sdap_sudo.h \
d3b35fd
     src/providers/ldap/sdap_autofs.h \
d3b35fd
     src/providers/ldap/sdap_id_op.h \
d3b35fd
@@ -2859,7 +2858,6 @@ libsss_ldap_common_la_LDFLAGS = \
d3b35fd
 
d3b35fd
 if BUILD_SUDO
d3b35fd
 libsss_ldap_common_la_SOURCES += \
d3b35fd
-    src/providers/ldap/sdap_sudo_cache.c \
d3b35fd
     src/providers/ldap/sdap_async_sudo.c \
d3b35fd
     src/providers/ldap/sdap_async_sudo_hostinfo.c \
d3b35fd
     src/providers/ldap/sdap_sudo_refresh.c \
d3b35fd
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
d3b35fd
index a71364d7c4b600eafd10fafa6641eac7b2292764..d4366a3c76f114bf113567754a1e0417afe664e3 100644
d3b35fd
--- a/src/db/sysdb.c
d3b35fd
+++ b/src/db/sysdb.c
d3b35fd
@@ -2013,3 +2013,101 @@ errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count,
d3b35fd
 
d3b35fd
     return EOK;
d3b35fd
 }
d3b35fd
+
d3b35fd
+int sysdb_compare_usn(const char *a, const char *b)
d3b35fd
+{
d3b35fd
+    size_t len_a;
d3b35fd
+    size_t len_b;
d3b35fd
+
d3b35fd
+    if (a == NULL) {
d3b35fd
+        return -1;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    if (b == NULL) {
d3b35fd
+        return 1;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    len_a = strlen(a);
d3b35fd
+    len_b = strlen(b);
d3b35fd
+
d3b35fd
+    /* trim leading zeros */
d3b35fd
+    while (len_a > 0 && *a == '0') {
d3b35fd
+        a++;
d3b35fd
+        len_a--;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    while (len_b > 0 && *b == '0') {
d3b35fd
+        b++;
d3b35fd
+        len_b--;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    /* less digits means lower number */
d3b35fd
+    if (len_a < len_b) {
d3b35fd
+        return -1;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    /* more digits means bigger number */
d3b35fd
+    if (len_a > len_b) {
d3b35fd
+        return 1;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    /* now we can compare digits since alphabetical order is the same
d3b35fd
+     * as numeric order */
d3b35fd
+    return strcmp(a, b);
d3b35fd
+}
d3b35fd
+
d3b35fd
+errno_t sysdb_get_highest_usn(TALLOC_CTX *mem_ctx,
d3b35fd
+                              struct sysdb_attrs **attrs,
d3b35fd
+                              size_t num_attrs,
d3b35fd
+                              char **_usn)
d3b35fd
+{
d3b35fd
+    const char *highest = NULL;
d3b35fd
+    const char *current = NULL;
d3b35fd
+    char *usn;
d3b35fd
+    errno_t ret;
d3b35fd
+    size_t i;
d3b35fd
+
d3b35fd
+    if (num_attrs == 0 || attrs == NULL) {
d3b35fd
+        goto done;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    for (i = 0; i < num_attrs; i++) {
d3b35fd
+        ret = sysdb_attrs_get_string(attrs[i], SYSDB_USN, ¤t;;
d3b35fd
+        if (ret == ENOENT) {
d3b35fd
+            /* USN value is not present, assuming zero. */
d3b35fd
+            current = "0";
d3b35fd
+        } else if (ret != EOK) {
d3b35fd
+            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to retrieve USN value "
d3b35fd
+                  "[%d]: %s\n", ret, sss_strerror(ret));
d3b35fd
+
d3b35fd
+            return ret;
d3b35fd
+        }
d3b35fd
+
d3b35fd
+        if (current == NULL) {
d3b35fd
+            continue;
d3b35fd
+        }
d3b35fd
+
d3b35fd
+        if (highest == NULL) {
d3b35fd
+            highest = current;
d3b35fd
+            continue;
d3b35fd
+        }
d3b35fd
+
d3b35fd
+        if (sysdb_compare_usn(current, highest) > 0 ) {
d3b35fd
+            highest = current;
d3b35fd
+        }
d3b35fd
+    }
d3b35fd
+
d3b35fd
+done:
d3b35fd
+    if (highest == NULL) {
d3b35fd
+        usn = talloc_strdup(mem_ctx, "0");
d3b35fd
+    } else {
d3b35fd
+        usn = talloc_strdup(mem_ctx, highest);
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    if (usn == NULL) {
d3b35fd
+        return ENOMEM;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    *_usn = usn;
d3b35fd
+    return EOK;
d3b35fd
+}
d3b35fd
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
d3b35fd
index ad1bf75b7437730af4a56d97e8f9868073e678aa..2e797fd7fa39163c2ab6a10e51228e0f1af3f9e3 100644
d3b35fd
--- a/src/db/sysdb.h
d3b35fd
+++ b/src/db/sysdb.h
d3b35fd
@@ -386,6 +386,13 @@ errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count,
d3b35fd
                         struct ldb_message **msgs,
d3b35fd
                         struct sysdb_attrs ***attrs);
d3b35fd
 
d3b35fd
+int sysdb_compare_usn(const char *a, const char *b);
d3b35fd
+
d3b35fd
+errno_t sysdb_get_highest_usn(TALLOC_CTX *mem_ctx,
d3b35fd
+                              struct sysdb_attrs **attrs,
d3b35fd
+                              size_t num_attrs,
d3b35fd
+                              char **_usn);
d3b35fd
+
d3b35fd
 /* convert an ldb error into an errno error */
d3b35fd
 int sysdb_error_to_errno(int ldberr);
d3b35fd
 
d3b35fd
diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c
d3b35fd
index 784ac8af3ae5cb08f30eb9631c7ffa4aa92bde23..76116abacb20219f0c1dcdde755e8268e10fd293 100644
d3b35fd
--- a/src/db/sysdb_sudo.c
d3b35fd
+++ b/src/db/sysdb_sudo.c
d3b35fd
@@ -27,6 +27,8 @@
d3b35fd
 #include "db/sysdb_private.h"
d3b35fd
 #include "db/sysdb_sudo.h"
d3b35fd
 
d3b35fd
+#define SUDO_ALL_FILTER "(" SYSDB_OBJECTCLASS "=" SYSDB_SUDO_CACHE_OC ")"
d3b35fd
+
d3b35fd
 #define NULL_CHECK(val, rval, label) do { \
d3b35fd
     if (!val) {                           \
d3b35fd
         rval = ENOMEM;                    \
d3b35fd
@@ -427,41 +429,6 @@ done:
d3b35fd
     return ret;
d3b35fd
 }
d3b35fd
 
d3b35fd
-errno_t
d3b35fd
-sysdb_save_sudorule(struct sss_domain_info *domain,
d3b35fd
-                    const char *rule_name,
d3b35fd
-                    struct sysdb_attrs *attrs)
d3b35fd
-{
d3b35fd
-    errno_t ret;
d3b35fd
-
d3b35fd
-    DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", rule_name);
d3b35fd
-
d3b35fd
-    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
d3b35fd
-                                 SYSDB_SUDO_CACHE_OC);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Could not set rule object class [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, rule_name);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Could not set name attribute [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_store_custom(domain, rule_name,
d3b35fd
-                             SUDORULE_SUBDIR, attrs);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_custom failed [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    return EOK;
d3b35fd
-}
d3b35fd
-
d3b35fd
 static errno_t sysdb_sudo_set_refresh_time(struct sss_domain_info *domain,
d3b35fd
                                            const char *attr_name,
d3b35fd
                                            time_t value)
d3b35fd
@@ -615,6 +582,26 @@ errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain,
d3b35fd
 
d3b35fd
 /* ====================  Purge functions ==================== */
d3b35fd
 
d3b35fd
+static const char *
d3b35fd
+sysdb_sudo_get_rule_name(struct sysdb_attrs *rule)
d3b35fd
+{
d3b35fd
+    const char *name;
d3b35fd
+    errno_t ret;
d3b35fd
+
d3b35fd
+    ret = sysdb_attrs_get_string(rule, SYSDB_SUDO_CACHE_AT_CN, &name);
d3b35fd
+    if (ret == ERANGE) {
d3b35fd
+        DEBUG(SSSDBG_MINOR_FAILURE, "Warning: found rule that contains none "
d3b35fd
+              "or multiple CN values. It will be skipped.\n");
d3b35fd
+        return NULL;
d3b35fd
+    } else if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to obtain rule name [%d]: %s\n",
d3b35fd
+              ret, strerror(ret));
d3b35fd
+        return NULL;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    return name;
d3b35fd
+}
d3b35fd
+
d3b35fd
 static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain)
d3b35fd
 {
d3b35fd
     struct ldb_dn *base_dn = NULL;
d3b35fd
@@ -627,6 +614,8 @@ static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain)
d3b35fd
     base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, SUDORULE_SUBDIR);
d3b35fd
     NULL_CHECK(base_dn, ret, done);
d3b35fd
 
d3b35fd
+    DEBUG(SSSDBG_TRACE_FUNC, "Deleting all cached sudo rules\n");
d3b35fd
+
d3b35fd
     ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
d3b35fd
     if (ret != EOK) {
d3b35fd
         DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
d3b35fd
@@ -639,42 +628,74 @@ done:
d3b35fd
     return ret;
d3b35fd
 }
d3b35fd
 
d3b35fd
-errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain,
d3b35fd
-                                const char *name)
d3b35fd
+static errno_t
d3b35fd
+sysdb_sudo_purge_byname(struct sss_domain_info *domain,
d3b35fd
+                        const char *name)
d3b35fd
 {
d3b35fd
     DEBUG(SSSDBG_TRACE_INTERNAL, "Deleting sudo rule %s\n", name);
d3b35fd
     return sysdb_delete_custom(domain, name, SUDORULE_SUBDIR);
d3b35fd
 }
d3b35fd
 
d3b35fd
-errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
d3b35fd
-                                  const char *filter)
d3b35fd
+static errno_t
d3b35fd
+sysdb_sudo_purge_byrules(struct sss_domain_info *dom,
d3b35fd
+                         struct sysdb_attrs **rules,
d3b35fd
+                         size_t num_rules)
d3b35fd
+{
d3b35fd
+    const char *name;
d3b35fd
+    errno_t ret;
d3b35fd
+    size_t i;
d3b35fd
+
d3b35fd
+    DEBUG(SSSDBG_TRACE_FUNC, "About to remove rules from sudo cache\n");
d3b35fd
+
d3b35fd
+    if (num_rules == 0 || rules == NULL) {
d3b35fd
+        return EOK;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    for (i = 0; i < num_rules; i++) {
d3b35fd
+        name = sysdb_sudo_get_rule_name(rules[i]);
d3b35fd
+        if (name == NULL) {
d3b35fd
+            continue;
d3b35fd
+        }
d3b35fd
+
d3b35fd
+        ret = sysdb_sudo_purge_byname(dom, name);
d3b35fd
+        if (ret != EOK) {
d3b35fd
+            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to delete rule "
d3b35fd
+                  "%s [%d]: %s\n", name, ret, sss_strerror(ret));
d3b35fd
+            continue;
d3b35fd
+        }
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    return EOK;
d3b35fd
+}
d3b35fd
+
d3b35fd
+static errno_t
d3b35fd
+sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
d3b35fd
+                          const char *filter)
d3b35fd
 {
d3b35fd
     TALLOC_CTX *tmp_ctx;
d3b35fd
-    size_t count;
d3b35fd
+    struct sysdb_attrs **rules;
d3b35fd
     struct ldb_message **msgs;
d3b35fd
-    const char *name;
d3b35fd
-    int i;
d3b35fd
+    size_t count;
d3b35fd
     errno_t ret;
d3b35fd
-    errno_t sret;
d3b35fd
-    bool in_transaction = false;
d3b35fd
     const char *attrs[] = { SYSDB_OBJECTCLASS,
d3b35fd
                             SYSDB_NAME,
d3b35fd
                             SYSDB_SUDO_CACHE_AT_CN,
d3b35fd
                             NULL };
d3b35fd
 
d3b35fd
-    /* just purge all if there's no filter */
d3b35fd
-    if (!filter) {
d3b35fd
+    if (filter == NULL || strcmp(filter, SUDO_ALL_FILTER) == 0) {
d3b35fd
         return sysdb_sudo_purge_all(domain);
d3b35fd
     }
d3b35fd
 
d3b35fd
     tmp_ctx = talloc_new(NULL);
d3b35fd
-    NULL_CHECK(tmp_ctx, ret, done);
d3b35fd
+    if (tmp_ctx == NULL) {
d3b35fd
+        ret = ENOMEM;
d3b35fd
+        goto done;
d3b35fd
+    }
d3b35fd
 
d3b35fd
-    /* match entries based on the filter and remove them one by one */
d3b35fd
     ret = sysdb_search_custom(tmp_ctx, domain, filter,
d3b35fd
                               SUDORULE_SUBDIR, attrs,
d3b35fd
                               &count, &msgs);
d3b35fd
-    if (ret == ENOENT) {
d3b35fd
+    if (ret == ENOENT || count == 0) {
d3b35fd
         DEBUG(SSSDBG_TRACE_FUNC, "No rules matched\n");
d3b35fd
         ret = EOK;
d3b35fd
         goto done;
d3b35fd
@@ -683,24 +704,165 @@ errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
d3b35fd
         goto done;
d3b35fd
     }
d3b35fd
 
d3b35fd
+    ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to convert ldb message to "
d3b35fd
+              "sysdb attrs [%d]: %s\n", ret, sss_strerror(ret));
d3b35fd
+        goto done;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    ret = sysdb_sudo_purge_byrules(domain, rules, count);
d3b35fd
+
d3b35fd
+done:
d3b35fd
+    talloc_free(tmp_ctx);
d3b35fd
+    return ret;
d3b35fd
+}
d3b35fd
+
d3b35fd
+errno_t sysdb_sudo_purge(struct sss_domain_info *domain,
d3b35fd
+                         const char *delete_filter,
d3b35fd
+                         struct sysdb_attrs **rules,
d3b35fd
+                         size_t num_rules)
d3b35fd
+{
d3b35fd
+    bool in_transaction = false;
d3b35fd
+    errno_t sret;
d3b35fd
+    errno_t ret;
d3b35fd
+
d3b35fd
     ret = sysdb_transaction_start(domain->sysdb);
d3b35fd
     if (ret != EOK) {
d3b35fd
         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+    in_transaction = true;
d3b35fd
+
d3b35fd
+    if (delete_filter) {
d3b35fd
+        ret = sysdb_sudo_purge_byfilter(domain, delete_filter);
d3b35fd
+    } else {
d3b35fd
+        ret = sysdb_sudo_purge_byrules(domain, rules, num_rules);
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    if (ret != EOK) {
d3b35fd
         goto done;
d3b35fd
     }
d3b35fd
+
d3b35fd
+    ret = sysdb_transaction_commit(domain->sysdb);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
d3b35fd
+        goto done;
d3b35fd
+    }
d3b35fd
+    in_transaction = false;
d3b35fd
+
d3b35fd
+done:
d3b35fd
+    if (in_transaction) {
d3b35fd
+        sret = sysdb_transaction_cancel(domain->sysdb);
d3b35fd
+        if (sret != EOK) {
d3b35fd
+            DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
d3b35fd
+        }
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to purge sudo cache [%d]: %s\n",
d3b35fd
+              ret, sss_strerror(ret));
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    return ret;
d3b35fd
+}
d3b35fd
+
d3b35fd
+static errno_t
d3b35fd
+sysdb_sudo_add_sss_attrs(struct sysdb_attrs *rule,
d3b35fd
+                         const char *name,
d3b35fd
+                         int cache_timeout,
d3b35fd
+                         time_t now)
d3b35fd
+{
d3b35fd
+    time_t expire;
d3b35fd
+    errno_t ret;
d3b35fd
+
d3b35fd
+    ret = sysdb_attrs_add_string(rule, SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n",
d3b35fd
+                SYSDB_OBJECTCLASS, ret, strerror(ret));
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    ret = sysdb_attrs_add_string(rule, SYSDB_NAME, name);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n",
d3b35fd
+                SYSDB_OBJECTCLASS, ret, strerror(ret));
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    expire = cache_timeout > 0 ? now + cache_timeout : 0;
d3b35fd
+    ret = sysdb_attrs_add_time_t(rule, SYSDB_CACHE_EXPIRE, expire);
d3b35fd
+    if (ret) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n",
d3b35fd
+              SYSDB_CACHE_EXPIRE, ret, strerror(ret));
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    return EOK;
d3b35fd
+}
d3b35fd
+
d3b35fd
+static errno_t
d3b35fd
+sysdb_sudo_store_rule(struct sss_domain_info *domain,
d3b35fd
+                      struct sysdb_attrs *rule,
d3b35fd
+                      int cache_timeout,
d3b35fd
+                      time_t now)
d3b35fd
+{
d3b35fd
+    const char *name;
d3b35fd
+    errno_t ret;
d3b35fd
+
d3b35fd
+    name = sysdb_sudo_get_rule_name(rule);
d3b35fd
+    if (name == NULL) {
d3b35fd
+        return EINVAL;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", name);
d3b35fd
+
d3b35fd
+    ret = sysdb_sudo_add_sss_attrs(rule, name, cache_timeout, now);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    ret = sysdb_store_custom(domain, name, SUDORULE_SUBDIR, rule);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to store rule %s [%d]: %s\n",
d3b35fd
+              name, ret, strerror(ret));
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    return EOK;
d3b35fd
+}
d3b35fd
+
d3b35fd
+errno_t
d3b35fd
+sysdb_sudo_store(struct sss_domain_info *domain,
d3b35fd
+                 struct sysdb_attrs **rules,
d3b35fd
+                 size_t num_rules)
d3b35fd
+{
d3b35fd
+    bool in_transaction = false;
d3b35fd
+    errno_t sret;
d3b35fd
+    errno_t ret;
d3b35fd
+    time_t now;
d3b35fd
+    size_t i;
d3b35fd
+
d3b35fd
+    if (num_rules == 0 || rules == NULL) {
d3b35fd
+        return EOK;
d3b35fd
+    }
d3b35fd
+
d3b35fd
+    ret = sysdb_transaction_start(domain->sysdb);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
d3b35fd
+        return ret;
d3b35fd
+    }
d3b35fd
     in_transaction = true;
d3b35fd
 
d3b35fd
-    for (i = 0; i < count; i++) {
d3b35fd
-        name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
d3b35fd
-        if (name == NULL) {
d3b35fd
-            DEBUG(SSSDBG_OP_FAILURE, "A rule without a name?\n");
d3b35fd
-            /* skip this one but still delete other entries */
d3b35fd
+    now = time(NULL);
d3b35fd
+    for (i = 0; i < num_rules; i++) {
d3b35fd
+        ret = sysdb_sudo_store_rule(domain, rules[i],
d3b35fd
+                                    domain->sudo_timeout, now);
d3b35fd
+        if (ret == EINVAL) {
d3b35fd
+            /* Multiple CNs are error on server side, we can just ignore this
d3b35fd
+             * rule and save the others. Loud debug message is in logs. */
d3b35fd
             continue;
d3b35fd
-        }
d3b35fd
-
d3b35fd
-        ret = sysdb_sudo_purge_byname(domain, name);
d3b35fd
-        if (ret != EOK) {
d3b35fd
-            DEBUG(SSSDBG_OP_FAILURE, "Could not delete rule %s\n", name);
d3b35fd
+        } else if (ret != EOK) {
d3b35fd
             goto done;
d3b35fd
         }
d3b35fd
     }
d3b35fd
@@ -720,6 +882,10 @@ done:
d3b35fd
         }
d3b35fd
     }
d3b35fd
 
d3b35fd
-    talloc_free(tmp_ctx);
d3b35fd
+    if (ret != EOK) {
d3b35fd
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to store sudo rules [%d]: %s\n",
d3b35fd
+              ret, sss_strerror(ret));
d3b35fd
+    }
d3b35fd
+
d3b35fd
     return ret;
d3b35fd
 }
d3b35fd
diff --git a/src/db/sysdb_sudo.h b/src/db/sysdb_sudo.h
d3b35fd
index fc896c385c6fa71e735b3db763ccee4a0354d007..6dd9ea7bb8ec947f5beceb89fd27bde156c27c36 100644
d3b35fd
--- a/src/db/sysdb_sudo.h
d3b35fd
+++ b/src/db/sysdb_sudo.h
d3b35fd
@@ -78,20 +78,19 @@ sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
d3b35fd
                          const char *username, uid_t *_uid,
d3b35fd
                          char ***groupnames);
d3b35fd
 
d3b35fd
-errno_t
d3b35fd
-sysdb_save_sudorule(struct sss_domain_info *domain,
d3b35fd
-                    const char *rule_name,
d3b35fd
-                    struct sysdb_attrs *attrs);
d3b35fd
-
d3b35fd
 errno_t sysdb_sudo_set_last_full_refresh(struct sss_domain_info *domain,
d3b35fd
                                          time_t value);
d3b35fd
 errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain,
d3b35fd
                                          time_t *value);
d3b35fd
 
d3b35fd
-errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain,
d3b35fd
-                                const char *name);
d3b35fd
+errno_t sysdb_sudo_purge(struct sss_domain_info *domain,
d3b35fd
+                         const char *delete_filter,
d3b35fd
+                         struct sysdb_attrs **rules,
d3b35fd
+                         size_t num_rules);
d3b35fd
 
d3b35fd
-errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
d3b35fd
-                                  const char *filter);
d3b35fd
+errno_t
d3b35fd
+sysdb_sudo_store(struct sss_domain_info *domain,
d3b35fd
+                 struct sysdb_attrs **rules,
d3b35fd
+                 size_t num_rules);
d3b35fd
 
d3b35fd
 #endif /* _SYSDB_SUDO_H_ */
d3b35fd
diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c
d3b35fd
index d7780d38405a2705e25a9c983aca2736548a624e..2fcfa4aec5d4d53f26d40395e99bdce1b41710d4 100644
d3b35fd
--- a/src/providers/ldap/sdap_async_sudo.c
d3b35fd
+++ b/src/providers/ldap/sdap_async_sudo.c
d3b35fd
@@ -31,7 +31,6 @@
d3b35fd
 #include "providers/ldap/sdap.h"
d3b35fd
 #include "providers/ldap/sdap_ops.h"
d3b35fd
 #include "providers/ldap/sdap_sudo.h"
d3b35fd
-#include "providers/ldap/sdap_sudo_cache.h"
d3b35fd
 #include "db/sysdb_sudo.h"
d3b35fd
 
d3b35fd
 struct sdap_sudo_load_sudoers_state {
d3b35fd
@@ -136,89 +135,6 @@ static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
d3b35fd
     return EOK;
d3b35fd
 }
d3b35fd
 
d3b35fd
-static int sdap_sudo_purge_sudoers(struct sss_domain_info *dom,
d3b35fd
-                                   const char *filter,
d3b35fd
-                                   struct sdap_attr_map *map,
d3b35fd
-                                   size_t rules_count,
d3b35fd
-                                   struct sysdb_attrs **rules)
d3b35fd
-{
d3b35fd
-    const char *name;
d3b35fd
-    size_t i;
d3b35fd
-    errno_t ret;
d3b35fd
-
d3b35fd
-    if (filter == NULL) {
d3b35fd
-        /* removes downloaded rules from the cache */
d3b35fd
-        if (rules_count == 0 || rules == NULL) {
d3b35fd
-            return EOK;
d3b35fd
-        }
d3b35fd
-
d3b35fd
-        for (i = 0; i < rules_count; i++) {
d3b35fd
-            ret = sysdb_attrs_get_string(rules[i],
d3b35fd
-                                         map[SDAP_AT_SUDO_NAME].sys_name,
d3b35fd
-                                         &name);
d3b35fd
-            if (ret != EOK) {
d3b35fd
-                DEBUG(SSSDBG_MINOR_FAILURE,
d3b35fd
-                      "Failed to retrieve rule name: [%s]\n", strerror(ret));
d3b35fd
-                continue;
d3b35fd
-            }
d3b35fd
-
d3b35fd
-            ret = sysdb_sudo_purge_byname(dom, name);
d3b35fd
-            if (ret != EOK) {
d3b35fd
-                DEBUG(SSSDBG_MINOR_FAILURE,
d3b35fd
-                      "Failed to delete rule %s: [%s]\n",
d3b35fd
-                      name, strerror(ret));
d3b35fd
-                continue;
d3b35fd
-            }
d3b35fd
-        }
d3b35fd
-
d3b35fd
-        ret = EOK;
d3b35fd
-    } else {
d3b35fd
-        /* purge cache by provided filter */
d3b35fd
-        ret = sysdb_sudo_purge_byfilter(dom, filter);
d3b35fd
-        if (ret != EOK) {
d3b35fd
-            goto done;
d3b35fd
-        }
d3b35fd
-    }
d3b35fd
-
d3b35fd
-done:
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "failed to purge sudo rules [%d]: %s\n",
d3b35fd
-                                 ret, strerror(ret));
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    return ret;
d3b35fd
-}
d3b35fd
-
d3b35fd
-static int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx,
d3b35fd
-                                   struct sss_domain_info *domain,
d3b35fd
-                                   struct sdap_options *opts,
d3b35fd
-                                   size_t rules_count,
d3b35fd
-                                   struct sysdb_attrs **rules,
d3b35fd
-                                   int cache_timeout,
d3b35fd
-                                   time_t now,
d3b35fd
-                                   char **_usn)
d3b35fd
-{
d3b35fd
-    errno_t ret;
d3b35fd
-
d3b35fd
-    /* Empty sudoers? Done. */
d3b35fd
-    if (rules_count == 0 || rules == NULL) {
d3b35fd
-        *_usn = NULL;
d3b35fd
-        return EOK;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sdap_save_native_sudorule_list(mem_ctx, domain,
d3b35fd
-                                         opts->sudorule_map, rules,
d3b35fd
-                                         rules_count, cache_timeout, now,
d3b35fd
-                                         _usn);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "failed to save sudo rules [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    return EOK;
d3b35fd
-}
d3b35fd
-
d3b35fd
 static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
d3b35fd
 {
d3b35fd
     unsigned int usn_number;
d3b35fd
@@ -230,23 +146,14 @@ static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
d3b35fd
     }
d3b35fd
 
d3b35fd
     if (usn == NULL) {
d3b35fd
-        /* If the USN value is unknown and we don't have max_sudo_value set
d3b35fd
-         * (possibly first full refresh which did not find any rule) we will
d3b35fd
-         * set zero so smart refresh can pick up. */
d3b35fd
-        if (srv_opts->max_sudo_value == NULL) {
d3b35fd
-            srv_opts->max_sudo_value = talloc_strdup(srv_opts, "0");
d3b35fd
-            if (srv_opts->max_sudo_value == NULL) {
d3b35fd
-                DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
d3b35fd
-            }
d3b35fd
-            return;
d3b35fd
-        }
d3b35fd
-
d3b35fd
-        DEBUG(SSSDBG_TRACE_FUNC, "Empty USN, ignoring\n");
d3b35fd
+        DEBUG(SSSDBG_TRACE_FUNC, "Bug: usn is NULL\n");
d3b35fd
         return;
d3b35fd
     }
d3b35fd
 
d3b35fd
-    talloc_zfree(srv_opts->max_sudo_value);
d3b35fd
-    srv_opts->max_sudo_value = talloc_steal(srv_opts, usn);
d3b35fd
+    if (sysdb_compare_usn(usn, srv_opts->max_sudo_value) > 0) {
d3b35fd
+        talloc_zfree(srv_opts->max_sudo_value);
d3b35fd
+        srv_opts->max_sudo_value = talloc_steal(srv_opts, usn);
d3b35fd
+    }
d3b35fd
 
d3b35fd
     usn_number = strtoul(usn, &endptr, 10);
d3b35fd
     if ((endptr == NULL || (*endptr == '\0' && endptr != usn))
d3b35fd
@@ -625,7 +532,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
d3b35fd
     int ret;
d3b35fd
     errno_t sret;
d3b35fd
     bool in_transaction = false;
d3b35fd
-    time_t now;
d3b35fd
 
d3b35fd
     req = tevent_req_callback_data(subreq, struct tevent_req);
d3b35fd
     state = tevent_req_data(req, struct sdap_sudo_refresh_state);
d3b35fd
@@ -654,17 +560,14 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
d3b35fd
     in_transaction = true;
d3b35fd
 
d3b35fd
     /* purge cache */
d3b35fd
-    ret = sdap_sudo_purge_sudoers(state->domain, state->delete_filter,
d3b35fd
-                                  state->opts->sudorule_map, rules_count, rules);
d3b35fd
+    ret = sysdb_sudo_purge(state->domain, state->delete_filter,
d3b35fd
+                           rules, rules_count);
d3b35fd
     if (ret != EOK) {
d3b35fd
         goto done;
d3b35fd
     }
d3b35fd
 
d3b35fd
     /* store rules */
d3b35fd
-    now = time(NULL);
d3b35fd
-    ret = sdap_sudo_store_sudoers(state, state->domain,
d3b35fd
-                                  state->opts, rules_count, rules,
d3b35fd
-                                  state->domain->sudo_timeout, now, &usn;;
d3b35fd
+    ret = sysdb_sudo_store(state->domain, rules, rules_count);
d3b35fd
     if (ret != EOK) {
d3b35fd
         goto done;
d3b35fd
     }
d3b35fd
@@ -680,7 +583,13 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
d3b35fd
     DEBUG(SSSDBG_TRACE_FUNC, "Sudoers is successfuly stored in cache\n");
d3b35fd
 
d3b35fd
     /* remember new usn */
d3b35fd
-    sdap_sudo_set_usn(state->srv_opts, usn);
d3b35fd
+    ret = sysdb_get_highest_usn(state, rules, rules_count, &usn;;
d3b35fd
+    if (ret == EOK) {
d3b35fd
+        sdap_sudo_set_usn(state->srv_opts, usn);
d3b35fd
+    } else {
d3b35fd
+        DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get highest USN [%d]: %s\n",
d3b35fd
+              ret, sss_strerror(ret));
d3b35fd
+    }
d3b35fd
 
d3b35fd
     ret = EOK;
d3b35fd
     state->num_rules = rules_count;
d3b35fd
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
d3b35fd
index 550784842c6e6162d153785940c1e37a51b5dc1f..10067e9ba779b5224bf21dd7a705c45e7f4e0f99 100644
d3b35fd
--- a/src/providers/ldap/sdap_sudo.c
d3b35fd
+++ b/src/providers/ldap/sdap_sudo.c
d3b35fd
@@ -27,7 +27,6 @@
d3b35fd
 #include "providers/ldap/sdap.h"
d3b35fd
 #include "providers/ldap/sdap_async.h"
d3b35fd
 #include "providers/ldap/sdap_sudo.h"
d3b35fd
-#include "providers/ldap/sdap_sudo_cache.h"
d3b35fd
 #include "db/sysdb_sudo.h"
d3b35fd
 
d3b35fd
 static void sdap_sudo_handler(struct be_req *breq);
d3b35fd
diff --git a/src/providers/ldap/sdap_sudo_cache.c b/src/providers/ldap/sdap_sudo_cache.c
d3b35fd
deleted file mode 100644
d3b35fd
index 56e84ce8f26338ea5856eb5c76627641eee93df1..0000000000000000000000000000000000000000
d3b35fd
--- a/src/providers/ldap/sdap_sudo_cache.c
d3b35fd
+++ /dev/null
d3b35fd
@@ -1,183 +0,0 @@
d3b35fd
-/*
d3b35fd
-    Authors:
d3b35fd
-        Jakub Hrozek <jhrozek@redhat.com>
d3b35fd
-
d3b35fd
-    Copyright (C) 2011 Red Hat
d3b35fd
-
d3b35fd
-    This program is free software; you can redistribute it and/or modify
d3b35fd
-    it under the terms of the GNU General Public License as published by
d3b35fd
-    the Free Software Foundation; either version 3 of the License, or
d3b35fd
-    (at your option) any later version.
d3b35fd
-
d3b35fd
-    This program is distributed in the hope that it will be useful,
d3b35fd
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
d3b35fd
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d3b35fd
-    GNU General Public License for more details.
d3b35fd
-
d3b35fd
-    You should have received a copy of the GNU General Public License
d3b35fd
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
d3b35fd
-*/
d3b35fd
-
d3b35fd
-#include <talloc.h>
d3b35fd
-
d3b35fd
-#include "db/sysdb.h"
d3b35fd
-#include "db/sysdb_sudo.h"
d3b35fd
-#include "providers/ldap/sdap_sudo_cache.h"
d3b35fd
-
d3b35fd
-/* ==========  Functions specific for the native sudo LDAP schema ========== */
d3b35fd
-static errno_t sdap_sudo_get_usn(TALLOC_CTX *mem_ctx,
d3b35fd
-                                 struct sysdb_attrs *attrs,
d3b35fd
-                                 struct sdap_attr_map *map,
d3b35fd
-                                 char **_usn)
d3b35fd
-{
d3b35fd
-    const char *usn;
d3b35fd
-    errno_t ret;
d3b35fd
-
d3b35fd
-    if (_usn == NULL) {
d3b35fd
-        return EINVAL;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_USN].sys_name, &usn;;
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_MINOR_FAILURE,
d3b35fd
-              "Failed to retrieve USN value: [%s]\n", strerror(ret));
d3b35fd
-
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    *_usn = talloc_strdup(mem_ctx, usn);
d3b35fd
-    if (*_usn == NULL) {
d3b35fd
-        return ENOMEM;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    return EOK;
d3b35fd
-}
d3b35fd
-
d3b35fd
-static errno_t
d3b35fd
-sdap_save_native_sudorule(TALLOC_CTX *mem_ctx,
d3b35fd
-                          struct sss_domain_info *domain,
d3b35fd
-                          struct sdap_attr_map *map,
d3b35fd
-                          struct sysdb_attrs *attrs,
d3b35fd
-                          int cache_timeout,
d3b35fd
-                          time_t now,
d3b35fd
-                          char **_usn)
d3b35fd
-{
d3b35fd
-    errno_t ret;
d3b35fd
-    const char *rule_name;
d3b35fd
-
d3b35fd
-    ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_NAME].sys_name,
d3b35fd
-                                 &rule_name);
d3b35fd
-    if (ret == ERANGE) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Warning: found rule that contains none "
d3b35fd
-              "or multiple CN values. It will be skipped.\n");
d3b35fd
-        return ret;
d3b35fd
-    } else if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Could not get rule name [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
d3b35fd
-                                 (cache_timeout ? (now + cache_timeout) : 0));
d3b35fd
-    if (ret) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n",
d3b35fd
-              ret, strerror(ret));
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sdap_sudo_get_usn(mem_ctx, attrs, map, _usn);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_MINOR_FAILURE, "Could not read USN from %s\n", rule_name);
d3b35fd
-        *_usn = NULL;
d3b35fd
-        /* but we will store the rule anyway */
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_save_sudorule(domain, rule_name, attrs);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_OP_FAILURE, "Could not save sudorule %s\n", rule_name);
d3b35fd
-        return ret;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    return ret;
d3b35fd
-}
d3b35fd
-
d3b35fd
-errno_t
d3b35fd
-sdap_save_native_sudorule_list(TALLOC_CTX *mem_ctx,
d3b35fd
-                               struct sss_domain_info *domain,
d3b35fd
-                               struct sdap_attr_map *map,
d3b35fd
-                               struct sysdb_attrs **replies,
d3b35fd
-                               size_t replies_count,
d3b35fd
-                               int cache_timeout,
d3b35fd
-                               time_t now,
d3b35fd
-                               char **_usn)
d3b35fd
-{
d3b35fd
-    TALLOC_CTX *tmp_ctx = NULL;
d3b35fd
-    char *higher_usn = NULL;
d3b35fd
-    char *usn_value = NULL;
d3b35fd
-    errno_t ret, tret;
d3b35fd
-    bool in_transaction = false;
d3b35fd
-    size_t i;
d3b35fd
-
d3b35fd
-    tmp_ctx = talloc_new(NULL);
d3b35fd
-    if (tmp_ctx == NULL)  {
d3b35fd
-        DEBUG(SSSDBG_FATAL_FAILURE, "talloc_new() failed\n");
d3b35fd
-        return ENOMEM;
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_transaction_start(domain->sysdb);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_CRIT_FAILURE, "Could not start transaction\n");
d3b35fd
-        goto fail;
d3b35fd
-    }
d3b35fd
-    in_transaction = true;
d3b35fd
-
d3b35fd
-    for (i=0; i < replies_count; i++) {
d3b35fd
-        usn_value = NULL;
d3b35fd
-        ret = sdap_save_native_sudorule(tmp_ctx, domain, map, replies[i],
d3b35fd
-                                        cache_timeout, now, &usn_value);
d3b35fd
-        if (ret != EOK) {
d3b35fd
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save sudo rule, "
d3b35fd
-                                        "will continue with next...\n");
d3b35fd
-            continue;
d3b35fd
-        }
d3b35fd
-
d3b35fd
-        /* find highest usn */
d3b35fd
-        if (usn_value) {
d3b35fd
-            if (higher_usn) {
d3b35fd
-                if ((strlen(usn_value) > strlen(higher_usn)) ||
d3b35fd
-                    (strcmp(usn_value, higher_usn) > 0)) {
d3b35fd
-                    talloc_zfree(higher_usn);
d3b35fd
-                    higher_usn = usn_value;
d3b35fd
-                } else {
d3b35fd
-                    talloc_zfree(usn_value);
d3b35fd
-                }
d3b35fd
-            } else {
d3b35fd
-                higher_usn = usn_value;
d3b35fd
-            }
d3b35fd
-        }
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = sysdb_transaction_commit(domain->sysdb);
d3b35fd
-    if (ret != EOK) {
d3b35fd
-        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
d3b35fd
-        goto fail;
d3b35fd
-    }
d3b35fd
-    in_transaction = false;
d3b35fd
-
d3b35fd
-    if (higher_usn != NULL) {
d3b35fd
-        *_usn = talloc_steal(mem_ctx, higher_usn);
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    ret = EOK;
d3b35fd
-fail:
d3b35fd
-    if (in_transaction) {
d3b35fd
-        tret = sysdb_transaction_cancel(domain->sysdb);
d3b35fd
-        if (tret != EOK) {
d3b35fd
-            DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
d3b35fd
-        }
d3b35fd
-    }
d3b35fd
-
d3b35fd
-    talloc_free(tmp_ctx);
d3b35fd
-
d3b35fd
-    return ret;
d3b35fd
-}
d3b35fd
diff --git a/src/providers/ldap/sdap_sudo_cache.h b/src/providers/ldap/sdap_sudo_cache.h
d3b35fd
deleted file mode 100644
d3b35fd
index 5a756bf313831267cf34676b392973a1a8e740ec..0000000000000000000000000000000000000000
d3b35fd
--- a/src/providers/ldap/sdap_sudo_cache.h
d3b35fd
+++ /dev/null
d3b35fd
@@ -1,37 +0,0 @@
d3b35fd
-/*
d3b35fd
-    Authors:
d3b35fd
-        Jakub Hrozek <jhrozek@redhat.com>
d3b35fd
-
d3b35fd
-    Copyright (C) 2011 Red Hat
d3b35fd
-
d3b35fd
-    This program is free software; you can redistribute it and/or modify
d3b35fd
-    it under the terms of the GNU General Public License as published by
d3b35fd
-    the Free Software Foundation; either version 3 of the License, or
d3b35fd
-    (at your option) any later version.
d3b35fd
-
d3b35fd
-    This program is distributed in the hope that it will be useful,
d3b35fd
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
d3b35fd
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d3b35fd
-    GNU General Public License for more details.
d3b35fd
-
d3b35fd
-    You should have received a copy of the GNU General Public License
d3b35fd
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
d3b35fd
-*/
d3b35fd
-
d3b35fd
-#ifndef _SDAP_SUDO_CACHE_H_
d3b35fd
-#define _SDAP_SUDO_CACHE_H_
d3b35fd
-
d3b35fd
-#include "src/providers/ldap/sdap.h"
d3b35fd
-
d3b35fd
-/* Cache functions specific for the native sudo LDAP schema */
d3b35fd
-errno_t
d3b35fd
-sdap_save_native_sudorule_list(TALLOC_CTX *mem_ctx,
d3b35fd
-                               struct sss_domain_info *domain,
d3b35fd
-                               struct sdap_attr_map *map,
d3b35fd
-                               struct sysdb_attrs **replies,
d3b35fd
-                               size_t replies_count,
d3b35fd
-                               int cache_timeout,
d3b35fd
-                               time_t now,
d3b35fd
-                               char **_usn);
d3b35fd
-
d3b35fd
-#endif /* _SDAP_SUDO_CACHE_H_ */
d3b35fd
-- 
d3b35fd
2.5.0
d3b35fd