diff --git a/SOURCES/0023-Tolerate-absence-of-PAC-ticket-signature-depending-o.patch b/SOURCES/0023-Tolerate-absence-of-PAC-ticket-signature-depending-o.patch new file mode 100644 index 0000000..a221759 --- /dev/null +++ b/SOURCES/0023-Tolerate-absence-of-PAC-ticket-signature-depending-o.patch @@ -0,0 +1,574 @@ +From 51c378f66fcf59322a0774a6d9b37e7e9ac55a17 Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Fri, 7 Apr 2023 17:04:06 +0200 +Subject: [PATCH] Tolerate absence of PAC ticket signature depending of server + capabilities + +Since November 2020, Active Directory KDC generates a new type of +signature as part of the PAC. It is called "ticket signature", and is +generated based on the encrypted part of the ticket. The presence of +this signature is not mandatory in order for the PAC to be accepted for +S4U requests. + +However, the behavior is different for MIT krb5. Support was added as +part of the 1.20 release, and this signature is required in order to +process S4U requests. Contrary to the PAC extended KDC signature, the +code generating this signature cannot be isolated and backported to +older krb5 versions because this version of the KDB API does not allow +passing the content of the ticket's encrypted part to IPA. + +This is an issue in gradual upgrade scenarios where some IPA servers +rely on 1.19 and older versions of MIT krb5, while others use version +1.20 or newer. A service ticket that was provided by 1.19- IPA KDC will +be rejected when used by a service against a 1.20+ IPA KDC for S4U +requests. + +On Fedora, CentOS 9 Stream, and RHEL 9, when the krb5 version is 1.20 or +newer, it will include a downstream-only update adding the +"optional_pac_tkt_chksum" KDB string attribute allowing to tolerate the +absence of PAC ticket signatures, if necessary. + +This commit adds an extra step during the installation and update +processes where it adds a "pacTktSignSupported" ipaConfigString +attribute in "cn=KDC,cn=[server],cn=masters,cn=ipa,cn=etc,[basedn]" if +the MIT krb5 version IPA what built with was 1.20 or newer. + +This commit also set "optional_pac_tkt_chksum" as a virtual KDB entry +attribute. This means the value of the attribute is not actually stored +in the database (to avoid race conditions), but its value is determined +at the KDC starting time by search the "pacTktSignSupported" +ipaConfigString in the server list. If this value is missing for at +least of them is missing, enforcement of the PAC ticket signature is +disabled by setting "optional_pac_tkt_chksum" to true for the local +realm TGS KDB entry. + +For foreign realm TGS KDB entries, the "optional_pac_tkt_chksum" virtual +string attribute is set to true systematically, because, at least for +now, trusted AD domains can still have PAC ticket signature support +disabled. + +Given the fact the "pacTktSignSupported" ipaConfigString for a single +server is added when this server is updated, and that the value of +"optional_pac_tkt_chksum" is determined at KDC starting time based on +the ipaConfigString attributes of all the KDCs in the domain, this +requires to restart all the KDCs in the domain after all IPA servers +were updated in order for PAC ticket signature enforcement to actually +take effect. + +Fixes: https://pagure.io/freeipa/issue/9371 +Signed-off-by: Julien Rische +Reviewed-By: Rob Crittenden +Reviewed-By: Alexander Bokovoy +(cherry picked from commit bbe545ff9feb972e549c743025e4a26b14ef8f89) +--- + VERSION.m4 | 6 ++ + configure.ac | 1 + + daemons/ipa-kdb/ipa_kdb.c | 55 +++++++++++ + daemons/ipa-kdb/ipa_kdb.h | 1 + + daemons/ipa-kdb/ipa_kdb_principals.c | 139 +++++++++++++++++++++++---- + ipapython/Makefile.am | 15 +-- + ipapython/version.py.in | 4 + + ipaserver/install/krbinstance.py | 25 ++++- + ipaserver/install/server/upgrade.py | 5 + + ipaserver/masters.py | 2 + + 10 files changed, 225 insertions(+), 28 deletions(-) + +diff --git a/VERSION.m4 b/VERSION.m4 +index e5d60c4c3..9b727feca 100644 +--- a/VERSION.m4 ++++ b/VERSION.m4 +@@ -137,6 +137,11 @@ ifelse(IPA_VERSION_IS_GIT_SNAPSHOT, yes, + IPA_GIT_VERSION), + NEWLINE)) dnl IPA_VERSION end + ++######################################################## ++# Version of MIT krb5 used to build IPA ++######################################################## ++define(IPA_KRB5_BUILD_VERSION, translit(esyscmd(krb5-config --version | awk '{ print $NF }'), NEWLINE)) ++ + dnl DEBUG: uncomment following lines and run command m4 VERSION.m4 + dnl `IPA_VERSION: ''IPA_VERSION' + dnl `IPA_GIT_VERSION: ''IPA_GIT_VERSION' +@@ -144,3 +149,4 @@ dnl `IPA_GIT_BRANCH: ''IPA_GIT_BRANCH' + dnl `IPA_API_VERSION: ''IPA_API_VERSION' + dnl `IPA_DATA_VERSION: ''IPA_DATA_VERSION' + dnl `IPA_NUM_VERSION: ''IPA_NUM_VERSION' ++dnl `IPA_KRB5_BUILD_VERSION: ''IPA_KRB5_BUILD_VERSION' +diff --git a/configure.ac b/configure.ac +index 140045821..973cba33c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -460,6 +460,7 @@ AC_SUBST(VENDOR_SUFFIX) + AC_SUBST([VERSION], [IPA_VERSION]) + AC_SUBST([GIT_VERSION], [IPA_GIT_VERSION]) + AC_SUBST([GIT_BRANCH], [IPA_GIT_BRANCH]) ++AC_SUBST([KRB5_BUILD_VERSION], [IPA_KRB5_BUILD_VERSION]) + # used by Makefile.am for files depending on templates + AC_SUBST([CONFIG_STATUS]) + +diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c +index 93563536c..9a56640ff 100644 +--- a/daemons/ipa-kdb/ipa_kdb.c ++++ b/daemons/ipa-kdb/ipa_kdb.c +@@ -524,6 +524,52 @@ static krb5_principal ipadb_create_local_tgs(krb5_context kcontext, + return tgtp; + } + ++static char *no_attrs[] = { ++ LDAP_NO_ATTRS, ++ ++ NULL ++}; ++ ++static krb5_error_code ++should_support_pac_tkt_sign(krb5_context kcontext, bool *result) ++{ ++ struct ipadb_context *ipactx; ++ krb5_error_code kerr; ++ LDAPMessage *res = NULL; ++ char *masters_dn = NULL; ++ int count; ++ ++ char *kdc_filter = "(&(cn=KDC)(objectClass=ipaConfigObject)" ++ "(!(ipaConfigString=pacTktSignSupported)))"; ++ ++ ipactx = ipadb_get_context(kcontext); ++ if (!ipactx) { ++ kerr = KRB5_KDB_DBNOTINITED; ++ goto done; ++ } ++ ++ count = asprintf(&masters_dn, "cn=masters,cn=ipa,cn=etc,%s", ipactx->base); ++ if (count < 0) { ++ kerr = ENOMEM; ++ goto done; ++ } ++ ++ kerr = ipadb_simple_search(ipactx, masters_dn, LDAP_SCOPE_SUBTREE, ++ kdc_filter, no_attrs, &res); ++ if (kerr) ++ goto done; ++ ++ count = ldap_count_entries(ipactx->lcontext, res); ++ ++ if (result) ++ *result = (count == 0); ++ ++done: ++ free(masters_dn); ++ ldap_msgfree(res); ++ return kerr; ++} ++ + /* INTERFACE */ + + static krb5_error_code ipadb_init_library(void) +@@ -544,6 +590,7 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext, + krb5_error_code kerr; + int ret; + int i; ++ bool pac_tkt_sign_supported; + + /* make sure the context is freed to avoid leaking it */ + ipactx = ipadb_get_context(kcontext); +@@ -628,6 +675,14 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext, + goto fail; + } + ++ /* Enforce PAC ticket signature verification if supported by all KDCs */ ++ kerr = should_support_pac_tkt_sign(kcontext, &pac_tkt_sign_supported); ++ if (kerr) { ++ ret = kerr; ++ goto fail; ++ } ++ ipactx->optional_pac_tkt_chksum = !pac_tkt_sign_supported; ++ + return 0; + + fail: +diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h +index 7aa5be494..0f4d3e431 100644 +--- a/daemons/ipa-kdb/ipa_kdb.h ++++ b/daemons/ipa-kdb/ipa_kdb.h +@@ -143,6 +143,7 @@ struct ipadb_context { + krb5_key_salt_tuple *def_encs; + int n_def_encs; + struct ipadb_mspac *mspac; ++ bool optional_pac_tkt_chksum; + #ifdef HAVE_KRB5_CERTAUTH_PLUGIN + krb5_certauth_moddata certauth_moddata; + #endif +diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c +index e95cb453c..e6c3fba21 100644 +--- a/daemons/ipa-kdb/ipa_kdb_principals.c ++++ b/daemons/ipa-kdb/ipa_kdb_principals.c +@@ -113,6 +113,8 @@ static char *std_principal_obj_classes[] = { + + #define DEFAULT_TL_DATA_CONTENT "\x00\x00\x00\x00principal@UNINITIALIZED" + ++#define OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME "optional_pac_tkt_chksum" ++ + static int ipadb_ldap_attr_to_tl_data(LDAP *lcontext, LDAPMessage *le, + char *attrname, + krb5_tl_data **result, int *num) +@@ -178,10 +180,56 @@ done: + return ret; + } + +-static krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry, +- krb5_int16 type, +- krb5_ui_2 length, +- const krb5_octet *data) ++static bool ++is_tgs_princ(krb5_context kcontext, krb5_const_principal princ) ++{ ++ krb5_data *primary; ++ size_t l_tgs_name; ++ ++ if (2 != krb5_princ_size(kcontext, princ)) ++ return false; ++ ++ primary = krb5_princ_component(kcontext, princ, 0); ++ ++ l_tgs_name = strlen(KRB5_TGS_NAME); ++ ++ if (l_tgs_name != primary->length) ++ return false; ++ ++ return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name); ++} ++ ++static krb5_error_code ++cmp_local_tgs_princ(krb5_context kcontext, const char *local_realm, ++ krb5_const_principal princ, bool *result) ++{ ++ krb5_principal local_tgs_princ; ++ size_t l_local_realm; ++ krb5_error_code kerr; ++ bool res; ++ ++ l_local_realm = strlen(local_realm); ++ ++ kerr = krb5_build_principal(kcontext, &local_tgs_princ, ++ l_local_realm, local_realm, ++ KRB5_TGS_NAME, local_realm, NULL); ++ if (kerr) ++ goto end; ++ ++ res = (bool) krb5_principal_compare(kcontext, local_tgs_princ, princ); ++ ++ if (result) ++ *result = res; ++ ++end: ++ krb5_free_principal(kcontext, local_tgs_princ); ++ return kerr; ++} ++ ++krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry, ++ krb5_int16 type, ++ krb5_ui_2 length, ++ const krb5_octet *data) + { + krb5_error_code kerr; + krb5_tl_data *new_td = NULL; +@@ -1632,6 +1680,8 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, + krb5_db_entry **entry) + { + struct ipadb_context *ipactx; ++ bool is_local_tgs_princ; ++ const char *opt_pac_tkt_chksum_val; + krb5_error_code kerr; + + *entry = NULL; +@@ -1647,11 +1697,33 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, + + /* Lookup local names and aliases first. */ + kerr = dbget_princ(kcontext, ipactx, search_for, flags, entry); +- if (kerr != KRB5_KDB_NOENTRY) { ++ if (kerr == KRB5_KDB_NOENTRY) { ++ kerr = dbget_alias(kcontext, ipactx, search_for, flags, entry); ++ } ++ if (kerr) + return kerr; ++ ++ /* If TGS principal, some virtual attributes may be added */ ++ if (is_tgs_princ(kcontext, (*entry)->princ)) { ++ kerr = cmp_local_tgs_princ(kcontext, ipactx->realm, (*entry)->princ, ++ &is_local_tgs_princ); ++ if (kerr) ++ return kerr; ++ ++ /* PAC ticket signature should be optional for foreign realms, and local ++ * realm if not supported by all servers ++ */ ++ if (!is_local_tgs_princ || ipactx->optional_pac_tkt_chksum) ++ opt_pac_tkt_chksum_val = "true"; ++ else ++ opt_pac_tkt_chksum_val = "false"; ++ ++ kerr = krb5_dbe_set_string(kcontext, *entry, ++ OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ opt_pac_tkt_chksum_val); + } + +- return dbget_alias(kcontext, ipactx, search_for, flags, entry); ++ return kerr; + } + + void ipadb_free_principal_e_data(krb5_context kcontext, krb5_octet *e_data) +@@ -1954,6 +2026,20 @@ done: + return kerr; + } + ++static bool should_filter_out_attr(krb5_tl_data *data) ++{ ++ switch (data->tl_data_type) { ++ case KRB5_TL_DB_ARGS: ++ case KRB5_TL_KADM_DATA: ++ case KRB5_TL_LAST_ADMIN_UNLOCK: ++ case KRB5_TL_LAST_PWD_CHANGE: ++ case KRB5_TL_MKVNO: ++ return true; ++ default: ++ return false; ++ } ++} ++ + static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods, + krb5_tl_data *tl_data, + int mod_op) +@@ -1965,13 +2051,8 @@ static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods, + int n, i; + + for (n = 0, data = tl_data; data; data = data->tl_data_next) { +- if (data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE || +- data->tl_data_type == KRB5_TL_KADM_DATA || +- data->tl_data_type == KRB5_TL_DB_ARGS || +- data->tl_data_type == KRB5_TL_MKVNO || +- data->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) { ++ if (should_filter_out_attr(data)) + continue; +- } + n++; + } + +@@ -1987,13 +2068,8 @@ static krb5_error_code ipadb_get_ldap_mod_extra_data(struct ipadb_mods *imods, + + for (i = 0, data = tl_data; data; data = data->tl_data_next) { + +- if (data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE || +- data->tl_data_type == KRB5_TL_KADM_DATA || +- data->tl_data_type == KRB5_TL_DB_ARGS || +- data->tl_data_type == KRB5_TL_MKVNO || +- data->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) { ++ if (should_filter_out_attr(data)) + continue; +- } + + be_type = htons(data->tl_data_type); + +@@ -2745,10 +2821,37 @@ done: + return kerr; + } + ++static krb5_error_code ++remove_virtual_str_attrs(krb5_context kcontext, krb5_db_entry *entry) ++{ ++ char *str_attr_val; ++ krb5_error_code kerr; ++ ++ kerr = krb5_dbe_get_string(kcontext, entry, ++ OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ &str_attr_val); ++ if (kerr) ++ return kerr; ++ ++ if (str_attr_val) ++ kerr = krb5_dbe_set_string(kcontext, entry, ++ OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ NULL); ++ ++ krb5_dbe_free_string(kcontext, str_attr_val); ++ return kerr; ++} ++ + krb5_error_code ipadb_put_principal(krb5_context kcontext, + krb5_db_entry *entry, + char **db_args) + { ++ krb5_error_code kerr; ++ ++ kerr = remove_virtual_str_attrs(kcontext, entry); ++ if (kerr) ++ return kerr; ++ + if (entry->mask & KMASK_PRINCIPAL) { + return ipadb_add_principal(kcontext, entry); + } else { +diff --git a/ipapython/Makefile.am b/ipapython/Makefile.am +index 7038e8b57..6b336d8fe 100644 +--- a/ipapython/Makefile.am ++++ b/ipapython/Makefile.am +@@ -13,11 +13,12 @@ bdist_wheel: version.py + $(AM_V_GEN)awk '$$1 == "default:" { print $$2 }' $< >$@ + + version.py: version.py.in .DEFAULT_PLUGINS $(top_builddir)/$(CONFIG_STATUS) +- $(AM_V_GEN)sed \ +- -e 's|@API_VERSION[@]|$(API_VERSION)|g' \ +- -e 's|@NUM_VERSION[@]|$(NUM_VERSION)|g' \ +- -e 's|@VERSION[@]|$(VERSION)|g' \ +- -e 's|@VENDOR_SUFFIX[@]|$(VENDOR_SUFFIX)|g' \ +- -e '/@DEFAULT_PLUGINS[@]/r .DEFAULT_PLUGINS' \ +- -e '/@DEFAULT_PLUGINS[@]/d' \ ++ $(AM_V_GEN)sed \ ++ -e 's|@API_VERSION[@]|$(API_VERSION)|g' \ ++ -e 's|@NUM_VERSION[@]|$(NUM_VERSION)|g' \ ++ -e 's|@VERSION[@]|$(VERSION)|g' \ ++ -e 's|@VENDOR_SUFFIX[@]|$(VENDOR_SUFFIX)|g' \ ++ -e 's|@KRB5_BUILD_VERSION[@]|$(KRB5_BUILD_VERSION)|g' \ ++ -e '/@DEFAULT_PLUGINS[@]/r .DEFAULT_PLUGINS' \ ++ -e '/@DEFAULT_PLUGINS[@]/d' \ + $< > $@ +diff --git a/ipapython/version.py.in b/ipapython/version.py.in +index 5a71fb8cf..a8f4218a7 100644 +--- a/ipapython/version.py.in ++++ b/ipapython/version.py.in +@@ -17,6 +17,8 @@ + # along with this program. If not, see . + # + ++from pkg_resources import parse_version ++ + # The full version including strings + VERSION = "@VERSION@" + +@@ -51,3 +53,5 @@ API_VERSION = "@API_VERSION@" + DEFAULT_PLUGINS = frozenset(l.strip() for l in """ + @DEFAULT_PLUGINS@ + """.strip().splitlines()) ++ ++KRB5_BUILD_VERSION = parse_version("@KRB5_BUILD_VERSION@") +diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py +index a5eaa7b17..acb7419d6 100644 +--- a/ipaserver/install/krbinstance.py ++++ b/ipaserver/install/krbinstance.py +@@ -26,6 +26,7 @@ import socket + import dbus + + import dns.name ++from pkg_resources import parse_version + + from ipalib import x509 + from ipalib.install import certstore +@@ -34,6 +35,7 @@ from ipaserver.install import installutils + from ipapython import ipaldap + from ipapython import ipautil + from ipapython import kernel_keyring ++from ipapython.version import KRB5_BUILD_VERSION + from ipalib import api, errors + from ipalib.constants import ANON_USER + from ipalib.install import certmonger +@@ -42,15 +44,17 @@ from ipapython.dogtag import KDC_PROFILE + + from ipaserver.install import replication + from ipaserver.install import certs +-from ipaserver.masters import find_providing_servers ++from ipaserver.masters import ( ++ find_providing_servers, ++ PAC_TKT_SIGN_SUPPORTED, ++ PKINIT_ENABLED, ++) + from ipaplatform.constants import constants + from ipaplatform.tasks import tasks + from ipaplatform.paths import paths + + logger = logging.getLogger(__name__) + +-PKINIT_ENABLED = 'pkinitEnabled' +- + MASTER_KEY_TYPE = 'aes256-sha2' + SUPPORTED_ENCTYPES = ('aes256-sha2:special', 'aes128-sha2:special', + 'aes256-sha2:normal', 'aes128-sha2:normal', +@@ -169,6 +173,13 @@ class KrbInstance(service.Service): + # Add the host to the ipaserver host group + self._ldap_update(['20-ipaservers_hostgroup.update']) + ++ def pac_tkt_sign_support_enable(self): ++ """ ++ Advertise PAC ticket signature support in master's KDC entry in LDAP ++ """ ++ service.set_service_entry_config( ++ 'KDC', self.fqdn, [PAC_TKT_SIGN_SUPPORTED], self.suffix) ++ + def __common_setup(self, realm_name, host_name, domain_name, admin_password): + self.fqdn = host_name + self.realm = realm_name.upper() +@@ -212,6 +223,10 @@ class KrbInstance(service.Service): + + self.__common_post_setup() + ++ if KRB5_BUILD_VERSION >= parse_version('1.20'): ++ self.step("enable PAC ticket signature support", ++ self.pac_tkt_sign_support_enable) ++ + self.start_creation() + + self.kpasswd = KpasswdInstance() +@@ -235,6 +250,10 @@ class KrbInstance(service.Service): + + self.__common_post_setup() + ++ if KRB5_BUILD_VERSION >= parse_version('1.20'): ++ self.step("enable PAC ticket signature support", ++ self.pac_tkt_sign_support_enable) ++ + self.start_creation() + + self.kpasswd = KpasswdInstance() +diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py +index 5f5a60d10..f8701c8a0 100644 +--- a/ipaserver/install/server/upgrade.py ++++ b/ipaserver/install/server/upgrade.py +@@ -18,6 +18,7 @@ import sys + import tempfile + from contextlib import contextmanager + from augeas import Augeas ++from pkg_resources import parse_version + + from ipalib import api, x509 + from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE, IPA_CA_RECORD +@@ -36,6 +37,7 @@ from ipapython import ipautil, version + from ipapython import ipaldap + from ipapython import directivesetter + from ipapython.dn import DN ++from ipapython.version import KRB5_BUILD_VERSION + from ipaplatform.constants import constants + from ipaplatform.paths import paths + from ipaserver import servroles +@@ -1961,6 +1963,9 @@ def upgrade_configuration(): + enable_server_snippet() + setup_kpasswd_server(krb) + ++ if KRB5_BUILD_VERSION >= parse_version('1.20'): ++ krb.pac_tkt_sign_support_enable() ++ + # Must be executed after certificate_renewal_update + # (see function docstring for details) + http_certificate_ensure_ipa_ca_dnsname(http) +diff --git a/ipaserver/masters.py b/ipaserver/masters.py +index b532f2b72..c9b57b2a5 100644 +--- a/ipaserver/masters.py ++++ b/ipaserver/masters.py +@@ -20,6 +20,8 @@ logger = logging.getLogger(__name__) + CONFIGURED_SERVICE = u'configuredService' + ENABLED_SERVICE = u'enabledService' + HIDDEN_SERVICE = u'hiddenService' ++PAC_TKT_SIGN_SUPPORTED = u'pacTktSignSupported' ++PKINIT_ENABLED = u'pkinitEnabled' + + # The service name as stored in cn=masters,cn=ipa,cn=etc. The values are: + # 0: systemd service name +-- +2.39.2 + diff --git a/SOURCES/0024-ipa-kdb-postpone-ticket-checksum-configuration.patch b/SOURCES/0024-ipa-kdb-postpone-ticket-checksum-configuration.patch new file mode 100644 index 0000000..dc2112f --- /dev/null +++ b/SOURCES/0024-ipa-kdb-postpone-ticket-checksum-configuration.patch @@ -0,0 +1,269 @@ +From 33242a967011b9cbce74b6b3c39a7247d66eda19 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Thu, 25 May 2023 09:19:57 +0300 +Subject: [PATCH] ipa-kdb: postpone ticket checksum configuration + +Postpone ticket checksum configuration after KDB module was initialized. +This, in practice, should now happen when a master key is retrieved. + +Signed-off-by: Alexander Bokovoy +Reviewed-By: Julien Rische +(cherry picked from commit fefa0248296413b6ee5ad2543d8feb1b31840aee) +--- + daemons/ipa-kdb/ipa_kdb.c | 56 +---------------------- + daemons/ipa-kdb/ipa_kdb.h | 8 +++- + daemons/ipa-kdb/ipa_kdb_common.c | 67 +++++++++++++++++++++++++++- + daemons/ipa-kdb/ipa_kdb_principals.c | 14 ++++-- + 4 files changed, 84 insertions(+), 61 deletions(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c +index 9a56640ff..a3c3746c2 100644 +--- a/daemons/ipa-kdb/ipa_kdb.c ++++ b/daemons/ipa-kdb/ipa_kdb.c +@@ -524,52 +524,6 @@ static krb5_principal ipadb_create_local_tgs(krb5_context kcontext, + return tgtp; + } + +-static char *no_attrs[] = { +- LDAP_NO_ATTRS, +- +- NULL +-}; +- +-static krb5_error_code +-should_support_pac_tkt_sign(krb5_context kcontext, bool *result) +-{ +- struct ipadb_context *ipactx; +- krb5_error_code kerr; +- LDAPMessage *res = NULL; +- char *masters_dn = NULL; +- int count; +- +- char *kdc_filter = "(&(cn=KDC)(objectClass=ipaConfigObject)" +- "(!(ipaConfigString=pacTktSignSupported)))"; +- +- ipactx = ipadb_get_context(kcontext); +- if (!ipactx) { +- kerr = KRB5_KDB_DBNOTINITED; +- goto done; +- } +- +- count = asprintf(&masters_dn, "cn=masters,cn=ipa,cn=etc,%s", ipactx->base); +- if (count < 0) { +- kerr = ENOMEM; +- goto done; +- } +- +- kerr = ipadb_simple_search(ipactx, masters_dn, LDAP_SCOPE_SUBTREE, +- kdc_filter, no_attrs, &res); +- if (kerr) +- goto done; +- +- count = ldap_count_entries(ipactx->lcontext, res); +- +- if (result) +- *result = (count == 0); +- +-done: +- free(masters_dn); +- ldap_msgfree(res); +- return kerr; +-} +- + /* INTERFACE */ + + static krb5_error_code ipadb_init_library(void) +@@ -590,7 +544,6 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext, + krb5_error_code kerr; + int ret; + int i; +- bool pac_tkt_sign_supported; + + /* make sure the context is freed to avoid leaking it */ + ipactx = ipadb_get_context(kcontext); +@@ -662,6 +615,8 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext, + goto fail; + } + ++ ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_UNDEFINED; ++ + ret = ipadb_get_connection(ipactx); + if (ret != 0) { + /* Not a fatal failure, as the LDAP server may be temporarily down. */ +@@ -675,13 +630,6 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext, + goto fail; + } + +- /* Enforce PAC ticket signature verification if supported by all KDCs */ +- kerr = should_support_pac_tkt_sign(kcontext, &pac_tkt_sign_supported); +- if (kerr) { +- ret = kerr; +- goto fail; +- } +- ipactx->optional_pac_tkt_chksum = !pac_tkt_sign_supported; + + return 0; + +diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h +index 0f4d3e431..edf3b0dfc 100644 +--- a/daemons/ipa-kdb/ipa_kdb.h ++++ b/daemons/ipa-kdb/ipa_kdb.h +@@ -126,6 +126,12 @@ struct ipadb_global_config { + bool disable_preauth_for_spns; + }; + ++enum ipadb_tristate_option { ++ IPADB_TRISTATE_FALSE = FALSE, ++ IPADB_TRISTATE_TRUE = TRUE, ++ IPADB_TRISTATE_UNDEFINED, ++}; ++ + #define IPA_CONTEXT_MAGIC 0x0c027ea7 + struct ipadb_context { + int magic; +@@ -143,7 +149,7 @@ struct ipadb_context { + krb5_key_salt_tuple *def_encs; + int n_def_encs; + struct ipadb_mspac *mspac; +- bool optional_pac_tkt_chksum; ++ enum ipadb_tristate_option optional_pac_tkt_chksum; + #ifdef HAVE_KRB5_CERTAUTH_PLUGIN + krb5_certauth_moddata certauth_moddata; + #endif +diff --git a/daemons/ipa-kdb/ipa_kdb_common.c b/daemons/ipa-kdb/ipa_kdb_common.c +index 42e0856d0..ae7742a32 100644 +--- a/daemons/ipa-kdb/ipa_kdb_common.c ++++ b/daemons/ipa-kdb/ipa_kdb_common.c +@@ -158,12 +158,75 @@ static bool ipadb_need_retry(struct ipadb_context *ipactx, int error) + return false; + } + ++static char *no_attrs[] = { ++ LDAP_NO_ATTRS, ++ ++ NULL ++}; ++ ++static int ++should_support_pac_tkt_sign(struct ipadb_context *ipactx, bool *result) ++{ ++ int ret; ++ LDAPMessage *res = NULL; ++ char *masters_dn = NULL; ++ int count; ++ ++ char *kdc_filter = "(&(cn=KDC)(objectClass=ipaConfigObject)" ++ "(!(ipaConfigString=pacTktSignSupported)))"; ++ ++ if (!ipactx) { ++ ret = KRB5_KDB_DBNOTINITED; ++ goto done; ++ } ++ ++ count = asprintf(&masters_dn, "cn=masters,cn=ipa,cn=etc,%s", ipactx->base); ++ if (count < 0) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = ipadb_simple_search(ipactx, masters_dn, LDAP_SCOPE_SUBTREE, ++ kdc_filter, no_attrs, &res); ++ if (ret) ++ goto done; ++ ++ count = ldap_count_entries(ipactx->lcontext, res); ++ ++ if (result) ++ *result = (count == 0); ++ ++done: ++ free(masters_dn); ++ ldap_msgfree(res); ++ return ret; ++} ++ + static int ipadb_check_connection(struct ipadb_context *ipactx) + { ++ int ret = 0; ++ + if (ipactx->lcontext == NULL) { +- return ipadb_get_connection(ipactx); ++ ret = ipadb_get_connection(ipactx); ++ } ++ if ((ret == 0) && (ipactx->optional_pac_tkt_chksum == IPADB_TRISTATE_UNDEFINED)) { ++ bool pac_tkt_sign_supported; ++ ++ /* Enforce PAC ticket signature verification if supported by all KDCs ++ * To avoid loops as all search functions call into ++ * ipadb_check_connection(), mark that the init is complete at this ++ * point. Default to not issuing PAC to be safe. ++ */ ++ ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_FALSE; ++ ret = should_support_pac_tkt_sign(ipactx, ++ &pac_tkt_sign_supported); ++ if (ret == 0) { ++ ipactx->optional_pac_tkt_chksum = !pac_tkt_sign_supported; ++ } else { ++ ipactx->optional_pac_tkt_chksum = IPADB_TRISTATE_UNDEFINED; ++ } + } +- return 0; ++ return ret; + } + + krb5_error_code ipadb_simple_search(struct ipadb_context *ipactx, +diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c +index e6c3fba21..d35cec2e0 100644 +--- a/daemons/ipa-kdb/ipa_kdb_principals.c ++++ b/daemons/ipa-kdb/ipa_kdb_principals.c +@@ -113,7 +113,9 @@ static char *std_principal_obj_classes[] = { + + #define DEFAULT_TL_DATA_CONTENT "\x00\x00\x00\x00principal@UNINITIALIZED" + +-#define OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME "optional_pac_tkt_chksum" ++#ifndef KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM ++#define KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM "optional_pac_tkt_chksum" ++#endif + + static int ipadb_ldap_attr_to_tl_data(LDAP *lcontext, LDAPMessage *le, + char *attrname, +@@ -1710,6 +1712,10 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, + if (kerr) + return kerr; + ++ /* We should have been initialized at this point already */ ++ if (ipactx->optional_pac_tkt_chksum == IPADB_TRISTATE_UNDEFINED) { ++ return KRB5_KDB_SERVER_INTERNAL_ERR; ++ } + /* PAC ticket signature should be optional for foreign realms, and local + * realm if not supported by all servers + */ +@@ -1719,7 +1725,7 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, + opt_pac_tkt_chksum_val = "false"; + + kerr = krb5_dbe_set_string(kcontext, *entry, +- OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, + opt_pac_tkt_chksum_val); + } + +@@ -2828,14 +2834,14 @@ remove_virtual_str_attrs(krb5_context kcontext, krb5_db_entry *entry) + krb5_error_code kerr; + + kerr = krb5_dbe_get_string(kcontext, entry, +- OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, + &str_attr_val); + if (kerr) + return kerr; + + if (str_attr_val) + kerr = krb5_dbe_set_string(kcontext, entry, +- OPT_PAC_TKT_CHKSUM_STR_ATTR_NAME, ++ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, + NULL); + + krb5_dbe_free_string(kcontext, str_attr_val); +-- +2.39.2 + diff --git a/SPECS/freeipa.spec b/SPECS/freeipa.spec index 97b5b00..3699d2e 100644 --- a/SPECS/freeipa.spec +++ b/SPECS/freeipa.spec @@ -66,7 +66,7 @@ %if 0%{?rhel} %global package_name ipa %global alt_name freeipa -%global krb5_version 1.20.1-1 +%global krb5_version 1.20.1-9 %global krb5_kdb_version 9.0 # 0.7.16: https://github.com/drkjam/netaddr/issues/71 %global python_netaddr_version 0.7.19 @@ -223,7 +223,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 6%{?rc_version:.%rc_version}%{?dist} +Release: 7%{?rc_version:.%rc_version}.0.1%{?dist} Summary: The Identity, Policy and Audit system License: GPLv3+ @@ -269,6 +269,8 @@ Patch0019: 0019-tests-Add-new-ipa-ca-error-messages-to-IPADNSSystemR.patch Patch0020: 0020-ipatests-tests-for-certificate-pruning.patch Patch0021: 0021-ipatests-ensure-that-ipa-automember-rebuild-prints-a.patch Patch0022: 0022-ipatests-fix-tests-in-TestACMEPrune.patch +Patch0023: 0023-Tolerate-absence-of-PAC-ticket-signature-depending-o.patch +Patch0024: 0024-ipa-kdb-postpone-ticket-checksum-configuration.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch %endif %endif @@ -1018,7 +1020,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 @@ -1756,6 +1759,12 @@ fi %endif %changelog +* Wed Jun 21 2023 EL Errata - 4.10.1-7.0.1 +- Set IPAPLATFORM=rhel when build on Oracle Linux [Orabug: 29516674] + +* Thu Jun 01 2023 Julien Rische - 4.10.1-7 +- Resolves: rhbz#2211389 Handle PAC signatures based on domain and server capabilities + * Wed Feb 22 2023 Florence Blanc-Renaud - 4.10.1-6 - Resolves: rhbz#2169632 Backport latest test fixes in python3-ipatests