diff options
-rw-r--r-- | src/db/sysdb.c | 76 | ||||
-rw-r--r-- | src/db/sysdb.h | 3 | ||||
-rw-r--r-- | src/db/sysdb_ops.c | 555 | ||||
-rw-r--r-- | src/db/sysdb_private.h | 25 | ||||
-rw-r--r-- | src/db/sysdb_search.c | 47 | ||||
-rw-r--r-- | src/tests/cmocka/test_responder_cache_req.c | 2 | ||||
-rw-r--r-- | src/tests/cmocka/test_sysdb_sudo.c | 1 |
7 files changed, 673 insertions, 36 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c index 81b731a0d..1224e96ad 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -1524,6 +1524,42 @@ errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count, return EOK; } +struct ldb_message *sysdb_attrs2msg(TALLOC_CTX *mem_ctx, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op) +{ + struct ldb_message *msg; + errno_t ret; + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = entry_dn; + + msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num); + if (msg->elements == NULL) { + ret = ENOMEM; + goto done; + } + + for (int i = 0; i < attrs->num; i++) { + msg->elements[i] = attrs->a[i]; + msg->elements[i].flags = mod_op; + } + msg->num_elements = attrs->num; + + ret = EOK; +done: + if (ret != EOK) { + talloc_zfree(msg); + } + return msg; +} + int sysdb_compare_usn(const char *a, const char *b) { size_t len_a; @@ -1715,3 +1751,43 @@ bool is_ts_ldb_dn(struct ldb_dn *dn) return false; } + +bool sysdb_msg_attrs_modts_differs(struct ldb_message *old_entry, + struct sysdb_attrs *new_entry) +{ + const char *old_entry_ts_attr = NULL; + const char *new_entry_ts_attr = NULL; + errno_t ret; + + old_entry_ts_attr = ldb_msg_find_attr_as_string(old_entry, + SYSDB_ORIG_MODSTAMP, + NULL); + if (old_entry_ts_attr == NULL) { + /* we didn't know the originalModifyTimestamp earlier. Regardless + * of whether the new_entry has the timestamp, we should do + * a comparison of the attributes + */ + return true; + } + + if (new_entry == NULL) { + return false; + } + + ret = sysdb_attrs_get_string(new_entry, SYSDB_ORIG_MODSTAMP, + &new_entry_ts_attr); + if (ret != EOK) { + /* Nothing to compare against in the new entry either, do + * a comparison of the attributes + */ + return true; + } + + if (old_entry_ts_attr != NULL + && new_entry_ts_attr != NULL + && strcmp(old_entry_ts_attr, new_entry_ts_attr) == 0) { + return false; + } + + return true; +} diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 4f69b6372..2bc20ff97 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -314,6 +314,9 @@ struct range_info { /* These attributes are stored in the timestamp cache */ extern const char *sysdb_ts_cache_attrs[]; +/* These attributes are stored in the timestamp cache */ +extern const char *sysdb_ts_cache_attrs[]; + /* values are copied in the structure, allocated on "attrs" */ int sysdb_attrs_add_val(struct sysdb_attrs *attrs, const char *name, const struct ldb_val *val); diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index 2f06444e7..4ea0d0ad7 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -96,14 +96,13 @@ int sss_ldb_modify_permissive(struct ldb_context *ldb, /* =Remove-Entry-From-Sysdb=============================================== */ - -int sysdb_delete_entry(struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - bool ignore_not_found) +static int sysdb_delete_cache_entry(struct ldb_context *ldb, + struct ldb_dn *dn, + bool ignore_not_found) { int ret; - ret = ldb_delete(sysdb->ldb, dn); + ret = ldb_delete(ldb, dn); switch (ret) { case LDB_SUCCESS: return EOK; @@ -114,11 +113,40 @@ int sysdb_delete_entry(struct sysdb_ctx *sysdb, /* fall through */ default: DEBUG(SSSDBG_CRIT_FAILURE, "LDB Error: %s(%d)\nError Message: [%s]\n", - ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)); + ldb_strerror(ret), ret, ldb_errstring(ldb)); return sysdb_error_to_errno(ret); } } +static int sysdb_delete_ts_entry(struct sysdb_ctx *sysdb, + struct ldb_dn *dn) +{ + if (sysdb->ldb_ts == NULL) { + return EOK; + } + + return sysdb_delete_cache_entry(sysdb->ldb_ts, dn, true); +} + +int sysdb_delete_entry(struct sysdb_ctx *sysdb, + struct ldb_dn *dn, + bool ignore_not_found) +{ + errno_t ret; + + ret = sysdb_delete_cache_entry(sysdb->ldb, dn, ignore_not_found); + if (ret == EOK) { + ret = sysdb_delete_ts_entry(sysdb, dn); + DEBUG(SSSDBG_MINOR_FAILURE, + "sysdb_delete_ts_entry failed: %d\n", ret); + } else { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_delete_cache_entry failed: %d\n", ret); + } + + return ret; +} + /* =Remove-Subentries-From-Sysdb=========================================== */ int sysdb_delete_recursive(struct sysdb_ctx *sysdb, @@ -719,54 +747,411 @@ done: return ret; } -/* =Replace-Attributes-On-Entry=========================================== */ +/* =Timestamp-cache-functions==============================================*/ -int sysdb_set_entry_attr(struct sysdb_ctx *sysdb, - struct ldb_dn *entry_dn, - struct sysdb_attrs *attrs, - int mod_op) +/* If modifyTimestamp is the same in the TS cache, return EOK. Return ERR_NO_TS + * if there is no timestamps cache for this domain and ERR_TS_CACHE_MISS if + * the entry had changed and the caller needs to update the sysdb cache as well. + */ +static errno_t sysdb_check_ts_cache(struct sss_domain_info *domain, + struct ldb_dn *entry_dn, + struct sysdb_attrs *entry) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + size_t msgs_count; + struct ldb_message **msgs; + bool mod_ts_differs; + + if (domain->sysdb->ldb_ts == NULL) { + return ERR_NO_TS; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* Check if the entry is in the timestamp cache */ + ret = sysdb_search_ts_entry(tmp_ctx, + domain->sysdb, + entry_dn, + LDB_SCOPE_BASE, + NULL, + sysdb_ts_cache_attrs, + &msgs_count, + &msgs); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Cannot find TS cache entry for [%s]: [%d]: %s\n", + ldb_dn_get_linearized(entry_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; + } + + mod_ts_differs = sysdb_msg_attrs_modts_differs(msgs[0], entry); + if (mod_ts_differs == true) { + ret = ERR_TS_CACHE_MISS; + goto done; + } + + ret = EOK; +done: + talloc_zfree(tmp_ctx); + return ret; +} + +static int sysdb_set_ts_entry_attr(struct sysdb_ctx *sysdb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op); + +static errno_t sysdb_create_ts_entry(struct sysdb_ctx *sysdb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs) { struct ldb_message *msg; - int i, ret; + errno_t ret; int lret; TALLOC_CTX *tmp_ctx; + if (sysdb->ldb_ts == NULL || attrs->num == 0) { + return EOK; + } + tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { + if (tmp_ctx == NULL) { return ENOMEM; } - if (!entry_dn || attrs->num == 0) { + if (entry_dn == NULL) { ret = EINVAL; goto done; } - msg = ldb_msg_new(tmp_ctx); - if (!msg) { + msg = sysdb_attrs2msg(tmp_ctx, entry_dn, attrs, 0); + if (msg == NULL) { ret = ENOMEM; goto done; } - msg->dn = entry_dn; + lret = ldb_add(sysdb->ldb_ts, msg); + if (lret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, + "ldb_add failed: [%s](%d)[%s]\n", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb_ts)); + } - msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num); - if (!msg->elements) { + ret = sysdb_error_to_errno(lret); +done: + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n"); + } else if (ret) { + DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_zfree(tmp_ctx); + return ret; +} + +static struct sysdb_attrs *ts_obj_attrs(TALLOC_CTX *mem_ctx, + enum sysdb_obj_type obj_type) +{ + struct sysdb_attrs *attrs; + const char *oc; + errno_t ret; + + switch (obj_type) { + case SYSDB_USER: + oc = SYSDB_USER_CLASS; + break; + case SYSDB_GROUP: + oc = SYSDB_GROUP_CLASS; + break; + default: + return NULL; + } + + attrs = sysdb_new_attrs(mem_ctx); + if (attrs == NULL) { + return NULL; + } + + ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, oc); + if (ret != EOK) { + talloc_free(attrs); + return NULL; + } + + return attrs; +} + +static errno_t sysdb_update_ts_cache(struct sss_domain_info *domain, + struct ldb_dn *entry_dn, + struct sysdb_attrs *entry_attrs, + struct sysdb_attrs *ts_attrs, + int mod_op, + uint64_t cache_timeout, + time_t now) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *modstamp; + + if (domain->sysdb->ldb_ts == NULL) { + DEBUG(SSSDBG_TRACE_INTERNAL, "No timestamp cache for this domain\n"); + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + if (ts_attrs == NULL) { + ts_attrs = sysdb_new_attrs(tmp_ctx); + if (ts_attrs == NULL) { + ret = ENOMEM; + goto done; + } + } + + ret = sysdb_attrs_add_time_t(ts_attrs, SYSDB_LAST_UPDATE, now); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to add %s to tsdb\n", SYSDB_LAST_UPDATE); + goto done; + } + + ret = sysdb_attrs_add_time_t(ts_attrs, SYSDB_CACHE_EXPIRE, + ((cache_timeout) ? + (now + cache_timeout) : 0)); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to add %s to tsdb\n", SYSDB_CACHE_EXPIRE); + goto done; + } + + if (entry_attrs != NULL) { + ret = sysdb_attrs_get_string(entry_attrs, SYSDB_ORIG_MODSTAMP, + &modstamp); + if (ret == EOK) { + ret = sysdb_attrs_add_string(ts_attrs, + SYSDB_ORIG_MODSTAMP, modstamp); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to add %s to tsdb\n", SYSDB_ORIG_MODSTAMP); + goto done; + } + } + } + + ret = sysdb_set_ts_entry_attr(domain->sysdb, entry_dn, + ts_attrs, mod_op); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set ts attrs for group %s\n", + ldb_dn_get_linearized(entry_dn)); + /* Not fatal */ + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t sysdb_check_and_update_ts_cache(struct sss_domain_info *domain, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + uint64_t cache_timeout, + time_t now) +{ + errno_t ret; + + ret = sysdb_check_ts_cache(domain, entry_dn, attrs); + switch (ret) { + case ENOENT: + DEBUG(SSSDBG_TRACE_INTERNAL, "No timestamps entry\n"); + break; + case EOK: + /* The entry's timestamp was the same. Just update the ts cache */ + ret = sysdb_update_ts_cache(domain, entry_dn, attrs, NULL, + SYSDB_MOD_REP, cache_timeout, now); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot update the timestamps cache [%d]: %s\n", + ret, sss_strerror(ret)); + } + break; + case ERR_TS_CACHE_MISS: + case ERR_NO_TS: + /* Either there is no cache or the cache is up-do-date. Just report + * what's up + */ + break; + default: + DEBUG(SSSDBG_OP_FAILURE, + "Error checking the timestamps cache [%d]: %s\n", + ret, sss_strerror(ret)); + break; + } + + return ret; +} + +static errno_t get_sysdb_obj_dn(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + enum sysdb_obj_type obj_type, + const char *obj_name, + struct ldb_dn **_obj_dn) +{ + struct ldb_dn *obj_dn; + + switch (obj_type) { + case SYSDB_USER: + obj_dn = sysdb_user_dn(mem_ctx, domain, obj_name); + break; + case SYSDB_GROUP: + obj_dn = sysdb_group_dn(mem_ctx, domain, obj_name); + break; + default: + return EINVAL; + } + + if (obj_dn == NULL) { + return ENOMEM; + } + + *_obj_dn = obj_dn; + return EOK; +} + +static errno_t sysdb_check_and_update_ts_obj(struct sss_domain_info *domain, + enum sysdb_obj_type obj_type, + const char *obj_name, + struct sysdb_attrs *attrs, + uint64_t cache_timeout, + time_t now) +{ + struct ldb_dn *entry_dn; + TALLOC_CTX *tmp_ctx; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + ret = get_sysdb_obj_dn(tmp_ctx, domain, obj_type, obj_name, &entry_dn); + if (ret != EOK) { + goto done; + } + + ret = sysdb_check_and_update_ts_cache(domain, entry_dn, attrs, + cache_timeout, now); +done: + talloc_zfree(tmp_ctx); + return ret; +} + +static errno_t sysdb_create_ts_obj(struct sss_domain_info *domain, + enum sysdb_obj_type obj_type, + const char *obj_name, + uint64_t cache_timeout, + time_t now) +{ + struct ldb_dn *entry_dn; + struct sysdb_attrs *ts_attrs = NULL; + TALLOC_CTX *tmp_ctx; + errno_t ret; + + if (domain->sysdb->ldb_ts == NULL) { + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = get_sysdb_obj_dn(tmp_ctx, domain, obj_type, obj_name, &entry_dn); + if (ret != EOK) { + goto done; + } + + ts_attrs = ts_obj_attrs(tmp_ctx, obj_type); + if (ts_attrs == NULL) { ret = ENOMEM; goto done; } - for (i = 0; i < attrs->num; i++) { - msg->elements[i] = attrs->a[i]; - msg->elements[i].flags = mod_op; + ret = sysdb_update_ts_cache(domain, entry_dn, NULL, ts_attrs, + SYSDB_MOD_ADD, cache_timeout, now); + if (ret != EOK) { + goto done; } - msg->num_elements = attrs->num; +done: + talloc_zfree(tmp_ctx); + return ret; +} - lret = ldb_modify(sysdb->ldb, msg); +static errno_t sysdb_check_and_update_ts_grp(struct sss_domain_info *domain, + const char *grp_name, + struct sysdb_attrs *attrs, + uint64_t cache_timeout, + time_t now) +{ + return sysdb_check_and_update_ts_obj(domain, SYSDB_GROUP, grp_name, + attrs, cache_timeout, now); +} + +static errno_t sysdb_create_ts_grp(struct sss_domain_info *domain, + const char *grp_name, + uint64_t cache_timeout, + time_t now) +{ + return sysdb_create_ts_obj(domain, SYSDB_GROUP, grp_name, + cache_timeout, now); +} + +/* =Replace-Attributes-On-Entry=========================================== */ +static int sysdb_set_cache_entry_attr(struct ldb_context *ldb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op) +{ + struct ldb_message *msg; + int ret; + int lret; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + if (entry_dn == NULL || attrs->num == 0) { + ret = EINVAL; + goto done; + } + + msg = sysdb_attrs2msg(tmp_ctx, entry_dn, attrs, mod_op); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + lret = ldb_modify(ldb, msg); if (lret != LDB_SUCCESS) { DEBUG(SSSDBG_MINOR_FAILURE, "ldb_modify failed: [%s](%d)[%s]\n", - ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)); + ldb_strerror(lret), lret, ldb_errstring(ldb)); } ret = sysdb_error_to_errno(lret); @@ -782,6 +1167,79 @@ done: return ret; } +int sysdb_set_entry_attr(struct sysdb_ctx *sysdb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op) +{ + errno_t ret = EOK; + errno_t tret = EOK; + + ret = sysdb_set_cache_entry_attr(sysdb->ldb, entry_dn, attrs, mod_op); + if (ret == EOK) { + tret = sysdb_set_ts_entry_attr(sysdb, entry_dn, attrs, mod_op); + if (tret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set ts attrs for %s\n", ldb_dn_get_linearized(entry_dn)); + /* Not fatal */ + } + } + + return ret; +} + +static int sysdb_rep_ts_entry_attr(struct sysdb_ctx *sysdb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs) +{ + if (sysdb->ldb_ts == NULL || attrs->num == 0) { + return EOK; + } + + return sysdb_set_cache_entry_attr(sysdb->ldb_ts, entry_dn, + attrs, SYSDB_MOD_REP); +} + +static int sysdb_set_ts_entry_attr(struct sysdb_ctx *sysdb, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op) +{ + struct sysdb_attrs *ts_attrs; + TALLOC_CTX *tmp_ctx; + errno_t ret; + + if (sysdb->ldb_ts == NULL) { + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + ts_attrs = sysdb_filter_ts_attrs(tmp_ctx, attrs); + if (ts_attrs == NULL) { + ret = ENOMEM; + goto done; + } + + switch (mod_op) { + case SYSDB_MOD_REP: + ret = sysdb_rep_ts_entry_attr(sysdb, entry_dn, ts_attrs); + break; + case SYSDB_MOD_ADD: + ret = sysdb_create_ts_entry(sysdb, entry_dn, ts_attrs); + break; + default: + ret = EINVAL; + break; + } + +done: + talloc_zfree(tmp_ctx); + return ret; +} /* =Replace-Attributes-On-User============================================ */ @@ -816,7 +1274,6 @@ done: return ret; } - /* =Replace-Attributes-On-Group=========================================== */ int sysdb_set_group_attr(struct sss_domain_info *domain, @@ -1600,6 +2057,13 @@ int sysdb_add_group(struct sss_domain_info *domain, goto done; } + ret = sysdb_create_ts_grp(domain, name, cache_timeout, now); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set timestamp cache attributes for a group\n"); + /* Not fatal */ + } + if (!attrs) { attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { @@ -1694,16 +2158,23 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain, ret = sysdb_add_basic_group(domain, name, gid); if (ret) goto done; + if (!now) { + now = time(NULL); + } + + ret = sysdb_create_ts_grp(domain, name, now-1, now); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Cannot set timestamp cache attributes for a group\n"); + /* Not fatal */ + } + attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { ret = ENOMEM; goto done; } - if (!now) { - now = time(NULL); - } - ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); if (ret) goto done; @@ -2104,14 +2575,22 @@ int sysdb_store_group(struct sss_domain_info *domain, time_t now) { TALLOC_CTX *tmp_ctx; - static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, - SYSDB_ORIG_MODSTAMP, NULL }; + static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL }; struct ldb_message *msg; bool new_group = false; int ret; errno_t sret = EOK; bool in_transaction = false; + ret = sysdb_check_and_update_ts_grp(domain, name, attrs, + cache_timeout, now); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_LIBS, + "The group record of %s did not change, only updated " + "the timestamp cache\n", name); + return EOK; + } + tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; @@ -2157,6 +2636,10 @@ int sysdb_store_group(struct sss_domain_info *domain, } else { ret = sysdb_store_group_attrs(domain, name, gid, attrs, cache_timeout, now); } + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cache update failed: %d\n", ret); + goto done; + } sret = sysdb_transaction_commit(domain->sysdb); if (sret != EOK) { @@ -2203,21 +2686,21 @@ static errno_t sysdb_store_new_group(struct sss_domain_info *domain, /* Not found by GID, return the original EEXIST, * this may be a conflict in MPG domain or something * else */ - DEBUG(SSSDBG_TRACE_LIBS, + DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_group failed (while renaming group). Not " "found by gid: [%"SPRIgid"].\n", gid); return EEXIST; } else if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, "sysdb_add_group failed.\n"); + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_group failed.\n"); return ret; } - DEBUG(SSSDBG_MINOR_FAILURE, + DEBUG(SSSDBG_TRACE_FUNC, "A group with the same GID [%"SPRIgid"] was removed from " "the cache\n", gid); ret = sysdb_add_group(domain, name, gid, attrs, cache_timeout, now); if (ret) { - DEBUG(SSSDBG_MINOR_FAILURE, + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_group failed (while renaming group) for: " "%s [%"SPRIgid"].\n", name, gid); return ret; diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h index dae348b0b..9d03d59f0 100644 --- a/src/db/sysdb_private.h +++ b/src/db/sysdb_private.h @@ -194,6 +194,18 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, */ bool is_ts_ldb_dn(struct ldb_dn *dn); +/* Returns true if the attrname is an attribute we store to the timestamp + * cache, false if it's a sysdb-only attribute + */ +bool is_ts_cache_attr(const char *attrname); + +/* Returns a subset of attrs that only contains the attributes we store to + * the timestamps cache. Useful in generic functions that set some attributes + * and we want to mirror that change in the timestamps cache + */ +struct sysdb_attrs *sysdb_filter_ts_attrs(TALLOC_CTX *mem_ctx, + struct sysdb_attrs *attrs); + /* 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. @@ -239,4 +251,17 @@ int sysdb_search_ts_groups(TALLOC_CTX *mem_ctx, size_t *msgs_count, struct ldb_message ***msgs); +/* Compares the modifyTimestamp attribute between old_entry and + * new_entry. Returns true if they differ (or either entry is missing + * the attribute) and false if the attribute is the same + */ +bool sysdb_msg_attrs_modts_differs(struct ldb_message *old_entry, + struct sysdb_attrs *new_entry); + +/* Given a sysdb_attrs pointer, returns a corresponding ldb_message */ +struct ldb_message *sysdb_attrs2msg(TALLOC_CTX *mem_ctx, + struct ldb_dn *entry_dn, + struct sysdb_attrs *attrs, + int mod_op); + #endif /* __INT_SYS_DB_H__ */ diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c index 9a1ae7a9f..61b07acc9 100644 --- a/src/db/sysdb_search.c +++ b/src/db/sysdb_search.c @@ -2293,3 +2293,50 @@ struct ldb_result *sss_merge_ldb_results(struct ldb_result *sysdb_res, sysdb_res->count = count; return sysdb_res; } + +bool is_ts_cache_attr(const char *attrname) +{ + size_t i; + + for (i = 0; sysdb_ts_cache_attrs[i] != NULL; i++) { + if (strcmp(attrname, sysdb_ts_cache_attrs[i]) == 0) { + break; + } + } + + if (sysdb_ts_cache_attrs[i] == NULL) { + return false; + } + + return true; +} + +struct sysdb_attrs *sysdb_filter_ts_attrs(TALLOC_CTX *mem_ctx, + struct sysdb_attrs *attrs) +{ + struct sysdb_attrs *ts_attrs; + int ti = 0; + + ts_attrs = sysdb_new_attrs(mem_ctx); + if (ts_attrs == NULL) { + return NULL; + } + + ts_attrs->a = talloc_zero_array(ts_attrs, + struct ldb_message_element, + attrs->num); + if (ts_attrs->a == NULL) { + talloc_free(ts_attrs); + return NULL; + } + + for (int i = 0; i < attrs->num; i++) { + if (is_ts_cache_attr(attrs->a[i].name)) { + ts_attrs->a[ti] = attrs->a[i]; + ti++; + } + } + ts_attrs->num = ti; + + return ts_attrs; +} diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c index f30f1eaad..ba7fbc194 100644 --- a/src/tests/cmocka/test_responder_cache_req.c +++ b/src/tests/cmocka/test_responder_cache_req.c @@ -483,6 +483,7 @@ static int test_multi_domain_setup(void **state) ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache); assert_int_equal(ret, EOK); + reset_ldb_errstrings(test_ctx->tctx->dom); check_leaks_push(test_ctx); return 0; @@ -497,6 +498,7 @@ static int test_multi_domain_teardown(void **state) talloc_zfree(test_ctx->result); talloc_zfree(test_ctx->name); + reset_ldb_errstrings(test_ctx->tctx->dom); assert_true(check_leaks_pop(test_ctx)); talloc_zfree(test_ctx); test_multidom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, domains); diff --git a/src/tests/cmocka/test_sysdb_sudo.c b/src/tests/cmocka/test_sysdb_sudo.c index 97f80d7e5..aebad88eb 100644 --- a/src/tests/cmocka/test_sysdb_sudo.c +++ b/src/tests/cmocka/test_sysdb_sudo.c @@ -155,6 +155,7 @@ static int test_sysdb_teardown(void **state) test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); + reset_ldb_errstrings(test_ctx->tctx->dom); assert_true(check_leaks_pop(test_ctx)); talloc_zfree(test_ctx); assert_true(leak_check_teardown()); |