gss: fix downlevel Windows interop regression

The recent changes to SPNEGO removed support for GSS_C_PEER_HAS_UPDATED_SPNEGO,
through which the Kerberos mechanism could indicate to SPNEGO that the peer did
not suffer from SPNEGO conformance bugs present in some versions of Windows.*

This patch restores this workaround, documented in [MS-SPNG] Appendix A <7>
Section 3.1.5.1. Whilst improving interoperability with these admittedly now
unsupported versions of Windows, it does introduce a risk that Kerberos with
pre-AES ciphers could be negotiated in lieu of a stronger and more preferred
mechanism.

Note: this patch inverts the mechanism interface from
GSS_C_PEER_HAS_UPDATED_SPNEGO to GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO, so that new
mechanisms (which did not ship with these older versions of Windows) are not
required to implement it.

* Windows 2000, Windows 2003, and Windows XP
This commit is contained in:
Luke Howard
2020-04-09 22:51:30 +10:00
parent 0cb752258e
commit 7df0195c26
7 changed files with 35 additions and 48 deletions

View File

@@ -263,39 +263,31 @@ static OM_uint32 inquire_sec_context_authz_data
return ret;
}
static OM_uint32 inquire_sec_context_has_updated_spnego
static OM_uint32 inquire_sec_context_has_buggy_spnego
(OM_uint32 *minor_status,
const gsskrb5_ctx context_handle,
gss_buffer_set_t *data_set)
{
int is_updated = 0;
uint8_t old_enctype;
gss_buffer_desc buffer;
*minor_status = 0;
*data_set = GSS_C_NO_BUFFER_SET;
/*
* For Windows SPNEGO implementations, both the initiator and the
* acceptor are assumed to have been updated if a "newer" [CLAR] or
* different enctype is negotiated for use by the Kerberos GSS-API
* mechanism.
* For Windows SPNEGO implementations, the initiator or acceptor
* are presumed to be "buggy" (Windows 2003 or earlier) if an
* "older" (i.e. pre-AES per RFC 4121) encryption type was used.
*/
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
is_updated = (context_handle->more_flags & IS_CFX);
if (is_updated == 0) {
krb5_keyblock *acceptor_subkey;
if (context_handle->more_flags & LOCAL)
acceptor_subkey = context_handle->auth_context->remote_subkey;
else
acceptor_subkey = context_handle->auth_context->local_subkey;
if (acceptor_subkey != NULL)
is_updated = (acceptor_subkey->keytype !=
context_handle->auth_context->keyblock->keytype);
}
old_enctype = ((context_handle->more_flags & IS_CFX) == 0);
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE;
buffer.value = &old_enctype;
buffer.length = sizeof(old_enctype);
return gss_add_buffer_set_member(minor_status, &buffer, data_set);
}
/*
@@ -549,10 +541,10 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_sec_context_by_oid
return inquire_sec_context_tkt_flags(minor_status,
ctx,
data_set);
} else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) {
return inquire_sec_context_has_updated_spnego(minor_status,
ctx,
data_set);
} else if (gss_oid_equal(desired_object, GSS_C_INQ_PEER_HAS_BUGGY_SPNEGO)) {
return inquire_sec_context_has_buggy_spnego(minor_status,
ctx,
data_set);
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) {
return inquire_sec_context_get_subkey(minor_status,
ctx,