summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_async_connection.c
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2010-07-12 04:04:34 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-09-02 12:23:18 -0400
commit56d8d19ac9d857580a233d8264e851883b883c67 (patch)
tree8cb6e8236a24d230ea51f46fe22cd68fd4574e13 /src/providers/ldap/sdap_async_connection.c
parent602fa2c3ef0d088b7b834e9d2ebb306d104a79ce (diff)
downloadsssd-56d8d19ac9d857580a233d8264e851883b883c67.tar.gz
sssd-56d8d19ac9d857580a233d8264e851883b883c67.tar.xz
sssd-56d8d19ac9d857580a233d8264e851883b883c67.zip
Make ldap bind asynchronous
Every ldap function that could possibly create a new connection is now wrapped in a tevent_req. If the connection is created, we will call the function again after the socket is ready for writing.
Diffstat (limited to 'src/providers/ldap/sdap_async_connection.c')
-rw-r--r--src/providers/ldap/sdap_async_connection.c218
1 files changed, 127 insertions, 91 deletions
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 806bd5fe2..d2ca356f3 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -24,6 +24,7 @@
#include "util/util.h"
#include "util/sss_krb5.h"
#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/ldap_req_wrap.h"
#define LDAP_X_SSSD_PASSWORD_EXPIRED 0x555D
@@ -40,9 +41,7 @@ struct sdap_connect_state {
int result;
};
-static void sdap_connect_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt);
+static void sdap_connect_tls_done(struct tevent_req *subreq);
struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
@@ -51,14 +50,12 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
bool use_start_tls)
{
struct tevent_req *req;
+ struct tevent_req *subreq;
struct sdap_connect_state *state;
struct timeval tv;
int ver;
int lret;
- int optret;
int ret = EOK;
- int msgid;
- char *errmsg = NULL;
bool ldap_referrals;
req = tevent_req_create(memctx, &state, struct sdap_connect_state);
@@ -145,37 +142,12 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
DEBUG(4, ("Executing START TLS\n"));
- lret = ldap_start_tls(state->sh->ldap, NULL, NULL, &msgid);
- if (lret != LDAP_SUCCESS) {
- optret = ldap_get_option(state->sh->ldap,
- SDAP_DIAGNOSTIC_MESSAGE,
- (void*)&errmsg);
- if (optret == LDAP_SUCCESS) {
- DEBUG(3, ("ldap_start_tls failed: [%s] [%s]\n",
- ldap_err2string(lret),
- errmsg));
- sss_log(SSS_LOG_ERR, "Could not start TLS. %s", errmsg);
- ldap_memfree(errmsg);
- }
- else {
- DEBUG(3, ("ldap_start_tls failed: [%s]\n",
- ldap_err2string(lret)));
- sss_log(SSS_LOG_ERR, "Could not start TLS. "
- "Check for certificate issues.");
- }
- goto fail;
- }
-
- ret = sdap_set_connected(state->sh, state->ev);
- if (ret) goto fail;
-
- /* FIXME: get timeouts from configuration, for now 5 secs. */
- ret = sdap_op_add(state, ev, state->sh, msgid,
- sdap_connect_done, req, 5, &state->op);
- if (ret) {
- DEBUG(1, ("Failed to set up operation!\n"));
+ subreq = ldap_start_tls_send(state, ev, state->sh, NULL, NULL);
+ if (!subreq) {
+ ret = ENOMEM;
goto fail;
}
+ tevent_req_set_callback(subreq, sdap_connect_tls_done, req);
return req;
@@ -195,6 +167,41 @@ fail:
static void sdap_connect_done(struct sdap_op *op,
struct sdap_msg *reply,
+ int error, void *pvt);
+
+static void sdap_connect_tls_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_connect_state *state;
+ int ret;
+ int msgid;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_connect_state);
+
+ ret = ldap_start_tls_recv(subreq, NULL, &msgid);
+ talloc_zfree(subreq);
+ if (ret != EOK) goto fail;
+
+ ret = sdap_set_connected(state->sh, state->ev);
+ if (ret != EOK) goto fail;
+
+ /* FIXME: get timeouts from configuration, for now 5 secs. */
+ ret = sdap_op_add(state, state->ev, state->sh, msgid,
+ sdap_connect_done, req, 5, &state->op);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to set up operation!\n"));
+ goto fail;
+ }
+
+ return;
+
+fail:
+ tevent_req_error(req, ret);
+}
+
+static void sdap_connect_done(struct sdap_op *op,
+ struct sdap_msg *reply,
int error, void *pvt)
{
struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
@@ -289,9 +296,7 @@ struct simple_bind_state {
int result;
};
-static void simple_bind_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt);
+static void simple_bind_step(struct tevent_req *subreq);
static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
@@ -302,9 +307,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
struct tevent_req *req;
struct simple_bind_state *state;
int ret = EOK;
- int msgid;
- int ldap_err;
LDAPControl *request_controls[2];
+ struct tevent_req *subreq;
req = tevent_req_create(memctx, &state, struct simple_bind_state);
if (!req) return NULL;
@@ -330,47 +334,69 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
DEBUG(4, ("Executing simple bind as: %s\n", state->user_dn));
- ret = ldap_sasl_bind(state->sh->ldap, state->user_dn, LDAP_SASL_SIMPLE,
- state->pw, request_controls, NULL, &msgid);
+ subreq = ldap_sasl_bind_send(state, ev, sh, user_dn, LDAP_SASL_SIMPLE, pw,
+ request_controls, NULL);
ldap_control_free(request_controls[0]);
- if (ret == -1 || msgid == -1) {
- ret = ldap_get_option(state->sh->ldap,
- LDAP_OPT_RESULT_CODE, &ldap_err);
- if (ret != LDAP_OPT_SUCCESS) {
- DEBUG(1, ("ldap_bind failed (couldn't get ldap error)\n"));
- ret = LDAP_LOCAL_ERROR;
- } else {
- DEBUG(1, ("ldap_bind failed (%d)[%s]\n",
- ldap_err, ldap_err2string(ldap_err)));
- ret = ldap_err;
- }
+
+ if (!subreq) goto fail;
+ tevent_req_set_callback(subreq, simple_bind_step, req);
+
+ return req;
+
+fail:
+ if (ret == LDAP_SERVER_DOWN) {
+ tevent_req_error(req, ETIMEDOUT);
+ } else {
+ tevent_req_error(req, EIO);
+ }
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void simple_bind_done(struct sdap_op *op,
+ struct sdap_msg *reply,
+ int error, void *pvt);
+
+static void simple_bind_step(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct simple_bind_state *state;
+ int ret;
+ int msgid;
+ int ldap_ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct simple_bind_state);
+
+ ret = ldap_sasl_bind_recv(subreq, &ldap_ret, &msgid);
+ talloc_zfree(subreq);
+ if (ret == ENOMEM) {
+ DEBUG(1, ("out of memory\n"));
+ } else if (ret == EIO) {
+ DEBUG(1, ("ldap_bind failed (%d)[%s]\n", ldap_ret,
+ ldap_err2string(ldap_ret)));
+ ret = (ldap_ret == LDAP_SERVER_DOWN) ? ETIMEDOUT : EIO;
goto fail;
}
- DEBUG(8, ("ldap simple bind sent, msgid = %d\n", msgid));
- if (!sh->connected) {
- ret = sdap_set_connected(sh, ev);
+ if (!state->sh->connected) {
+ ret = sdap_set_connected(state->sh, state->ev);
if (ret) goto fail;
}
/* FIXME: get timeouts from configuration, for now 5 secs. */
- ret = sdap_op_add(state, ev, sh, msgid,
+ ret = sdap_op_add(state, state->ev, state->sh, msgid,
simple_bind_done, req, 5, &state->op);
if (ret) {
DEBUG(1, ("Failed to set up operation!\n"));
+ ret = EIO;
goto fail;
}
- return req;
+ tevent_req_done(req);
fail:
- if (ret == LDAP_SERVER_DOWN) {
- tevent_req_error(req, ETIMEDOUT);
- } else {
- tevent_req_error(req, EIO);
- }
- tevent_req_post(req, ev);
- return req;
+ tevent_req_error(req, ret);
}
static void simple_bind_done(struct sdap_op *op,
@@ -501,6 +527,7 @@ struct sasl_bind_state {
static int sdap_sasl_interact(LDAP *ld, unsigned flags,
void *defaults, void *interact);
+static void sasl_bind_interactive_done(struct tevent_req *subreq);
static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
@@ -510,8 +537,8 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
struct berval *sasl_cred)
{
struct tevent_req *req;
+ struct tevent_req *subreq;
struct sasl_bind_state *state;
- int ret = EOK;
req = tevent_req_create(memctx, &state, struct sasl_bind_state);
if (!req) return NULL;
@@ -525,36 +552,45 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
DEBUG(4, ("Executing sasl bind mech: %s, user: %s\n",
sasl_mech, sasl_user));
- /* FIXME: Warning, this is a sync call!
- * No async variant exist in openldap libraries yet */
-
- ret = ldap_sasl_interactive_bind_s(state->sh->ldap, NULL,
- sasl_mech, NULL, NULL,
- LDAP_SASL_QUIET,
- (*sdap_sasl_interact), state);
- state->result = ret;
- if (ret != LDAP_SUCCESS) {
- DEBUG(1, ("ldap_sasl_bind failed (%d)[%s]\n",
- ret, ldap_err2string(ret)));
- goto fail;
- }
-
- if (!sh->connected) {
- ret = sdap_set_connected(sh, ev);
- if (ret) goto fail;
+ subreq = ldap_sasl_interactive_bind_send(state, ev, sh, NULL, sasl_mech,
+ NULL, NULL, LDAP_SASL_QUIET,
+ (*sdap_sasl_interact), state);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ tevent_req_post(req, ev);
+ return req;
}
+ tevent_req_set_callback(subreq, sasl_bind_interactive_done, req);
- tevent_req_post(req, ev);
return req;
+}
-fail:
- if (ret == LDAP_SERVER_DOWN) {
- tevent_req_error(req, ETIMEDOUT);
- } else {
- tevent_req_error(req, EIO);
+static void sasl_bind_interactive_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sasl_bind_state *state;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sasl_bind_state);
+
+ ret = ldap_sasl_interactive_bind_recv(subreq);
+ talloc_zfree(subreq);
+
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
}
- tevent_req_post(req, ev);
- return req;
+
+ if (!state->sh->connected) {
+ ret = sdap_set_connected(state->sh, state->ev);
+ if (ret != EOK) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+ }
+
+ tevent_req_done(req);
}
static int sdap_sasl_interact(LDAP *ld, unsigned flags,