summaryrefslogtreecommitdiffstats
path: root/server/providers/ldap/sdap_async.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/providers/ldap/sdap_async.c')
-rw-r--r--server/providers/ldap/sdap_async.c1018
1 files changed, 0 insertions, 1018 deletions
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
deleted file mode 100644
index 959c08a65..000000000
--- a/server/providers/ldap/sdap_async.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/*
- SSSD
-
- Async LDAP Helper routines
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <ctype.h>
-#include "util/util.h"
-#include "providers/ldap/sdap_async_private.h"
-
-#define REALM_SEPARATOR '@'
-#define REPLY_REALLOC_INCREMENT 10
-
-void make_realm_upper_case(const char *upn)
-{
- char *c;
-
- c = strchr(upn, REALM_SEPARATOR);
- if (c == NULL) {
- DEBUG(9, ("No realm delimiter found in upn [%s].\n", upn));
- return;
- }
-
- while(*(++c) != '\0') {
- c[0] = toupper(*c);
- }
-
- return;
-}
-
-/* ==LDAP-Memory-Handling================================================= */
-
-static int lmsg_destructor(void *mem)
-{
- ldap_msgfree((LDAPMessage *)mem);
- return 0;
-}
-
-static int sdap_msg_attach(TALLOC_CTX *memctx, LDAPMessage *msg)
-{
- void *h;
-
- if (!msg) return EINVAL;
-
- h = sss_mem_attach(memctx, msg, lmsg_destructor);
- if (!h) return ENOMEM;
-
- return EOK;
-}
-
-/* ==sdap-hanlde-utility-functions======================================== */
-
-static inline void sdap_handle_release(struct sdap_handle *sh);
-static int sdap_handle_destructor(void *mem);
-
-struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx)
-{
- struct sdap_handle *sh;
-
- sh = talloc_zero(memctx, struct sdap_handle);
- if (!sh) return NULL;
-
- talloc_set_destructor((TALLOC_CTX *)sh, sdap_handle_destructor);
-
- return sh;
-}
-
-static int sdap_handle_destructor(void *mem)
-{
- struct sdap_handle *sh = talloc_get_type(mem, struct sdap_handle);
-
- sdap_handle_release(sh);
-
- return 0;
-}
-
-static void sdap_handle_release(struct sdap_handle *sh)
-{
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->ldap));
-
- if (sh->connected) {
- struct sdap_op *op;
-
-#ifdef HAVE_LDAP_CONNCB
- /* remove all related fd events from the event loop */
- talloc_zfree(sh->conncb->lc_arg);
-#else
- talloc_zfree(sh->fde);
-#endif
-
- while (sh->ops) {
- op = sh->ops;
- op->callback(op, NULL, EIO, op->data);
- /* calling the callback may result in freeing the op */
- /* check if it is still the same or avoid freeing */
- if (op == sh->ops) talloc_free(op);
- }
-
- if (sh->ldap) {
- ldap_unbind_ext(sh->ldap, NULL, NULL);
- }
-#ifdef HAVE_LDAP_CONNCB
- talloc_zfree(sh->conncb);
-#endif
- sh->connected = false;
- sh->ldap = NULL;
- sh->ops = NULL;
- }
-}
-
-/* ==Parse-Results-And-Handle-Disconnections============================== */
-static void sdap_process_message(struct tevent_context *ev,
- struct sdap_handle *sh, LDAPMessage *msg);
-static void sdap_process_result(struct tevent_context *ev, void *pvt);
-static void sdap_process_next_reply(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt);
-
-static void sdap_ldap_result(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt)
-{
- sdap_process_result(ev, pvt);
-}
-
-static void sdap_ldap_next_result(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- sdap_process_result(ev, pvt);
-}
-
-static void sdap_process_result(struct tevent_context *ev, void *pvt)
-{
- struct sdap_handle *sh = talloc_get_type(pvt, struct sdap_handle);
- struct timeval no_timeout = {0, 0};
- struct tevent_timer *te;
- LDAPMessage *msg;
- int ret;
-
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->ldap));
-
- if (!sh->connected || !sh->ldap) {
- DEBUG(2, ("ERROR: LDAP connection is not connected!\n"));
- return;
- }
-
- ret = ldap_result(sh->ldap, LDAP_RES_ANY, 0, &no_timeout, &msg);
- if (ret == 0) {
- /* this almost always means we have reached the end of
- * the list of received messages */
- DEBUG(8, ("Trace: ldap_result found nothing!\n"));
- return;
- }
-
- if (ret == -1) {
- DEBUG(4, ("ldap_result gave -1, something bad happend!\n"));
- sdap_handle_release(sh);
- return;
- }
-
- /* We don't know if this will be the last result.
- *
- * important: we must do this before actually processing the message
- * because the message processing might even free the sdap_handler
- * so it must be the last operation.
- * FIXME: use tevent_immediate/tevent_queues, when avilable */
- memset(&no_timeout, 0, sizeof(struct timeval));
-
- te = tevent_add_timer(ev, sh, no_timeout, sdap_ldap_next_result, sh);
- if (!te) {
- DEBUG(1, ("Failed to add critical timer to fetch next result!\n"));
- }
-
- /* now process this message */
- sdap_process_message(ev, sh, msg);
-}
-
-/* process a messgae calling the right operation callback.
- * msg is completely taken care of (including freeeing it)
- * NOTE: this function may even end up freeing the sdap_handle
- * so sdap_hanbdle must not be used after this function is called
- */
-static void sdap_process_message(struct tevent_context *ev,
- struct sdap_handle *sh, LDAPMessage *msg)
-{
- struct sdap_msg *reply;
- struct sdap_op *op;
- int msgid;
- int msgtype;
- int ret;
-
- msgid = ldap_msgid(msg);
- if (msgid == -1) {
- DEBUG(2, ("can't fire callback, message id invalid!\n"));
- ldap_msgfree(msg);
- return;
- }
-
- msgtype = ldap_msgtype(msg);
-
- for (op = sh->ops; op; op = op->next) {
- if (op->msgid == msgid) break;
- }
-
- if (op == NULL) {
- DEBUG(2, ("Unmatched msgid, discarding message (type: %0x)\n",
- msgtype));
- ldap_msgfree(msg);
- return;
- }
-
- /* shouldn't happen */
- if (op->done) {
- DEBUG(2, ("Operation [%p] already handled (type: %0x)\n", op, msgtype));
- ldap_msgfree(msg);
- return;
- }
-
- switch (msgtype) {
- case LDAP_RES_SEARCH_ENTRY:
- /* go and process entry */
- break;
-
- case LDAP_RES_SEARCH_REFERENCE:
- /* more ops to come with this msgid */
- /* just ignore */
- ldap_msgfree(msg);
- return;
-
- case LDAP_RES_BIND:
- case LDAP_RES_SEARCH_RESULT:
- case LDAP_RES_MODIFY:
- case LDAP_RES_ADD:
- case LDAP_RES_DELETE:
- case LDAP_RES_MODDN:
- case LDAP_RES_COMPARE:
- case LDAP_RES_EXTENDED:
- case LDAP_RES_INTERMEDIATE:
- /* no more results expected with this msgid */
- op->done = true;
- break;
-
- default:
- /* unkwon msg type ?? */
- DEBUG(1, ("Couldn't figure out the msg type! [%0x]\n", msgtype));
- ldap_msgfree(msg);
- return;
- }
-
- reply = talloc_zero(op, struct sdap_msg);
- if (!reply) {
- ldap_msgfree(msg);
- ret = ENOMEM;
- } else {
- reply->msg = msg;
- ret = sdap_msg_attach(reply, msg);
- if (ret != EOK) {
- ldap_msgfree(msg);
- talloc_zfree(reply);
- }
- }
-
- if (op->list) {
- /* list exist, queue it */
-
- op->last->next = reply;
- op->last = reply;
-
- } else {
- /* create list, then call callback */
- op->list = op->last = reply;
-
- /* must be the last operation as it may end up freeing all memory
- * including all ops handlers */
- op->callback(op, reply, ret, op->data);
- }
-}
-
-static void sdap_unlock_next_reply(struct sdap_op *op)
-{
- struct timeval tv;
- struct tevent_timer *te;
- struct sdap_msg *next_reply;
-
- if (op->list) {
- next_reply = op->list->next;
- /* get rid of the previous reply, it has been processed already */
- talloc_zfree(op->list);
- op->list = next_reply;
- }
-
- /* if there are still replies to parse, queue a new operation */
- if (op->list) {
- /* use a very small timeout, so that fd operations have a chance to be
- * served while processing a long reply */
- tv = tevent_timeval_current();
-
- /* wait 5 microsecond */
- tv.tv_usec += 5;
- tv.tv_sec += tv.tv_usec / 1000000;
- tv.tv_usec = tv.tv_usec % 1000000;
-
- te = tevent_add_timer(op->ev, op, tv,
- sdap_process_next_reply, op);
- if (!te) {
- DEBUG(1, ("Failed to add critical timer for next reply!\n"));
- op->callback(op, NULL, EFAULT, op->data);
- }
- }
-}
-
-static void sdap_process_next_reply(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- struct sdap_op *op = talloc_get_type(pvt, struct sdap_op);
-
- op->callback(op, op->list, EOK, op->data);
-}
-
-#ifdef HAVE_LDAP_CONNCB
-int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
- struct sockaddr *addr, struct ldap_conncb *ctx)
-{
- int ret;
- ber_socket_t ber_fd;
- struct fd_event_item *fd_event_item;
- struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
- struct ldap_cb_data);
-
- ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
- if (ret == -1) {
- DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
- return EINVAL;
- }
- DEBUG(9, ("New LDAP connection to [%s] with fd [%d].\n",
- ldap_url_desc2str(srv), ber_fd));
-
- fd_event_item = talloc_zero(cb_data, struct fd_event_item);
- if (fd_event_item == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- return ENOMEM;
- }
-
- fd_event_item->fde = tevent_add_fd(cb_data->ev, fd_event_item, ber_fd,
- TEVENT_FD_READ, sdap_ldap_result,
- cb_data->sh);
- if (fd_event_item->fde == NULL) {
- DEBUG(1, ("tevent_add_fd failed.\n"));
- talloc_free(fd_event_item);
- return ENOMEM;
- }
- fd_event_item->fd = ber_fd;
-
- DLIST_ADD(cb_data->fd_list, fd_event_item);
-
- return LDAP_SUCCESS;
-}
-
-void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb,
- struct ldap_conncb *ctx)
-{
- int ret;
- ber_socket_t ber_fd;
- struct fd_event_item *fd_event_item;
- struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
- struct ldap_cb_data);
-
- if (sb == NULL || cb_data == NULL) {
- return;
- }
-
- ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
- if (ret == -1) {
- DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
- return;
- }
- DEBUG(9, ("Closing LDAP connection with fd [%d].\n", ber_fd));
-
- DLIST_FOR_EACH(fd_event_item, cb_data->fd_list) {
- if (fd_event_item->fd == ber_fd) {
- break;
- }
- }
- if (fd_event_item == NULL) {
- DEBUG(1, ("No event for fd [%d] found.\n", ber_fd));
- return;
- }
-
- DLIST_REMOVE(cb_data->fd_list, fd_event_item);
- talloc_zfree(fd_event_item);
-
- return;
-}
-
-#else
-
-static int get_fd_from_ldap(LDAP *ldap, int *fd)
-{
- int ret;
-
- ret = ldap_get_option(ldap, LDAP_OPT_DESC, fd);
- if (ret != LDAP_OPT_SUCCESS) {
- DEBUG(1, ("Failed to get fd from ldap!!\n"));
- *fd = -1;
- return EIO;
- }
-
- return EOK;
-}
-
-int sdap_install_ldap_callbacks(struct sdap_handle *sh,
- struct tevent_context *ev)
-{
- int fd;
- int ret;
-
- ret = get_fd_from_ldap(sh->ldap, &fd);
- if (ret) return ret;
-
- sh->fde = tevent_add_fd(ev, sh, fd, TEVENT_FD_READ, sdap_ldap_result, sh);
- if (!sh->fde) return ENOMEM;
-
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap));
-
- return EOK;
-}
-
-#endif
-
-
-/* ==LDAP-Operations-Helpers============================================== */
-
-static int sdap_op_destructor(void *mem)
-{
- struct sdap_op *op = (struct sdap_op *)mem;
-
- DLIST_REMOVE(op->sh->ops, op);
-
- if (op->done) return 0;
-
- /* we don't check the result here, if a message was really abandoned,
- * hopefully the server will get an abandon.
- * If the operation was already fully completed, this is going to be
- * just a noop */
- ldap_abandon_ext(op->sh->ldap, op->msgid, NULL, NULL);
-
- return 0;
-}
-
-static void sdap_op_timeout(struct tevent_req *req)
-{
- struct sdap_op *op = tevent_req_callback_data(req, struct sdap_op);
-
- /* should never happen, but just in case */
- if (op->done) {
- DEBUG(2, ("Timeout happened after op was finished !?\n"));
- return;
- }
-
- /* signal the caller that we have a timeout */
- op->callback(op, NULL, ETIMEDOUT, op->data);
-}
-
-int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev,
- struct sdap_handle *sh, int msgid,
- sdap_op_callback_t *callback, void *data,
- int timeout, struct sdap_op **_op)
-{
- struct sdap_op *op;
-
- op = talloc_zero(memctx, struct sdap_op);
- if (!op) return ENOMEM;
-
- op->sh = sh;
- op->msgid = msgid;
- op->callback = callback;
- op->data = data;
- op->ev = ev;
-
- /* check if we need to set a timeout */
- if (timeout) {
- struct tevent_req *req;
- struct timeval tv;
-
- tv = tevent_timeval_current();
- tv = tevent_timeval_add(&tv, timeout, 0);
-
- /* allocate on op, so when it get freed the timeout is removed */
- req = tevent_wakeup_send(op, ev, tv);
- if (!req) {
- talloc_zfree(op);
- return ENOMEM;
- }
- tevent_req_set_callback(req, sdap_op_timeout, op);
- }
-
- DLIST_ADD(sh->ops, op);
-
- talloc_set_destructor((TALLOC_CTX *)op, sdap_op_destructor);
-
- *_op = op;
- return EOK;
-}
-
-/* ==Modify-Password====================================================== */
-
-struct sdap_exop_modify_passwd_state {
- struct sdap_handle *sh;
-
- struct sdap_op *op;
-
- int result;
- char *user_error_message;
-};
-
-static void sdap_exop_modify_passwd_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt);
-
-struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sdap_handle *sh,
- char *user_dn,
- char *password,
- char *new_password)
-{
- struct tevent_req *req = NULL;
- struct sdap_exop_modify_passwd_state *state;
- int ret;
- BerElement *ber = NULL;
- struct berval *bv = NULL;
- int msgid;
- LDAPControl *request_controls[2];
-
- req = tevent_req_create(memctx, &state,
- struct sdap_exop_modify_passwd_state);
- if (!req) return NULL;
-
- state->sh = sh;
- state->user_error_message = NULL;
-
- ber = ber_alloc_t( LBER_USE_DER );
- if (ber == NULL) {
- DEBUG(7, ("ber_alloc_t failed.\n"));
- talloc_zfree(req);
- return NULL;
- }
-
- ret = ber_printf( ber, "{tststs}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
- user_dn,
- LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, password,
- LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, new_password);
- if (ret == -1) {
- DEBUG(1, ("ber_printf failed.\n"));
- ber_free(ber, 1);
- talloc_zfree(req);
- return NULL;
- }
-
- ret = ber_flatten(ber, &bv);
- ber_free(ber, 1);
- if (ret == -1) {
- DEBUG(1, ("ber_flatten failed.\n"));
- talloc_zfree(req);
- return NULL;
- }
-
- ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
- 0, NULL, 0, &request_controls[0]);
- if (ret != LDAP_SUCCESS) {
- DEBUG(1, ("sss_ldap_control_create failed.\n"));
- goto fail;
- }
- request_controls[1] = NULL;
-
- DEBUG(4, ("Executing extended operation\n"));
-
- ret = ldap_extended_operation(state->sh->ldap, LDAP_EXOP_MODIFY_PASSWD,
- bv, request_controls, NULL, &msgid);
- ber_bvfree(bv);
- ldap_control_free(request_controls[0]);
- if (ret == -1 || msgid == -1) {
- DEBUG(1, ("ldap_extended_operation failed\n"));
- goto fail;
- }
- DEBUG(8, ("ldap_extended_operation sent, msgid = %d\n", msgid));
-
- /* FIXME: get timeouts from configuration, for now 5 secs. */
- ret = sdap_op_add(state, ev, state->sh, msgid,
- sdap_exop_modify_passwd_done, req, 5, &state->op);
- if (ret) {
- DEBUG(1, ("Failed to set up operation!\n"));
- goto fail;
- }
-
- return req;
-
-fail:
- tevent_req_error(req, EIO);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void sdap_exop_modify_passwd_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_exop_modify_passwd_state *state = tevent_req_data(req,
- struct sdap_exop_modify_passwd_state);
- char *errmsg = NULL;
- int ret;
- LDAPControl **response_controls = NULL;
- int c;
- ber_int_t pp_grace;
- ber_int_t pp_expire;
- LDAPPasswordPolicyError pp_error;
-
- if (error) {
- tevent_req_error(req, error);
- return;
- }
-
- ret = ldap_parse_result(state->sh->ldap, reply->msg,
- &state->result, NULL, &errmsg, NULL,
- &response_controls, 0);
- if (ret != LDAP_SUCCESS) {
- DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid));
- ret = EIO;
- goto done;
- }
-
- if (response_controls == NULL) {
- DEBUG(5, ("Server returned no controls.\n"));
- } else {
- for (c = 0; response_controls[c] != NULL; c++) {
- DEBUG(9, ("Server returned control [%s].\n",
- response_controls[c]->ldctl_oid));
- if (strcmp(response_controls[c]->ldctl_oid,
- LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
- ret = ldap_parse_passwordpolicy_control(state->sh->ldap,
- response_controls[c],
- &pp_expire, &pp_grace,
- &pp_error);
- if (ret != LDAP_SUCCESS) {
- DEBUG(1, ("ldap_parse_passwordpolicy_control failed.\n"));
- ret = EIO;
- goto done;
- }
-
- DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] "
- "error [%s].\n", pp_expire, pp_grace,
- ldap_passwordpolicy_err2txt(pp_error)));
- }
- }
- }
-
- if (state->result != LDAP_SUCCESS) {
- state->user_error_message = talloc_strdup(state, errmsg);
- if (state->user_error_message == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- }
- }
-
- DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n",
- ldap_err2string(state->result), state->result, errmsg));
-
- ret = LDAP_SUCCESS;
-done:
- ldap_controls_free(response_controls);
- ldap_memfree(errmsg);
-
- if (ret == LDAP_SUCCESS) {
- tevent_req_done(req);
- } else {
- tevent_req_error(req, ret);
- }
-}
-
-int sdap_exop_modify_passwd_recv(struct tevent_req *req,
- TALLOC_CTX * mem_ctx,
- enum sdap_result *result,
- char **user_error_message)
-{
- struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
- struct sdap_exop_modify_passwd_state);
-
- *result = SDAP_ERROR;
- *user_error_message = talloc_steal(mem_ctx, state->user_error_message);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- if (state->result == LDAP_SUCCESS) {
- *result = SDAP_SUCCESS;
- }
-
- return EOK;
-}
-
-/* ==Fetch-RootDSE============================================= */
-
-struct sdap_get_rootdse_state {
- struct tevent_context *ev;
- struct sdap_options *opts;
- struct sdap_handle *sh;
-
- struct sysdb_attrs *rootdse;
-};
-
-static void sdap_get_rootdse_done(struct tevent_req *subreq);
-
-struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sdap_options *opts,
- struct sdap_handle *sh)
-{
- struct tevent_req *req, *subreq;
- struct sdap_get_rootdse_state *state;
-
- DEBUG(9, ("Getting rootdse\n"));
-
- req = tevent_req_create(memctx, &state, struct sdap_get_rootdse_state);
- if (!req) return NULL;
-
- state->ev = ev;
- state->opts = opts;
- state->sh = sh;
- state->rootdse = NULL;
-
- subreq = sdap_get_generic_send(state, ev, opts, sh,
- "", LDAP_SCOPE_BASE,
- "(objectclass=*)", NULL, NULL, 0);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, sdap_get_rootdse_done, req);
-
- return req;
-}
-
-static void sdap_get_rootdse_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct sdap_get_rootdse_state *state = tevent_req_data(req,
- struct sdap_get_rootdse_state);
- struct sysdb_attrs **results;
- size_t num_results;
- int ret;
-
- ret = sdap_get_generic_recv(subreq, state, &num_results, &results);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- if (num_results == 0 || !results) {
- DEBUG(2, ("No RootDSE for server ?!\n"));
- tevent_req_error(req, ENOENT);
- return;
- }
-
- if (num_results > 1) {
- DEBUG(2, ("Multiple replies when searching for RootDSE ??\n"));
- tevent_req_error(req, EIO);
- return;
- }
-
- state->rootdse = talloc_steal(state, results[0]);
- talloc_zfree(results);
-
- DEBUG(9, ("Got rootdse\n"));
-
- tevent_req_done(req);
-}
-
-int sdap_get_rootdse_recv(struct tevent_req *req,
- TALLOC_CTX *memctx,
- struct sysdb_attrs **rootdse)
-{
- struct sdap_get_rootdse_state *state = tevent_req_data(req,
- struct sdap_get_rootdse_state);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *rootdse = talloc_steal(memctx, state->rootdse);
-
- return EOK;
-}
-
-/* ==Generic Search============================================ */
-
-struct sdap_get_generic_state {
- struct tevent_context *ev;
- struct sdap_options *opts;
- struct sdap_handle *sh;
- const char *search_base;
- int scope;
- const char *filter;
- const char **attrs;
- struct sdap_attr_map *map;
- int map_num_attrs;
-
- struct sdap_op *op;
-
- size_t reply_max;
- size_t reply_count;
- struct sysdb_attrs **reply;
-};
-
-static errno_t add_to_reply(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 sdap_options *opts,
- struct sdap_handle *sh,
- const char *search_base,
- int scope,
- const char *filter,
- const char **attrs,
- struct sdap_attr_map *map,
- int map_num_attrs)
-{
- 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->sh = sh;
- state->search_base = search_base;
- state->scope = scope;
- state->filter = filter;
- state->attrs = attrs;
- state->map = map;
- state->map_num_attrs = map_num_attrs;
- state->op = NULL;
- state->reply_max = 0;
- state->reply_count = 0;
- state->reply = NULL;
-
- DEBUG(6, ("calling ldap_search_ext with [%s][%s].\n", state->filter,
- state->search_base));
- if (debug_level >= 7) {
- int i;
-
- if (state->attrs) {
- 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,
- state->scope, 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);
- struct sysdb_attrs *attrs;
- char *errmsg;
- int result;
- int ret;
-
- 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_entry(state, state->sh, reply,
- state->map, state->map_num_attrs,
- &attrs, NULL);
- if (ret != EOK) {
- DEBUG(1, ("sdap_parse_generic_entry failed.\n"));
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- ret = add_to_reply(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:
- 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(6, ("Search result: %s(%d), %s\n",
- ldap_err2string(result), result, errmsg));
-
- tevent_req_done(req);
- return;
-
- default:
- /* what is going on here !? */
- tevent_req_error(req, EIO);
- return;
- }
-}
-
-static errno_t add_to_reply(struct sdap_get_generic_state *state,
- struct sysdb_attrs *msg)
-{
- if (state->reply == NULL || state->reply_max == state->reply_count) {
- state->reply_max += REPLY_REALLOC_INCREMENT;
- state->reply = talloc_realloc(state, state->reply,
- struct sysdb_attrs *,
- state->reply_max);
- if (state->reply == NULL) {
- DEBUG(1, ("talloc_realloc failed.\n"));
- return ENOMEM;
- }
- }
-
- state->reply[state->reply_count++] = talloc_steal(state->reply, msg);
-
- return EOK;
-}
-
-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);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *reply_count = state->reply_count;
- *reply = talloc_steal(mem_ctx, state->reply);
-
- return EOK;
-}
-