summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2014-09-15 14:13:21 +0100
committerJakub Hrozek <jhrozek@redhat.com>2014-10-12 18:27:31 +0200
commitdaa3dd779fbaec36142d112f8a47c7b9f23177c1 (patch)
tree5da4cecd5f858bbdd15a3e56638edd63a0e207ec
parent28929b67fed17df3b7622bb48ed3700f944d91d0 (diff)
downloadsssd-daa3dd779fbaec36142d112f8a47c7b9f23177c1.tar.gz
sssd-daa3dd779fbaec36142d112f8a47c7b9f23177c1.tar.xz
sssd-daa3dd779fbaec36142d112f8a47c7b9f23177c1.zip
SDAP: check that connection is open before bind
Tivoli server does not return an empty response when being asked for the rootDSE data but an error. In this case the rootDSE lookup in SSSD will terminate the connection to the server and return a error. But since errors except timeouts are ignored SSSD will try to continue with the bind, but since the connection is already terminated this will fail as well. And this will terminate the whole operation. Make sure the connection is open before performing bind operation. Resolves: https://fedorahosted.org/sssd/ticket/2435 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-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,