diff --git a/SOURCES/0012-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch b/SOURCES/0012-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch new file mode 100644 index 0000000..aa6e876 --- /dev/null +++ b/SOURCES/0012-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch @@ -0,0 +1,227 @@ +From e3a3f44c4cdcb936b59941636ff576de613366d1 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 13 Sep 2024 15:45:59 +0200 +Subject: [PATCH] ldap: add 'exop_force' value for ldap_pwmodify_mode + +In case the LDAP server allows to run the extended operation to change a +password even if an authenticated bind fails due to missing grace logins +the new option 'exop_force' can be used to run the extended operation to +change the password anyways. + +:config: Added `exop_force` value for configuration option + `ldap_pwmodify_mode`. This can be used to force a password change even + if no grace logins are left. Depending on the configuration of the + LDAP server it might be expected that the password change will fail. + +(cherry picked from commit 72a7fd0ded236a16b00bb4e26221f7e23b702a53) + +Reviewed-by: Justin Stephenson +--- + src/man/sssd-ldap.5.xml | 11 +++++++++ + src/providers/ipa/ipa_auth.c | 3 ++- + src/providers/ldap/ldap_auth.c | 5 +++- + src/providers/ldap/ldap_options.c | 2 ++ + src/providers/ldap/sdap.h | 5 ++-- + src/providers/ldap/sdap_async.h | 3 ++- + src/providers/ldap/sdap_async_connection.c | 27 +++++++++++++++++----- + 7 files changed, 45 insertions(+), 11 deletions(-) + +diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml +index cdf6b483e..42514ae50 100644 +--- a/src/man/sssd-ldap.5.xml ++++ b/src/man/sssd-ldap.5.xml +@@ -234,6 +234,17 @@ + userPassword (not recommended). + + ++ ++ ++ exop_force - Try Password Modify ++ Extended Operation (RFC 3062) even if ++ there are no grace logins left. ++ Depending on the type and configuration ++ of the LDAP server the password change ++ might fail because an authenticated bind ++ is not possible. ++ ++ + + + +diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c +index e5e1bf30c..af33cea2d 100644 +--- a/src/providers/ipa/ipa_auth.c ++++ b/src/providers/ipa/ipa_auth.c +@@ -394,7 +394,8 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq) + SDAP_OPT_TIMEOUT); + + subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn, +- state->pd->authtok, timeout); ++ state->pd->authtok, timeout, ++ state->auth_ctx->sdap_auth_ctx->opts->pwmodify_mode); + if (subreq == NULL) { + goto done; + } +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 8ec4d3af5..023ed2277 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -896,7 +896,8 @@ static void auth_do_bind(struct tevent_req *req) + NULL, NULL, state->dn, + state->authtok, + dp_opt_get_int(state->ctx->opts->basic, +- SDAP_OPT_TIMEOUT)); ++ SDAP_OPT_TIMEOUT), ++ state->ctx->opts->pwmodify_mode); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; +@@ -1186,6 +1187,7 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx, + + switch (opts->pwmodify_mode) { + case SDAP_PWMODIFY_EXOP: ++ case SDAP_PWMODIFY_EXOP_FORCE: + subreq = sdap_exop_modify_passwd_send(state, ev, sh, user_dn, + password, new_password, + timeout); +@@ -1229,6 +1231,7 @@ static void sdap_pam_change_password_done(struct tevent_req *subreq) + + switch (state->mode) { + case SDAP_PWMODIFY_EXOP: ++ case SDAP_PWMODIFY_EXOP_FORCE: + ret = sdap_exop_modify_passwd_recv(subreq, state, + &state->user_error_message); + break; +diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c +index 277bcb529..72a95300d 100644 +--- a/src/providers/ldap/ldap_options.c ++++ b/src/providers/ldap/ldap_options.c +@@ -294,6 +294,8 @@ int ldap_get_options(TALLOC_CTX *memctx, + opts->pwmodify_mode = SDAP_PWMODIFY_EXOP; + } else if (strcasecmp(pwmodify, "ldap_modify") == 0) { + opts->pwmodify_mode = SDAP_PWMODIFY_LDAP; ++ } else if (strcasecmp(pwmodify, "exop_force") == 0) { ++ opts->pwmodify_mode = SDAP_PWMODIFY_EXOP_FORCE; + } else { + DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized pwmodify mode: %s\n", pwmodify); + ret = EINVAL; +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 103d50ed4..cc34c8198 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -546,8 +546,9 @@ struct sdap_options { + + /* password modify mode */ + enum pwmodify_mode { +- SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */ +- SDAP_PWMODIFY_LDAP = 2 /* ldap_modify of userPassword */ ++ SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */ ++ SDAP_PWMODIFY_LDAP = 2, /* ldap_modify of userPassword */ ++ SDAP_PWMODIFY_EXOP_FORCE = 3 /* forced pwmodify extended operation */ + } pwmodify_mode; + + /* The search bases for the domain or its subdomain */ +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index a45e057d0..80b403bc3 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -146,7 +146,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + const char *sasl_user, + const char *user_dn, + struct sss_auth_token *authtok, +- int simple_bind_timeout); ++ int simple_bind_timeout, ++ enum pwmodify_mode pwmodify_mode); + + errno_t sdap_auth_recv(struct tevent_req *req, + TALLOC_CTX *memctx, +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index e8638725c..992a5798c 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -643,6 +643,7 @@ struct simple_bind_state { + struct tevent_context *ev; + struct sdap_handle *sh; + const char *user_dn; ++ enum pwmodify_mode pwmodify_mode; + + struct sdap_op *op; + +@@ -659,7 +660,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, + struct sdap_handle *sh, + int timeout, + const char *user_dn, +- struct berval *pw) ++ struct berval *pw, ++ enum pwmodify_mode pwmodify_mode) + { + struct tevent_req *req; + struct simple_bind_state *state; +@@ -682,6 +684,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, + state->ev = ev; + state->sh = sh; + state->user_dn = user_dn; ++ state->pwmodify_mode = pwmodify_mode; + + ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST, + 0, NULL, 0, &ctrls[0]); +@@ -866,7 +869,12 @@ static void simple_bind_done(struct sdap_op *op, + * Grace Authentications". */ + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, grace logins exhausted.\n"); +- ret = ERR_AUTH_FAILED; ++ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) { ++ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n"); ++ ret = ERR_PASSWORD_EXPIRED; ++ } else { ++ ret = ERR_AUTH_FAILED; ++ } + } + } else if (strcmp(response_controls[c]->ldctl_oid, + LDAP_CONTROL_PWEXPIRED) == 0) { +@@ -879,7 +887,12 @@ static void simple_bind_done(struct sdap_op *op, + if (result == LDAP_INVALID_CREDENTIALS) { + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, grace logins exhausted.\n"); +- ret = ERR_AUTH_FAILED; ++ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) { ++ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n"); ++ ret = ERR_PASSWORD_EXPIRED; ++ } else { ++ ret = ERR_AUTH_FAILED; ++ } + } else { + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, user must set a new password.\n"); +@@ -1358,7 +1371,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + const char *sasl_user, + const char *user_dn, + struct sss_auth_token *authtok, +- int simple_bind_timeout) ++ int simple_bind_timeout, ++ enum pwmodify_mode pwmodify_mode) + { + struct tevent_req *req, *subreq; + struct sdap_auth_state *state; +@@ -1397,7 +1411,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + pw.bv_len = pwlen; + + state->is_sasl = false; +- subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw); ++ subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw, pwmodify_mode); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return tevent_req_post(req, ev); +@@ -1972,7 +1986,8 @@ static void sdap_cli_auth_step(struct tevent_req *req) + SDAP_SASL_AUTHID), + user_dn, authtok, + dp_opt_get_int(state->opts->basic, +- SDAP_OPT_TIMEOUT)); ++ SDAP_OPT_TIMEOUT), ++ state->opts->pwmodify_mode); + talloc_free(authtok); + if (!subreq) { + tevent_req_error(req, ENOMEM); +-- +2.46.1 + diff --git a/SOURCES/0013-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch b/SOURCES/0013-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch new file mode 100644 index 0000000..26557db --- /dev/null +++ b/SOURCES/0013-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch @@ -0,0 +1,35 @@ +From dafe48341d2f74c97619be799e915b7588484ef7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20L=C3=B3pez?= +Date: Thu, 14 Nov 2024 17:27:49 +0100 +Subject: [PATCH 13/14] OPTS: Add the option for DP_OPT_DYNDNS_REFRESH_OFFSET + +The label `DP_OPT_DYNDNS_REFRESH_OFFSET` was introduced in +https://github.com/SSSD/sssd/blob/fb91349cfeba653942b32141f890e3de78b3fb13/src/providers/be_dyndns.h#L55 +but the corresponding option is missing in +https://github.com/SSSD/sssd/blob/fb91349cfeba653942b32141f890e3de78b3fb13/src/providers/be_dyndns.c#L1200 + +This error was introduced by +https://github.com/SSSD/sssd/commit/35c35de42012481a6bd2690d12d5d11a4ae23ea5 + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Sumit Bose +(cherry picked from commit 9ee10f98e0070774e0e7f0794bc296ef06a671e4) +--- + src/providers/be_dyndns.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c +index 2c655ef1e..5d0f51119 100644 +--- a/src/providers/be_dyndns.c ++++ b/src/providers/be_dyndns.c +@@ -1201,6 +1201,7 @@ static struct dp_option default_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_update_per_family", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "dyndns_refresh_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, ++ { "dyndns_refresh_interval_offset", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, + { "dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, + { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE }, +-- +2.46.1 + diff --git a/SOURCES/0014-TESTS-Also-test-default_dyndns_opts.patch b/SOURCES/0014-TESTS-Also-test-default_dyndns_opts.patch new file mode 100644 index 0000000..af2ed71 --- /dev/null +++ b/SOURCES/0014-TESTS-Also-test-default_dyndns_opts.patch @@ -0,0 +1,69 @@ +From 5411fa745f939bdf4cb105bd9f6b9b77703532af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20L=C3=B3pez?= +Date: Thu, 14 Nov 2024 18:46:44 +0100 +Subject: [PATCH 14/14] TESTS: Also test default_dyndns_opts + +Compare this structure to ipa_dyndns_opts, which is already compared +to ad_dyndns_opts. + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Sumit Bose +(cherry picked from commit 2c72834e657197012b3a32207ffe307e8ba5f9e2) +--- + src/providers/be_dyndns.c | 2 +- + src/providers/be_dyndns.h | 1 + + src/tests/ipa_ldap_opt-tests.c | 6 ++++++ + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c +index 5d0f51119..e6fa7dfd6 100644 +--- a/src/providers/be_dyndns.c ++++ b/src/providers/be_dyndns.c +@@ -1197,7 +1197,7 @@ be_nsupdate_check(void) + return ret; + } + +-static struct dp_option default_dyndns_opts[] = { ++struct dp_option default_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_update_per_family", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "dyndns_refresh_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, +diff --git a/src/providers/be_dyndns.h b/src/providers/be_dyndns.h +index 2185fee95..719c13942 100644 +--- a/src/providers/be_dyndns.h ++++ b/src/providers/be_dyndns.h +@@ -63,6 +63,7 @@ enum dp_dyndns_opts { + + DP_OPT_DYNDNS /* attrs counter */ + }; ++extern struct dp_option default_dyndns_opts[DP_OPT_DYNDNS + 1]; + + #define DYNDNS_REMOVE_A 0x1 + #define DYNDNS_REMOVE_AAAA 0x2 +diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c +index a1a0e9cc6..da990acaf 100644 +--- a/src/tests/ipa_ldap_opt-tests.c ++++ b/src/tests/ipa_ldap_opt-tests.c +@@ -103,6 +103,10 @@ START_TEST(test_compare_opts) + ret = compare_dp_options(ipa_dyndns_opts, DP_OPT_DYNDNS, + ad_dyndns_opts); + ck_assert_msg(ret == EOK, "[%s]", strerror(ret)); ++ ++ ret = compare_dp_options(ipa_dyndns_opts, DP_OPT_DYNDNS, ++ default_dyndns_opts); ++ ck_assert_msg(ret == EOK, "[%s]", strerror(ret)); + } + END_TEST + +@@ -200,6 +204,8 @@ START_TEST(test_dp_opt_sentinel) + + fail_unless_dp_opt_is_terminator(&default_krb5_opts[KRB5_OPTS]); + ++ fail_unless_dp_opt_is_terminator(&default_dyndns_opts[DP_OPT_DYNDNS]); ++ + fail_unless_dp_opt_is_terminator(&ad_basic_opts[AD_OPTS_BASIC]); + fail_unless_dp_opt_is_terminator(&ad_def_ldap_opts[SDAP_OPTS_BASIC]); + fail_unless_dp_opt_is_terminator(&ad_def_krb5_opts[KRB5_OPTS]); +-- +2.46.1 + diff --git a/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch b/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch new file mode 100644 index 0000000..0f0f149 --- /dev/null +++ b/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch @@ -0,0 +1,55 @@ +From a34098c541a3a533abf0eacdf75b5e99adf18d46 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 21 Nov 2024 09:16:09 +0100 +Subject: [PATCH] ldap_child: make sure invalid krb5 context is not used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://github.com/SSSD/sssd/issues/7715 + +Reviewed-by: Alejandro López +Reviewed-by: Alexey Tikhonov +(cherry picked from commit fce94aec3f335cbe33c509b14e389b9df0748744) +--- + src/util/sss_krb5.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c +index 3f57e5b26..f44df2b5f 100644 +--- a/src/util/sss_krb5.c ++++ b/src/util/sss_krb5.c +@@ -83,6 +83,10 @@ const char *sss_printable_keytab_name(krb5_context ctx, const char *keytab_name) + return keytab_name; + } + ++ if (ctx == NULL) { ++ return "-unknown-"; ++ } ++ + if (krb5_kt_default_name(ctx, buff, sizeof(buff)) != 0) { + return "-default keytab-"; + } +@@ -1355,8 +1359,9 @@ krb5_error_code sss_krb5_init_context(krb5_context *context) + { + krb5_error_code kerr; + const char *msg; ++ krb5_context ctx; + +- kerr = krb5_init_context(context); ++ kerr = krb5_init_context(&ctx); + if (kerr != 0) { + /* It is safe to call (sss_)krb5_get_error_message() with NULL as first + * argument. */ +@@ -1365,6 +1370,8 @@ krb5_error_code sss_krb5_init_context(krb5_context *context) + "Failed to init Kerberos context [%s]\n", msg); + sss_log(SSS_LOG_CRIT, "Failed to init Kerberos context [%s]\n", msg); + sss_krb5_free_error_message(NULL, msg); ++ } else { ++ *context = ctx; + } + + return kerr; +-- +2.46.1 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index afcb35f..e6ce888 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -27,7 +27,7 @@ Name: sssd Version: 2.9.5 -Release: 4%{?dist}.1 +Release: 4%{?dist}.4 Summary: System Security Services Daemon License: GPLv3+ URL: https://github.com/SSSD/sssd/ @@ -45,6 +45,10 @@ 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 +Patch0012: 0012-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch +Patch0013: 0013-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch +Patch0014: 0014-TESTS-Also-test-default_dyndns_opts.patch +Patch0015: 0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch ### Dependencies ### @@ -1094,6 +1098,15 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Fri Nov 22 2024 Alexey Tikhonov - 2.9.5-4.4 +- Resolves: RHEL-68508 - sssd backend process segfaults when krb5.conf is invalid [rhel-9.5.z] + +* Mon Nov 18 2024 Alexey Tikhonov - 2.9.5-4.3 +- Resolves: RHEL-67673 - Label DP_OPT_DYNDNS_REFRESH_OFFSET has no corresponding option [rhel-9.5.z] + +* Fri Nov 8 2024 Alexey Tikhonov - 2.9.5-4.2 +- Resolves: RHEL-66268 - SSSD needs an option to indicate if the LDAP server can run the exop with an anonymous bind or not [rhel-9.5.z] + * 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