>From 725cb791d43e9f651345ec50419143c4e6bd22b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Thu, 6 Aug 2015 09:16:03 +0200
Subject: [PATCH 1/3] SYSDB: Add function to expire entry

Ticket:
https://fedorahosted.org/sssd/ticket/2676

Added function to expire entry in sysdb using
its DN.
---
 src/db/sysdb.h          |  7 ++++-
 src/db/sysdb_ops.c      | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/tests/sysdb-tests.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 9e28b5c..75d7318 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -717,11 +717,16 @@ int sysdb_delete_entry(struct sysdb_ctx *sysdb,
                        struct ldb_dn *dn,
                        bool ignore_not_found);
 
-
 int sysdb_delete_recursive(struct sysdb_ctx *sysdb,
                            struct ldb_dn *dn,
                            bool ignore_not_found);
 
+/* Mark entry as expired */
+int sysdb_mark_entry_as_expired_ldb_dn(struct sss_domain_info *dom,
+                                       struct ldb_dn *ldbdn);
+int sysdb_mark_entry_as_expired_ldb_val(struct sss_domain_info *dom,
+                                        struct ldb_val *dn_val);
+
 /* Search Entry */
 int sysdb_search_entry(TALLOC_CTX *mem_ctx,
                        struct sysdb_ctx *sysdb,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index d1d43eb..6d4070a 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3875,3 +3875,73 @@ errno_t sysdb_handle_original_uuid(const char *orig_name,
 
     return EOK;
 }
+
+/* Mark entry as expired */
+int sysdb_mark_entry_as_expired_ldb_dn(struct sss_domain_info *dom,
+                                       struct ldb_dn *ldbdn)
+{
+    struct ldb_message *msg;
+    int ret;
+    TALLOC_CTX *tmp_ctx;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    msg = ldb_msg_new(tmp_ctx);
+    if (msg == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    msg->dn = ldbdn;
+
+    ret = ldb_msg_add_empty(msg, SYSDB_CACHE_EXPIRE,
+                            LDB_FLAG_MOD_REPLACE, NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = ldb_msg_add_string(msg, SYSDB_CACHE_EXPIRE, "1");
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = ldb_modify(dom->sysdb->ldb, msg);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+int sysdb_mark_entry_as_expired_ldb_val(struct sss_domain_info *dom,
+                                        struct ldb_val *dn_val)
+{
+    struct ldb_dn *ldbdn;
+    int ret;
+    TALLOC_CTX *tmpctx;
+
+    tmpctx = talloc_new(NULL);
+    if (tmpctx == NULL) {
+        return ENOMEM;
+    }
+
+    ldbdn = ldb_dn_from_ldb_val(tmpctx, dom->sysdb->ldb, dn_val);
+    if (ldbdn == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_mark_entry_as_expired_ldb_dn(dom, ldbdn);
+done:
+    talloc_free(tmpctx);
+    return ret;
+}
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 24d1527..3bd03b1 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -6212,6 +6212,74 @@ START_TEST(test_confdb_list_all_domain_names_multi_dom)
 }
 END_TEST
 
+START_TEST(test_sysdb_mark_entry_as_expired_ldb_dn)
+{
+    errno_t ret;
+    struct sysdb_test_ctx *test_ctx;
+    const char *attrs[] = { SYSDB_CACHE_EXPIRE, NULL };
+    size_t count;
+    struct ldb_message **msgs;
+    uint64_t expire;
+    struct ldb_dn *userdn;
+
+    ret = setup_sysdb_tests(&test_ctx);
+    fail_if(ret != EOK, "Could not setup the test");
+
+    /* Add something to database to test against */
+
+    ret = sysdb_transaction_start(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_add_user(test_ctx->domain, "testuser",
+                         2000, 0, "Test User", "/home/testuser",
+                         "/bin/bash",
+                         NULL, NULL, 500, 0);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_transaction_commit(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_search_users(test_ctx, test_ctx->domain,
+                             "("SYSDB_UIDNUM"=2000)", attrs, &count, &msgs);
+    ck_assert_int_eq(ret, EOK);
+    ck_assert_int_eq(count, 1);
+
+    expire = ldb_msg_find_attr_as_uint64(msgs[0], SYSDB_CACHE_EXPIRE, 0);
+    ck_assert(expire != 1);
+
+    userdn = sysdb_user_dn(test_ctx, test_ctx->domain, "testuser");
+    ck_assert(userdn != NULL);
+
+    ret = sysdb_transaction_start(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+
+    /* Expire entry */
+    ret = sysdb_mark_entry_as_expired_ldb_dn(test_ctx->domain, userdn);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_transaction_commit(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_search_users(test_ctx, test_ctx->domain,
+                             "("SYSDB_UIDNUM"=2000)", attrs, &count, &msgs);
+    ck_assert_int_eq(ret, EOK);
+    ck_assert_int_eq(count, 1);
+
+    expire = ldb_msg_find_attr_as_uint64(msgs[0], SYSDB_CACHE_EXPIRE, 0);
+    ck_assert_int_eq(expire, 1);
+
+    /* Attempt to mark missing entry should be OK */
+    ret = sysdb_transaction_start(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_mark_entry_as_expired_ldb_dn(test_ctx->domain, userdn);
+    ck_assert_int_eq(ret, EOK);
+
+    ret = sysdb_transaction_commit(test_ctx->sysdb);
+    ck_assert_int_eq(ret, EOK);
+}
+END_TEST
+
 Suite *create_sysdb_suite(void)
 {
     Suite *s = suite_create("sysdb");
@@ -6424,6 +6492,7 @@ Suite *create_sysdb_suite(void)
 
 /* ===== Misc ===== */
     tcase_add_test(tc_sysdb, test_sysdb_set_get_bool);
+    tcase_add_test(tc_sysdb, test_sysdb_mark_entry_as_expired_ldb_dn);
 
 /* Add all test cases to the test suite */
     suite_add_tcase(s, tc_sysdb);
-- 
2.1.0

