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

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