summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--src/responder/common/responder_cache_req.c10
-rw-r--r--src/tests/cmocka/test_sysdb_sudo.c4
-rw-r--r--src/tests/common.h2
-rw-r--r--src/tests/common_dom.c16
-rw-r--r--src/util/util_errors.c2
-rw-r--r--src/util/util_errors.h2
11 files changed, 667 insertions, 41 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;
+}
diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c
index a8f846c96..c1f67cd90 100644
--- a/src/responder/common/responder_cache_req.c
+++ b/src/responder/common/responder_cache_req.c
@@ -43,11 +43,14 @@ static errno_t updated_users_by_filter(TALLOC_CTX *mem_ctx,
recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
SYSDB_LAST_UPDATE, since);
+ if (recent_filter == NULL) {
+ return ENOMEM;
+ }
+
ret = sysdb_enumpwent_filter_with_views(mem_ctx, domain,
name_filter, recent_filter,
_res);
talloc_free(recent_filter);
-
return ret;
}
@@ -62,11 +65,14 @@ static errno_t updated_groups_by_filter(TALLOC_CTX *mem_ctx,
recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
SYSDB_LAST_UPDATE, since);
+ if (recent_filter == NULL) {
+ return ENOMEM;
+ }
+
ret = sysdb_enumgrent_filter_with_views(mem_ctx, domain,
name_filter, recent_filter,
_res);
talloc_free(recent_filter);
-
return ret;
}
diff --git a/src/tests/cmocka/test_sysdb_sudo.c b/src/tests/cmocka/test_sysdb_sudo.c
index 7289454a4..97f80d7e5 100644
--- a/src/tests/cmocka/test_sysdb_sudo.c
+++ b/src/tests/cmocka/test_sysdb_sudo.c
@@ -23,9 +23,11 @@
#include <setjmp.h>
#include <cmocka.h>
#include <popt.h>
+#include <ldb_module.h>
#include "tests/cmocka/common_mock.h"
#include "src/db/sysdb_sudo.h"
+#include "src/db/sysdb_private.h"
#define TESTS_PATH "tp_" BASE_FILE_STEM
#define TEST_CONF_DB "test_sysdb_sudorules.ldb"
@@ -138,6 +140,7 @@ static int test_sysdb_setup(void **state)
create_groups(test_ctx->tctx->dom);
create_users(test_ctx->tctx->dom);
+ reset_ldb_errstrings(test_ctx->tctx->dom);
check_leaks_push(test_ctx);
*state = (void *)test_ctx;
@@ -710,7 +713,6 @@ int main(int argc, const char *argv[])
cmocka_unit_test_setup_teardown(test_sudo_get_filter,
test_sysdb_setup,
test_sysdb_teardown),
-
/* sysdb_get_sudo_user_info() */
cmocka_unit_test_setup_teardown(test_get_sudo_user_info,
test_sysdb_setup,
diff --git a/src/tests/common.h b/src/tests/common.h
index c9b3815cd..b49cfea9b 100644
--- a/src/tests/common.h
+++ b/src/tests/common.h
@@ -84,6 +84,8 @@ struct sss_test_conf_param {
struct sss_test_ctx *create_ev_test_ctx(TALLOC_CTX *mem_ctx);
+void reset_ldb_errstrings(struct sss_domain_info *dom);
+
struct sss_test_ctx *
create_multidom_test_ctx(TALLOC_CTX *mem_ctx,
const char *tests_path,
diff --git a/src/tests/common_dom.c b/src/tests/common_dom.c
index 615b613c8..f1a92cc99 100644
--- a/src/tests/common_dom.c
+++ b/src/tests/common_dom.c
@@ -173,6 +173,14 @@ done:
return ret;
}
+void reset_ldb_errstrings(struct sss_domain_info *dom)
+{
+ ldb_reset_err_string(sysdb_ctx_get_ldb(dom->sysdb));
+ if (dom->sysdb->ldb_ts) {
+ ldb_reset_err_string(dom->sysdb->ldb_ts);
+ }
+}
+
static errno_t
mock_domain(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
@@ -191,12 +199,7 @@ mock_domain(TALLOC_CTX *mem_ctx,
goto done;
}
- /* reset ldb error if any */
- ldb_reset_err_string(sysdb_ctx_get_ldb(domain->sysdb));
-
- if (domain->sysdb->ldb_ts != NULL) {
- ldb_reset_err_string(domain->sysdb->ldb_ts);
- }
+ reset_ldb_errstrings(domain);
/* init with an AD-style regex to be able to test flat name */
ret = sss_names_init_from_args(domain,
@@ -378,6 +381,7 @@ void test_multidom_suite_cleanup(const char *tests_path,
}
talloc_zfree(sysdb_path);
+
}
}
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 458321a08..2d2bafb1e 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -91,6 +91,8 @@ struct err_string error_to_str[] = {
{ "SBUS request already handled" }, /* ERR_SBUS_REQUEST_HANDLED */
{ "Sysdb version is too old" }, /* ERR_SYSDB_VERSION_TOO_OLD */
{ "Sysdb version is too new" }, /* ERR_SYSDB_VERSION_TOO_NEW */
+ { "Domain has to timestamp cache" }, /* ERR_NO_TS */
+ { "No timestamp cache record" }, /* ERR_TS_CACHE_MISS */
{ "ERR_LAST" } /* ERR_LAST */
};
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index 2f4791522..e8ea87765 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -113,6 +113,8 @@ enum sssd_errors {
ERR_SBUS_REQUEST_HANDLED,
ERR_SYSDB_VERSION_TOO_OLD,
ERR_SYSDB_VERSION_TOO_NEW,
+ ERR_NO_TS,
+ ERR_TS_CACHE_MISS,
ERR_LAST /* ALWAYS LAST */
};