diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 6 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.c | 127 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_connection.c | 54 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_private.h | 16 | ||||
-rw-r--r-- | src/providers/ldap/sdap_fd_events.c | 259 |
6 files changed, 280 insertions, 184 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e56d7b16..92244f4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -722,6 +722,7 @@ libsss_ldap_la_SOURCES = \ providers/ldap/sdap_async_accounts.c \ providers/ldap/sdap_async_connection.c \ providers/ldap/sdap_child_helpers.c \ + providers/ldap/sdap_fd_events.c \ providers/ldap/sdap.c \ util/user_info_msg.c \ util/sss_ldap.c \ @@ -793,6 +794,7 @@ libsss_ipa_la_SOURCES = \ providers/ldap/sdap_async_accounts.c \ providers/ldap/sdap_async_connection.c \ providers/ldap/sdap_child_helpers.c \ + providers/ldap/sdap_fd_events.c \ providers/ldap/sdap.c \ util/user_info_msg.c \ util/sss_ldap.c \ diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index f0e345ec..aca98457 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -71,11 +71,7 @@ struct sdap_handle { LDAP *ldap; bool connected; -#ifdef HAVE_LDAP_CONNCB - struct ldap_conncb *conncb; -#else - struct tevent_fd *fde; -#endif + struct sdap_fd_events *sdap_fd_events; struct sdap_op *ops; }; diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c index 15f3048b..a25c50bb 100644 --- a/src/providers/ldap/sdap_async.c +++ b/src/providers/ldap/sdap_async.c @@ -97,12 +97,7 @@ static void sdap_handle_release(struct sdap_handle *sh) 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 + talloc_zfree(sh->sdap_fd_events); while (sh->ops) { op = sh->ops; @@ -115,9 +110,6 @@ static void sdap_handle_release(struct sdap_handle *sh) 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; @@ -132,9 +124,8 @@ 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) +void sdap_ldap_result(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *pvt) { sdap_process_result(ev, pvt); } @@ -336,118 +327,6 @@ static void sdap_process_next_reply(struct tevent_context *ev, 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) diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c index 083bc0cc..9871dc21 100644 --- a/src/providers/ldap/sdap_async_connection.c +++ b/src/providers/ldap/sdap_async_connection.c @@ -127,37 +127,11 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, goto fail; } -#ifdef HAVE_LDAP_CONNCB - struct ldap_cb_data *cb_data; - - /* add connection callback */ - state->sh->conncb = talloc_zero(state->sh, struct ldap_conncb); - if (state->sh->conncb == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto fail; - } - - cb_data = talloc_zero(state->sh->conncb, struct ldap_cb_data); - if (cb_data == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto fail; - } - cb_data->sh = state->sh; - cb_data->ev = state->ev; - - state->sh->conncb->lc_add = sdap_ldap_connect_callback_add; - state->sh->conncb->lc_del = sdap_ldap_connect_callback_del; - state->sh->conncb->lc_arg = cb_data; - - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_CONNECT_CB, - state->sh->conncb); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set connection callback\n")); + ret = setup_ldap_connection_callbacks(state->sh, state->ev); + if (ret != EOK) { + DEBUG(1, ("setup_ldap_connection_callbacks failed.\n")); goto fail; } -#endif /* if we do not use start_tls the connection is not really connected yet * just fake an async procedure and leave connection to the bind call */ @@ -174,11 +148,8 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, goto fail; } - state->sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(state->sh, state->ev); + ret = sdap_set_connected(state->sh, state->ev); if (ret) goto fail; -#endif /* FIXME: get timeouts from configuration, for now 5 secs. */ ret = sdap_op_add(state, ev, state->sh, msgid, @@ -350,11 +321,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, DEBUG(8, ("ldap simple bind sent, msgid = %d\n", msgid)); if (!sh->connected) { - sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(sh, ev); + ret = sdap_set_connected(sh, ev); if (ret) goto fail; -#endif } /* FIXME: get timeouts from configuration, for now 5 secs. */ @@ -544,11 +512,8 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx, } if (!sh->connected) { - sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(sh, ev); + ret = sdap_set_connected(sh, ev); if (ret) goto fail; -#endif } tevent_req_post(req, ev); @@ -980,6 +945,7 @@ static void sdap_cli_rootdse_step(struct tevent_req *req) struct sdap_cli_connect_state *state = tevent_req_data(req, struct sdap_cli_connect_state); struct tevent_req *subreq; + int ret; subreq = sdap_get_rootdse_send(state, state->ev, state->opts, state->sh); if (!subreq) { @@ -992,15 +958,11 @@ static void sdap_cli_rootdse_step(struct tevent_req *req) /* this rootdse search is performed before we actually do a bind, * so we need to set up the callbacks or we will never get notified * of a reply */ - state->sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - int ret; - ret = sdap_install_ldap_callbacks(state->sh, state->ev); + ret = sdap_set_connected(state->sh, state->ev); if (ret) { tevent_req_error(req, ret); } -#endif } } diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h index 55f76ed7..75597c6d 100644 --- a/src/providers/ldap/sdap_async_private.h +++ b/src/providers/ldap/sdap_async_private.h @@ -28,15 +28,13 @@ void make_realm_upper_case(const char *upn); struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx); -#ifdef HAVE_LDAP_CONNCB -int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, - struct sockaddr *addr, struct ldap_conncb *ctx); -void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb, - struct ldap_conncb *ctx); -#else -int sdap_install_ldap_callbacks(struct sdap_handle *sh, - struct tevent_context *ev); -#endif +void sdap_ldap_result(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *pvt); + +int setup_ldap_connection_callbacks(struct sdap_handle *sh, + struct tevent_context *ev); + +errno_t sdap_set_connected(struct sdap_handle *sh, struct tevent_context *ev); int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev, struct sdap_handle *sh, int msgid, diff --git a/src/providers/ldap/sdap_fd_events.c b/src/providers/ldap/sdap_fd_events.c new file mode 100644 index 00000000..11527789 --- /dev/null +++ b/src/providers/ldap/sdap_fd_events.c @@ -0,0 +1,259 @@ +/* + SSSD + + Helper routines for file descriptor events + + Authors: + Sumit Bose <sbose@redhat.com> + + Copyright (C) 2010 Red Hat + + 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 "util/util.h" +#include "providers/ldap/sdap_async_private.h" + +struct sdap_fd_events { +#ifdef HAVE_LDAP_CONNCB + struct ldap_conncb *conncb; +#else + struct tevent_fd *fde; +#endif +}; + +#ifdef HAVE_LDAP_CONNCB +static int remove_connection_callback(TALLOC_CTX *mem_ctx) +{ + int lret; + struct ldap_conncb *conncb = talloc_get_type(mem_ctx, struct ldap_conncb); + + struct ldap_cb_data *cb_data = talloc_get_type(conncb->lc_arg, + struct ldap_cb_data); + + lret = ldap_get_option(cb_data->sh->ldap, LDAP_OPT_CONNECT_CB, conncb); + if (lret != LDAP_OPT_SUCCESS) { + DEBUG(1, ("Failed to remove connection callback.\n")); + } else { + DEBUG(9, ("Successfully removed connection callback.\n")); + } + return lret; +} + +static 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); + + if (cb_data == NULL) { + DEBUG(1, ("sdap_ldap_connect_callback_add called without " + "callback data.\n")); + return EINVAL; + } + + 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; +} + +static 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; +} + +static int sdap_install_ldap_callbacks(struct sdap_handle *sh, + struct tevent_context *ev) +{ + int fd; + int ret; + + if (sh->sdap_fd_events) { + DEBUG(1, ("sdap_install_ldap_callbacks is called with already " + "initialized sdap_fd_events.\n")); + return EINVAL; + } + + sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events); + if (!sh->sdap_fd_events) { + DEBUG(1, ("talloc_zero failed.\n")); + return ENOMEM; + } + + ret = get_fd_from_ldap(sh->ldap, &fd); + if (ret) return ret; + + sh->sdap_fd_events->fde = tevent_add_fd(ev, sh->sdap_fd_events, fd, + TEVENT_FD_READ, sdap_ldap_result, + sh); + if (!sh->sdap_fd_events->fde) { + talloc_zfree(sh->sdap_fd_events); + return ENOMEM; + } + + DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n", + sh, (int)sh->connected, sh->ops, sh->sdap_fd_events->fde, + sh->ldap)); + + return EOK; +} + +#endif + + +errno_t setup_ldap_connection_callbacks(struct sdap_handle *sh, + struct tevent_context *ev) +{ +#ifdef HAVE_LDAP_CONNCB + int ret; + struct ldap_cb_data *cb_data; + + sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events); + if (sh->sdap_fd_events == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + ret = ENOMEM; + goto fail; + } + + sh->sdap_fd_events->conncb = talloc_zero(sh->sdap_fd_events, + struct ldap_conncb); + if (sh->sdap_fd_events->conncb == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + ret = ENOMEM; + goto fail; + } + + cb_data = talloc_zero(sh->sdap_fd_events->conncb, struct ldap_cb_data); + if (cb_data == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + ret = ENOMEM; + goto fail; + } + cb_data->sh = sh; + cb_data->ev = ev; + + sh->sdap_fd_events->conncb->lc_add = sdap_ldap_connect_callback_add; + sh->sdap_fd_events->conncb->lc_del = sdap_ldap_connect_callback_del; + sh->sdap_fd_events->conncb->lc_arg = cb_data; + + ret = ldap_set_option(sh->ldap, LDAP_OPT_CONNECT_CB, + sh->sdap_fd_events->conncb); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(1, ("Failed to set connection callback\n")); + ret = EFAULT; + goto fail; + } + + talloc_set_destructor((TALLOC_CTX *) sh->sdap_fd_events->conncb, + remove_connection_callback); + + return EOK; + +fail: + talloc_zfree(sh->sdap_fd_events); + return ret; +#else + DEBUG(9, ("LDAP connection callbacks are not supported.\n")); + return EOK; +#endif +} + +errno_t sdap_set_connected(struct sdap_handle *sh, struct tevent_context *ev) +{ + int ret = EOK; + + sh->connected = true; + +#ifndef HAVE_LDAP_CONNCB + ret = sdap_install_ldap_callbacks(sh, ev); +#endif + + return ret; +} |