Implement KERB_AP_OPTIONS_CBT (server side)

if the client asserted knowledge of channel-bindings by
passing KERB_AP_OPTIONS_CBT, and the server passed bindings,
require the bindings to match.
This commit is contained in:
Isaac Boukris
2020-04-21 20:12:21 +02:00
committed by Luke Howard
parent 51ce4c8d15
commit a4527a28a3
6 changed files with 65 additions and 4 deletions

View File

@@ -213,6 +213,7 @@ AUTHDATA-TYPE ::= INTEGER {
KRB5-AUTHDATA-SIGNTICKET-OLDER(-17),
KRB5-AUTHDATA-SIGNTICKET-OLD(142),
KRB5-AUTHDATA-SIGNTICKET(512),
KRB5-AUTHDATA-AP-OPTIONS(143),
-- N.B. these assignments have not been confirmed yet.
--
-- DO NOT USE in production yet!

View File

@@ -163,6 +163,50 @@ _gsskrb5_create_8003_checksum (
return GSS_S_COMPLETE;
}
static krb5_error_code
check_ap_options_cbt(void *ad_data, size_t ad_len,
krb5_boolean *client_asserted_cb)
{
uint32_t ad_ap_options;
*client_asserted_cb = FALSE;
if (ad_len != sizeof(uint32_t))
return KRB5KRB_AP_ERR_MSG_TYPE;
_gss_mg_decode_le_uint32(ad_data, &ad_ap_options);
if (ad_ap_options & KERB_AP_OPTIONS_CBT)
*client_asserted_cb = TRUE;
return 0;
}
static krb5_error_code
find_ap_options(krb5_context context,
krb5_authenticator authenticator,
krb5_boolean *client_asserted_cb)
{
krb5_error_code ret;
krb5_authdata *ad;
krb5_data data;
*client_asserted_cb = FALSE;
ad = authenticator->authorization_data;
if (ad == NULL)
return 0;
ret = _krb5_get_ad(context, ad, NULL, KRB5_AUTHDATA_AP_OPTIONS, &data);
if (ret)
return ret == ENOENT ? 0 : ret;
ret = check_ap_options_cbt(data.data, data.length, client_asserted_cb);
krb5_data_free(&data);
return ret;
}
/*
* verify the checksum in `cksum' over `input_chan_bindings'
* returning `flags' and `fwd_data'
@@ -170,9 +214,10 @@ _gsskrb5_create_8003_checksum (
OM_uint32
_gsskrb5_verify_8003_checksum(
krb5_context context,
OM_uint32 *minor_status,
const gss_channel_bindings_t input_chan_bindings,
const Checksum *cksum,
krb5_authenticator authenticator,
OM_uint32 *flags,
krb5_data *fwd_data)
{
@@ -182,6 +227,9 @@ _gsskrb5_verify_8003_checksum(
int DlgOpt;
static unsigned char zeros[16];
krb5_boolean channel_bound = FALSE;
const Checksum *cksum = authenticator->cksum;
krb5_boolean client_asserted_cb;
krb5_error_code ret;
/* XXX should handle checksums > 24 bytes */
if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) {
@@ -198,8 +246,14 @@ _gsskrb5_verify_8003_checksum(
p += 4;
ret = find_ap_options(context, authenticator, &client_asserted_cb);
if (ret) {
*minor_status = ret;
return GSS_S_FAILURE;
}
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS
&& memcmp(p, zeros, sizeof(zeros)) != 0) {
&& (memcmp(p, zeros, sizeof(zeros)) != 0 || client_asserted_cb)) {
if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) {
*minor_status = 0;
return GSS_S_BAD_BINDINGS;

View File

@@ -566,9 +566,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
if (authenticator->cksum != NULL
&& authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {
ret = _gsskrb5_verify_8003_checksum(minor_status,
ret = _gsskrb5_verify_8003_checksum(context,
minor_status,
input_chan_bindings,
authenticator->cksum,
authenticator,
&ctx->flags,
&ctx->fwd_data);

View File

@@ -391,4 +391,7 @@ struct krb5_pk_init_ctx_data {
# define ISPATHSEP(x) (x == '/')
#endif
/* Flag in KRB5_AUTHDATA_AP_OPTIONS */
#define KERB_AP_OPTIONS_CBT 0x00004000
#endif /* __KRB5_LOCL_H__ */

View File

@@ -788,6 +788,7 @@ EXPORTS
_krb5_kt_client_default_name
_krb5_have_debug
_krb5_SP800_108_HMAC_KDF
_krb5_get_ad
; Shared with libkadm5
_krb5_load_plugins

View File

@@ -780,6 +780,7 @@ HEIMDAL_KRB5_2.0 {
_krb5_kt_client_default_name;
_krb5_have_debug;
_krb5_SP800_108_HMAC_KDF;
_krb5_get_ad;
# Shared with libkadm5
_krb5_load_plugins;