From: Stefan Metzmacher Date: Fri, 21 Mar 2025 12:23:41 +0000 (+0100) Subject: third_party/heimdal: Import lorikeet-heimdal-202503211313 (commit f5c091eff46b975ede0... X-Git-Tag: tevent-0.17.0~400 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b0b52399c3ec93f45ea82ac2923a1c581407ea2;p=thirdparty%2Fsamba.git third_party/heimdal: Import lorikeet-heimdal-202503211313 (commit f5c091eff46b975ede09860066239aee5f563bdf) This is a rebase on Heimdal master as well as some patches to prepare sid-filtering support in Samba. NOTE: THIS COMMIT WON’T COMPILE/WORK ON ITS OWN! Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/third_party/heimdal/.gitignore b/third_party/heimdal/.gitignore index e5b52468af5..6a56c208980 100644 --- a/third_party/heimdal/.gitignore +++ b/third_party/heimdal/.gitignore @@ -44,11 +44,14 @@ asn1_*_asn1.c /aclocal.m4 /autom4te.cache /compile +/confdefs.h /config.guess /config.log /config.status /config.sub /configure +/conftest.c +/conftest.err /depcomp /install-sh /libtool @@ -58,6 +61,7 @@ asn1_*_asn1.c /stage1.diff /stage2.diff /test-driver +/tmp.h /ylwrap /lib/libedit/aclocal.m4 diff --git a/third_party/heimdal/appl/test/auditdns.c b/third_party/heimdal/appl/test/auditdns.c index 4f5b1dde5d6..3a79af45e61 100644 --- a/third_party/heimdal/appl/test/auditdns.c +++ b/third_party/heimdal/appl/test/auditdns.c @@ -40,6 +40,10 @@ #include "resolve.h" #include "roken.h" +#if (__STDC_VERSION__ - 0) < 199901L +# define restrict /* empty */ +#endif + struct rk_dns_reply * rk_dns_lookup(const char *domain, const char *type_name) { diff --git a/third_party/heimdal/cf/find-func-no-libs2.m4 b/third_party/heimdal/cf/find-func-no-libs2.m4 index 5e5ed0e69ba..a6b3ad6d347 100644 --- a/third_party/heimdal/cf/find-func-no-libs2.m4 +++ b/third_party/heimdal/cf/find-func-no-libs2.m4 @@ -21,7 +21,7 @@ if eval "test \"\$ac_cv_func_$1\" != yes" ; then *) ac_lib="-l$ac_lib" ;; esac LIBS="$6 $ac_lib $5 $ac_save_LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM([[$3]],[[$1($4)]])],[eval "if test -n \"$ac_lib\";then ac_cv_funclib_$1=$ac_lib; else ac_cv_funclib_$1=yes; fi";break]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[char $1 (void);]],[[$1()]])],[eval "if test -n \"$ac_lib\";then ac_cv_funclib_$1=$ac_lib; else ac_cv_funclib_$1=yes; fi";break]) done eval "ac_cv_funclib_$1=\${ac_cv_funclib_$1-no}" LIBS="$ac_save_LIBS" diff --git a/third_party/heimdal/cf/have-struct-field.m4 b/third_party/heimdal/cf/have-struct-field.m4 index bb7bcefbcc6..3962d850645 100644 --- a/third_party/heimdal/cf/have-struct-field.m4 +++ b/third_party/heimdal/cf/have-struct-field.m4 @@ -7,7 +7,8 @@ dnl AC_HAVE_STRUCT_FIELD(struct, field, headers) AC_DEFUN([AC_HAVE_STRUCT_FIELD], [ define(cache_val, translit(ac_cv_type_$1_$2, [A-Z ], [a-z_])) AC_CACHE_CHECK([for $2 in $1], cache_val,[ -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$3]], +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +$3]], [[$1 x; memset(&x, 0, sizeof(x)); x.$2]])], [cache_val=yes], [cache_val=no]) diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c index d6b6ab2bbb3..235cdc5e3f0 100644 --- a/third_party/heimdal/kdc/fast.c +++ b/third_party/heimdal/kdc/fast.c @@ -953,6 +953,11 @@ _kdc_fast_check_armor_pac(astgs_request_t r, int flags) if (r->req.req_body.kdc_options.canonicalize) flags |= HDB_F_CANON; + if (krb5_principal_is_krbtgt(r->context, r->armor_server->principal) && + !krb5_principal_is_root_krbtgt(r->context, r->armor_server->principal)) { + flags |= HDB_F_CROSS_REALM_PRINCIPAL; + } + ret = _krb5_principalname2krb5_principal(r->context, &armor_client_principal, r->armor_ticket->ticket.cname, @@ -996,6 +1001,9 @@ _kdc_fast_check_armor_pac(astgs_request_t r, int flags) r->armor_clientdb = armor_db; armor_db = NULL; + r->armor_client_principal = armor_client_principal; + armor_client_principal = NULL; + r->armor_client = armor_client; armor_client = NULL; diff --git a/third_party/heimdal/kdc/kdc-accessors.h b/third_party/heimdal/kdc/kdc-accessors.h index 8d1305a139e..76415f65e20 100644 --- a/third_party/heimdal/kdc/kdc-accessors.h +++ b/third_party/heimdal/kdc/kdc-accessors.h @@ -359,6 +359,9 @@ 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 Principal * KDC_LIB_CALL +kdc_request_get_explicit_armor_client_principal(astgs_request_t); + KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL kdc_request_get_explicit_armor_server(astgs_request_t); @@ -378,6 +381,13 @@ ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, armor_clientdb) */ ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, armor_client); +/* + * const Principal * + * kdc_request_get_armor_client_principal(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, armor_client_principal) + /* * const hdb_entry * * kdc_request_get_armor_server(astgs_request_t); diff --git a/third_party/heimdal/kdc/kdc-plugin.c b/third_party/heimdal/kdc/kdc-plugin.c index bf41099d9b0..e358626c6ca 100644 --- a/third_party/heimdal/kdc/kdc-plugin.c +++ b/third_party/heimdal/kdc/kdc-plugin.c @@ -767,6 +767,12 @@ kdc_request_get_explicit_armor_client(astgs_request_t r) return r->explicit_armor_present ? r->armor_client : NULL; } +KDC_LIB_FUNCTION const Principal * KDC_LIB_CALL +kdc_request_get_explicit_armor_client_principal(astgs_request_t r) +{ + return r->explicit_armor_present ? r->armor_client_principal : NULL; +} + KDC_LIB_FUNCTION const hdb_entry * KDC_LIB_CALL kdc_request_get_explicit_armor_server(astgs_request_t r) { diff --git a/third_party/heimdal/kdc/kdc.h b/third_party/heimdal/kdc/kdc.h index 057d29a02a1..857e3251959 100644 --- a/third_party/heimdal/kdc/kdc.h +++ b/third_party/heimdal/kdc/kdc.h @@ -49,7 +49,8 @@ enum krb5_kdc_trpolicy { TRPOLICY_ALWAYS_CHECK, TRPOLICY_ALLOW_PER_PRINCIPAL, - TRPOLICY_ALWAYS_HONOUR_REQUEST + TRPOLICY_ALWAYS_HONOUR_REQUEST, + TRPOLICY_NEVER_CHECK, }; struct krb5_kdc_configuration; @@ -114,7 +115,8 @@ struct krb5_kdc_service { unsigned int require_pac : 1; \ unsigned int enable_fast : 1; \ unsigned int enable_fast_cookie : 1; \ - unsigned int enable_armored_pa_enc_timestamp : 1 + unsigned int enable_armored_pa_enc_timestamp : 1; \ + enum krb5_kdc_trpolicy trpolicy #ifndef __KDC_LOCL_H__ struct krb5_kdc_configuration { diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h index d56d6b557b9..7db8f0117ab 100644 --- a/third_party/heimdal/kdc/kdc_locl.h +++ b/third_party/heimdal/kdc/kdc_locl.h @@ -84,7 +84,6 @@ struct krb5_kdc_configuration { unsigned int allow_anonymous : 1; unsigned int historical_anon_realm : 1; unsigned int strict_nametypes : 1; - enum krb5_kdc_trpolicy trpolicy; unsigned int disable_pac : 1; unsigned int enable_unarmored_pa_enc_timestamp : 1; @@ -179,6 +178,7 @@ struct astgs_request_desc { krb5_ticket *armor_ticket; Key *armor_key; + krb5_principal armor_client_principal; hdb_entry *armor_client; HDB *armor_clientdb; krb5_pac armor_pac; diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c index 3bcf00c984b..4c0362c8fd5 100644 --- a/third_party/heimdal/kdc/kerberos5.c +++ b/third_party/heimdal/kdc/kerberos5.c @@ -1384,8 +1384,8 @@ struct kdc_patypes { #define PA_SYNTHETIC_OK 4 #define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */ #define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */ -#define PA_USES_FAST_COOKIE 32 /* Multi-step PA mech maintains state in PA-FX-COOKIE */ -#define PA_HARDWARE_AUTH 64 /* PA mech uses hardware authentication */ +#define PA_HARDWARE_AUTH 32 /* PA mech uses hardware authentication */ +#define PA_USES_FAST_COOKIE 64 /* Multi-step PA mech maintains state in PA-FX-COOKIE */ krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa); krb5_error_code (*finalize_pac)(astgs_request_t r); void (*cleanup)(astgs_request_t r); @@ -1584,7 +1584,7 @@ _kdc_encode_reply(krb5_context context, * Hide client name for privacy reasons */ if (r->fast.flags.requested_hidden_names) { - Realm anon_realm = KRB5_ANON_REALM; + const Realm anon_realm = KRB5_ANON_REALM; free_Realm(&rep->crealm); ret = copy_Realm(&anon_realm, &rep->crealm); @@ -2849,7 +2849,7 @@ _kdc_as_rep(astgs_request_t r) if (!config->historical_anon_realm && _kdc_is_anonymous(r->context, r->client_princ)) { - Realm anon_realm = KRB5_ANON_REALM; + const Realm anon_realm = KRB5_ANON_REALM; ret = copy_Realm(&anon_realm, &rep->crealm); } else if (f.canonicalize || r->client->flags.force_canonicalize) ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm); @@ -3248,6 +3248,16 @@ 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->armor_client_principal) { + krb5_free_principal(r->context, r->armor_client_principal); + r->armor_client_principal = NULL; + } + if (r->armor_client) + _kdc_free_ent(r->context, + 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->session_key); diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c index d744f5610f3..f8fe63d88d7 100644 --- a/third_party/heimdal/kdc/krb5tgs.c +++ b/third_party/heimdal/kdc/krb5tgs.c @@ -550,6 +550,7 @@ tgs_make_reply(astgs_request_t r, KDCOptions f = b->kdc_options; krb5_error_code ret; int is_weak = 0; + krb5_boolean check_policy = FALSE; heim_assert(r->client_princ != NULL, "invalid client name passed to tgs_make_reply"); @@ -581,18 +582,30 @@ tgs_make_reply(astgs_request_t r, (r->config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL) #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \ (r->config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST) +#define GLOBAL_DISABLE_TRANSITED_CHECK \ + (r->config->trpolicy == TRPOLICY_NEVER_CHECK) /* these will consult the database in future release */ #define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 + if (GLOBAL_DISABLE_TRANSITED_CHECK) { + check_policy = FALSE; + } else if (!f.disable_transited_check) { + check_policy = TRUE; + } else if (GLOBAL_FORCE_TRANSITED_CHECK) { + check_policy = TRUE; + } else if (PRINCIPAL_FORCE_TRANSITED_CHECK(r->server)) { + check_policy = TRUE; + } else if (!((GLOBAL_ALLOW_PER_PRINCIPAL && + PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(r->server)) || + GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK)) + { + check_policy = TRUE; + } + ret = fix_transited_encoding(r->context, r->config, - !f.disable_transited_check || - GLOBAL_FORCE_TRANSITED_CHECK || - PRINCIPAL_FORCE_TRANSITED_CHECK(r->server) || - !((GLOBAL_ALLOW_PER_PRINCIPAL && - PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(r->server)) || - GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), + check_policy, &tgt->transited, et, krb5_principal_get_realm(r->context, r->client_princ), krb5_principal_get_realm(r->context, r->server->principal), @@ -688,6 +701,10 @@ tgs_make_reply(astgs_request_t r, et->flags.hw_authent = tgt->flags.hw_authent; et->flags.ok_as_delegate = r->server->flags.ok_as_delegate; + /* See MS-KILE 3.3.5.7.5 Cross-Domain Trust and Referrals */ + if (!r->krbtgt->flags.ok_as_delegate) + et->flags.ok_as_delegate = 0; + /* See MS-KILE 3.3.5.1 */ if (!r->server->flags.forwardable) et->flags.forwardable = 0; @@ -1307,6 +1324,9 @@ _kdc_db_fetch_client(krb5_context context, * This is OK, we are just trying to find out if they have * been disabled or deleted in the meantime; missing secrets * are OK. + * + * If HDB_F_CROSS_REALM_PRINCIPAL was passed this + * indicates the client is remote. */ } else if (ret) { /* @@ -1717,7 +1737,7 @@ server_lookup: * proper checks. */ ret = _kdc_db_fetch(context, config, user2user_princ, - HDB_F_GET_CLIENT | flags, + HDB_F_GET_CLIENT | HDB_F_USER2USER_PRINCIPAL | flags, NULL, &user2user_db, &user2user_client); if (ret == HDB_ERR_NOENTRY) ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; @@ -1877,6 +1897,9 @@ server_lookup: if (_kdc_synthetic_princ_used_p(context, priv->ticket)) flags |= HDB_F_SYNTHETIC_OK; + if (!krb5_principal_compare(context, priv->krbtgt->principal, krbtgt_out->principal)) + flags |= HDB_F_CROSS_REALM_PRINCIPAL; + ret = _kdc_db_fetch_client(context, config, flags, priv->client_princ, cpn, our_realm, &clientdb, &priv->client); if (ret) @@ -2293,6 +2316,10 @@ 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->armor_client_principal) { + krb5_free_principal(r->context, r->armor_client_principal); + r->armor_client_principal = NULL; + } if (r->armor_client) _kdc_free_ent(r->context, r->armor_clientdb, diff --git a/third_party/heimdal/kdc/libkdc-exports.def b/third_party/heimdal/kdc/libkdc-exports.def index 1c6997a23c2..0499b1f0c9d 100644 --- a/third_party/heimdal/kdc/libkdc-exports.def +++ b/third_party/heimdal/kdc/libkdc-exports.def @@ -28,6 +28,7 @@ EXPORTS kdc_request_get_addr kdc_request_get_armor_client kdc_request_get_armor_clientdb + kdc_request_get_armor_client_principal kdc_request_get_armor_pac kdc_request_get_armor_server kdc_request_get_canon_client_princ @@ -41,6 +42,7 @@ EXPORTS kdc_request_get_explicit_armor_pac kdc_request_get_explicit_armor_clientdb kdc_request_get_explicit_armor_client + kdc_request_get_explicit_armor_client_principal kdc_request_get_explicit_armor_present kdc_request_get_explicit_armor_server kdc_request_get_from diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c index 554e2f2112a..92ec65e15ae 100644 --- a/third_party/heimdal/kdc/mssfu.c +++ b/third_party/heimdal/kdc/mssfu.c @@ -107,8 +107,10 @@ check_rbcd(krb5_context context, HDB *clientdb, krb5_const_principal s4u_principal, const hdb_entry *client_krbtgt, + krb5_const_principal client_principal, const hdb_entry *client, const hdb_entry *device_krbtgt, + krb5_const_principal device_principal, const hdb_entry *device, krb5_const_pac client_pac, krb5_const_pac device_pac, @@ -120,8 +122,10 @@ check_rbcd(krb5_context context, ret = clientdb->hdb_check_rbcd(context, clientdb, client_krbtgt, + client_principal, client, device_krbtgt, + device_principal, device, s4u_principal, client_pac, @@ -150,7 +154,7 @@ _kdc_validate_protocol_transition(astgs_request_t r, const PA_DATA *for_user) EncTicketPart *ticket = &r->ticket->ticket; hdb_entry *s4u_client = NULL; HDB *s4u_clientdb; - int flags = HDB_F_FOR_TGS_REQ; + int flags = HDB_F_FOR_TGS_REQ | HDB_F_S4U2SELF_PRINCIPAL; krb5_principal s4u_client_name = NULL, s4u_canon_client_name = NULL; krb5_pac s4u_pac = NULL; char *s4ucname = NULL; @@ -375,7 +379,7 @@ _kdc_validate_constrained_delegation(astgs_request_t r) { krb5_error_code ret; KDC_REQ_BODY *b = &r->req.req_body; - int flags = HDB_F_FOR_TGS_REQ; + int flags = HDB_F_FOR_TGS_REQ | HDB_F_S4U2PROXY_PRINCIPAL; krb5_principal s4u_client_name = NULL, s4u_server_name = NULL; krb5_principal s4u_canon_client_name = NULL; krb5_pac s4u_pac = NULL; @@ -542,9 +546,14 @@ _kdc_validate_constrained_delegation(astgs_request_t r) if (rbcd_support) { ret = check_rbcd(r->context, r->config, r->clientdb, s4u_client_name, - r->krbtgt, r->client, - r->armor_server, r->armor_client, - r->pac, r->armor_pac, + r->krbtgt, + r->client_princ, + r->client, + r->armor_server, + r->armor_client_principal, + r->armor_client, + r->pac, + r->armor_pac, r->server); } else { ret = KRB5KDC_ERR_BADOPTION; @@ -577,6 +586,10 @@ _kdc_validate_constrained_delegation(astgs_request_t r) goto out; } + /* s4u_client_name can be remote */ + if (!krb5_realm_compare(r->context, s4u_client_name, s4u_server_name)) + flags |= HDB_F_CROSS_REALM_PRINCIPAL; + /* Try lookup the delegated client in DB */ ret = _kdc_db_fetch_client(r->context, r->config, flags, s4u_client_name, s4ucname, local_realm, diff --git a/third_party/heimdal/kdc/version-script.map b/third_party/heimdal/kdc/version-script.map index 508357d0a7d..808f9f74314 100644 --- a/third_party/heimdal/kdc/version-script.map +++ b/third_party/heimdal/kdc/version-script.map @@ -31,6 +31,7 @@ HEIMDAL_KDC_1.0 { kdc_request_get_addr; kdc_request_get_armor_client; kdc_request_get_armor_clientdb; + kdc_request_get_armor_client_principal; kdc_request_get_armor_pac; kdc_request_get_armor_server; kdc_request_get_canon_client_princ; @@ -44,6 +45,7 @@ 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_client_principal; kdc_request_get_explicit_armor_present; kdc_request_get_explicit_armor_server; kdc_request_get_from; diff --git a/third_party/heimdal/lib/gssapi/krb5/arcfour.c b/third_party/heimdal/lib/gssapi/krb5/arcfour.c index 787a8d3d2d6..02780b62189 100644 --- a/third_party/heimdal/lib/gssapi/krb5/arcfour.c +++ b/third_party/heimdal/lib/gssapi/krb5/arcfour.c @@ -740,15 +740,15 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, return GSS_S_BAD_MIC; } + if (conf_state) + *conf_state = conf_flag; + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); omret = _gssapi_msg_order_check(context_handle->order, seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (omret) return omret; - if (conf_state) - *conf_state = conf_flag; - *minor_status = 0; return GSS_S_COMPLETE; } @@ -1375,6 +1375,10 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, } } + if (pconf_state) { + *pconf_state = conf_state; + } + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); ret = _gssapi_msg_order_check(ctx->order, seq_number); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); @@ -1382,10 +1386,6 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, return ret; } - if (pconf_state) { - *pconf_state = conf_state; - } - *minor_status = 0; return GSS_S_COMPLETE; } diff --git a/third_party/heimdal/lib/gssapi/krb5/cfx.c b/third_party/heimdal/lib/gssapi/krb5/cfx.c index cb9ea773bbb..af50292c286 100644 --- a/third_party/heimdal/lib/gssapi/krb5/cfx.c +++ b/third_party/heimdal/lib/gssapi/krb5/cfx.c @@ -748,7 +748,7 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, gss_iov_buffer_desc *header, *trailer, *padding; gss_cfx_wrap_token token, ttoken; u_char token_flags; - krb5_error_code ret; + krb5_error_code ret, seq_err; unsigned usage; uint16_t ec, rrc; krb5_crypto_iov *data = NULL; @@ -818,17 +818,16 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, if (seq_number_hi) { /* no support for 64-bit sequence numbers */ *minor_status = ERANGE; - return GSS_S_UNSEQ_TOKEN; + return GSS_S_FAILURE | GSS_S_UNSEQ_TOKEN; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); - if (ret != 0) { - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - return ret; - } + seq_err = _gssapi_msg_order_check(ctx->order, seq_number_lo); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (seq_err == GSS_S_FAILURE) { + *minor_status = 0; + return seq_err; + } /* * Decrypt and/or verify checksum @@ -1025,7 +1024,7 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, free(data); *minor_status = 0; - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; failure: if (data) @@ -1401,7 +1400,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, { gss_cfx_wrap_token token; u_char token_flags; - krb5_error_code ret; + krb5_error_code ret, seq_err; unsigned usage; krb5_data data; uint16_t ec, rrc; @@ -1459,18 +1458,16 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, if (seq_number_hi) { /* no support for 64-bit sequence numbers */ *minor_status = ERANGE; - return GSS_S_UNSEQ_TOKEN; + return GSS_S_FAILURE | GSS_S_UNSEQ_TOKEN; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); - if (ret != 0) { - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - _gsskrb5_release_buffer(minor_status, output_message_buffer); - return ret; - } + seq_err = _gssapi_msg_order_check(ctx->order, seq_number_lo); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (seq_err == GSS_S_FAILURE) { + *minor_status = 0; + return seq_err; + } /* * Decrypt and/or verify checksum @@ -1594,7 +1591,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, } *minor_status = 0; - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; } OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, @@ -1690,7 +1687,7 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, { gss_cfx_mic_token token; u_char token_flags; - krb5_error_code ret; + krb5_error_code ret, seq_err; unsigned usage; OM_uint32 seq_number_lo, seq_number_hi; u_char *buf, *p; @@ -1736,17 +1733,16 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, _gss_mg_decode_be_uint32(&token->SND_SEQ[4], &seq_number_lo); if (seq_number_hi) { *minor_status = ERANGE; - return GSS_S_UNSEQ_TOKEN; + return GSS_S_UNSEQ_TOKEN | GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); - if (ret != 0) { - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - return ret; - } + seq_err = _gssapi_msg_order_check(ctx->order, seq_number_lo); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + if (seq_err == GSS_S_FAILURE) { + *minor_status = 0; + return seq_err; + } /* * Verify checksum @@ -1793,5 +1789,5 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, *qop_state = GSS_C_QOP_DEFAULT; } - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; } diff --git a/third_party/heimdal/lib/gssapi/krb5/sequence.c b/third_party/heimdal/lib/gssapi/krb5/sequence.c index 2e0e7b20f92..56ce447f537 100644 --- a/third_party/heimdal/lib/gssapi/krb5/sequence.c +++ b/third_party/heimdal/lib/gssapi/krb5/sequence.c @@ -188,7 +188,7 @@ _gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) for (i = 0; i < o->length - 1; i++) { if (o->elem[i] == seq_num) return GSS_S_DUPLICATE_TOKEN; - if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) { + if (o->elem[i + 1] < seq_num && o->elem[i] > seq_num) { elem_insert(o, i, seq_num); if (r) return GSS_S_COMPLETE; diff --git a/third_party/heimdal/lib/gssapi/krb5/unwrap.c b/third_party/heimdal/lib/gssapi/krb5/unwrap.c index 1eea68eace2..9e45fbd2745 100644 --- a/third_party/heimdal/lib/gssapi/krb5/unwrap.c +++ b/third_party/heimdal/lib/gssapi/krb5/unwrap.c @@ -57,7 +57,7 @@ unwrap_des size_t i; uint32_t seq_number; size_t padlength; - OM_uint32 ret; + OM_uint32 ret, seq_err; int cstate; int cmp; int token_len; @@ -175,10 +175,10 @@ unwrap_des return GSS_S_BAD_MIC; } - ret = _gssapi_msg_order_check(context_handle->order, seq_number); - if (ret) { + seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); + if (seq_err == GSS_S_FAILURE) { HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return ret; + return seq_err; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -194,7 +194,7 @@ unwrap_des memcpy (output_message_buffer->value, p + 24, output_message_buffer->length); - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; } #endif @@ -217,7 +217,7 @@ unwrap_des3 u_char cksum[20]; uint32_t seq_number; size_t padlength; - OM_uint32 ret; + OM_uint32 ret, seq_err; int cstate; krb5_crypto crypto; Checksum csum; @@ -349,11 +349,11 @@ unwrap_des3 return GSS_S_BAD_MIC; } - ret = _gssapi_msg_order_check(context_handle->order, seq_number); - if (ret) { + seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); + if (seq_err == GSS_S_FAILURE) { *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return ret; + return seq_err; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -396,7 +396,7 @@ unwrap_des3 memcpy (output_message_buffer->value, p + 36, output_message_buffer->length); - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; } OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap diff --git a/third_party/heimdal/lib/gssapi/krb5/verify_mic.c b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c index 4a776c8099b..3b97a905994 100644 --- a/third_party/heimdal/lib/gssapi/krb5/verify_mic.c +++ b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c @@ -148,7 +148,7 @@ verify_mic_des3 u_char *p; u_char *seq; uint32_t seq_number; - OM_uint32 ret; + OM_uint32 ret, seq_err; krb5_crypto crypto; krb5_data seq_data; int cmp, docompat; @@ -226,8 +226,8 @@ retry: return GSS_S_BAD_MIC; } - ret = _gssapi_msg_order_check(context_handle->order, seq_number); - if (ret) { + seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); + if (seq_err == GSS_S_FAILURE) { krb5_crypto_destroy (context, crypto); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -269,7 +269,7 @@ retry: HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); krb5_crypto_destroy (context, crypto); - return GSS_S_COMPLETE; + return GSS_S_COMPLETE | seq_err; } OM_uint32 diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c index 0ae3df1bf95..23de0c3c5d1 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c @@ -12,6 +12,10 @@ mp_err mp_2expt(mp_int *a, int b) { mp_err err; + if (b < 0) { + return MP_VAL; + } + /* zero a as per default */ mp_zero(a); diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c index 9e904c547e1..2b168265189 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c @@ -9,6 +9,10 @@ mp_err mp_grow(mp_int *a, int size) int i; mp_digit *tmp; + if (size < 0) { + return MP_VAL; + } + /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* reallocate the array a->dp diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c index d62268721a8..99573833fbc 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c @@ -6,6 +6,11 @@ /* init an mp_init for a given size */ mp_err mp_init_size(mp_int *a, int size) { + + if (size < 0) { + return MP_VAL; + } + size = MP_MAX(MP_MIN_PREC, size); /* alloc mem */ diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c index 87354de2024..bfeaf2eb226 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c @@ -9,6 +9,10 @@ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) mp_digit d; mp_err err; + if (b < 0) { + return MP_VAL; + } + /* copy */ if (a != c) { if ((err = mp_copy(a, c)) != MP_OKAY) { diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c index 64509d4cb93..3682b49800a 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c @@ -16,6 +16,10 @@ mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_word r; mp_digit tmpx, *tmpt, *tmpy; + if (digs < 0) { + return MP_VAL; + } + /* can we use the fast multiplier? */ if ((digs < MP_WARRAY) && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c index b2a287b027b..3c4176a8790 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c @@ -26,6 +26,10 @@ mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_digit W[MP_WARRAY]; mp_word _W; + if (digs < 0) { + return MP_VAL; + } + /* grow the destination as required */ if (c->alloc < digs) { if ((err = mp_grow(c, digs)) != MP_OKAY) { diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c index 2bb2a50985f..c9dd355f83f 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c @@ -15,6 +15,10 @@ mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_word r; mp_digit tmpx, *tmpt, *tmpy; + if (digs < 0) { + return MP_VAL; + } + /* can we use the fast multiplier? */ if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) && ((a->used + b->used + 1) < MP_WARRAY) diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c index a2c4fb6924a..4ce7f590ce8 100644 --- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c +++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c @@ -19,6 +19,10 @@ mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int mp_digit W[MP_WARRAY]; mp_word _W; + if (digs < 0) { + return MP_VAL; + } + /* grow the destination as required */ pa = a->used + b->used; if (c->alloc < pa) { diff --git a/third_party/heimdal/lib/hdb/hdb.h b/third_party/heimdal/lib/hdb/hdb.h index e5d23711a2c..8900df3e09e 100644 --- a/third_party/heimdal/lib/hdb/hdb.h +++ b/third_party/heimdal/lib/hdb/hdb.h @@ -79,6 +79,9 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; #define HDB_F_GET_FAST_COOKIE 0x20000 /* fetch the FX-COOKIE key (not a normal principal) */ #define HDB_F_ARMOR_PRINCIPAL 0x40000 /* fetch is for the client of an armor ticket */ #define HDB_F_USER2USER_PRINCIPAL 0x80000 /* fetch is for the server of a user2user tgs-req */ +#define HDB_F_CROSS_REALM_PRINCIPAL 0x100000 /* fetch is cross-realm ticket */ +#define HDB_F_S4U2SELF_PRINCIPAL 0x200000 /* fetch is for S4U2Self */ +#define HDB_F_S4U2PROXY_PRINCIPAL 0x400000 /* fetch is for S4U2Proxy */ /* hdb_capability_flags */ #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 @@ -290,7 +293,18 @@ typedef struct HDB { /** * Check if resource-based constrained delegation (RBCD) is allowed. */ - krb5_error_code (*hdb_check_rbcd)(krb5_context, struct HDB *, const hdb_entry *, const hdb_entry *, const hdb_entry *, const hdb_entry *, krb5_const_principal, krb5_const_pac, krb5_const_pac, const hdb_entry *); + krb5_error_code (*hdb_check_rbcd)(krb5_context context, + struct HDB *clientdb, + const hdb_entry *client_krbtgt, + krb5_const_principal client_principal, + const hdb_entry *client, + const hdb_entry *device_krbtgt, + krb5_const_principal device_principal, + const hdb_entry *device, + krb5_const_principal s4u_principal, + krb5_const_pac client_pac, + krb5_const_pac device_pac, + const hdb_entry *target); /** * Check if this name is an alias for the supplied client for PKINIT userPrinicpalName logins @@ -311,7 +325,7 @@ typedef struct HDB { krb5_error_code (*hdb_set_sync)(krb5_context, struct HDB *, int); }HDB; -#define HDB_INTERFACE_VERSION 11 +#define HDB_INTERFACE_VERSION 12 struct hdb_method { HEIM_PLUGIN_FTABLE_COMMON_ELEMENTS(krb5_context); diff --git a/third_party/heimdal/lib/krb5/fast.c b/third_party/heimdal/lib/krb5/fast.c index 4026ed62327..858398f29d9 100644 --- a/third_party/heimdal/lib/krb5/fast.c +++ b/third_party/heimdal/lib/krb5/fast.c @@ -271,7 +271,7 @@ make_fast_ap_fxarmor(krb5_context context, if (ret) goto out; - ret = copy_KrbFastArmor(fxarmor, &msg.armor); + ret = copy_KrbFastArmor(&msg.armor, fxarmor); if (ret) { free_KERB_ARMOR_SERVICE_REPLY(&msg); goto out; diff --git a/third_party/heimdal/lib/krb5/fcache.c b/third_party/heimdal/lib/krb5/fcache.c index 9fed685d639..1c32389fac4 100644 --- a/third_party/heimdal/lib/krb5/fcache.c +++ b/third_party/heimdal/lib/krb5/fcache.c @@ -983,6 +983,17 @@ fcc_get_first(krb5_context context, return 0; } +/* + * Return true if cred is a removed entry. We assume that any active entry + * with endtime=0 (such as a config entry or gssproxy encrypted credential) + * will also have authtime=0. + */ +static inline krb5_boolean +cred_removed(krb5_creds *c) +{ + return c->times.endtime == 0 && c->times.authtime != 0; +} + static krb5_error_code KRB5_CALLCONV fcc_get_next (krb5_context context, krb5_ccache id, @@ -997,15 +1008,25 @@ fcc_get_next (krb5_context context, if (FCC_CURSOR(*cursor) == NULL) return krb5_einval(context, 3); - FCC_CURSOR(*cursor)->cred_start = - krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR); + while (1) { + FCC_CURSOR(*cursor)->cred_start = + krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR); - ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds); - if (ret) - krb5_clear_error_message(context); + ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds); - FCC_CURSOR(*cursor)->cred_end = - krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR); + FCC_CURSOR(*cursor)->cred_end = + krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR); + + if (ret) { + krb5_clear_error_message(context); + break; + } + + if (!cred_removed(creds)) + break; + + krb5_free_cred_contents(context, creds); + } return ret; } @@ -1078,6 +1099,9 @@ cred_delete(krb5_context context, */ cred->times.endtime = 0; + /* For compatibility with MIT d3b39a8bac6206b5ea78b0bf6a2958c1df0b0dd5 */ + cred->times.authtime = -1; + /* ...except for config creds because we don't check their endtimes */ if (srealm && strcmp(srealm, "X-CACHECONF:") == 0) { ret = krb5_principal_set_realm(context, cred->server, "X-RMED-CONF:"); diff --git a/third_party/heimdal/lib/krb5/krbhst.c b/third_party/heimdal/lib/krb5/krbhst.c index ac218576a55..12f05394a4b 100644 --- a/third_party/heimdal/lib/krb5/krbhst.c +++ b/third_party/heimdal/lib/krb5/krbhst.c @@ -49,12 +49,22 @@ string_to_proto(const char *string) return -1; } +#define YOUR_DNS_NEEDS_IMM_ATTENTION "your-dns-needs-immediate-attention." static int is_invalid_tld_srv_target(const char *target) { - return (strncmp("your-dns-needs-immediate-attention.", - target, 35) == 0 - && strchr(&target[35], '.') == NULL); + if (strncmp(YOUR_DNS_NEEDS_IMM_ATTENTION, target, + sizeof(YOUR_DNS_NEEDS_IMM_ATTENTION) - 1) != 0) + return 0; + target += sizeof(YOUR_DNS_NEEDS_IMM_ATTENTION) - 1; + if (target[0] == '\0' || target[0] == '.') + return 0; /* malformed; should be followed by a TLD */ + target = strchr(target, '.'); + if (target == NULL) + return 0; /* malformed; should end in a '.' */ + if (target[1] != '\0') + return 0; /* malformed; should be followed by just one label (the TLD) */ + return 1; } /* @@ -138,28 +148,25 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, if(rr->type == rk_ns_t_srv) { krb5_krbhst_info *hi = NULL; size_t len; - int invalid_tld = 1; /* Test for top-level domain controlled interruptions */ - if (!is_invalid_tld_srv_target(rr->u.srv->target)) { - invalid_tld = 0; - len = strlen(rr->u.srv->target); - hi = calloc(1, sizeof(*hi) + len); + if (is_invalid_tld_srv_target(rr->u.srv->target)) { + krb5_warnx(context, + "Domain lookup failed: " + "Realm %s needs immediate attention " + "see https://icann.org/namecollision", + realm); + return KRB5_KDC_UNREACH; } + + len = strlen(rr->u.srv->target); + hi = calloc(1, sizeof(*hi) + len); if(hi == NULL) { rk_dns_free_data(r); while(--num_srv >= 0) free((*res)[num_srv]); free(*res); *res = NULL; - if (invalid_tld) { - krb5_warnx(context, - "Domain lookup failed: " - "Realm %s needs immediate attention " - "see https://icann.org/namecollision", - realm); - return KRB5_KDC_UNREACH; - } return krb5_enomem(context); } (*res)[num_srv++] = hi; diff --git a/third_party/heimdal/lib/krb5/salt-des.c b/third_party/heimdal/lib/krb5/salt-des.c index 474ba5d591d..cb727c15dbe 100644 --- a/third_party/heimdal/lib/krb5/salt-des.c +++ b/third_party/heimdal/lib/krb5/salt-des.c @@ -35,6 +35,10 @@ #ifdef HEIM_WEAK_CRYPTO +#if !defined(HAVE_CRYPT) +# undef ENABLE_AFS_STRING_TO_KEY +#endif + #ifdef ENABLE_AFS_STRING_TO_KEY /* This defines the Andrew string_to_key function. It accepts a password diff --git a/third_party/heimdal/lib/otp/otp_db.c b/third_party/heimdal/lib/otp/otp_db.c index c7b2b763a01..036359c1db1 100644 --- a/third_party/heimdal/lib/otp/otp_db.c +++ b/third_party/heimdal/lib/otp/otp_db.c @@ -38,10 +38,13 @@ RCSID("$Id$"); #include "otp_locl.h" -#if !defined(HAVE_NDBM) && !defined(HAVE_DB_NDBM) -#include "ndbm_wrap.h" +#if defined(HAVE_DB_NDBM) +# include +#elif !defined(HAVE_NDBM) +# include "ndbm_wrap.h" #endif + #define RETRIES 5 void *