From 9091fdea936f7d21584682b7f3d58f49b1e7b013 Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Mon, 15 Aug 2022 05:38:55 -0400 Subject: Moved some functions in sdap_async_initgroups --- src/providers/ldap/sdap_async_initgroups.c | 1440 ++++++++++++++-------------- 1 file changed, 722 insertions(+), 718 deletions(-) (limited to 'src/providers') diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 8edda2e3..2191c133 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -231,7 +231,7 @@ done: return ret; } -/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */ +/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307===================== */ struct sdap_initgr_rfc2307_state { struct tevent_context *ev; @@ -970,404 +970,523 @@ static int sdap_initgr_nested_recv(struct tevent_req *req) return EOK; } +/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-BIS================= */ -/* ==Initgr-call-(groups-a-user-is-member-of)============================= */ - -struct sdap_get_initgr_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - struct sdap_handle *sh; - struct sdap_id_ctx *id_ctx; - const char *name; - const char **grp_attrs; - const char **ldap_attrs; - - struct sysdb_attrs *orig_user; -}; - -static void sdap_get_initgr_user(struct tevent_req *subreq); -static void sdap_get_initgr_done(struct tevent_req *subreq); +static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq); +static void sdap_initgr_rfc2307bis_done(struct tevent_req *subreq); +errno_t save_rfc2307bis_user_memberships( + struct sdap_initgr_rfc2307_state *state); +struct tevent_req *rfc2307bis_nested_groups_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct sdap_options *opts, struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, struct sdap_handle *sh, + struct sysdb_attrs **groups, size_t num_groups, + size_t nesting); +static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); -struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - struct sdap_id_ctx *id_ctx, - const char *name, - const char **grp_attrs) +static struct tevent_req *sdap_initgr_rfc2307bis_send( + TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_options *opts, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_handle *sh, + const char *base_dn, + const char *name, + const char *orig_dn) { - struct tevent_req *req, *subreq; - struct sdap_get_initgr_state *state; - const char *base_dn; - char *filter; - int ret; - char *clean_name; - - DEBUG(9, ("Retrieving info for initgroups call\n")); + errno_t ret; + struct tevent_req *req; + struct tevent_req *subreq; + struct sdap_initgr_rfc2307_state *state; + const char *filter; + const char **attrs; + char *clean_orig_dn; - req = tevent_req_create(memctx, &state, struct sdap_get_initgr_state); + req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state); if (!req) return NULL; state->ev = ev; - state->opts = id_ctx->opts; - state->sysdb = id_ctx->be->sysdb; - state->dom = id_ctx->be->domain; + state->opts = opts; + state->sysdb = sysdb; + state->dom = dom; state->sh = sh; - state->id_ctx = id_ctx; + state->op = NULL; state->name = name; - state->grp_attrs = grp_attrs; - state->orig_user = NULL; - ret = sss_filter_sanitize(state, name, &clean_name); + ret = build_attrs_from_map(state, opts->group_map, + SDAP_OPTS_GROUP, &attrs); if (ret != EOK) { + talloc_free(req); return NULL; } - filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", - state->opts->user_map[SDAP_AT_USER_NAME].name, - clean_name, - state->opts->user_map[SDAP_OC_USER].name); - if (!filter) { - talloc_zfree(req); - return NULL; - } - - base_dn = dp_opt_get_string(state->opts->basic, - SDAP_USER_SEARCH_BASE); - if (!base_dn) { - talloc_zfree(req); + ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn); + if (ret != EOK) { + talloc_free(req); return NULL; } - ret = build_attrs_from_map(state, state->opts->user_map, - SDAP_OPTS_USER, &state->ldap_attrs); - if (ret) { + filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*))", + opts->group_map[SDAP_AT_GROUP_MEMBER].name, + clean_orig_dn, + opts->group_map[SDAP_OC_GROUP].name, + opts->group_map[SDAP_AT_GROUP_NAME].name); + if (!filter) { talloc_zfree(req); return NULL; } + talloc_zfree(clean_orig_dn); - subreq = sdap_get_generic_send(state, state->ev, - state->opts, state->sh, - base_dn, LDAP_SCOPE_SUBTREE, - filter, state->ldap_attrs, - state->opts->user_map, SDAP_OPTS_USER, + DEBUG(6, ("Looking up parent groups for user [%s]\n", orig_dn)); + subreq = sdap_get_generic_send(state, state->ev, state->opts, + state->sh, base_dn, LDAP_SCOPE_SUBTREE, + filter, attrs, + state->opts->group_map, SDAP_OPTS_GROUP, dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT)); if (!subreq) { talloc_zfree(req); return NULL; } - tevent_req_set_callback(subreq, sdap_get_initgr_user, req); + tevent_req_set_callback(subreq, sdap_initgr_rfc2307bis_process, req); return req; + } -static struct tevent_req *sdap_initgr_rfc2307bis_send( - TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, - struct sdap_handle *sh, - const char *base_dn, - const char *name, - const char *orig_dn); -static void sdap_get_initgr_user(struct tevent_req *subreq) +static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - struct sysdb_attrs **usr_attrs; - size_t count; + struct tevent_req *req; + struct sdap_initgr_rfc2307_state *state; int ret; - const char *orig_dn; - DEBUG(9, ("Receiving info for the user\n")); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_initgr_rfc2307_state); - ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs); + ret = sdap_get_generic_recv(subreq, state, + &state->ldap_groups_count, + &state->ldap_groups); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); return; } - if (count != 1) { - DEBUG(2, ("Expected one user entry and got %d\n", count)); - tevent_req_error(req, ENOENT); + if (state->ldap_groups_count == 0) { + /* Start a transaction to look up the groups in the sysdb + * and update them with LDAP data + */ + ret = save_rfc2307bis_user_memberships(state); + if (ret != EOK) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } return; } - state->orig_user = usr_attrs[0]; - - ret = sysdb_transaction_start(state->sysdb); - if (ret) { - tevent_req_error(req, ret); + subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts, + state->sysdb, state->dom, + state->sh, state->ldap_groups, + state->ldap_groups_count, 0); + if (!subreq) { + tevent_req_error(req, EIO); return; } + tevent_req_set_callback(subreq, sdap_initgr_rfc2307bis_done, req); +} - DEBUG(9, ("Storing the user\n")); +static void sdap_initgr_rfc2307bis_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 = sdap_save_user(state, state->sysdb, - state->opts, state->dom, - state->orig_user, state->ldap_attrs, - true, NULL); - if (ret) { - sysdb_transaction_cancel(state->sysdb); + ret = rfc2307bis_nested_groups_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { tevent_req_error(req, ret); return; } - DEBUG(9, ("Commit change\n")); - - ret = sysdb_transaction_commit(state->sysdb); - if (ret) { + /* save the user memberships */ + ret = save_rfc2307bis_user_memberships(state); + if (ret != EOK) { tevent_req_error(req, ret); - return; + } else { + tevent_req_done(req); } + return; +} - DEBUG(9, ("Process user's groups\n")); +static int sdap_initgr_rfc2307bis_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} - switch (state->opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts, - state->sysdb, state->dom, state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - state->name); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - break; +errno_t save_rfc2307bis_user_memberships( + struct sdap_initgr_rfc2307_state *state) +{ + errno_t ret, tret; + char *member_dn; + char *sanitized_dn; + char *filter; + const char **attrs; + size_t reply_count, i; + struct ldb_message **replies; + char **ldap_grouplist; + char **sysdb_grouplist; + char **add_groups; + char **del_groups; + const char *tmp_str; + bool in_transaction = false; - case SDAP_SCHEMA_RFC2307BIS: - ret = sysdb_attrs_get_string(state->orig_user, - SYSDB_ORIG_DN, - &orig_dn); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + if(!tmp_ctx) { + return ENOMEM; + } - subreq = sdap_initgr_rfc2307bis_send( - state, state->ev, state->opts, state->sysdb, - state->dom, state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - state->name, orig_dn); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - talloc_steal(subreq, orig_dn); - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - break; - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - /* TODO: AD uses a different member/memberof schema - * We need an AD specific call that is able to unroll - * nested groups by doing extensive recursive searches */ - - subreq = sdap_initgr_nested_send(state, state->ev, state->opts, - state->sysdb, state->dom, state->sh, - state->orig_user, state->grp_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - return; + DEBUG(7, ("Save parent groups to sysdb\n")); + ret = sysdb_transaction_start(state->sysdb); + if (ret != EOK) { + goto error; + } + in_transaction = true; - default: - tevent_req_error(req, EINVAL); - return; + /* Save this user and their memberships */ + attrs = talloc_array(tmp_ctx, const char *, 2); + if (!attrs) { + ret = ENOMEM; + goto error; } -} -static int sdap_initgr_rfc2307bis_recv(struct tevent_req *req); -static void sdap_get_initgr_pgid(struct tevent_req *req); -static void sdap_get_initgr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - gid_t primary_gid; - char *gid; + attrs[0] = SYSDB_NAME; + attrs[1] = NULL; - DEBUG(9, ("Initgroups done\n")); + member_dn = sysdb_user_strdn(tmp_ctx, state->dom->name, state->name); + if (!member_dn) { + ret = ENOMEM; + goto error; + } + ret = sss_filter_sanitize(tmp_ctx, member_dn, &sanitized_dn); + if (ret != EOK) { + goto error; + } + talloc_free(member_dn); - switch (state->opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - ret = sdap_initgr_rfc2307_recv(subreq); - break; + filter = talloc_asprintf(tmp_ctx, "(member=%s)", sanitized_dn); + if (!filter) { + ret = ENOMEM; + goto error; + } + talloc_free(sanitized_dn); - case SDAP_SCHEMA_RFC2307BIS: - ret = sdap_initgr_rfc2307bis_recv(subreq); - break; + ret = sysdb_search_groups(tmp_ctx, state->sysdb, filter, attrs, + &reply_count, &replies); + if (ret != EOK && ret != ENOENT) { + goto error; + } if (ret == ENOENT) { + reply_count = 0; + } - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - ret = sdap_initgr_nested_recv(subreq); - break; + if (reply_count == 0) { + DEBUG(6, ("User [%s] is not a direct member of any groups\n", + state->name)); + sysdb_grouplist = NULL; + } else { + sysdb_grouplist = talloc_array(tmp_ctx, char *, reply_count+1); + if (!sysdb_grouplist) { + ret = ENOMEM; + goto error; + } - default: + for (i = 0; i < reply_count; i++) { + tmp_str = ldb_msg_find_attr_as_string(replies[i], + SYSDB_NAME, + NULL); + if (!tmp_str) { + /* This should never happen, but if it + * does, just skip it. + */ + continue; + } - ret = EINVAL; - break; + sysdb_grouplist[i] = talloc_strdup(sysdb_grouplist, tmp_str); + if (!sysdb_grouplist[i]) { + ret = ENOMEM; + goto error; + } + } + sysdb_grouplist[i] = NULL; } - talloc_zfree(subreq); - if (ret) { - DEBUG(9, ("Error in initgroups: [%d][%s]\n", - ret, strerror(ret))); - tevent_req_error(req, ret); - return; + if (state->ldap_groups_count == 0) { + ldap_grouplist = NULL; + } + else { + ret = sysdb_attrs_primary_name_list( + state->sysdb, tmp_ctx, + state->ldap_groups, state->ldap_groups_count, + state->opts->group_map[SDAP_AT_GROUP_NAME].name, + &ldap_grouplist); + if (ret != EOK) { + goto error; + } } - /* We also need to update the user's primary group, since - * the user may not be an explicit member of that group + /* 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 = sysdb_attrs_get_uint32_t(state->orig_user, SYSDB_GIDNUM, &primary_gid); + ret = diff_string_lists(tmp_ctx, + ldap_grouplist, sysdb_grouplist, + &add_groups, &del_groups, NULL); if (ret != EOK) { - DEBUG(6, ("Could not find user's primary GID\n")); - tevent_req_error(req, ret); - return; + goto error; } - gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid); - if (gid == NULL) { - tevent_req_error(req, ENOMEM); - return; + DEBUG(8, ("Updating memberships for %s\n", state->name)); + ret = sysdb_update_members(state->sysdb, state->name, SYSDB_MEMBER_USER, + (const char *const *)add_groups, + (const char *const *)del_groups); + if (ret != EOK) { + goto error; } - subreq = groups_get_send(req, state->ev, state->id_ctx, gid, - BE_FILTER_IDNUM, BE_ATTR_ALL); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; + ret = sysdb_transaction_commit(state->sysdb); + if (ret != EOK) { + goto error; } - tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req); - tevent_req_done(req); -} - -static void sdap_get_initgr_pgid(struct tevent_req *subreq) -{ - struct tevent_req *req = - tevent_req_callback_data(subreq, struct tevent_req); - errno_t ret; + return EOK; - ret = groups_get_recv(subreq, NULL); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; +error: + if (in_transaction) { + tret = sysdb_transaction_cancel(state->sysdb); + if (tret != EOK) { + DEBUG(1, ("Failed to cancel transaction\n")); + } } - - tevent_req_done(req); + talloc_free(tmp_ctx); + return ret; } -int sdap_get_initgr_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); +struct sdap_rfc2307bis_nested_ctx { + struct tevent_context *ev; + struct sdap_options *opts; + struct sysdb_ctx *sysdb; + struct sss_domain_info *dom; + struct sdap_handle *sh; + struct sysdb_attrs **groups; + size_t num_groups; - return EOK; -} + size_t nesting_level; -static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq); -static struct tevent_req *sdap_initgr_rfc2307bis_send( - TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, - struct sdap_handle *sh, - const char *base_dn, - const char *name, - const char *orig_dn) + size_t group_iter; + struct sysdb_attrs **ldap_groups; + size_t ldap_groups_count; + + struct sysdb_handle *handle; +}; + +static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req); +struct tevent_req *rfc2307bis_nested_groups_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct sdap_options *opts, struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, struct sdap_handle *sh, + struct sysdb_attrs **groups, size_t num_groups, + size_t nesting) { errno_t ret; struct tevent_req *req; - struct tevent_req *subreq; - struct sdap_initgr_rfc2307_state *state; - const char *filter; - const char **attrs; - char *clean_orig_dn; + struct sdap_rfc2307bis_nested_ctx *state; - req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state); + req = tevent_req_create(mem_ctx, &state, + struct sdap_rfc2307bis_nested_ctx); if (!req) return NULL; + if ((num_groups == 0) || + (nesting > dp_opt_get_int(opts->basic, SDAP_NESTING_LEVEL))) { + /* No parent groups to process or too deep*/ + tevent_req_done(req); + tevent_req_post(req, ev); + return req; + } + state->ev = ev; state->opts = opts; state->sysdb = sysdb; state->dom = dom; state->sh = sh; - state->op = NULL; - state->name = name; + state->groups = groups; + state->num_groups = num_groups; + state->group_iter = 0; + state->nesting_level = nesting; - ret = build_attrs_from_map(state, opts->group_map, - SDAP_OPTS_GROUP, &attrs); + ret = rfc2307bis_nested_groups_step(req); if (ret != EOK) { - talloc_free(req); - return NULL; + tevent_req_error(req, ret); + tevent_req_post(req, ev); } + return req; +} - ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn); +static void rfc2307bis_nested_groups_process(struct tevent_req *subreq); +static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) +{ + errno_t ret, tret; + struct tevent_req *subreq; + const char *name; + struct sysdb_attrs **grouplist; + char **groupnamelist; + bool in_transaction = false; + TALLOC_CTX *tmp_ctx = NULL; + char *filter; + const char *orig_dn; + const char **attrs; + char *clean_orig_dn; + struct sdap_rfc2307bis_nested_ctx *state = + tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); + + tmp_ctx = talloc_new(state); + if (!tmp_ctx) { + ret = ENOMEM; + goto error; + } + + ret = sysdb_attrs_primary_name( + state->sysdb, + state->groups[state->group_iter], + state->opts->group_map[SDAP_AT_GROUP_NAME].name, + &name); if (ret != EOK) { - talloc_free(req); - return NULL; + goto error; } - filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*))", - opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_orig_dn, - opts->group_map[SDAP_OC_GROUP].name, - opts->group_map[SDAP_AT_GROUP_NAME].name); + DEBUG(6, ("Processing group [%s]\n", name)); + + ret = sysdb_transaction_start(state->sysdb); + if (ret != EOK) { + goto error; + } + in_transaction = true; + + /* First, save the group we're processing to the sysdb + * sdap_add_incomplete_groups_send will add them if needed + */ + + /* sdap_add_incomplete_groups_send expects a list of groups */ + grouplist = talloc_array(tmp_ctx, struct sysdb_attrs *, 1); + if (!grouplist) { + ret = ENOMEM; + goto error; + } + grouplist[0] = state->groups[state->group_iter]; + + groupnamelist = talloc_array(tmp_ctx, char *, 2); + if (!groupnamelist) { + ret = ENOMEM; + goto error; + } + groupnamelist[0] = talloc_strdup(groupnamelist, name); + if (!groupnamelist[0]) { + ret = ENOMEM; + goto error; + } + groupnamelist[1] = NULL; + + DEBUG(6, ("Saving incomplete group [%s] to the sysdb\n", + groupnamelist[0])); + ret = sdap_add_incomplete_groups(state->sysdb, state->opts, + state->dom, groupnamelist, + grouplist, 1); + if (ret != EOK) { + goto error; + } + + ret = sysdb_transaction_commit(state->sysdb); + if (ret != EOK) { + goto error; + } + + /* Get any parent groups for this group */ + ret = sysdb_attrs_get_string(state->groups[state->group_iter], + SYSDB_ORIG_DN, + &orig_dn); + if (ret != EOK) { + goto error; + } + + ret = build_attrs_from_map(tmp_ctx, state->opts->group_map, + SDAP_OPTS_GROUP, &attrs); + if (ret != EOK) { + goto error; + } + + ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn); + if (ret != EOK) { + goto error; + } + + filter = talloc_asprintf( + tmp_ctx, "(&(%s=%s)(objectclass=%s)(%s=*))", + state->opts->group_map[SDAP_AT_GROUP_MEMBER].name, + clean_orig_dn, + state->opts->group_map[SDAP_OC_GROUP].name, + state->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!filter) { - talloc_zfree(req); - return NULL; + ret = ENOMEM; + goto error; } talloc_zfree(clean_orig_dn); - DEBUG(6, ("Looking up parent groups for user [%s]\n", orig_dn)); + DEBUG(6, ("Looking up parent groups for group [%s]\n", orig_dn)); subreq = sdap_get_generic_send(state, state->ev, state->opts, - state->sh, base_dn, LDAP_SCOPE_SUBTREE, + state->sh, + dp_opt_get_string(state->opts->basic, + SDAP_GROUP_SEARCH_BASE), + LDAP_SCOPE_SUBTREE, filter, attrs, state->opts->group_map, SDAP_OPTS_GROUP, dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT)); if (!subreq) { - talloc_zfree(req); - return NULL; + ret = EIO; + goto error; } - tevent_req_set_callback(subreq, sdap_initgr_rfc2307bis_process, req); + talloc_steal(subreq, tmp_ctx); + tevent_req_set_callback(subreq, + rfc2307bis_nested_groups_process, + req); - return req; + return EOK; + +error: + if (in_transaction) { + tret = sysdb_transaction_cancel(state->sysdb); + if (tret != EOK) { + DEBUG(1, ("Failed to cancel transaction\n")); + } + } + talloc_free(tmp_ctx); + return ret; } -errno_t save_rfc2307bis_user_memberships( - struct sdap_initgr_rfc2307_state *state); -struct tevent_req *rfc2307bis_nested_groups_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_options *opts, struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, struct sdap_handle *sh, - struct sysdb_attrs **groups, size_t num_groups, - size_t nesting); -static void sdap_initgr_rfc2307bis_done(struct tevent_req *subreq); -static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq) +static errno_t rfc2307bis_nested_groups_update_sysdb( + struct sdap_rfc2307bis_nested_ctx *state); +static void rfc2307bis_nested_groups_done(struct tevent_req *subreq); +static void rfc2307bis_nested_groups_process(struct tevent_req *subreq) { - struct tevent_req *req; - struct sdap_initgr_rfc2307_state *state; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_initgr_rfc2307_state); + errno_t ret; + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_rfc2307bis_nested_ctx *state = + tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); ret = sdap_get_generic_recv(subreq, state, &state->ldap_groups_count, @@ -1379,73 +1498,145 @@ static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq) } if (state->ldap_groups_count == 0) { - /* Start a transaction to look up the groups in the sysdb - * and update them with LDAP data + /* No parent groups for this group in LDAP + * We need to ensure that there are no groups + * in the sysdb either. */ - ret = save_rfc2307bis_user_memberships(state); + + ret = rfc2307bis_nested_groups_update_sysdb(state); if (ret != EOK) { tevent_req_error(req, ret); + return; + } + + state->group_iter++; + if (state->group_iter < state->num_groups) { + ret = rfc2307bis_nested_groups_step(req); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } } else { tevent_req_done(req); } return; } - subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts, - state->sysdb, state->dom, - state->sh, state->ldap_groups, - state->ldap_groups_count, 0); + /* Otherwise, recurse into the groups */ + subreq = rfc2307bis_nested_groups_send( + state, state->ev, state->opts, state->sysdb, + state->dom, state->sh, + state->ldap_groups, + state->ldap_groups_count, + state->nesting_level+1); if (!subreq) { tevent_req_error(req, EIO); return; } - tevent_req_set_callback(subreq, sdap_initgr_rfc2307bis_done, req); + tevent_req_set_callback(subreq, rfc2307bis_nested_groups_done, req); } -errno_t save_rfc2307bis_user_memberships( - struct sdap_initgr_rfc2307_state *state) +static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + +static void rfc2307bis_nested_groups_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_rfc2307bis_nested_ctx *state = + tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); + + ret = rfc2307bis_nested_groups_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(6, ("rfc2307bis_nested failed [%d][%s]\n", + ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + + /* All of the parent groups have been added + * Now add the memberships + */ + + ret = rfc2307bis_nested_groups_update_sysdb(state); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + state->group_iter++; + if (state->group_iter < state->num_groups) { + ret = rfc2307bis_nested_groups_step(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } + } else { + tevent_req_done(req); + } +} + +static errno_t rfc2307bis_nested_groups_update_sysdb( + struct sdap_rfc2307bis_nested_ctx *state) { errno_t ret, tret; + const char *name; + bool in_transaction = false; char *member_dn; char *sanitized_dn; char *filter; const char **attrs; size_t reply_count, i; struct ldb_message **replies; - char **ldap_grouplist; char **sysdb_grouplist; + char **ldap_grouplist; char **add_groups; char **del_groups; const char *tmp_str; - bool in_transaction = false; - TALLOC_CTX *tmp_ctx = talloc_new(NULL); - if(!tmp_ctx) { + TALLOC_CTX *tmp_ctx = talloc_new(state); + if (!tmp_ctx) { return ENOMEM; } - DEBUG(7, ("Save parent groups to sysdb\n")); + /* Start a transaction to look up the groups in the sysdb + * and update them with LDAP data + */ ret = sysdb_transaction_start(state->sysdb); if (ret != EOK) { goto error; } in_transaction = true; - /* Save this user and their memberships */ + ret = sysdb_attrs_primary_name( + state->sysdb, + state->groups[state->group_iter], + state->opts->group_map[SDAP_AT_GROUP_NAME].name, + &name); + if (ret != EOK) { + goto error; + } + + DEBUG(6, ("Processing group [%s]\n", name)); + attrs = talloc_array(tmp_ctx, const char *, 2); if (!attrs) { ret = ENOMEM; goto error; } - attrs[0] = SYSDB_NAME; attrs[1] = NULL; - member_dn = sysdb_user_strdn(tmp_ctx, state->dom->name, state->name); + member_dn = sysdb_group_strdn(tmp_ctx, state->dom->name, name); if (!member_dn) { ret = ENOMEM; goto error; } + ret = sss_filter_sanitize(tmp_ctx, member_dn, &sanitized_dn); if (ret != EOK) { goto error; @@ -1463,13 +1654,12 @@ errno_t save_rfc2307bis_user_memberships( &reply_count, &replies); if (ret != EOK && ret != ENOENT) { goto error; - } if (ret == ENOENT) { + } else if (ret == ENOENT) { reply_count = 0; } if (reply_count == 0) { - DEBUG(6, ("User [%s] is not a direct member of any groups\n", - state->name)); + DEBUG(6, ("Group [%s] is not a direct member of any groups\n", name)); sysdb_grouplist = NULL; } else { sysdb_grouplist = talloc_array(tmp_ctx, char *, reply_count+1); @@ -1516,15 +1706,17 @@ errno_t save_rfc2307bis_user_memberships( * Groups in ldap only must be added to the sysdb; * groups in the sysdb only must be removed. */ - ret = diff_string_lists(tmp_ctx, + ret = diff_string_lists(state, ldap_grouplist, sysdb_grouplist, &add_groups, &del_groups, NULL); if (ret != EOK) { goto error; } + talloc_free(ldap_grouplist); + talloc_free(sysdb_grouplist); - DEBUG(8, ("Updating memberships for %s\n", state->name)); - ret = sysdb_update_members(state->sysdb, state->name, SYSDB_MEMBER_USER, + DEBUG(8, ("Updating memberships for %s\n", name)); + ret = sysdb_update_members(state->sysdb, name, SYSDB_MEMBER_GROUP, (const char *const *)add_groups, (const char *const *)del_groups); if (ret != EOK) { @@ -1535,8 +1727,9 @@ errno_t save_rfc2307bis_user_memberships( if (ret != EOK) { goto error; } + in_transaction = false; - return EOK; + ret = EOK; error: if (in_transaction) { @@ -1549,501 +1742,312 @@ error: return ret; } -static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); -static void sdap_initgr_rfc2307bis_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 = rfc2307bis_nested_groups_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - /* save the user memberships */ - ret = save_rfc2307bis_user_memberships(state); - if (ret != EOK) { - tevent_req_error(req, ret); - } else { - tevent_req_done(req); - } - return; -} +/* ==Initgr-call-(groups-a-user-is-member-of)============================= */ -struct sdap_rfc2307bis_nested_ctx { +struct sdap_get_initgr_state { struct tevent_context *ev; - struct sdap_options *opts; struct sysdb_ctx *sysdb; + struct sdap_options *opts; struct sss_domain_info *dom; struct sdap_handle *sh; - struct sysdb_attrs **groups; - size_t num_groups; - - size_t nesting_level; - - size_t group_iter; - struct sysdb_attrs **ldap_groups; - size_t ldap_groups_count; + struct sdap_id_ctx *id_ctx; + const char *name; + const char **grp_attrs; + const char **ldap_attrs; - struct sysdb_handle *handle; + struct sysdb_attrs *orig_user; }; -static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req); -struct tevent_req *rfc2307bis_nested_groups_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct sdap_options *opts, struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, struct sdap_handle *sh, - struct sysdb_attrs **groups, size_t num_groups, - size_t nesting) +static void sdap_get_initgr_user(struct tevent_req *subreq); +static void sdap_get_initgr_done(struct tevent_req *subreq); + +struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, + const char *name, + const char **grp_attrs) { - errno_t ret; - struct tevent_req *req; - struct sdap_rfc2307bis_nested_ctx *state; + struct tevent_req *req, *subreq; + struct sdap_get_initgr_state *state; + const char *base_dn; + char *filter; + int ret; + char *clean_name; - req = tevent_req_create(mem_ctx, &state, - struct sdap_rfc2307bis_nested_ctx); - if (!req) return NULL; + DEBUG(9, ("Retrieving info for initgroups call\n")); - if ((num_groups == 0) || - (nesting > dp_opt_get_int(opts->basic, SDAP_NESTING_LEVEL))) { - /* No parent groups to process or too deep*/ - tevent_req_done(req); - tevent_req_post(req, ev); - return req; - } + req = tevent_req_create(memctx, &state, struct sdap_get_initgr_state); + if (!req) return NULL; state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; + state->opts = id_ctx->opts; + state->sysdb = id_ctx->be->sysdb; + state->dom = id_ctx->be->domain; state->sh = sh; - state->groups = groups; - state->num_groups = num_groups; - state->group_iter = 0; - state->nesting_level = nesting; + state->id_ctx = id_ctx; + state->name = name; + state->grp_attrs = grp_attrs; + state->orig_user = NULL; - ret = rfc2307bis_nested_groups_step(req); + ret = sss_filter_sanitize(state, name, &clean_name); if (ret != EOK) { - tevent_req_error(req, ret); - tevent_req_post(req, ev); + return NULL; + } + + filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", + state->opts->user_map[SDAP_AT_USER_NAME].name, + clean_name, + state->opts->user_map[SDAP_OC_USER].name); + if (!filter) { + talloc_zfree(req); + return NULL; + } + + base_dn = dp_opt_get_string(state->opts->basic, + SDAP_USER_SEARCH_BASE); + if (!base_dn) { + talloc_zfree(req); + return NULL; + } + + ret = build_attrs_from_map(state, state->opts->user_map, + SDAP_OPTS_USER, &state->ldap_attrs); + if (ret) { + talloc_zfree(req); + return NULL; + } + + subreq = sdap_get_generic_send(state, state->ev, + state->opts, state->sh, + base_dn, LDAP_SCOPE_SUBTREE, + filter, state->ldap_attrs, + state->opts->user_map, SDAP_OPTS_USER, + dp_opt_get_int(state->opts->basic, + SDAP_SEARCH_TIMEOUT)); + if (!subreq) { + talloc_zfree(req); + return NULL; } + tevent_req_set_callback(subreq, sdap_get_initgr_user, req); + return req; } -static void rfc2307bis_nested_groups_process(struct tevent_req *subreq); -static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) +static struct tevent_req *sdap_initgr_rfc2307bis_send( + TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_options *opts, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_handle *sh, + const char *base_dn, + const char *name, + const char *orig_dn); +static void sdap_get_initgr_user(struct tevent_req *subreq) { - errno_t ret, tret; - struct tevent_req *subreq; - const char *name; - struct sysdb_attrs **grouplist; - char **groupnamelist; - bool in_transaction = false; - TALLOC_CTX *tmp_ctx = NULL; - char *filter; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_initgr_state *state = tevent_req_data(req, + struct sdap_get_initgr_state); + struct sysdb_attrs **usr_attrs; + size_t count; + int ret; const char *orig_dn; - const char **attrs; - char *clean_orig_dn; - struct sdap_rfc2307bis_nested_ctx *state = - tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); - tmp_ctx = talloc_new(state); - if (!tmp_ctx) { - ret = ENOMEM; - goto error; + DEBUG(9, ("Receiving info for the user\n")); + + ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; } - ret = sysdb_attrs_primary_name( - state->sysdb, - state->groups[state->group_iter], - state->opts->group_map[SDAP_AT_GROUP_NAME].name, - &name); - if (ret != EOK) { - goto error; + if (count != 1) { + DEBUG(2, ("Expected one user entry and got %d\n", count)); + tevent_req_error(req, ENOENT); + return; } - DEBUG(6, ("Processing group [%s]\n", name)); + state->orig_user = usr_attrs[0]; ret = sysdb_transaction_start(state->sysdb); - if (ret != EOK) { - goto error; + if (ret) { + tevent_req_error(req, ret); + return; } - in_transaction = true; - /* First, save the group we're processing to the sysdb - * sdap_add_incomplete_groups_send will add them if needed - */ + DEBUG(9, ("Storing the user\n")); - /* sdap_add_incomplete_groups_send expects a list of groups */ - grouplist = talloc_array(tmp_ctx, struct sysdb_attrs *, 1); - if (!grouplist) { - ret = ENOMEM; - goto error; + ret = sdap_save_user(state, state->sysdb, + state->opts, state->dom, + state->orig_user, state->ldap_attrs, + true, NULL); + if (ret) { + sysdb_transaction_cancel(state->sysdb); + tevent_req_error(req, ret); + return; } - grouplist[0] = state->groups[state->group_iter]; - groupnamelist = talloc_array(tmp_ctx, char *, 2); - if (!groupnamelist) { - ret = ENOMEM; - goto error; - } - groupnamelist[0] = talloc_strdup(groupnamelist, name); - if (!groupnamelist[0]) { - ret = ENOMEM; - goto error; - } - groupnamelist[1] = NULL; - - DEBUG(6, ("Saving incomplete group [%s] to the sysdb\n", - groupnamelist[0])); - ret = sdap_add_incomplete_groups(state->sysdb, state->opts, - state->dom, groupnamelist, - grouplist, 1); - if (ret != EOK) { - goto error; - } + DEBUG(9, ("Commit change\n")); ret = sysdb_transaction_commit(state->sysdb); - if (ret != EOK) { - goto error; - } - - /* Get any parent groups for this group */ - ret = sysdb_attrs_get_string(state->groups[state->group_iter], - SYSDB_ORIG_DN, - &orig_dn); - if (ret != EOK) { - goto error; - } - - ret = build_attrs_from_map(tmp_ctx, state->opts->group_map, - SDAP_OPTS_GROUP, &attrs); - if (ret != EOK) { - goto error; - } - - ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn); - if (ret != EOK) { - goto error; - } - - filter = talloc_asprintf( - tmp_ctx, "(&(%s=%s)(objectclass=%s)(%s=*))", - state->opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_orig_dn, - state->opts->group_map[SDAP_OC_GROUP].name, - state->opts->group_map[SDAP_AT_GROUP_NAME].name); - if (!filter) { - ret = ENOMEM; - goto error; - } - talloc_zfree(clean_orig_dn); - - DEBUG(6, ("Looking up parent groups for group [%s]\n", orig_dn)); - subreq = sdap_get_generic_send(state, state->ev, state->opts, - state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - LDAP_SCOPE_SUBTREE, - filter, attrs, - state->opts->group_map, SDAP_OPTS_GROUP, - dp_opt_get_int(state->opts->basic, - SDAP_SEARCH_TIMEOUT)); - if (!subreq) { - ret = EIO; - goto error; - } - talloc_steal(subreq, tmp_ctx); - tevent_req_set_callback(subreq, - rfc2307bis_nested_groups_process, - req); - - return EOK; - -error: - if (in_transaction) { - tret = sysdb_transaction_cancel(state->sysdb); - if (tret != EOK) { - DEBUG(1, ("Failed to cancel transaction\n")); - } - } - - talloc_free(tmp_ctx); - return ret; -} - -static errno_t rfc2307bis_nested_groups_update_sysdb( - struct sdap_rfc2307bis_nested_ctx *state); -static void rfc2307bis_nested_groups_done(struct tevent_req *subreq); -static void rfc2307bis_nested_groups_process(struct tevent_req *subreq) -{ - errno_t ret; - struct tevent_req *req = - tevent_req_callback_data(subreq, struct tevent_req); - struct sdap_rfc2307bis_nested_ctx *state = - tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); - - ret = sdap_get_generic_recv(subreq, state, - &state->ldap_groups_count, - &state->ldap_groups); - talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); return; } - if (state->ldap_groups_count == 0) { - /* No parent groups for this group in LDAP - * We need to ensure that there are no groups - * in the sysdb either. - */ + DEBUG(9, ("Process user's groups\n")); - ret = rfc2307bis_nested_groups_update_sysdb(state); + switch (state->opts->schema_type) { + case SDAP_SCHEMA_RFC2307: + subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts, + state->sysdb, state->dom, state->sh, + dp_opt_get_string(state->opts->basic, + SDAP_GROUP_SEARCH_BASE), + state->name); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_get_initgr_done, req); + break; + + case SDAP_SCHEMA_RFC2307BIS: + ret = sysdb_attrs_get_string(state->orig_user, + SYSDB_ORIG_DN, + &orig_dn); if (ret != EOK) { tevent_req_error(req, ret); return; } - state->group_iter++; - if (state->group_iter < state->num_groups) { - ret = rfc2307bis_nested_groups_step(req); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - } else { - tevent_req_done(req); + subreq = sdap_initgr_rfc2307bis_send( + state, state->ev, state->opts, state->sysdb, + state->dom, state->sh, + dp_opt_get_string(state->opts->basic, + SDAP_GROUP_SEARCH_BASE), + state->name, orig_dn); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + talloc_steal(subreq, orig_dn); + tevent_req_set_callback(subreq, sdap_get_initgr_done, req); + break; + case SDAP_SCHEMA_IPA_V1: + case SDAP_SCHEMA_AD: + /* TODO: AD uses a different member/memberof schema + * We need an AD specific call that is able to unroll + * nested groups by doing extensive recursive searches */ + + subreq = sdap_initgr_nested_send(state, state->ev, state->opts, + state->sysdb, state->dom, state->sh, + state->orig_user, state->grp_attrs); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; } + tevent_req_set_callback(subreq, sdap_get_initgr_done, req); return; - } - /* Otherwise, recurse into the groups */ - subreq = rfc2307bis_nested_groups_send( - state, state->ev, state->opts, state->sysdb, - state->dom, state->sh, - state->ldap_groups, - state->ldap_groups_count, - state->nesting_level+1); - if (!subreq) { - tevent_req_error(req, EIO); + default: + tevent_req_error(req, EINVAL); return; } - tevent_req_set_callback(subreq, rfc2307bis_nested_groups_done, req); } -static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) +static int sdap_initgr_rfc2307bis_recv(struct tevent_req *req); +static void sdap_get_initgr_pgid(struct tevent_req *req); +static void sdap_get_initgr_done(struct tevent_req *subreq) { - TEVENT_REQ_RETURN_ON_ERROR(req); - return EOK; -} + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_get_initgr_state *state = tevent_req_data(req, + struct sdap_get_initgr_state); + int ret; + gid_t primary_gid; + char *gid; -static void rfc2307bis_nested_groups_done(struct tevent_req *subreq) -{ - errno_t ret; - struct tevent_req *req = - tevent_req_callback_data(subreq, struct tevent_req); - struct sdap_rfc2307bis_nested_ctx *state = - tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); + DEBUG(9, ("Initgroups done\n")); + + switch (state->opts->schema_type) { + case SDAP_SCHEMA_RFC2307: + ret = sdap_initgr_rfc2307_recv(subreq); + break; + + case SDAP_SCHEMA_RFC2307BIS: + ret = sdap_initgr_rfc2307bis_recv(subreq); + break; + + case SDAP_SCHEMA_IPA_V1: + case SDAP_SCHEMA_AD: + ret = sdap_initgr_nested_recv(subreq); + break; + + default: + + ret = EINVAL; + break; + } - ret = rfc2307bis_nested_groups_recv(subreq); talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(6, ("rfc2307bis_nested failed [%d][%s]\n", + if (ret) { + DEBUG(9, ("Error in initgroups: [%d][%s]\n", ret, strerror(ret))); tevent_req_error(req, ret); return; } - /* All of the parent groups have been added - * Now add the memberships + /* We also need to update the user's primary group, since + * the user may not be an explicit member of that group */ - - ret = rfc2307bis_nested_groups_update_sysdb(state); + ret = sysdb_attrs_get_uint32_t(state->orig_user, SYSDB_GIDNUM, &primary_gid); if (ret != EOK) { + DEBUG(6, ("Could not find user's primary GID\n")); tevent_req_error(req, ret); return; } - state->group_iter++; - if (state->group_iter < state->num_groups) { - ret = rfc2307bis_nested_groups_step(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } - } else { - tevent_req_done(req); - } -} - -static errno_t rfc2307bis_nested_groups_update_sysdb( - struct sdap_rfc2307bis_nested_ctx *state) -{ - errno_t ret, tret; - const char *name; - bool in_transaction = false; - char *member_dn; - char *sanitized_dn; - char *filter; - const char **attrs; - size_t reply_count, i; - struct ldb_message **replies; - char **sysdb_grouplist; - char **ldap_grouplist; - char **add_groups; - char **del_groups; - const char *tmp_str; - - TALLOC_CTX *tmp_ctx = talloc_new(state); - if (!tmp_ctx) { - return ENOMEM; - } - - /* Start a transaction to look up the groups in the sysdb - * and update them with LDAP data - */ - ret = sysdb_transaction_start(state->sysdb); - if (ret != EOK) { - goto error; - } - in_transaction = true; - - ret = sysdb_attrs_primary_name( - state->sysdb, - state->groups[state->group_iter], - state->opts->group_map[SDAP_AT_GROUP_NAME].name, - &name); - if (ret != EOK) { - goto error; - } - - DEBUG(6, ("Processing group [%s]\n", name)); - - attrs = talloc_array(tmp_ctx, const char *, 2); - if (!attrs) { - ret = ENOMEM; - goto error; - } - attrs[0] = SYSDB_NAME; - attrs[1] = NULL; - - member_dn = sysdb_group_strdn(tmp_ctx, state->dom->name, name); - if (!member_dn) { - ret = ENOMEM; - goto error; - } - - ret = sss_filter_sanitize(tmp_ctx, member_dn, &sanitized_dn); - if (ret != EOK) { - goto error; - } - talloc_free(member_dn); - - filter = talloc_asprintf(tmp_ctx, "(member=%s)", sanitized_dn); - if (!filter) { - ret = ENOMEM; - goto error; - } - talloc_free(sanitized_dn); - - ret = sysdb_search_groups(tmp_ctx, state->sysdb, filter, attrs, - &reply_count, &replies); - if (ret != EOK && ret != ENOENT) { - goto error; - } else if (ret == ENOENT) { - reply_count = 0; - } - - if (reply_count == 0) { - DEBUG(6, ("Group [%s] is not a direct member of any groups\n", name)); - sysdb_grouplist = NULL; - } else { - sysdb_grouplist = talloc_array(tmp_ctx, char *, reply_count+1); - if (!sysdb_grouplist) { - ret = ENOMEM; - goto error; - } - - for (i = 0; i < reply_count; i++) { - tmp_str = ldb_msg_find_attr_as_string(replies[i], - SYSDB_NAME, - NULL); - if (!tmp_str) { - /* This should never happen, but if it - * does, just skip it. - */ - continue; - } - - sysdb_grouplist[i] = talloc_strdup(sysdb_grouplist, tmp_str); - if (!sysdb_grouplist[i]) { - ret = ENOMEM; - goto error; - } - } - sysdb_grouplist[i] = NULL; + gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid); + if (gid == NULL) { + tevent_req_error(req, ENOMEM); + return; } - if (state->ldap_groups_count == 0) { - ldap_grouplist = NULL; - } - else { - ret = sysdb_attrs_primary_name_list( - state->sysdb, tmp_ctx, - state->ldap_groups, state->ldap_groups_count, - state->opts->group_map[SDAP_AT_GROUP_NAME].name, - &ldap_grouplist); - if (ret != EOK) { - goto error; - } + subreq = groups_get_send(req, state->ev, state->id_ctx, gid, + BE_FILTER_IDNUM, BE_ATTR_ALL); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; } + tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req); - /* 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, - ldap_grouplist, sysdb_grouplist, - &add_groups, &del_groups, NULL); - if (ret != EOK) { - goto error; - } - talloc_free(ldap_grouplist); - talloc_free(sysdb_grouplist); + tevent_req_done(req); +} - DEBUG(8, ("Updating memberships for %s\n", name)); - ret = sysdb_update_members(state->sysdb, name, SYSDB_MEMBER_GROUP, - (const char *const *)add_groups, - (const char *const *)del_groups); - if (ret != EOK) { - goto error; - } +static void sdap_get_initgr_pgid(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, struct tevent_req); + errno_t ret; - ret = sysdb_transaction_commit(state->sysdb); + ret = groups_get_recv(subreq, NULL); + talloc_zfree(subreq); if (ret != EOK) { - goto error; + tevent_req_error(req, ret); + return; } - in_transaction = false; - - ret = EOK; -error: - if (in_transaction) { - tret = sysdb_transaction_cancel(state->sysdb); - if (tret != EOK) { - DEBUG(1, ("Failed to cancel transaction\n")); - } - } - talloc_free(tmp_ctx); - return ret; + tevent_req_done(req); } -static int sdap_initgr_rfc2307bis_recv(struct tevent_req *req) +int sdap_get_initgr_recv(struct tevent_req *req) { TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; } + -- cgit