summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/sdap_async_connection.c113
1 files changed, 103 insertions, 10 deletions
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index cc6c58aae..304505458 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1399,6 +1399,7 @@ struct sdap_cli_connect_state {
enum connect_tls force_tls;
bool do_auth;
+ bool use_tls;
};
static int sdap_cli_resolve_next(struct tevent_req *req);
@@ -1411,6 +1412,8 @@ static void sdap_cli_kinit_step(struct tevent_req *req);
static void sdap_cli_kinit_done(struct tevent_req *subreq);
static void sdap_cli_auth_step(struct tevent_req *req);
static void sdap_cli_auth_done(struct tevent_req *subreq);
+static errno_t sdap_cli_auth_reconnect(struct tevent_req *subreq);
+static void sdap_cli_auth_reconnect_done(struct tevent_req *subreq);
static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq);
static errno_t
@@ -1507,15 +1510,6 @@ static void sdap_cli_resolve_done(struct tevent_req *subreq)
struct sdap_cli_connect_state *state = tevent_req_data(req,
struct sdap_cli_connect_state);
int ret;
- bool use_tls;
-
- ret = decide_tls_usage(state->force_tls, state->opts->basic,
- state->service->uri, &use_tls);
-
- if (ret != EOK) {
- tevent_req_error(req, EINVAL);
- return;
- }
ret = be_resolve_server_recv(subreq, &state->srv);
talloc_zfree(subreq);
@@ -1527,10 +1521,18 @@ static void sdap_cli_resolve_done(struct tevent_req *subreq)
return;
}
+ ret = decide_tls_usage(state->force_tls, state->opts->basic,
+ state->service->uri, &state->use_tls);
+
+ if (ret != EOK) {
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
subreq = sdap_connect_send(state, state->ev, state->opts,
state->service->uri,
state->service->sockaddr,
- use_tls);
+ state->use_tls);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -1782,6 +1784,21 @@ static void sdap_cli_auth_step(struct tevent_req *req)
struct sss_auth_token *authtok;
errno_t ret;
+ /* It's possible that connection was terminated by server (e.g. #2435),
+ to overcome this try to connect again. */
+ if (state->sh == NULL || !state->sh->connected) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No connection available. "
+ "Trying to reconnect.\n");
+ ret = sdap_cli_auth_reconnect(req);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "sdap_cli_auth_reconnect failed: %d:[%s]",
+ ret, sss_strerror(ret));
+ tevent_req_error(req, ret);
+ }
+ return;
+ }
+
/* Set the LDAP expiration time
* If SASL has already set it, use the sooner of the two
*/
@@ -1843,6 +1860,82 @@ static void sdap_cli_auth_step(struct tevent_req *req)
tevent_req_set_callback(subreq, sdap_cli_auth_done, req);
}
+static errno_t sdap_cli_auth_reconnect(struct tevent_req *req)
+{
+ struct sdap_cli_connect_state *state;
+ struct tevent_req *subreq;
+ errno_t ret;
+
+ state = tevent_req_data(req, struct sdap_cli_connect_state);
+
+ ret = decide_tls_usage(state->force_tls, state->opts->basic,
+ state->service->uri, &state->use_tls);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ subreq = sdap_connect_send(state, state->ev, state->opts,
+ state->service->uri,
+ state->service->sockaddr,
+ state->use_tls);
+
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sdap_cli_auth_reconnect_done, req);
+
+ ret = EOK;
+
+done:
+ return ret;
+}
+
+static void sdap_cli_auth_reconnect_done(struct tevent_req *subreq)
+{
+ struct sdap_cli_connect_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_cli_connect_state);
+
+ talloc_zfree(state->sh);
+
+ ret = sdap_connect_recv(subreq, state, &state->sh);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* if TLS was used, the sdap handle is already marked as connected */
+ if (!state->use_tls) {
+ /* we need to mark handle as connected to allow anonymous bind */
+ ret = sdap_set_connected(state->sh, state->ev);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_set_connected() failed.\n");
+ goto done;
+ }
+ }
+
+ /* End request if reconnecting failed to avoid endless loop */
+ if (state->sh == NULL || !state->sh->connected) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to reconnect.\n");
+ ret = EIO;
+ goto done;
+ }
+
+ sdap_cli_auth_step(req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ }
+}
+
static void sdap_cli_auth_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,