Blob Blame History Raw
From f5d031ba41b1c297f95df61f013f1c7ef8bca275 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Sun, 12 May 2019 16:38:43 +0200
Subject: [PATCH 30/31] SDAP: allow GSS-SPNEGO for LDAP SASL bind as well

From the LDAP client perspective GSS-SPNEGO and GSSAPI are quite
similar. To support GSS-SPNEGO SSSD must make sure that a Kerberos
ticket is available before the LDAP SASL bind is started.

Related to https://pagure.io/SSSD/sssd/issue/4006

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 3b89934e831fa4e575e398fee6e4c3d4d24854eb)
---
 src/man/sssd-ldap.5.xml                    | 29 ++++++++++++----------
 src/providers/ad/ad_common.c               |  6 ++---
 src/providers/ad/ad_init.c                 |  2 +-
 src/providers/ldap/ldap_auth.c             | 10 ++++----
 src/providers/ldap/ldap_common.h           |  2 +-
 src/providers/ldap/ldap_init.c             |  2 +-
 src/providers/ldap/sdap.c                  |  9 +++++++
 src/providers/ldap/sdap.h                  |  2 ++
 src/providers/ldap/sdap_async_connection.c |  8 +++---
 9 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 25acc19e6..17c5523c0 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1805,8 +1805,8 @@
                     <term>ldap_sasl_mech (string)</term>
                     <listitem>
                         <para>
-                            Specify the SASL mechanism to use.
-                            Currently only GSSAPI is tested and supported.
+                            Specify the SASL mechanism to use.  Currently only
+                            GSSAPI and GSS-SPNEGO are tested and supported.
                         </para>
                         <para>
                             Default: not set
@@ -1818,13 +1818,14 @@
                     <term>ldap_sasl_authid (string)</term>
                     <listitem>
                         <para>
-                            Specify the SASL authorization id to use.
-                            When GSSAPI is used, this represents the Kerberos
-                            principal used for authentication to the directory.
-                            This option can either contain the full principal (for
-                            example host/myhost@EXAMPLE.COM) or just the principal name
-                            (for example host/myhost). By default, the value is not set
-                            and the following principals are used:
+                            Specify the SASL authorization id to use.  When
+                            GSSAPI/GSS-SPNEGO are used, this represents the
+                            Kerberos principal used for authentication to the
+                            directory.  This option can either contain the full
+                            principal (for example host/myhost@EXAMPLE.COM) or
+                            just the principal name (for example host/myhost).
+                            By default, the value is not set and the following
+                            principals are used:
                             <programlisting>
 hostname@REALM
 netbiosname$@REALM
@@ -1875,7 +1876,8 @@ host/*
                     <term>ldap_krb5_keytab (string)</term>
                     <listitem>
                         <para>
-                            Specify the keytab to use when using SASL/GSSAPI.
+                            Specify the keytab to use when using
+                            SASL/GSSAPI/GSS-SPNEGO.
                         </para>
                         <para>
                             Default: System keytab, normally <filename>/etc/krb5.keytab</filename>
@@ -1890,7 +1892,7 @@ host/*
                             Specifies that the id_provider should init
                             Kerberos credentials (TGT).
                             This action is performed only if SASL is used and
-                            the mechanism selected is GSSAPI.
+                            the mechanism selected is GSSAPI or GSS-SPNEGO.
                         </para>
                         <para>
                             Default: true
@@ -1903,7 +1905,7 @@ host/*
                     <listitem>
                         <para>
                             Specifies the lifetime in seconds of the TGT if
-                            GSSAPI is used.
+                            GSSAPI or GSS-SPNEGO is used.
                         </para>
                         <para>
                             Default: 86400 (24 hours)
@@ -1944,7 +1946,8 @@ host/*
                     <term>krb5_realm (string)</term>
                     <listitem>
                         <para>
-                            Specify the Kerberos REALM (for SASL/GSSAPI auth).
+                            Specify the Kerberos REALM (for
+                            SASL/GSSAPI/GSS-SPNEGO auth).
                         </para>
                         <para>
                             Default: System defaults, see <filename>/etc/krb5.conf</filename>
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 4d1800806..19d4b3d5a 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -577,7 +577,7 @@ _ad_servers_init(struct ad_service *service,
         if (resolv_is_address(list[j])) {
             DEBUG(SSSDBG_IMPORTANT_INFO,
                   "ad_server [%s] is detected as IP address, "
-                  "this can cause GSSAPI problems\n", list[j]);
+                  "this can cause GSSAPI/GSS-SPNEGO problems\n", list[j]);
         }
     }
 
@@ -1012,7 +1012,7 @@ ad_set_sdap_options(struct ad_options *ad_opts,
         goto done;
     }
 
-    /* Set the Kerberos Realm for GSSAPI */
+    /* Set the Kerberos Realm for GSSAPI or GSS-SPNEGO */
     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
     if (!krb5_realm) {
         /* Should be impossible, this is set in ad_get_common_options() */
@@ -1269,7 +1269,7 @@ ad_get_auth_options(TALLOC_CTX *mem_ctx,
            ad_servers);
 
     /* Set krb5 realm */
-    /* Set the Kerberos Realm for GSSAPI */
+    /* Set the Kerberos Realm for GSSAPI/GSS-SPNEGO */
     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
     if (!krb5_realm) {
         /* Should be impossible, this is set in ad_get_common_options() */
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 612d4587e..302bcae7d 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -56,7 +56,7 @@ static int ad_sasl_getopt(void *context, const char *plugin_name,
     if (!plugin_name || !result) {
         return SASL_FAIL;
     }
-    if (strcmp(plugin_name, "GSSAPI") != 0) {
+    if (!sdap_sasl_mech_needs_kinit(plugin_name)) {
         return SASL_FAIL;
     }
     if (strcmp(option, "ad_compat") != 0) {
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index de22689ae..86724e388 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -715,9 +715,9 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
          * we don't need to authenticate the connection, because we're not
          * looking up any information using the connection. This might be
          * needed e.g. in case both ID and AUTH providers are set to LDAP
-         * and the server is AD, because otherwise the connection would
-         * both do a startTLS and later bind using GSSAPI which doesn't work
-         * well with AD.
+         * and the server is AD, because otherwise the connection would both
+         * do a startTLS and later bind using GSSAPI or GSS-SPNEGO which
+         * doesn't work well with AD.
          */
         skip_conn_auth = true;
     }
@@ -725,8 +725,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
     if (skip_conn_auth == false) {
         sasl_mech = dp_opt_get_string(state->ctx->opts->basic,
                                       SDAP_SASL_MECH);
-        if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) {
-            /* Don't force TLS on if we're told to use GSSAPI */
+        if (sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
+            /* Don't force TLS on if we're told to use GSSAPI or GSS-SPNEGO */
             use_tls = false;
         }
     }
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 6647241b4..04548a388 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -65,7 +65,7 @@ struct sdap_id_ctx {
     struct be_ctx *be;
     struct sdap_options *opts;
 
-    /* If using GSSAPI */
+    /* If using GSSAPI or GSS-SPNEGO */
     struct krb5_service *krb5_service;
     /* connection to a server */
     struct sdap_id_conn_ctx *conn;
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 44b3e9ab3..352f0b656 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -365,7 +365,7 @@ static bool should_call_gssapi_init(struct sdap_options *opts)
         return false;
     }
 
-    if (strcasecmp(sasl_mech, "GSSAPI") != 0) {
+    if (!sdap_sasl_mech_needs_kinit(sasl_mech)) {
         return false;
     }
 
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 5c9d0a45d..5591a6718 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -904,6 +904,15 @@ errno_t setup_tls_config(struct dp_option *basic_opts)
     return EOK;
 }
 
+bool sdap_sasl_mech_needs_kinit(const char *sasl_mech)
+{
+    if (strcasecmp(sasl_mech, "GSSAPI") == 0
+            || strcasecmp(sasl_mech, "GSS-SPNEGO") == 0) {
+        return true;
+    }
+
+    return false;
+}
 
 bool sdap_check_sup_list(struct sup_list *l, const char *val)
 {
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 48061d389..dddcf5faf 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -619,6 +619,8 @@ bool sdap_check_sup_list(struct sup_list *l, const char *val);
 #define sdap_is_extension_supported(sh, ext_oid) \
     sdap_check_sup_list(&((sh)->supported_extensions), ext_oid)
 
+bool sdap_sasl_mech_needs_kinit(const char *mech);
+
 int build_attrs_from_map(TALLOC_CTX *memctx,
                          struct sdap_attr_map *map,
                          size_t size,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 8aacd6705..6bc271a91 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1605,14 +1605,14 @@ static void sdap_cli_connect_done(struct tevent_req *subreq)
     sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
 
     if (state->do_auth && sasl_mech && state->use_rootdse) {
-        /* check if server claims to support GSSAPI */
+        /* check if server claims to support the configured SASL MECH */
         if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
             tevent_req_error(req, ENOTSUP);
             return;
         }
     }
 
-    if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
+    if (state->do_auth && sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
         if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
             sdap_cli_kinit_step(req);
             return;
@@ -1690,14 +1690,14 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq)
     sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
 
     if (state->do_auth && sasl_mech && state->rootdse) {
-        /* check if server claims to support GSSAPI */
+        /* check if server claims to support the configured SASL MECH */
         if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
             tevent_req_error(req, ENOTSUP);
             return;
         }
     }
 
-    if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
+    if (state->do_auth && sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
         if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
             sdap_cli_kinit_step(req);
             return;
-- 
2.20.1