summaryrefslogtreecommitdiffstats
path: root/src/providers
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers')
-rw-r--r--src/providers/ldap/ldap_id_enum.c367
1 files changed, 131 insertions, 236 deletions
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 95b35e0ca..87b956331 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -39,6 +39,8 @@ extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx,
static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
struct sdap_id_ctx *ctx);
+static int ldap_id_enumerate_retry(struct tevent_req *req);
+static void ldap_id_enumerate_connect_done(struct tevent_req *req);
static void ldap_id_enumerate_reschedule(struct tevent_req *req);
@@ -146,8 +148,6 @@ static void ldap_id_enumerate_reschedule(struct tevent_req *req)
ldap_id_enumerate_set_timer(ctx, tv);
}
-
-
int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv)
{
struct tevent_timer *enum_task;
@@ -170,30 +170,30 @@ int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv)
struct global_enum_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
+ struct sdap_id_op *op;
bool purge;
- int restarts;
};
static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
+ struct sdap_id_op *op,
bool purge);
static void ldap_id_enum_users_done(struct tevent_req *subreq);
static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
+ struct sdap_id_op *op,
bool purge);
static void ldap_id_enum_groups_done(struct tevent_req *subreq);
static void ldap_id_enum_cleanup_done(struct tevent_req *subreq);
-static int ldap_id_enum_users_restart(struct tevent_req *req);
-static int ldap_id_enum_groups_restart(struct tevent_req *req);
static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
struct sdap_id_ctx *ctx)
{
struct global_enum_state *state;
- struct tevent_req *req, *subreq;
+ struct tevent_req *req;
int t;
req = tevent_req_create(ctx, &state, struct global_enum_state);
@@ -201,7 +201,12 @@ static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
state->ev = ev;
state->ctx = ctx;
- state->restarts = 0;
+ state->op = sdap_id_op_create(state, state->ctx->conn_cache);
+ if (!state->op) {
+ DEBUG(2, ("sdap_id_op_create failed\n"));
+ talloc_zfree(req);
+ return NULL;
+ }
ctx->last_enum = tevent_timeval_current();
@@ -212,64 +217,66 @@ static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
state->purge = false;
}
- subreq = enum_users_send(state, ev, ctx, state->purge);
- if (!subreq) {
+ int ret = ldap_id_enumerate_retry(req);
+ if (ret != EOK) {
+ DEBUG(2, ("ldap_id_enumerate_retry failed\n"));
talloc_zfree(req);
return NULL;
}
- tevent_req_set_callback(subreq, ldap_id_enum_users_done, req);
return req;
}
-static void ldap_id_enum_users_done(struct tevent_req *subreq)
+static int ldap_id_enumerate_retry(struct tevent_req *req)
{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
struct global_enum_state *state = tevent_req_data(req,
- struct global_enum_state);
- enum tevent_req_state tstate;
- uint64_t err = 0;
+ struct global_enum_state);
+ struct tevent_req *subreq;
int ret;
- if (tevent_req_is_error(subreq, &tstate, &err)) {
- if (tstate != TEVENT_REQ_USER_ERROR) {
- err = EIO;
- }
- if (err != ENOENT) {
- goto fail;
- }
- }
- talloc_zfree(subreq);
-
- subreq = enum_groups_send(state, state->ev, state->ctx, state->purge);
+ subreq = sdap_id_op_connect_send(state->op, state, &ret);
if (!subreq) {
- goto fail;
+ return ret;
}
- tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req);
- return;
+ tevent_req_set_callback(subreq, ldap_id_enumerate_connect_done, req);
+ return EOK;
+}
-fail:
- if (err) {
- DEBUG(9, ("User enumeration failed with: (%d)[%s]\n",
- (int)err, strerror(err)));
+static void ldap_id_enumerate_connect_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct global_enum_state *state = tevent_req_data(req,
+ struct global_enum_state);
+ int ret, dp_error;
- if (sdap_check_gssapi_reconnect(state->ctx)) {
- if (state->ctx->gsh) {
- state->ctx->gsh->connected = false;
- }
- ret = ldap_id_enum_users_restart(req);
- if (ret == EOK) return;
+ ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ if (dp_error == DP_ERR_OFFLINE) {
+ tevent_req_done(req);
+ } else {
+ DEBUG(9, ("User enumeration failed to connect to LDAP server: (%d)[%s]\n",
+ ret, strerror(ret)));
+ tevent_req_error(req, ret);
}
- sdap_mark_offline(state->ctx);
+
+ return;
}
- DEBUG(1, ("Failed to enumerate users, retrying later!\n"));
- tevent_req_done(req);
+ subreq = enum_users_send(state, state->ev,
+ state->ctx, state->op,
+ state->purge);
+ if(!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_set_callback(subreq, ldap_id_enum_users_done, req);
}
-static void ldap_id_enum_groups_done(struct tevent_req *subreq)
+static void ldap_id_enum_users_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
@@ -277,154 +284,135 @@ static void ldap_id_enum_groups_done(struct tevent_req *subreq)
struct global_enum_state);
enum tevent_req_state tstate;
uint64_t err = 0;
- int ret;
+ int ret, dp_error = DP_ERR_FATAL;
if (tevent_req_is_error(subreq, &tstate, &err)) {
if (tstate != TEVENT_REQ_USER_ERROR) {
err = EIO;
}
- if (err != ENOENT) {
- goto fail;
+
+ if (err == ENOENT) {
+ err = EOK;
}
}
talloc_zfree(subreq);
- if (state->purge) {
+ if (err != EOK) {
+ /* We call sdap_id_op_done only on error
+ * as the connection is reused by groups enumeration */
+ ret = sdap_id_op_done(state->op, (int)err, &dp_error);
+ if (dp_error == DP_ERR_OK) {
+ /* retry */
+ ret = ldap_id_enumerate_retry(req);
+ if (ret == EOK) {
+ return;
+ }
- subreq = ldap_id_cleanup_send(state, state->ev, state->ctx);
- if (!subreq) {
- goto fail;
+ dp_error = DP_ERR_FATAL;
}
- tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req);
-
- return;
- }
- tevent_req_done(req);
- return;
-
-fail:
- /* check if credentials are expired otherwise go offline on failures */
- if (sdap_check_gssapi_reconnect(state->ctx)) {
- if (state->ctx->gsh) {
- state->ctx->gsh->connected = false;
+ if (dp_error == DP_ERR_OFFLINE) {
+ tevent_req_done(req);
+ } else {
+ DEBUG(9, ("User enumeration failed with: (%d)[%s]\n",
+ ret, strerror(ret)));
+ tevent_req_error(req, ret);
}
- ret = ldap_id_enum_groups_restart(req);
- if (ret == EOK) return;
+ return;
}
- sdap_mark_offline(state->ctx);
- DEBUG(1, ("Failed to enumerate groups (%d [%s]), retrying later!\n",
- (int)err, strerror(err)));
- tevent_req_done(req);
-}
-
-static void ldap_id_enum_cleanup_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- talloc_zfree(subreq);
- tevent_req_done(req);
-}
-
-static void ldap_id_enum_users_immediate(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data)
-{
- struct tevent_req *req = talloc_get_type(private_data,
- struct tevent_req);
- struct global_enum_state *state = tevent_req_data(req,
- struct global_enum_state);
- struct tevent_req *subreq;
- subreq = enum_users_send(state, state->ev, state->ctx, state->purge);
- if (subreq == NULL) {
+ subreq = enum_groups_send(state, state->ev, state->ctx, state->op, state->purge);
+ if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
}
- tevent_req_set_callback(subreq, ldap_id_enum_users_done, req);
+ tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req);
}
-static int ldap_id_enum_users_restart(struct tevent_req *req)
+static void ldap_id_enum_groups_done(struct tevent_req *subreq)
{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
struct global_enum_state *state = tevent_req_data(req,
struct global_enum_state);
- struct tevent_immediate *im;
+ enum tevent_req_state tstate;
+ uint64_t err = 0;
+ int ret, dp_error = DP_ERR_FATAL;
- state->restarts++;
- if (state->restarts < MAX_ENUM_RESTARTS) {
- return ELOOP;
- }
+ if (tevent_req_is_error(subreq, &tstate, &err)) {
+ if (tstate != TEVENT_REQ_USER_ERROR) {
+ err = EIO;
+ }
- im = tevent_create_immediate(req);
- if (!im) {
- return ENOMEM;
+ if (err == ENOENT) {
+ err = EOK;
+ }
}
+ talloc_zfree(subreq);
- /* schedule a completely new event to avoid deep recursions */
- tevent_schedule_immediate(im, state->ev,
- ldap_id_enum_users_immediate, req);
+ ret = sdap_id_op_done(state->op, (int)err, &dp_error);
+ if (dp_error == DP_ERR_OK && ret != EOK) {
+ /* retry */
+ ret = ldap_id_enumerate_retry(req);
+ if (ret == EOK) {
+ return;
+ }
- return EOK;
-}
+ dp_error = DP_ERR_FATAL;
+ }
-static void ldap_id_enum_groups_immediate(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data)
-{
- struct tevent_req *req = talloc_get_type(private_data,
- struct tevent_req);
- struct global_enum_state *state = tevent_req_data(req,
- struct global_enum_state);
- struct tevent_req *subreq;
+ if (ret != EOK) {
+ if (dp_error == DP_ERR_OFFLINE) {
+ tevent_req_done(req);
+ } else {
+ DEBUG(9, ("Group enumeration failed with: (%d)[%s]\n",
+ ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ }
- subreq = enum_groups_send(state, state->ev, state->ctx, state->purge);
- if (subreq == NULL) {
- tevent_req_error(req, ENOMEM);
return;
}
- tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req);
-}
-static int ldap_id_enum_groups_restart(struct tevent_req *req)
-{
- struct global_enum_state *state = tevent_req_data(req,
- struct global_enum_state);
- struct tevent_immediate *im;
+ if (state->purge) {
- state->restarts++;
- if (state->restarts < MAX_ENUM_RESTARTS) {
- return ELOOP;
- }
+ subreq = ldap_id_cleanup_send(state, state->ev, state->ctx);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
- im = tevent_create_immediate(req);
- if (!im) {
- return ENOMEM;
+ tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req);
+ return;
}
- /* schedule a completely new event to avoid deep recursions */
- tevent_schedule_immediate(im, state->ev,
- ldap_id_enum_groups_immediate, req);
-
- return EOK;
+ tevent_req_done(req);
}
+static void ldap_id_enum_cleanup_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ talloc_zfree(subreq);
+ tevent_req_done(req);
+}
/* ==User-Enumeration===================================================== */
struct enum_users_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
+ struct sdap_id_op *op;
char *filter;
const char **attrs;
};
-static void enum_users_connect_done(struct tevent_req *subreq);
static void enum_users_op_done(struct tevent_req *subreq);
static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
+ struct sdap_id_op *op,
bool purge)
{
struct tevent_req *req, *subreq;
@@ -436,6 +424,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
+ state->op = op;
if (ctx->max_user_timestamp && !purge) {
@@ -464,28 +453,11 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
SDAP_OPTS_USER, &state->attrs);
if (ret != EOK) goto fail;
- if (!sdap_connected(ctx)) {
-
- /* FIXME: add option to decide if tls should be used
- * or SASL/GSSAPI, etc ... */
- subreq = sdap_cli_connect_send(state, ev, ctx->opts,
- ctx->be, ctx->service,
- &ctx->rootDSE);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, enum_users_connect_done, req);
-
- return req;
- }
-
subreq = sdap_get_users_send(state, state->ev,
state->ctx->be->domain,
state->ctx->be->sysdb,
state->ctx->opts,
- state->ctx->gsh,
+ sdap_id_op_handle(state->op),
state->attrs, state->filter);
if (!subreq) {
ret = ENOMEM;
@@ -501,37 +473,6 @@ fail:
return req;
}
-static void enum_users_connect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct enum_users_state *state = tevent_req_data(req,
- struct enum_users_state);
- int ret;
-
- ret = sdap_cli_connect_recv(subreq, state->ctx,
- &state->ctx->gsh, &state->ctx->rootDSE);
- talloc_zfree(subreq);
- if (ret) {
- if (ret == ENOTSUP) {
- DEBUG(0, ("Authentication mechanism not Supported by server"));
- }
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sdap_get_users_send(state, state->ev,
- state->ctx->be->domain,
- state->ctx->be->sysdb,
- state->ctx->opts, state->ctx->gsh,
- state->attrs, state->filter);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, enum_users_op_done, req);
-}
-
static void enum_users_op_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -564,17 +505,18 @@ static void enum_users_op_done(struct tevent_req *subreq)
struct enum_groups_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
+ struct sdap_id_op *op;
char *filter;
const char **attrs;
};
-static void enum_groups_connect_done(struct tevent_req *subreq);
static void enum_groups_op_done(struct tevent_req *subreq);
static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
+ struct sdap_id_op *op,
bool purge)
{
struct tevent_req *req, *subreq;
@@ -587,6 +529,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
+ state->op = op;
attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
@@ -617,27 +560,10 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
SDAP_OPTS_GROUP, &state->attrs);
if (ret != EOK) goto fail;
- if (!sdap_connected(ctx)) {
-
- /* FIXME: add option to decide if tls should be used
- * or SASL/GSSAPI, etc ... */
- subreq = sdap_cli_connect_send(state, ev, ctx->opts,
- ctx->be, ctx->service,
- &ctx->rootDSE);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, enum_groups_connect_done, req);
-
- return req;
- }
-
subreq = sdap_get_groups_send(state, state->ev,
state->ctx->be->domain,
state->ctx->be->sysdb,
- state->ctx->opts, state->ctx->gsh,
+ state->ctx->opts, sdap_id_op_handle(state->op),
state->attrs, state->filter);
if (!subreq) {
ret = ENOMEM;
@@ -653,37 +579,6 @@ fail:
return req;
}
-static void enum_groups_connect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct enum_groups_state *state = tevent_req_data(req,
- struct enum_groups_state);
- int ret;
-
- ret = sdap_cli_connect_recv(subreq, state->ctx,
- &state->ctx->gsh, &state->ctx->rootDSE);
- talloc_zfree(subreq);
- if (ret) {
- if (ret == ENOTSUP) {
- DEBUG(0, ("Authentication mechanism not Supported by server"));
- }
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sdap_get_groups_send(state, state->ev,
- state->ctx->be->domain,
- state->ctx->be->sysdb,
- state->ctx->opts, state->ctx->gsh,
- state->attrs, state->filter);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, enum_groups_op_done, req);
-}
-
static void enum_groups_op_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,