diff options
Diffstat (limited to 'server/providers/ldap/sdap_async.c')
-rw-r--r-- | server/providers/ldap/sdap_async.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index f088e517..6350433b 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -30,6 +30,8 @@ #define LDAP_X_SSSD_PASSWORD_EXPIRED 0x555D +#define REPLY_REALLOC_INCREMENT 10 + static void make_realm_upper_case(const char *upn) { char *c; @@ -3020,3 +3022,202 @@ int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, } return EOK; } + +/* ==Generic Search============================================ */ + +struct sdap_get_generic_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; + struct sss_domain_info *dom; + const char **attrs; + const char *filter; + const char *search_base; + struct sysdb_attrs **reply; + size_t reply_max; + size_t reply_count; + + struct sysdb_handle *handle; + struct sdap_op *op; +}; + +static errno_t add_to_reply(TALLOC_CTX *memctx, + struct sdap_get_generic_state *state, + struct sysdb_attrs *msg); + +static void sdap_get_generic_done(struct sdap_op *op, + struct sdap_msg *reply, + int error, void *pvt); + +struct tevent_req *sdap_get_generic_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, + const char *search_base) +{ + struct tevent_req *req = NULL; + struct sdap_get_generic_state *state = NULL; + int lret; + int ret; + int msgid; + + req = tevent_req_create(memctx, &state, struct sdap_get_generic_state); + if (!req) return NULL; + + state->ev = ev; + state->opts = opts; + state->dom = dom; + state->sh = sh; + state->filter = filter; + state->attrs = attrs; + state->search_base = search_base; + state->reply = NULL; + state->reply_max = 0; + state->reply_count = 0; + state->op = NULL; + state->handle = NULL; + + DEBUG(7, ("calling ldap_search_ext with [%s][%s].\n", state->filter, + state->search_base)); + if (debug_level >= 7) { + int i; + + for (i = 0; state->attrs[i]; i++) { + DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i])); + } + } + + lret = ldap_search_ext(state->sh->ldap, state->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))); + ret = EIO; + goto fail; + } + DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid)); + + ret = sdap_op_add(state, state->ev, state->sh, msgid, + sdap_get_generic_done, req, + dp_opt_get_int(state->opts->basic,SDAP_SEARCH_TIMEOUT), + &state->op); + if (ret != EOK) { + DEBUG(1, ("Failed to set up operation!\n")); + goto fail; + } + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + + +static void sdap_get_generic_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_generic_state *state = tevent_req_data(req, + struct sdap_get_generic_state); + int ret; + struct sysdb_attrs *attrs; + + if (error) { + tevent_req_error(req, error); + 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: + ret = sdap_parse_generic_entry(state, state->sh, reply, &attrs); + if (ret != EOK) { + DEBUG(1, ("sdap_parse_generic_entry failed.\n")); + tevent_req_error(req, ENOMEM); + return; + } + + ret = add_to_reply(state, state, attrs); + if (ret != EOK) { + DEBUG(1, ("add_to_reply failed.\n")); + tevent_req_error(req, ret); + return; + } + + sdap_unlock_next_reply(state->op); + break; + case LDAP_RES_SEARCH_RESULT: + tevent_req_done(req); + return; + + break; + default: + /* what is going on here !? */ + tevent_req_error(req, EIO); + return; + } + + return; +} + +int sdap_get_generic_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + size_t *reply_count, + struct sysdb_attrs ***reply) +{ + struct sdap_get_generic_state *state = tevent_req_data(req, + struct sdap_get_generic_state); + enum tevent_req_state tstate; + uint64_t err; + int i; + + if (tevent_req_is_error(req, &tstate, &err)) { + if (err) return err; + return EIO; + } + + *reply_count = state->reply_count; + *reply = talloc_steal(mem_ctx, state->reply); + for (i = 0; i < state->reply_count; i++) { + talloc_steal(mem_ctx, state->reply[i]); + } + + return EOK; +} + +static errno_t add_to_reply(TALLOC_CTX *memctx, + struct sdap_get_generic_state *state, + struct sysdb_attrs *msg) +{ + struct sysdb_attrs **dummy; + + if (state->reply == NULL || state->reply_max == state->reply_count) { + state->reply_max += REPLY_REALLOC_INCREMENT; + dummy = talloc_realloc(memctx, state->reply, struct sysdb_attrs *, + state->reply_max); + if (dummy == NULL) { + DEBUG(1, ("talloc_realloc failed.\n")); + return ENOMEM; + } + state->reply = dummy; + } + + state->reply[state->reply_count++] = talloc_steal(state->reply, msg); + + return EOK; +} |