summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-07-30 08:57:15 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-07-30 15:57:58 -0400
commitb47a7c2697dde7a8a2ef937554ee8146491b7e57 (patch)
treecdaabcf0e421cdf4b525cc5d8144afde1ceb8727
parent41edee286a924ec00ed9b9fc8a9cb37539fc6237 (diff)
downloadsssd-b47a7c2697dde7a8a2ef937554ee8146491b7e57.tar.gz
sssd-b47a7c2697dde7a8a2ef937554ee8146491b7e57.tar.xz
sssd-b47a7c2697dde7a8a2ef937554ee8146491b7e57.zip
Clean up initgroups processing for RFC2307
Instead of recursively updating all users of each group the user being queried belongs to, just add or remove membership for the requested user. Fixes https://fedorahosted.org/sssd/ticket/478
-rw-r--r--src/providers/ldap/sdap_async_accounts.c212
1 files changed, 196 insertions, 16 deletions
diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 384936db4..beab326a0 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -1485,12 +1485,17 @@ struct sdap_initgr_rfc2307_state {
struct sdap_options *opts;
struct sss_domain_info *dom;
struct sdap_handle *sh;
+ char *name;
+
+ struct sysdb_handle *handle;
+ char **ldap_grouplist;
struct sdap_op *op;
};
static void sdap_initgr_rfc2307_process(struct tevent_req *subreq);
-static void sdap_initgr_rfc2307_done(struct tevent_req *subreq);
+
+static
struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_options *opts,
@@ -1498,12 +1503,12 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct sdap_handle *sh,
const char *base_dn,
- const char *name,
- const char **grp_attrs)
+ const char *name)
{
struct tevent_req *req, *subreq;
struct sdap_initgr_rfc2307_state *state;
const char *filter;
+ const char *attrs[2];
req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state);
if (!req) return NULL;
@@ -1514,6 +1519,18 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
state->dom = dom;
state->sh = sh;
state->op = NULL;
+ state->name = talloc_strdup(state, name);
+ if (!state->name) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ attrs[0] = talloc_strdup(state, opts->group_map[SDAP_AT_GROUP_NAME].name);
+ if (!attrs[0]) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ attrs[1] = NULL;
filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
opts->group_map[SDAP_AT_GROUP_MEMBER].name,
@@ -1525,7 +1542,7 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
subreq = sdap_get_generic_send(state, state->ev, state->opts,
state->sh, base_dn, LDAP_SCOPE_SUBTREE,
- filter, grp_attrs,
+ filter, attrs,
state->opts->group_map, SDAP_OPTS_GROUP);
if (!subreq) {
talloc_zfree(req);
@@ -1536,6 +1553,7 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
return req;
}
+static void sdap_initgr_rfc2307_get_sysdb_groups(struct tevent_req *subreq);
static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
{
struct tevent_req *req;
@@ -1555,34 +1573,196 @@ static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
}
if (count == 0) {
- tevent_req_done(req);
- return;
+ /* No groups for this user in LDAP
+ * We need to ensure that there are no groups
+ * in the sysdb either.
+ */
+
+ state->ldap_grouplist = NULL;
+ }
+ else {
+ ret = sysdb_attrs_to_list(state, groups, count,
+ state->opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &state->ldap_grouplist);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
}
+ /* Start a transaction to look up the groups in the sysdb
+ * and update them with LDAP data
+ */
- subreq = sdap_save_groups_send(state, state->ev, state->dom,
- state->sysdb, state->opts,
- groups, count);
+ subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
if (!subreq) {
- tevent_req_error(req, ENOMEM);
+ tevent_req_error(req, EIO);
return;
}
- tevent_req_set_callback(subreq, sdap_initgr_rfc2307_done, req);
+ tevent_req_set_callback(subreq,
+ sdap_initgr_rfc2307_get_sysdb_groups,
+ req);
}
-static void sdap_initgr_rfc2307_done(struct tevent_req *subreq)
+static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq);
+static void sdap_initgr_rfc2307_get_sysdb_groups(struct tevent_req *subreq)
{
- struct tevent_req *req;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_initgr_rfc2307_state *state =
+ tevent_req_data(req, struct sdap_initgr_rfc2307_state);
int ret;
+ const char **attrs;
- req = tevent_req_callback_data(subreq, struct tevent_req);
+ ret = sysdb_transaction_recv(subreq, state, &state->handle);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- ret = sdap_save_groups_recv(subreq, NULL, NULL);
+ attrs = talloc_array(state, const char *, 2);
+ if (!attrs) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ attrs[0] = SYSDB_MEMBEROF;
+ attrs[1] = NULL;
+
+ /* Search for all groups for which this user is a member */
+ subreq = sysdb_search_user_by_name_send(state, state->ev, state->sysdb,
+ state->handle, state->dom,
+ state->name, attrs);
+ if (!subreq) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(subreq,
+ sdap_initgr_rfc2307_update_sysdb_groups,
+ req);
+}
+
+static void
+sdap_initgr_rfc2307_update_sysdb_groups_done(struct tevent_req *subreq);
+static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_initgr_rfc2307_state *state =
+ tevent_req_data(req, struct sdap_initgr_rfc2307_state);
+ int ret, i;
+ struct ldb_message *reply;
+ struct ldb_message_element *groups;
+ char **sysdb_grouplist;
+ char **add_groups;
+ char **del_groups;
+
+ ret = sysdb_search_user_recv(subreq, state, &reply);
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
return;
}
+ groups = ldb_msg_find_element(reply, SYSDB_MEMBEROF);
+ if (!groups || groups->num_values == 0) {
+ DEBUG(6, ("User is not a member of any groups\n"));
+
+ tevent_req_done(req);
+ return;
+ }
+
+ sysdb_grouplist = talloc_array(state, char *,
+ groups->num_values+1);
+ if (!sysdb_grouplist) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ /* Get a list of the groups by groupname only */
+ for (i=0; i < groups->num_values; i++) {
+ ret = sysdb_group_dn_name(state->sysdb,
+ sysdb_grouplist,
+ (const char *)groups->values[i].data,
+ &sysdb_grouplist[i]);
+ if (ret != EOK) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ }
+
+ sysdb_grouplist[groups->num_values] = NULL;
+
+ /* Find the differences between the sysdb and ldap lists
+ * Groups in ldap only must be added to the sysdb;
+ * groups in the sysdb only must be removed.
+ */
+ ret = diff_string_lists(state,
+ state->ldap_grouplist, sysdb_grouplist,
+ &add_groups, &del_groups, NULL);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sysdb_update_members_send(state, state->ev, state->handle,
+ state->dom, state->name,
+ add_groups, del_groups);
+ if (!subreq) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(subreq,
+ sdap_initgr_rfc2307_update_sysdb_groups_done,
+ req);
+}
+
+static void
+sdap_initgr_rfc2307_transaction_done(struct tevent_req *subreq);
+static void
+sdap_initgr_rfc2307_update_sysdb_groups_done(struct tevent_req *subreq)
+{
+ errno_t ret;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_initgr_rfc2307_state *state =
+ tevent_req_data(req, struct sdap_initgr_rfc2307_state);
+
+ ret = sysdb_update_members_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Commit the transaction */
+ subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
+ if (!subreq) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(subreq,
+ sdap_initgr_rfc2307_transaction_done,
+ req);
+}
+
+static void
+sdap_initgr_rfc2307_transaction_done(struct tevent_req *subreq)
+{
+ errno_t ret;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sysdb_transaction_commit_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Processing completed. Return control to sdap_get_initgr_done() */
tevent_req_done(req);
}
@@ -1988,7 +2168,7 @@ static void sdap_get_initgr_process(struct tevent_req *subreq)
state->sysdb, state->dom, state->sh,
dp_opt_get_string(state->opts->basic,
SDAP_GROUP_SEARCH_BASE),
- state->name, state->grp_attrs);
+ state->name);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;