summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/providers/ldap/sdap.h6
-rw-r--r--src/providers/ldap/sdap_async.c127
-rw-r--r--src/providers/ldap/sdap_async_connection.c54
-rw-r--r--src/providers/ldap/sdap_async_private.h16
-rw-r--r--src/providers/ldap/sdap_fd_events.c259
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;
+}