From: Stefan Metzmacher Date: Mon, 4 Mar 2024 09:30:55 +0000 (+0100) Subject: third_party/heimdal: import lorikeet-heimdal-202404171655 (commit 28a56d818074e049f03... X-Git-Tag: tdb-1.4.11~978 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b92cbacac11fb64cca2c4770cbdce789525b87a;p=thirdparty%2Fsamba.git third_party/heimdal: import lorikeet-heimdal-202404171655 (commit 28a56d818074e049f0361ef74d7017f2a9391847) BUG: https://bugzilla.samba.org/show_bug.cgi?id=15603 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15621 See also: https://github.com/heimdal/heimdal/pull/1234 https://github.com/heimdal/heimdal/pull/1238 https://github.com/heimdal/heimdal/pull/1240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- diff --git a/third_party/heimdal/lib/gssapi/krb5/8003.c b/third_party/heimdal/lib/gssapi/krb5/8003.c index 0b91cf83b82..74ff349ab7b 100644 --- a/third_party/heimdal/lib/gssapi/krb5/8003.c +++ b/third_party/heimdal/lib/gssapi/krb5/8003.c @@ -87,6 +87,11 @@ _gsskrb5_create_8003_checksum ( { u_char *p; +#define _GSS_C_NON_8003_WIRE_FLAGS \ + GSS_C_CHANNEL_BOUND_FLAG + + flags &= ~_GSS_C_NON_8003_WIRE_FLAGS; + /* * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value * field's format) */ diff --git a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c index 7749fc6cadd..fbf9e5521c2 100644 --- a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -498,6 +498,7 @@ init_auth_restart krb5_data fwd_data, timedata; int32_t offset = 0, oldoffset = 0; uint32_t flagmask; + krb5_boolean channel_bound = FALSE; krb5_data_zero(&outbuf); krb5_data_zero(&fwd_data); @@ -587,6 +588,11 @@ init_auth_restart } flags |= GSS_C_TRANS_FLAG; + if (req_flags & GSS_C_CHANNEL_BOUND_FLAG) { + flags |= GSS_C_CHANNEL_BOUND_FLAG; + channel_bound = TRUE; + } + if (ret_flags) *ret_flags = flags; ctx->flags = flags; @@ -626,6 +632,7 @@ init_auth_restart enctype, ctx->kcred, &cksum, + channel_bound, &authenticator, KRB5_KU_AP_REQ_AUTH); @@ -787,6 +794,9 @@ repl_mutual return GSS_S_FAILURE; } } + if (ret != GSS_S_COMPLETE) { + return ret; + } kret = krb5_rd_rep (context, ctx->auth_context, &indata, diff --git a/third_party/heimdal/lib/gssapi/test_context.c b/third_party/heimdal/lib/gssapi/test_context.c index 907e9c4d208..e6d505033c3 100644 --- a/third_party/heimdal/lib/gssapi/test_context.c +++ b/third_party/heimdal/lib/gssapi/test_context.c @@ -82,6 +82,7 @@ static int token_split = 0; static int version_flag = 0; static int verbose_flag = 0; static int help_flag = 0; +static int i_channel_bound = 0; static char *i_channel_bindings = NULL; static char *a_channel_bindings = NULL; @@ -287,6 +288,8 @@ loop(gss_OID mechoid, flags |= GSS_C_DELEG_FLAG; if (policy_deleg_flag) flags |= GSS_C_DELEG_POLICY_FLAG; + if (i_channel_bound) + flags |= GSS_C_CHANNEL_BOUND_FLAG; input_token.value = rk_UNCONST(target); input_token.length = strlen(target); @@ -904,6 +907,7 @@ static struct getargs args[] = { {"client-name", 0, arg_string, &client_name, "client name", NULL }, {"client-password", 0, arg_string, &client_password, "client password", NULL }, {"anonymous", 0, arg_flag, &anon_flag, "anonymous auth", NULL }, + {"i-channel-bound",0, arg_flag, &i_channel_bound, "initiator channel bound", NULL }, {"i-channel-bindings", 0, arg_string, &i_channel_bindings, "initiator channel binding data", NULL }, {"a-channel-bindings", 0, arg_string, &a_channel_bindings, "acceptor channel binding data", NULL }, {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, diff --git a/third_party/heimdal/lib/krb5/build_auth.c b/third_party/heimdal/lib/krb5/build_auth.c index 3e0012562a3..ae757f7b043 100644 --- a/third_party/heimdal/lib/krb5/build_auth.c +++ b/third_party/heimdal/lib/krb5/build_auth.c @@ -86,6 +86,7 @@ add_etypelist(krb5_context context, static krb5_error_code add_ap_options(krb5_context context, + krb5_boolean channel_bound, krb5_authdata *auth_data) { krb5_error_code ret; @@ -98,6 +99,9 @@ add_ap_options(krb5_context context, "client_aware_channel_bindings", NULL); + if (channel_bound) + require_cb = TRUE; + if (!require_cb) return 0; @@ -115,8 +119,90 @@ add_ap_options(krb5_context context, return ret; } +static krb5_error_code +add_target_principal(krb5_context context, + krb5_const_principal server, + krb5_authdata *auth_data) +{ + krb5_error_code ret; + AuthorizationDataElement ade; + char *s, *s2 = NULL; + size_t s2_len; + + if (server == NULL) { + return 0; + } + + ret = krb5_unparse_name_flags(context, server, + KRB5_PRINCIPAL_UNPARSE_DISPLAY, + &s); + if (ret) + return ret; + + { + size_t ucs2_len; + uint16_t *ucs2; + unsigned int flags; + + ret = wind_utf8ucs2_length(s, &ucs2_len); + if (ret) { + krb5_set_error_message(context, ret, "Principal %s is not valid UTF-8", s); + free(s); + return ret; + } + + ucs2 = malloc(sizeof(ucs2[0]) * ucs2_len); + if (ucs2 == NULL) { + free(s); + return krb5_enomem(context); + } + + ret = wind_utf8ucs2(s, ucs2, &ucs2_len); + if (ret) { + free(ucs2); + krb5_set_error_message(context, ret, "Principal %s is not valid UTF-8", s); + free(s); + return ret; + } else + free(s); + + s2_len = (ucs2_len + 1) * 2; + s2 = malloc(s2_len); + if (s2 == NULL) { + free(ucs2); + return krb5_enomem(context); + } + + flags = WIND_RW_LE; + ret = wind_ucs2write(ucs2, ucs2_len, + &flags, s2, &s2_len); + free(ucs2); + if (ret) { + free(s2); + krb5_set_error_message(context, ret, "Failed to write to UCS-2 buffer"); + return ret; + } + + /* + * we do not want zero termination + */ + s2_len = ucs2_len * 2; + } + + ade.ad_type = KRB5_AUTHDATA_TARGET_PRINCIPAL; + ade.ad_data.length = s2_len; + ade.ad_data.data = s2; + + ret = add_AuthorizationData(auth_data, &ade); + free(s2); + + return ret; +} + static krb5_error_code make_ap_authdata(krb5_context context, + krb5_boolean channel_bound, + krb5_const_principal server, krb5_authdata **auth_data) { krb5_error_code ret; @@ -136,7 +222,13 @@ make_ap_authdata(krb5_context context, * in the AP authenticator when looking for AD-AP-OPTIONS. Make sure to * bundle it together with etypes. */ - ret = add_ap_options(context, &ad); + ret = add_ap_options(context, channel_bound, &ad); + if (ret) { + free_AuthorizationData(&ad); + return ret; + } + + ret = add_target_principal(context, server, &ad); if (ret) { free_AuthorizationData(&ad); return ret; @@ -165,6 +257,7 @@ _krb5_build_authenticator (krb5_context context, krb5_enctype enctype, krb5_creds *cred, Checksum *cksum, + krb5_boolean channel_bound, krb5_data *result, krb5_key_usage usage) { @@ -221,7 +314,10 @@ _krb5_build_authenticator (krb5_context context, * This is not GSS-API specific, we only enable it for * GSS for now */ - ret = make_ap_authdata(context, &auth.authorization_data); + ret = make_ap_authdata(context, + channel_bound, + cred->server, + &auth.authorization_data); if (ret) goto fail; } diff --git a/third_party/heimdal/lib/krb5/mk_req_ext.c b/third_party/heimdal/lib/krb5/mk_req_ext.c index a8a07f1c718..09c116cd97b 100644 --- a/third_party/heimdal/lib/krb5/mk_req_ext.c +++ b/third_party/heimdal/lib/krb5/mk_req_ext.c @@ -117,6 +117,7 @@ _krb5_mk_req_internal(krb5_context context, ac->keyblock->keytype, in_creds, c_opt, + FALSE, /* channel_bound */ &authenticator, encrypt_usage); if (c_opt) diff --git a/third_party/heimdal/tests/gss/check-context.in b/third_party/heimdal/tests/gss/check-context.in index 266fc384902..5a836b9dc77 100644 --- a/third_party/heimdal/tests/gss/check-context.in +++ b/third_party/heimdal/tests/gss/check-context.in @@ -389,6 +389,41 @@ for mech in krb5 spnego; do --mech-type=$mech host@lucid.test.h5l.se 2>/dev/null && \ { eval "$testfailed"; } + echo "${mech}: initiator null bindings bound (client-aware-flag)" ; > messages.log + ${context} -v --i-channel-bound \ + --mech-type=$mech host@lucid.test.h5l.se > cbinding.log || \ + { eval "$testfailed"; } + grep "sflags:" cbinding.log | grep "channel-bound" > /dev/null && \ + { echo "channel-bound flag unexpected"; eval "$testfailed"; } + + echo "${mech}: initiator only bindings (client-aware-flag)" ; > messages.log + ${context} -v --i-channel-bound \ + --i-channel-bindings=abc \ + --mech-type=$mech host@lucid.test.h5l.se > cbinding.log || \ + { eval "$testfailed"; } + grep "sflags:" cbinding.log | grep "channel-bound" > /dev/null && \ + { echo "channel-bound flag unexpected"; eval "$testfailed"; } + + echo "${mech}: acceptor only bindings (client-aware-flag)" ; > messages.log + ${context} -v --i-channel-bound \ + --a-channel-bindings=abc \ + --mech-type=$mech host@lucid.test.h5l.se 2>/dev/null && \ + { eval "$testfailed"; } + + echo "${mech}: matching bindings (client-aware-flag)" ; > messages.log + ${context} -v --i-channel-bound \ + --i-channel-bindings=abc --a-channel-bindings=abc \ + --mech-type=$mech host@lucid.test.h5l.se > cbinding.log || \ + { eval "$testfailed"; } + grep "sflags:" cbinding.log | grep "channel-bound" > /dev/null || \ + { echo "no channel-bound flag"; eval "$testfailed"; } + + echo "${mech}: non matching bindings (client-aware-flag)" ; > messages.log + ${context} -v --i-channel-bound \ + --i-channel-bindings=abc --a-channel-bindings=xyz \ + --mech-type=$mech host@lucid.test.h5l.se 2>/dev/null && \ + { eval "$testfailed"; } + done #echo "sasl-digest-md5"