diff --git a/SOURCES/0018-adtrustinstance-make-sure-NetBIOS-name-defaults-are-.patch b/SOURCES/0018-adtrustinstance-make-sure-NetBIOS-name-defaults-are-.patch new file mode 100644 index 0000000..fbd49d7 --- /dev/null +++ b/SOURCES/0018-adtrustinstance-make-sure-NetBIOS-name-defaults-are-.patch @@ -0,0 +1,35 @@ +From eab52d3cda9bbec716008c040551bd11facd0e11 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 17 Jan 2024 12:27:26 +0200 +Subject: [PATCH] adtrustinstance: make sure NetBIOS name defaults are set + properly + +Some tools may pass None as NetBIOS name if not put explicitly by a +user. This meant to use default NetBIOS name generator based on the +domain (realm) name. However, this wasn't done properly, so None is +passed later to python-ldap and it rejects such LDAP entry. + +Fixes: https://pagure.io/freeipa/issue/9514 + +Signed-off-by: Alexander Bokovoy +Reviewed-By: Florence Blanc-Renaud +--- + ipaserver/install/adtrustinstance.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py +index d55ba849157bee8e335e2e0772514fc15ec11193..2ff68dfb46371a6118eb67515347eb762a37e1ec 100644 +--- a/ipaserver/install/adtrustinstance.py ++++ b/ipaserver/install/adtrustinstance.py +@@ -189,6 +189,8 @@ class ADTRUSTInstance(service.Service): + self.fqdn = self.fqdn or api.env.host + self.host_netbios_name = make_netbios_name(self.fqdn) + self.realm = self.realm or api.env.realm ++ if not self.netbios_name: ++ self.netbios_name = make_netbios_name(self.realm) + + self.suffix = ipautil.realm_to_suffix(self.realm) + self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % \ +-- +2.43.0 + diff --git a/SOURCES/0019-ipatests-wait-for-replica-update-in-test_dns_locatio.patch b/SOURCES/0019-ipatests-wait-for-replica-update-in-test_dns_locatio.patch new file mode 100644 index 0000000..61926ae --- /dev/null +++ b/SOURCES/0019-ipatests-wait-for-replica-update-in-test_dns_locatio.patch @@ -0,0 +1,42 @@ +From 3b2f3d41e4de0bcb78bfaecb32e06cbd22b809c2 Mon Sep 17 00:00:00 2001 +From: Masahiro Matsuya +Date: Tue, 9 Jan 2024 23:12:11 +0900 +Subject: [PATCH] ipatests: wait for replica update in test_dns_locations + +test_ipa_ca_records and test_adtrust_system_records can fail with +NXDOMAIN, because it doesn't wait enough for the update on replica. +It can be resolved by waiting for the update with wait_for_replication. + +Fixes: https://pagure.io/freeipa/issue/9504 +Reviewed-By: Florence Blanc-Renaud +--- + ipatests/test_integration/test_dns_locations.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ipatests/test_integration/test_dns_locations.py b/ipatests/test_integration/test_dns_locations.py +index 44900af8015ff62728f64bc626eedfcead41e214..89a310892954cbee88d1cf38683e80a2e47122ef 100644 +--- a/ipatests/test_integration/test_dns_locations.py ++++ b/ipatests/test_integration/test_dns_locations.py +@@ -534,6 +534,9 @@ class TestDNSLocations(IntegrationTest): + + expected_servers = (self.master.ip, self.replicas[1].ip) + ++ ldap = self.master.ldap_connect() ++ tasks.wait_for_replication(ldap) ++ + for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip): + self._test_A_rec_against_server(ip, self.domain, expected_servers) + +@@ -557,6 +560,9 @@ class TestDNSLocations(IntegrationTest): + (self.PRIO_HIGH, self.WEIGHT, DNSName(self.master.hostname)), + ) + ++ ldap = self.master.ldap_connect() ++ tasks.wait_for_replication(ldap) ++ + for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip): + self._test_SRV_rec_against_server( + ip, self.domain, expected_servers, +-- +2.43.0 + diff --git a/SOURCES/0020-ipa-kdb-Disable-Bronze-Bit-check-if-PAC-not-available_rhel.patch b/SOURCES/0020-ipa-kdb-Disable-Bronze-Bit-check-if-PAC-not-available_rhel.patch new file mode 100644 index 0000000..2f88986 --- /dev/null +++ b/SOURCES/0020-ipa-kdb-Disable-Bronze-Bit-check-if-PAC-not-available_rhel.patch @@ -0,0 +1,147 @@ +From 27b96c17dd51d076e04d97662b7c788658a5094a Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Jan 26 2024 09:35:57 +0000 +Subject: ipa-kdb: Disable Bronze-Bit check if PAC not available + + +The Bronze-Bit check introduced in commit +a847e2483b4c4832ee5129901da169f4eb0d1392 requires the MS-PAC to be +present in the evidence ticket in order for S4U2Proxy requests to be +accepted. This actually requires SIDs to be set. + +However, domains that were initialized before commit +e527857d000e558b3288a7a210400abaf2171237 may still not have SIDs +configured. This would results in all S4U2Proxy requests to fail +(including all the HTTP API requests). + +This present commit disables the check for the Bronze-Bit exploit +(CVE-2020-17049) in case the domain is not able to generate PACs. +Instead, it prints a warning message in the KDC logs each time a +S4U2Proxy request is processed. + +Fixes: https://pagure.io/freeipa/issue/9521 + +Signed-off-by: Julien Rische +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h +index c6926f7..621c235 100644 +--- a/daemons/ipa-kdb/ipa_kdb.h ++++ b/daemons/ipa-kdb/ipa_kdb.h +@@ -368,17 +368,21 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, + char **trusted_realm); + + /* Try to detect a Bronze-Bit attack based on the content of the request and +- * data from the KDB. ++ * data from the KDB. This check will work only if the domain supports MS-PAC. + * + * context krb5 context + * request KDB request +- * detected Set to "true" if a bronze bit attack is detected and the +- * pointer is not NULL. Remains unset otherwise. ++ * supported If not NULL, set to "false" in case the Bronze-Bit exploit ++ * detection process silently failed to complete because the ++ * domain does not meet requirements. Set to "true" otherwise. ++ * detected If not NULL, set to "true" if a Bronze-Bit attack is detected. ++ * Set to "false" otherwise. + * status If the call fails and the pointer is not NULL, set it with a + * message describing the cause of the failure. */ + krb5_error_code + ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, +- bool *detected, const char **status); ++ bool *supported, bool *detected, ++ const char **status); + + /* DELEGATION CHECKS */ + +diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c +index ee0546c..713e9a0 100644 +--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c ++++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c +@@ -186,11 +186,19 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata, + krb5_deltat *renew_lifetime_out) + { + krb5_error_code kerr; ++ bool supported; + +- kerr = ipadb_check_for_bronze_bit_attack(context, request, NULL, status); ++ kerr = ipadb_check_for_bronze_bit_attack(context, request, supported, NULL, ++ status); + if (kerr) + return KRB5KDC_ERR_POLICY; + ++ if (!supported) ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC not available. This makes " ++ "FreeIPA vulnerable to the Bronze-Bit exploit " ++ "(CVE-2020-17049). Please generate SIDs to enable " ++ "PAC support."); ++ + *status = NULL; + *lifetime_out = 0; + *renew_lifetime_out = 0; +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 05d5b40..a18beff 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -3301,11 +3301,14 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, + + krb5_error_code + ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, +- bool *detected, const char **status) ++ bool *supported, bool *detected, ++ const char **status) + { + krb5_error_code kerr; + const char *st = NULL; + size_t i, j; ++ bool in_supported = true, in_detected = false; ++ struct ipadb_context *ipactx; + krb5_ticket *evidence_tkt; + krb5_authdata **authdata, **ifrel = NULL; + krb5_pac pac = NULL; +@@ -3325,6 +3328,21 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, + goto end; + } + ++ ipactx = ipadb_get_context(context); ++ if (!ipactx) { ++ kerr = KRB5_KDB_DBNOTINITED; ++ goto end; ++ } ++ ++ /* Handle the case where the domain is not able to generate PACs (probably ++ * because SIDs are not set). In this case, we just skip the Bronze-Bit ++ * check. */ ++ if (!ipactx->mspac) { ++ in_supported = false; ++ kerr = 0; ++ goto end; ++ } ++ + evidence_tkt = request->second_ticket[0]; + + /* No need to check the Forwardable flag. If it was not set, this request +@@ -3449,8 +3467,7 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, + /* This evidence ticket cannot be forwardable given the privileges + * of the proxy principal. + * This is a Bronze Bit attack. */ +- if (detected) +- *detected = true; ++ in_detected = true; + st = "S4U2PROXY_BRONZE_BIT_ATTACK_DETECTED"; + kerr = EBADE; + goto end; +@@ -3462,6 +3479,10 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, + end: + if (st && status) + *status = st; ++ if (supported) ++ *supported = in_supported; ++ if (detected) ++ *detected = in_detected; + + krb5_free_authdata(context, ifrel); + krb5_pac_free(context, pac); + diff --git a/SOURCES/0021-Fix-session-cookie-access_rhel.patch b/SOURCES/0021-Fix-session-cookie-access_rhel.patch new file mode 100644 index 0000000..87a33f0 --- /dev/null +++ b/SOURCES/0021-Fix-session-cookie-access_rhel.patch @@ -0,0 +1,238 @@ +From 381af470779ea87335f57038dcbe72cd042ae6bb Mon Sep 17 00:00:00 2001 +From: Stanislav Levin +Date: Jan 30 2024 15:11:05 +0000 +Subject: ipapython: Clean up krb5_error + + +`krb5_error` has different definition in MIT krb. +https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/types/krb5_error.html + +> Error message structure. +> +> Declaration: +> typedef struct _krb5_error krb5_error + +While `krb5_error_code` +https://web.mit.edu/kerberos/www/krb5-latest/doc/appdev/refs/types/krb5_error_code.html#c.krb5_error_code + +> krb5_error_code +> Used to convey an operation status. +> +> The value 0 indicates success; any other values are com_err codes. Use krb5_get_error_message() to obtain a string describing the error. +> +> Declaration +> typedef krb5_int32 krb5_error_code + +And this is what was actually used. + +To prevent confusion of types `krb5_error` was replaced with +`krb5_error_code`. + +Fixes: https://pagure.io/freeipa/issue/9519 +Signed-off-by: Stanislav Levin +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py +index c43ef7d..371cf15 100644 +--- a/ipapython/session_storage.py ++++ b/ipapython/session_storage.py +@@ -111,7 +111,7 @@ class KRB5Error(Exception): + + + def krb5_errcheck(result, func, arguments): +- """Error checker for krb5_error return value""" ++ """Error checker for krb5_error_code return value""" + if result != 0: + raise KRB5Error(result, func.__name__, arguments) + +@@ -119,14 +119,13 @@ def krb5_errcheck(result, func, arguments): + krb5_context = ctypes.POINTER(_krb5_context) + krb5_ccache = ctypes.POINTER(_krb5_ccache) + krb5_data_p = ctypes.POINTER(_krb5_data) +-krb5_error = ctypes.c_int32 + krb5_creds = _krb5_creds + krb5_pointer = ctypes.c_void_p + krb5_cc_cursor = krb5_pointer + + krb5_init_context = LIBKRB5.krb5_init_context + krb5_init_context.argtypes = (ctypes.POINTER(krb5_context), ) +-krb5_init_context.restype = krb5_error ++krb5_init_context.restype = krb5_error_code + krb5_init_context.errcheck = krb5_errcheck + + krb5_free_context = LIBKRB5.krb5_free_context +@@ -143,30 +142,30 @@ krb5_free_data_contents.restype = None + + krb5_cc_default = LIBKRB5.krb5_cc_default + krb5_cc_default.argtypes = (krb5_context, ctypes.POINTER(krb5_ccache), ) +-krb5_cc_default.restype = krb5_error ++krb5_cc_default.restype = krb5_error_code + krb5_cc_default.errcheck = krb5_errcheck + + krb5_cc_close = LIBKRB5.krb5_cc_close + krb5_cc_close.argtypes = (krb5_context, krb5_ccache, ) +-krb5_cc_close.restype = krb5_error ++krb5_cc_close.restype = krb5_error_code + krb5_cc_close.errcheck = krb5_errcheck + + krb5_parse_name = LIBKRB5.krb5_parse_name + krb5_parse_name.argtypes = (krb5_context, ctypes.c_char_p, + ctypes.POINTER(krb5_principal), ) +-krb5_parse_name.restype = krb5_error ++krb5_parse_name.restype = krb5_error_code + krb5_parse_name.errcheck = krb5_errcheck + + krb5_cc_set_config = LIBKRB5.krb5_cc_set_config + krb5_cc_set_config.argtypes = (krb5_context, krb5_ccache, krb5_principal, + ctypes.c_char_p, krb5_data_p, ) +-krb5_cc_set_config.restype = krb5_error ++krb5_cc_set_config.restype = krb5_error_code + krb5_cc_set_config.errcheck = krb5_errcheck + + krb5_cc_get_principal = LIBKRB5.krb5_cc_get_principal + krb5_cc_get_principal.argtypes = (krb5_context, krb5_ccache, + ctypes.POINTER(krb5_principal), ) +-krb5_cc_get_principal.restype = krb5_error ++krb5_cc_get_principal.restype = krb5_error_code + krb5_cc_get_principal.errcheck = krb5_errcheck + + # krb5_build_principal is a variadic function but that can't be expressed +@@ -177,26 +176,26 @@ krb5_build_principal.argtypes = (krb5_context, ctypes.POINTER(krb5_principal), + ctypes.c_uint, ctypes.c_char_p, + ctypes.c_char_p, ctypes.c_char_p, + ctypes.c_char_p, ctypes.c_char_p, ) +-krb5_build_principal.restype = krb5_error ++krb5_build_principal.restype = krb5_error_code + krb5_build_principal.errcheck = krb5_errcheck + + krb5_cc_start_seq_get = LIBKRB5.krb5_cc_start_seq_get + krb5_cc_start_seq_get.argtypes = (krb5_context, krb5_ccache, + ctypes.POINTER(krb5_cc_cursor), ) +-krb5_cc_start_seq_get.restype = krb5_error ++krb5_cc_start_seq_get.restype = krb5_error_code + krb5_cc_start_seq_get.errcheck = krb5_errcheck + + krb5_cc_next_cred = LIBKRB5.krb5_cc_next_cred + krb5_cc_next_cred.argtypes = (krb5_context, krb5_ccache, + ctypes.POINTER(krb5_cc_cursor), + ctypes.POINTER(krb5_creds), ) +-krb5_cc_next_cred.restype = krb5_error ++krb5_cc_next_cred.restype = krb5_error_code + krb5_cc_next_cred.errcheck = krb5_errcheck + + krb5_cc_end_seq_get = LIBKRB5.krb5_cc_end_seq_get + krb5_cc_end_seq_get.argtypes = (krb5_context, krb5_ccache, + ctypes.POINTER(krb5_cc_cursor), ) +-krb5_cc_end_seq_get.restype = krb5_error ++krb5_cc_end_seq_get.restype = krb5_error_code + krb5_cc_end_seq_get.errcheck = krb5_errcheck + + krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents +@@ -212,7 +211,7 @@ krb5_principal_compare.restype = krb5_boolean + krb5_unparse_name = LIBKRB5.krb5_unparse_name + krb5_unparse_name.argtypes = (krb5_context, krb5_principal, + ctypes.POINTER(ctypes.c_char_p), ) +-krb5_unparse_name.restype = krb5_error ++krb5_unparse_name.restype = krb5_error_code + krb5_unparse_name.errcheck = krb5_errcheck + + krb5_free_unparsed_name = LIBKRB5.krb5_free_unparsed_name + +From 2a4bad8bb3295c5c0f5a760ecd41871c4c5a0c56 Mon Sep 17 00:00:00 2001 +From: Stanislav Levin +Date: Jan 30 2024 15:11:05 +0000 +Subject: ipapython: Correct return type of krb5_free_cred_contents + + +According to https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/api/krb5_free_cred_contents.html + +> krb5_free_cred_contents - Free the contents of a krb5_creds structure. +> +> void krb5_free_cred_contents(krb5_context context, krb5_creds * val) +> param: +> [in] context - Library context +> +> [in] val - Credential structure to free contents of +> +> This function frees the contents of val , but not the structure itself. + +https://github.com/krb5/krb5/blob/5b00197227231943bd2305328c8260dd0b0dbcf0/src/lib/krb5/krb/kfree.c#L166 + +This leads to undefined behavior and `krb5_free_cred_contents` can +raise KRB5Error (because of garbage data) while actually its foreign +function doesn't. + +Fixes: https://pagure.io/freeipa/issue/9519 +Signed-off-by: Stanislav Levin +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py +index 371cf15..dc36f54 100644 +--- a/ipapython/session_storage.py ++++ b/ipapython/session_storage.py +@@ -200,8 +200,7 @@ krb5_cc_end_seq_get.errcheck = krb5_errcheck + + krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents + krb5_free_cred_contents.argtypes = (krb5_context, ctypes.POINTER(krb5_creds)) +-krb5_free_cred_contents.restype = krb5_error +-krb5_free_cred_contents.errcheck = krb5_errcheck ++krb5_free_cred_contents.restype = None + + krb5_principal_compare = LIBKRB5.krb5_principal_compare + krb5_principal_compare.argtypes = (krb5_context, krb5_principal, + +From beb402afdbf32c01eed860e9416356f7b492ad74 Mon Sep 17 00:00:00 2001 +From: Stanislav Levin +Date: Jan 30 2024 15:11:05 +0000 +Subject: ipapython: Propagate KRB5Error exceptions on iterating ccache + + +`ipapython.session_storage.get_data` iterates over +credentials in a credential cache till `krb5_cc_next_cred` returns +an error. This function doesn't expect any error on calling +other kerberos foreign functions during iteration. But that can +actually happen and KRB5Error exceptions stop an iteration while +they should be propagated. + +With this change iteration will exactly stop on `krb5_cc_next_cred` +error as it was supposed to be. + +Fixes: https://pagure.io/freeipa/issue/9519 +Signed-off-by: Stanislav Levin +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py +index dc36f54..e890dc9 100644 +--- a/ipapython/session_storage.py ++++ b/ipapython/session_storage.py +@@ -312,8 +312,12 @@ def get_data(princ_name, key): + checkcreds = krb5_creds() + # the next function will throw an error and break out of the + # while loop when we try to access past the last cred +- krb5_cc_next_cred(context, ccache, ctypes.byref(cursor), +- ctypes.byref(checkcreds)) ++ try: ++ krb5_cc_next_cred(context, ccache, ctypes.byref(cursor), ++ ctypes.byref(checkcreds)) ++ except KRB5Error: ++ break ++ + if (krb5_principal_compare(context, principal, + checkcreds.client) == 1 and + krb5_principal_compare(context, srv_princ, +@@ -328,8 +332,6 @@ def get_data(princ_name, key): + else: + krb5_free_cred_contents(context, + ctypes.byref(checkcreds)) +- except KRB5Error: +- pass + finally: + krb5_cc_end_seq_get(context, ccache, ctypes.byref(cursor)) + + diff --git a/SOURCES/0022-ipa-kdb-Fix-memory-leak-during-PAC-verification_rhel.patch b/SOURCES/0022-ipa-kdb-Fix-memory-leak-during-PAC-verification_rhel.patch new file mode 100644 index 0000000..d4ba709 --- /dev/null +++ b/SOURCES/0022-ipa-kdb-Fix-memory-leak-during-PAC-verification_rhel.patch @@ -0,0 +1,89 @@ +From bac601b7f35827236a106f7137f378e4888260da Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Jan 30 2024 15:17:44 +0000 +Subject: ipa-kdb: Fix memory leak during PAC verification + + +Commit 0022bd70d93708d325855d5271516d6cd894d6e8 introduced a memory leak +during the copy of some PAC buffers, because of an unfreed memory +allocation context. + +Fixes: https://pagure.io/freeipa/issue/9520 + +Signed-off-by: Julien Rische +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index a18beff..9e1431c 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -2316,6 +2316,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context, + size_t i; + struct dom_sid *requester_sid = NULL; + struct dom_sid req_sid; ++ TALLOC_CTX *tmpctx = NULL; + + if (signing_krbtgt != NULL && + ipadb_is_cross_realm_krbtgt(signing_krbtgt->princ)) { +@@ -2371,6 +2372,12 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context, + goto done; + } + ++ tmpctx = talloc_new(NULL); ++ if (tmpctx == NULL) { ++ kerr = ENOMEM; ++ goto done; ++ } ++ + for (i = 0; i < num_buffers; i++) { + if (types[i] == KRB5_PAC_SERVER_CHECKSUM || + types[i] == KRB5_PAC_PRIVSVR_CHECKSUM || +@@ -2395,32 +2402,21 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context, + DATA_BLOB pac_attrs_data; + krb5_boolean pac_requested; + +- TALLOC_CTX *tmpctx = talloc_new(NULL); +- if (tmpctx == NULL) { +- kerr = ENOMEM; +- goto done; +- } +- + kerr = ipadb_client_requested_pac(context, old_pac, tmpctx, &pac_requested); +- if (kerr != 0) { +- talloc_free(tmpctx); ++ if (kerr) + goto done; +- } + + kerr = ipadb_get_pac_attrs_blob(tmpctx, &pac_requested, &pac_attrs_data); +- if (kerr) { +- talloc_free(tmpctx); ++ if (kerr) + goto done; +- } ++ + data.magic = KV5M_DATA; + data.data = (char *)pac_attrs_data.data; + data.length = pac_attrs_data.length; + + kerr = krb5_pac_add_buffer(context, new_pac, PAC_TYPE_ATTRIBUTES_INFO, &data); +- if (kerr) { +- talloc_free(tmpctx); ++ if (kerr) + goto done; +- } + + continue; + } +@@ -2467,6 +2463,8 @@ done: + if (kerr != 0 && (new_pac != *pac)) { + krb5_pac_free(context, new_pac); + } ++ if (tmpctx) ++ talloc_free(tmpctx); + krb5_free_data_contents(context, &pac_blob); + free(types); + return kerr; + diff --git a/SOURCES/0023-Do-not-ignore-staged-users-in-sidgen-plugin_rhel.patch b/SOURCES/0023-Do-not-ignore-staged-users-in-sidgen-plugin_rhel.patch new file mode 100644 index 0000000..9e70f2d --- /dev/null +++ b/SOURCES/0023-Do-not-ignore-staged-users-in-sidgen-plugin_rhel.patch @@ -0,0 +1,108 @@ +From b56a80581ef388e19d5761020454e51463036cd6 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Tue, 23 Jan 2024 14:47:50 +0200 +Subject: [PATCH] sidgen: ignore staged users when generating SIDs + +Staged users have + + uidNumber: -1 + gidNumber: -1 + ipaUniqueID: autogenerate + +We cannot generate ipaSecurityIdentifier based on those UID/GID numbers. +However, '-1' value will trigger an error + + find_sid_for_ldap_entry - [file ipa_sidgen_common.c, line 483]: ID value too large. + +And that, in turn, will cause stopping SID generation for all users. + +Detect 'ipaUniqueID: autogenerate' situation and ignore these entries. + +Fixes: https://pagure.io/freeipa/issue/9517 + +Signed-off-by: Alexander Bokovoy +Reviewed-By: Florence Blanc-Renaud +Reviewed-By: Thierry Bordaz +--- + daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h | 2 ++ + .../ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c | 12 ++++++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h +index 0feff7eec..bd46982d0 100644 +--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h ++++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h +@@ -45,6 +45,8 @@ + #define UID_NUMBER "uidnumber" + #define GID_NUMBER "gidnumber" + #define IPA_SID "ipantsecurityidentifier" ++#define IPA_UNIQUEID "ipauniqueid" ++#define IPA_UNIQUEID_AUTOGENERATE "autogenerate" + #define DOM_ATTRS_FILTER OBJECTCLASS"=ipantdomainattrs" + #define DOMAIN_ID_RANGE_FILTER OBJECTCLASS"=ipadomainidrange" + #define POSIX_ACCOUNT "posixaccount" +diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c +index 6f784804c..cb763ebf8 100644 +--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c ++++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c +@@ -454,6 +454,7 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry, + uint32_t id; + char *sid = NULL; + char **objectclasses = NULL; ++ char *uniqueid = NULL; + Slapi_PBlock *mod_pb = NULL; + Slapi_Mods *smods = NULL; + int result; +@@ -479,6 +480,16 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry, + goto done; + } + ++ uniqueid = slapi_entry_attr_get_charptr(entry, IPA_UNIQUEID); ++ if (uniqueid != NULL && ++ strncmp(IPA_UNIQUEID_AUTOGENERATE, uniqueid, ++ sizeof(IPA_UNIQUEID_AUTOGENERATE)) == 0) { ++ LOG("Staged entry [%s] does not have Posix IDs, nothing to do.\n", ++ dn_str); ++ ret = 0; ++ goto done; ++ } ++ + if (uid_number >= UINT32_MAX || gid_number >= UINT32_MAX) { + LOG_FATAL("ID value too large.\n"); + ret = LDAP_CONSTRAINT_VIOLATION; +@@ -554,6 +565,7 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry, + } + + done: ++ slapi_ch_free_string(&uniqueid); + slapi_ch_free_string(&sid); + slapi_pblock_destroy(mod_pb); + slapi_mods_free(&smods); +-- +2.43.0 + +From 07150b71537744f491d022c737ef04775c72a10a Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Tue, 23 Jan 2024 14:53:39 +0200 +Subject: [PATCH] sidgen: fix missing prototypes + +Signed-off-by: Alexander Bokovoy +Reviewed-By: Florence Blanc-Renaud +Reviewed-By: Thierry Bordaz +--- + daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h +index bd46982d0..aec862796 100644 +--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h ++++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h +@@ -106,3 +106,6 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry, + const char *base_dn, + const char *dom_sid, + struct range_info **ranges); ++ ++int sidgen_task_init(Slapi_PBlock *pb); ++int ipa_sidgen_init(Slapi_PBlock *pb); +-- +2.43.0 diff --git a/SOURCES/0024-kdb-PAC-generator-do-not-fail-if-canonical-principal-is-missing_rhel.patch b/SOURCES/0024-kdb-PAC-generator-do-not-fail-if-canonical-principal-is-missing_rhel.patch new file mode 100644 index 0000000..e37ead8 --- /dev/null +++ b/SOURCES/0024-kdb-PAC-generator-do-not-fail-if-canonical-principal-is-missing_rhel.patch @@ -0,0 +1,45 @@ +From dcb9d6edc7ae4278cd552e87f644705faa13d558 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Jan 31 2024 08:31:13 +0000 +Subject: kdb: PAC generator: do not fail if canonical principal is missing + + +krbCanonicalName is mandatory for services but IPA services created +before commit e6ff83e (FreeIPA 4.4.0, ~2016) had no normalization done +to set krbCanonicalName; services created after that version were +upgraded to do have krbCanonicalName. + +Accept krbPrincipalName alone since they have no alias either */ + +Fixes: https://pagure.io/freeipa/issue/9465 + +Signed-off-by: Alexander Bokovoy +Reviewed-By: Florence Blanc-Renaud +Reviewed-By: Thierry Bordaz + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 9e1431c..8035036 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -496,8 +496,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, + ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, + "krbCanonicalName", &strres); + if (ret) { +- /* krbCanonicalName is mandatory for services */ +- return ret; ++ /* krbCanonicalName is mandatory for services but IPA services ++ * created before commit e6ff83e (FreeIPA 4.4.0, ~2016) had no ++ * normalization to set krbCanonicalName; services created after ++ * that version were upgraded to do have krbCanonicalName. ++ * ++ * Accept krbPrincipalName alone since they have no alias either */ ++ ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, ++ "krbPrincipalName", &strres); ++ if (ret) ++ return ret; + } + + ret = krb5_parse_name(ipactx->kcontext, strres, &princ); + diff --git a/SOURCES/0025-ipd-kdb-Fix-some-mistakes-in.patch b/SOURCES/0025-ipd-kdb-Fix-some-mistakes-in.patch new file mode 100644 index 0000000..ced9344 --- /dev/null +++ b/SOURCES/0025-ipd-kdb-Fix-some-mistakes-in.patch @@ -0,0 +1,61 @@ +From 81aa6ef695838a4b2fb5a53e773ea379a492913d Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Feb 12 2024 14:25:16 +0000 +Subject: ipd-kdb: Fix some mistakes in ipadb_check_for_bronze_bit_attack() + + +Fixes: https://pagure.io/freeipa/issue/9521 +Signed-off-by: Julien Rische +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h +index 621c235..5de5ea7 100644 +--- a/daemons/ipa-kdb/ipa_kdb.h ++++ b/daemons/ipa-kdb/ipa_kdb.h +@@ -382,7 +382,8 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, + * status If the call fails and the pointer is not NULL, set it with a + * message describing the cause of the failure. */ + krb5_error_code +-ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, ++ipadb_check_for_bronze_bit_attack(krb5_context context, ++ const krb5_kdc_req *request, + bool *supported, bool *detected, + const char **status); + +diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c +index 713e9a0..44959f3 100644 +--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c ++++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c +@@ -188,7 +188,7 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata, + krb5_error_code kerr; + bool supported; + +- kerr = ipadb_check_for_bronze_bit_attack(context, request, supported, NULL, ++ kerr = ipadb_check_for_bronze_bit_attack(context, request, &supported, NULL, + status); + if (kerr) + return KRB5KDC_ERR_POLICY; +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 8035036..886ed77 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -3306,13 +3306,14 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, + } + + krb5_error_code +-ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request, ++ipadb_check_for_bronze_bit_attack(krb5_context context, ++ const krb5_kdc_req *request, + bool *supported, bool *detected, + const char **status) + { + krb5_error_code kerr; + const char *st = NULL; +- size_t i, j; ++ size_t i, j = 0; + bool in_supported = true, in_detected = false; + struct ipadb_context *ipactx; + krb5_ticket *evidence_tkt; + diff --git a/SOURCES/0026-ipa-kdb-Rework-ipadb_reinit_mspac.patch b/SOURCES/0026-ipa-kdb-Rework-ipadb_reinit_mspac.patch new file mode 100644 index 0000000..3fb3af5 --- /dev/null +++ b/SOURCES/0026-ipa-kdb-Rework-ipadb_reinit_mspac.patch @@ -0,0 +1,697 @@ +From 7f072e348d318e928f6270a182ca04dee8716677 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Feb 16 2024 09:17:20 +0000 +Subject: ipa-kdb: Rework ipadb_reinit_mspac() + + +Modify ipadb_reinit_mspac() to allocate and initialize ipactx->mspac +only if all its attributes can be set. If not, ipactx->mspac is set to +NULL. This makes easier to determine if the KDC is able to generate PACs +or not. + +Also ipadb_reinit_mspac() is now able to return a status message +explaining why initialization of the PAC generator failed. This message +is printed in KDC logs. + +Fixes: https://pagure.io/freeipa/issue/9535 + +Signed-off-by: Julien Rische +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c +index 0c6325d..fcadb8e 100644 +--- a/daemons/ipa-kdb/ipa_kdb.c ++++ b/daemons/ipa-kdb/ipa_kdb.c +@@ -394,6 +394,7 @@ int ipadb_get_connection(struct ipadb_context *ipactx) + struct timeval tv = { 5, 0 }; + LDAPMessage *res = NULL; + LDAPMessage *first; ++ const char *stmsg; + int ret; + int v3; + +@@ -473,16 +474,9 @@ int ipadb_get_connection(struct ipadb_context *ipactx) + } + + /* get adtrust options using default refresh interval */ +- ret = ipadb_reinit_mspac(ipactx, false); +- if (ret && ret != ENOENT) { +- /* TODO: log that there is an issue with adtrust settings */ +- if (ipactx->lcontext == NULL) { +- /* for some reason ldap connection was reset in ipadb_reinit_mspac +- * and is no longer established => failure of ipadb_get_connection +- */ +- goto done; +- } +- } ++ ret = ipadb_reinit_mspac(ipactx, false, &stmsg); ++ if (ret && stmsg) ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg); + + ret = 0; + +diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h +index 5de5ea7..7baf469 100644 +--- a/daemons/ipa-kdb/ipa_kdb.h ++++ b/daemons/ipa-kdb/ipa_kdb.h +@@ -352,7 +352,9 @@ krb5_error_code ipadb_v9_issue_pac(krb5_context context, unsigned int flags, + krb5_data ***auth_indicators); + #endif + +-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit); ++krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, ++ bool force_reinit, ++ const char **stmsg); + + void ipadb_mspac_struct_free(struct ipadb_mspac **mspac); + krb5_error_code ipadb_check_transited_realms(krb5_context kcontext, +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 886ed77..deed513 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -793,16 +793,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, + return ret; + } + ++ if (!ipactx->mspac) { ++ /* can't give a PAC without server NetBIOS name or primary group RID */ ++ return ENOENT; ++ } ++ + if (info3->base.primary_gid == 0) { + if (is_host || is_service) { + info3->base.primary_gid = 515; /* Well known RID for domain computers group */ + } else { +- if (ipactx->mspac->fallback_rid) { +- info3->base.primary_gid = ipactx->mspac->fallback_rid; +- } else { +- /* can't give a pack without a primary group rid */ +- return ENOENT; +- } ++ info3->base.primary_gid = ipactx->mspac->fallback_rid; + } + } + +@@ -812,26 +812,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, + /* always zero out, not used for Krb, only NTLM */ + memset(&info3->base.key, '\0', sizeof(info3->base.key)); + +- if (ipactx->mspac->flat_server_name) { +- info3->base.logon_server.string = +- talloc_strdup(memctx, ipactx->mspac->flat_server_name); +- if (!info3->base.logon_server.string) { +- return ENOMEM; +- } +- } else { +- /* can't give a pack without Server NetBIOS Name :-| */ +- return ENOENT; ++ info3->base.logon_server.string = ++ talloc_strdup(memctx, ipactx->mspac->flat_server_name); ++ if (!info3->base.logon_server.string) { ++ return ENOMEM; + } + +- if (ipactx->mspac->flat_domain_name) { +- info3->base.logon_domain.string = +- talloc_strdup(memctx, ipactx->mspac->flat_domain_name); +- if (!info3->base.logon_domain.string) { +- return ENOMEM; +- } +- } else { +- /* can't give a pack without Domain NetBIOS Name :-| */ +- return ENOENT; ++ info3->base.logon_domain.string = ++ talloc_strdup(memctx, ipactx->mspac->flat_domain_name); ++ if (!info3->base.logon_domain.string) { ++ return ENOMEM; + } + + if (is_host || is_service) { +@@ -1044,6 +1034,11 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext, + return KRB5_KDB_DBNOTINITED; + } + ++ /* Check if PAC generator is initialized */ ++ if (!ipactx->mspac) { ++ return ENOENT; ++ } ++ + ied = (struct ipadb_e_data *)client->e_data; + if (ied->magic != IPA_E_DATA_MAGIC) { + return EINVAL; +@@ -1626,14 +1621,14 @@ static struct ipadb_adtrusts *get_domain_from_realm(krb5_context context, + { + struct ipadb_context *ipactx; + struct ipadb_adtrusts *domain; +- int i; ++ size_t i; + + ipactx = ipadb_get_context(context); + if (!ipactx) { + return NULL; + } + +- if (ipactx->mspac == NULL) { ++ if (!ipactx->mspac) { + return NULL; + } + +@@ -1655,6 +1650,7 @@ static struct ipadb_adtrusts *get_domain_from_realm_update(krb5_context context, + { + struct ipadb_context *ipactx; + struct ipadb_adtrusts *domain; ++ const char *stmsg = NULL; + krb5_error_code kerr; + + ipactx = ipadb_get_context(context); +@@ -1663,8 +1659,10 @@ static struct ipadb_adtrusts *get_domain_from_realm_update(krb5_context context, + } + + /* re-init MS-PAC info using default update interval */ +- kerr = ipadb_reinit_mspac(ipactx, false); ++ kerr = ipadb_reinit_mspac(ipactx, false, &stmsg); + if (kerr != 0) { ++ if (stmsg) ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg); + return NULL; + } + domain = get_domain_from_realm(context, realm); +@@ -1717,6 +1715,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, + struct ipadb_e_data *ied = NULL; + int flags = 0; + struct dom_sid client_sid; ++ const char *stmsg = NULL; + #ifdef KRB5_KDB_FLAG_ALIAS_OK + flags = KRB5_KDB_FLAG_ALIAS_OK; + #endif +@@ -1730,10 +1729,14 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, + * check that our own view on the PAC details is up to date */ + if (ipactx->mspac->domsid.num_auths == 0) { + /* Force re-init of KDB's view on our domain */ +- kerr = ipadb_reinit_mspac(ipactx, true); ++ kerr = ipadb_reinit_mspac(ipactx, true, &stmsg); + if (kerr != 0) { +- krb5_klog_syslog(LOG_ERR, +- "PAC issue: unable to update realm's view on PAC info"); ++ if (stmsg) { ++ krb5_klog_syslog(LOG_ERR, "MS-PAC generator: %s", stmsg); ++ } else { ++ krb5_klog_syslog(LOG_ERR, "PAC issue: unable to update " \ ++ "realm's view on PAC info"); ++ } + return KRB5KDC_ERR_POLICY; + } + } +@@ -1746,7 +1749,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, + if (is_s4u && (ipactx->mspac->trusts != NULL)) { + /* Iterate through list of trusts and check if this SID belongs to + * one of the domains we trust */ +- for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) { ++ for(size_t i = 0 ; i < ipactx->mspac->num_trusts ; i++) { + result = dom_sid_check(&ipactx->mspac->trusts[i].domsid, + info->info->info3.base.domain_sid, true); + if (result) { +@@ -1858,11 +1861,11 @@ krb5_error_code filter_logon_info(krb5_context context, + struct ipadb_mspac *mspac_ctx = ipactx->mspac; + result = FALSE; + /* Didn't match but perhaps the original PAC was issued by a child domain's DC? */ +- for (k = 0; k < mspac_ctx->num_trusts; k++) { +- result = dom_sid_check(&mspac_ctx->trusts[k].domsid, ++ for (size_t m = 0; m < mspac_ctx->num_trusts; m++) { ++ result = dom_sid_check(&mspac_ctx->trusts[m].domsid, + info->info->info3.base.domain_sid, true); + if (result) { +- domain = &mspac_ctx->trusts[k]; ++ domain = &mspac_ctx->trusts[m]; + break; + } + } +@@ -2091,10 +2094,10 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context, + return KRB5_KDB_DBNOTINITED; + } + /* In S4U case we might be dealing with the PAC issued by the trusted domain */ +- if ((ipactx->mspac->trusts != NULL)) { ++ if (ipactx->mspac->trusts) { + /* Iterate through list of trusts and check if this SID belongs to + * one of the domains we trust */ +- for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) { ++ for(size_t i = 0 ; i < ipactx->mspac->num_trusts ; i++) { + result = dom_sid_check(&ipactx->mspac->trusts[i].domsid, + &client_sid, false); + if (result) { +@@ -2631,7 +2634,7 @@ static char *get_server_netbios_name(struct ipadb_context *ipactx) + + void ipadb_mspac_struct_free(struct ipadb_mspac **mspac) + { +- int i, j; ++ size_t i, j; + + if (!*mspac) return; + +@@ -2786,7 +2789,8 @@ ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) + LDAPDN dn = NULL; + char **sid_blocklist_incoming = NULL; + char **sid_blocklist_outgoing = NULL; +- int ret, n, i; ++ size_t i, n; ++ int ret; + + ret = asprintf(&base, "cn=ad,cn=trusts,%s", ipactx->base); + if (ret == -1) { +@@ -2871,7 +2875,7 @@ ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) + + t[n].upn_suffixes_len = NULL; + if (t[n].upn_suffixes != NULL) { +- int len = 0; ++ size_t len = 0; + + for (; t[n].upn_suffixes[len] != NULL; len++); + +@@ -2986,108 +2990,114 @@ done: + return ret; + } + +-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit) ++krb5_error_code ++ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit, ++ const char **stmsg) + { + char *dom_attrs[] = { "ipaNTFlatName", + "ipaNTFallbackPrimaryGroup", + "ipaNTSecurityIdentifier", + NULL }; + char *grp_attrs[] = { "ipaNTSecurityIdentifier", NULL }; +- krb5_error_code kerr; + LDAPMessage *result = NULL; + LDAPMessage *lentry; +- struct dom_sid gsid; +- char *resstr; +- int ret; ++ struct dom_sid gsid, domsid; ++ char *resstr = NULL; ++ char *flat_domain_name = NULL; ++ char *flat_server_name = NULL; ++ char *fallback_group = NULL; ++ uint32_t fallback_rid; + time_t now; ++ const char *in_stmsg = NULL; ++ int err; ++ krb5_error_code trust_kerr = 0; ++ + + /* Do not update the mspac struct more than once a minute. This would + * avoid heavy load on the directory server if there are lots of requests + * from domains which we do not trust. */ + now = time(NULL); + +- if (ipactx->mspac != NULL && +- (force_reinit == false) && +- (now > ipactx->mspac->last_update) && +- (now - ipactx->mspac->last_update) < 60) { +- return 0; +- } +- +- if (ipactx->mspac && ipactx->mspac->num_trusts == 0) { +- /* Check if there is any trust configured. If not, just return +- * and do not re-initialize the MS-PAC structure. */ +- kerr = ipadb_mspac_check_trusted_domains(ipactx); +- if (kerr == KRB5_KDB_NOENTRY) { +- kerr = 0; +- goto done; +- } else if (kerr != 0) { +- goto done; ++ if (ipactx->mspac) { ++ if (!force_reinit && ++ (now > ipactx->mspac->last_update) && ++ (now - ipactx->mspac->last_update) < 60) { ++ /* SKIP */ ++ err = 0; ++ goto end; + } +- } +- +- /* clean up in case we had old values around */ +- ipadb_mspac_struct_free(&ipactx->mspac); + +- ipactx->mspac = calloc(1, sizeof(struct ipadb_mspac)); +- if (!ipactx->mspac) { +- kerr = ENOMEM; +- goto done; ++ if (ipactx->mspac->num_trusts == 0) { ++ /* Check if there is any trust configured. If not, just return ++ * and do not re-initialize the MS-PAC structure. */ ++ err = ipadb_mspac_check_trusted_domains(ipactx); ++ if (err) { ++ if (err == KRB5_KDB_NOENTRY) { ++ /* SKIP */ ++ err = 0; ++ } else { ++ in_stmsg = "Failed to fetch trusted domains information"; ++ } ++ goto end; ++ } ++ } + } + +- ipactx->mspac->last_update = now; +- +- kerr = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE, +- "(objectclass=ipaNTDomainAttrs)", dom_attrs, +- &result); +- if (kerr == KRB5_KDB_NOENTRY) { +- return ENOENT; +- } else if (kerr != 0) { +- return EIO; ++ err = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE, ++ "(objectclass=ipaNTDomainAttrs)", dom_attrs, ++ &result); ++ if (err == KRB5_KDB_NOENTRY) { ++ err = ENOENT; ++ in_stmsg = "Local domain NT attributes not configured"; ++ goto end; ++ } else if (err) { ++ err = EIO; ++ in_stmsg = "Failed to fetch local domain NT attributes"; ++ goto end; + } + + lentry = ldap_first_entry(ipactx->lcontext, result); + if (!lentry) { +- kerr = ENOENT; +- goto done; ++ err = ENOENT; ++ in_stmsg = "Local domain NT attributes not configured"; ++ goto end; + } + +- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, +- "ipaNTFlatName", +- &ipactx->mspac->flat_domain_name); +- if (ret) { +- kerr = ret; +- goto done; ++ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, "ipaNTFlatName", ++ &flat_domain_name); ++ if (err) { ++ in_stmsg = "Local domain NT flat name not configured"; ++ goto end; + } + +- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, +- "ipaNTSecurityIdentifier", +- &resstr); +- if (ret) { +- kerr = ret; +- goto done; ++ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, ++ "ipaNTSecurityIdentifier", &resstr); ++ if (err) { ++ in_stmsg = "Local domain SID not configured"; ++ goto end; + } + +- ret = ipadb_string_to_sid(resstr, &ipactx->mspac->domsid); +- if (ret) { +- kerr = ret; +- free(resstr); +- goto done; ++ err = ipadb_string_to_sid(resstr, &domsid); ++ if (err) { ++ in_stmsg = "Malformed local domain SID"; ++ goto end; + } ++ + free(resstr); + +- free(ipactx->mspac->flat_server_name); +- ipactx->mspac->flat_server_name = get_server_netbios_name(ipactx); +- if (!ipactx->mspac->flat_server_name) { +- kerr = ENOMEM; +- goto done; ++ flat_server_name = get_server_netbios_name(ipactx); ++ if (!flat_server_name) { ++ err = ENOMEM; ++ goto end; + } + +- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, +- "ipaNTFallbackPrimaryGroup", +- &ipactx->mspac->fallback_group); +- if (ret && ret != ENOENT) { +- kerr = ret; +- goto done; ++ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, ++ "ipaNTFallbackPrimaryGroup", &fallback_group); ++ if (err) { ++ in_stmsg = (err == ENOENT) ++ ? "Local fallback primary group not configured" ++ : "Failed to fetch local fallback primary group"; ++ goto end; + } + + /* result and lentry not valid any more from here on */ +@@ -3095,53 +3105,81 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_rein + result = NULL; + lentry = NULL; + +- if (ret != ENOENT) { +- kerr = ipadb_simple_search(ipactx, ipactx->mspac->fallback_group, +- LDAP_SCOPE_BASE, +- "(objectclass=posixGroup)", +- grp_attrs, &result); +- if (kerr && kerr != KRB5_KDB_NOENTRY) { +- kerr = ret; +- goto done; +- } ++ err = ipadb_simple_search(ipactx, fallback_group, LDAP_SCOPE_BASE, ++ "(objectclass=posixGroup)", grp_attrs, &result); ++ if (err) { ++ in_stmsg = (err == KRB5_KDB_NOENTRY) ++ ? "Local fallback primary group has no POSIX definition" ++ : "Failed to fetch SID of POSIX group mapped as local fallback " \ ++ "primary group"; ++ goto end; ++ } + +- lentry = ldap_first_entry(ipactx->lcontext, result); +- if (!lentry) { +- kerr = ENOENT; +- goto done; +- } ++ lentry = ldap_first_entry(ipactx->lcontext, result); ++ if (!lentry) { ++ err = ENOENT; ++ goto end; ++ } + +- if (kerr == 0) { +- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, +- "ipaNTSecurityIdentifier", +- &resstr); +- if (ret && ret != ENOENT) { +- kerr = ret; +- goto done; +- } +- if (ret == 0) { +- ret = ipadb_string_to_sid(resstr, &gsid); +- if (ret) { +- free(resstr); +- kerr = ret; +- goto done; +- } +- ret = sid_split_rid(&gsid, &ipactx->mspac->fallback_rid); +- if (ret) { +- free(resstr); +- kerr = ret; +- goto done; +- } +- free(resstr); +- } +- } ++ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, ++ "ipaNTSecurityIdentifier", &resstr); ++ if (err) { ++ in_stmsg = (err == ENOENT) ++ ? "The POSIX group set as fallback primary group has no SID " \ ++ "configured" ++ : "Failed to fetch SID of POSIX group set as local fallback " \ ++ "primary group"; ++ goto end; + } + +- kerr = ipadb_mspac_get_trusted_domains(ipactx); ++ err = ipadb_string_to_sid(resstr, &gsid); ++ if (err) { ++ in_stmsg = "Malformed SID of POSIX group set as local fallback " \ ++ "primary group"; ++ goto end; ++ } + +-done: ++ err = sid_split_rid(&gsid, &fallback_rid); ++ if (err) { ++ in_stmsg = "Malformed SID of POSIX group mapped as local fallback " \ ++ "primary group"; ++ goto end; ++ } ++ ++ /* clean up in case we had old values around */ ++ ipadb_mspac_struct_free(&ipactx->mspac); ++ ++ ipactx->mspac = calloc(1, sizeof(struct ipadb_mspac)); ++ if (!ipactx->mspac) { ++ err = ENOMEM; ++ goto end; ++ } ++ ++ ipactx->mspac->last_update = now; ++ ipactx->mspac->flat_domain_name = flat_domain_name; ++ ipactx->mspac->flat_server_name = flat_server_name; ++ ipactx->mspac->domsid = domsid; ++ ipactx->mspac->fallback_group = fallback_group; ++ ipactx->mspac->fallback_rid = fallback_rid; ++ ++ trust_kerr = ipadb_mspac_get_trusted_domains(ipactx); ++ if (trust_kerr) ++ in_stmsg = "Failed to assemble trusted domains information"; ++ ++end: ++ if (stmsg) ++ *stmsg = in_stmsg; ++ ++ if (resstr) free(resstr); + ldap_msgfree(result); +- return kerr; ++ ++ if (err) { ++ if (flat_domain_name) free(flat_domain_name); ++ if (flat_server_name) free(flat_server_name); ++ if (fallback_group) free(fallback_group); ++ } ++ ++ return err ? (krb5_error_code)err : trust_kerr; + } + + krb5_error_code ipadb_check_transited_realms(krb5_context kcontext, +@@ -3151,11 +3189,11 @@ krb5_error_code ipadb_check_transited_realms(krb5_context kcontext, + { + struct ipadb_context *ipactx; + bool has_transited_contents, has_client_realm, has_server_realm; +- int i; ++ size_t i; + krb5_error_code ret; + + ipactx = ipadb_get_context(kcontext); +- if (!ipactx || !ipactx->mspac) { ++ if (!ipactx) { + return KRB5_KDB_DBNOTINITED; + } + +@@ -3217,7 +3255,7 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, + char **trusted_realm) + { + struct ipadb_context *ipactx; +- int i, j, length; ++ size_t i, j, length; + const char *name; + bool result = false; + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_private.h b/daemons/ipa-kdb/ipa_kdb_mspac_private.h +index 7f0ca7a..e650cfa 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac_private.h ++++ b/daemons/ipa-kdb/ipa_kdb_mspac_private.h +@@ -31,7 +31,7 @@ struct ipadb_mspac { + char *fallback_group; + uint32_t fallback_rid; + +- int num_trusts; ++ size_t num_trusts; + struct ipadb_adtrusts *trusts; + time_t last_update; + }; +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_v6.c b/daemons/ipa-kdb/ipa_kdb_mspac_v6.c +index faf47ad..96cd50e 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac_v6.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac_v6.c +@@ -233,6 +233,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context, + krb5_db_entry *client_entry = NULL; + krb5_boolean is_equal; + bool force_reinit_mspac = false; ++ const char *stmsg = NULL; + + + is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0); +@@ -309,7 +310,9 @@ krb5_error_code ipadb_sign_authdata(krb5_context context, + force_reinit_mspac = true; + } + +- (void)ipadb_reinit_mspac(ipactx, force_reinit_mspac); ++ kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg); ++ if (kerr && stmsg) ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg); + + kerr = ipadb_get_pac(context, flags, client, server, NULL, authtime, &pac); + if (kerr != 0 && kerr != ENOENT) { +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_v9.c b/daemons/ipa-kdb/ipa_kdb_mspac_v9.c +index 3badd5b..60db048 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac_v9.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac_v9.c +@@ -46,6 +46,7 @@ ipadb_v9_issue_pac(krb5_context context, unsigned int flags, + bool with_pad; + krb5_error_code kerr = 0; + bool is_as_req = flags & CLIENT_REFERRALS_FLAGS; ++ const char *stmsg = NULL; + + if (is_as_req) { + get_authz_data_types(context, client, &with_pac, &with_pad); +@@ -110,12 +111,19 @@ ipadb_v9_issue_pac(krb5_context context, unsigned int flags, + force_reinit_mspac = TRUE; + } + } +- (void)ipadb_reinit_mspac(ipactx, force_reinit_mspac); + +- /* MS-PAC needs proper configuration and if it is missing, we simply skip issuing one */ +- if (ipactx->mspac->flat_server_name == NULL) { ++ /* MS-PAC generator has to be initalized */ ++ kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg); ++ if (kerr && stmsg) ++ krb5_klog_syslog(LOG_ERR, "MS-PAC generator: %s", stmsg); ++ ++ /* Continue even if initilization of PAC generator failed. ++ * It may caused by the trust objects part only. */ ++ ++ /* At least the core part of the PAC generator is required. */ ++ if (!ipactx->mspac) + return KRB5_PLUGIN_OP_NOTSUPP; +- } ++ + kerr = ipadb_get_pac(context, flags, + client, server, replaced_reply_key, + authtime, &new_pac); +diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c +index fadb132..07cc877 100644 +--- a/daemons/ipa-kdb/ipa_kdb_principals.c ++++ b/daemons/ipa-kdb/ipa_kdb_principals.c +@@ -1495,6 +1495,7 @@ static krb5_error_code dbget_alias(krb5_context kcontext, + krb5_db_entry *kentry = NULL; + krb5_data *realm; + krb5_boolean check = FALSE; ++ const char *stmsg = NULL; + + /* TODO: also support hostbased aliases */ + +@@ -1562,8 +1563,11 @@ static krb5_error_code dbget_alias(krb5_context kcontext, + if (kerr == KRB5_KDB_NOENTRY) { + /* If no trusted realm found, refresh trusted domain data and try again + * because it might be a freshly added trust to AD */ +- kerr = ipadb_reinit_mspac(ipactx, false); ++ kerr = ipadb_reinit_mspac(ipactx, false, &stmsg); + if (kerr != 0) { ++ if (stmsg) ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", ++ stmsg); + kerr = KRB5_KDB_NOENTRY; + goto done; + } diff --git a/SOURCES/0027-ipatests-fix-tasks_wait_for_replication-method.patch b/SOURCES/0027-ipatests-fix-tasks_wait_for_replication-method.patch new file mode 100644 index 0000000..c433849 --- /dev/null +++ b/SOURCES/0027-ipatests-fix-tasks_wait_for_replication-method.patch @@ -0,0 +1,34 @@ +From 44a762413c83f9637399afeb61b1e4b1ac111260 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Feb 14 2024 12:24:48 +0000 +Subject: ipatests: fix tasks.wait_for_replication method + + +With the fix for https://pagure.io/freeipa/issue/9171, the +method entry.single_value['nsds5replicaupdateinprogress'] now +returns a Boolean instead of a string "TRUE"/"FALSE". + +The method tasks.wait_for_replication needs to be fixed so that +it properly detects when replication is not done. + +Fixes: https://pagure.io/freeipa/issue/9530 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py +index 9068ba6..952c9e6 100755 +--- a/ipatests/pytest_ipa/integration/tasks.py ++++ b/ipatests/pytest_ipa/integration/tasks.py +@@ -1510,7 +1510,7 @@ def wait_for_replication(ldap, timeout=30, + statuses = [entry.single_value[status_attr] for entry in entries] + wrong_statuses = [s for s in statuses + if not re.match(target_status_re, s)] +- if any(e.single_value[progress_attr] == 'TRUE' for e in entries): ++ if any(e.single_value[progress_attr] for e in entries): + msg = 'Replication not finished' + logger.debug(msg) + elif wrong_statuses: + diff --git a/SOURCES/0028-ipa-kdb-Fix-double-free-in-ipadb_reinit_mspac.patch b/SOURCES/0028-ipa-kdb-Fix-double-free-in-ipadb_reinit_mspac.patch new file mode 100644 index 0000000..501c1c0 --- /dev/null +++ b/SOURCES/0028-ipa-kdb-Fix-double-free-in-ipadb_reinit_mspac.patch @@ -0,0 +1,27 @@ +From ac44c3d0a69aa2b3f8230c3ab13dca5ab5a78dd0 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Tue, 20 Feb 2024 15:14:24 +0100 +Subject: [PATCH] ipa-kdb: Fix double free in ipadb_reinit_mspac() + +Fixes: https://pagure.io/freeipa/issue/9535 + +Signed-off-by: Julien Rische +Reviewed-By: Florence Blanc-Renaud +--- + daemons/ipa-kdb/ipa_kdb_mspac.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index b0eb3324bf4b7d8eeb7b332c39de4023784f6337..9723103d8a77294ed7457d9b48bfc0d98b9ccef1 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -3084,6 +3084,7 @@ ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit, + } + + free(resstr); ++ resstr = NULL; + + flat_server_name = get_server_netbios_name(ipactx); + if (!flat_server_name) { +-- +2.43.0 diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec index a56d6ff..4434bf1 100644 --- a/SPECS/ipa.spec +++ b/SPECS/ipa.spec @@ -189,7 +189,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 11%{?rc_version:.%rc_version}%{?dist}.alma.1 +Release: 14%{?rc_version:.%rc_version}%{?dist}.alma.1 Summary: The Identity, Policy and Audit system License: GPLv3+ @@ -233,6 +233,26 @@ Patch0016: 0016-ipa-kdb-Detect-and-block-Bronze-Bit-attacks.patch # https://github.com/freeipa/freeipa/commit/86b073a7f03ba0edf4dd91f85b96c89107e9e673 Patch0017: 0017-Integration-tests-for-verifying-Referer.patch +# https://gitlab.com/redhat/centos-stream/rpms/ipa/-/commit/e57a97aa674560ef56317c22526c47d73fbdbc4d +Patch0018: 0018-adtrustinstance-make-sure-NetBIOS-name-defaults-are-.patch +# https://gitlab.com/redhat/centos-stream/rpms/ipa/-/commit/13b768665085c547533f5cd433b6c80243a8605a +Patch0019: 0019-ipatests-wait-for-replica-update-in-test_dns_locatio.patch +# https://gitlab.com/redhat/centos-stream/rpms/ipa/-/blob/4ced5cbefbd3d602546a4a16a38ce24fbae6aee8/ +Patch0020: 0020-ipa-kdb-Disable-Bronze-Bit-check-if-PAC-not-available_rhel.patch +Patch0021: 0021-Fix-session-cookie-access_rhel.patch +Patch0022: 0022-ipa-kdb-Fix-memory-leak-during-PAC-verification_rhel.patch +Patch0023: 0023-Do-not-ignore-staged-users-in-sidgen-plugin_rhel.patch +Patch0024: 0024-kdb-PAC-generator-do-not-fail-if-canonical-principal-is-missing_rhel.patch +# https://pagure.io/freeipa/c/81aa6ef695838a4b2fb5a53e773ea379a492913d +Patch0025: 0025-ipd-kdb-Fix-some-mistakes-in.patch +# https://pagure.io/freeipa/c/7f072e348d318e928f6270a182ca04dee8716677 +Patch0026: 0026-ipa-kdb-Rework-ipadb_reinit_mspac.patch +# https://pagure.io/freeipa/c/44a762413c83f9637399afeb61b1e4b1ac111260 +Patch0027: 0027-ipatests-fix-tasks_wait_for_replication-method.patch +# https://gitlab.com/redhat/centos-stream/rpms/ipa/-/commit/a727d75b875b82042f453746bf3c2e24d374364f +Patch0028: 0028-ipa-kdb-Fix-double-free-in-ipadb_reinit_mspac.patch + + Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch @@ -1747,6 +1767,21 @@ fi %endif %changelog +* Wed Apr 10 2024 Eduard Abdullin - 4.9.12-14.alma.1 +- adtrustinstance: make sure NetBIOS name defaults are set + properly +- ipatests: wait for replica update in test_dns_locations +- ipa-kdb: Disable Bronze-Bit check if PAC not available +- ipapython: Clean up krb5_error +- ipapython: Correct return type of krb5_free_cred_contents +- ipa-kdb: Fix memory leak during PAC verification +- sidgen: ignore staged users when generating SIDs +- kdb: PAC generator: do not fail if canonical principal is missing +- Fix some mistakes in ipadb_check_for_bronze_bit_attack() +- ipa-kdb: Rework ipadb_reinit_mspac() +- ipatests: fix tasks.wait_for_replication method +- ipa-kdb: Fix double free in ipadb_reinit_mspac() + * Mon Jan 15 2024 Eduard Abdullin - 4.9.12-11.alma.1 - CVE-2023-5455 - ipa-kdb: Detect and block Bronze-Bit attacks @@ -1801,7 +1836,7 @@ fi * Thu May 25 2023 Rafael Jeffman - 4.9.12-2 - Use the OpenSSL certificate parser in cert-find - Resolves: RHBZ#2209947 + Resolves: RHBZ#2209947 * Wed May 24 2023 Rafael Jeffman - 4.9.12-1 - Rebase ipa to 4.9.12 @@ -1834,7 +1869,7 @@ fi Resolves: RHBZ#2129895 - Fix canonicalization issue in Web UI Resolves: RHBZ#2127035 -- Remove idnssoaserial argument from dns zone API. +- Remove idnssoaserial argument from dns zone API. Resolves: RHBZ#2108630 - Warn for permissions with read/write/search/compare and no attrs Resolves: RHBZ#2098187