Blame SOURCES/0007-sdap_get_users_send-new-argument-mapped_attrs.patch

ecf709
From af96fbe97576133ca6077c47f39b812e7e289040 Mon Sep 17 00:00:00 2001
ecf709
From: Sumit Bose <sbose@redhat.com>
ecf709
Date: Sun, 12 Mar 2017 18:31:03 +0100
ecf709
Subject: [PATCH 07/15] sdap_get_users_send(): new argument mapped_attrs
ecf709
MIME-Version: 1.0
ecf709
Content-Type: text/plain; charset=UTF-8
ecf709
Content-Transfer-Encoding: 8bit
ecf709
ecf709
mapped_attrs can be a list of sysdb_attrs which are not available on
ecf709
the server side but should be store with the cached user entry. This is
ecf709
needed e.g. when the input to look up the user in LDAP is not an
ecf709
attribute which is stored in LDAP but some data where LDAP attributes
ecf709
are extracted from. The current use case is the certificate mapping
ecf709
library which can create LDAP search filters based on content of the
ecf709
certificate. To allow upcoming cache lookup to use the input directly it
ecf709
is stored in the user object in the cache.
ecf709
ecf709
Related to https://pagure.io/SSSD/sssd/issue/3050
ecf709
ecf709
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
ecf709
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
ecf709
---
ecf709
 src/db/sysdb.h                             |  3 ++
ecf709
 src/db/sysdb_ops.c                         | 61 ++++++++++++++++++++++++++++++
ecf709
 src/providers/ldap/ldap_id.c               |  4 +-
ecf709
 src/providers/ldap/sdap_async.h            |  3 +-
ecf709
 src/providers/ldap/sdap_async_enum.c       |  2 +-
ecf709
 src/providers/ldap/sdap_async_initgroups.c |  2 +-
ecf709
 src/providers/ldap/sdap_async_private.h    |  1 +
ecf709
 src/providers/ldap/sdap_async_users.c      | 41 +++++++++++++++++++-
ecf709
 src/providers/ldap/sdap_users.h            |  1 +
ecf709
 9 files changed, 111 insertions(+), 7 deletions(-)
ecf709
ecf709
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
ecf709
index c677957bb639e40db2f985205160612094302e78..098f47f91187aac75c58c02f0af738c344765762 100644
ecf709
--- a/src/db/sysdb.h
ecf709
+++ b/src/db/sysdb.h
ecf709
@@ -1246,6 +1246,9 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx,
ecf709
 errno_t sysdb_remove_cert(struct sss_domain_info *domain,
ecf709
                           const char *cert);
ecf709
 
ecf709
+errno_t sysdb_remove_mapped_data(struct sss_domain_info *domain,
ecf709
+                                 struct sysdb_attrs *mapped_attr);
ecf709
+
ecf709
 /* === Functions related to GPOs === */
ecf709
 
ecf709
 #define SYSDB_GPO_CONTAINER "cn=gpos,cn=ad,cn=custom"
ecf709
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
ecf709
index 242d3ce3bb795691e329790a07c3493672e8f523..6c2254df2b75d3d3419528523103ad9cddb40c9d 100644
ecf709
--- a/src/db/sysdb_ops.c
ecf709
+++ b/src/db/sysdb_ops.c
ecf709
@@ -4685,6 +4685,67 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx,
ecf709
     return sysdb_search_object_by_cert(mem_ctx, domain, cert, user_attrs, res);
ecf709
 }
ecf709
 
ecf709
+errno_t sysdb_remove_mapped_data(struct sss_domain_info *domain,
ecf709
+                                 struct sysdb_attrs *mapped_attr)
ecf709
+{
ecf709
+    int ret;
ecf709
+    char *val;
ecf709
+    char *filter;
ecf709
+    const char *attrs[] = {SYSDB_NAME, NULL};
ecf709
+    struct ldb_result *res = NULL;
ecf709
+    size_t c;
ecf709
+    bool all_ok = true;
ecf709
+
ecf709
+    if (mapped_attr->num != 1 || mapped_attr->a[0].num_values != 1) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "Unsupported number of attributes.\n");
ecf709
+        return EINVAL;
ecf709
+    }
ecf709
+
ecf709
+    ret = bin_to_ldap_filter_value(NULL, mapped_attr->a[0].values[0].data,
ecf709
+                                   mapped_attr->a[0].values[0].length, &val;;
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "bin_to_ldap_filter_value failed.\n");
ecf709
+        return ret;
ecf709
+    }
ecf709
+
ecf709
+    filter = talloc_asprintf(NULL, "(&("SYSDB_UC")(%s=%s))",
ecf709
+                             mapped_attr->a[0].name, val);
ecf709
+    talloc_free(val);
ecf709
+    if (filter == NULL) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
ecf709
+        return ENOMEM;
ecf709
+    }
ecf709
+
ecf709
+    ret = sysdb_search_object_attr(NULL, domain, filter, attrs, false, &res;;
ecf709
+    talloc_free(filter);
ecf709
+    if (ret == ENOENT || res == NULL) {
ecf709
+        DEBUG(SSSDBG_TRACE_ALL, "Mapped data not found.\n");
ecf709
+        talloc_free(res);
ecf709
+        return EOK;
ecf709
+    } else if (ret != EOK) {
ecf709
+        talloc_free(res);
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_object_attr failed.\n");
ecf709
+        return ret;
ecf709
+    }
ecf709
+
ecf709
+    for (c = 0; c < res->count; c++) {
ecf709
+        DEBUG(SSSDBG_TRACE_ALL, "Removing mapped data from [%s].\n",
ecf709
+                                ldb_dn_get_linearized(res->msgs[c]->dn));
ecf709
+        /* The timestamp cache is skipped on purpose here. */
ecf709
+        ret = sysdb_set_cache_entry_attr(domain->sysdb->ldb, res->msgs[c]->dn,
ecf709
+                                         mapped_attr, SYSDB_MOD_DEL);
ecf709
+        if (ret != EOK) {
ecf709
+            all_ok = false;
ecf709
+            DEBUG(SSSDBG_OP_FAILURE,
ecf709
+                  "Failed to remove mapped data from [%s], skipping.\n",
ecf709
+                  ldb_dn_get_linearized(res->msgs[c]->dn));
ecf709
+        }
ecf709
+    }
ecf709
+    talloc_free(res);
ecf709
+
ecf709
+    return (all_ok ? EOK : EIO);
ecf709
+}
ecf709
+
ecf709
 errno_t sysdb_remove_cert(struct sss_domain_info *domain,
ecf709
                           const char *cert)
ecf709
 {
ecf709
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
ecf709
index e9455b538daa2d65d944dbb68022a2773623d7b7..898ddb18689d55fcc3fdf021b38df0e574003eb2 100644
ecf709
--- a/src/providers/ldap/ldap_id.c
ecf709
+++ b/src/providers/ldap/ldap_id.c
ecf709
@@ -442,7 +442,7 @@ static void users_get_search(struct tevent_req *req)
ecf709
                                  state->attrs, state->filter,
ecf709
                                  dp_opt_get_int(state->ctx->opts->basic,
ecf709
                                                 SDAP_SEARCH_TIMEOUT),
ecf709
-                                 lookup_type);
ecf709
+                                 lookup_type, NULL);
ecf709
     if (!subreq) {
ecf709
         tevent_req_error(req, ENOMEM);
ecf709
         return;
ecf709
@@ -507,7 +507,7 @@ static void users_get_done(struct tevent_req *subreq)
ecf709
             ret = sdap_fallback_local_user(state, state->shortname, uid, &usr_attrs);
ecf709
             if (ret == EOK) {
ecf709
                 ret = sdap_save_user(state, state->ctx->opts, state->domain,
ecf709
-                                     usr_attrs[0], NULL, 0);
ecf709
+                                     usr_attrs[0], NULL, NULL, 0);
ecf709
             }
ecf709
         }
ecf709
     }
ecf709
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
ecf709
index 2ebde6b83646408e446c91cb324809cb767b2617..6e5800b42ba4a045fa7985b09a80b6b86b8c6055 100644
ecf709
--- a/src/providers/ldap/sdap_async.h
ecf709
+++ b/src/providers/ldap/sdap_async.h
ecf709
@@ -90,7 +90,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
ecf709
                                        const char **attrs,
ecf709
                                        const char *filter,
ecf709
                                        int timeout,
ecf709
-                                       enum sdap_entry_lookup_type lookup_type);
ecf709
+                                       enum sdap_entry_lookup_type lookup_type,
ecf709
+                                       struct sysdb_attrs *mapped_attrs);
ecf709
 int sdap_get_users_recv(struct tevent_req *req,
ecf709
                         TALLOC_CTX *mem_ctx, char **timestamp);
ecf709
 
ecf709
diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
ecf709
index 387e53155b567ce106cc68009c7cb99e27d24a17..3f65059e18d5c8b548da0babec867d27c3a64198 100644
ecf709
--- a/src/providers/ldap/sdap_async_enum.c
ecf709
+++ b/src/providers/ldap/sdap_async_enum.c
ecf709
@@ -635,7 +635,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
ecf709
                                  state->attrs, state->filter,
ecf709
                                  dp_opt_get_int(state->ctx->opts->basic,
ecf709
                                                 SDAP_ENUM_SEARCH_TIMEOUT),
ecf709
-                                 SDAP_LOOKUP_ENUMERATE);
ecf709
+                                 SDAP_LOOKUP_ENUMERATE, NULL);
ecf709
     if (!subreq) {
ecf709
         ret = ENOMEM;
ecf709
         goto fail;
ecf709
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
ecf709
index 8c7a65bf36abf341e077cf9eac18a234d3a07c07..79af7a3eda3fe8533933535c98c2b4b4698dfda2 100644
ecf709
--- a/src/providers/ldap/sdap_async_initgroups.c
ecf709
+++ b/src/providers/ldap/sdap_async_initgroups.c
ecf709
@@ -2991,7 +2991,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
ecf709
     DEBUG(SSSDBG_TRACE_ALL, "Storing the user\n");
ecf709
 
ecf709
     ret = sdap_save_user(state, state->opts, state->dom, state->orig_user,
ecf709
-                         NULL, 0);
ecf709
+                         NULL, NULL, 0);
ecf709
     if (ret) {
ecf709
         goto fail;
ecf709
     }
ecf709
diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
ecf709
index 266bc03115e2bdd6a283f5f7da565fd00d3a77be..72507442a9ffd5c0e24ccbd95d75d3ebf9bf0940 100644
ecf709
--- a/src/providers/ldap/sdap_async_private.h
ecf709
+++ b/src/providers/ldap/sdap_async_private.h
ecf709
@@ -94,6 +94,7 @@ int sdap_save_users(TALLOC_CTX *memctx,
ecf709
                     struct sdap_options *opts,
ecf709
                     struct sysdb_attrs **users,
ecf709
                     int num_users,
ecf709
+                    struct sysdb_attrs *mapped_attrs,
ecf709
                     char **_usn_value);
ecf709
 
ecf709
 int sdap_initgr_common_store(struct sysdb_ctx *sysdb,
ecf709
diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
ecf709
index 87d91d8247c37a4c6a1d83b7189399056528fc90..3d957ab584865f74499bc732395388a78965fe5f 100644
ecf709
--- a/src/providers/ldap/sdap_async_users.c
ecf709
+++ b/src/providers/ldap/sdap_async_users.c
ecf709
@@ -117,6 +117,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
ecf709
                    struct sdap_options *opts,
ecf709
                    struct sss_domain_info *dom,
ecf709
                    struct sysdb_attrs *attrs,
ecf709
+                   struct sysdb_attrs *mapped_attrs,
ecf709
                    char **_usn_value,
ecf709
                    time_t now)
ecf709
 {
ecf709
@@ -511,6 +512,11 @@ int sdap_save_user(TALLOC_CTX *memctx,
ecf709
                            user_attrs, missing, cache_timeout, now);
ecf709
     if (ret) goto done;
ecf709
 
ecf709
+    if (mapped_attrs != NULL) {
ecf709
+        ret = sysdb_set_user_attr(dom, user_name, mapped_attrs, SYSDB_MOD_ADD);
ecf709
+        if (ret) return ret;
ecf709
+    }
ecf709
+
ecf709
     if (_usn_value) {
ecf709
         *_usn_value = talloc_steal(memctx, usn_value);
ecf709
     }
ecf709
@@ -537,6 +543,7 @@ int sdap_save_users(TALLOC_CTX *memctx,
ecf709
                     struct sdap_options *opts,
ecf709
                     struct sysdb_attrs **users,
ecf709
                     int num_users,
ecf709
+                    struct sysdb_attrs *mapped_attrs,
ecf709
                     char **_usn_value)
ecf709
 {
ecf709
     TALLOC_CTX *tmpctx;
ecf709
@@ -565,11 +572,20 @@ int sdap_save_users(TALLOC_CTX *memctx,
ecf709
     }
ecf709
     in_transaction = true;
ecf709
 
ecf709
+    if (mapped_attrs != NULL) {
ecf709
+        ret = sysdb_remove_mapped_data(dom, mapped_attrs);
ecf709
+        if (ret != EOK) {
ecf709
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_remove_mapped_data failed, "
ecf709
+                  "some cached entries might contain invalid mapping data.\n");
ecf709
+        }
ecf709
+    }
ecf709
+
ecf709
     now = time(NULL);
ecf709
     for (i = 0; i < num_users; i++) {
ecf709
         usn_value = NULL;
ecf709
 
ecf709
-        ret = sdap_save_user(tmpctx, opts, dom, users[i], &usn_value, now);
ecf709
+        ret = sdap_save_user(tmpctx, opts, dom, users[i], mapped_attrs,
ecf709
+                             &usn_value, now);
ecf709
 
ecf709
         /* Do not fail completely on errors.
ecf709
          * Just report the failure to save and go on */
ecf709
@@ -868,6 +884,7 @@ struct sdap_get_users_state {
ecf709
 
ecf709
     char *higher_usn;
ecf709
     struct sysdb_attrs **users;
ecf709
+    struct sysdb_attrs *mapped_attrs;
ecf709
     size_t count;
ecf709
 };
ecf709
 
ecf709
@@ -883,7 +900,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
ecf709
                                        const char **attrs,
ecf709
                                        const char *filter,
ecf709
                                        int timeout,
ecf709
-                                       enum sdap_entry_lookup_type lookup_type)
ecf709
+                                       enum sdap_entry_lookup_type lookup_type,
ecf709
+                                       struct sysdb_attrs *mapped_attrs)
ecf709
 {
ecf709
     errno_t ret;
ecf709
     struct tevent_req *req;
ecf709
@@ -900,6 +918,23 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
ecf709
     state->filter = filter;
ecf709
     PROBE(SDAP_SEARCH_USER_SEND, state->filter);
ecf709
 
ecf709
+    if (mapped_attrs == NULL) {
ecf709
+        state->mapped_attrs = NULL;
ecf709
+    } else {
ecf709
+        state->mapped_attrs = sysdb_new_attrs(state);
ecf709
+        if (state->mapped_attrs == NULL) {
ecf709
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
ecf709
+            ret = ENOMEM;
ecf709
+            goto done;
ecf709
+        }
ecf709
+
ecf709
+        ret = sysdb_attrs_copy(mapped_attrs, state->mapped_attrs);
ecf709
+        if (ret != EOK) {
ecf709
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_copy failed.\n");
ecf709
+            goto done;
ecf709
+        }
ecf709
+    }
ecf709
+
ecf709
     subreq = sdap_search_user_send(state, ev, dom, opts, search_bases,
ecf709
                                    sh, attrs, filter, timeout, lookup_type);
ecf709
     if (subreq == NULL) {
ecf709
@@ -938,9 +973,11 @@ static void sdap_get_users_done(struct tevent_req *subreq)
ecf709
     }
ecf709
 
ecf709
     PROBE(SDAP_SEARCH_USER_SAVE_BEGIN, state->filter);
ecf709
+
ecf709
     ret = sdap_save_users(state, state->sysdb,
ecf709
                           state->dom, state->opts,
ecf709
                           state->users, state->count,
ecf709
+                          state->mapped_attrs,
ecf709
                           &state->higher_usn);
ecf709
     PROBE(SDAP_SEARCH_USER_SAVE_END, state->filter);
ecf709
     if (ret) {
ecf709
diff --git a/src/providers/ldap/sdap_users.h b/src/providers/ldap/sdap_users.h
ecf709
index 78dafb31a2a07e7289055daec77c5dc5da1bdeef..a6d088a6d7114db75b0f0ea22ef85c57da6fab0f 100644
ecf709
--- a/src/providers/ldap/sdap_users.h
ecf709
+++ b/src/providers/ldap/sdap_users.h
ecf709
@@ -34,6 +34,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
ecf709
                    struct sdap_options *opts,
ecf709
                    struct sss_domain_info *dom,
ecf709
                    struct sysdb_attrs *attrs,
ecf709
+                   struct sysdb_attrs *mapped_attrs,
ecf709
                    char **_usn_value,
ecf709
                    time_t now);
ecf709
 
ecf709
-- 
ecf709
2.9.3
ecf709