From 23336160f21611942512e7b1996051d34817873d Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sat, 30 Oct 2021 10:08:34 +0300 Subject: [PATCH] ipa-kdb: add support for PAC_UPN_DNS_INFO_EX CVE-2020-25721 mitigation: KDC must provide the new HAS_SAM_NAME_AND_SID buffer with sAMAccountName and ObjectSID values associated with the principal. The mitigation only works if NDR library supports the PAC_UPN_DNS_INFO_EX buffer type. In case we cannot detect it at compile time, a warning will be displayed at configure stage. Fixes: https://pagure.io/freeipa/issue/9031 Signed-off-by: Alexander Bokovoy Reviewed-by: Rob Crittenden Reviewed-By: Rob Crittenden --- daemons/ipa-kdb/ipa_kdb_mspac.c | 41 +++++++++++++++++++++++++++++++-- server.m4 | 7 ++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c index f729b9f2e..75cb4f3b7 100644 --- a/daemons/ipa-kdb/ipa_kdb_mspac.c +++ b/daemons/ipa-kdb/ipa_kdb_mspac.c @@ -812,6 +812,25 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, return ret; } +static krb5_error_code ipadb_get_sid_from_pac(TALLOC_CTX *ctx, + struct PAC_LOGON_INFO *info, + struct dom_sid *sid) +{ + struct dom_sid *client_sid = NULL; + /* Construct SID from the PAC */ + if (info->info3.base.rid == 0) { + client_sid = info->info3.sids[0].sid; + } else { + client_sid = dom_sid_dup(ctx, info->info3.base.domain_sid); + if (!client_sid) { + return ENOMEM; + } + sid_append_rid(client_sid, info->info3.base.rid); + } + *sid = *client_sid; + return 0; +} + static krb5_error_code ipadb_get_pac(krb5_context kcontext, krb5_db_entry *client, unsigned int flags, @@ -830,6 +849,7 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, enum ndr_err_code ndr_err; union PAC_INFO pac_upn; char *principal = NULL; + struct dom_sid client_sid; /* When no client entry is there, we cannot generate MS-PAC */ if (!client) { @@ -930,6 +950,18 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED; } + kerr = ipadb_get_sid_from_pac(tmpctx, pac_info.logon_info.info, &client_sid); + if (kerr) { + goto done; + } + +#ifdef HAVE_PAC_UPN_DNS_INFO_EX + /* Add samAccountName and a SID */ + pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID; + pac_upn.upn_dns_info.ex.sam_name_and_sid.samaccountname = pac_info.logon_info.info->info3.base.account_name.string; + pac_upn.upn_dns_info.ex.sam_name_and_sid.objectsid = &client_sid; +#endif + ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_upn, PAC_TYPE_UPN_DNS_INFO, (ndr_push_flags_fn_t)ndr_push_PAC_INFO); @@ -1415,6 +1447,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, krb5_db_entry *client_actual = NULL; struct ipadb_e_data *ied = NULL; int flags = 0; + struct dom_sid client_sid; #ifdef KRB5_KDB_FLAG_ALIAS_OK flags = KRB5_KDB_FLAG_ALIAS_OK; #endif @@ -1460,11 +1493,15 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, goto done; } - result = dom_sid_check(ied->sid, info->info->info3.sids[0].sid, true); + kerr = ipadb_get_sid_from_pac(memctx, info->info, &client_sid); + if (kerr) { + goto done; + } + result = dom_sid_check(ied->sid, &client_sid, true); if (!result) { /* memctx is freed by the caller */ char *local_sid = dom_sid_string(memctx, ied->sid); - char *pac_sid = dom_sid_string(memctx, info->info->info3.sids[0].sid); + char *pac_sid = dom_sid_string(memctx, &client_sid); krb5_klog_syslog(LOG_ERR, "PAC issue: client principal has a SID " "different from what PAC claims. " "local [%s] vs PAC [%s]", diff --git a/server.m4 b/server.m4 index 3a2c3ae33..65c82d25a 100644 --- a/server.m4 +++ b/server.m4 @@ -101,6 +101,13 @@ AC_CHECK_MEMBER( [AC_MSG_NOTICE([struct PAC_DOMAIN_GROUP_MEMBERSHIP is not available])], [[#include #include ]]) +AC_CHECK_MEMBER( + [struct PAC_UPN_DNS_INFO.ex], + [AC_DEFINE([HAVE_PAC_UPN_DNS_INFO_EX], [1], + [union PAC_UPN_DNS_INFO_EX is available.])], + [AC_MSG_NOTICE([union PAC_UPN_DNS_INFO_EX is not available, account protection is not active])], + [[#include + #include ]]) CFLAGS="$bck_cflags"