summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/providers/ldap/sdap_async_accounts.c178
1 files changed, 165 insertions, 13 deletions
diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 3387e3ee..d2913e20 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -1817,6 +1817,12 @@ int sdap_get_groups_recv(struct tevent_req *req,
return EOK;
}
+static errno_t sdap_nested_group_populate_users(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *dom,
+ struct sdap_options *opts,
+ struct sysdb_attrs **users,
+ int num_users);
+
static void sdap_nested_done(struct tevent_req *subreq)
{
errno_t ret;
@@ -1862,9 +1868,8 @@ static void sdap_nested_done(struct tevent_req *subreq)
/* Save all of the users first so that they are in
* place for the groups to add them.
*/
- ret = sdap_save_users(state, state->sysdb, state->attrs,
- state->dom, state->opts,
- users, count, &state->higher_usn);
+ ret = sdap_nested_group_populate_users(state->sysdb, state->dom,
+ state->opts, users, count);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1900,6 +1905,138 @@ static void sdap_nested_done(struct tevent_req *subreq)
tevent_req_done(req);
}
+static errno_t sdap_nested_group_populate_users(struct sysdb_ctx *sysdb,
+ struct sss_domain_info *dom,
+ struct sdap_options *opts,
+ struct sysdb_attrs **users,
+ int num_users)
+{
+ int i;
+ errno_t ret, sret;
+ struct ldb_message_element *el;
+ const char *username;
+ char *clean_orig_dn;
+ const char *original_dn;
+
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message **msgs;
+ char *filter;
+ const char *sysdb_name;
+ struct sysdb_attrs *attrs;
+ static const char *search_attrs[] = { SYSDB_NAME, NULL };
+ size_t count;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) return ENOMEM;
+
+ if (num_users == 0) {
+ /* Nothing to do if there are no users */
+ return EOK;
+ }
+
+ ret = sysdb_transaction_start(sysdb);
+ if (ret) {
+ DEBUG(1, ("Failed to start transaction!\n"));
+ goto done;
+ }
+
+ for (i = 0; i < num_users; i++) {
+ ret = sysdb_attrs_primary_name(sysdb, users[i],
+ opts->user_map[SDAP_AT_USER_NAME].name,
+ &username);
+ if (ret != EOK) {
+ DEBUG(1, ("User entry %d has no name attribute\n", i));
+ goto done;
+ }
+
+ ret = sysdb_attrs_get_el(users[i], SYSDB_ORIG_DN, &el);
+ if (el->num_values == 0) {
+ ret = EINVAL;
+ }
+ if (ret != EOK) {
+ DEBUG(1, ("User entry %s has no originalDN attribute\n", i));
+ goto done;
+ }
+ original_dn = (const char *) el->values[0].data;
+
+ ret = sss_filter_sanitize(tmp_ctx, original_dn,
+ &clean_orig_dn);
+ if (ret != EOK) {
+ DEBUG(1, ("Cannot sanitize originalDN\n", i));
+ goto done;
+ }
+
+ /* Check for the specified origDN in the sysdb */
+ filter = talloc_asprintf(tmp_ctx, "(%s=%s)",
+ SYSDB_ORIG_DN,
+ clean_orig_dn);
+ if (!filter) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = sysdb_search_users(tmp_ctx, sysdb, dom, filter,
+ search_attrs, &count, &msgs);
+ talloc_zfree(filter);
+ talloc_zfree(clean_orig_dn);
+ if (ret != EOK && ret != ENOENT) {
+ DEBUG(1, ("Error checking cache for user entry\n"));
+ goto done;
+ }
+ if (ret == EOK) {
+ /* The entry is cached but expired. Update the username
+ * if needed. */
+ if (count != 1) {
+ DEBUG(1, ("More than one entry with this origDN? Skipping\n"));
+ continue;
+ }
+
+ sysdb_name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
+ if (strcmp(sysdb_name, username) == 0) {
+ /* Username is correct, continue */
+ continue;
+ }
+
+ attrs = sysdb_new_attrs(tmp_ctx);
+ if (!attrs) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, username);
+ if (ret) goto done;
+ ret = sysdb_set_user_attr(tmp_ctx, sysdb,
+ dom, sysdb_name, attrs, SYSDB_MOD_REP);
+ if (ret != EOK) goto done;
+ }
+
+ /* If the entry does not exist add a fake user record */
+ ret = sysdb_add_fake_user(sysdb, dom, username, original_dn);
+ if (ret != EOK) {
+ DEBUG(1, ("Cannot store fake user entry, ignoring: [%d]: %s\n",
+ ret, strerror(ret)));
+ continue;
+ } else {
+ DEBUG(9, ("Added incomplete user %s!\n", username));
+ }
+ }
+
+ ret = sysdb_transaction_commit(sysdb);
+ if (ret) {
+ DEBUG(1, ("Failed to commit transaction!\n"));
+ goto done;
+ }
+
+ ret = EOK;
+done:
+ talloc_zfree(tmp_ctx);
+ if (ret != EOK) {
+ sret = sysdb_transaction_cancel(sysdb);
+ if (sret != EOK) {
+ DEBUG(2, ("Could not cancel transaction\n"));
+ }
+ }
+ return ret;
+}
/* ==Save-fake-group-list=====================================*/
static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
@@ -3268,7 +3405,6 @@ immediate:
return req;
}
-
static void sdap_nested_group_process_ldap_user(struct tevent_req *subreq);
static void sdap_nested_group_process_user(struct tevent_req *subreq);
static errno_t sdap_nested_group_lookup_user(struct tevent_req *req,
@@ -3285,10 +3421,12 @@ static errno_t sdap_nested_group_process_step(struct tevent_req *req)
size_t count;
struct ldb_message **msgs;
uint64_t expiration;
+ uint64_t create_time;
bool has_key = false;
hash_key_t key;
uint8_t *data;
time_t now = time(NULL);
+ uid_t user_uid;
while (true) {
/* Continue to loop through until all entries have been
@@ -3419,9 +3557,22 @@ static errno_t sdap_nested_group_process_step(struct tevent_req *req)
continue;
}
- expiration = ldb_msg_find_attr_as_uint64(msgs[0],
- SYSDB_CACHE_EXPIRE,
- 0);
+ user_uid = ldb_msg_find_attr_as_uint64(msgs[0], SYSDB_UIDNUM, 0);
+ if (!user_uid) {
+ /* Refresh the fake user if he was created before cache_timeout */
+ create_time = ldb_msg_find_attr_as_uint64(msgs[0],
+ SYSDB_CREATE_TIME,
+ 0);
+ expiration = create_time +
+ dp_opt_get_int(state->opts->basic,
+ SDAP_ENTRY_CACHE_TIMEOUT);
+ } else {
+ /* Regular user, check if we need a refresh */
+ expiration = ldb_msg_find_attr_as_uint64(msgs[0],
+ SYSDB_CACHE_EXPIRE,
+ 0);
+ }
+
if (expiration && expiration > now) {
DEBUG(6, ("Cached values are still valid. Skipping\n"));
state->member_index++;
@@ -3445,18 +3596,19 @@ error:
static errno_t sdap_nested_group_lookup_user(struct tevent_req *req,
tevent_req_fn fn)
{
- errno_t ret;
const char **sdap_attrs;
char *filter;
struct tevent_req *subreq;
struct sdap_nested_group_ctx *state =
tevent_req_data(req, struct sdap_nested_group_ctx);
- ret = build_attrs_from_map(state, state->opts->user_map,
- SDAP_OPTS_USER, &sdap_attrs);
- if (ret != EOK) {
- return ret;
- }
+
+ /* Only pull down username and originalDN */
+ sdap_attrs = talloc_array(state, const char *, 3);
+ if (!sdap_attrs) return ENOMEM;
+ sdap_attrs[0] = "objectClass";
+ sdap_attrs[1] = state->opts->user_map[SDAP_AT_USER_NAME].name;
+ sdap_attrs[2] = NULL;
filter = talloc_asprintf(
sdap_attrs, "(objectclass=%s)",