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

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