From 921d528d8bc2e90ee9bc790e7a4e1dc012fac4f3 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 4 Feb 2020 16:39:34 +1100 Subject: [PATCH] gss: add mechanism-force-mechListMIC hook to SPNEGO NTLM erroneously requires a mechListMIC at the SPNEGO layer if an internal MIC in the NTLM protocol was used. Add a private interface between SPNEGO and the Samba NTLM mechanism to allow the mechanism to signal that a mechListMIC is required even if it otherwise would not be. This interface is the same as that supported by MIT. Note that only the Samba NTLM mechanism currently implements this feature, it is not implemented by the Heimdal NTLM mechanism (which does not support NTLM authenticate message MICs). --- lib/gssapi/gssapi/gssapi_oid.h | 3 +++ lib/gssapi/mech/gss_oid.c | 4 +++ lib/gssapi/oid.txt | 1 + lib/gssapi/spnego/compat.c | 48 ++++++++++++++++++++++++++++------ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/gssapi/gssapi/gssapi_oid.h b/lib/gssapi/gssapi/gssapi_oid.h index 268271861..6081c6989 100644 --- a/lib/gssapi/gssapi/gssapi_oid.h +++ b/lib/gssapi/gssapi/gssapi_oid.h @@ -138,6 +138,9 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_negoex_key_oid_desc; extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_negoex_verify_key_oid_desc; #define GSS_C_INQ_NEGOEX_VERIFY_KEY (&__gss_c_inq_negoex_verify_key_oid_desc) +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_inq_require_mechlist_mic_oid_desc; +#define GSS_C_INQ_REQUIRE_MECHLIST_MIC (&__gss_c_inq_require_mechlist_mic_oid_desc) + /* * "Standard" mechs */ diff --git a/lib/gssapi/mech/gss_oid.c b/lib/gssapi/mech/gss_oid.c index 14d53c977..20d216069 100644 --- a/lib/gssapi/mech/gss_oid.c +++ b/lib/gssapi/mech/gss_oid.c @@ -130,6 +130,9 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_negoex_key_oid_desc = { 11, rk_UNCO /* GSS_C_INQ_NEGOEX_VERIFY_KEY - 1.2.840.113554.1.2.2.5.17 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_negoex_verify_key_oid_desc = { 11, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x11") }; +/* GSS_C_INQ_REQUIRE_MECHLIST_MIC - 1.3.6.1.4.1.7165.655.1.2 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_inq_require_mechlist_mic_oid_desc = { 11, rk_UNCONST("\x2b\x06\x01\x04\x01\xb7\x7d\x85\x0f\x01\x02") }; + /* GSS_KRB5_MECHANISM - 1.2.840.113554.1.2.2 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_mechanism_oid_desc = { 9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; @@ -318,6 +321,7 @@ gss_OID _gss_ot_internal[] = { &__gss_c_inq_sspi_session_key_oid_desc, &__gss_c_inq_negoex_key_oid_desc, &__gss_c_inq_negoex_verify_key_oid_desc, + &__gss_c_inq_require_mechlist_mic_oid_desc, &__gss_krb5_mechanism_oid_desc, &__gss_ntlm_mechanism_oid_desc, &__gss_spnego_mechanism_oid_desc, diff --git a/lib/gssapi/oid.txt b/lib/gssapi/oid.txt index 20b749b41..2bf101ea6 100644 --- a/lib/gssapi/oid.txt +++ b/lib/gssapi/oid.txt @@ -54,6 +54,7 @@ oid base GSS_C_INQ_WIN2K_PAC_X 1.2.752.43.13.3.128 oid base GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 oid base GSS_C_INQ_NEGOEX_KEY 1.2.840.113554.1.2.2.5.16 oid base GSS_C_INQ_NEGOEX_VERIFY_KEY 1.2.840.113554.1.2.2.5.17 +oid base GSS_C_INQ_REQUIRE_MECHLIST_MIC 1.3.6.1.4.1.7165.655.1.2 #/* # * "Standard" mechs diff --git a/lib/gssapi/spnego/compat.c b/lib/gssapi/spnego/compat.c index 1383c2bf2..1ae88d489 100644 --- a/lib/gssapi/spnego/compat.c +++ b/lib/gssapi/spnego/compat.c @@ -152,6 +152,35 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context return ret; } +/* + * Returns TRUE if the mechanism believes that a mechListMIC is required. + * This is an internal interface for NTLM which requires a mechListMIC if + * an internal MIC in the NTLM protocol was used. Note that only the Samba + * NTLM mechanism supports this, it is not yet implemented in Heimdal's. + */ + +static int +mech_require_mechlist_mic_p(gssspnego_ctx ctx) +{ + OM_uint32 major, minor; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + uint8_t mech_require_mic = 0; + + major = gss_inquire_sec_context_by_oid(&minor, ctx->negotiated_ctx_id, + GSS_C_INQ_REQUIRE_MECHLIST_MIC, &data_set); + if (major != GSS_S_COMPLETE) + return FALSE; + + if (data_set != GSS_C_NO_BUFFER_SET && + data_set->count == 1 && + data_set->elements[0].length == 1) + mech_require_mic = *((uint8_t *)data_set->elements[0].value); + + gss_release_buffer_set(&minor, &data_set); + + return mech_require_mic == 1; +} + /* * Returns TRUE if it is safe to omit mechListMIC because the preferred * mechanism was selected, and the peer did not require it. @@ -160,15 +189,18 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context int _gss_spnego_safe_omit_mechlist_mic(gssspnego_ctx ctx) { - int safe_omit = 0; + int safe_omit = FALSE; - if (ctx->flags.peer_require_mic == FALSE) - safe_omit = gss_oid_equal(ctx->selected_mech_type, ctx->preferred_mech_type); - - if (safe_omit) - _gss_mg_log(10, "spnego: safe to omit mechListMIC, as preferred mechanism selected"); - else - _gss_mg_log(10, "spnego: mechListMIC required"); + if (ctx->flags.peer_require_mic) { + _gss_mg_log(10, "spnego: mechListMIC required by peer"); + } else if (mech_require_mechlist_mic_p(ctx)) { + _gss_mg_log(10, "spnego: mechListMIC required by mechanism"); + } else if (gss_oid_equal(ctx->selected_mech_type, ctx->preferred_mech_type)) { + safe_omit = TRUE; + _gss_mg_log(10, "spnego: mechListMIC may be omitted as preferred mechanism selected"); + } else { + _gss_mg_log(10, "spnego: mechListMIC required by default"); + } return safe_omit; }