diff --git a/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch b/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch new file mode 100644 index 0000000..91d15c4 --- /dev/null +++ b/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch @@ -0,0 +1,655 @@ +From c2e8879189ecbbdfdd4b42395319a4cd91cb569f Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Fri, 12 Feb 2021 20:02:52 +0100 +Subject: [PATCH] pam_sss_gss: support authentication indicators (upstream +patch 5ce7ced269c7b3dd8f75122a50f539083b5697ae by Alexander Bokovoy) + +MIT Kerberos allows to associate authentication indicators with the +issued ticket based on the way how the TGT was obtained. The indicators +present in the TGT then copied to service tickets. There are two ways to +check the authentication indicators: + + - when KDC issues a service ticket, a policy at KDC side can reject the + ticket issuance based on a lack of certain indicator + + - when a server application presented with a service ticket from a + client, it can verify that this ticket contains intended + authentication indicators before authorizing access from the client. + +Add support to validate presence of a specific (set of) authentication +indicator(s) in pam_sss_gss when validating a user's TGT. + +This concept can be used to only allow access to a PAM service when user +is in possession of a ticket obtained using some of pre-authentication +mechanisms that require multiple factors: smart-cards (PKINIT), 2FA +tokens (otp/radius), etc. + +Patch by: Alexander Bokovoy + +Reviewed by: Sumit Bose + +Adapted to 8.4 branch by: Alexey Tikhonov +--- + src/confdb/confdb.c | 13 ++ + src/confdb/confdb.h | 3 + + src/config/SSSDConfig/sssdoptions.py | 2 + + src/config/SSSDConfigTest.py | 6 +- + src/config/cfg_rules.ini | 3 + + src/config/etc/sssd.api.conf | 2 + + src/db/sysdb_subdomains.c | 12 ++ + src/man/pam_sss_gss.8.xml | 13 ++ + src/man/sssd.conf.5.xml | 64 +++++++ + src/responder/pam/pamsrv.c | 21 +++ + src/responder/pam/pamsrv.h | 2 + + src/responder/pam/pamsrv_gssapi.c | 250 +++++++++++++++++++++++++++ + 12 files changed, 389 insertions(+), 2 deletions(-) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index befcfff..cca7615 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -1603,6 +1603,19 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + } + } + ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP, ++ NULL); ++ if (tmp != NULL && tmp[0] != '\0') { ++ ret = split_on_separator(domain, tmp, ',', true, true, ++ &domain->gssapi_indicators_map, NULL); ++ if (ret != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Cannot parse %s\n", CONFDB_PAM_GSSAPI_INDICATORS_MAP); ++ goto done; ++ } ++ } ++ + domain->has_views = false; + domain->view_name = NULL; + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 036f9ec..a2be227 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -146,6 +146,7 @@ + #define CONFDB_PAM_INITGROUPS_SCHEME "pam_initgroups_scheme" + #define CONFDB_PAM_GSSAPI_SERVICES "pam_gssapi_services" + #define CONFDB_PAM_GSSAPI_CHECK_UPN "pam_gssapi_check_upn" ++#define CONFDB_PAM_GSSAPI_INDICATORS_MAP "pam_gssapi_indicators_map" + + /* SUDO */ + #define CONFDB_SUDO_CONF_ENTRY "config/sudo" +@@ -437,6 +438,8 @@ struct sss_domain_info { + /* List of PAM services that are allowed to authenticate with GSSAPI. */ + char **gssapi_services; + char *gssapi_check_upn; /* true | false | NULL */ ++ /* List of indicators associated with the specific PAM service */ ++ char **gssapi_indicators_map; + }; + + /** +diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py +index 5da52a9..0d849bc 100644 +--- a/src/config/SSSDConfig/sssdoptions.py ++++ b/src/config/SSSDConfig/sssdoptions.py +@@ -106,6 +106,8 @@ class SSSDOptions(object): + 'pam_initgroups_scheme' : _('When shall the PAM responder force an initgroups request'), + 'pam_gssapi_services' : _('List of PAM services that are allowed to authenticate with GSSAPI.'), + 'pam_gssapi_check_upn' : _('Whether to match authenticated UPN with target user'), ++ 'pam_gssapi_indicators_map' : _('List of pairs : that ' ++ 'must be enforced for PAM access with GSSAPI authentication'), + + # [sudo] + 'sudo_timed': _('Whether to evaluate the time-based attributes in sudo rules'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index ea4e4f6..d0422df 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -655,7 +655,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'cached_auth_timeout', + 'auto_private_groups', + 'pam_gssapi_services', +- 'pam_gssapi_check_upn'] ++ 'pam_gssapi_check_upn', ++ 'pam_gssapi_indicators_map'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +@@ -1034,7 +1035,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'cached_auth_timeout', + 'auto_private_groups', + 'pam_gssapi_services', +- 'pam_gssapi_check_upn'] ++ 'pam_gssapi_check_upn', ++ 'pam_gssapi_indicators_map'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 6642c63..872ceba 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -141,6 +141,7 @@ option = p11_uri + option = pam_initgroups_scheme + option = pam_gssapi_services + option = pam_gssapi_check_upn ++option = pam_gssapi_indicators_map + + [rule/allowed_sudo_options] + validator = ini_allowed_options +@@ -441,6 +442,7 @@ option = re_expression + option = auto_private_groups + option = pam_gssapi_services + option = pam_gssapi_check_upn ++option = pam_gssapi_indicators_map + + #Entry cache timeouts + option = entry_cache_user_timeout +@@ -837,6 +839,7 @@ option = use_fully_qualified_names + option = auto_private_groups + option = pam_gssapi_services + option = pam_gssapi_check_upn ++option = pam_gssapi_indicators_map + + [rule/sssd_checks] + validator = sssd_checks +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index d3cad73..49ced63 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -82,6 +82,7 @@ p11_uri = str, None, false + pam_initgroups_scheme = str, None, false + pam_gssapi_services = str, None, false + pam_gssapi_check_upn = bool, None, false ++pam_gssapi_indicators_map = str, None, false + + [sudo] + # sudo service +@@ -203,6 +204,7 @@ re_expression = str, None, false + auto_private_groups = str, None, false + pam_gssapi_services = str, None, false + pam_gssapi_check_upn = bool, None, false ++pam_gssapi_indicators_map = str, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index 03ba121..2243872 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -185,6 +185,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + dom->override_gid = parent->override_gid; + + dom->gssapi_services = parent->gssapi_services; ++ dom->gssapi_indicators_map = parent->gssapi_indicators_map; + + if (parent->sysdb == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n"); +@@ -266,6 +267,17 @@ check_subdom_config_file(struct confdb_ctx *confdb, + goto done; + } + ++ /* allow to set pam_gssapi_indicators_map */ ++ ret = confdb_get_string_as_list(confdb, subdomain, sd_conf_path, ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP, ++ &subdomain->gssapi_indicators_map); ++ if (ret != EOK && ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to get %s option for the subdomain: %s\n", ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP, subdomain->name); ++ goto done; ++ } ++ + ret = EOK; + done: + talloc_free(tmp_ctx); +diff --git a/src/man/pam_sss_gss.8.xml b/src/man/pam_sss_gss.8.xml +index ce5b11b..a83369d 100644 +--- a/src/man/pam_sss_gss.8.xml ++++ b/src/man/pam_sss_gss.8.xml +@@ -70,6 +70,19 @@ + 5 + for more details on these options. + ++ ++ Some Kerberos deployments allow to assocate authentication ++ indicators with a particular pre-authentication method used to ++ obtain the ticket granting ticket by the user. ++ pam_sss_gss.so allows to enforce presence of ++ authentication indicators in the service tickets before a particular ++ PAM service can be accessed. ++ ++ ++ If is set in the [pam] or ++ domain section of sssd.conf, then SSSD will perform a check of the ++ presence of any configured indicators in the service ticket. ++ + + + +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index 8b330de..3a9955b 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -1770,6 +1770,70 @@ pam_gssapi_services = sudo, sudo-i + + + ++ ++ pam_gssapi_indicators_map ++ ++ ++ Comma separated list of authentication indicators required ++ to be present in a Kerberos ticket to access a PAM service ++ that is allowed to try GSSAPI authentication using ++ pam_sss_gss.so module. ++ ++ ++ Each element of the list can be either an authentication indicator ++ name or a pair service:indicator. Indicators not ++ prefixed with the PAM service name will be required to access any ++ PAM service configured to be used with ++ . A resulting list of indicators ++ per PAM service is then checked against indicators in the Kerberos ++ ticket during authentication by pam_sss_gss.so. Any indicator from the ++ ticket that matches the resulting list of indicators for the PAM service ++ would grant access. If none of the indicators in the list match, access ++ will be denied. If the resulting list of indicators for the PAM service ++ is empty, the check will not prevent the access. ++ ++ ++ To disable GSSAPI authentication indicator check, set this option ++ to - (dash). To disable the check for a specific PAM ++ service, add service:-. ++ ++ ++ Note: This option can also be set per-domain which ++ overwrites the value in [pam] section. It can also ++ be set for trusted domain which overwrites the value ++ in the domain section. ++ ++ ++ Following authentication indicators are supported by IPA Kerberos deployments: ++ ++ ++ pkinit -- pre-authentication using X.509 certificates -- whether stored in files or on smart cards. ++ ++ ++ hardened -- SPAKE pre-authentication or any pre-authentication wrapped in a FAST channel. ++ ++ ++ radius -- pre-authentication with the help of a RADIUS server. ++ ++ ++ otp -- pre-authentication using integrated two-factor authentication (2FA or one-time password, OTP) in IPA. ++ ++ ++ ++ ++ Example: to require access to SUDO services only ++ for users which obtained their Kerberos tickets ++ with a X.509 certificate pre-authentication ++ (PKINIT), set ++ ++pam_gssapi_indicators_map = sudo:pkinit, sudo-i:pkinit ++ ++ ++ ++ Default: not set (use of authentication indicators is not required) ++ ++ ++ + + + +diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c +index 3904c09..9b4d6c1 100644 +--- a/src/responder/pam/pamsrv.c ++++ b/src/responder/pam/pamsrv.c +@@ -370,6 +370,27 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, + goto done; + } + ++ ret = confdb_get_string(pctx->rctx->cdb, pctx, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP, "-", &tmpstr); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Failed to determine gssapi services.\n"); ++ goto done; ++ } ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Found value [%s] for option [%s].\n", tmpstr, ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP); ++ ++ if (tmpstr != NULL) { ++ ret = split_on_separator(pctx, tmpstr, ',', true, true, ++ &pctx->gssapi_indicators_map, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "split_on_separator() failed [%d]: [%s].\n", ret, ++ sss_strerror(ret)); ++ goto done; ++ } ++ } ++ + /* The responder is initialized. Now tell it to the monitor. */ + ret = sss_monitor_service_init(rctx, rctx->ev, SSS_BUS_PAM, + SSS_PAM_SBUS_SERVICE_NAME, +diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h +index 3553296..383c7be 100644 +--- a/src/responder/pam/pamsrv.h ++++ b/src/responder/pam/pamsrv.h +@@ -65,6 +65,8 @@ struct pam_ctx { + + /* List of PAM services that are allowed to authenticate with GSSAPI. */ + char **gssapi_services; ++ /* List of authentication indicators associated with a PAM service */ ++ char **gssapi_indicators_map; + bool gssapi_check_upn; + }; + +diff --git a/src/responder/pam/pamsrv_gssapi.c b/src/responder/pam/pamsrv_gssapi.c +index 2d05c78..e4da4c4 100644 +--- a/src/responder/pam/pamsrv_gssapi.c ++++ b/src/responder/pam/pamsrv_gssapi.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -83,6 +84,117 @@ static bool pam_gssapi_should_check_upn(struct pam_ctx *pam_ctx, + return pam_ctx->gssapi_check_upn; + } + ++static int pam_gssapi_check_indicators(TALLOC_CTX *mem_ctx, ++ const char *pam_service, ++ char **gssapi_indicators_map, ++ char **indicators) ++{ ++ char *authind = NULL; ++ size_t pam_len = strlen(pam_service); ++ char **map = gssapi_indicators_map; ++ char **result = NULL; ++ int res; ++ ++ authind = talloc_strdup(mem_ctx, ""); ++ if (authind == NULL) { ++ return ENOMEM; ++ } ++ ++ for (int i = 0; map[i]; i++) { ++ if (map[i][0] == '-') { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Indicators aren't used for [%s]\n", ++ pam_service); ++ talloc_free(authind); ++ return EOK; ++ } ++ if (!strchr(map[i], ':')) { ++ authind = talloc_asprintf_append(authind, "%s ", map[i]); ++ if (authind == NULL) { ++ /* Since we allocate on pam_ctx, caller will free it */ ++ return ENOMEM; ++ } ++ continue; ++ } ++ ++ res = strncmp(map[i], pam_service, pam_len); ++ if (res == 0) { ++ if (strlen(map[i]) > pam_len) { ++ if (map[i][pam_len] != ':') { ++ /* different PAM service, skip it */ ++ continue; ++ } ++ ++ if (map[i][pam_len + 1] == '-') { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Indicators aren't used for [%s]\n", ++ pam_service); ++ talloc_free(authind); ++ return EOK; ++ } ++ ++ authind = talloc_asprintf_append(authind, "%s ", ++ map[i] + (pam_len + 1)); ++ if (authind == NULL) { ++ /* Since we allocate on pam_ctx, caller will free it */ ++ return ENOMEM; ++ } ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Invalid value for %s: [%s]\n", ++ CONFDB_PAM_GSSAPI_INDICATORS_MAP, map[i]); ++ talloc_free(authind); ++ return EINVAL; ++ } ++ } ++ } ++ ++ res = ENOENT; ++ map = NULL; ++ ++ if (authind[0] == '\0') { ++ /* empty list of per-service indicators -> skip */ ++ goto done; ++ } ++ ++ /* trim a space after the final indicator ++ * to prevent split_on_separator() to fail */ ++ authind[strlen(authind) - 1] = '\0'; ++ ++ res = split_on_separator(mem_ctx, authind, ' ', true, true, ++ &map, NULL); ++ if (res != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Cannot parse list of indicators: [%s]\n", authind); ++ res = EINVAL; ++ goto done; ++ } ++ ++ res = diff_string_lists(mem_ctx, indicators, map, NULL, NULL, &result); ++ if (res != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE,"Cannot diff lists of indicators\n"); ++ res = EINVAL; ++ goto done; ++ } ++ ++ if (result && result[0] != NULL) { ++ for (int i = 0; result[i]; i++) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "indicator [%s] is allowed for PAM service [%s]\n", ++ result[i], pam_service); ++ } ++ res = EOK; ++ goto done; ++ } ++ ++ res = EPERM; ++ ++done: ++ talloc_free(result); ++ talloc_free(authind); ++ talloc_free(map); ++ return res; ++} ++ + static bool pam_gssapi_allowed(struct pam_ctx *pam_ctx, + struct sss_domain_info *domain, + const char *service) +@@ -385,12 +497,126 @@ static char *gssapi_get_name(TALLOC_CTX *mem_ctx, gss_name_t gss_name) + return exported; + } + ++#define AUTH_INDICATORS_TAG "auth-indicators" ++ ++static char **gssapi_get_indicators(TALLOC_CTX *mem_ctx, gss_name_t gss_name) ++{ ++ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; ++ int is_mechname; ++ OM_uint32 major; ++ OM_uint32 minor; ++ gss_buffer_desc value = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER; ++ char *exported = NULL; ++ char **map = NULL; ++ int res; ++ ++ major = gss_inquire_name(&minor, gss_name, &is_mechname, NULL, &attrs); ++ if (major != GSS_S_COMPLETE) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to inquire name\n"); ++ return NULL; ++ } ++ ++ if (attrs == GSS_C_NO_BUFFER_SET) { ++ DEBUG(SSSDBG_TRACE_FUNC, "No krb5 attributes in the ticket\n"); ++ return NULL; ++ } ++ ++ exported = talloc_strdup(mem_ctx, ""); ++ if (exported == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to pre-allocate indicators\n"); ++ goto done; ++ } ++ ++ for (int i = 0; i < attrs->count; i++) { ++ int authenticated = 0; ++ int complete = 0; ++ int more = -1; ++ ++ /* skip anything but auth-indicators */ ++ if (strncmp(AUTH_INDICATORS_TAG, attrs->elements[i].value, ++ sizeof(AUTH_INDICATORS_TAG) - 1) != 0) ++ continue; ++ ++ /* retrieve all indicators */ ++ while (more != 0) { ++ value.value = NULL; ++ display_value.value = NULL; ++ ++ major = gss_get_name_attribute(&minor, gss_name, ++ &attrs->elements[i], ++ &authenticated, ++ &complete, &value, ++ &display_value, ++ &more); ++ if (major != GSS_S_COMPLETE) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to retrieve an attribute\n"); ++ goto done; ++ } ++ ++ if ((value.value != NULL) && authenticated) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "attribute's [%.*s] value [%.*s] authenticated\n", ++ (int) attrs->elements[i].length, ++ (char*) attrs->elements[i].value, ++ (int) value.length, ++ (char*) value.value); ++ exported = talloc_asprintf_append(exported, "%.*s ", ++ (int) value.length, ++ (char*) value.value); ++ } ++ ++ if (exported == NULL) { ++ /* Since we allocate on mem_ctx, caller will free ++ * the previous version of 'exported' */ ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to collect an attribute value\n"); ++ goto done; ++ } ++ (void) gss_release_buffer(&minor, &value); ++ (void) gss_release_buffer(&minor, &display_value); ++ } ++ } ++ ++ if (exported[0] != '\0') { ++ /* trim a space after the final indicator ++ * to prevent split_on_separator() to fail */ ++ exported[strlen(exported) - 1] = '\0'; ++ } else { ++ /* empty list */ ++ goto done; ++ } ++ ++ res = split_on_separator(mem_ctx, exported, ' ', true, true, ++ &map, NULL); ++ if (res != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Cannot parse list of indicators: [%s]\n", exported); ++ goto done; ++ } else { ++ DEBUG(SSSDBG_TRACE_FUNC, "authentication indicators: [%s]\n", ++ exported); ++ } ++ ++done: ++ (void) gss_release_buffer(&minor, &value); ++ (void) gss_release_buffer(&minor, &display_value); ++ (void) gss_release_buffer_set(&minor, &attrs); ++ ++ talloc_free(exported); ++ return map; ++} ++ ++ + struct gssapi_state { + struct cli_ctx *cli_ctx; + struct sss_domain_info *domain; + const char *username; + + char *authenticated_upn; ++ char **auth_indicators; + bool established; + gss_ctx_id_t ctx; + }; +@@ -568,6 +794,8 @@ gssapi_handshake(struct gssapi_state *state, + DEBUG(SSSDBG_TRACE_FUNC, "Security context established with [%s]\n", + state->authenticated_upn); + ++ state->auth_indicators = gssapi_get_indicators(state, client_name); ++ + state->established = true; + ret = EOK; + +@@ -632,6 +860,7 @@ pam_cmd_gssapi_sec_ctx(struct cli_ctx *cli_ctx) + const char *domain_name; + const char *username; + char *target; ++ char **indicators_map = NULL; + size_t gss_data_len; + uint8_t *gss_data; + errno_t ret; +@@ -699,6 +928,27 @@ pam_cmd_gssapi_sec_ctx(struct cli_ctx *cli_ctx) + goto done; + } + ++ /* Use map for auth-indicators from the domain, if defined and ++ * fallback to the [pam] section otherwise */ ++ indicators_map = domain->gssapi_indicators_map ? ++ domain->gssapi_indicators_map : ++ (pam_ctx->gssapi_indicators_map ? ++ pam_ctx->gssapi_indicators_map : NULL); ++ if (indicators_map != NULL) { ++ ret = pam_gssapi_check_indicators(state, ++ pam_service, ++ indicators_map, ++ state->auth_indicators); ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Check if acquired service ticket has req. indicators: %d\n", ++ ret); ++ if ((ret == EPERM) || (ret == ENOMEM) || (ret == EINVAL)) { ++ /* skip further checks if denied or no memory, ++ * ENOENT means the check is not applicable */ ++ goto done; ++ } ++ } ++ + if (!pam_gssapi_should_check_upn(pam_ctx, domain)) { + /* We are done. */ + goto done; +-- +2.21.3 + diff --git a/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch b/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch new file mode 100644 index 0000000..af99e4f --- /dev/null +++ b/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch @@ -0,0 +1,121 @@ +From b100efbfabd96dcfb2825777b75b9a9dfaacb937 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 29 Jan 2021 12:41:28 +0100 +Subject: [PATCH] sudo: do not search by low usn value to improve performance + +This is a follow up on these two commits. + +- 819d70ef6e6fa0e736ebd60a7f8a26f672927d57 +- 6815844daa7701c76e31addbbdff74656cd30bea + +The first one improved the search filter little bit to achieve better +performance, however it also changed the behavior: we started to search +for `usn >= 1` in the filter if no usn number was known. + +This caused issues on OpenLDAP server which was fixed by the second patch. +However, the fix was wrong and searching by this meaningfully low number +can cause performance issues depending on how the filter is optimized and +evaluated on the server. + +Now we omit the usn attribute from the filter if there is no meaningful value. + +How to test: +1. Setup LDAP with no sudo rules defined +2. Make sure that the LDAP server does not support USN or use the following diff + to enforce modifyTimestamp (last USN is always available from rootDSE) +```diff + +Reviewed-by: Alexey Tikhonov +--- + src/providers/ldap/sdap.c | 4 ++-- + src/providers/ldap/sdap_sudo_refresh.c | 6 ++++-- + src/providers/ldap/sdap_sudo_shared.c | 21 ++++++--------------- + 3 files changed, 12 insertions(+), 19 deletions(-) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index 32c0144b9..c853e4dc1 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1391,7 +1391,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name; + entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name; + if (rootdse) { +- if (last_usn_name) { ++ if (false) { + ret = sysdb_attrs_get_string(rootdse, + last_usn_name, &last_usn_value); + if (ret != EOK) { +@@ -1500,7 +1500,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + } + } + +- if (!last_usn_name) { ++ if (true) { + DEBUG(SSSDBG_FUNC_DATA, + "No known USN scheme is supported by this server!\n"); + if (!entry_usn_name) { +diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c +index ddcb23781..83f944ccf 100644 +--- a/src/providers/ldap/sdap_sudo_refresh.c ++++ b/src/providers/ldap/sdap_sudo_refresh.c +@@ -181,8 +181,10 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, + state->sysdb = id_ctx->be->domain->sysdb; + + /* Download all rules from LDAP that are newer than usn */ +- if (srv_opts == NULL || srv_opts->max_sudo_value == 0) { +- DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n"); ++ if (srv_opts == NULL || srv_opts->max_sudo_value == NULL ++ || strcmp(srv_opts->max_sudo_value, "0") == 0) { ++ DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and " ++ "omitting it from the filter.\n"); + usn = "0"; + search_filter = talloc_asprintf(state, "(%s=%s)", + map[SDAP_AT_SUDO_OC].name, +diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c +index 4f09957ea..75d1bc3d8 100644 +--- a/src/providers/ldap/sdap_sudo_shared.c ++++ b/src/providers/ldap/sdap_sudo_shared.c +@@ -129,25 +129,17 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx, + static char * + sdap_sudo_new_usn(TALLOC_CTX *mem_ctx, + unsigned long usn, +- const char *leftover, +- bool supports_usn) ++ const char *leftover) + { + const char *str = leftover == NULL ? "" : leftover; + char *newusn; + +- /* This is a fresh start and server uses modifyTimestamp. We need to +- * provide proper datetime value. */ +- if (!supports_usn && usn == 0) { +- newusn = talloc_strdup(mem_ctx, "00000101000000Z"); +- if (newusn == NULL) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n"); +- return NULL; +- } +- +- return newusn; ++ /* Current largest USN is unknown so we keep "0" to indicate it. */ ++ if (usn == 0) { ++ return talloc_strdup(mem_ctx, "0"); + } + +- /* We increment USN number so that we can later use simplify filter ++ /* We increment USN number so that we can later use simplified filter + * (just usn >= last+1 instead of usn >= last && usn != last). + */ + usn++; +@@ -219,8 +211,7 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, + srv_opts->last_usn = usn_number; + } + +- newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone, +- srv_opts->supports_usn); ++ newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone); + if (newusn == NULL) { + return; + } +-- +2.21.3 + diff --git a/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch b/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch new file mode 100644 index 0000000..ae6dfb7 --- /dev/null +++ b/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch @@ -0,0 +1,34 @@ +From fff02bbf7967d291ccb019fae741e6591ed8fd41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 12 Feb 2021 15:30:59 +0100 +Subject: [PATCH] ldap: fix modifytimestamp debugging leftovers + +--- + src/providers/ldap/sdap.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index c853e4dc1..32c0144b9 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1391,7 +1391,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name; + entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name; + if (rootdse) { +- if (false) { ++ if (last_usn_name) { + ret = sysdb_attrs_get_string(rootdse, + last_usn_name, &last_usn_value); + if (ret != EOK) { +@@ -1500,7 +1500,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + } + } + +- if (true) { ++ if (!last_usn_name) { + DEBUG(SSSDBG_FUNC_DATA, + "No known USN scheme is supported by this server!\n"); + if (!entry_usn_name) { +-- +2.21.3 + diff --git a/SOURCES/0047-ssh-restore-default-debug-level.patch b/SOURCES/0047-ssh-restore-default-debug-level.patch new file mode 100644 index 0000000..7b29783 --- /dev/null +++ b/SOURCES/0047-ssh-restore-default-debug-level.patch @@ -0,0 +1,49 @@ +From 2d26c95d78cf43798b54ac8c478b8a9ee41cab39 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 3 Feb 2021 18:28:29 +0100 +Subject: [PATCH] ssh: restore default debug level + +The recent change of the default debug level for the main SSSD +components affected the ssh helpers sss_ssh_authorizedkeys and +sss_ssh_knownhostsproxy as well. + +To avoid any confusion about unexpected debug messages this patch +restores to original value for the two helpers. + +Resolves: https://github.com/SSSD/sssd/issues/5488 + +Reviewed-by: Alexey Tikhonov +--- + src/sss_client/ssh/sss_ssh_authorizedkeys.c | 2 +- + src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c +index 8e80f9663..877c00299 100644 +--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c ++++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c +@@ -32,7 +32,7 @@ + int main(int argc, const char **argv) + { + TALLOC_CTX *mem_ctx = NULL; +- int pc_debug = SSSDBG_DEFAULT; ++ int pc_debug = SSSDBG_FATAL_FAILURE; + const char *pc_domain = NULL; + const char *pc_user = NULL; + struct poptOption long_options[] = { +diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c +index ad6af81d8..1102fd4ab 100644 +--- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c ++++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c +@@ -174,7 +174,7 @@ connect_proxy_command(char **args) + int main(int argc, const char **argv) + { + TALLOC_CTX *mem_ctx = NULL; +- int pc_debug = SSSDBG_DEFAULT; ++ int pc_debug = SSSDBG_FATAL_FAILURE; + int pc_port = 22; + const char *pc_domain = NULL; + const char *pc_host = NULL; +-- +2.21.3 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 0bc7768..07ea246 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -26,7 +26,7 @@ Name: sssd Version: 2.4.0 -Release: 7%{?dist} +Release: 8%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -77,6 +77,10 @@ Patch0040: 0040-sudo-runas-do-not-add-to-external-groups-in-IPA.patch Patch0041: 0041-responders-add-callback-to-schedule_get_domains_task.patch Patch0042: 0042-pam-refresh-certificate-maps-at-the-end-of-initial-d.patch Patch0043: 0043-SBUS-set-sbus_name-before-dp_init_send.patch +Patch0044: 0044-pam_sss_gss-support-authentication-indicators.patch +Patch0045: 0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch +Patch0046: 0046-ldap-fix-modifytimestamp-debugging-leftovers.patch +Patch0047: 0047-ssh-restore-default-debug-level.patch ### Downstream Patches ### @@ -1257,6 +1261,11 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Fri Feb 12 2021 Alexey Tikhonov - 2.4.0-8 +- Resolves: rhbz#1926622 - Add support to verify authentication indicators in pam_sss_gss +- Resolves: rhbz#1926454 - First smart refresh query contains modifyTimestamp even if the modifyTimestamp is 0. +- Resolves: rhbz#1893159 - Default debug level should report all errors / failures (additional patch) + * Tue Jan 26 2021 Alexey Tikhonov - 2.4.0-7 - Resolves: rhbz#1920001 - Do not add '%' to group names already prefixed with '%' in IPA sudo rules - Resolves: rhbz#1918433 - sssd unable to lookup certmap rules