diff --git a/SOURCES/0056-kdb-keep-ipadb_get_connection-from-succeeding-with-n.patch b/SOURCES/0056-kdb-keep-ipadb_get_connection-from-succeeding-with-n.patch new file mode 100644 index 0000000..751c1d9 --- /dev/null +++ b/SOURCES/0056-kdb-keep-ipadb_get_connection-from-succeeding-with-n.patch @@ -0,0 +1,87 @@ +From 5d893c9c3b8d384873f40d2524b1ebf0f34fb452 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Mon, 28 Apr 2025 18:01:39 +0200 +Subject: [PATCH] kdb: keep ipadb_get_connection() from succeeding with null + LDAP context + +The final call to ipadb_reinit_mspac() in ipadb_get_connection() is not +considered essential for the function to succeed, as there might be +cases where the required pieces of information to generate PACs are not +yet configured in the database. However, in environments where 389ds is +overwhelmed, the LDAP connection established at the beginning of +ipadb_get_connection() might already be lost while executing +ipadb_reinit_mspac(). + +Connection errors were not distinguished from configuration errors, +which could result in ipadb_get_connection() succeeding while the LDAP +context is set to null, leading to a KDC crash on the next LDAP request. + +ipadb_get_connection() now explicitly checks the value of the LDAP +context before returning. + +Fixes: https://pagure.io/freeipa/issue/9777 +Reviewed-By: Rob Crittenden +Reviewed-By: Rob Crittenden +Reviewed-By: Rafael Guterres Jeffman +--- + daemons/ipa-kdb/ipa_kdb.c | 31 ++++++++++++++++++++++++------- + 1 file changed, 24 insertions(+), 7 deletions(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c +index 903e19e83bbe383b878a3b9261dd501f96058d51..531ee223e1d5157c87a5c31dfe44b9cfa8dcc554 100644 +--- a/daemons/ipa-kdb/ipa_kdb.c ++++ b/daemons/ipa-kdb/ipa_kdb.c +@@ -530,26 +530,43 @@ int ipadb_get_connection(struct ipadb_context *ipactx) + + /* get adtrust options using default refresh interval */ + ret = ipadb_reinit_mspac(ipactx, false, &stmsg); +- if (ret && stmsg) +- krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg); ++ if (ret) { ++ if (stmsg) { ++ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg); ++ } ++ /* Initialization of the MS-PAC generator is an optional dependency. ++ * Fail only if the connection was lost. */ ++ if (!ipactx->lcontext) { ++ goto done; ++ } ++ } + + ret = 0; + + done: + ldap_msgfree(res); + ++ /* LDAP context should never be null on success, but keep this test out of ++ * security to make sure we do not return an invalid context. */ ++ if (ret == 0 && !ipactx->lcontext) { ++ krb5_klog_syslog(LOG_WARNING, "Internal malfunction: LDAP connection " ++ "process resulted in an invalid context " ++ "(please report this incident)"); ++ ret = LDAP_SERVER_DOWN; ++ } ++ + if (ret) { ++ /* Cleanup LDAP context if connection failed. */ + if (ipactx->lcontext) { + ldap_unbind_ext_s(ipactx->lcontext, NULL, NULL); + ipactx->lcontext = NULL; + } +- if (ret == LDAP_SERVER_DOWN) { +- return ETIMEDOUT; +- } +- return EIO; ++ ++ /* Replace LDAP error code by POSIX error code. */ ++ ret = ret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO; + } + +- return 0; ++ return ret; + } + + static krb5_principal ipadb_create_local_tgs(krb5_context kcontext, +-- +2.49.0 + diff --git a/SOURCES/0057-Set-krbCanonicalName-admin-REALM-on-the-admin-user.patch b/SOURCES/0057-Set-krbCanonicalName-admin-REALM-on-the-admin-user.patch new file mode 100644 index 0000000..28ac9c6 --- /dev/null +++ b/SOURCES/0057-Set-krbCanonicalName-admin-REALM-on-the-admin-user.patch @@ -0,0 +1,188 @@ +From d6d2282f9f1b93ae7fb6e074920e41e64f35ab12 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 28 Apr 2025 13:43:40 -0400 +Subject: [PATCH] Set krbCanonicalName=admin@REALM on the admin user + +The admin must always own this name. If another entry has this +value set then remove it. + +There is a uniqueness plugin for this attribute so the only two +possibilities are: + +- no entry has this value set +- the admin user has this value set +- a different entry has the value set + +Still, for robustness purposes, the upgrade plugin will handle +more entries. + +Signed-off-by: Rob Crittenden +--- + install/share/bootstrap-template.ldif | 1 + + .../updates/90-post_upgrade_plugins.update | 1 + + .../plugins/add_admin_krbcanonicalname.py | 79 +++++++++++++++++++ + ipatests/test_integration/test_commands.py | 38 +++++++++ + 4 files changed, 119 insertions(+) + create mode 100644 ipaserver/install/plugins/add_admin_krbcanonicalname.py + +diff --git a/install/share/bootstrap-template.ldif b/install/share/bootstrap-template.ldif +index 325eb8450..94972eb72 100644 +--- a/install/share/bootstrap-template.ldif ++++ b/install/share/bootstrap-template.ldif +@@ -239,6 +239,7 @@ objectClass: ipasshuser + uid: admin + krbPrincipalName: admin@$REALM + krbPrincipalName: root@$REALM ++krbCanonicalName: admin@$REALM + cn: Administrator + sn: Administrator + uidNumber: $IDSTART +diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update +index 7c3bba3e0..3d78c7b5a 100644 +--- a/install/updates/90-post_upgrade_plugins.update ++++ b/install/updates/90-post_upgrade_plugins.update +@@ -25,6 +25,7 @@ plugin: update_mapping_Guests_to_nobody + plugin: fix_kra_people_entry + plugin: update_pwpolicy + plugin: update_pwpolicy_grace ++plugin: add_admin_krbcanonicalname + + # last + # DNS version 1 +diff --git a/ipaserver/install/plugins/add_admin_krbcanonicalname.py b/ipaserver/install/plugins/add_admin_krbcanonicalname.py +new file mode 100644 +index 000000000..e9ffdf55a +--- /dev/null ++++ b/ipaserver/install/plugins/add_admin_krbcanonicalname.py +@@ -0,0 +1,79 @@ ++# ++# Copyright (C) 2025 FreeIPA Contributors see COPYING for license ++# ++ ++from __future__ import absolute_import ++ ++import logging ++ ++from ipalib import errors ++from ipalib import Registry ++from ipalib import Updater ++from ipapython.dn import DN ++ ++logger = logging.getLogger(__name__) ++ ++register = Registry() ++ ++ ++@register() ++class add_admin_krbcanonicalname(Updater): ++ """ ++ Ensures that only the admin user has the krbCanonicalName of ++ admin@$REALM. ++ """ ++ ++ def execute(self, **options): ++ ldap = self.api.Backend.ldap2 ++ ++ search_filter = ( ++ "(krbcanonicalname=admin@{})".format(self.api.env.realm)) ++ try: ++ (entries, _truncated) = ldap.find_entries( ++ filter=search_filter, base_dn=self.api.env.basedn, ++ time_limit=0, size_limit=0) ++ except errors.EmptyResult: ++ logger.debug("add_admin_krbcanonicalname: No user set with " ++ "admin krbcanonicalname") ++ entries = [] ++ # fall through ++ except errors.ExecutionError as e: ++ logger.error("add_admin_krbcanonicalname: Can not get list " ++ "of krbcanonicalname: %s", e) ++ return False, [] ++ ++ admin_set = False ++ # admin should be only user with admin@ as krbcanonicalname ++ # It has a uniquness setting so there can be only one, we ++ # just didn't automatically set it for admin. ++ for entry in entries: ++ if entry.single_value.get('uid') != 'admin': ++ logger.critical( ++ "add_admin_krbcanonicalname: " ++ "entry %s has a krbcanonicalname of admin. Removing.", ++ entry.dn) ++ del entry['krbcanonicalname'] ++ ldap.update_entry(entry) ++ else: ++ admin_set = True ++ ++ if not admin_set: ++ dn = DN( ++ ('uid', 'admin'), ++ self.api.env.container_user, ++ self.api.env.basedn) ++ entry = ldap.get_entry(dn) ++ entry['krbcanonicalname'] = 'admin@%s' % self.api.env.realm ++ try: ++ ldap.update_entry(entry) ++ except errors.DuplicateEntry: ++ logger.critical( ++ "add_admin_krbcanonicalname: " ++ "Failed to set krbcanonicalname on admin. It is set " ++ "on another entry.") ++ except errors.ExecutionError as e: ++ logger.critical( ++ "add_admin_krbcanonicalname: " ++ "Failed to set krbcanonicalname on admin: %s", e) ++ ++ return False, [] +diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py +index 621982c4f..1526a6e0d 100644 +--- a/ipatests/test_integration/test_commands.py ++++ b/ipatests/test_integration/test_commands.py +@@ -1883,6 +1883,44 @@ class TestIPACommandWithoutReplica(IntegrationTest): + assert old_err_msg not in dirsrv_error_log + assert re.search(new_err_msg, dirsrv_error_log) + ++ def test_unique_krbcanonicalname(self): ++ """Verify that the uniqueness for krbcanonicalname is working""" ++ master = self.master ++ ++ base_dn = str(master.domain.basedn) ++ hostname = master.hostname ++ realm = master.domain.realm ++ principal = f'test/{hostname}@{realm}' ++ entry_ldif = textwrap.dedent(""" ++ dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn} ++ changetype: add ++ ipakrbprincipalalias: test/{hostname}@{realm} ++ krbprincipalname: {principal} ++ objectclass: ipakrbprincipal ++ objectclass: ipaobject ++ objectclass: ipaservice ++ objectclass: krbprincipal ++ objectclass: krbprincipalaux ++ objectclass: top ++ krbcanonicalname: admin@{realm} ++ managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn} ++ """).format( ++ base_dn=base_dn, ++ hostname=hostname, ++ principal=principal, ++ realm=realm) ++ tasks.kdestroy_all(master) ++ master.run_command( ++ ['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}']) ++ args = [ ++ 'ldapmodify', ++ '-Y', ++ 'GSSAPI' ++ ] ++ result = master.run_command(args, stdin_text=entry_ldif, ++ raiseonerr=False) ++ assert "entry with the same attribute value" in result.stderr_text ++ + + class TestIPAautomount(IntegrationTest): + @classmethod +-- +2.48.1 + diff --git a/SPECS/freeipa.spec b/SPECS/freeipa.spec index 843a547..59b9b59 100644 --- a/SPECS/freeipa.spec +++ b/SPECS/freeipa.spec @@ -218,7 +218,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 14%{?rc_version:.%rc_version}%{?dist} +Release: 14%{?rc_version:.%rc_version}.0.1%{?dist}.1 Summary: The Identity, Policy and Audit system License: GPL-3.0-or-later @@ -297,6 +297,8 @@ Patch0052: 0052-Add-DNS-over-TLS-support.patch Patch0053: 0053-Configure-the-pki-tomcatd-service-systemd-timeout.patch Patch0054: 0054-Align-startup_timeout-with-the-systemd-default-and-d.patch Patch0055: 0055-dns-only-disable-unbound-when-DoT-is-enabled.patch +Patch0056: 0056-kdb-keep-ipadb_get_connection-from-succeeding-with-n.patch +Patch0057: 0057-Set-krbCanonicalName-admin-REALM-on-the-admin-user.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch %endif %endif @@ -625,6 +627,7 @@ BuildArch: noarch Requires: %{name}-client-common = %{version}-%{release} Requires: httpd >= %{httpd_version} Requires: systemd-units >= %{systemd_version} +Requires: bind >= %{bind_version} %if 0%{?rhel} >= 8 && ! 0%{?eln} Requires: system-logos-ipa >= 80.4 %endif @@ -1099,7 +1102,8 @@ autoreconf -ivf %{enable_server_option} \ %{with_ipatests_option} \ %{with_ipa_join_xml_option} \ - %{linter_options} + %{linter_options} \ + --with-ipaplatform=rhel # run build in default dir # -Onone is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1398405 @@ -1943,6 +1947,16 @@ fi %endif %changelog +* Tue Jun 17 2025 EL Errata - 4.12.2-14.0.1 +- Set IPAPLATFORM=rhel when build on Oracle Linux [Orabug: 29516674] +- Add bind to ipa-server-common Requires [Orabug: 36518596] + +* Thu May 15 2025 Florence Blanc-Renaud - 4.12.2-14.1 +- Resolves: RHEL-89908 + EMBARGOED CVE-2025-4404 ipa: Privilege escalation from host to domain admin in FreeIPA +- Resolves: RHEL-89144 + kdb: ipadb_get_connection() succeeds but returns null LDAP context + * Thu Mar 20 2025 Thomas Woerner - 4.12.2-14 - Resolves: RHEL-80345 Use new bind9.18-dyndb-ldap and bind9.18 only for DNS over TLS with the ipa-server-encrypted-dns package