[cifs-protocol] RE: (More): Status: SRX080803600053: [MS-NLMP] raw NTLMSSP tokens in GSS-API/SPNEGO

Bill Wesse billwe at microsoft.com
Tue Dec 16 12:06:46 GMT 2008


Good afternoon Mr. Simpkins. Thank you for your patience.

We have modified [MS-NLMP] for a future posting, as shown below, to address your comments (which I have also included, for the sake of completeness).

Please let me know if this meets your needs.

==============================================================================
[MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol Specification

3.1.4 Higher-Layer Triggered Events

The application client initiates NTLM authentication through the Security
Support Provider Interface (SSPI), the Microsoft implementation of GSS-API
[RFC2743]. NTLM does not support RFC 2743 token framing (Section 3.1
[RFC2743]).

==============================================================================
Notes (billwe):

For the initial negotiation token, as exemplified in spnego_ntlmssp.cap frame
6, [RFC4178] sections 4.2 (Negotiation Tokens) and 4.2.1 (negTokenInit) (BNF
description) apply (capture details and RFC extracts for comparison are near
the end of this email).

As noted, NTLM does not support RFC 2743 token framing as described in
[RFC2743] Section 3.1).

Additionally (unlike our GSS Kerberos implementation), NTLM does not perform
nested InnerContextToken embedding discussed in [RFC4178] section 3.2 with
regard to GSS_Accept_sec_context().

Reference:

[MS-SPNG]: Simple and Protected Generic Security Service Application Program
           Interface Negotiation Mechanism (SPNEGO) Protocol Extensions

3.2.5.2 Universal Receiver
  <8>

<8> Section 3.2.5.2: This behavior is present on Windows 2000, Windows XP,
    Windows Server 2003, and Windows Vista. For backward compatibility and
    historical reasons, a Windows implementation of SPNEGO has the following
    behavior: it accepts raw Kerberos messages that are based on [RFC4121]
    and [RFC4120], and it accepts raw NTLM messages that are not embedded in
    [RFC4178] SPNEGO messages. This behavior is known as the universal
    receiver behavior.

==============================================================================
Comments:

The documentation updates so far have addressed the fact that the Windows
implementation accepts raw NTLM SSP tokens that are not correctly embedded in
GSS InitialContextTokens.  However, I don't recall any updates addressing the
fact that the Windows implementation does not accept well-formed GSS
InitialContextTokens containing NTLM SSP.

This could probably be addressed by updating [MS-NLMP] somewhere to indicate
that the NTLM implementation of GSS_Init_sec_context() never outputs a GSS
InitialContextToken for the first token, and GSS_Accept_sec_context() does not
accept well-formed GSS InitialContextTokens.

Updating [MS-NLMP] this way would address both the behavior with and without
SPNEGO, since SPNEGO should merely be invoking GSS_Init_sec_context() /
GSS_Accept_sec_context() to handle the inner NTLM SSP mechToken. The
"Universal Receiver" section of [MS-SPNG] probably wouldn't even be relevant
anymore.

I'm not sure where the best place in [MS-NLMP] would be to mention this.
Section 1.4 talks about the GSS-API interface to NTLM.  It references section
3.4.6, but that only talks about the GSS_WrapEx() call.

==============================================================================
Previous comments:

spnego_ntlmssp.cap, frame 6 contains the initial SESSION_SETUP_ANDX request.
This contains a GSS-API InitialContextToken that uses SPNEGO. The mechToken
inside the SPNEGO NegTokenInit contains just raw NTLMSSP data. According to
RFC 4178 section 3.2 item (c), this should be a GSS InitialContextToken.

Perhaps there is some confusion here because RFC 4178 section 3.2 mentions two
separate calls to GSS_Accept_sec_context().  Initially, the entire GSS token
(bytes 0x75-0xBE in this trace) is passed to GSS_Accept_sec_context(), as
mentioned at the beginning of item (c), so it can be processed by the SPNEGO
mechanism.  Then, if the SPNEGO mechanism accepts the initiator's preferred
mechanism, and the initiator included an optimistic mechToken (bytes 0x97-0xBE
in this trace), the optimistic mechToken must be passed to
GSS_Accept_sec_context() so it can be processed by the negotiated mechanism.
This behavior is from the end of item (c), which I quote above.

Based on my understanding, this second call to GSS_Accept_sec_context() is
establishing a new "inner" context that uses the negotiated mechanism.
Therefore this call to GSS_Accept_sec_context() is the also first call for
this context, so it should receive an InitialContextToken.

Admittedly, RFC 4178 could be a bit clearer in this regard.  However, other
available SPNEGO implementations appear to agree with my interpretation.
For example, this appears to be how the MIT Kerberos implementation behaves:

http://anonsvn.mit.edu/cgi-bin/viewcvs.cgi/trunk/src/lib/gssapi/spnego/spnego_mech.c?rev=19831&view=markup

They pass the received tokens to gss_init_sec_context() /
gss_accept_sec_context() with a separate inner context.  As a result, the
initial mechToken is always a GSS InitialContextToken.

spnego_ntlmssp.cap, frame 6

- Smb: C; Session Setup Andx, NTLM NEGOTIATE MESSAGE
  + SMBHeader: Command, TID: 0x0000, PID: 0xFEFF, UID: 0x0000, MID: 0x0040
  - CSessionSetupAndXNTLMESS:
   - Capabilities: 0xA00000D4
      ExtendedSecurity:    (1...............................) Supports
                           extended security exchange (CAP_EXTENDED_SECURITY)
   - SecurityBlob:
    - GssApi:
     + ApplicationHeader:
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2)
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0:
       - NegTokenInit: 0x1
        + SequenceHeader:
        + Tag0:
        - MechTypes:
         + SequenceHeader:
         + MechType: NLMP (1.3.6.1.4.1.311.2.2.10)
        + Tag2:
        + OctetStringHeader:
        - MechToken: NTLM NEGOTIATE MESSAGE
         + NLMP: NTLM NEGOTIATE MESSAGE

http://www.ietf.org/rfc/rfc4178.txt

4.2.  Negotiation Tokens

   The syntax of the initial negotiation tokens follows the
   initialContextToken syntax defined in Section 3.1 of [RFC2743].  The
   SPNEGO pseudo mechanism is identified by the Object Identifier
   iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2).
   Subsequent tokens MUST NOT be encapsulated in this GSS-API generic
   token framing.

   This section specifies the syntax of the inner token for the initial
   message and the syntax of subsequent context establishment tokens.

      NegotiationToken ::= CHOICE {
          negTokenInit    [0] NegTokenInit,
          negTokenResp    [1] NegTokenResp
      }

4.2.1.  negTokenInit

      NegTokenInit ::= SEQUENCE {
          mechTypes       [0] MechTypeList,
          reqFlags        [1] ContextFlags  OPTIONAL,
            -- inherited from RFC 2478 for backward compatibility,
            -- RECOMMENDED to be left out
          mechToken       [2] OCTET STRING  OPTIONAL,
          mechListMIC     [3] OCTET STRING  OPTIONAL,
          ...
      }

Regards,
Bill Wesse
MCSE, MCTS / Senior Escalation Engineer, US-CSS DSC PROTOCOL TEAM
8055 Microsoft Way
Charlotte, NC 28273
TEL:  +1(980) 776-8200
CELL: +1(704) 661-5438
FAX:  +1(704) 665-9606


-----Original Message-----
From: Bill Wesse
Sent: Tuesday, November 04, 2008 5:57 AM
To: 'Adam Simpkins'
Cc: 'cifs-protocol at samba.org'
Subject: RE: (More): Status: SRX080803600053: [MS-NLMP] raw NTLMSSP tokens in GSS-API/SPNEGO

Thank you very much for your considerations. I have filed a documentation change request against [MS-NLMP] concerning NTLMSSP InitialContextTokens (see 'Expected' below)..

==============================================================================
Change Comment / Request:

The documentation updates so far have addressed the fact that the Windows implementation accepts raw NTLM SSP tokens that are not correctly embedded in GSS InitialContextTokens.  However, I don't recall any updates addressing the fact that the Windows implementation does not accept well-formed GSS InitialContextTokens containing NTLM SSP.

This could probably be addressed by updating [MS-NLMP] somewhere to indicate that the NTLM implementation of GSS_Init_sec_context() never outputs a GSS InitialContextToken for the first token, and GSS_Accept_sec_context() does not accept well-formed GSS InitialContextTokens.

Updating [MS-NLMP] this way would address both the behavior with and without SPNEGO, since SPNEGO should merely be invoking GSS_Init_sec_context()/GSS_Accept_sec_context() to handle the inner NTLM SSP mechToken.  The "Universal Receiver" section of [MS-SPNG] probably wouldn't even be relevant anymore.

I'm not sure where the best place in [MS-NLMP] would be to mention this.  Section 1.4 talks about the GSS-API interface to NTLM.  It references section 3.4.6, but that only talks about the GSS_WrapEx() call.

==============================================================================
Ref:
The Simple and Protected Generic Security Service Application Program Interface (GSS-API) Negotiation Mechanism
http://www.ietf.org/rfc/rfc4178.txt?number=4178

3.2.  Negotiation Procedure

      If the initiator's preferred mechanism is accepted, and an
      optimistic mechanism token was included, this mechanism token MUST
      be passed to the selected mechanism by invoking
      GSS_Accept_sec_context().

GSS_Accept_sec_context() is defined in RFC 2743, and the first token passed to it must use the format specified in section 3.1 (i.e., it must be an InitialContextToken).

In this trace, the mechToken contains raw NTLMSSP data, not an InitialContextToken containing NTLMSSP data.  Based on the references I listed above, this behavior appears to be different than what is required by RFC 4178 and RFC 2743.

See attached spnego_ntlmssp.cap, frame 6.

Perhaps there is some confusion here because RFC 4178 section 3.2 mentions two separate calls to GSS_Accept_sec_context().  Initially, the entire GSS token (bytes 0x75-0xBE in this trace) is passed to GSS_Accept_sec_context(), as mentioned at the beginning of item (c), so it can be processed by the SPNEGO mechanism.  Then, if the SPNEGO mechanism accepts the initiator's preferred mechanism, and the initiator included an optimistic mechToken (bytes 0x97-0xBE in this trace), the optimistic mechToken must be passed to GSS_Accept_sec_context() so it can be processed by the negotiated mechanism.  This behavior is from the end of item (c), which I quote above.

Based on my understanding, this second call to GSS_Accept_sec_context() is establishing a new "inner" context that uses the negotiated mechanism.  Therefore this call to GSS_Accept_sec_context() is the also first call for this context, so it should receive an InitialContextToken.

Admittedly, RFC 4178 could be a bit clearer in this regard.  However, other available SPNEGO implementations appear to agree with my interpretation.  For example, this appears to be how the MIT Kerberos implementation behaves:

http://anonsvn.mit.edu/cgi-bin/viewcvs.cgi/trunk/src/lib/gssapi/spnego/spnego_mech.c?rev=19831&view=markup

They pass the received tokens to gss_init_sec_context()/ gss_accept_sec_context() with a separate inner context.  As a result, the initial mechToken is always a GSS InitialContextToken.


Expected:

Even though we are not claiming compliance with RFC4178, the interpretation of '3.2.  Negotiation Procedure' is a point of interest concerning how we embed the NTLM NEGOTIATE MESSAGE MechToken (Netmon 3.2 trace extract below, from the attached spnego_ntlmssp.cap, frame 6.

The customer is requesting that we annotate this concerning that 'the Windows implementation does not accept well-formed GSS InitialContextTokens containing NTLM SSP'.

   - SecurityBlob:
    - GssApi:
     + ApplicationHeader:
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2)
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0:
       - NegTokenInit: 0x1
        + SequenceHeader:
        + Tag0:
        + MechTypes:
        + Tag2:
        + OctetStringHeader:
        - MechToken: NTLM NEGOTIATE MESSAGE
         + NLMP: NTLM NEGOTIATE MESSAGE



Regards,
Bill Wesse
MCSE, MCTS / Escalation Engineer, US-CSS DSC PROTOCOL TEAM
8055 Microsoft Way
Charlotte, NC 28273
TEL:  +1(980) 776-8200
CELL: +1(704) 661-5438
FAX:  +1(704) 665-9606



More information about the cifs-protocol mailing list