Hi, Is it really the intended behaviour of the sssd LDAP backend (I am running the current code from the master branch) to only return the group members that are already cached in sysdb and to silently ignore everything else? E.g. when I start sssd with empty caches and do a "getent group <random-ldap-group>" I will only get back the group without any members. Somehow I think this can't be intended :)
I have started working on a patch to let sssd look up the non-cached users via LDAP (and save them into the cache). Find it attached. Note: That patch is not really complete (e.g. it doesn't handle rfc2307 groups correctly). But before putting more effort into this I like to make sure that I am not trying to fix a "feature" here. -- regards, Ralf
From 063dab6715f97aeeb6c29f5c3210f609cfea0f81 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp <rha...@suse.de> Date: Wed, 8 Sep 2010 10:30:03 +0200 Subject: [PATCH] Return all group members from getgr(nam|gid) getgrnam()/getgrgid() should return all group members instead of only those which have already been cached (in sysdb). To achieve this every member that is currently not in the cache is looked up via LDAP and saved to the cache. --- src/providers/ldap/sdap_async_accounts.c | 177 ++++++++++++++++++++++++++++-- 1 files changed, 169 insertions(+), 8 deletions(-) diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c index 8999ba0..795c7ca 100644 --- a/src/providers/ldap/sdap_async_accounts.c +++ b/src/providers/ldap/sdap_async_accounts.c @@ -4,6 +4,7 @@ Async LDAP Helper routines Copyright (C) Simo Sorce <sso...@redhat.com> - 2009 + Copyright (C) 2010, Ralf Haferkamp <rha...@suse.de>, Novell Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -917,6 +918,20 @@ struct sdap_get_groups_state { char *higher_timestamp; struct sysdb_attrs **groups; size_t count; + size_t check_count; +}; + +struct sdap_process_group_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; + struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; + + struct sysdb_attrs *group; + struct sysdb_attrs **new_members; + size_t count; + size_t check_count; }; static void sdap_get_groups_process(struct tevent_req *subreq); @@ -962,13 +977,22 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, return req; } +static void sdap_groupmember_process(struct tevent_req *subreq); +static void sdap_group_process(struct tevent_req *subreq); + static void sdap_get_groups_process(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sdap_get_groups_state *state = tevent_req_data(req, struct sdap_get_groups_state); - int ret; + struct tevent_req *process_member_req; + struct tevent_req *process_grp_req; + struct ldb_message_element *el; + struct sdap_process_group_state *grp_state; + const char **attrs; + char *filter; + int ret,i,k; ret = sdap_get_generic_recv(subreq, state, &state->count, &state->groups); @@ -985,19 +1009,156 @@ static void sdap_get_groups_process(struct tevent_req *subreq) return; } - ret = sdap_save_groups(state, state->sysdb, - state->dom, state->opts, - state->groups, state->count, - &state->higher_timestamp); + state->check_count = state->count; + + ret = build_attrs_from_map(state, state->opts->user_map, SDAP_OPTS_USER, + &attrs); + filter = talloc_asprintf(state, "(objectclass=%s)", + state->opts->user_map[SDAP_OC_USER].name); + + for (i=0; i < state->count; i++) { + ret = sysdb_attrs_get_el(state->groups[i], + state->opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el); + if (ret || el->num_values == 0) { + tevent_req_error(req, ENOENT); + return; + } + + DEBUG(2, ("Processing Group %s\n", (const char*)el->values[0].data)); + process_grp_req = tevent_req_create(state, &grp_state, + struct sdap_process_group_state); + if (!process_grp_req) { + tevent_req_error(req, ENOMEM); + return; + } + + grp_state->ev = state->ev; + grp_state->opts = state->opts; + grp_state->dom = state->dom; + grp_state->sh = state->sh; + grp_state->sysdb = state->sysdb; + grp_state->group = state->groups[i]; + grp_state->check_count = 0; + grp_state->new_members = NULL; + tevent_req_set_callback(process_grp_req, sdap_group_process, req); + + ret = sysdb_attrs_get_el(state->groups[i], + state->opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); + if (ret) { + /* FIXME: Is this really the correct thing todo? */ + tevent_req_error(req, ENOENT); + return; + } + + /* + * For each member check if it is already present in sysdb, + * if it isn't read it from LDAP + */ + for (k=0; k < el->num_values; k++) { + char *tmp; + DEBUG(7, ("checking member: %s\n", + (const char*)el->values[k].data)); + ret = sdap_find_entry_by_origDN(grp_state, grp_state->sysdb, + grp_state->dom, + (const char *)el->values[k].data, + &tmp); + if (ret == ENOENT) { + DEBUG(7, (" member #%d (%s): not found in sysdb, searching LDAP\n", + k, (char *)el->values[k].data)); + grp_state->check_count++; + process_member_req = sdap_get_generic_send(grp_state, + grp_state->ev, + grp_state->opts, + grp_state->sh, + (char *)el->values[k].data, + LDAP_SCOPE_BASE, + filter, + attrs, + grp_state->opts->user_map, + SDAP_OPTS_USER); + tevent_req_set_callback(process_member_req, sdap_groupmember_process, + process_grp_req); + } + } + + if (grp_state->check_count == 0) { + /* + * All group members are already cached in sysdb, we are done + * with this group + */ + tevent_req_done(process_grp_req); + } else { + grp_state->count = grp_state->check_count; + grp_state->new_members = talloc_zero_array(grp_state, + struct sysdb_attrs *, + grp_state->count + 1); + } + } +} + +static void sdap_groupmember_process(struct tevent_req *subreq) +{ + struct sysdb_attrs **usr_attrs; + size_t count; + int ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_process_group_state *state = tevent_req_data(req, + struct sdap_process_group_state); + + state->check_count--; + DEBUG(9, ("Members remaining: %d\n", state->check_count)); + + ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs); + talloc_zfree(subreq); if (ret) { - DEBUG(2, ("Failed to store groups.\n")); tevent_req_error(req, ret); return; } - DEBUG(9, ("Saving %d Groups - Done\n", state->count)); + if (count != 1) { + DEBUG(2, ("Expected one user entry and got %d\n", count)); + tevent_req_error(req, ENOENT); + return; + } - tevent_req_done(req); + state->new_members[ state->check_count ] = usr_attrs[0]; + + if (state->check_count == 0) { + ret = sdap_save_users(state, state->sysdb, state->dom, state->opts, + state->new_members, state->count, NULL); + DEBUG(9, ("Processed Group - Done\n")); + tevent_req_done(req); + } +} + +static void sdap_group_process(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_groups_state *state = tevent_req_data(req, + struct sdap_get_groups_state); + + state->check_count--; + DEBUG(9, ("Groups remaining: %d\n", state->check_count)); + + talloc_zfree(subreq); + + if (state->check_count == 0) { + int ret; + DEBUG(9, ("All groups processed\n")); + + ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, + state->groups, state->count, + &state->higher_timestamp); + if (ret) { + DEBUG(2, ("Failed to store groups.\n")); + tevent_req_error(req, ret); + return; + } + DEBUG(9, ("Saving %d Groups - Done\n", state->count)); + tevent_req_done(req); + } } int sdap_get_groups_recv(struct tevent_req *req, -- 1.7.1
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel