From a74c5fe9967888b3bce98e1b0f6d7054207b0e13 Mon Sep 17 00:00:00 2001 From: Julien Rische Date: Wed, 12 Jun 2024 15:32:55 +0200 Subject: [PATCH] ipa release 4.9.13-11 - Add missing part of backported CVE-2024-3183 fix Resolves: RHEL-29927 Signed-off-by: Julien Rische --- ...combinatorial-logic-for-ticket-flags.patch | 199 ++++++++++++------ ipa.spec | 6 +- 2 files changed, 138 insertions(+), 67 deletions(-) diff --git a/0028-kdb-apply-combinatorial-logic-for-ticket-flags.patch b/0028-kdb-apply-combinatorial-logic-for-ticket-flags.patch index 7e0a72c..d4c98a6 100644 --- a/0028-kdb-apply-combinatorial-logic-for-ticket-flags.patch +++ b/0028-kdb-apply-combinatorial-logic-for-ticket-flags.patch @@ -1,4 +1,4 @@ -From 70d23b8f6bbcabe2eb621ffa5009866b43e5570a Mon Sep 17 00:00:00 2001 +From 542e12325afc2f64298f90296760235bfdcef04a Mon Sep 17 00:00:00 2001 From: Julien Rische Date: Mon, 25 Mar 2024 18:25:52 +0200 Subject: [PATCH] kdb: apply combinatorial logic for ticket flags @@ -44,15 +44,21 @@ flags like -allow_svr for a user principal by setting the case, any ticket flag can be configured in the principal ticket policy, except requires_preauth and allow_tix. +When in IPA setup mode (using the "ipa-setup-override-restrictions" KDB +argument), all the system described above is disabled and ticket flags +are written in the principal ticket policy as they are provided. This is +required to initialize the Kerberos LDAP container during IPA server +installation. + This fixes CVE-2024-3183 Signed-off-by: Julien Rische --- daemons/ipa-kdb/ipa_kdb.h | 43 ++++ - daemons/ipa-kdb/ipa_kdb_principals.c | 306 ++++++++++++++++++++++----- + daemons/ipa-kdb/ipa_kdb_principals.c | 353 +++++++++++++++++++++++---- util/ipa_krb5.c | 18 ++ util/ipa_krb5.h | 4 + - 4 files changed, 319 insertions(+), 52 deletions(-) + 4 files changed, 365 insertions(+), 53 deletions(-) diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h index 7baf4697f..85cabe142 100644 @@ -116,10 +122,10 @@ index 7baf4697f..85cabe142 100644 int ipadb_get_connection(struct ipadb_context *ipactx); diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c -index 07cc87746..cb18861bb 100644 +index 07cc87746..6eb542d4f 100644 --- a/daemons/ipa-kdb/ipa_kdb_principals.c +++ b/daemons/ipa-kdb/ipa_kdb_principals.c -@@ -706,9 +706,10 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, +@@ -706,9 +706,12 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, "krbTicketFlags", &result); if (ret == 0) { entry->attributes = result; @@ -127,12 +133,28 @@ index 07cc87746..cb18861bb 100644 - *polmask |= TKTFLAGS_BIT; } + /* Since principal, global policy, and virtual ticket flags are combined, -+ * they must always be resolved. */ -+ *polmask |= TKTFLAGS_BIT; ++ * they must always be resolved, except if we are in IPA setup mode (because ++ * ticket policies and virtual ticket flags are irrelevant in this case). */ ++ if (!ipactx->override_restrictions) ++ *polmask |= TKTFLAGS_BIT; ret = ipadb_ldap_attr_to_int(lcontext, lentry, "krbMaxTicketLife", &result); -@@ -1251,23 +1252,150 @@ done: +@@ -912,7 +915,12 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, + goto done; + } + if (ret == 0) { +- ied->ipa_user = true; ++ if (1 == krb5_princ_size(kcontext, entry->princ)) { ++ /* A principal must be a POSIX account AND have only one element to ++ * be considered a user (this is to filter out CIFS principals). */ ++ ied->ipa_user = true; ++ } ++ + ret = ipadb_ldap_attr_to_str(lcontext, lentry, + "uid", &uidstring); + if (ret != 0 && ret != ENOENT) { +@@ -1251,23 +1259,150 @@ done: return ret; } @@ -162,8 +184,10 @@ index 07cc87746..cb18861bb 100644 + if (!ied->ipa_user) { + kerr = 0; + goto end; -+ } -+ + } + +- /* By default require preauth for all principals */ +- return KRB5_KDB_REQUIRES_PRE_AUTH; + kerr = krb5_dbe_get_string(ipactx->kcontext, entry, + IPA_KDB_STRATTR_FINAL_USER_TKTFLAGS, &str); + if (kerr) @@ -208,10 +232,8 @@ index 07cc87746..cb18861bb 100644 + gcfg = ipadb_get_global_config(ipactx); + if (gcfg && gcfg->disable_preauth_for_spns) + vsflg &= ~KRB5_KDB_REQUIRES_PRE_AUTH; - } - -- /* By default require preauth for all principals */ -- return KRB5_KDB_REQUIRES_PRE_AUTH; ++ } ++ + if (tktflags) + *tktflags |= vsflg; + @@ -295,7 +317,7 @@ index 07cc87746..cb18861bb 100644 } static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, -@@ -1280,6 +1408,7 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, +@@ -1280,6 +1415,7 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, char *policy_dn = NULL; LDAPMessage *res = NULL; LDAPMessage *first; @@ -303,7 +325,7 @@ index 07cc87746..cb18861bb 100644 int result; int ret; -@@ -1288,12 +1417,18 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, +@@ -1288,12 +1424,18 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, return KRB5_KDB_DBNOTINITED; } @@ -322,7 +344,7 @@ index 07cc87746..cb18861bb 100644 ret = asprintf(&policy_dn, "cn=%s,cn=kerberos,%s", ipactx->realm, ipactx->base); if (ret == -1) { -@@ -1337,12 +1472,13 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, +@@ -1337,12 +1479,13 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, } } if (polmask & TKTFLAGS_BIT) { @@ -342,7 +364,7 @@ index 07cc87746..cb18861bb 100644 } } -@@ -1366,13 +1502,27 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, +@@ -1366,13 +1509,27 @@ static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, if (polmask & MAXRENEWABLEAGE_BIT) { entry->max_renewable_life = 604800; } @@ -373,7 +395,44 @@ index 07cc87746..cb18861bb 100644 done: ldap_msgfree(res); free(policy_dn); -@@ -2275,6 +2425,85 @@ static krb5_error_code ipadb_get_ldap_mod_auth_ind(krb5_context kcontext, +@@ -1864,6 +2021,36 @@ static void ipadb_mods_free_tip(struct ipadb_mods *imods) + imods->tip--; + } + ++/* Use LDAP REPLACE operation to remove an attribute. ++ * Contrary to the DELETE operation, it will not fail if the attribute does not ++ * exist. */ ++static krb5_error_code ++ipadb_ldap_replace_remove(struct ipadb_mods *imods, char *attribute) ++{ ++ krb5_error_code kerr; ++ LDAPMod *m = NULL; ++ ++ kerr = ipadb_mods_new(imods, &m); ++ if (kerr) ++ return kerr; ++ ++ m->mod_op = LDAP_MOD_REPLACE; ++ m->mod_type = strdup(attribute); ++ if (!m->mod_type) { ++ kerr = ENOMEM; ++ goto end; ++ } ++ ++ m->mod_values = NULL; ++ ++ kerr = 0; ++ ++end: ++ if (kerr) ++ ipadb_mods_free_tip(imods); ++ return kerr; ++} ++ + static krb5_error_code ipadb_get_ldap_mod_str(struct ipadb_mods *imods, + char *attribute, char *value, + int mod_op) +@@ -2275,6 +2462,93 @@ static krb5_error_code ipadb_get_ldap_mod_auth_ind(krb5_context kcontext, return ret; } @@ -388,70 +447,78 @@ index 07cc87746..cb18861bb 100644 + krb5_flags tktflags_mask; + int tktflags; + -+ kerr = ipadb_get_edata(entry, &ied); -+ if (kerr) -+ goto end; -+ + ipactx = ipadb_get_context(kcontext); + if (!ipactx) { + kerr = KRB5_KDB_DBNOTINITED; + goto end; + } + -+ kerr = get_virtual_static_tktflags_mask(ipactx, entry, &tktflags_mask); -+ if (kerr) -+ goto end; -+ -+ kerr = are_final_tktflags(ipactx, entry, &final_tktflags); -+ if (kerr) -+ goto end; -+ -+ /* Flags from the global ticket policy are filtered out only if the user -+ * principal flags are not final. */ -+ if (!final_tktflags) { -+ krb5_flags gtpol_tktflags = 0; -+ -+ kerr = add_global_ticket_policy_flags(ipactx, NULL, >pol_tktflags); ++ if (ipactx->override_restrictions) { ++ /* In IPA setup mode, IPA edata might not be available. In this mode, ++ * ticket flags are written as they are provided. */ ++ tktflags = (int)entry->attributes; ++ } else { ++ kerr = ipadb_get_edata(entry, &ied); + if (kerr) + goto end; + -+ tktflags_mask &= ~gtpol_tktflags; -+ } -+ -+ tktflags = (int)(entry->attributes & tktflags_mask); -+ -+ if (LDAP_MOD_REPLACE == mod_op && !ied->has_tktpolaux) { -+ if (0 == tktflags) { -+ /* No point initializing principal ticket policy if there are no -+ * flags left after filtering out virtual and global ticket policy -+ * ones. */ -+ kerr = 0; ++ kerr = get_virtual_static_tktflags_mask(ipactx, entry, &tktflags_mask); ++ if (kerr) + goto end; ++ ++ kerr = are_final_tktflags(ipactx, entry, &final_tktflags); ++ if (kerr) ++ goto end; ++ ++ /* Flags from the global ticket policy are filtered out only if the user ++ * principal flags are not final. */ ++ if (!final_tktflags) { ++ krb5_flags gbl_tktflags = 0; ++ ++ kerr = add_global_ticket_policy_flags(ipactx, NULL, &gbl_tktflags); ++ if (kerr) ++ goto end; ++ ++ tktflags_mask &= ~gbl_tktflags; + } + -+ /* if the object does not have the krbTicketPolicyAux class -+ * we need to add it or this will fail, only for modifications. -+ * We always add this objectclass by default when doing an add -+ * from scratch. */ -+ kerr = ipadb_get_ldap_mod_str(imods, "objectclass", -+ "krbTicketPolicyAux", LDAP_MOD_ADD); -+ if (kerr) -+ goto end; ++ tktflags = (int)(entry->attributes & tktflags_mask); ++ ++ if (LDAP_MOD_REPLACE == mod_op && ied && !ied->has_tktpolaux) { ++ if (0 == tktflags) { ++ /* No point initializing principal ticket policy if there are no ++ * flags left after filtering out virtual and global ticket ++ * policy ones. */ ++ kerr = 0; ++ goto end; ++ } ++ ++ /* if the object does not have the krbTicketPolicyAux class ++ * we need to add it or this will fail, only for modifications. ++ * We always add this objectclass by default when doing an add ++ * from scratch. */ ++ kerr = ipadb_get_ldap_mod_str(imods, "objectclass", ++ "krbTicketPolicyAux", LDAP_MOD_ADD); ++ if (kerr) ++ goto end; ++ } + } + -+ kerr = ipadb_get_ldap_mod_int(imods, "krbTicketFlags", tktflags, mod_op); -+ if (kerr) -+ goto end; -+ -+ /* If there are no custom ticket flags set in the principal, remove the -+ * "krbTicketFlags" attribute. */ -+ if (0 == tktflags) { ++ if (tktflags != 0) { + kerr = ipadb_get_ldap_mod_int(imods, "krbTicketFlags", tktflags, -+ LDAP_MOD_DELETE); ++ mod_op); ++ if (kerr) ++ goto end; ++ } else if (LDAP_MOD_REPLACE == mod_op) { ++ /* If the principal is not being created, and there are no custom ticket ++ * flags to be set, remove the "krbTicketFlags" attribute. */ ++ kerr = ipadb_ldap_replace_remove(imods, "krbTicketFlags"); + if (kerr) + goto end; + } + ++ kerr = 0; ++ +end: + return kerr; +} @@ -459,7 +526,7 @@ index 07cc87746..cb18861bb 100644 static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext, struct ipadb_mods *imods, krb5_db_entry *entry, -@@ -2350,36 +2579,9 @@ static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext, +@@ -2350,36 +2624,9 @@ static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext, /* KADM5_ATTRIBUTES */ if (entry->mask & KMASK_ATTRIBUTES) { @@ -544,5 +611,5 @@ index 7d2ebae98..d0280940a 100644 + * src/lib/krb5/krb/libdef_parse.c:_krb5_conf_boolean() */ +bool ipa_krb5_parse_bool(const char *str); -- -2.44.0 +2.45.1 diff --git a/ipa.spec b/ipa.spec index 65595ba..a646bfc 100644 --- a/ipa.spec +++ b/ipa.spec @@ -190,7 +190,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 10%{?rc_version:.%rc_version}%{?dist} +Release: 11%{?rc_version:.%rc_version}%{?dist} Summary: The Identity, Policy and Audit system License: GPLv3+ @@ -1752,6 +1752,10 @@ fi %endif %changelog +* Wed Jun 12 2024 Julien Rische - 4.9.13-11 +- Add missing part of backported CVE-2024-3183 fix + Resolves: RHEL-29927 + * Tue Apr 30 2024 Julien Rische - 4.9.13-10 - kdb: apply combinatorial logic for ticket flags (CVE-2024-3183) Resolves: RHEL-29927