diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/providers/ldap/sdap_async.c | 1066 |
1 files changed, 473 insertions, 593 deletions
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index 63445f55..a5d1f718 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -1294,7 +1294,6 @@ struct sdap_save_user_state { struct tevent_context *ev; struct sysdb_handle *handle; struct sdap_options *opts; - struct sdap_handle *sh; struct sss_domain_info *dom; @@ -1312,7 +1311,6 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, struct sysdb_handle *handle, struct sdap_options *opts, struct sss_domain_info *dom, - struct sdap_handle *sh, struct sysdb_attrs *attrs) { struct tevent_req *req, *subreq; @@ -1338,7 +1336,6 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, state->ev = ev; state->handle = handle; - state->sh = sh; state->dom = dom; state->opts = opts; state->attrs = attrs; @@ -1584,76 +1581,6 @@ static int sdap_save_user_recv(struct tevent_req *req, /* ==Group-Parsing Routines=============================================== */ -struct sdap_grp_members { - struct sdap_grp_members *prev, *next; - - char *name; - char *dn; - struct ldb_val *member_dns; - int num_mem_dns; -}; - -/* this function steals memory from "attrs", but does not modify its - * pointers. Make sure that's ok with what the caller expects */ -static int sdap_get_groups_save_membership(TALLOC_CTX *memctx, - struct sdap_options *opts, - struct sysdb_attrs *attrs, - struct sdap_grp_members **list) -{ - struct sdap_grp_members *m; - struct ldb_message_element *el; - int ret; - - m = talloc_zero(memctx, struct sdap_grp_members); - if (!m) { - return ENOMEM; - } - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el); - if (ret != EOK) { - goto fail; - } - - m->name = talloc_steal(m, (char *)el->values[0].data); - if (!m->name) { - ret = ENOMEM; - goto fail; - } - - ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); - if (ret != EOK) { - goto fail; - } - m->dn = talloc_steal(m, (char *)el->values[0].data); - if (!m->dn) { - ret = ENOMEM; - goto fail; - } - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); - if (ret != EOK) { - goto fail; - } - if (el->num_values) { - m->member_dns = talloc_steal(m, el->values); - if (!m->member_dns) { - ret = ENOMEM; - goto fail; - } - } - m->num_mem_dns = el->num_values; - - DLIST_ADD(*list, m); - - return EOK; - -fail: - talloc_free(m); - return ret; -} - static int sdap_parse_memberships(TALLOC_CTX *memctx, struct sysdb_handle *handle, struct sdap_options *opts, @@ -1878,140 +1805,6 @@ done: return ret; } -/* ==Save-Groups-Members================================================== */ - -struct sdap_set_members_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sdap_options *opts; - - struct sss_domain_info *dom; - - struct sdap_grp_members *curmem; -}; - -static void sdap_set_members_done(struct tevent_req *subreq); -static struct tevent_req *sdap_set_grpmem_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sdap_grp_members *gm); -static struct tevent_req *sdap_set_members_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sdap_grp_members *m) -{ - struct tevent_req *req, *subreq; - struct sdap_set_members_state *state; - - DEBUG(9, ("Now setting group members.\n")); - - req = tevent_req_create(memctx, &state, struct sdap_set_members_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->dom = dom; - state->opts = opts; - state->curmem = m; - - subreq = sdap_set_grpmem_send(state, state->ev, state->handle, - state->opts, state->dom, - state->curmem); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - return NULL; - } - tevent_req_set_callback(subreq, sdap_set_members_done, req); - - return req; -} - -static struct tevent_req *sdap_set_grpmem_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sdap_grp_members *gm) -{ - struct tevent_req *subreq; - const char **member_groups = NULL; - const char **member_users = NULL; - int ret; - - DEBUG(7, ("Adding member users to group [%s]\n", gm->name)); - - ret = sdap_parse_memberships(memctx, handle, opts, - gm->member_dns, - gm->num_mem_dns, - &member_users, &member_groups); - if (ret != EOK) { - return NULL; - } - - subreq = sysdb_store_group_send(memctx, ev, handle, dom, - gm->name, 0, - member_users, member_groups, NULL, - dp_opt_get_int(opts->basic, - SDAP_ENTRY_CACHE_TIMEOUT)); - - /* steal members on subreq, - * so they are freed when the request is finished */ - talloc_steal(subreq, member_users); - talloc_steal(subreq, member_groups); - - return subreq; -} - -static void sdap_set_members_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_set_members_state *state = tevent_req_data(req, - struct sdap_set_members_state); - int ret; - - ret = sysdb_store_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to store group members for %s. Ignoring\n", - state->curmem->name)); - } - - if (state->curmem->next) { - state->curmem = state->curmem->next; - - subreq = sdap_set_grpmem_send(state, state->ev, state->handle, - state->opts, state->dom, - state->curmem); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_set_members_done, req); - return; - } - - tevent_req_done(req); -} - -static int sdap_set_members_recv(struct tevent_req *req) -{ - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(req, &tstate, &err)) { - if (err) return err; - return EIO; - } - - return EOK; -} - /* ==Save-Group-Entry===================================================== */ struct sdap_save_group_state { @@ -2212,195 +2005,235 @@ static int sdap_save_group_recv(struct tevent_req *req, } -/* ==Search-Users-with-filter============================================= */ +/* ==Save-Group-Memebrs=================================================== */ -struct sdap_get_users_state { +struct sdap_save_grpmem_state { struct tevent_context *ev; + struct sysdb_handle *handle; struct sdap_options *opts; - struct sdap_handle *sh; - struct sss_domain_info *dom; - const char **attrs; - const char *filter; - struct sysdb_handle *handle; - struct sdap_op *op; + struct sss_domain_info *dom; - char *higher_timestamp; + const char *name; }; -static void sdap_get_users_transaction(struct tevent_req *subreq); -static void sdap_get_users_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); -static void sdap_get_users_save_done(struct tevent_req *subreq); +static void sdap_save_grpmem_done(struct tevent_req *subreq); -struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char **attrs, - const char *filter) + /* FIXME: support non legacy */ + /* FIXME: support storing additional attributes */ + +static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sdap_options *opts, + struct sss_domain_info *dom, + struct sysdb_attrs *attrs) { struct tevent_req *req, *subreq; - struct sdap_get_users_state *state; + struct sdap_save_grpmem_state *state; + struct ldb_message_element *el; + const char **member_groups = NULL; + const char **member_users = NULL; + int ret; - req = tevent_req_create(memctx, &state, struct sdap_get_users_state); + req = tevent_req_create(memctx, &state, struct sdap_save_grpmem_state); if (!req) return NULL; state->ev = ev; - state->opts = opts; + state->handle = handle; state->dom = dom; - state->sh = sh; - state->filter = filter; - state->attrs = attrs; - state->higher_timestamp = NULL; + state->opts = opts; - subreq = sysdb_transaction_send(state, state->ev, sysdb); - if (!subreq) return NULL; - tevent_req_set_callback(subreq, sdap_get_users_transaction, req); + ret = sysdb_attrs_get_string(attrs, + opts->group_map[SDAP_AT_GROUP_NAME].sys_name, + &state->name); + if (ret != EOK) { + goto fail; + } + ret = sysdb_attrs_get_el(attrs, + opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); + if (ret != EOK) { + goto fail; + } + if (el->num_values == 0) { + DEBUG(7, ("No members for group [%s]\n", state->name)); + + } else { + DEBUG(7, ("Adding member users to group [%s]\n", state->name)); + + ret = sdap_parse_memberships(state, handle, opts, + el->values, el->num_values, + &member_users, &member_groups); + if (ret) { + goto fail; + } + } + + DEBUG(6, ("Storing members for group %s\n", state->name)); + + subreq = sysdb_store_group_send(state, state->ev, + state->handle, state->dom, + state->name, 0, + member_users, member_groups, + NULL, + dp_opt_get_int(opts->basic, + SDAP_ENTRY_CACHE_TIMEOUT)); + if (!subreq) { + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sdap_save_grpmem_done, req); + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); return req; } -static void sdap_get_users_transaction(struct tevent_req *subreq) +static void sdap_save_grpmem_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); - int lret, ret; - int msgid; + struct sdap_save_grpmem_state *state = tevent_req_data(req, + struct sdap_save_grpmem_state); + int ret; - ret = sysdb_transaction_recv(subreq, state, &state->handle); + ret = sysdb_store_group_recv(subreq); talloc_zfree(subreq); if (ret) { + DEBUG(2, ("Failed to save group members for %s [%d]\n", + state->name, ret)); tevent_req_error(req, ret); return; } - DEBUG(5, ("calling ldap_search_ext with [%s].\n", state->filter)); + tevent_req_done(req); +} - lret = ldap_search_ext(state->sh->ldap, - dp_opt_get_string(state->opts->basic, - SDAP_USER_SEARCH_BASE), - LDAP_SCOPE_SUBTREE, state->filter, - discard_const(state->attrs), - false, NULL, NULL, NULL, 0, &msgid); - if (lret != LDAP_SUCCESS) { - DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret))); - tevent_req_error(req, EIO); - return; - } - DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid)); +static int sdap_save_grpmem_recv(struct tevent_req *req) +{ + enum tevent_req_state tstate; + uint64_t err; - ret = sdap_op_add(state, state->ev, state->sh, msgid, - sdap_get_users_done, req, - dp_opt_get_int(state->opts->basic, - SDAP_SEARCH_TIMEOUT), - &state->op); - if (ret) { - DEBUG(1, ("Failed to set up operation!\n")); - tevent_req_error(req, ret); + if (tevent_req_is_error(req, &tstate, &err)) { + if (!err) return EIO; + return err; } + return EOK; } -static void sdap_get_users_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); - struct tevent_req *subreq; - struct sysdb_attrs *usr_attrs; - char *errmsg; - int result; - int ret; - if (error) { - tevent_req_error(req, error); - return; - } +/* ==Generic-Function-to-save-multiple-users============================= */ - switch (ldap_msgtype(reply->msg)) { - case LDAP_RES_SEARCH_REFERENCE: - /* ignore references for now */ - talloc_free(reply); +struct sdap_save_users_state { + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sdap_options *opts; + struct sss_domain_info *dom; - /* unlock the operation so that we can proceed with the next result */ - sdap_unlock_next_reply(state->op); - break; + struct sysdb_attrs **users; + int count; + int cur; - case LDAP_RES_SEARCH_ENTRY: + struct sysdb_handle *handle; - ret = sdap_parse_user(state, state->opts, state->sh, - reply, &usr_attrs, NULL); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } + char *higher_timestamp; +}; - subreq = sdap_save_user_send(state, state->ev, state->handle, - state->opts, state->dom, - state->sh, usr_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_users_save_done, req); +static void sdap_save_users_trans(struct tevent_req *subreq); +static void sdap_save_users_store(struct tevent_req *req); +static void sdap_save_users_process(struct tevent_req *subreq); +struct tevent_req *sdap_save_users_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sss_domain_info *dom, + struct sysdb_ctx *sysdb, + struct sdap_options *opts, + struct sysdb_attrs **users, + int num_users) +{ + struct tevent_req *req, *subreq; + struct sdap_save_users_state *state; - break; + req = tevent_req_create(memctx, &state, struct sdap_save_users_state); + if (!req) return NULL; - case LDAP_RES_SEARCH_RESULT: - /* End of the story */ + state->ev = ev; + state->opts = opts; + state->sysdb = sysdb; + state->dom = dom; + state->users = users; + state->count = 0; + state->cur = 0; + state->handle = NULL; + state->higher_timestamp = NULL; - ret = ldap_parse_result(state->sh->ldap, reply->msg, - &result, NULL, &errmsg, NULL, NULL, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - tevent_req_error(req, EIO); - return; - } + subreq = sysdb_transaction_send(state, state->ev, state->sysdb); + if (!subreq) { + tevent_req_error(req, ENOMEM); + tevent_req_post(req, ev); + return req; + } + tevent_req_set_callback(subreq, sdap_save_users_trans, req); - DEBUG(3, ("Search result: %s(%d), %s\n", - ldap_err2string(result), result, errmsg)); + return req; +} - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - break; +static void sdap_save_users_trans(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_save_users_state *state; + int ret; - default: - /* what is going on here !? */ - tevent_req_error(req, EIO); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_save_users_state); + + ret = sysdb_transaction_recv(subreq, state, &state->handle); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); return; } + + sdap_save_users_store(req); } -static void sdap_get_users_save_done(struct tevent_req *subreq) +static void sdap_save_users_store(struct tevent_req *req) { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); + struct tevent_req *subreq; + struct sdap_save_users_state *state; + + state = tevent_req_data(req, struct sdap_save_users_state); + + subreq = sdap_save_user_send(state, state->ev, state->handle, + state->opts, state->dom, + state->users[state->cur]); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_save_users_process, req); +} + +static void sdap_save_users_process(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_save_users_state *state; char *timestamp = NULL; int ret; + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_save_users_state); + ret = sdap_save_user_recv(subreq, state, ×tamp); talloc_zfree(subreq); /* Do not fail completely on errors. * Just report the failure to save and go on */ if (ret) { - DEBUG(2, ("Failed to store user. Ignoring.\n")); - timestamp = NULL; + DEBUG(2, ("Failed to store user %d. Ignoring.\n", state->cur)); } if (timestamp) { @@ -2416,15 +2249,26 @@ static void sdap_get_users_save_done(struct tevent_req *subreq) } } - /* unlock the operation so that we can proceed with the next result */ - sdap_unlock_next_reply(state->op); + state->cur++; + if (state->cur < state->count) { + sdap_save_users_store(req); + } else { + subreq = sysdb_transaction_commit_send(state, state->ev, + state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + /* sysdb_transaction_complete will call tevent_req_done(req) */ + tevent_req_set_callback(subreq, sysdb_transaction_complete, req); + } } -int sdap_get_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) +static int sdap_save_users_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, char **timestamp) { - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); + struct sdap_save_users_state *state = tevent_req_data(req, + struct sdap_save_users_state); enum tevent_req_state tstate; uint64_t err; @@ -2440,31 +2284,27 @@ int sdap_get_users_recv(struct tevent_req *req, return EOK; } -/* ==Search-Groups-with-filter============================================ */ -struct sdap_get_groups_state { +/* ==Search-Users-with-filter============================================= */ + +struct sdap_get_users_state { struct tevent_context *ev; struct sdap_options *opts; struct sdap_handle *sh; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; const char **attrs; const char *filter; - struct sysdb_handle *handle; - struct sdap_op *op; char *higher_timestamp; - - struct sdap_grp_members *mlist; + struct sysdb_attrs **users; + size_t count; }; -static void sdap_get_groups_transaction(struct tevent_req *subreq); -static void sdap_get_groups_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); -static void sdap_get_groups_save_done(struct tevent_req *subreq); -static void sdap_get_groups_save_mems(struct tevent_req *subreq); +static void sdap_get_users_process(struct tevent_req *subreq); +static void sdap_get_users_done(struct tevent_req *subreq); -struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, +struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sss_domain_info *dom, struct sysdb_ctx *sysdb, @@ -2474,274 +2314,96 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, const char *filter) { struct tevent_req *req, *subreq; - struct sdap_get_groups_state *state; + struct sdap_get_users_state *state; - req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); + req = tevent_req_create(memctx, &state, struct sdap_get_users_state); if (!req) return NULL; state->ev = ev; state->opts = opts; state->dom = dom; state->sh = sh; + state->sysdb = sysdb; state->filter = filter; state->attrs = attrs; state->higher_timestamp = NULL; - state->mlist = NULL; + state->users = NULL; + state->count = 0; - subreq = sysdb_transaction_send(state, state->ev, sysdb); + subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, + dp_opt_get_string(state->opts->basic, + SDAP_USER_SEARCH_BASE), + LDAP_SCOPE_SUBTREE, + state->filter, state->attrs, + state->opts->user_map, SDAP_OPTS_USER); if (!subreq) { + talloc_zfree(req); return NULL; } - tevent_req_set_callback(subreq, sdap_get_groups_transaction, req); + tevent_req_set_callback(subreq, sdap_get_users_process, req); return req; } -static void sdap_get_groups_transaction(struct tevent_req *subreq) +static void sdap_get_users_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, lret; - int msgid; + struct sdap_get_users_state *state = tevent_req_data(req, + struct sdap_get_users_state); + int ret; - ret = sysdb_transaction_recv(subreq, state, &state->handle); + ret = sdap_get_generic_recv(subreq, state, + &state->count, &state->users); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); return; } - DEBUG(7, ("calling ldap_search_ext with [%s].\n", state->filter)); - if (debug_level >= 7) { - int i; - - for (i = 0; state->attrs[i]; i++) { - DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i])); - } - } + DEBUG(6, ("Search for users, returned %d results.\n", state->count)); - lret = ldap_search_ext(state->sh->ldap, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - LDAP_SCOPE_SUBTREE, state->filter, - discard_const(state->attrs), - false, NULL, NULL, NULL, 0, &msgid); - if (lret != LDAP_SUCCESS) { - DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret))); - tevent_req_error(req, EIO); - return; - } - DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid)); - - /* FIXME: get timeouts from configuration, for now 10 minutes */ - ret = sdap_op_add(state, state->ev, state->sh, msgid, - sdap_get_groups_done, req, - dp_opt_get_int(state->opts->basic, - SDAP_SEARCH_TIMEOUT), - &state->op); - if (ret) { - DEBUG(1, ("Failed to set up operation!\n")); - tevent_req_error(req, ret); - } -} - -static void sdap_get_groups_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_get_groups_state *state = tevent_req_data(req, - struct sdap_get_groups_state); - struct tevent_req *subreq; - struct sysdb_attrs *grp_attrs; - char *errmsg; - int result; - int ret; - - if (error) { - tevent_req_error(req, error); + if (state->count == 0) { + tevent_req_error(req, ENOENT); return; } - switch (ldap_msgtype(reply->msg)) { - case LDAP_RES_SEARCH_REFERENCE: - /* ignore references for now */ - talloc_free(reply); - - /* unlock the operation so that we can proceed with the next result */ - sdap_unlock_next_reply(state->op); - break; - - case LDAP_RES_SEARCH_ENTRY: - - /* allocate on reply so that it will be freed once the - * reply is processed. Remember to steal if you need something - * to stick longer */ - ret = sdap_parse_group(reply, state->opts, state->sh, - reply, &grp_attrs, NULL); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - switch (state->opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - case SDAP_SCHEMA_RFC2307BIS: - - subreq = sdap_save_group_send(state, state->ev, state->handle, - state->opts, state->dom, - grp_attrs, true); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_groups_save_done, req); - - break; - - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - - subreq = sdap_save_group_send(state, state->ev, state->handle, - state->opts, state->dom, - grp_attrs, false); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_groups_save_done, req); - - ret = sdap_get_groups_save_membership(state, state->opts, - grp_attrs, &state->mlist); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - break; - - default: - tevent_req_error(req, EFAULT); - return; - } - - break; - - case LDAP_RES_SEARCH_RESULT: - /* End of the story */ - - ret = ldap_parse_result(state->sh->ldap, reply->msg, - &result, NULL, &errmsg, NULL, NULL, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - tevent_req_error(req, EIO); - return; - } - - DEBUG(3, ("Search result: %s(%d), %s\n", - ldap_err2string(result), result, errmsg)); - - if (state->mlist) { - /* need second pass to set members */ - subreq = sdap_set_members_send(state, state->ev, state->handle, - state->opts, state->dom, - state->mlist); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_groups_save_mems, req); - - } else { - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - } - - break; - - default: - /* what is going on here !? */ - tevent_req_error(req, EIO); + subreq = sdap_save_users_send(state, state->ev, state->dom, + state->sysdb, state->opts, + state->users, state->count); + if (!subreq) { + tevent_req_error(req, ENOMEM); return; } + tevent_req_set_callback(subreq, sdap_get_users_done, req); } -static void sdap_get_groups_save_done(struct tevent_req *subreq) +static void sdap_get_users_done(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); - char *timestamp; + struct sdap_get_users_state *state = tevent_req_data(req, + struct sdap_get_users_state); int ret; - ret = sdap_save_group_recv(subreq, state, ×tamp); - talloc_zfree(subreq); - - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - - if (ret) { - DEBUG(2, ("Failed to store group. Ignoring.\n")); - timestamp = NULL; - } + DEBUG(9, ("Saving %d Users - Done\n", state->count)); - if (timestamp) { - if (state->higher_timestamp) { - if (strcmp(timestamp, state->higher_timestamp) > 0) { - talloc_zfree(state->higher_timestamp); - state->higher_timestamp = timestamp; - } else { - talloc_zfree(timestamp); - } - } else { - state->higher_timestamp = timestamp; - } - } - - /* unlock the operation so that we can proceed with the next result */ - sdap_unlock_next_reply(state->op); -} - -static void sdap_get_groups_save_mems(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; - - ret = sdap_set_members_recv(subreq); + ret = sdap_save_users_recv(subreq, state, &state->higher_timestamp); talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to store group memberships.\n")); + DEBUG(2, ("Failed to store users.\n")); tevent_req_error(req, ret); return; } - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); + tevent_req_done(req); } -int sdap_get_groups_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) +int sdap_get_users_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, char **timestamp) { - struct sdap_get_groups_state *state = tevent_req_data(req, - struct sdap_get_groups_state); + struct sdap_get_users_state *state = tevent_req_data(req, + struct sdap_get_users_state); enum tevent_req_state tstate; uint64_t err; @@ -2757,7 +2419,7 @@ int sdap_get_groups_recv(struct tevent_req *req, return EOK; } -/* ==Initgr-call-(groups-a-user-is-member-of)-Save-Groups================= */ +/* ==Generic-Function-to-save-multiple-groups============================= */ struct sdap_save_groups_state { struct tevent_context *ev; @@ -2768,14 +2430,18 @@ struct sdap_save_groups_state { struct sysdb_attrs **groups; int count; int cur; - bool savemembers; + bool twopass; struct sysdb_handle *handle; + + char *higher_timestamp; }; static void sdap_save_groups_trans(struct tevent_req *subreq); -static void sdap_save_groups_store(struct tevent_req *req); -static void sdap_save_groups_process(struct tevent_req *subreq); +static void sdap_save_groups_save(struct tevent_req *req); +static void sdap_save_groups_loop(struct tevent_req *subreq); +static void sdap_save_groups_mem_save(struct tevent_req *req); +static void sdap_save_groups_mem_loop(struct tevent_req *subreq); struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sss_domain_info *dom, @@ -2798,16 +2464,17 @@ struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx, state->count = 0; state->cur = 0; state->handle = NULL; + state->higher_timestamp = NULL; switch (opts->schema_type) { case SDAP_SCHEMA_RFC2307: case SDAP_SCHEMA_RFC2307BIS: - state->savemembers = true; + state->twopass = false; break; case SDAP_SCHEMA_IPA_V1: case SDAP_SCHEMA_AD: - state->savemembers = false; + state->twopass = true; break; default: @@ -2843,39 +2510,39 @@ static void sdap_save_groups_trans(struct tevent_req *subreq) return; } - sdap_save_groups_store(req); + sdap_save_groups_save(req); } -static void sdap_save_groups_store(struct tevent_req *req) +static void sdap_save_groups_save(struct tevent_req *req) { struct tevent_req *subreq; struct sdap_save_groups_state *state; state = tevent_req_data(req, struct sdap_save_groups_state); - /* 1st pass savemembers = false */ - /* 2nd pass savemembers = true */ + /* if 2 pass savemembers = false */ subreq = sdap_save_group_send(state, state->ev, state->handle, state->opts, state->dom, state->groups[state->cur], - state->savemembers); + (!state->twopass)); if (!subreq) { tevent_req_error(req, ENOMEM); return; } - tevent_req_set_callback(subreq, sdap_save_groups_process, req); + tevent_req_set_callback(subreq, sdap_save_groups_loop, req); } -static void sdap_save_groups_process(struct tevent_req *subreq) +static void sdap_save_groups_loop(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_save_groups_state *state; + char *timestamp = NULL; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_save_groups_state); - ret = sdap_save_group_recv(subreq, NULL, NULL); + ret = sdap_save_group_recv(subreq, state, ×tamp); talloc_zfree(subreq); /* Do not fail completely on errors. @@ -2884,14 +2551,31 @@ static void sdap_save_groups_process(struct tevent_req *subreq) DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur)); } + if (timestamp) { + if (state->higher_timestamp) { + if (strcmp(timestamp, state->higher_timestamp) > 0) { + talloc_zfree(state->higher_timestamp); + state->higher_timestamp = timestamp; + } else { + talloc_zfree(timestamp); + } + } else { + state->higher_timestamp = timestamp; + } + } + state->cur++; if (state->cur < state->count) { - sdap_save_groups_store(req); - } else if (state->savemembers == false) { - state->savemembers = true; + + sdap_save_groups_save(req); + + } else if (state->twopass) { + state->cur = 0; - sdap_save_groups_store(req); + sdap_save_groups_mem_save(req); + } else { + subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); if (!subreq) { @@ -2903,8 +2587,199 @@ static void sdap_save_groups_process(struct tevent_req *subreq) } } -static int sdap_save_groups_recv(struct tevent_req *req) +static void sdap_save_groups_mem_save(struct tevent_req *req) +{ + struct tevent_req *subreq; + struct sdap_save_groups_state *state; + + state = tevent_req_data(req, struct sdap_save_groups_state); + + subreq = sdap_save_grpmem_send(state, state->ev, state->handle, + state->opts, state->dom, + state->groups[state->cur]); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_save_groups_mem_loop, req); +} + +static void sdap_save_groups_mem_loop(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_save_groups_state *state; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_save_groups_state); + + ret = sdap_save_grpmem_recv(subreq); + talloc_zfree(subreq); + + /* Do not fail completely on errors. + * Just report the failure to save and go on */ + if (ret) { + DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur)); + } + + state->cur++; + if (state->cur < state->count) { + + sdap_save_groups_mem_save(req); + + } else { + + subreq = sysdb_transaction_commit_send(state, state->ev, + state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + /* sysdb_transaction_complete will call tevent_req_done(req) */ + tevent_req_set_callback(subreq, sysdb_transaction_complete, req); + } +} + +static int sdap_save_groups_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, char **timestamp) +{ + struct sdap_save_groups_state *state = tevent_req_data(req, + struct sdap_save_groups_state); + enum tevent_req_state tstate; + uint64_t err; + + if (tevent_req_is_error(req, &tstate, &err)) { + if (err) return err; + return EIO; + } + + if (timestamp) { + *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); + } + + return EOK; +} + + +/* ==Search-Groups-with-filter============================================ */ + +struct sdap_get_groups_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; + struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; + const char **attrs; + const char *filter; + + char *higher_timestamp; + struct sysdb_attrs **groups; + size_t count; +}; + +static void sdap_get_groups_process(struct tevent_req *subreq); +static void sdap_get_groups_done(struct tevent_req *subreq); + +struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sss_domain_info *dom, + struct sysdb_ctx *sysdb, + struct sdap_options *opts, + struct sdap_handle *sh, + const char **attrs, + const char *filter) +{ + struct tevent_req *req, *subreq; + struct sdap_get_groups_state *state; + + req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); + if (!req) return NULL; + + state->ev = ev; + state->opts = opts; + state->dom = dom; + state->sh = sh; + state->sysdb = sysdb; + state->filter = filter; + state->attrs = attrs; + state->higher_timestamp = NULL; + state->groups = NULL; + state->count = 0; + + 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, + state->filter, state->attrs, + state->opts->group_map, SDAP_OPTS_GROUP); + if (!subreq) { + talloc_zfree(req); + return NULL; + } + tevent_req_set_callback(subreq, sdap_get_groups_process, req); + + return req; +} + +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; + + ret = sdap_get_generic_recv(subreq, state, + &state->count, &state->groups); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + DEBUG(6, ("Search for groups, returned %d results.\n", state->count)); + + if (state->count == 0) { + tevent_req_error(req, ENOENT); + return; + } + + subreq = sdap_save_groups_send(state, state->ev, state->dom, + state->sysdb, state->opts, + state->groups, state->count); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sdap_get_groups_done, req); +} + +static void sdap_get_groups_done(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; + + DEBUG(9, ("Saving %d Groups - Done\n", state->count)); + + ret = sdap_save_groups_recv(subreq, state, &state->higher_timestamp); + talloc_zfree(subreq); + if (ret) { + DEBUG(2, ("Failed to store groups.\n")); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +int sdap_get_groups_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, char **timestamp) +{ + struct sdap_get_groups_state *state = tevent_req_data(req, + struct sdap_get_groups_state); enum tevent_req_state tstate; uint64_t err; @@ -2912,6 +2787,11 @@ static int sdap_save_groups_recv(struct tevent_req *req) if (err) return err; return EIO; } + + if (timestamp) { + *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); + } + return EOK; } @@ -3015,7 +2895,7 @@ static void sdap_initgr_rfc2307_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_save_groups_recv(subreq); + ret = sdap_save_groups_recv(subreq, NULL, NULL); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); @@ -3214,7 +3094,7 @@ static void sdap_initgr_nested_done(struct tevent_req *subreq) req = tevent_req_callback_data(subreq, struct tevent_req); - ret = sdap_save_groups_recv(subreq); + ret = sdap_save_groups_recv(subreq, NULL, NULL); talloc_zfree(subreq); if (ret) { tevent_req_error(req, ret); @@ -3380,7 +3260,7 @@ static void sdap_get_initgr_store(struct tevent_req *subreq) subreq = sdap_save_user_send(state, state->ev, state->handle, state->opts, state->dom, - state->sh, state->orig_user); + state->orig_user); if (!subreq) { tevent_req_error(req, ENOMEM); return; |