[krbdev.mit.edu #9018] Bugs while authenticating to azure files

Amandeep Gautam via RT rt at kerborg-prod-app-1.mit.edu
Mon Jul 26 19:48:06 EDT 2021


<URL: http://kerborg-prod-app-1.mit.edu/rt/Ticket/Display.html?id=9018 >

Hi Greg,
   Thanks for the prompt reply. I think you are right. I mistook
mechListMIC set to GSS_C_NO_BUFFER as an invalid token. These 2 are
different. I added some more logs and here is more detailed information:

In, *init_ctx_cont* the *buf->length* is 9. From *init_ctx_cont*, we call
*get_negTokenResp*, which returns empty *mechListMIC* token with status:
*GSS_S_COMPLETE*.
Progressing in *init_ctx_cont*, we hit the following if-else block


        *....*
*        } else if (!sc->mech_complete ||*



*                   (sc->mic_reqd &&                    (sc->ctx_flags &
GSS_C_INTEG_FLAG))) {                /* Not obviously done; we may decide
we're done later in                 * init_ctx_call_init or handle_mic. */*






*                *tokflag = CONT_TOKEN_SEND;                ret =
GSS_S_COMPLETE;        } else {                /* mech finished on last
pass and no MIC required, so done. */                *tokflag =
NO_TOKEN_SEND;                ret = GSS_S_COMPLETE;        }*
*        ...*

After returning from here, we return back to *spnego_gss_init_sec_context*
function (from where we called *init_ctx_cont*). In this function, the
handle_mic call leads to the problem. Code snippet for the call:

*        ...*



*        negState = ACCEPT_INCOMPLETE;        if (spnego_ctx->mech_complete
&&            (spnego_ctx->ctx_flags & GSS_C_INTEG_FLAG)) {*







*                        ret = handle_mic(minor_status,
                     mechListMIC_in,
 (mechtok_out.length != 0),
 spnego_ctx, &mechListMIC_out,
 &negState, &send_token);                        if (HARD_ERROR(ret))
                          goto cleanup;*
*        ...*

To be more specific, in *handle_mic* function, I hit the following section:

*        ...*










*        } else if (sc->mic_reqd && !send_mechtok) {                /*
           * If the peer sends the final mechanism token, it
 * must send the MIC with that token if the                 * negotiation
requires MICs.                 */                *negState = REJECT;
        *tokflag = ERROR_TOKEN_SEND;                return
GSS_S_DEFECTIVE_TOKEN;        }*
*        ...*

So, I think you were right.

About, the suggestions that were made, I think what you are saying is that
(1) is not possible (or very hard). If you can add more details on (2), I
will be happy to make the change and test it.
Basically, I do not understand if the problem is
(a) The assumption that: if we send one, we should receive one? OR
(b) Sending MIC in the first place.

Regards,
Aman


On Mon, Jul 26, 2021 at 11:53 AM Greg Hudson via RT <
rt at kerborg-prod-app-1.mit.edu> wrote:

> Thanks for the comprehensive interop issue report.  I have one question:
>
> > In function, src/lib/gssapi/spnego/spnego_mech.c: get_negTokenResp we
> return
> error code that it is a defective token.
>
> This function should only return a defective token error if the packet has
> a
> bad length, which does not appear to be the case.  Is it possible that the
> error came from handle_mic() at the first else-if clause?
>
> Some background:
>
> * RFC 4178 (SPNEGO) section 5 only requires a mechlistMIC exchange if the
> negotiated mech is not the most-preferred mech of one of the two parties.
> Otherwise the MIC exchange is optional (unless the negotiated mech has no
> MIC
> support, in which case it's impossible).
>
> * RFC 4178 section 5 (c) (I) says, for the acceptor processing the final
> initiator token: "If a mechlistMIC token was included and is correctly
> verified, GSS_Accept_sec_context() indicates GSS_S_COMPLETE.  The output
> negotiation message contains a mechlistMIC token and an accept_complete
> state."
>
> In this exchange both parties prefer NTLMSSP, so one would expect the MIC
> exchange to be optional.   However, Microsoft imposes an additional
> constraint
> for NTLMSSP.  This is both observed and documented; [MS-SPNG] Appendix A
> says:
>
>     If NTLM authentication is most preferred by the client and the server,
> and
> the
>     client includes a MIC in AUTHENTICATE_MESSAGE ([MS-NLMP] section
>     2.2.1.3), then the mechListMIC field becomes mandatory in order for the
>     authentication to succeed. Windows clients in this case send an NTLM
> token
>     instead of an SPNEGO token.
>
> Accordingly, we have a helper mech_requires_mechlistMIC(), so that NTLMSSP
> can
> report that it's behaving in a way that causes a SPNEGO MIC to be
> required.
> In our code, the MIC requirement is treated as symmetrical; if we send
> one, we
> believe we must receive one, and (following RFC 4178 5.c.I) if we receive
> one,
> we send one.
>
> From the packet traces it would appear that the Azure server does not
> believe
> a MIC is required (i.e. it is not behaving according to [MS-SPNG] Appendix
> A)
> and isn't sending a MIC in response to the initiator's MIC (i.e. it it
> violates RFC 4178 section 5(c)(I)).  This apparent misbehavior could be
> accomodated in two ways:
>
> 1. Following the hint in [MS-SPNG] Appendix A, the application could send
> an
> NTLM token instead of a SPNEGO token.  Generally if a client prefers NTLM,
> it
> can only do NTLM, so negotiation isn't required.  However, it may be
> difficult
> for an application using MIT krb5 to implement this due to the abstraction
> boundaries; the application doesn't know that the client is only capable of
> NTLM and the SPNEGO layer can't generate a non-SPNEGO token.
>
> 2. In our SPNEGO layer, a true result from mech_requires_mechlistMIC()
> could
> cause a MIC token to be generated, but not required from the other party.
>
>
>



More information about the krb5-bugs mailing list