From ed82746253c4f0a312469280b5196f8759027b27 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov Date: Tue, 24 Sep 2024 19:00:04 +0200 Subject: [PATCH] Resolves: RHEL-59876 - EL9/CentOS Stream 9 lost offline smart card authentication Resolves: RHEL-50912 - possible regression of rhbz#2196521 --- ...DB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch | 58 ++++ ...ovide-user_map-when-looking-up-group.patch | 307 ++++++++++++++++++ ...ser_map-when-looking-of-host-groups-.patch | 77 +++++ sssd.spec | 9 +- 4 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 0009-pam-only-set-SYSDB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch create mode 100644 0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch create mode 100644 0011-ad-use-default-user_map-when-looking-of-host-groups-.patch diff --git a/0009-pam-only-set-SYSDB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch b/0009-pam-only-set-SYSDB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch new file mode 100644 index 0000000..e069a48 --- /dev/null +++ b/0009-pam-only-set-SYSDB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch @@ -0,0 +1,58 @@ +From b4c496856d466ff00d06cd5177cb216110f5e3b3 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 18 Sep 2024 15:18:14 +0200 +Subject: [PATCH] pam: only set SYSDB_LOCAL_SMARTCARD_AUTH to 'true' but never + to 'false'. + +The krb5 backend will only returns that Smartcard authentication is +available if a Smartcard is present. That means if the user +authenticates with a different method and a Smartcard is not present at +this time 'sc_allow' will be 'false' and might overwrite a 'true' value +written during a previous authentication attempt where a Smartcard was +present. To avoid this we only write 'true' values. Since the default if +SYSDB_LOCAL_SMARTCARD_AUTH is missing is 'false' local Smartcard +authentication (offline) will still only be enabled if online Smartcard +authentication was detected. + +Resolves: https://github.com/SSSD/sssd/issues/7532 + +Reviewed-by: Iker Pedrosa +Reviewed-by: Justin Stephenson +(cherry picked from commit 67ba42c48abb9270982836310488e35d9fc1d451) +--- + src/responder/pam/pamsrv_cmd.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 1394147a0..941446d94 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -554,9 +554,22 @@ static errno_t set_local_auth_type(struct pam_auth_req *preq, + goto fail; + } + +- ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_SMARTCARD_AUTH, sc_allow); +- if (ret != EOK) { +- goto fail; ++ if (sc_allow) { ++ /* Only set SYSDB_LOCAL_SMARTCARD_AUTH to 'true' but never to ++ * 'false'. The krb5 backend will only returns that Smartcard ++ * authentication is available if a Smartcard is present. That means ++ * if the user authenticates with a different method and a Smartcard ++ * is not present at this time 'sc_allow' will be 'false' and might ++ * overwrite a 'true' value written during a previous authentication ++ * attempt where a Smartcard was present. To avoid this we only write ++ * 'true' values. Since the default if SYSDB_LOCAL_SMARTCARD_AUTH is ++ * missing is 'false' local Smartcard authentication (offline) will ++ * still only be enabled if online Smartcard authentication was ++ * detected. */ ++ ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_SMARTCARD_AUTH, sc_allow); ++ if (ret != EOK) { ++ goto fail; ++ } + } + + ret = sysdb_attrs_add_bool(attrs, SYSDB_LOCAL_PASSKEY_AUTH, passkey_allow); +-- +2.45.0 + diff --git a/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch b/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch new file mode 100644 index 0000000..1286417 --- /dev/null +++ b/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch @@ -0,0 +1,307 @@ +From 321ca19ae09609ac4195f323b696bdcd7ee573e4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 6 Sep 2024 14:27:19 +0200 +Subject: [PATCH 10/11] sdap: allow to provide user_map when looking up group + memberships +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To allow to lookup group memberships of other objects similar to user +objects but with different attribute mappings, e.g. host objects in AD, +a new option to provide an alternative attribute map is added. + +Resolves: https://github.com/SSSD/sssd/issues/7590 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +(cherry picked from commit 69f63f1fa64bd9cc7c2ee1f8e8d736727b13b3be) +--- + src/providers/ad/ad_gpo.c | 2 +- + src/providers/ldap/ldap_common.h | 2 + + src/providers/ldap/ldap_id.c | 9 ++++ + src/providers/ldap/sdap_async.h | 2 + + src/providers/ldap/sdap_async_initgroups.c | 51 ++++++++++++++-------- + 5 files changed, 48 insertions(+), 18 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index ed664ec83..fa68d814f 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2244,7 +2244,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) + search_bases, + state->host_fqdn, + BE_FILTER_NAME, +- NULL, ++ NULL, NULL, 0, + true, + true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 2c984ef50..61a35553b 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -308,6 +308,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + bool noexist_delete, + bool set_non_posix); + +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index b3ea2333f..0596ad4cf 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -1144,6 +1144,8 @@ struct groups_by_user_state { + const char *filter_value; + int filter_type; + const char *extra_value; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + const char **attrs; + bool non_posix; + +@@ -1165,6 +1167,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + bool noexist_delete, + bool set_non_posix) + { +@@ -1192,6 +1196,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + state->filter_value = filter_value; + state->filter_type = filter_type; + state->extra_value = extra_value; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; + state->domain = sdom->dom; + state->sysdb = sdom->dom->sysdb; + state->search_bases = search_bases; +@@ -1256,6 +1262,8 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) + state->sdom, + sdap_id_op_handle(state->op), + state->ctx, ++ state->user_map, ++ state->user_map_cnt, + state->conn, + state->search_bases, + state->filter_value, +@@ -1457,6 +1465,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->extra_value, ++ NULL, 0, + noexist_delete, false); + break; + +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 89245f41f..a45e057d0 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -157,6 +157,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_domain *sdom, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, + const char *name, +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index fb3d8fe24..8ce1f6cd4 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -785,6 +785,8 @@ struct sdap_initgr_nested_state { + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sdap_options *opts; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + struct sss_domain_info *dom; + struct sdap_handle *sh; + +@@ -812,6 +814,8 @@ static void sdap_initgr_nested_store(struct tevent_req *req); + static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_options *opts, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_handle *sh, +@@ -828,6 +832,8 @@ static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, + + state->ev = ev; + state->opts = opts; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; + state->sysdb = sysdb; + state->dom = dom; + state->sh = sh; +@@ -968,7 +974,7 @@ static errno_t sdap_initgr_nested_deref_search(struct tevent_req *req) + + subreq = sdap_deref_search_send(state, state->ev, state->opts, + state->sh, state->orig_dn, +- state->opts->user_map[SDAP_AT_USER_MEMBEROF].name, ++ state->user_map[SDAP_AT_USER_MEMBEROF].name, + sdap_attrs, num_maps, maps, timeout); + if (!subreq) { + ret = EIO; +@@ -2697,6 +2703,8 @@ struct sdap_get_initgr_state { + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sdap_options *opts; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + struct sss_domain_info *dom; + struct sdap_domain *sdom; + struct sdap_handle *sh; +@@ -2731,6 +2739,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_domain *sdom, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, + const char *filter_value, +@@ -2754,6 +2764,12 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + + state->ev = ev; + state->opts = id_ctx->opts; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; ++ if (state->user_map == NULL) { ++ state->user_map = id_ctx->opts->user_map; ++ state->user_map_cnt = id_ctx->opts->user_map_cnt; ++ } + state->dom = sdom->dom; + state->sysdb = sdom->dom->sysdb; + state->sdom = sdom; +@@ -2785,7 +2801,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + + switch (filter_type) { + case BE_FILTER_SECID: +- search_attr = state->opts->user_map[SDAP_AT_USER_OBJECTSID].name; ++ search_attr = state->user_map[SDAP_AT_USER_OBJECTSID].name; + + ret = sss_filter_sanitize(state, state->filter_value, &clean_name); + if (ret != EOK) { +@@ -2794,7 +2810,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + break; + case BE_FILTER_UUID: +- search_attr = state->opts->user_map[SDAP_AT_USER_UUID].name; ++ search_attr = state->user_map[SDAP_AT_USER_UUID].name; + + ret = sss_filter_sanitize(state, state->filter_value, &clean_name); + if (ret != EOK) { +@@ -2812,23 +2828,23 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + + ep_filter = get_enterprise_principal_string_filter(state, +- state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ state->user_map[SDAP_AT_USER_PRINC].name, + clean_name, state->opts->basic); + state->user_base_filter = + talloc_asprintf(state, + "(&(|(%s=%s)(%s=%s)%s)(objectclass=%s)", +- state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ state->user_map[SDAP_AT_USER_PRINC].name, + clean_name, +- state->opts->user_map[SDAP_AT_USER_EMAIL].name, ++ state->user_map[SDAP_AT_USER_EMAIL].name, + clean_name, + ep_filter == NULL ? "" : ep_filter, +- state->opts->user_map[SDAP_OC_USER].name); ++ state->user_map[SDAP_OC_USER].name); + if (state->user_base_filter == NULL) { + talloc_zfree(req); + return NULL; + } + } else { +- search_attr = state->opts->user_map[SDAP_AT_USER_NAME].name; ++ search_attr = state->user_map[SDAP_AT_USER_NAME].name; + + ret = sss_parse_internal_fqname(state, filter_value, + &state->shortname, NULL); +@@ -2860,7 +2876,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + state->user_base_filter = + talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)", + search_attr, clean_name, +- state->opts->user_map[SDAP_OC_USER].name); ++ state->user_map[SDAP_OC_USER].name); + if (!state->user_base_filter) { + talloc_zfree(req); + return NULL; +@@ -2877,14 +2893,14 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + */ + state->user_base_filter = talloc_asprintf_append(state->user_base_filter, + "(%s=*))", +- id_ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); ++ state->user_map[SDAP_AT_USER_OBJECTSID].name); + } else { + /* When not ID-mapping or looking up app users, make sure there + * is a non-NULL UID */ + state->user_base_filter = talloc_asprintf_append(state->user_base_filter, + "(&(%s=*)(!(%s=0))))", +- id_ctx->opts->user_map[SDAP_AT_USER_UID].name, +- id_ctx->opts->user_map[SDAP_AT_USER_UID].name); ++ state->user_map[SDAP_AT_USER_UID].name, ++ state->user_map[SDAP_AT_USER_UID].name); + } + if (!state->user_base_filter) { + talloc_zfree(req); +@@ -2892,8 +2908,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + + ret = build_attrs_from_map(state, +- state->opts->user_map, +- state->opts->user_map_cnt, ++ state->user_map, ++ state->user_map_cnt, + NULL, &state->user_attrs, NULL); + if (ret) { + talloc_zfree(req); +@@ -2990,7 +3006,7 @@ static errno_t sdap_get_initgr_next_base(struct tevent_req *req) + state->user_search_bases[state->user_base_iter]->basedn, + state->user_search_bases[state->user_base_iter]->scope, + state->filter, state->user_attrs, +- state->opts->user_map, state->opts->user_map_cnt, ++ state->user_map, state->user_map_cnt, + state->timeout, + false); + if (!subreq) { +@@ -3179,6 +3195,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) + + case SDAP_SCHEMA_IPA_V1: + subreq = sdap_initgr_nested_send(state, state->ev, state->opts, ++ state->user_map, state->user_map_cnt, + state->sysdb, state->dom, state->sh, + state->orig_user, state->grp_attrs); + if (!subreq) { +@@ -3377,7 +3394,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + */ + ret = sdap_attrs_get_sid_str( + tmp_ctx, opts->idmap_ctx, state->orig_user, +- opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, ++ state->user_map[SDAP_AT_USER_OBJECTSID].sys_name, + &sid_str); + if (ret != EOK) goto done; + +@@ -3392,7 +3409,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + + ret = sysdb_attrs_get_uint32_t( + state->orig_user, +- opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, ++ state->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, + &primary_gid); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +-- +2.45.0 + diff --git a/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch b/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch new file mode 100644 index 0000000..6318be3 --- /dev/null +++ b/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch @@ -0,0 +1,77 @@ +From 2c233636c093708d5cdd7ddb69af9b0ecde633bd Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 6 Sep 2024 14:37:05 +0200 +Subject: [PATCH 11/11] ad: use default user_map when looking of host groups + for GPO +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the default AD user attribute map to lookup the group membership of +the AD host object. This should help to avoid issues if user attributes +are overwritten in the user attribute map. + +Resolves: https://github.com/SSSD/sssd/issues/7590 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +(cherry picked from commit 5f5077ac1158deff6fbb51722d37b9c5f8b05cf7) +--- + src/providers/ad/ad_access.h | 1 + + src/providers/ad/ad_gpo.c | 15 ++++++++++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h +index 34d5597da..c54b53eed 100644 +--- a/src/providers/ad/ad_access.h ++++ b/src/providers/ad/ad_access.h +@@ -49,6 +49,7 @@ struct ad_access_ctx { + } gpo_map_type; + hash_table_t *gpo_map_options_table; + enum gpo_map_type gpo_default_right; ++ struct sdap_attr_map *host_attr_map; + }; + + struct tevent_req * +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index fa68d814f..6b154f71d 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -45,6 +45,7 @@ + #include "providers/ad/ad_common.h" + #include "providers/ad/ad_domain_info.h" + #include "providers/ad/ad_gpo.h" ++#include "providers/ad/ad_opts.h" + #include "providers/ldap/sdap_access.h" + #include "providers/ldap/sdap_async.h" + #include "providers/ldap/sdap.h" +@@ -2238,13 +2239,25 @@ ad_gpo_connect_done(struct tevent_req *subreq) + "trying with user search base."); + } + ++ if (state->access_ctx->host_attr_map == NULL) { ++ ret = sdap_copy_map(state->access_ctx, ++ ad_2008r2_user_map, SDAP_OPTS_USER, ++ &state->access_ctx->host_attr_map); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to copy user map.\n"); ++ goto done; ++ } ++ } ++ + subreq = groups_by_user_send(state, state->ev, + state->access_ctx->ad_id_ctx->sdap_id_ctx, + sdom, state->conn, + search_bases, + state->host_fqdn, + BE_FILTER_NAME, +- NULL, NULL, 0, ++ NULL, ++ state->access_ctx->host_attr_map, ++ SDAP_OPTS_USER, + true, + true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); +-- +2.45.0 + diff --git a/sssd.spec b/sssd.spec index fa50f47..0686bc1 100644 --- a/sssd.spec +++ b/sssd.spec @@ -27,7 +27,7 @@ Name: sssd Version: 2.9.5 -Release: 4%{?dist} +Release: 4%{?dist}.1 Summary: System Security Services Daemon License: GPLv3+ URL: https://github.com/SSSD/sssd/ @@ -42,6 +42,9 @@ Patch0005: 0005-SYSDB-remove-index-on-dataExpireTimestamp.patch Patch0006: 0006-pam_sss-fix-passthrow-of-old-authtok-from-another-pa.patch Patch0007: 0007-krb5_child-do-not-try-passwords-with-OTP.patch Patch0008: 0008-pam_sss-add-missing-optional-2nd-factor-handling.patch +Patch0009: 0009-pam-only-set-SYSDB_LOCAL_SMARTCARD_AUTH-to-true-but-.patch +Patch0010: 0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch +Patch0011: 0011-ad-use-default-user_map-when-looking-of-host-groups-.patch ### Dependencies ### @@ -1091,6 +1094,10 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Tue Sep 24 2024 Alexey Tikhonov - 2.9.5-4.1 +- Resolves: RHEL-59876 - EL9/CentOS Stream 9 lost offline smart card authentication +- Resolves: RHEL-50912 - possible regression of rhbz#2196521 + * Thu Jul 18 2024 Alexey Tikhonov - 2.9.5-4 - Resolves: RHEL-49711 - SYSDB: remove index on dataExpireTimestamp - Resolves: RHEL-49811 - 2FA is being enforced after upgrading 2.9.1->2.9.4