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).
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user