diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2011-09-21 10:50:18 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2011-09-28 09:22:48 -0400 |
commit | 033d1e3985288ec827db85882b052104485606ac (patch) | |
tree | 007e9ee457afe42904f15d1abd23133fc94bca6c | |
parent | fd61c807554d5a3ff74f065eb0438fe2524f4ba2 (diff) | |
download | sssd-033d1e3985288ec827db85882b052104485606ac.tar.gz sssd-033d1e3985288ec827db85882b052104485606ac.tar.bz2 sssd-033d1e3985288ec827db85882b052104485606ac.zip |
Store name aliases for users, groups
Also checks fake users for aliases when storing a real users so that
getgrnam for a RFC2307 group that references a user by his secondary
name followed by getpwnam for this user by his primary name works
-rw-r--r-- | src/providers/ldap/sdap_async.c | 90 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 6 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_groups.c | 129 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 7 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_users.c | 21 |
5 files changed, 216 insertions, 37 deletions
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index 0f9855b7..5d701998 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -1887,3 +1887,93 @@ bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts) return false; } + +errno_t sdap_check_aliases(struct sysdb_ctx *sysdb, + struct sysdb_attrs *user_attrs, + struct sss_domain_info *dom, + struct sdap_options *opts, + bool steal_memberships) +{ + errno_t ret; + const char **aliases = NULL; + const char *name = NULL; + struct ldb_message *msg; + TALLOC_CTX *tmp_ctx = NULL; + char **parents; + uid_t alias_uid; + int i; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + + ret = sysdb_attrs_primary_name(sysdb, user_attrs, + opts->user_map[SDAP_AT_USER_NAME].name, + &name); + if (ret != EOK) { + DEBUG(1, ("Could not get the primary name\n")); + goto done; + } + + ret = sysdb_attrs_get_aliases(tmp_ctx, user_attrs, name, &aliases); + if (ret != EOK) { + DEBUG(1, ("Failed to get the alias list\n")); + goto done; + } + + for (i = 0; aliases[i]; i++) { + /* In RFC2307 schema, another group might be referencing user + * using secondary name, so there might be fake users in the cache + * from a previous getgr call */ + ret = sysdb_search_user_by_name(tmp_ctx, sysdb, + aliases[i], NULL, &msg); + if (ret && ret != ENOENT) { + DEBUG(1, ("Error searching the cache\n")); + goto done; + } else if (ret == ENOENT) { + DEBUG(9, ("No user with primary name same as alias %s\n", aliases[i])); + continue; + } + + alias_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); + if (alias_uid) { + DEBUG(1, ("Cache contains non-fake user with same name " + "as alias %s\n", aliases[i])); + ret = EIO; + goto done; + } + DEBUG(7, ("%s is a fake user\n", aliases[i])); + + if (steal_memberships) { + /* Get direct sysdb parents */ + ret = sysdb_get_direct_parents(tmp_ctx, sysdb, dom, + SYSDB_MEMBER_USER, + aliases[i], &parents); + if (ret) { + DEBUG(1, ("Could not get direct parents for %s: %d [%s]\n", + aliases[i], ret, strerror(ret))); + goto done; + } + + ret = sysdb_update_members(sysdb, name, SYSDB_MEMBER_USER, + (const char *const *) parents, + NULL); + if (ret != EOK) { + DEBUG(1, ("Membership update failed [%d]: %s\n", + ret, strerror(ret))); + goto done; + } + } + + ret = sysdb_delete_user(sysdb, aliases[i], alias_uid); + if (ret) { + DEBUG(1, ("Error deleting fake user %s\n", aliases[i])); + goto done; + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 9b5a3079..8714e2ba 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -169,4 +169,10 @@ int sdap_deref_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, size_t *reply_count, struct sdap_deref_attrs ***reply); + +errno_t sdap_check_aliases(struct sysdb_ctx *sysdb, + struct sysdb_attrs *user_attrs, + struct sss_domain_info *dom, + struct sdap_options *opts, + bool steal_memberships); #endif /* _SDAP_ASYNC_H_ */ diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index f887651d..2b48af92 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -222,9 +222,11 @@ static int sdap_save_group(TALLOC_CTX *memctx, const char *name = NULL; gid_t gid; int ret; + int i; char *usn_value = NULL; TALLOC_CTX *tmpctx = NULL; bool posix_group; + const char **aliases = NULL; tmpctx = talloc_new(memctx); if (!tmpctx) { @@ -367,6 +369,20 @@ static int sdap_save_group(TALLOC_CTX *memctx, } } + ret = sysdb_attrs_get_aliases(tmpctx, attrs, name, &aliases); + if (ret != EOK) { + DEBUG(1, ("Failed to get the alias list\n")); + goto fail; + } + + for (i = 0; aliases[i]; i++) { + ret = sysdb_attrs_add_string(group_attrs, SYSDB_NAME_ALIAS, + aliases[i]); + if (ret) { + goto fail; + } + } + DEBUG(6, ("Storing info for group %s\n", name)); ret = sdap_store_group_with_gid(group_attrs, ctx, dom, @@ -853,17 +869,73 @@ sdap_process_group_members_2307bis(struct tevent_req *req, } static int +sdap_add_group_member_2307(struct sdap_process_group_state *state, + const char *username) +{ + char *strdn; + + strdn = sysdb_user_strdn(state->sysdb_dns->values, + state->dom->name, username); + if (!strdn) { + return ENOMEM; + } + + state->sysdb_dns->values[state->sysdb_dns->num_values].data = + (uint8_t *) strdn; + state->sysdb_dns->values[state->sysdb_dns->num_values].length = + strlen(strdn); + state->sysdb_dns->num_values++; + + return EOK; +} + +static int sdap_process_missing_member_2307(struct sdap_process_group_state *state, - char *username, bool *in_transaction) + char *member_name, bool *in_transaction) { int ret, sret; - struct ldb_dn *dn; - char* dn_string; - - DEBUG(7, ("Adding a dummy entry\n")); + TALLOC_CTX *tmp_ctx; + const char *filter; + const char *username; + size_t count; + struct ldb_message **msgs = NULL; + static const char *attrs[] = { SYSDB_NAME, NULL }; if (!in_transaction) return EINVAL; + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + + /* Check for the alias in the sysdb */ + filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME_ALIAS, member_name); + if (!filter) { + ret = ENOMEM; + goto fail; + } + + ret = sysdb_search_users(tmp_ctx, state->sysdb, filter, + attrs, &count, &msgs); + if (ret == EOK && count > 0) { + /* Entry exists but the group references it with an alias. */ + + if (count != 1) { + DEBUG(1, ("More than one entry with this alias?\n")); + ret = EIO; + goto fail; + } + + /* fill username with primary name */ + username = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL); + goto done; + } else if (ret != EOK && ret != ENOENT) { + ret = EIO; + goto fail; + } + + username = member_name; + /* The entry really does not exist, add a fake entry */ + DEBUG(7, ("Adding a dummy entry\n")); + if (!*in_transaction) { ret = sysdb_transaction_start(state->sysdb); if (ret != EOK) { @@ -885,27 +957,17 @@ sdap_process_missing_member_2307(struct sdap_process_group_state *state, * Convert the just received DN into the corresponding sysdb DN * for saving into member attribute of the group */ - dn = sysdb_user_dn(state->sysdb, state, state->dom->name, - (char*) username); - if (!dn) { - ret = ENOMEM; - goto fail; - } - - dn_string = ldb_dn_alloc_linearized(state->sysdb_dns->values, dn); - if (!dn_string) { - ret = ENOMEM; +done: + ret = sdap_add_group_member_2307(state, username); + if (ret != EOK) { + DEBUG(1, ("Could not add group member %s\n", username)); goto fail; } - state->sysdb_dns->values[state->sysdb_dns->num_values].data = - (uint8_t *) dn_string; - state->sysdb_dns->values[state->sysdb_dns->num_values].length = - strlen(dn_string); - state->sysdb_dns->num_values++; - + talloc_free(tmp_ctx); return EOK; fail: + talloc_free(tmp_ctx); if (*in_transaction) { sret = sysdb_transaction_cancel(state->sysdb); if (sret == EOK) { @@ -925,7 +987,6 @@ sdap_process_group_members_2307(struct sdap_process_group_state *state, struct ldb_message *msg; bool in_transaction = false; char *member_name; - char *strdn; int ret; errno_t sret; int i; @@ -939,23 +1000,17 @@ sdap_process_group_members_2307(struct sdap_process_group_state *state, ret = sysdb_search_user_by_name(state, state->sysdb, member_name, NULL, &msg); if (ret == EOK) { - strdn = sysdb_user_strdn(state->sysdb_dns->values, - state->dom->name, - member_name); - if (!strdn) { - ret = ENOMEM; + /* + * User already cached in sysdb. Remember the sysdb DN for later + * use by sdap_save_groups() + */ + DEBUG(7, ("Member already cached in sysdb: %s\n", member_name)); + + ret = sdap_add_group_member_2307(state, member_name); + if (ret != EOK) { + DEBUG(1, ("Could not add member %s into sysdb\n", member_name)); goto done; } - /* - * User already cached in sysdb. Remember the sysdb DN for later - * use by sdap_save_groups() - */ - DEBUG(7,("Member already cached in sysdb: %s\n", strdn)); - state->sysdb_dns->values[state->sysdb_dns->num_values].data = - (uint8_t *) strdn; - state->sysdb_dns->values[state->sysdb_dns->num_values].length = - strlen(strdn); - state->sysdb_dns->num_values++; } else if (ret == ENOENT) { /* The user is not in sysdb, need to add it */ DEBUG(7, ("member #%d (%s): not found in sysdb\n", diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index f5c37078..4cf5a53b 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -1851,6 +1851,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) switch (state->opts->schema_type) { case SDAP_SCHEMA_RFC2307: + ret = sdap_check_aliases(state->sysdb, state->orig_user, state->dom, + state->opts, false); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts, state->sysdb, state->dom, state->sh, dp_opt_get_string(state->opts->basic, diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c index 82338dc1..adf3cf4e 100644 --- a/src/providers/ldap/sdap_async_users.c +++ b/src/providers/ldap/sdap_async_users.c @@ -56,6 +56,7 @@ int sdap_save_user(TALLOC_CTX *memctx, char *usn_value = NULL; size_t c; char **missing = NULL; + const char **aliases = NULL; TALLOC_CTX *tmpctx = NULL; DEBUG(9, ("Save user\n")); @@ -282,6 +283,20 @@ int sdap_save_user(TALLOC_CTX *memctx, } } + ret = sysdb_attrs_get_aliases(tmpctx, attrs, name, &aliases); + if (ret != EOK) { + DEBUG(1, ("Failed to get the alias list")); + goto fail; + } + + for (i = 0; aliases[i]; i++) { + ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME_ALIAS, + aliases[i]); + if (ret) { + goto fail; + } + } + /* Make sure that any attributes we requested from LDAP that we * did not receive are also removed from the sysdb */ @@ -366,6 +381,12 @@ int sdap_save_users(TALLOC_CTX *memctx, DEBUG(9, ("User %d processed!\n", i)); } + ret = sdap_check_aliases(sysdb, users[i], dom, + opts, true); + if (ret) { + DEBUG(2, ("Failed to check aliases for user %d. Ignoring.\n", i)); + } + if (usn_value) { if (higher_usn) { if ((strlen(usn_value) > strlen(higher_usn)) || |