>From 464e9879103f2a5f708435737ad2653b63b3f999 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 17 Sep 2009 11:12:36 +0200 Subject: [PATCH] added generic LDAP search sdap_get_generic_send/_recv --- server/providers/ldap/sdap_async.c | 261 ++++++++++++++++++++++++++++++++++++ server/providers/ldap/sdap_async.h | 17 +++ 2 files changed, 278 insertions(+), 0 deletions(-) diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index f088e51..1de2f34 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -3020,3 +3020,264 @@ 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 reply_item *reply_list; + + struct sysdb_handle *handle; + struct sdap_op *op; +}; + +static int sdap_parse_generic_entry(TALLOC_CTX *memctx, + struct sdap_handle *sh, + struct sdap_msg *sm, + struct sysdb_attrs **_attrs) +{ + struct sysdb_attrs *attrs; + BerElement *ber = NULL; + struct berval **vals; + struct ldb_val v; + char *str; + int lerrno; + int i; + int ret; + + lerrno = 0; + ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + + attrs = sysdb_new_attrs(memctx); + if (!attrs) return ENOMEM; + + str = ldap_get_dn(sh->ldap, sm->msg); + if (!str) { + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + DEBUG(1, ("ldap_get_dn failed: %d(%s)\n", + lerrno, ldap_err2string(lerrno))); + ret = EIO; + goto fail; + } + + DEBUG(9, ("OriginalDN: [%s].\n", str)); + ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str); + if (ret) goto fail; + ldap_memfree(str); + + str = ldap_first_attribute(sh->ldap, sm->msg, &ber); + if (!str) { + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + DEBUG(9, ("Entry has no attributes [%d(%s)]!?\n", + lerrno, ldap_err2string(lerrno))); + } + while (str) { + vals = ldap_get_values_len(sh->ldap, sm->msg, str); + if (!vals) { + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + DEBUG(1, ("LDAP Library error: %d(%s)", + lerrno, ldap_err2string(lerrno))); + ret = EIO; + goto fail; + } + if (!vals[0]) { + DEBUG(1, ("Missing value after ldap_get_values() ??\n")); + ret = EINVAL; + goto fail; + } + for (i = 0; vals[i]; i++) { + v.data = (uint8_t *) vals[i]->bv_val; + v.length = vals[i]->bv_len; + + ret = sysdb_attrs_add_val(attrs, str, &v); + if (ret) goto fail; + } + ldap_value_free_len(vals); + + ldap_memfree(str); + str = ldap_next_attribute(sh->ldap, sm->msg, ber); + } + ber_free(ber, 0); + + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + if (lerrno) { + DEBUG(1, ("LDAP Library error: %d(%s)", + lerrno, ldap_err2string(lerrno))); + ret = EIO; + goto fail; + } + + *_attrs = attrs; + return EOK; + +fail: + if (ber) ber_free(ber, 0); + talloc_free(attrs); + return ret; +} + +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_list = 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)); + + /* FIXME: get timeouts from configuration, for now 10 minutes */ + ret = sdap_op_add(state, state->ev, state->sh, msgid, + sdap_get_generic_done, req, 600, &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); + struct reply_item *reply_item; + 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; + } + + reply_item = talloc(state, struct reply_item); + if (reply_item == NULL) { + DEBUG(1, ("talloc failed.\n")); + tevent_req_error(req, ENOMEM); + return; + } + + talloc_steal(reply_item, attrs); + reply_item->attrs = attrs; + reply_item->next = state->reply_list; + + state->reply_list = reply_item; + + 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, + struct reply_item **reply_list) +{ + struct sdap_get_generic_state *state = tevent_req_data(req, + struct sdap_get_generic_state); + enum tevent_req_state tstate; + uint64_t err; + struct reply_item *ri; + + if (tevent_req_is_error(req, &tstate, &err)) { + if (err) return err; + return EIO; + } + + if (reply_list) { + ri = state->reply_list; + while (ri != NULL) { + talloc_steal(mem_ctx, ri); + ri = ri->next; + } + *reply_list = state->reply_list; + } + + return EOK; +} + diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h index c50133c..8baf0c9 100644 --- a/server/providers/ldap/sdap_async.h +++ b/server/providers/ldap/sdap_async.h @@ -95,3 +95,20 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, struct sdap_options *opts); int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx, struct sdap_handle **gsh); + +struct reply_item { + struct sysdb_attrs *attrs; + struct reply_item *next; +}; + +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); +int sdap_get_generic_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, struct reply_item **reply_list); -- 1.6.2.5