summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/providers/ldap/ldap_id.c70
-rw-r--r--server/providers/ldap/sdap_async.c27
2 files changed, 83 insertions, 14 deletions
diff --git a/server/providers/ldap/ldap_id.c b/server/providers/ldap/ldap_id.c
index 5da21cd5..efd9e914 100644
--- a/server/providers/ldap/ldap_id.c
+++ b/server/providers/ldap/ldap_id.c
@@ -58,12 +58,22 @@ static bool is_offline(struct sdap_id_ctx *ctx)
{
time_t now = time(NULL);
+ /* check if we are past the offline blackout timeout */
if (ctx->went_offline + ctx->opts->offline_timeout < now) {
- return false;
+ ctx->offline = false;
}
+
return ctx->offline;
}
+static void mark_offline(struct sdap_id_ctx *ctx)
+{
+ DEBUG(8, ("Going offline!\n"));
+
+ ctx->went_offline = time(NULL);
+ ctx->offline = true;
+}
+
static void sdap_check_online(struct be_req *req)
{
struct be_online_req *oreq;
@@ -376,16 +386,26 @@ static void users_get_op_done(struct tevent_req *subreq)
static void users_get_done(struct tevent_req *req)
{
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
+ struct sdap_id_ctx *ctx;
enum tevent_req_state tstate;
uint64_t err;
const char *error = NULL;
int ret = EOK;
+
if (tevent_req_is_error(req, &tstate, &err)) {
ret = err;
}
- if (ret) error = "Enum Users Failed";
+ if (ret) {
+ error = "Enum Users Failed";
+
+ if (ret == ETIMEDOUT) {
+ ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
+ struct sdap_id_ctx);
+ mark_offline(ctx);
+ }
+ }
return sdap_req_done(breq, ret, error);
}
@@ -532,6 +552,7 @@ static void groups_get_op_done(struct tevent_req *subreq)
static void groups_get_done(struct tevent_req *req)
{
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
+ struct sdap_id_ctx *ctx;
enum tevent_req_state tstate;
uint64_t err;
const char *error = NULL;
@@ -541,7 +562,15 @@ static void groups_get_done(struct tevent_req *req)
ret = err;
}
- if (ret) error = "Enum Groups Failed";
+ if (ret) {
+ error = "Enum Groups Failed";
+
+ if (ret == ETIMEDOUT) {
+ ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
+ struct sdap_id_ctx);
+ mark_offline(ctx);
+ }
+ }
return sdap_req_done(breq, ret, error);
}
@@ -663,6 +692,7 @@ static void groups_by_user_op_done(struct tevent_req *subreq)
static void groups_by_user_done(struct tevent_req *req)
{
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
+ struct sdap_id_ctx *ctx;
enum tevent_req_state tstate;
uint64_t err;
const char *error = NULL;
@@ -672,7 +702,15 @@ static void groups_by_user_done(struct tevent_req *req)
ret = err;
}
- if (ret) error = "Init Groups Failed";
+ if (ret) {
+ error = "Init Groups Failed";
+
+ if (ret == ETIMEDOUT) {
+ ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
+ struct sdap_id_ctx);
+ mark_offline(ctx);
+ }
+ }
return sdap_req_done(breq, ret, error);
}
@@ -792,6 +830,13 @@ static void ldap_id_enumerate(struct tevent_context *ev,
struct tevent_timer *timeout;
struct tevent_req *req;
+ if (is_offline(ctx)) {
+ DEBUG(4, ("Backend is marked offline, retry later!\n"));
+ /* schedule starting from now, not the last run */
+ ldap_id_enumerate_set_timer(ctx, tevent_timeval_current());
+ return;
+ }
+
ctx->last_run = tv;
req = ldap_id_enumerate_send(ev, ctx);
@@ -894,7 +939,7 @@ static void ldap_id_enum_users_done(struct tevent_req *subreq)
struct global_enum_state *state = tevent_req_data(req,
struct global_enum_state);
enum tevent_req_state tstate;
- uint64_t err;
+ uint64_t err = 0;
if (tevent_req_is_error(subreq, &tstate, &err)) {
goto fail;
@@ -910,6 +955,15 @@ static void ldap_id_enum_users_done(struct tevent_req *subreq)
return;
fail:
+ if (err) {
+ DEBUG(9, ("User enumeration failed with: (%d)[%s]\n",
+ (int)err, strerror(err)));
+
+ if (err == ETIMEDOUT) {
+ mark_offline(state->ctx);
+ }
+ }
+
DEBUG(1, ("Failed to enumerate users, retrying later!\n"));
/* schedule starting from now, not the last run */
ldap_id_enumerate_set_timer(state->ctx, tevent_timeval_current());
@@ -936,6 +990,10 @@ static void ldap_id_enum_groups_done(struct tevent_req *subreq)
return;
fail:
+ if (err == ETIMEDOUT) {
+ mark_offline(state->ctx);
+ }
+
DEBUG(1, ("Failed to enumerate groups, retrying later!\n"));
/* schedule starting from now, not the last run */
ldap_id_enumerate_set_timer(state->ctx, tevent_timeval_current());
@@ -1118,7 +1176,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
- attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
+ attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
if (ctx->max_group_timestamp) {
state->filter = talloc_asprintf(state,
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 550cb9d3..15985fff 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -372,7 +372,7 @@ static void sdap_op_timeout(struct tevent_req *req)
}
/* signal the caller that we have a timeout */
- op->callback(op, NULL, ETIME, op->data);
+ op->callback(op, NULL, ETIMEDOUT, op->data);
/* send back to the server an abandon (see destructor) and free the op */
talloc_free(op);
@@ -534,7 +534,7 @@ fail:
tevent_req_error(req, ret);
} else {
if (lret == LDAP_SERVER_DOWN) {
- tevent_req_error(req, EAGAIN);
+ tevent_req_error(req, ETIMEDOUT);
} else {
tevent_req_error(req, EIO);
}
@@ -635,6 +635,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
struct simple_bind_state *state;
int ret = EOK;
int msgid;
+ int ldap_err;
req = tevent_req_create(memctx, &state, struct simple_bind_state);
if (!req) return NULL;
@@ -655,7 +656,16 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
ret = ldap_sasl_bind(state->sh->ldap, state->user_dn, LDAP_SASL_SIMPLE,
state->pw, NULL, NULL, &msgid);
if (ret == -1 || msgid == -1) {
- DEBUG(1, ("ldap_bind failed\n"));
+ 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;
+ }
goto fail;
}
DEBUG(8, ("ldap simple bind sent, msgid = %d\n", msgid));
@@ -678,7 +688,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
fail:
if (ret == LDAP_SERVER_DOWN) {
- tevent_req_error(req, EAGAIN);
+ tevent_req_error(req, ETIMEDOUT);
} else {
tevent_req_error(req, EIO);
}
@@ -726,11 +736,12 @@ static int simple_bind_recv(struct tevent_req *req, int *ldaperr)
if (tevent_req_is_error(req, &tstate, &err)) {
*ldaperr = LDAP_OTHER;
- return -1;
+ if (err) return err;
+ return EIO;
}
*ldaperr = state->result;
- return 0;
+ return EOK;
}
/* ==Authenticaticate-User-by-DN========================================== */
@@ -790,8 +801,8 @@ static void sdap_auth_done(struct tevent_req *subreq)
int ret;
ret = simple_bind_recv(subreq, &state->result);
- if (ret == -1) {
- tevent_req_error(req, EFAULT);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
return;
}
tevent_req_done(req);