From: Joseph Sutton Date: Mon, 19 Jun 2023 22:52:01 +0000 (+1200) Subject: third_party/heimdal: Import lorikeet-heimdal-202306192129 (commit 0096f9c1dc105d8ac9f... X-Git-Tag: talloc-2.4.1~192 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=95c02a9794b624e89eccd73cb0a4401a7417040a;p=thirdparty%2Fsamba.git third_party/heimdal: Import lorikeet-heimdal-202306192129 (commit 0096f9c1dc105d8ac9f7dd96d653b05228f7d280) NOTE: THIS COMMIT WON’T COMPILE/WORK ON ITS OWN! Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 2fbf7f72284..095234514e9 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -3,11 +3,6 @@ # kerberos ^samba.tests.krb5.compatability_tests.samba.tests.krb5.compatability_tests.SimpleKerberosTests.test_mit_ # -# AS-REQ tests -# -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_logon_hours_wrong_password.fl2003dc -^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_logon_hours_wrong_password.fl2008r2dc -# # Heimdal currently fails the following MS-KILE client principal lookup # tests ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_6_a @@ -39,7 +34,7 @@ ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed # -^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac_no_auth_data_required ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd\( ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_no_auth_data_required_a @@ -152,7 +147,6 @@ ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow.ad_dc ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_constrained_delegation.ad_dc ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_constrained_delegation_to_self.ad_dc -^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_constrained_delegation_wrong_sname.ad_dc ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_domain_local_group.ad_dc ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_domain_local_group_from_rodc.ad_dc ^samba.tests.krb5.authn_policy_tests.samba.tests.krb5.authn_policy_tests.AuthnPolicyTests.test_authn_policy_allowed_to_user_allow_from_rodc.ad_dc diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c index 1352a10fe01..b63d0b16a9d 100644 --- a/third_party/heimdal/kdc/fast.c +++ b/third_party/heimdal/kdc/fast.c @@ -877,8 +877,10 @@ _kdc_fast_strengthen_reply_key(astgs_request_t r) ret = krb5_generate_random_keyblock(r->context, r->reply_key.keytype, &r->strengthen_key); - if (ret) - krb5_abortx(r->context, "random generator fail"); + if (ret) { + kdc_log(r->context, r->config, 0, "failed to prepare random keyblock"); + return ret; + } ret = _krb5_fast_cf2(r->context, &r->strengthen_key, "strengthenkey", @@ -969,16 +971,14 @@ _kdc_fast_check_armor_pac(astgs_request_t r, int flags) goto out; } - if (r->explicit_armor_present) { - r->explicit_armor_clientdb = armor_db; - armor_db = NULL; + r->armor_clientdb = armor_db; + armor_db = NULL; - r->explicit_armor_client = armor_client; - armor_client = NULL; + r->armor_client = armor_client; + armor_client = NULL; - r->explicit_armor_pac = mspac; - mspac = NULL; - } + r->armor_pac = mspac; + mspac = NULL; out: krb5_xfree(armor_client_principal_name); diff --git a/third_party/heimdal/kdc/kdc-accessors.h b/third_party/heimdal/kdc/kdc-accessors.h index 911b83d7576..c00fd49d60b 100644 --- a/third_party/heimdal/kdc/kdc-accessors.h +++ b/third_party/heimdal/kdc/kdc-accessors.h @@ -346,24 +346,49 @@ ASTGS_REQUEST_GET_ACCESSOR(uint64_t, pac_attributes) ASTGS_REQUEST_SET_ACCESSOR(uint64_t, pac_attributes) +KDC_LIB_FUNCTION const HDB * KDC_LIB_CALL +kdc_request_get_explicit_armor_clientdb(astgs_request_t); + +KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL +kdc_request_get_explicit_armor_client(astgs_request_t); + +KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL +kdc_request_get_explicit_armor_server(astgs_request_t); + +KDC_LIB_FUNCTION krb5_const_pac KDC_LIB_CALL +kdc_request_get_explicit_armor_pac(astgs_request_t); + /* * const HDB * - * kdc_request_get_explicit_armor_clientdb(astgs_request_t); + * kdc_request_get_armor_clientdb(astgs_request_t); */ -ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, explicit_armor_clientdb) +ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, armor_clientdb) + +/* + * const hdb_entry * + * kdc_request_get_armor_client(astgs_request_t); + */ +ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, armor_client); /* * const hdb_entry * - * kdc_request_get_explicit_armor_client(astgs_request_t); + * kdc_request_get_armor_server(astgs_request_t); */ -ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, explicit_armor_client); +ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, armor_server); /* * krb5_const_pac - * kdc_request_get_explicit_armor_pac(astgs_request_t); + * kdc_request_get_armor_pac(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(struct krb5_pac_data *, armor_pac); + +/* + * krb5_boolean + * kdc_request_get_explicit_armor_present(astgs_request_t); */ -ASTGS_REQUEST_GET_ACCESSOR_PTR(struct krb5_pac_data *, explicit_armor_pac); +ASTGS_REQUEST_GET_ACCESSOR_PTR(krb5_boolean, explicit_armor_present); #endif /* HEIMDAL_KDC_KDC_ACCESSORS_H */ diff --git a/third_party/heimdal/kdc/kdc-audit.h b/third_party/heimdal/kdc/kdc-audit.h index df5362031f5..4097c48b761 100644 --- a/third_party/heimdal/kdc/kdc-audit.h +++ b/third_party/heimdal/kdc/kdc-audit.h @@ -52,6 +52,7 @@ #define KDC_AUTH_EVENT_PREAUTH_FAILED 8 /* generic PA failure */ #define KDC_AUTH_EVENT_PREAUTH_SUCCEEDED 9 /* generic (non-long term key) PA success */ #define KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY 10 /* PA failed to validate current long term key, but historic */ +#define KDC_AUTH_EVENT_CLIENT_FOUND 11 /* the client was successfully looked up */ /* * Audit keys to be queried using kdc_audit_getkv(). There are other keys diff --git a/third_party/heimdal/kdc/kdc-plugin.c b/third_party/heimdal/kdc/kdc-plugin.c index cbb61b51fc2..f1d9a1f7579 100644 --- a/third_party/heimdal/kdc/kdc-plugin.c +++ b/third_party/heimdal/kdc/kdc-plugin.c @@ -140,8 +140,8 @@ _kdc_pac_generate(astgs_request_t r, struct verify_uc { astgs_request_t r; - krb5_principal client_principal; - krb5_principal delegated_proxy_principal; + krb5_const_principal client_principal; + hdb_entry *delegated_proxy; hdb_entry *client; hdb_entry *server; hdb_entry *krbtgt; @@ -163,7 +163,7 @@ verify(krb5_context context, const void *plug, void *plugctx, void *userctx) ret = ft->pac_verify((void *)plug, uc->r, uc->client_principal, - uc->delegated_proxy_principal, + uc->delegated_proxy, uc->client, uc->server, uc->krbtgt, uc->ticket, uc->pac, uc->is_trusted); @@ -172,8 +172,8 @@ verify(krb5_context context, const void *plug, void *plugctx, void *userctx) krb5_error_code _kdc_pac_verify(astgs_request_t r, - const krb5_principal client_principal, - const krb5_principal delegated_proxy_principal, + krb5_const_principal client_principal, + hdb_entry *delegated_proxy, hdb_entry *client, hdb_entry *server, hdb_entry *krbtgt, @@ -188,7 +188,7 @@ _kdc_pac_verify(astgs_request_t r, uc.r = r; uc.client_principal = client_principal; - uc.delegated_proxy_principal = delegated_proxy_principal; + uc.delegated_proxy = delegated_proxy; uc.client = client; uc.server = server; uc.krbtgt = krbtgt; @@ -202,8 +202,9 @@ _kdc_pac_verify(astgs_request_t r, struct update_uc { astgs_request_t r; - krb5_principal client_principal; - krb5_principal delegated_proxy_principal; + krb5_const_principal client_principal; + hdb_entry *delegated_proxy; + krb5_const_pac delegated_proxy_pac; hdb_entry *client; hdb_entry *server; hdb_entry *krbtgt; @@ -223,15 +224,17 @@ update(krb5_context context, const void *plug, void *plugctx, void *userctx) ret = ft->pac_update((void *)plug, uc->r, uc->client_principal, - uc->delegated_proxy_principal, + uc->delegated_proxy, + uc->delegated_proxy_pac, uc->client, uc->server, uc->krbtgt, uc->pac); return ret; } krb5_error_code _kdc_pac_update(astgs_request_t r, - const krb5_principal client_principal, - const krb5_principal delegated_proxy_principal, + krb5_const_principal client_principal, + hdb_entry *delegated_proxy, + krb5_const_pac delegated_proxy_pac, hdb_entry *client, hdb_entry *server, hdb_entry *krbtgt, @@ -244,7 +247,8 @@ _kdc_pac_update(astgs_request_t r, uc.r = r; uc.client_principal = client_principal; - uc.delegated_proxy_principal = delegated_proxy_principal; + uc.delegated_proxy = delegated_proxy; + uc.delegated_proxy_pac = delegated_proxy_pac; uc.client = client; uc.server = server; uc.krbtgt = krbtgt; @@ -714,3 +718,27 @@ free_keyblock(EncryptionKey *key) #undef HEIMDAL_KDC_KDC_ACCESSORS_H #include "kdc-accessors.h" + +KDC_LIB_FUNCTION const HDB * KDC_LIB_CALL +kdc_request_get_explicit_armor_clientdb(astgs_request_t r) +{ + return r->explicit_armor_present ? r->armor_clientdb : NULL; +} + +KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL +kdc_request_get_explicit_armor_client(astgs_request_t r) +{ + return r->explicit_armor_present ? r->armor_client : NULL; +} + +KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL +kdc_request_get_explicit_armor_server(astgs_request_t r) +{ + return r->explicit_armor_present ? r->armor_server : NULL; +} + +KDC_LIB_FUNCTION krb5_const_pac KDC_LIB_CALL +kdc_request_get_explicit_armor_pac(astgs_request_t r) +{ + return r->explicit_armor_present ? r->armor_pac : NULL; +} diff --git a/third_party/heimdal/kdc/kdc-plugin.h b/third_party/heimdal/kdc/kdc-plugin.h index 2e26d90137e..7d44f0a5243 100644 --- a/third_party/heimdal/kdc/kdc-plugin.h +++ b/third_party/heimdal/kdc/kdc-plugin.h @@ -65,8 +65,8 @@ typedef krb5_error_code typedef krb5_error_code (KRB5_CALLCONV *krb5plugin_kdc_pac_verify)(void *, astgs_request_t, - const krb5_principal, /* new ticket client */ - const krb5_principal, /* delegation proxy */ + krb5_const_principal, /* new ticket client */ + hdb_entry *, /* delegation proxy */ hdb_entry *,/* client */ hdb_entry *,/* server */ hdb_entry *,/* krbtgt */ @@ -84,8 +84,9 @@ typedef krb5_error_code typedef krb5_error_code (KRB5_CALLCONV *krb5plugin_kdc_pac_update)(void *, astgs_request_t, - const krb5_principal, /* new ticket client */ - const krb5_principal, /* delegation proxy */ + krb5_const_principal, /* new ticket client */ + hdb_entry *, /* delegation proxy */ + krb5_const_pac, /* delegation proxy pac */ hdb_entry *,/* client */ hdb_entry *,/* server */ hdb_entry *,/* krbtgt */ diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h index bf9a0bc55e9..5fe9ce620ad 100644 --- a/third_party/heimdal/kdc/kdc_locl.h +++ b/third_party/heimdal/kdc/kdc_locl.h @@ -176,9 +176,9 @@ struct astgs_request_desc { krb5_ticket *armor_ticket; Key *armor_key; - hdb_entry *explicit_armor_client; - HDB *explicit_armor_clientdb; - krb5_pac explicit_armor_pac; + hdb_entry *armor_client; + HDB *armor_clientdb; + krb5_pac armor_pac; KDCFastState fast; }; diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c index 6d4887a44a6..463ee369117 100644 --- a/third_party/heimdal/kdc/kerberos5.c +++ b/third_party/heimdal/kdc/kerberos5.c @@ -1275,7 +1275,7 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa) struct kdc_patypes { int type; - char *name; + const char *name; unsigned int flags; #define PA_ANNOUNCE 1 #define PA_REQ_FAST 2 /* only use inside fast */ @@ -2199,7 +2199,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey, rodc_id, NULL, /* UPN */ canon_princ, - false, /* add_full_sig */ + FALSE, /* add_full_sig */ is_tgs ? &r->pac_attributes : NULL, &data); krb5_free_principal(r->context, client); @@ -2384,6 +2384,13 @@ _kdc_as_rep(astgs_request_t r) goto out; } + /* Validate armor TGT, and initialize the armor client and PAC */ + if (r->armor_ticket) { + ret = _kdc_fast_check_armor_pac(r, HDB_F_FOR_AS_REQ); + if (ret) + goto out; + } + b = &req->req_body; f = b->kdc_options; @@ -2476,6 +2483,10 @@ _kdc_as_rep(astgs_request_t r) goto out; } } + + kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT, + KDC_AUTH_EVENT_CLIENT_FOUND); + ret = _kdc_db_fetch(r->context, config, r->server_princ, HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags | (is_tgs ? HDB_F_GET_KRBTGT : 0), @@ -2495,6 +2506,10 @@ _kdc_as_rep(astgs_request_t r) goto out; } + ret = _kdc_check_access(r); + if(ret) + goto out; + /* * This has to be here (not later), because we need to have r->sessionetype * set prior to calling pa_pkinit_validate(), which in turn calls @@ -2662,15 +2677,6 @@ _kdc_as_rep(astgs_request_t r) r->canon_client_princ = r->client->principal; - /* - * Verify flags after the user been required to prove its identity - * with in a preauth mech. - */ - - ret = _kdc_check_access(r); - if(ret) - goto out; - if (_kdc_is_anon_request(&r->req)) { ret = _kdc_check_anon_policy(r); if (ret) { @@ -3058,7 +3064,10 @@ _kdc_as_rep(astgs_request_t r) } out: - r->error_code = ret; + if (ret) { + /* Overwrite ‘error_code’ only if we have an actual error. */ + r->error_code = ret; + } { krb5_error_code ret2 = _kdc_audit_request(r); if (ret2) { @@ -3076,7 +3085,7 @@ out: r->rep.padata, r->armor_crypto, &req->req_body, - r->error_code, + r->error_code ? r->error_code : ret, r->client_princ, r->server_princ, NULL, NULL, diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c index b01aa526283..79dbe6622f4 100644 --- a/third_party/heimdal/kdc/krb5tgs.c +++ b/third_party/heimdal/kdc/krb5tgs.c @@ -78,7 +78,7 @@ _kdc_synthetic_princ_used_p(krb5_context context, krb5_ticket *ticket) krb5_error_code _kdc_check_pac(astgs_request_t r, const krb5_principal client_principal, - const krb5_principal delegated_proxy_principal, + hdb_entry *delegated_proxy, hdb_entry *client, hdb_entry *server, hdb_entry *krbtgt, @@ -125,11 +125,11 @@ _kdc_check_pac(astgs_request_t r, /* Verify the KDC signatures. */ ret = _kdc_pac_verify(r, - client_principal, delegated_proxy_principal, + client_principal, delegated_proxy, client, server, krbtgt, tkt, pac, &is_trusted); if (ret == 0) { if (is_trusted) { - krb5_pac_set_trusted(pac, true); + krb5_pac_set_trusted(pac, TRUE); } if (pac_canon_name) { @@ -1383,6 +1383,9 @@ tgs_build_reply(astgs_request_t priv, int result; + const PA_DATA *for_user = NULL; + int for_user_idx = 0; + memset(&sessionkey, 0, sizeof(sessionkey)); memset(&adtkt, 0, sizeof(adtkt)); @@ -1592,7 +1595,7 @@ server_lookup: ret = krb5_unparse_name(context, priv->krbtgt->principal, &ktpn); kdc_log(context, config, 4, "No such principal %s (needed for authz-data signature keys) " - "while processing TGS-REQ for service %s with krbtg %s", + "while processing TGS-REQ for service %s with krbtgt %s", krbtgt_out_n, spn, (ret == 0) ? ktpn : ""); free(ktpn); ret = KRB5KRB_AP_ERR_NOT_US; @@ -1892,8 +1895,35 @@ server_lookup: goto out; } - if (priv->pac != NULL) { - ret = _kdc_pac_update(priv, priv->client_princ, NULL, + /* + * Process request + */ + + /* + * Services for User: protocol transition and constrained delegation + */ + + if (priv->client != NULL && + (for_user = _kdc_find_padata(&priv->req, + &for_user_idx, + KRB5_PADATA_FOR_USER)) != NULL) + { + /* Process an S4U2Self request. */ + ret = _kdc_validate_protocol_transition(priv, for_user); + if (ret) + goto out; + } else if (priv->client != NULL + && b->additional_tickets != NULL + && b->additional_tickets->len != 0 + && b->kdc_options.cname_in_addl_tkt + && b->kdc_options.enc_tkt_in_skey == 0) + { + /* Process an S4U2Proxy request. */ + ret = _kdc_validate_constrained_delegation(priv); + if (ret) + goto out; + } else if (priv->pac != NULL) { + ret = _kdc_pac_update(priv, priv->client_princ, NULL, NULL, priv->client, priv->server, priv->krbtgt, &priv->pac); if (ret == KRB5_PLUGIN_NO_HANDLE) { @@ -1915,18 +1945,6 @@ server_lookup: } } - /* - * Process request - */ - - /* - * Services for User: protocol transition and constrained delegation - */ - - ret = _kdc_validate_services_for_user(priv); - if (ret) - goto out; - if (b->enc_authorization_data) { unsigned auth_data_usage; krb5_crypto crypto; @@ -2206,7 +2224,10 @@ _kdc_tgs_rep(astgs_request_t r) } out: - r->error_code = ret; + if (ret) { + /* Overwrite ‘error_code’ only if we have an actual error. */ + r->error_code = ret; + } { krb5_error_code ret2 = _kdc_audit_request(r); if (ret2) { @@ -2223,7 +2244,7 @@ out: &error_method, r->armor_crypto, &req->req_body, - r->error_code, + r->error_code ? r->error_code : ret, r->client_princ ? r->client_princ :(r->ticket != NULL ? r->ticket->client : NULL), r->server_princ ? r->server_princ :(r->ticket != NULL ? r->ticket->server : NULL), csec, cusec, @@ -2260,12 +2281,12 @@ out: krb5_free_ticket(r->context, r->armor_ticket); if (r->armor_server) _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server); - if (r->explicit_armor_client) + if (r->armor_client) _kdc_free_ent(r->context, - r->explicit_armor_clientdb, - r->explicit_armor_client); - if (r->explicit_armor_pac) - krb5_pac_free(r->context, r->explicit_armor_pac); + r->armor_clientdb, + r->armor_client); + if (r->armor_pac) + krb5_pac_free(r->context, r->armor_pac); krb5_free_keyblock_contents(r->context, &r->reply_key); krb5_free_keyblock_contents(r->context, &r->enc_ad_key); krb5_free_keyblock_contents(r->context, &r->strengthen_key); diff --git a/third_party/heimdal/kdc/libkdc-exports.def b/third_party/heimdal/kdc/libkdc-exports.def index d7c5a0de1ab..a6aaf94d3fc 100644 --- a/third_party/heimdal/kdc/libkdc-exports.def +++ b/third_party/heimdal/kdc/libkdc-exports.def @@ -26,6 +26,10 @@ EXPORTS kdc_request_add_pac_buffer kdc_request_add_reply_padata kdc_request_get_addr + kdc_request_get_armor_client + kdc_request_get_armor_clientdb + kdc_request_get_armor_pac + kdc_request_get_armor_server kdc_request_get_canon_client_princ kdc_request_get_client kdc_request_get_clientdb @@ -37,6 +41,8 @@ EXPORTS kdc_request_get_explicit_armor_pac kdc_request_get_explicit_armor_clientdb kdc_request_get_explicit_armor_client + kdc_request_get_explicit_armor_present + kdc_request_get_explicit_armor_server kdc_request_get_from kdc_request_get_krbtgt kdc_request_get_krbtgtdb diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c index 6145fc8e8e1..c583c9b667d 100644 --- a/third_party/heimdal/kdc/mssfu.c +++ b/third_party/heimdal/kdc/mssfu.c @@ -97,13 +97,13 @@ check_constrained_delegation(krb5_context context, } /* - * Validate a protocol transition (S4U2Self) request. If present and - * successfully validated then the client in the request structure - * will be replaced with the impersonated client. + * Validate a protocol transition (S4U2Self) request. If successfully + * validated then the client in the request structure will be replaced + * with the impersonated client. */ -static krb5_error_code -validate_protocol_transition(astgs_request_t r) +krb5_error_code +_kdc_validate_protocol_transition(astgs_request_t r, const PA_DATA *for_user) { krb5_error_code ret; KDC_REQ_BODY *b = &r->req.req_body; @@ -113,28 +113,21 @@ validate_protocol_transition(astgs_request_t r) int flags = HDB_F_FOR_TGS_REQ; krb5_principal s4u_client_name = NULL, s4u_canon_client_name = NULL; krb5_pac s4u_pac = NULL; - const PA_DATA *sdata; char *s4ucname = NULL; - int i = 0; krb5_crypto crypto; krb5_data datack; PA_S4U2Self self; const char *str; - if (r->client == NULL) - return 0; - - sdata = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FOR_USER); - if (sdata == NULL) - return 0; + heim_assert(r->client != NULL, "client must be non-NULL"); memset(&self, 0, sizeof(self)); if (b->kdc_options.canonicalize) flags |= HDB_F_CANON; - ret = decode_PA_S4U2Self(sdata->padata_value.data, - sdata->padata_value.length, + ret = decode_PA_S4U2Self(for_user->padata_value.data, + for_user->padata_value.length, &self, NULL); if (ret) { kdc_audit_addreason((kdc_request_t)r, @@ -293,13 +286,13 @@ validate_protocol_transition(astgs_request_t r) */ if (r->client->flags.trusted_for_delegation && s4u_client->flags.forwardable) { - str = "[forwardable]"; + str = " [forwardable]"; } else { b->kdc_options.forwardable = 0; str = ""; } kdc_log(r->context, r->config, 4, "s4u2self %s impersonating %s to " - "service %s %s", r->cname, s4ucname, r->sname, str); + "service %s%s", r->cname, s4ucname, r->sname, str); /* * Replace all client information in the request with the @@ -332,13 +325,13 @@ out: } /* - * Validate a constrained delegation (S4U2Proxy) request. If present - * and successfully validated then the client in the request structure - * will be replaced with the client from the evidence ticket. + * Validate a constrained delegation (S4U2Proxy) request. If + * successfully validated then the client in the request structure will + * be replaced with the client from the evidence ticket. */ -static krb5_error_code -validate_constrained_delegation(astgs_request_t r) +krb5_error_code +_kdc_validate_constrained_delegation(astgs_request_t r) { krb5_error_code ret; KDC_REQ_BODY *b = &r->req.req_body; @@ -351,18 +344,13 @@ validate_constrained_delegation(astgs_request_t r) EncTicketPart evidence_tkt; HDB *s4u_clientdb; hdb_entry *s4u_client = NULL; + HDB *s4u_serverdb = NULL; + hdb_entry *s4u_server = NULL; krb5_boolean ad_kdc_issued = FALSE; Key *clientkey; Ticket *t; krb5_const_realm local_realm; - if (r->client == NULL - || b->additional_tickets == NULL - || b->additional_tickets->len == 0 - || b->kdc_options.cname_in_addl_tkt == 0 - || b->kdc_options.enc_tkt_in_skey) - return 0; - memset(&evidence_tkt, 0, sizeof(evidence_tkt)); local_realm = krb5_principal_get_comp_string(r->context, r->krbtgt->principal, 1); @@ -382,6 +370,49 @@ validate_constrained_delegation(astgs_request_t r) t = &b->additional_tickets->val[0]; + ret = _krb5_principalname2krb5_principal(r->context, + &s4u_server_name, + t->sname, + t->realm); + if (ret) + goto out; + + ret = krb5_unparse_name(r->context, s4u_server_name, &s4usname); + if (ret) + goto out; + + /* + * Look up the name given in the ticket in the database. We don’t ask for + * canonicalisation, so that we get back the same principal that was + * specified in the ticket. + */ + ret = _kdc_db_fetch(r->context, r->config, s4u_server_name, + HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags, + NULL, &s4u_serverdb, &s4u_server); + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + if (ret) { + kdc_audit_addreason((kdc_request_t)r, + "Constrained delegation service principal unknown"); + goto out; + } + + /* + * Check that the delegating server (r->client) is the same one as specified + * in the ticket. This is to make sure that the server hasn’t forged the + * sname, which is in the unencrypted part of the ticket. + */ + ret = _kdc_check_client_matches_target_service(r->context, + r->config, + s4u_serverdb, + s4u_server, + r->client, + r->client_princ); + if (ret == KRB5KRB_AP_ERR_BADMATCH) + ret = KRB5KDC_ERR_BADOPTION; + if (ret) + goto out; + ret = hdb_enctype2key(r->context, r->client, hdb_kvno2keys(r->context, r->client, t->enc_part.kvno ? * t->enc_part.kvno : 0), @@ -397,7 +428,7 @@ validate_constrained_delegation(astgs_request_t r) "Failed to decrypt constrained delegation ticket"); kdc_log(r->context, r->config, 4, "failed to decrypt ticket for " - "constrained delegation from %s to %s ", r->cname, r->sname); + "constrained delegation from %s to %s", r->cname, r->sname); goto out; } @@ -414,17 +445,6 @@ validate_constrained_delegation(astgs_request_t r) kdc_audit_addkv((kdc_request_t)r, 0, "impersonatee", "%s", s4ucname); - ret = _krb5_principalname2krb5_principal(r->context, - &s4u_server_name, - t->sname, - t->realm); - if (ret) - goto out; - - ret = krb5_unparse_name(r->context, s4u_server_name, &s4usname); - if (ret) - goto out; - /* check that ticket is valid */ if (evidence_tkt.flags.forwardable == 0) { kdc_audit_addreason((kdc_request_t)r, @@ -472,7 +492,7 @@ validate_constrained_delegation(astgs_request_t r) * TODO: pass in t->sname and t->realm and build * a S4U_DELEGATION_INFO blob to the PAC. */ - ret = _kdc_check_pac(r, s4u_client_name, s4u_server_name, + ret = _kdc_check_pac(r, s4u_client_name, s4u_server, s4u_client, r->server, r->krbtgt, r->client, &clientkey->key, &r->ticket_key->key, &evidence_tkt, &ad_kdc_issued, &s4u_pac, @@ -482,7 +502,7 @@ validate_constrained_delegation(astgs_request_t r) kdc_audit_addreason((kdc_request_t)r, "Constrained delegation ticket PAC check failed"); kdc_log(r->context, r->config, 4, - "Verify delegated PAC failed to %s for client" + "Verify delegated PAC failed to %s for client " "%s (%s) as %s from %s with %s", r->sname, r->cname, s4usname, s4ucname, r->from, msg); krb5_free_error_message(r->context, msg); @@ -503,7 +523,7 @@ validate_constrained_delegation(astgs_request_t r) heim_assert(s4u_pac != NULL, "ad_kdc_issued implies the PAC is non-NULL"); - ret = _kdc_pac_update(r, s4u_client_name, s4u_server_name, + ret = _kdc_pac_update(r, s4u_client_name, s4u_server, r->pac, s4u_client, r->server, r->krbtgt, &s4u_pac); if (ret == KRB5_PLUGIN_NO_HANDLE) { @@ -514,7 +534,7 @@ validate_constrained_delegation(astgs_request_t r) kdc_audit_addreason((kdc_request_t)r, "Constrained delegation ticket PAC update failed"); kdc_log(r->context, r->config, 4, - "Update delegated PAC failed to %s for client" + "Update delegated PAC failed to %s for client " "%s (%s) as %s from %s with %s", r->sname, r->cname, s4usname, s4ucname, r->from, msg); krb5_free_error_message(r->context, msg); @@ -569,6 +589,8 @@ validate_constrained_delegation(astgs_request_t r) out: if (s4u_client) _kdc_free_ent(r->context, s4u_clientdb, s4u_client); + if (s4u_server) + _kdc_free_ent(r->context, s4u_serverdb, s4u_server); krb5_free_principal(r->context, s4u_client_name); krb5_xfree(s4ucname); krb5_free_principal(r->context, s4u_server_name); @@ -580,19 +602,3 @@ out: return ret; } - -/* - * - */ - -krb5_error_code -_kdc_validate_services_for_user(astgs_request_t r) -{ - krb5_error_code ret; - - ret = validate_protocol_transition(r); - if (ret == 0) - ret = validate_constrained_delegation(r); - - return ret; -} diff --git a/third_party/heimdal/kdc/pkinit.c b/third_party/heimdal/kdc/pkinit.c index f01178983f3..d06fc32cfbd 100644 --- a/third_party/heimdal/kdc/pkinit.c +++ b/third_party/heimdal/kdc/pkinit.c @@ -1988,7 +1988,7 @@ krb5_kdc_pk_initialize(krb5_context context, ret = hx509_cert_get_subject(cert, &name); if (ret == 0) { hx509_name_to_string(name, &str); - krb5_warnx(context, "WARNING Found KDC certificate (%s)" + krb5_warnx(context, "WARNING Found KDC certificate (%s) " "is missing the PKINIT KDC EKU, this is bad for " "interoperability.", str); hx509_name_free(&name); diff --git a/third_party/heimdal/kdc/version-script.map b/third_party/heimdal/kdc/version-script.map index 3028789cb60..415526c007c 100644 --- a/third_party/heimdal/kdc/version-script.map +++ b/third_party/heimdal/kdc/version-script.map @@ -29,6 +29,10 @@ HEIMDAL_KDC_1.0 { kdc_request_add_pac_buffer; kdc_request_add_reply_padata; kdc_request_get_addr; + kdc_request_get_armor_client; + kdc_request_get_armor_clientdb; + kdc_request_get_armor_pac; + kdc_request_get_armor_server; kdc_request_get_canon_client_princ; kdc_request_get_client; kdc_request_get_clientdb; @@ -40,6 +44,8 @@ HEIMDAL_KDC_1.0 { kdc_request_get_explicit_armor_pac; kdc_request_get_explicit_armor_clientdb; kdc_request_get_explicit_armor_client; + kdc_request_get_explicit_armor_present; + kdc_request_get_explicit_armor_server; kdc_request_get_from; kdc_request_get_krbtgt; kdc_request_get_krbtgtdb; diff --git a/third_party/heimdal/lib/base/dict.c b/third_party/heimdal/lib/base/dict.c index 86be109ffc5..de924f48036 100644 --- a/third_party/heimdal/lib/base/dict.c +++ b/third_party/heimdal/lib/base/dict.c @@ -52,8 +52,10 @@ dict_dealloc(void *ptr) { heim_dict_t dict = ptr; struct hashentry **h, *g, *i; + size_t j; - for (h = dict->tab; h < &dict->tab[dict->size]; ++h) { + for (j = 0; j < dict->size; ++j) { + h = &dict->tab[j]; for (g = h[0]; g; g = i) { i = g->next; heim_release(g->key); diff --git a/third_party/heimdal/lib/krb5/changepw.c b/third_party/heimdal/lib/krb5/changepw.c index 1982925bf06..4336cddc37c 100644 --- a/third_party/heimdal/lib/krb5/changepw.c +++ b/third_party/heimdal/lib/krb5/changepw.c @@ -695,7 +695,7 @@ krb5_change_password (krb5_context context, int *result_code, krb5_data *result_code_string, krb5_data *result_string) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_set_password instead") { struct kpwd_proc *p = find_chpw_proto("change password"); diff --git a/third_party/heimdal/lib/krb5/crypto.c b/third_party/heimdal/lib/krb5/crypto.c index 699d227d696..ce1faad72d6 100644 --- a/third_party/heimdal/lib/krb5/crypto.c +++ b/third_party/heimdal/lib/krb5/crypto.c @@ -612,7 +612,7 @@ verify_checksum_iov(krb5_context context, return ret; } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) { krb5_clear_error_message (context); - krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY, + krb5_set_error_message(context, KRB5KRB_AP_ERR_INAPP_CKSUM, N_("Unkeyed checksum type %s provided where keyed " "checksum was expected", ""), ct->name); diff --git a/third_party/heimdal/lib/krb5/deprecated.c b/third_party/heimdal/lib/krb5/deprecated.c index 0efa162702c..172f089175c 100644 --- a/third_party/heimdal/lib/krb5/deprecated.c +++ b/third_party/heimdal/lib/krb5/deprecated.c @@ -57,7 +57,7 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_free_data_contents(krb5_context context, krb5_data *data) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_data_free instead") { krb5_data_free(data); } @@ -120,7 +120,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_keytype_to_string(krb5_context context, krb5_keytype keytype, char **string) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_enctype_to_string instead") { const char *name = NULL; int i; @@ -154,7 +154,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_string_to_keytype(krb5_context context, const char *string, krb5_keytype *keytype) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_string_to_enctype instead") { char *end; int i; @@ -386,7 +386,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_cc_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_cc_new_unique instead") { return krb5_cc_new_unique(context, ops->prefix, NULL, id); } @@ -400,7 +400,7 @@ krb5_cc_gen_new(krb5_context context, KRB5_LIB_FUNCTION krb5_realm * KRB5_LIB_CALL krb5_princ_realm(krb5_context context, krb5_principal principal) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_principal_get_realm instead") { return &principal->realm; } @@ -416,7 +416,7 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_princ_set_realm(krb5_context context, krb5_principal principal, krb5_realm *realm) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_principal_set_realm instead") { principal->realm = *realm; } @@ -430,7 +430,7 @@ krb5_princ_set_realm(krb5_context context, /* keep this for compatibility with older code */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_free_creds_contents (krb5_context context, krb5_creds *c) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_free_cred_contents instead") { return krb5_free_cred_contents (context, c); } @@ -448,7 +448,7 @@ krb5_free_creds_contents (krb5_context context, krb5_creds *c) KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_free_error_string(krb5_context context, char *str) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_free_error_message instead") { krb5_free_error_message(context, str); } @@ -456,7 +456,7 @@ krb5_free_error_string(krb5_context context, char *str) /** * Set the error message returned by krb5_get_error_string(). * - * Deprecated: use krb5_get_error_message() + * Deprecated: use krb5_set_error_message() * * @param context Kerberos context * @param fmt error message to free @@ -469,7 +469,7 @@ krb5_free_error_string(krb5_context context, char *str) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_set_error_string(krb5_context context, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_set_error_message instead") { va_list ap; @@ -480,8 +480,7 @@ krb5_set_error_string(krb5_context context, const char *fmt, ...) } /** - * Set the error message returned by krb5_get_error_string(), - * deprecated, use krb5_set_error_message(). + * Set the error message returned by krb5_get_error_string(). * * Deprecated: use krb5_vset_error_message() * @@ -497,7 +496,7 @@ krb5_set_error_string(krb5_context context, const char *fmt, ...) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) __attribute__ ((__format__ (__printf__, 2, 0))) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_vset_error_message instead") { krb5_vset_error_message(context, 0, fmt, args); return 0; @@ -515,7 +514,7 @@ krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_clear_error_string(krb5_context context) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_clear_error_message instead") { krb5_clear_error_message(context); } @@ -533,7 +532,7 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_creds **out_creds, krb5_creds ***ret_tgts, krb5_flags flags) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_get_credentials_with_flags instead") { krb5_kdc_flags f; f.i = flags; @@ -554,7 +553,7 @@ krb5_get_cred_from_kdc(krb5_context context, krb5_creds *in_creds, krb5_creds **out_creds, krb5_creds ***ret_tgts) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_get_credentials_with_flags instead") { return krb5_get_cred_from_kdc_opt(context, ccache, in_creds, out_creds, ret_tgts, 0); @@ -568,7 +567,7 @@ krb5_get_cred_from_kdc(krb5_context context, KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_free_unparsed_name(krb5_context context, char *str) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_xfree instead") { krb5_xfree(str); } @@ -583,7 +582,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblock **subkey) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_generate_subkey_extended instead") { return krb5_generate_subkey_extended(context, key, ETYPE_NULL, subkey); } @@ -598,7 +597,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_auth_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, int32_t *seqnumber) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_auth_con_getremoteseqnumber instead") { *seqnumber = auth_context->remote_seqnumber; return 0; diff --git a/third_party/heimdal/lib/krb5/init_creds.c b/third_party/heimdal/lib/krb5/init_creds.c index b34e3eb325c..b2d0d39a3dc 100644 --- a/third_party/heimdal/lib/krb5/init_creds.c +++ b/third_party/heimdal/lib/krb5/init_creds.c @@ -408,7 +408,7 @@ krb5_get_init_creds_opt_set_process_last_req(krb5_context context, KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) - KRB5_DEPRECATED_FUNCTION("Use X instead") + KRB5_DEPRECATED_FUNCTION("Use krb5_get_init_creds_opt_alloc instead") { memset (opt, 0, sizeof(*opt)); }