gss: add mechanism-force-mechListMIC hook to SPNEGO
authorLuke Howard <lukeh@padl.com>
Tue, 4 Feb 2020 05:39:34 +0000 (16:39 +1100)
committerLuke Howard <lukeh@padl.com>
Tue, 4 Feb 2020 06:28:35 +0000 (17:28 +1100)
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
lib/gssapi/mech/gss_oid.c
lib/gssapi/oid.txt
lib/gssapi/spnego/compat.c

index 2682718619ad74ab34c17862c30d2d139a116d0d..6081c6989319ba34b5b823fa523f3940f96e9258 100644 (file)
@@ -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
  */
index 14d53c97794bc5605167f99101617fbc26764dba..20d216069a2715a83fefa8620f6e39de9f5f0a58 100644 (file)
@@ -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,
index 20b749b41b5beb87b450e09c2daa670a5c34c4d9..2bf101ea6c429d57ffdf6e074b2a839d708128d7 100644 (file)
@@ -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
index 1383c2bf27011889f6c96021bf23d97f370d3a73..1ae88d489c3dacbf19901462d0f9ae550f42b4aa 100644 (file)
@@ -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;
-
-    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");
+    int safe_omit = FALSE;
+
+    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;
 }