diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.c | 32 | ||||
-rw-r--r-- | src/db/sysdb.h | 1 | ||||
-rw-r--r-- | src/db/sysdb_ops.c | 189 | ||||
-rw-r--r-- | src/db/sysdb_private.h | 56 | ||||
-rw-r--r-- | src/db/sysdb_search.c | 394 | ||||
-rw-r--r-- | src/responder/common/responder_cache_req.c | 10 | ||||
-rw-r--r-- | src/tests/cmocka/test_sysdb_sudo.c | 4 | ||||
-rw-r--r-- | src/tests/common.h | 2 | ||||
-rw-r--r-- | src/tests/common_dom.c | 16 | ||||
-rw-r--r-- | src/util/util_errors.c | 2 | ||||
-rw-r--r-- | src/util/util_errors.h | 2 |
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 */ }; |