Blame SOURCES/0076-NEGCACHE-Add-API-for-setting-and-checking-locate-acc.patch

ced1f5
From 72fdce0007af1baa0504c2d11be8b19e1a3296f1 Mon Sep 17 00:00:00 2001
ced1f5
From: Jakub Hrozek <jhrozek@redhat.com>
ced1f5
Date: Mon, 6 Nov 2017 10:09:16 +0100
ced1f5
Subject: [PATCH 76/83] NEGCACHE: Add API for setting and checking
ced1f5
 locate-account-domain requests
ced1f5
MIME-Version: 1.0
ced1f5
Content-Type: text/plain; charset=UTF-8
ced1f5
Content-Transfer-Encoding: 8bit
ced1f5
ced1f5
Extends the negative cache API with several request getsetters:
ced1f5
    - sss_ncache_set/check_domain_locate_type - check if this request
ced1f5
      type supports locating account domain or set that this request
ced1f5
      type does not support the locator.
ced1f5
ced1f5
    - sss_ncache_set/check_locate_gid/uid - check if it is time to call
ced1f5
      the locator again or set that the locator should not be called
ced1f5
      for IDs again for the duration of the negative cache.
ced1f5
ced1f5
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
ced1f5
Reviewed-by: Sumit Bose <sbose@redhat.com>
ced1f5
(cherry picked from commit 07452697a67902dc6876d2f40d364cf1eadf2431)
ced1f5
---
ced1f5
 src/responder/common/negcache.c  | 155 +++++++++++++++++++++++++++++++++++++++
ced1f5
 src/responder/common/negcache.h  |  64 ++++++++++++++++
ced1f5
 src/tests/cmocka/test_negcache.c |  75 +++++++++++++++++++
ced1f5
 3 files changed, 294 insertions(+)
ced1f5
ced1f5
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
ced1f5
index b751d89ee9e67eea32ec4ed0935fcd67d3e92f47..bd3c9d36805adc5cca5621c815576ac21cfbec38 100644
ced1f5
--- a/src/responder/common/negcache.c
ced1f5
+++ b/src/responder/common/negcache.c
ced1f5
@@ -37,6 +37,8 @@
ced1f5
 #define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
ced1f5
 #define NC_SID_PREFIX NC_ENTRY_PREFIX"SID"
ced1f5
 #define NC_CERT_PREFIX NC_ENTRY_PREFIX"CERT"
ced1f5
+#define NC_DOMAIN_ACCT_LOCATE_PREFIX NC_ENTRY_PREFIX"DOM_LOCATE"
ced1f5
+#define NC_DOMAIN_ACCT_LOCATE_TYPE_PREFIX NC_ENTRY_PREFIX"DOM_LOCATE_TYPE"
ced1f5
 
ced1f5
 struct sss_nc_ctx {
ced1f5
     struct tdb_context *tdb;
ced1f5
@@ -665,6 +667,159 @@ int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
ced1f5
     return ret;
ced1f5
 }
ced1f5
 
ced1f5
+static char *domain_lookup_type_str(TALLOC_CTX *mem_ctx,
ced1f5
+                                    struct sss_domain_info *dom,
ced1f5
+                                    const char *lookup_type)
ced1f5
+{
ced1f5
+    return talloc_asprintf(mem_ctx,
ced1f5
+                           "%s/%s/%s",
ced1f5
+                           NC_DOMAIN_ACCT_LOCATE_TYPE_PREFIX,
ced1f5
+                           dom->name,
ced1f5
+                           lookup_type);
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_set_domain_locate_type(struct sss_nc_ctx *ctx,
ced1f5
+                                      struct sss_domain_info *dom,
ced1f5
+                                      const char *lookup_type)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    str = domain_lookup_type_str(ctx, dom, lookup_type);
ced1f5
+    if (!str) return ENOMEM;
ced1f5
+
ced1f5
+    /* Permanent cache is always used here, because whether the lookup
ced1f5
+     * type (getgrgid, getpwuid, ..) supports locating an entry's domain
ced1f5
+     * doesn't change
ced1f5
+     */
ced1f5
+    ret = sss_ncache_set_str(ctx, str, true, false);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_check_domain_locate_type(struct sss_nc_ctx *ctx,
ced1f5
+                                        struct sss_domain_info *dom,
ced1f5
+                                        const char *lookup_type)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    str = domain_lookup_type_str(ctx, dom, lookup_type);
ced1f5
+    if (!str) return ENOMEM;
ced1f5
+
ced1f5
+    ret = sss_ncache_check_str(ctx, str);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
+static char *locate_gid_str(TALLOC_CTX *mem_ctx,
ced1f5
+                            struct sss_domain_info *dom,
ced1f5
+                            gid_t gid)
ced1f5
+{
ced1f5
+    return talloc_asprintf(mem_ctx,
ced1f5
+                           "%s/%s/%s/%"SPRIgid,
ced1f5
+                           NC_DOMAIN_ACCT_LOCATE_PREFIX,
ced1f5
+                           NC_GID_PREFIX,
ced1f5
+                           dom->name,
ced1f5
+                           gid);
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_set_locate_gid(struct sss_nc_ctx *ctx,
ced1f5
+                              struct sss_domain_info *dom,
ced1f5
+                              gid_t gid)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    if (dom == NULL) {
ced1f5
+        return EINVAL;
ced1f5
+    }
ced1f5
+
ced1f5
+    str = locate_gid_str(ctx, dom, gid);
ced1f5
+    if (str == NULL) {
ced1f5
+        return ENOMEM;
ced1f5
+    }
ced1f5
+
ced1f5
+    ret = sss_ncache_set_str(ctx, str, false, false);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_check_locate_gid(struct sss_nc_ctx *ctx,
ced1f5
+                                struct sss_domain_info *dom,
ced1f5
+                                gid_t gid)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    if (dom == NULL) {
ced1f5
+        return EINVAL;
ced1f5
+    }
ced1f5
+
ced1f5
+    str = locate_gid_str(ctx, dom, gid);
ced1f5
+    if (str == NULL) {
ced1f5
+        return ENOMEM;
ced1f5
+    }
ced1f5
+
ced1f5
+    ret = sss_ncache_check_str(ctx, str);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
+static char *locate_uid_str(struct sss_nc_ctx *ctx,
ced1f5
+                            struct sss_domain_info *dom,
ced1f5
+                            uid_t uid)
ced1f5
+{
ced1f5
+    return talloc_asprintf(ctx,
ced1f5
+                           "%s/%s/%s/%"SPRIuid,
ced1f5
+                           NC_DOMAIN_ACCT_LOCATE_PREFIX,
ced1f5
+                           NC_UID_PREFIX,
ced1f5
+                           dom->name,
ced1f5
+                           uid);
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_set_locate_uid(struct sss_nc_ctx *ctx,
ced1f5
+                              struct sss_domain_info *dom,
ced1f5
+                              uid_t uid)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    if (dom == NULL) {
ced1f5
+        return EINVAL;
ced1f5
+    }
ced1f5
+
ced1f5
+    str = locate_uid_str(ctx, dom, uid);
ced1f5
+    if (str == NULL) {
ced1f5
+        return ENOMEM;
ced1f5
+    }
ced1f5
+
ced1f5
+    ret = sss_ncache_set_str(ctx, str, false, false);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
+int sss_ncache_check_locate_uid(struct sss_nc_ctx *ctx,
ced1f5
+                                struct sss_domain_info *dom,
ced1f5
+                                uid_t uid)
ced1f5
+{
ced1f5
+    char *str;
ced1f5
+    int ret;
ced1f5
+
ced1f5
+    if (dom == NULL) {
ced1f5
+        return EINVAL;
ced1f5
+    }
ced1f5
+
ced1f5
+    str = locate_uid_str(ctx, dom, uid);
ced1f5
+    if (str == NULL) {
ced1f5
+        return ENOMEM;
ced1f5
+    }
ced1f5
+
ced1f5
+    ret = sss_ncache_check_str(ctx, str);
ced1f5
+    talloc_free(str);
ced1f5
+    return ret;
ced1f5
+}
ced1f5
+
ced1f5
 static int delete_permanent(struct tdb_context *tdb,
ced1f5
                             TDB_DATA key, TDB_DATA data, void *state)
ced1f5
 {
ced1f5
diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h
ced1f5
index 782ec140fb7dfe3ec82bed8d25290c0f7b8a36ea..2ed38e5b9a64d3393513ea2110a7c6fcb7675623 100644
ced1f5
--- a/src/responder/common/negcache.h
ced1f5
+++ b/src/responder/common/negcache.h
ced1f5
@@ -80,6 +80,70 @@ int sss_ncache_set_service_name(struct sss_nc_ctx *ctx, bool permanent,
ced1f5
 int sss_ncache_set_service_port(struct sss_nc_ctx *ctx, bool permanent,
ced1f5
                                 struct sss_domain_info *dom,
ced1f5
                                 uint16_t port, const char *proto);
ced1f5
+/*
ced1f5
+ * Mark the lookup_type as not supporting the negative cache. This
ced1f5
+ * would be used by the corresponding checker to avoid needless
ced1f5
+ * subsequent calls to the locator for configurations that do not
ced1f5
+ * support the locator plugin.
ced1f5
+ *
ced1f5
+ * @param ctx   The negative cache
ced1f5
+ * @param dom   The top-level domain. It is expected that the caller
ced1f5
+ *              would use the top-level domain head here, because
ced1f5
+ *              this negative cache is "per-request-type" which is the
ced1f5
+ *              same for all subdomains of a domain
ced1f5
+ * @param lookup_type   Lookup type, e.g. getpwuid, getgrnam.
ced1f5
+ *
ced1f5
+ * @return EOK on success, errno on failure.
ced1f5
+ */
ced1f5
+int sss_ncache_set_domain_locate_type(struct sss_nc_ctx *ctx,
ced1f5
+                                      struct sss_domain_info *dom,
ced1f5
+                                      const char *lookup_type);
ced1f5
+/*
ced1f5
+ * Check if the lookup_type supports the domain locator request.
ced1f5
+ *
ced1f5
+ * @param ctx   The negative cache
ced1f5
+ * @param dom   The top-level domain. It is expected that the caller
ced1f5
+ *              would use the top-level domain head here, because
ced1f5
+ *              this negative cache is "per-request-type" which is the
ced1f5
+ *              same for all subdomains of a domain
ced1f5
+ * @param lookup_type   Lookup type, e.g. getpwuid, getgrnam.
ced1f5
+ *
ced1f5
+ * @return      ENOENT if the request supports the locator (or we
ced1f5
+ *              haven't checked yet), EEXIST if the request does
ced1f5
+ *              not support the domain locator request.
ced1f5
+ */
ced1f5
+int sss_ncache_check_domain_locate_type(struct sss_nc_ctx *ctx,
ced1f5
+                                        struct sss_domain_info *dom,
ced1f5
+                                        const char *key);
ced1f5
+
ced1f5
+/*
ced1f5
+ * Call these two functions to mark a GID as checked until the negative
ced1f5
+ * cache expires. This function is used to avoid a situation where
ced1f5
+ * GID would be found in a subsequent domain, so any request that
ced1f5
+ * searches for this GID again (even if it was cached) would first
ced1f5
+ * run the locator again.
ced1f5
+ *
ced1f5
+ * While this negative cache entry is valid, it is expected that
ced1f5
+ * the negatively cached entries in the domain's GID negative
ced1f5
+ * cache (if any) are valid
ced1f5
+ *
ced1f5
+ * The sss_ncache_set_locate_gid() is called by the locator request
ced1f5
+ * when it finishes, the sss_ncache_check_locate_gid() is called
ced1f5
+ * by the caller of the locator request to find if the locator
ced1f5
+ * should be called at all.
ced1f5
+ */
ced1f5
+int sss_ncache_set_locate_gid(struct sss_nc_ctx *ctx,
ced1f5
+                              struct sss_domain_info *dom,
ced1f5
+                              gid_t gid);
ced1f5
+int sss_ncache_check_locate_gid(struct sss_nc_ctx *ctx,
ced1f5
+                                struct sss_domain_info *dom,
ced1f5
+                                gid_t gid);
ced1f5
+int sss_ncache_check_locate_uid(struct sss_nc_ctx *ctx,
ced1f5
+                                struct sss_domain_info *dom,
ced1f5
+                                uid_t uid);
ced1f5
+int sss_ncache_set_locate_uid(struct sss_nc_ctx *ctx,
ced1f5
+                              struct sss_domain_info *dom,
ced1f5
+                              uid_t uid);
ced1f5
 
ced1f5
 int sss_ncache_reset_permanent(struct sss_nc_ctx *ctx);
ced1f5
 int sss_ncache_reset_users(struct sss_nc_ctx *ctx);
ced1f5
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
ced1f5
index ba39f778d5ddc6a4e1708aef66fc2aa1c809f150..a0210928bd60e364c60717c8b37b2405730f34ab 100644
ced1f5
--- a/src/tests/cmocka/test_negcache.c
ced1f5
+++ b/src/tests/cmocka/test_negcache.c
ced1f5
@@ -883,6 +883,77 @@ static void test_sss_ncache_reset(void **state)
ced1f5
     assert_int_equal(ret, ENOENT);
ced1f5
 }
ced1f5
 
ced1f5
+static void test_sss_ncache_locate_uid_gid(void **state)
ced1f5
+{
ced1f5
+    uid_t uid;
ced1f5
+    gid_t gid;
ced1f5
+    int ret;
ced1f5
+    struct test_state *ts;
ced1f5
+    struct sss_domain_info *dom;
ced1f5
+    struct sss_domain_info *dom2;
ced1f5
+
ced1f5
+    ts = talloc_get_type_abort(*state, struct test_state);
ced1f5
+
ced1f5
+    uid = getuid();
ced1f5
+    gid = getgid();
ced1f5
+
ced1f5
+    dom = talloc(ts, struct sss_domain_info);
ced1f5
+    assert_non_null(dom);
ced1f5
+    dom->name = discard_const_p(char, TEST_DOM_NAME);
ced1f5
+
ced1f5
+    dom2 = talloc(ts, struct sss_domain_info);
ced1f5
+    assert_non_null(dom2);
ced1f5
+    dom2->name = discard_const_p(char, TEST_DOM_NAME"2");
ced1f5
+
ced1f5
+    ret = sss_ncache_check_locate_gid(ts->ctx, dom, gid);
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+    ret = sss_ncache_check_locate_uid(ts->ctx, dom, uid);
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+
ced1f5
+    ret = sss_ncache_set_locate_gid(ts->ctx, dom, gid);
ced1f5
+    assert_int_equal(ret, EOK);
ced1f5
+    ret = sss_ncache_set_locate_uid(ts->ctx, dom, uid);
ced1f5
+    assert_int_equal(ret, EOK);
ced1f5
+
ced1f5
+    ret = sss_ncache_check_locate_gid(ts->ctx, dom, gid);
ced1f5
+    assert_int_equal(ret, EEXIST);
ced1f5
+    ret = sss_ncache_check_locate_uid(ts->ctx, dom, uid);
ced1f5
+    assert_int_equal(ret, EEXIST);
ced1f5
+
ced1f5
+    ret = sss_ncache_check_locate_gid(ts->ctx, dom2, gid);
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+    ret = sss_ncache_check_locate_uid(ts->ctx, dom2, uid);
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+}
ced1f5
+
ced1f5
+static void test_sss_ncache_domain_locate_type(void **state)
ced1f5
+{
ced1f5
+    int ret;
ced1f5
+    struct test_state *ts;
ced1f5
+    struct sss_domain_info *dom;
ced1f5
+    struct sss_domain_info *dom2;
ced1f5
+
ced1f5
+    ts = talloc_get_type_abort(*state, struct test_state);
ced1f5
+
ced1f5
+    dom = talloc(ts, struct sss_domain_info);
ced1f5
+    assert_non_null(dom);
ced1f5
+    dom->name = discard_const_p(char, TEST_DOM_NAME);
ced1f5
+
ced1f5
+    dom2 = talloc(ts, struct sss_domain_info);
ced1f5
+    assert_non_null(dom2);
ced1f5
+    dom2->name = discard_const_p(char, TEST_DOM_NAME"2");
ced1f5
+
ced1f5
+    ret = sss_ncache_check_domain_locate_type(ts->ctx, dom, "foo");
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+    ret = sss_ncache_set_domain_locate_type(ts->ctx, dom, "foo");
ced1f5
+    assert_int_equal(ret, EOK);
ced1f5
+    ret = sss_ncache_check_domain_locate_type(ts->ctx, dom, "foo");
ced1f5
+    assert_int_equal(ret, EEXIST);
ced1f5
+
ced1f5
+    ret = sss_ncache_check_domain_locate_type(ts->ctx, dom2, "foo");
ced1f5
+    assert_int_equal(ret, ENOENT);
ced1f5
+}
ced1f5
+
ced1f5
 int main(void)
ced1f5
 {
ced1f5
     int rv;
ced1f5
@@ -909,6 +980,10 @@ int main(void)
ced1f5
                                         setup, teardown),
ced1f5
         cmocka_unit_test_setup_teardown(test_sss_ncache_reset,
ced1f5
                                         setup, teardown),
ced1f5
+        cmocka_unit_test_setup_teardown(test_sss_ncache_locate_uid_gid,
ced1f5
+                                        setup, teardown),
ced1f5
+        cmocka_unit_test_setup_teardown(test_sss_ncache_domain_locate_type,
ced1f5
+                                        setup, teardown),
ced1f5
     };
ced1f5
 
ced1f5
     tests_set_cwd();
ced1f5
-- 
ced1f5
2.14.3
ced1f5