summaryrefslogtreecommitdiffstats
path: root/src/db
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2016-05-18 14:30:28 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-06-23 13:40:11 +0200
commitdd285415d7a8d8376207960cfa3e977524c3b98c (patch)
tree38d848dcdc43045ef5d781665b0a28bf85bffd7b /src/db
parent13d7df10bf4d76c333a9169f9fcbeb891d870351 (diff)
downloadsssd-dd285415d7a8d8376207960cfa3e977524c3b98c.tar.gz
sssd-dd285415d7a8d8376207960cfa3e977524c3b98c.tar.xz
sssd-dd285415d7a8d8376207960cfa3e977524c3b98c.zip
SYSDB: Search the timestamp caches in addition to the sysdb cache
When a sysdb entry is searched, the sysdb cache is consulted first for users or groups. If an entry is found in the sysdb cache, the attributes from the timestamp cache are merged to return the full and up-to-date set of attributes. The merging is done with a single BASE search which is a direct lookup into the underlying key-value database, so it should be relatively fast. More complex merging is done only for enumeration by filter which is currently done only via the IFP back end and should be quite infrequent, so I hope we can justify a more complex merging there. Reviewed-by: Sumit Bose <sbose@redhat.com>
Diffstat (limited to 'src/db')
-rw-r--r--src/db/sysdb.c32
-rw-r--r--src/db/sysdb.h1
-rw-r--r--src/db/sysdb_ops.c189
-rw-r--r--src/db/sysdb_private.h56
-rw-r--r--src/db/sysdb_search.c394
5 files changed, 640 insertions, 32 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index fcdea0e01..81b731a0d 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1683,3 +1683,35 @@ int sysdb_delete_ulong(struct ldb_message *msg,
{
return sysdb_ldb_msg_ulong_helper(msg, LDB_FLAG_MOD_DELETE, attr, value);
}
+
+bool is_ts_ldb_dn(struct ldb_dn *dn)
+{
+ const char *sysdb_comp_name = NULL;
+ const struct ldb_val *sysdb_comp_val = NULL;
+
+ if (dn == NULL) {
+ return false;
+ }
+
+ sysdb_comp_name = ldb_dn_get_component_name(dn, 1);
+ if (strcasecmp("cn", sysdb_comp_name) != 0) {
+ /* The second component name is not "cn" */
+ return false;
+ }
+
+ sysdb_comp_val = ldb_dn_get_component_val(dn, 1);
+ if (strncasecmp("users",
+ (const char *) sysdb_comp_val->data,
+ sysdb_comp_val->length) == 0) {
+ return true;
+ }
+
+ sysdb_comp_val = ldb_dn_get_component_val(dn, 1);
+ if (strncasecmp("groups",
+ (const char *) sysdb_comp_val->data,
+ sysdb_comp_val->length) == 0) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index e343de20c..4f69b6372 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -59,6 +59,7 @@
#define SYSDB_DOMAIN_ID_RANGE_CLASS "domainIDRange"
#define SYSDB_TRUSTED_AD_DOMAIN_RANGE_CLASS "TrustedADDomainRange"
+#define SYSDB_DN "dn"
#define SYSDB_NAME "name"
#define SYSDB_NAME_ALIAS "nameAlias"
#define SYSDB_OBJECTCLASS "objectClass"
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 79d7eef9e..2f06444e7 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -186,14 +186,14 @@ done:
/* =Search-Entry========================================================== */
-int sysdb_search_entry(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- struct ldb_dn *base_dn,
- enum ldb_scope scope,
- const char *filter,
- const char **attrs,
- size_t *_msgs_count,
- struct ldb_message ***_msgs)
+static int sysdb_cache_search_entry(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb,
+ struct ldb_dn *base_dn,
+ enum ldb_scope scope,
+ const char *filter,
+ const char **attrs,
+ size_t *_msgs_count,
+ struct ldb_message ***_msgs)
{
TALLOC_CTX *tmp_ctx;
struct ldb_result *res;
@@ -205,7 +205,7 @@ int sysdb_search_entry(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
+ ret = ldb_search(ldb, tmp_ctx, &res,
base_dn, scope, attrs,
filter?"%s":NULL, filter);
if (ret != EOK) {
@@ -226,6 +226,51 @@ done:
return ret;
}
+int sysdb_search_entry(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ struct ldb_dn *base_dn,
+ enum ldb_scope scope,
+ const char *filter,
+ const char **attrs,
+ size_t *_msgs_count,
+ struct ldb_message ***_msgs)
+{
+ errno_t ret;
+
+ ret = sysdb_cache_search_entry(mem_ctx, sysdb->ldb, base_dn, scope,
+ filter, attrs, _msgs_count, _msgs);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return sysdb_merge_msg_list_ts_attrs(sysdb, *_msgs_count, *_msgs,
+ attrs);
+}
+
+int sysdb_search_ts_entry(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ struct ldb_dn *base_dn,
+ enum ldb_scope scope,
+ const char *filter,
+ const char **attrs,
+ size_t *_msgs_count,
+ struct ldb_message ***_msgs)
+{
+ if (sysdb->ldb_ts == NULL) {
+ if (_msgs_count != NULL) {
+ *_msgs_count = 0;
+ }
+ if (_msgs != NULL) {
+ *_msgs = NULL;
+ }
+
+ return EOK;
+ }
+
+ return sysdb_cache_search_entry(mem_ctx, sysdb->ldb_ts, base_dn, scope,
+ filter, attrs, _msgs_count, _msgs);
+}
+
/* =Search-Entry-by-SID-string============================================ */
int sysdb_search_entry_by_sid_str(TALLOC_CTX *mem_ctx,
@@ -357,6 +402,11 @@ static int sysdb_search_by_name(TALLOC_CTX *mem_ctx,
goto done;
}
+ ret = sysdb_merge_msg_list_ts_attrs(domain->sysdb, msgs_count, msgs, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot retrieve timestamp attributes\n");
+ }
+
*msg = talloc_steal(mem_ctx, msgs[0]);
done:
@@ -493,6 +543,14 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res,
+ attrs ? attrs : def_attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*out_res = talloc_steal(mem_ctx, res);
ret = EOK;
@@ -2707,12 +2765,13 @@ fail:
/* =Search-Users-with-Custom-Filter====================================== */
-int sysdb_search_users(TALLOC_CTX *mem_ctx,
- struct sss_domain_info *domain,
- const char *sub_filter,
- const char **attrs,
- size_t *msgs_count,
- struct ldb_message ***msgs)
+static int sysdb_cache_search_users(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ struct ldb_context *ldb,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
{
TALLOC_CTX *tmp_ctx;
struct ldb_dn *basedn;
@@ -2741,9 +2800,9 @@ int sysdb_search_users(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_INTERNAL,
"Search users with filter: %s\n", filter);
- ret = sysdb_search_entry(mem_ctx, domain->sysdb, basedn,
- LDB_SCOPE_SUBTREE, filter, attrs,
- msgs_count, msgs);
+ ret = sysdb_cache_search_entry(mem_ctx, ldb, basedn,
+ LDB_SCOPE_SUBTREE, filter, attrs,
+ msgs_count, msgs);
if (ret) {
goto fail;
}
@@ -2762,6 +2821,40 @@ fail:
return ret;
}
+int sysdb_search_users(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
+{
+ errno_t ret;
+
+ ret = sysdb_cache_search_users(mem_ctx, domain, domain->sysdb->ldb,
+ sub_filter, attrs, msgs_count, msgs);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return sysdb_merge_msg_list_ts_attrs(domain->sysdb, *msgs_count, *msgs,
+ attrs);
+}
+
+int sysdb_search_ts_users(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
+{
+ if (domain->sysdb->ldb_ts == NULL) {
+ return ENOENT;
+ }
+
+ return sysdb_cache_search_users(mem_ctx, domain, domain->sysdb->ldb_ts,
+ sub_filter, attrs, msgs_count, msgs);
+}
+
/* =Delete-User-by-Name-OR-uid============================================ */
int sysdb_delete_user(struct sss_domain_info *domain,
@@ -2874,12 +2967,13 @@ fail:
/* =Search-Groups-with-Custom-Filter===================================== */
-int sysdb_search_groups(TALLOC_CTX *mem_ctx,
- struct sss_domain_info *domain,
- const char *sub_filter,
- const char **attrs,
- size_t *msgs_count,
- struct ldb_message ***msgs)
+static int sysdb_cache_search_groups(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ struct ldb_context *ldb,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
{
TALLOC_CTX *tmp_ctx;
struct ldb_dn *basedn;
@@ -2908,9 +3002,9 @@ int sysdb_search_groups(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_INTERNAL,
"Search groups with filter: %s\n", filter);
- ret = sysdb_search_entry(mem_ctx, domain->sysdb, basedn,
- LDB_SCOPE_SUBTREE, filter, attrs,
- msgs_count, msgs);
+ ret = sysdb_cache_search_entry(mem_ctx, ldb, basedn,
+ LDB_SCOPE_SUBTREE, filter, attrs,
+ msgs_count, msgs);
if (ret) {
goto fail;
}
@@ -2929,6 +3023,40 @@ fail:
return ret;
}
+int sysdb_search_groups(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
+{
+ errno_t ret;
+
+ ret = sysdb_cache_search_groups(mem_ctx, domain, domain->sysdb->ldb,
+ sub_filter, attrs, msgs_count, msgs);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return sysdb_merge_msg_list_ts_attrs(domain->sysdb, *msgs_count, *msgs,
+ attrs);
+}
+
+int sysdb_search_ts_groups(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs)
+{
+ if (domain->sysdb->ldb_ts == NULL) {
+ return ENOENT;
+ }
+
+ return sysdb_cache_search_groups(mem_ctx, domain, domain->sysdb->ldb_ts,
+ sub_filter, attrs, msgs_count, msgs);
+}
+
/* =Delete-Group-by-Name-OR-gid=========================================== */
int sysdb_delete_group(struct sss_domain_info *domain,
@@ -3730,6 +3858,13 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
index 828863df7..dae348b0b 100644
--- a/src/db/sysdb_private.h
+++ b/src/db/sysdb_private.h
@@ -183,4 +183,60 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
const char *forest,
uint32_t trust_direction);
+/* Helper functions to deal with the timestamp cache should not be used
+ * outside the sysdb itself. The timestamp cache should be completely
+ * opaque to the sysdb consumers
+ */
+
+/* Returns true if the 'dn' parameter is a user or a group DN, because
+ * at the moment, the timestamps cache only handles users and groups.
+ * Returns false otherwise.
+ */
+bool is_ts_ldb_dn(struct ldb_dn *dn);
+
+/* Given a ldb_result found in the timestamp cache, merge in the
+ * corresponding full attributes from the sysdb cache. The new
+ * attributes are allocated on the messages in the ldb_result.
+ */
+errno_t sysdb_merge_res_ts_attrs(struct sysdb_ctx *ctx,
+ struct ldb_result *res,
+ const char *attrs[]);
+
+/* Given an array of ldb_message structures found in the timestamp cache,
+ * merge in the corresponding full attributes from the sysdb cache. The
+ * new attributes are allocated atop the ldb messages.
+ */
+errno_t sysdb_merge_msg_list_ts_attrs(struct sysdb_ctx *ctx,
+ size_t msgs_count,
+ struct ldb_message **msgs,
+ const char *attrs[]);
+
+/* Merge two sets of ldb_result structures. */
+struct ldb_result *sss_merge_ldb_results(struct ldb_result *res,
+ struct ldb_result *subres);
+
+/* Search Entry in the timestamp cache */
+int sysdb_search_ts_entry(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ struct ldb_dn *base_dn,
+ enum ldb_scope scope,
+ const char *filter,
+ const char **attrs,
+ size_t *_msgs_count,
+ struct ldb_message ***_msgs);
+
+int sysdb_search_ts_users(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs);
+
+int sysdb_search_ts_groups(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *sub_filter,
+ const char **attrs,
+ size_t *msgs_count,
+ struct ldb_message ***msgs);
+
#endif /* __INT_SYS_DB_H__ */
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index e9c384046..9a1ae7a9f 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -25,6 +25,158 @@
#include <time.h>
#include <ctype.h>
+/* helpers */
+static errno_t merge_ts_attr(struct ldb_message *ts_msg,
+ struct ldb_message *sysdb_msg,
+ const char *ts_attr,
+ const char *want_attrs[])
+{
+ errno_t ret;
+ bool include = true;
+ struct ldb_message_element *ts_el;
+ struct ldb_message_element *sysdb_el;
+
+ if (want_attrs != NULL) {
+ /* Otherwise merge all ts attrs */
+ include = string_in_list(ts_attr, discard_const(want_attrs), true);
+ }
+ if (include == false) {
+ return EOK;
+ }
+
+ ts_el = ldb_msg_find_element(ts_msg, ts_attr);
+ if (ts_el == NULL || ts_el->num_values == 0) {
+ return EOK;
+ }
+
+ if (ts_el->num_values > 1) {
+ return EIO;
+ }
+
+ sysdb_el = ldb_msg_find_element(sysdb_msg, ts_attr);
+ if (sysdb_el == NULL || sysdb_el->num_values == 0) {
+ ret = ldb_msg_add_steal_value(sysdb_msg, ts_attr, &ts_el->values[0]);
+ if (ret != EOK) {
+ return sysdb_error_to_errno(ret);
+ }
+ } else {
+ /* Assumes the timestamps cache only holds single-valued
+ * attributes */
+ sysdb_el->values = talloc_steal(sysdb_el->values, ts_el->values);
+ }
+
+ return EOK;
+}
+
+static errno_t merge_msg_ts_attrs(struct sysdb_ctx *sysdb,
+ struct ldb_message *sysdb_msg,
+ const char *attrs[])
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ size_t msgs_count;
+ struct ldb_message **ts_msgs;
+ bool ts_dn;
+
+ ts_dn = is_ts_ldb_dn(sysdb_msg->dn);
+ if (ts_dn == false) {
+ return ERR_NO_TS;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_search_ts_entry(tmp_ctx, sysdb, sysdb_msg->dn,
+ LDB_SCOPE_BASE,
+ NULL,
+ sysdb_ts_cache_attrs,
+ &msgs_count,
+ &ts_msgs);
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "No such DN in the timestamp cache: %s\n",
+ ldb_dn_get_linearized(sysdb_msg->dn));
+ ret = ERR_TS_CACHE_MISS;
+ goto done;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Cannot find TS cache entry for [%s]: [%d]: %s\n",
+ ldb_dn_get_linearized(sysdb_msg->dn),
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ if (msgs_count != 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Expected 1 result for base search, got %zu\n", msgs_count);
+ return EIO;
+ }
+
+ /* Deliberately start from 1 in order to not merge objectclass and avoid
+ * breaking MPGs where the OC might be made up
+ */
+ for (size_t c = 1; sysdb_ts_cache_attrs[c]; c++) {
+ ret = merge_ts_attr(ts_msgs[0], sysdb_msg,
+ sysdb_ts_cache_attrs[c], attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Canot merge ts attr %s\n", sysdb_ts_cache_attrs[c]);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+done:
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_merge_res_ts_attrs(struct sysdb_ctx *ctx,
+ struct ldb_result *res,
+ const char *attrs[])
+{
+ errno_t ret;
+
+ if (res == NULL || ctx->ldb_ts == NULL) {
+ return EOK;
+ }
+
+ for (size_t c = 0; c < res->count; c++) {
+ ret = merge_msg_ts_attrs(ctx, res->msgs[c], attrs);
+ if (ret == ERR_NO_TS) {
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "TS cache doesn't handle this DN type, skipping\n");
+ continue;
+ } else if (ret == ERR_TS_CACHE_MISS) {
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "TS cache doesn't contain this DN, skipping\n");
+ continue;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Cannot merge timestamp cache values for %s\n",
+ ldb_dn_get_linearized(res->msgs[c]->dn));
+ /* non-fatal */
+ continue;
+ }
+ }
+
+ return EOK;
+}
+
+errno_t sysdb_merge_msg_list_ts_attrs(struct sysdb_ctx *ctx,
+ size_t msgs_count,
+ struct ldb_message **msgs,
+ const char *attrs[])
+{
+ struct ldb_result res;
+
+ res.count = msgs_count;
+ res.msgs = msgs;
+ return sysdb_merge_res_ts_attrs(ctx, &res, attrs);
+}
+
/* users */
int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
@@ -75,6 +227,13 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -180,6 +339,13 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -324,6 +490,73 @@ done:
return ret;
}
+static errno_t search_ts_matches(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
+ const char *attrs[],
+ struct ldb_result *ts_res,
+ const char *filter,
+ struct ldb_result **_res)
+{
+ char *dn_filter;
+ TALLOC_CTX *tmp_ctx = NULL;
+ struct ldb_result *res;
+ errno_t ret;
+
+ if (ts_res->count == 0) {
+ *_res = NULL;
+ ret = EOK;
+ goto done;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (res == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ dn_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|", SYSDB_NAME, filter);
+ if (dn_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (size_t i = 0; i < ts_res->count; i++) {
+ dn_filter = talloc_asprintf_append(
+ dn_filter,
+ "(%s=%s)",
+ SYSDB_DN,
+ ldb_dn_get_linearized(ts_res->msgs[i]->dn));
+ if (dn_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ dn_filter = talloc_asprintf_append(dn_filter, "))");
+ if (dn_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_search(sysdb->ldb, tmp_ctx, &res, NULL,
+ LDB_SCOPE_SUBTREE, attrs, "%s", dn_filter);
+ if (ret) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+
+ ret = EOK;
+ *_res = talloc_steal(mem_ctx, res);
+done:
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
const char *name_filter,
@@ -333,8 +566,11 @@ int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
TALLOC_CTX *tmp_ctx;
static const char *attrs[] = SYSDB_PW_ATTRS;
char *filter = NULL;
+ const char *ts_filter = NULL;
struct ldb_dn *base_dn;
struct ldb_result *res;
+ struct ldb_result ts_res;
+ struct ldb_result *ts_cache_res;
int ret;
tmp_ctx = talloc_new(NULL);
@@ -348,6 +584,28 @@ int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
goto done;
}
+ ts_filter = enum_filter(tmp_ctx, SYSDB_PWENT_FILTER,
+ NULL, addtl_filter);
+ if (ts_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_LIBS, "Searching timestamp cache with [%s]\n", ts_filter);
+
+ ZERO_STRUCT(ts_res);
+ ret = sysdb_search_ts_users(tmp_ctx, domain, ts_filter,
+ sysdb_ts_cache_attrs,
+ (size_t *) &ts_res.count, &ts_res.msgs);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ }
+
+ ret = search_ts_matches(tmp_ctx, domain->sysdb, attrs, &ts_res,
+ name_filter, &ts_cache_res);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ }
+
filter = enum_filter(tmp_ctx, SYSDB_PWENT_FILTER,
name_filter, addtl_filter);
if (filter == NULL) {
@@ -363,6 +621,19 @@ int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
+ res = sss_merge_ldb_results(res, ts_cache_res);
+ if (res == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -618,6 +889,12 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
goto done;
}
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -755,6 +1032,12 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
goto done;
}
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -771,10 +1054,18 @@ int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
TALLOC_CTX *tmp_ctx;
static const char *attrs[] = SYSDB_GRSRC_ATTRS;
const char *filter = NULL;
+ const char *ts_filter = NULL;
const char *base_filter;
struct ldb_dn *base_dn;
struct ldb_result *res;
- int ret;
+ struct ldb_result ts_res;
+ struct ldb_result *ts_cache_res;
+ int ret, lret;
+
+ if (_res == NULL) {
+ return EINVAL;
+ }
+ *_res = NULL;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
@@ -794,6 +1085,28 @@ int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
goto done;
}
+ ts_filter = enum_filter(tmp_ctx, base_filter,
+ NULL, addtl_filter);
+ if (ts_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_LIBS, "Searching timestamp cache with [%s]\n", ts_filter);
+
+ ZERO_STRUCT(ts_res);
+ ret = sysdb_search_ts_groups(tmp_ctx, domain, ts_filter,
+ sysdb_ts_cache_attrs,
+ (size_t *) &ts_res.count, &ts_res.msgs);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ }
+
+ ret = search_ts_matches(tmp_ctx, domain->sysdb, attrs, &ts_res,
+ name_filter, &ts_cache_res);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ }
+
filter = enum_filter(tmp_ctx, base_filter,
name_filter, addtl_filter);
if (filter == NULL) {
@@ -802,10 +1115,10 @@ int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
}
DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter);
- ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
- LDB_SCOPE_SUBTREE, attrs, "%s", filter);
- if (ret) {
- ret = sysdb_error_to_errno(ret);
+ lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+ LDB_SCOPE_SUBTREE, attrs, "%s", filter);
+ if (lret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(lret);
goto done;
}
@@ -814,6 +1127,19 @@ int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
+ res = sss_merge_ldb_results(res, ts_cache_res);
+ if (res == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -1212,6 +1538,13 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
goto done;
}
+ /* Merge in the timestamps from the fast ts db */
+ ret = sysdb_merge_res_ts_attrs(domain->sysdb, res, attributes);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot merge timestamp cache values\n");
+ /* non-fatal */
+ }
+
*_res = talloc_steal(mem_ctx, res);
done:
@@ -1909,3 +2242,54 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+struct ldb_result *sss_merge_ldb_results(struct ldb_result *sysdb_res,
+ struct ldb_result *ts_res)
+{
+ size_t i, ii, count, total;
+ int ret;
+
+ if (ts_res == NULL || ts_res->count == 0) {
+ return sysdb_res;
+ }
+
+ total = sysdb_res->count + ts_res->count;
+ sysdb_res->msgs = talloc_realloc(sysdb_res, sysdb_res->msgs,
+ struct ldb_message *,
+ total);
+ if (sysdb_res->msgs == NULL) {
+ return NULL;
+ }
+
+ /* FIXME - this is O(2), so inefficient for large sets! */
+ count = sysdb_res->count;
+ for (i = 0; i < ts_res->count; i++) {
+ for (ii = 0; ii < sysdb_res->count; ii++) {
+ ret = ldb_dn_compare(ts_res->msgs[i]->dn, sysdb_res->msgs[ii]->dn);
+ if (ret == 0) {
+ break;
+ }
+ }
+
+ if (ii < sysdb_res->count) {
+ /* We already have this DN but ts_res might be more up-to-date
+ * wrt timestamps */
+ sysdb_res->msgs[ii] = talloc_steal(sysdb_res, ts_res->msgs[i]);
+ continue;
+ }
+ /* new DN, merge */
+ sysdb_res->msgs[count] = talloc_steal(sysdb_res, ts_res->msgs[i]);
+ count++;
+ }
+
+ if (count < total) {
+ sysdb_res->msgs = talloc_realloc(sysdb_res, sysdb_res->msgs,
+ struct ldb_message *,
+ count);
+ if (sysdb_res->msgs == NULL) {
+ return NULL;
+ }
+ }
+ sysdb_res->count = count;
+ return sysdb_res;
+}