dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone

Blame SOURCES/0079-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch

71e593
From 57fc60c9dc77698cf824813c36eb0f90d767b315 Mon Sep 17 00:00:00 2001
71e593
From: Jakub Hrozek <jhrozek@redhat.com>
71e593
Date: Thu, 22 Nov 2018 12:17:51 +0100
71e593
Subject: [PATCH 79/80] LDAP: Only authenticate the auth connection if we need
71e593
 to look up user information
71e593
71e593
Related:
71e593
https://pagure.io/SSSD/sssd/issue/3451
71e593
71e593
Commit add72860c7a7a2c418f4d8b6790b5caeaf7dfb7b initially addressed #3451 by
71e593
using the full sdap_cli_connect() request during LDAP authentication. This
71e593
was a good idea as it addressed the case where the authentication connection
71e593
must also look up some user information (typically with id_provider=proxy
71e593
where you don't know the DN to bind as during authentication), but this
71e593
approach also broke the use-case of id_provider=ldap and auth_provider=ldap
71e593
with ldap_sasl_auth=gssapi.
71e593
71e593
This is because (for reason I don't know) AD doesn't like if you use
71e593
both GSSAPI and startTLS on the same connection. But the code would
71e593
force TLS during the authentication as a general measure to not transmit
71e593
passwords in the clear, but then, the connection would also see that
71e593
ldap_sasl_auth=gssapi is set and also bind with GSSAPI.
71e593
71e593
This patch checks if the user DN is already known and if yes, then
71e593
doesn't authenticate the connection as the connection will then only be
71e593
used for the user simple bind.
71e593
71e593
Reviewed-by: Sumit Bose <sbose@redhat.com>
71e593
---
71e593
 src/providers/ldap/ldap_auth.c | 53 +++++++++++++++++++++++++++-------
71e593
 1 file changed, 42 insertions(+), 11 deletions(-)
71e593
71e593
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
71e593
index c409353d9..b4d045a65 100644
71e593
--- a/src/providers/ldap/ldap_auth.c
71e593
+++ b/src/providers/ldap/ldap_auth.c
71e593
@@ -664,6 +664,18 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
71e593
         state->sdap_service = ctx->service;
71e593
     }
71e593
 
71e593
+    ret = get_user_dn(state, state->ctx->be->domain,
71e593
+                      state->ctx->opts, state->username, &state->dn,
71e593
+                      &state->pw_expire_type, &state->pw_expire_data);
71e593
+    if (ret == EAGAIN) {
71e593
+        DEBUG(SSSDBG_TRACE_FUNC,
71e593
+              "Need to look up the DN of %s later\n", state->username);
71e593
+    } else if (ret != EOK) {
71e593
+        DEBUG(SSSDBG_OP_FAILURE,
71e593
+              "Cannot get user DN [%d]: %s\n", ret, sss_strerror(ret));
71e593
+        goto fail;
71e593
+    }
71e593
+
71e593
     if (auth_connect_send(req) == NULL) {
71e593
         ret = ENOMEM;
71e593
         goto fail;
71e593
@@ -683,6 +695,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
71e593
     struct auth_state *state = tevent_req_data(req,
71e593
                                                struct auth_state);
71e593
     bool use_tls;
71e593
+    bool skip_conn_auth = false;
71e593
+    const char *sasl_mech;
71e593
 
71e593
     /* Check for undocumented debugging feature to disable TLS
71e593
      * for authentication. This should never be used in production
71e593
@@ -695,10 +709,33 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
71e593
                                "for debugging purposes only.");
71e593
     }
71e593
 
71e593
+    if (state->dn != NULL) {
71e593
+        /* In case the user's DN is known, the connection will only be used
71e593
+         * to bind as the user to perform the authentication. In that case,
71e593
+         * we don't need to authenticate the connection, because we're not
71e593
+         * looking up any information using the connection. This might be
71e593
+         * needed e.g. in case both ID and AUTH providers are set to LDAP
71e593
+         * and the server is AD, because otherwise the connection would
71e593
+         * both do a startTLS and later bind using GSSAPI which doesn't work
71e593
+         * well with AD.
71e593
+         */
71e593
+        skip_conn_auth = true;
71e593
+    }
71e593
+
71e593
+    if (skip_conn_auth == false) {
71e593
+        sasl_mech = dp_opt_get_string(state->ctx->opts->basic,
71e593
+                                      SDAP_SASL_MECH);
71e593
+        if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) {
71e593
+            /* Don't force TLS on if we're told to use GSSAPI */
71e593
+            use_tls = false;
71e593
+        }
71e593
+    }
71e593
+
71e593
     subreq = sdap_cli_connect_send(state, state->ev, state->ctx->opts,
71e593
                                    state->ctx->be,
71e593
                                    state->sdap_service, false,
71e593
-                                   use_tls ? CON_TLS_ON : CON_TLS_OFF, false);
71e593
+                                   use_tls ? CON_TLS_ON : CON_TLS_OFF,
71e593
+                                   skip_conn_auth);
71e593
 
71e593
     if (subreq == NULL) {
71e593
         tevent_req_error(req, ENOMEM);
71e593
@@ -739,15 +776,7 @@ static void auth_connect_done(struct tevent_req *subreq)
71e593
         return;
71e593
     }
71e593
 
71e593
-    ret = get_user_dn(state, state->ctx->be->domain,
71e593
-                      state->ctx->opts, state->username, &state->dn,
71e593
-                      &state->pw_expire_type, &state->pw_expire_data);
71e593
-    if (ret == EOK) {
71e593
-        /* All required user data was pre-cached during an identity lookup.
71e593
-         * We can proceed with the bind */
71e593
-        auth_do_bind(req);
71e593
-        return;
71e593
-    } else if (ret == EAGAIN) {
71e593
+    if (state->dn == NULL) {
71e593
         /* The cached user entry was missing the bind DN. Need to look
71e593
          * it up based on user name in order to perform the bind */
71e593
         subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain,
71e593
@@ -760,7 +789,9 @@ static void auth_connect_done(struct tevent_req *subreq)
71e593
         return;
71e593
     }
71e593
 
71e593
-    tevent_req_error(req, ret);
71e593
+    /* All required user data was pre-cached during an identity lookup.
71e593
+     * We can proceed with the bind */
71e593
+    auth_do_bind(req);
71e593
     return;
71e593
 }
71e593
 
71e593
-- 
71e593
2.19.1
71e593