From 0022bd70d93708d325855d5271516d6cd894d6e8 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Nov 10 2021 20:00:27 +0000 Subject: ipa-kdb: add PAC_ATTRIBUTES_INFO PAC buffer support PAC_ATTRIBUTES_INFO PAC buffer allows both client and KDC to tell whether a PAC structure was requested by the client or it was provided by the KDC implicitly. Kerberos service then can continue processing or deny access in case client explicitly requested to operate without PAC. Fixes: https://pagure.io/freeipa/issue/9031 Signed-off-by: Alexander Bokovoy Signed-off-by: Andrew Bartlett Reviewed-By: Rob Crittenden --- diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am index 14c0546..5775d40 100644 --- a/daemons/ipa-kdb/Makefile.am +++ b/daemons/ipa-kdb/Makefile.am @@ -61,6 +61,7 @@ ipadb_la_LIBADD = \ $(UNISTRING_LIBS) \ $(SSSCERTMAP_LIBS) \ $(top_builddir)/util/libutil.la \ + -lsamba-errors \ $(NULL) if HAVE_CMOCKA @@ -104,6 +105,7 @@ ipa_kdb_tests_LDADD = \ -lkdb5 \ -lsss_idmap \ -lsamba-security-samba4 \ + -lsamba-errors \ $(NULL) appdir = $(libexecdir)/ipa diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c index ca6dacc..8a77a35 100644 --- a/daemons/ipa-kdb/ipa_kdb_mspac.c +++ b/daemons/ipa-kdb/ipa_kdb_mspac.c @@ -880,6 +880,87 @@ static krb5_error_code ipadb_get_sid_from_pac(TALLOC_CTX *ctx, return 0; } +#ifdef HAVE_PAC_ATTRIBUTES_INFO +static krb5_error_code ipadb_client_requested_pac(krb5_context context, + krb5_pac pac, + TALLOC_CTX *mem_ctx, + krb5_boolean *requested_pac) +{ + enum ndr_err_code ndr_err; + krb5_data k5pac_attrs_in; + DATA_BLOB pac_attrs_in; + union PAC_INFO pac_attrs; + krb5_error_code ret; + + *requested_pac = true; + + ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_ATTRIBUTES_INFO, + &k5pac_attrs_in); + if (ret != 0) { + return ret == ENOENT ? 0 : ret; + } + + pac_attrs_in = data_blob_const(k5pac_attrs_in.data, + k5pac_attrs_in.length); + + ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs, + PAC_TYPE_ATTRIBUTES_INFO, + (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); + krb5_free_data_contents(context, &k5pac_attrs_in); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); + krb5_klog_syslog(LOG_ERR, "can't parse the PAC ATTRIBUTES_INFO: %s\n", + nt_errstr(nt_status)); + return KRB5_KDB_INTERNAL_ERROR; + } + + if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY + | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) { + *requested_pac = true; + } else { + *requested_pac = false; + } + + return 0; +} + +static krb5_error_code ipadb_get_pac_attrs_blob(TALLOC_CTX *mem_ctx, + const krb5_boolean *pac_request, + DATA_BLOB *pac_attrs_data) +{ + union PAC_INFO pac_attrs; + enum ndr_err_code ndr_err; + + memset(&pac_attrs, 0, sizeof(pac_attrs)); + + *pac_attrs_data = data_blob_null; + + /* Set the length of the flags in bits. */ + pac_attrs.attributes_info.flags_length = 2; + + if (pac_request == NULL) { + pac_attrs.attributes_info.flags + |= PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY; + } else if (*pac_request) { + pac_attrs.attributes_info.flags + |= PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED; + } + + ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs, + PAC_TYPE_ATTRIBUTES_INFO, + (ndr_push_flags_fn_t)ndr_push_PAC_INFO); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); + krb5_klog_syslog(LOG_ERR, "can't create PAC ATTRIBUTES_INFO: %s\n", + nt_errstr(nt_status)); + return KRB5_KDB_INTERNAL_ERROR; + } + + return 0; +} + +#endif + static krb5_error_code ipadb_get_pac(krb5_context kcontext, krb5_db_entry *client, unsigned int flags, @@ -1025,6 +1106,26 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_UPN_DNS_INFO, &data); +#ifdef HAVE_PAC_ATTRIBUTES_INFO + /* == Add implicit PAC type attributes info as we always try to generate PAC == */ + { + DATA_BLOB pac_attrs_data; + + kerr = ipadb_get_pac_attrs_blob(tmpctx, NULL, &pac_attrs_data); + 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(kcontext, *pac, PAC_TYPE_ATTRIBUTES_INFO, &data); + if (kerr) { + goto done; + } + } +#endif + #ifdef HAVE_PAC_REQUESTER_SID { union PAC_INFO pac_requester_sid; @@ -2165,6 +2266,48 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, continue; } +#ifdef HAVE_PAC_ATTRIBUTES_INFO + if (types[i] == PAC_TYPE_ATTRIBUTES_INFO && + pac_blob.length != 0) { + /* == Check whether PAC was requested or given implicitly == */ + DATA_BLOB pac_attrs_data; + krb5_boolean pac_requested; + + TALLOC_CTX *tmpctx = talloc_new(NULL); + if (tmpctx == NULL) { + kerr = ENOMEM; + krb5_pac_free(context, new_pac); + goto done; + } + + kerr = ipadb_client_requested_pac(context, old_pac, tmpctx, &pac_requested); + if (kerr != 0) { + talloc_free(tmpctx); + krb5_pac_free(context, new_pac); + goto done; + } + + kerr = ipadb_get_pac_attrs_blob(tmpctx, &pac_requested, &pac_attrs_data); + if (kerr) { + talloc_free(tmpctx); + krb5_pac_free(context, new_pac); + 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); + krb5_pac_free(context, new_pac); + goto done; + } + + continue; + } +#endif + if (types[i] == KRB5_PAC_DELEGATION_INFO && (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { /* skip it here, we will add it explicitly later */ diff --git a/server.m4 b/server.m4 index 648423d..5a14af0 100644 --- a/server.m4 +++ b/server.m4 @@ -116,6 +116,14 @@ AC_CHECK_MEMBER( [AC_MSG_NOTICE([struct PAC_REQUESTER_SID is not available, account protection is not active])], [[#include #include ]]) + +AC_CHECK_MEMBER( + [struct PAC_ATTRIBUTES_INFO.flags], + [AC_DEFINE([HAVE_PAC_ATTRIBUTES_INFO], [1], + [struct PAC_ATTRIBUTES_INFO is available.])], + [AC_MSG_NOTICE([struct PAC_ATTRIBUTES_INFO is not available, account protection is not active])], + [[#include + #include ]]) CFLAGS="$bck_cflags" LIBPDB_NAME=""