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

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