diff options
author | Petr Čech <pcech@redhat.com> | 2017-02-27 17:21:14 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-15 15:38:08 +0100 |
commit | ed2a5dad1ec82eda8a43ed8b0a05a6b01c3a6586 (patch) | |
tree | b9d1c98a805751883f58b6c6d2fb78263c6f0baa /src/providers | |
parent | 91b0592cdab22915dff27ceae6d8e49c608aea4a (diff) | |
download | sssd-ed2a5dad1ec82eda8a43ed8b0a05a6b01c3a6586.tar.gz sssd-ed2a5dad1ec82eda8a43ed8b0a05a6b01c3a6586.tar.xz sssd-ed2a5dad1ec82eda8a43ed8b0a05a6b01c3a6586.zip |
PROXY: Remove duplicit users from group
It is possible to have duplicit members in local files (/etc/group).
This patch removes duplicity in groups in proxy provider.
Resolves:
https://pagure.io/SSSD/sssd/issue/3314
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/proxy/proxy_id.c | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c index 9b83f7a3c..9e0ab2155 100644 --- a/src/providers/proxy/proxy_id.c +++ b/src/providers/proxy/proxy_id.c @@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <dhash.h> #include "config.h" #include "util/sss_format.h" @@ -574,6 +575,143 @@ done: } while(0) +static errno_t remove_duplicit_group_members(TALLOC_CTX *mem_ctx, + struct group *orig_grp, + struct group **_grp) +{ + TALLOC_CTX *tmp_ctx; + hash_table_t *member_tbl = NULL; + struct hash_iter_context_t *iter; + hash_entry_t *entry; + hash_key_t key; + hash_value_t value; + struct group *grp; + size_t orig_member_count= 0; + size_t member_count= 0; + size_t i; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n"); + return ENOMEM; + } + + if (orig_grp->gr_mem == NULL) { + ret = ENOENT; + goto done; + } + + for (i=0; orig_grp->gr_mem[i] != NULL; i++) { + orig_member_count++; + } + + if (orig_member_count == 0) { + ret = ENOENT; + goto done; + } + + ret = sss_hash_create(tmp_ctx, orig_member_count, &member_tbl); + if (ret != HASH_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create hash table.\n"); + ret = ENOMEM; + goto done; + } + + for (i=0; orig_grp->gr_mem[i] != NULL; i++) { + key.type = HASH_KEY_STRING; + key.str = talloc_strdup(member_tbl, orig_grp->gr_mem[i]); + if (key.str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + + value.type = HASH_VALUE_PTR; + value.ptr = talloc_strdup(member_tbl, orig_grp->gr_mem[i]); + if (key.str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = hash_enter(member_tbl, &key, &value); + if (ret != HASH_SUCCESS) { + talloc_free(key.str); + ret = ENOMEM; + goto done; + } + } + + member_count = hash_count(member_tbl); + if (member_count == 0) { + ret = ENOENT; + goto done; + } + + grp = talloc(mem_ctx, struct group); + if (grp == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n"); + ret = ENOMEM; + goto done; + } + + grp->gr_mem = talloc_zero_array(grp, char *, member_count + 1); + if (grp->gr_mem == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); + ret = ENOMEM; + goto done; + } + + iter = new_hash_iter_context(member_tbl); + if (iter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "new_hash_iter_context failed.\n"); + ret = EINVAL; + goto done; + } + + i = 0; + while ((entry = iter->next(iter)) != NULL) { + grp->gr_mem[i] = talloc_strdup(grp, entry->key.str); + if (grp->gr_mem[i] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + i++; + } + grp->gr_mem[i] = NULL; + + grp->gr_gid = orig_grp->gr_gid; + + grp->gr_name = talloc_strdup(grp, orig_grp->gr_name); + if (grp->gr_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + + grp->gr_passwd = talloc_strdup(grp, orig_grp->gr_passwd); + if (grp->gr_passwd == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + + *_grp = talloc_steal(mem_ctx, grp); + ret = EOK; + +done: + talloc_zfree(tmp_ctx); + + if (ret == ENOENT) { + *_grp = talloc_steal(mem_ctx, orig_grp); + ret = EOK; + } + + return ret; +} + static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, struct sysdb_attrs *group_attrs, @@ -585,6 +723,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, const char *alias) /* already qualified */ { errno_t ret, sret; + struct group *ngroup = NULL; struct sysdb_attrs *attrs = NULL; TALLOC_CTX *tmp_ctx; time_t now = time(NULL); @@ -596,7 +735,13 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, return ENOMEM; } - DEBUG_GR_MEM(SSSDBG_TRACE_LIBS, grp); + ret = remove_duplicit_group_members(tmp_ctx, grp, &ngroup); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to remove duplicit group members\n"); + goto done; + } + + DEBUG_GR_MEM(SSSDBG_TRACE_LIBS, ngroup); ret = sysdb_transaction_start(sysdb); if (ret != EOK) { @@ -605,7 +750,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, } in_transaction = true; - if (grp->gr_mem && grp->gr_mem[0]) { + if (ngroup->gr_mem && ngroup->gr_mem[0]) { attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n"); @@ -615,7 +760,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, fq_gr_mem = sss_create_internal_fqname_list( tmp_ctx, - (const char *const*) grp->gr_mem, + (const char *const*) ngroup->gr_mem, dom->name); if (fq_gr_mem == NULL) { ret = ENOMEM; @@ -647,7 +792,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, ret = sysdb_store_group(dom, real_name, - grp->gr_gid, + ngroup->gr_gid, attrs, dom->group_timeout, now); |