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:
@@ -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