From f5d031ba41b1c297f95df61f013f1c7ef8bca275 Mon Sep 17 00:00:00 2001 From: Sumit Bose 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 (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 @@ ldap_sasl_mech (string) - 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. Default: not set @@ -1818,13 +1818,14 @@ ldap_sasl_authid (string) - 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: hostname@REALM netbiosname$@REALM @@ -1875,7 +1876,8 @@ host/* ldap_krb5_keytab (string) - Specify the keytab to use when using SASL/GSSAPI. + Specify the keytab to use when using + SASL/GSSAPI/GSS-SPNEGO. Default: System keytab, normally /etc/krb5.keytab @@ -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. Default: true @@ -1903,7 +1905,7 @@ host/* Specifies the lifetime in seconds of the TGT if - GSSAPI is used. + GSSAPI or GSS-SPNEGO is used. Default: 86400 (24 hours) @@ -1944,7 +1946,8 @@ host/* krb5_realm (string) - Specify the Kerberos REALM (for SASL/GSSAPI auth). + Specify the Kerberos REALM (for + SASL/GSSAPI/GSS-SPNEGO auth). Default: System defaults, see /etc/krb5.conf 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