[cifs-protocol] RE: Status: raw NTLMSSP tokens in GSS-API/SPNEGO? SRX080803600053

Bill Wesse billwe at microsoft.com
Fri Aug 8 16:27:54 GMT 2008


Good afternoon Mr. Simpkins. I have provided summaries concerning your follow up questions on the original questions 1, 2 & 4. In addition, I have attached the full text and responses (with the material below interpolated) for the sake of completeness.

To summarize, you raised several issues (I have provided indented response summaries; there are more complete responses in the follow up section for each question, and an attachment with both original and follow up text).

Please let me know if there is anything that I have not answered fully (or misconstrued); I want to make sure we pare this down to specific document changes or product bugs that may apply.

Summary:
========
Question 1.

Windows does not generate well-formed NTLMv2 GSS InitialContextTokens as
specified in RFC 4178 section 3.2 (re: spnego_ntlmssp.cap frame 6), as is
done with Kerberos (re: spnego_krb.cap frame 7).

   Your comments appear correct. The current Windows implementations are
   subject to backward compatibility constraints.

Question 2.

Windows does not accept well-formed NTLMv2 GSS InitialContextTokens as
specified in RFC 4178 section 3.2 (re: gss_ntlmssp.cap frame 7), as is done
with Kerberos (re: spnego_krb.cap frame 7).

   As noted, this appears to be an interoperability deficiency. Action on our
   part may well require bug filings against newer versions of Windows.
   Could you advise me of any known implementations that do this? That would
   be necessary for evidence to justify any Windows updates.

Question 4.

Windows generates and accepts raw NTLM tokens (re: raw_ntlmssp.cap frame 7),
and denotes Kerberos behavior as Windows Behavior.

   The Windows Behavior noted applies to Kerberos OID encoding - Windows 2000
   encoded this incorrectly; subsequent Windows versions encode this
   correctly. Reference:  [MS-SPNG] Appendix A notes <5> and <8>

Full Responses:
===============

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 1 Follow-up:
---------------------

Just to clarify terminology, the mechToken (inside the SPNEGO NegTokenInit)
is what's at 0x97-0xBE.

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.

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.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Response:

Thanks for correcting my terminology on the text 'negotiate message is
encapsulated', which should have been 'the mechToken (inside the SPNEGO
NegTokenInit) is what's at 0x97-0xBE'.

I agree - the below extract from 'RFC 4178 section 3.2 (c)' implies that a
new inner context should be established (as is done with Kerberos, as shown
in spnego_krb.cap frame 7).

The possibility of guaranteeing an update to a majority of deployed Windows
clients and servers approaches the impossible. This constrains Windows
versions to preserve backward compatibility for some time to come. Any updates
would need to be accomodated per the follow up on Question 2, below.

RFC 4178 section 3.2 (c)
...
      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().  If a response mechanism token is
      returned, it MUST be included in the response negotiation token.
      Otherwise, the target will not generate a response mechanism token
      in the first reply.

spnego_krb.cap frame 7:

    - GssApi:
     + ApplicationHeader:
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2)
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0:
       - NegTokenInit:               ([RFC2478] NegotiationToken, negTokenInit [0] NegTokenInit)
        + SequenceHeader:
        + Tag0:
        + MechTypes:                 ([RFC2478] mechTypes [0] MechTypeList  OPTIONAL)
        + Tag2:                      ([RFC2478] mechToken [2] OCTET STRING OPTIONAL)
        + OctetStringHeader:
        - MechToken: 0x1
         + MsKerberosToken: 0x1
          - GssApi:                   ([RFC4178] section 3.2 (c))
           + ApplicationHeader:
           + ThisMech: KerberosToken (1.2.840.113554.1.2.2)
           + InnerContextToken: 0x1

spnego_ntlmssp.cap frame 6:

    - GssApi:
     + ApplicationHeader:
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2) ([RFC2078])
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0:
       - NegTokenInit:               ([RFC2478] NegotiationToken, negTokenInit [0] NegTokenInit)
        + SequenceHeader:
        + Tag0:
        - MechTypes:                 ([RFC2478] mechTypes [0] MechTypeList  OPTIONAL)
         + SequenceHeader:
         + MechType: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
        + Tag2:                      ([RFC2478] mechToken [2] OCTET STRING OPTIONAL)
        + OctetStringHeader:
          MechToken: 0x1              (NtlmSsp: NTLM NEGOTIATE MESSAGE)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 2 Follow-up:
---------------------
Windows servers do not seem to accept well-formed GSS InitialContextTokens
containing NTLMSSP (re: gss_ntlmssp.cap frame 7), as is done with Kerberos
(re: spnego_krb.cap frame 7).

Response:

This refers to the same GSS-API construction information referenced in
Question 1. above.

   As noted, this appears to be an interoperability deficiency. Action on our
   part may well require bug filings against newer versions of Windows.
   Could you advise me of any known implementations that do this? That would
   be necessary for evidence to justify any Windows updates.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 4 Follow-up:
---------------------

Yes, I assumed this is the behavior that this section of the text was trying
to describe.  However, it's not clear to me how this is related to SPNEGO.

According to MS-SMB section 2.2.4 and MS-SMB 3.2.4.2.3, the security blob in
the SESSION_SETUP_ANDX request should be a GSS authentication token.
According to RFC 2743, the thisMech field of the GSS InitialContextToken
indicates which security mechanism has been selected by the client.
If the thisMech field is the SPNEGO OID (1.3.6.1.5.5.2), one would expect
SPNEGO to be in use.

However, in this case the security blob isn't a GSS InitialContextToken, and
doesn't include the SPNEGO OID.  It's therefore unclear to me why one would
assume that this is related to SPNEGO, and not just GSS-API in general.

Also, note that the Kerberos behavior described by this passage does not seem
like a Windows extension.  This seems to be normal behavior for a GSS-API
acceptor when the thisMech field is the Kerberos OID.

Response:

raw_ntlmssp.cap frame 7:

Microsoft's implementation does indeed accept raw NTLMSSP data (per Reference
A below) in the SecurityBlob in an SMB_COM_SESSION_SETUP_ANDX request packet.
This does not relate to SPNEGO negotiation, and was introduced in the NTLMv2
implementation on Windows NT 4 Service Pack 4.

Kerberos support (under GSSAPI/SPNEGO) was, of course, introduced in
Windows 2000 (along with NTLMSSP; Reference A does not apply here).

spnego_krb.cap frame 7:

Kerberos behavior (per Reference B below), is indeed Windows Behavior. I
assume that you are referring to the follow up to Question 1 (RFC 4178
section 3.2 (c)). In this case, the Windows Behavior that applies also
refers to Reference C below, which is specific to the Kerberos OID
encoding (erroneous: 1.2.840.48018.1.2.2, correct: 1.2.840.113554.1.2.2).

Reference A:
   [MS-SMB] 3.2.4.2.3
   User Authentication / 'Implicit NTLM

Reference B:
[MS-SPNG]
   3.2.5.2 Universal Receiver
   <8>
   ...
   6 Appendix A: Windows Behavior
   <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.

Reference C:
[MS-SPNG]
   6 Appendix A: Windows Behavior
   <5> Section 3.1.5.2: Windows versions offer and accept two distinct OIDs
       as identifiers for the Kerberos authentication mechanism. The SPNEGO
       extensions consider both OIDs as equivalent and make no distinction
       between them.

       Windows 2000 incorrectly encoded the OID for the Kerberos protocol.
       Rather than the OID { iso(1) member-body(2) United States(840)
       mit(113554) infosys(1) gssapi(2) krb5(2) }, an implementation error
       truncated the values at 16 bits. Therefore, the OID became { iso(1)
       member-body(2) United States(840) ???(48018) infosys(1) gssapi(2) krb5
       (2) }. 48018 is not a known member under that OID branch; this is an
       error.

       Windows XP, Windows Server 2003, Windows Vista, and Windows Server
       2008 do not truncate the value, and they correctly offer and receive
       1.2.840.113554.1.2.2. For compatibility reasons, the erroneous value
       (1.2.840.48018.1.2.2) is still offered and accepted by systems that
       run Windows 2000. The presence of this value can be used to determine
       that the peer is a Windows 2000 implementation.

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

-------------- next part --------------
==============================================================================
Question 1
==========

spnego_ntlmssp.cap
frame 6

Question / Comment:
-------------------
This was taken between a client running Windows XP SP3 and a server running
Windows Server 2003 SP2 (Enterprise Edition).

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.

Response:
---------
   Please correct me if I missed anything.

   I have annotated spnego_ntlmssp.cap frame 6 below, and it seems to me
   that we meet the specification, given that [RFC2078] defines the
   InnerContextToken (+ ThisMech: SpnegoToken (1.3.6.1.5.5.2) ([RFC2078]))
   to be defined as mechanism-specific, not requiring ASN.1 encoding.

   Please see 'Reference 1' below; [MS-SMB] specifies additional information
   in sections 2.2.4 and 3.2.4.2.3:
   
      SecurityBlob (variable): This field MUST be the authentication token
      sent to the server, as specified in section 3.2.4.2.3 and [RFC4178].
   
   [RFC4178] specifies the 'InitialContextToken' to be in the format
   defined in [RFC2078]:

       [APPLICATION 0] IMPLICIT SEQUENCE {
               thisMech MechType,
               innerContextToken ANY DEFINED BY thisMech
                  -- contents mechanism-specific
                  -- ASN.1 structure not required
               }

   o See 'Reference 2' [RFC2078] below Section 3.1 for the description
     of the InitialContextToken. Definition: 
        innerContextToken ANY DEFINED BY thisMech

   o  [RFC4178] : See 'Reference 5' below for the BNF.
      3.2. Negotiation Tokens
      The syntax of the negotiation tokens follows the InitialContextToken
      syntax defined in [1] ([RFC2078])
      
      See 'Reference 5' [RFC4178] below for the negotiation token BNF.

   o In the capture details below, 'NtlmSsp: NTLM NEGOTIATE MESSAGE' is
     indented, since NTLM is considered a separate protocol by Network
     Monitor 3.2. As you know, the InnerContextToken is from offset
     0x7F - 0xBE, and the negotiate message is encapsulated at offset
     0x97 - 0xBE.
   
     See 'Reference 1 / Extended Security' [MS-SMB] below.

     ThisMech: SpnegoToken (1.3.6.1.5.5.2) See 'Reference 3' below.
     OID Repository - Home
     http://www.oid-info.com/
     iso(1) identified-organization(3) dod(6) internet(1) security(5)
     mechanisms(5) snego(2)
     Child OID:  modules(4)
     Ref: http://www.ietf.org/rfc/rfc2743.txt

------------------------------------------------------------------------------
Capture Details (Network Monitor 3.2)

  - CSessionSetupAndXNTLMESS: 
     WordCount: 12 (0xC)
     ANDXCommand: No Secondary Command 255(0xFF)
     AndXReserved: 0 (0x0)
     ANDXOffset: 236 (0xEC)
     MaxBufferSize: 16644 (0x4104)
     MaxMpxCount: 50 (0x32)
     VcNumber: 0 (0x0)
     SessionKey: 0 (0x0)
     SecurityBlobLength: 74 (0x4A)
     Reserved: 0 (0x0)
   + Capabilities: 0xA00000D4
     ByteCount: 177 (0xB1)
   - SecurityBlob: 
    - GssApi: 
     + ApplicationHeader: 
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2) ([RFC2078])
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0: 
       - NegTokenInit:               ([RFC2478] NegotiationToken, negTokenInit [0] NegTokenInit)
        + SequenceHeader: 
        + Tag0: 
        - MechTypes:                 ([RFC2478] mechTypes [0] MechTypeList  OPTIONAL)
         + SequenceHeader: 
         + MechType: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
        + Tag2:                      ([RFC2478] mechToken [2] OCTET STRING OPTIONAL)
        + OctetStringHeader: 
          MechToken: 0x1              (NtlmSsp: NTLM NEGOTIATE MESSAGE)
   + UnicodeParameters: 
     ANDXPadding: Binary Large Object (2 Bytes)
- NtlmSsp: NTLM NEGOTIATE MESSAGE
    Signature: NTLMSSP
    MessageType: Negotiate Message (0x00000001)
  - NtlmsspNegotiateMessage: 
   + NegotiateFlags: 0xE2088297 (NTLM v2128-bit encryption, Always Sign)
   + WorkstationDomainHeader: Length: 0, Offset: 0
   + WorkstationNameHeader: Length: 0, Offset: 0
   + Version: Windows 5.1 Build 10250 NTLMSSPv15

0075                 60 48 06 06 2B 06 01 05 05 02     GssApi:
007E                                               A0  InnerContextToken: (SpnegoToken:)
0080  3E 30 3C A0 0E 30 0C 06 0A 2B 06 01 04 01 82 37
0090  02 02 0A A2 2A 04 28
0096                       4E 54 4C 4D 53 53 50 00 01  MechToken: (NtlmSsp: NTLM NEGOTIATE MESSAGE)
00A0  00 00 00 97 82 08 E2 00 00 00 00 00 00 00 00 00
00B0  00 00 00 00 00 00 00 05 01 28 0A 00 00 00 0F 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 1 Follow-up:
---------------------

Just to clarify terminology, the mechToken (inside the SPNEGO NegTokenInit)
is what's at 0x97-0xBE.

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.

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.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Response:

Thanks for correcting my terminology on the text 'negotiate message is
encapsulated', which should have been 'the mechToken (inside the SPNEGO
NegTokenInit) is what's at 0x97-0xBE'.

I agree - the below extract from 'RFC 4178 section 3.2 (c)' implies that a
new inner context should be established (as is done with Kerberos, as shown
in spnego_krb.cap frame 7).

The possibility of guaranteeing an update to a majority of deployed Windows
clients and servers approaches the impossible. This constrains Windows
versions to preserve backward compatibility for some time to come. Any updates
would need to be accomodated per the follow up on Question 2, below.

RFC 4178 section 3.2 (c)
...
      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().  If a response mechanism token is
      returned, it MUST be included in the response negotiation token.
      Otherwise, the target will not generate a response mechanism token
      in the first reply.

spnego_krb.cap frame 7:

    - GssApi: 
     + ApplicationHeader: 
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2)
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0: 
       - NegTokenInit:               ([RFC2478] NegotiationToken, negTokenInit [0] NegTokenInit)
        + SequenceHeader: 
        + Tag0: 
        + MechTypes:                 ([RFC2478] mechTypes [0] MechTypeList  OPTIONAL)
        + Tag2:                      ([RFC2478] mechToken [2] OCTET STRING OPTIONAL)
        + OctetStringHeader: 
        - MechToken: 0x1
         + MsKerberosToken: 0x1
          - GssApi:                   ([RFC4178] section 3.2 (c))
           + ApplicationHeader: 
           + ThisMech: KerberosToken (1.2.840.113554.1.2.2)
           + InnerContextToken: 0x1

spnego_ntlmssp.cap frame 6:

    - GssApi: 
     + ApplicationHeader: 
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2) ([RFC2078])
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0: 
       - NegTokenInit:               ([RFC2478] NegotiationToken, negTokenInit [0] NegTokenInit)
        + SequenceHeader: 
        + Tag0: 
        - MechTypes:                 ([RFC2478] mechTypes [0] MechTypeList  OPTIONAL)
         + SequenceHeader: 
         + MechType: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
        + Tag2:                      ([RFC2478] mechToken [2] OCTET STRING OPTIONAL)
        + OctetStringHeader: 
          MechToken: 0x1              (NtlmSsp: NTLM NEGOTIATE MESSAGE)

==============================================================================
Question 2
==========

gss_ntlmssp.cap
frame 7

Question / Comment:
-------------------

Another related point that should probably be documented is that Windows
servers do not seem to accept well-formed GSS InitialContextTokens containing
NTLMSSP.  I have attached a trace of that, too.  (The server is the same
Windows Server 2003 system as in the other traces.)

Response:
---------

   I believe this refers to the same GSS-API construction information I
   referenced in Question 1. above.

   ThisMech: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
   OID Repository - Home
   http://www.oid-info.com/
   iso(1) identified-organization(3) dod(6) internet(1) private(4)
   enterprise(1) microsoft(311) 2  
   Child OID:  modules(4)
   Ref: http://www.ietf.org/rfc/rfc2743.txt

------------------------------------------------------------------------------
Capture Details (Network Monitor 3.2)

  - CSessionSetupAndXNTLMESS: 
     WordCount: 12 (0xC)
     ANDXCommand: No Secondary Command 255(0xFF)
     AndXReserved: 0 (0x0)
     ANDXOffset: 146 (0x92)
     MaxBufferSize: 16384 (0x4000)
     MaxMpxCount: 50 (0x32)
     VcNumber: 1 (0x1)
     SessionKey: 0 (0x0)
     SecurityBlobLength: 46 (0x2E)
     Reserved: 0 (0x0)
   + Capabilities: 0x8000C25C
     ByteCount: 87 (0x57)
   - SecurityBlob: 
    - GssApi: 
     + ApplicationHeader: 
     + ThisMech: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
       InnerContextToken: 0x1
   + UnicodeParameters: 
     ANDXPadding: Binary Large Object (2 Bytes)
- NtlmSsp: NTLM NEGOTIATE MESSAGE
    Signature: NTLMSSP
    MessageType: Negotiate Message (0x00000001)
  - NtlmsspNegotiateMessage: 
   + NegotiateFlags: 0xA0000217 (NTLM v1128-bit encryption, , Sign)
   + WorkstationDomainHeader: Length: 0, Offset: 0
   + WorkstationNameHeader: Length: 0, Offset: 0

0081     60 2C                                         GssApi:
0083           06 0A 2B 06 01 04 01 82 37 02 02 0A     ThisMech: NtlmSsp (1.3.6.1.4.1.311.2.2.10)
008F                                               4E  InnerContextToken: 0x1 (NtlmSsp: NTLM NEGOTIATE MESSAGE)
0090  54 4C 4D 53 53 50 00 01 00 00 00 17 02 00 A0 00
00A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 2 Follow-up:
---------------------
Windows servers do not seem to accept well-formed GSS InitialContextTokens
containing NTLMSSP (re: gss_ntlmssp.cap frame 7), as is done with Kerberos
(re: spnego_krb.cap frame 7).

Response:

This refers to the same GSS-API construction information referenced in
Question 1. above.

   As noted, this appears to be an interoperability deficiency. Action on our
   part may well require bug filings against newer versions of Windows.
   Could you advise me of any known implementations that do this? That would
   be necessary for evidence to justify any Windows updates.

==============================================================================
Question 3
==========

spnego_krb.cap
frame 7

Question / Comment:
-------------------
This was taken between a client running Windows XP SP3 and a server running
Windows Server 2003 SP2 (Enterprise Edition), using Kerberos over SPNEGO.
In this trace, the mechToken is a GSS InitialContextToken.

Response:
---------

   I agree totally; thank you for the detail.
   ThisMech: SpnegoToken (1.3.6.1.5.5.2) See 'Reference 3' ([RFC2743]) below.

   OID Repository - Home
   http://www.oid-info.com/
   iso(1) identified-organization(3) dod(6) internet(1) security(5)
   mechanisms(5) snego(2)
   Child OID:  modules(4)
   Ref: http://www.ietf.org/rfc/rfc2743.txt

   NtlmSsp: NTLM NEGOTIATE MESSAGE
   - this is indented, since NTLM is considered a separate protocol by Network
     Monitor 3.2. The InnerContextToken is from offset 0x7F - 0xBE. The
     negotiate message is encapsulated (offset 0x97 - 0xBE).

------------------------------------------------------------------------------
Capture Details (Network Monitor 3.2)

  - CSessionSetupAndXNTLMESS: 
     WordCount: 12 (0xC)
     ANDXCommand: No Secondary Command 255(0xFF)
     AndXReserved: 0 (0x0)
     ANDXOffset: 2772 (0xAD4)
     MaxBufferSize: 16644 (0x4104)
     MaxMpxCount: 50 (0x32)
     VcNumber: 0 (0x0)
     SessionKey: 0 (0x0)
     SecurityBlobLength: 2610 (0xA32)
     Reserved: 0 (0x0)
   + Capabilities: 0xA00000D4
     ByteCount: 2713 (0xA99)
   - SecurityBlob: 
    - GssApi: 
     + ApplicationHeader: 
     + ThisMech: SpnegoToken (1.3.6.1.5.5.2)
     - InnerContextToken: 0x1
      - SpnegoToken: 0x1
       + Tag0: 
       - NegTokenInit: 
        + SequenceHeader: 
        + Tag0: 
        + MechTypes: 
        + Tag2: 
        + OctetStringHeader: 
        - MechToken: 0x1
         + MsKerberosToken: 0x1
          - GssApi: 
           + ApplicationHeader: 
           + ThisMech: KerberosToken (1.2.840.113554.1.2.2)
           + InnerContextToken: 0x1


0070                 60 82 0A 2E 06 06 2B 06 01 05 05  GssApi:
0080  02
....
0081     A0 82 0A 22 30 82 0A 1E A0 24 30 22 06 09 2A  InnerContextToken:
0090  86 48 82 F7 12 01 02 02 06 09 2A 86 48 86 F7 12
00A0  01 02 02 06 0A 2B 06 01 04 01 82 37 02 02 0A A2
00B0  82 09 F4 04 82 09 F0
....
00B7                       60 82 09 EC 06 09 2A 86 48  MechToken: (MsKerberosToken:)
00C0  86 F7 12 01 02 02
00C6                    01 00 6E 82 09 DB 30 82 09 D7  InnerContextToken:
00D0  A0 03 02 01 05 A1 03 02 01 0E A2 07 03 05 00 20
....

Follow-up Question / Comment:
-----------------------------
Yes, there isn't really a question here.  I'm just demonstrating that when
Kerberos is negotiated, the SPNEGO mechToken is a GSS InitialContextToken.

==============================================================================
Question 4
==========

raw_ntlmssp.cap
frame 7

Question / Comment:
-------------------

Here's another trace of a Windows XP SP3 client sending raw NTLMSSP
(no SPNEGO) to a server.  This server is just a proxy in front of a Windows
Server 2003 machine, but I configured it to strip off the securit blob from
the server's NEGOTIATE response before sending it to the client.
This causes the client to send raw NTLMSSP instead of SPNEGO.

Based on the documentation in MS-SMB 2.2.4 and MS-SMB 3.2.4.2.3, I would
expect the client to send a GSS authentication token here (i.e., an
InitialContextToken).  However, in this case the client sends raw NTLMSSP
data.

A reasonable explanation for this would be that Microsoft's GSS-API
implementation accepts raw NTLMSSP data for the first token, in addition to
normal GSS InitialContextTokens.  I think this is what item <8> of MS-SPNG
Appendix A is trying to explain, but it mentions this as an extension of
SPNEGO, not GSS-API.  Assuming that this is a general extension that Microsoft
has made to their GSS-API implementation, this would also explain the lack of
the InitialContextToken for NTLMSSP when SPNEGO is used.

Response:
---------
   You are indeed correct - this, of course, per [MS-SPNG] <8>, is not
   GSS-API. Please see 'Reference 1 / Implicit NTLM' ([MS-SMB]) below
   for additional information.

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

   <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.

------------------------------------------------------------------------------
Capture Details (Network Monitor 3.2)

  - CSessionSetupAndXNTLMESS: 
     WordCount: 12 (0xC)
     ANDXCommand: No Secondary Command 255(0xFF)
     AndXReserved: 0 (0x0)
     ANDXOffset: 202 (0xCA)
     MaxBufferSize: 4356 (0x1104)
     MaxMpxCount: 50 (0x32)
     VcNumber: 0 (0x0)
     SessionKey: 0 (0x0)
     SecurityBlobLength: 40 (0x28)
     Reserved: 0 (0x0)
   + Capabilities: 0xA00000D4
      ExtenedSecurity:    (1... ...) Supports extended security exchange (CAP_EXTENDED_SECURITY)
     ByteCount: 143 (0x8F)
     SecurityBlob: 
   + UnicodeParameters: 
     ANDXPadding: Binary Large Object (2 Bytes)
- NtlmSSP: NTLM NEGOTIATE MESSAGE
    Signature: NTLMSSP
    MessageType: Negotiate Message (0x00000001)
  - NtlmsspNegotiateMessage: 
   + NegotiateFlags: 0xA2088207 (NTLM v2128-bit encryption, Always Sign)
   + WorkstationDomainHeader: Length: 0, Offset: 0
   + WorkstationNameHeader: Length: 0, Offset: 0
   + Version: Windows 5.1 Build 10250 NTLMSSPv15

0075              4E 54 4C 4D 53 53 50 00 01 00 00  SecurityBlob: (NtlmSSP: NTLM NEGOTIATE MESSAGE)
0080  00 07 82 08 A2 00 00 00 00 00 00 00 00 00 00
0090  00 00 00 00 00 00 05 01 28 0A 00 00 00 0F

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Question 4 Follow-up:
---------------------

Yes, I assumed this is the behavior that this section of the text was trying
to describe.  However, it's not clear to me how this is related to SPNEGO.

According to MS-SMB section 2.2.4 and MS-SMB 3.2.4.2.3, the security blob in
the SESSION_SETUP_ANDX request should be a GSS authentication token.
According to RFC 2743, the thisMech field of the GSS InitialContextToken
indicates which security mechanism has been selected by the client.
If the thisMech field is the SPNEGO OID (1.3.6.1.5.5.2), one would expect
SPNEGO to be in use.

However, in this case the security blob isn't a GSS InitialContextToken, and
doesn't include the SPNEGO OID.  It's therefore unclear to me why one would
assume that this is related to SPNEGO, and not just GSS-API in general.

Also, note that the Kerberos behavior described by this passage does not seem
like a Windows extension.  This seems to be normal behavior for a GSS-API
acceptor when the thisMech field is the Kerberos OID.

Response:

raw_ntlmssp.cap frame 7:

Microsoft's implementation does indeed accept raw NTLMSSP data (per Reference
A below) in the SecurityBlob in an SMB_COM_SESSION_SETUP_ANDX request packet.
This does not relate to SPNEGO negotiation, and was introduced in the NTLMv2
implementation on Windows NT 4 Service Pack 4. 

Kerberos support (under GSSAPI/SPNEGO) was, of course, introduced in
Windows 2000 (along with NTLMSSP; Reference A does not apply here).

Kerberos behavior (per Reference B below), is indeed Windows Behavior. Am I
correct that you are referring to the follow up to Question 1 (RFC 4178
section 3.2 (c))? If so, the Windows Behavior noted applies to 

Reference A:
   [MS-SMB] 3.2.4.2.3
   User Authentication / 'Implicit NTLM

Reference B:
[MS-SPNG]
   3.2.5.2 Universal Receiver
   <8>
   ...
   6 Appendix A: Windows Behavior
   <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.

Reference C:
[MS-SPNG]
   6 Appendix A: Windows Behavior
   <5> Section 3.1.5.2: Windows versions offer and accept two distinct OIDs
       as identifiers for the Kerberos authentication mechanism. The SPNEGO
       extensions consider both OIDs as equivalent and make no distinction
       between them.

       Windows 2000 incorrectly encoded the OID for the Kerberos protocol.
       Rather than the OID { iso(1) member-body(2) United States(840)
       mit(113554) infosys(1) gssapi(2) krb5(2) }, an implementation error
       truncated the values at 16 bits. Therefore, the OID became { iso(1)
       member-body(2) United States(840) ???(48018) infosys(1) gssapi(2) krb5
       (2) }. 48018 is not a known member under that OID branch; this is an
       error.

       Windows XP, Windows Server 2003, Windows Vista, and Windows Server
       2008 do not truncate the value, and they correctly offer and receive
       1.2.840.113554.1.2.2. For compatibility reasons, the erroneous value
       (1.2.840.48018.1.2.2) is still offered and accepted by systems that
       run Windows 2000. The presence of this value can be used to determine
       that the peer is a Windows 2000 implementation.

==============================================================================
Reference 1:
============

[MS-SMB] Server Message Block (SMB) Protocol Specification

2.2.4 SMB_COM_SESSION_SETUP_ANDX Client Request Extension
...
   SecurityBlob (variable): This field MUST be the authentication token sent
   to the server, as specified in section 3.2.4.2.3 and [RFC4178].

3.2.4.2.3 User Authentication
-----------------------------
...
Extended Security
-----------------

   If the CAP_EXTENDED_SECURITY bit in ServerCapabilities is set, the
   SMB_COM_SESSION_SETUP_ANDX command MUST be generated, as defined here.
   Otherwise, the client MUST generate the authentication portion, as
   described in section Implicit NTLM.

   The client MUST do one of the following:
   
   o Pass the GSSNegotiateToken (if valid) to the configured GSS
     authentication mechanism to obtain a GSS output token for the
     authentication protocol exchange.
    -OR-
   o Choose to ignore the GSSNegotiateToken received from the server, and give
     an empty input token to the configured GSS authentication protocol to
     obtain a GSS output token for the authentication protocol exchange.

     In either case, it initializes the GSS authentication protocol with the
     MutualAuth and Delegate options, which are specified in [MS-KILE] section
     3.2.1.1.<152>

   The client creates an SMB_COM_SESSION_SETUP_ANDX request (section 2.2.4)
   message. The client MUST set CAP_EXTENDED_SECURITY in the Capabilities
   field, SMB_FLAGS2_EXTENDED_SECURITY in the SMB header Flags2 field, the
   SecurityBlob field to the output token generated above, and the
   SecurityBlobLength to the token length. The Uid field in the SMB header
   MUST be set to 0.

Implicit NTLM
-------------

   If the CAP_EXTENDED_SECURITY bit in ServerCapabilities is not set, the
   SMB_COM_SESSION_SETUP_ANDX request MUST be generated, as defined here.
   This is not new to the extension, but is included for completeness.

   The server MUST construct an NTLM CHALLENGE_MESSAGE, as specified in
   [MS-NLMP]. The CHALLENGE_MESSAGE is used by the server to challenge the
   client to prove its identity. The following parameters MUST be set to the
   following values.

   o The Signature field is set to an 8-byte character array that MUST contain
     the ASCII string ('N', 'T', 'L', 'M', 'S', 'S', 'P', '\0').
...
   The client creates the appropriate AUTHENTICATE_MESSAGE to respond to the
   CHALLENGE_MESSAGE, as specified in [MS-NLMP].

   The client MUST build an SMB_COM_SESSION_SETUP_ANDX , as specified in
   [CIFS] section 4.1.2. The following fields MUST be set to these values:
   
   o The CaseSensitivePasswordLength field is set to the Length of the
     NtChallengeResponse from the AUTHENTICATE_MESSAGE.
   o The CaseSensitivePassword field is set to the value of the
     NtChallengeResponse field from the AUTHENTICATE_MESSAGE.
   o The CaseInsensitivePasswordLength field is set to the Length of the
     LmChallengeResponse from the AUTHENTICATE_MESSAGE.
   o The CaseInsensitivePassword field is set to the value of the
     LmChallengeResponse field from the AUTHENTICATE_MESSAGE.
   o The AccountName field is set to the value of the UserName field
     from the AUTHENTICATE_MESSAGE.
   o The PrimaryDomain field is set to the value of the DomainName field
     from the AUTHENTICATE_MESSAGE.

==============================================================================
Reference 2:
============

Generic Security Service Application Program Interface, Version 2
http://www.ietf.org/rfc/rfc2078.txt

1.1.4:  Mechanism Types
...
                                                       ... The OID
   representing the DASS MechType, for example, is 1.3.12.2.1011.7.5,
   and that of the Kerberos V5 mechanism, once advanced to the level of
   Proposed Standard, will be 1.2.840.113554.1.2.2.

3.1: Mechanism-Independent Token Format

...       InitialContextToken ::=
       -- option indication (delegation, etc.) indicated within
       -- mechanism-specific token
       [APPLICATION 0] IMPLICIT SEQUENCE {
               thisMech MechType,
               innerContextToken ANY DEFINED BY thisMech
                  -- contents mechanism-specific
                  -- ASN.1 structure not required
               }


==============================================================================
Reference 3:
============

Generic Security Service Application Program Interface Version 2, Update 1
http://www.ietf.org/rfc/rfc2743.txt

1.1.4:  Mechanism Types
...
   The OID representing the DASS ([RFC-1507]) MechType, for example, is
   1.3.12.2.1011.7.5, and that of the Kerberos V5 mechanism ([RFC-
   1964]), having been advanced to the level of Proposed Standard, is
   1.2.840.113554.1.2.2.

3.1: Mechanism-Independent Token Format

      InitialContextToken ::=
      -- option indication (delegation, etc.) indicated within
      -- mechanism-specific token
      [APPLICATION 0] IMPLICIT SEQUENCE {
              thisMech MechType,
              innerContextToken ANY DEFINED BY thisMech
                 -- contents mechanism-specific
                 -- ASN.1 structure not required
              }

      MechType ::= OBJECT IDENTIFIER

3.2.  Negotiation Tokens

   The syntax of the negotiation tokens follows the InitialContextToken
   syntax defined in [1]. The security mechanism of the initial
   negotiation token is identified by the Object Identifier
   iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2).

3.2.1. Syntax

   This section specifies the syntax of the corresponding
   "innerContextToken" field for the first token and subsequent
   negotiation tokens. During the mechanism negociation, the
   "innerContextToken" field contains the ASN.1 structure
   "NegociationToken" given below, encoded using the DER encoding
   conventions.

NegotiationToken ::= CHOICE {
                              negTokenInit  [0]  NegTokenInit,
                              negTokenTarg  [1]  NegTokenTarg }

MechTypeList ::= SEQUENCE OF MechType

NegTokenInit ::= SEQUENCE {
                            mechTypes       [0] MechTypeList  OPTIONAL,
                            reqFlags        [1] ContextFlags  OPTIONAL,
                            mechToken       [2] OCTET STRING  OPTIONAL,
                            mechListMIC     [3] OCTET STRING  OPTIONAL
                         }

==============================================================================
Reference 4:
============

The Simple and Protected GSS-API Negotiation Mechanism
http://www.ietf.org/rfc/rfc2478.txt

3.2.1. Syntax

1. ABSTRACT

   The Simple and Protected GSS-API Negotiation Mechanism defined here
   is a pseudo-security mechanism, represented by the object identifier
   iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2) which

3.1.  Mechanism Type

   MechType::= OBJECT IDENTIFIER

   mechType
        Each security mechanism is as defined in [1].

3.2.1. Syntax

NegotiationToken ::= CHOICE {
                              negTokenInit  [0]  NegTokenInit,
                              negTokenTarg  [1]  NegTokenTarg }

MechTypeList ::= SEQUENCE OF MechType

NegTokenInit ::= SEQUENCE {
                            mechTypes       [0] MechTypeList  OPTIONAL,
                            reqFlags        [1] ContextFlags  OPTIONAL,
                            mechToken       [2] OCTET STRING  OPTIONAL,
                            mechListMIC     [3] OCTET STRING  OPTIONAL
                         }

   [1] Linn, J., "Generic Security Service Application Program
       Interface", RFC 2078, January 1997.


==============================================================================
Reference 5:
============

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

3.2.  Negotiation Procedure
...
   c) The GSS-API initiator application sends the token to the target
      application.  The GSS-API target application passes the token by
      invoking GSS_Accept_sec_context().  The acceptor will do one of
      the following:

        I) If none of the proposed mechanisms are acceptable, the
           negotiation SHALL be terminated.  GSS_Accept_sec_context
           indicates GSS_S_BAD_MECH.  The acceptor MAY output a
           negotiation token containing a reject state.

       II) If either the initiator's preferred mechanism is not accepted
           by the target or this mechanism is accepted but is not the
           acceptor's most preferred mechanism (i.e., the MIC token
           exchange as described in Section 5 is required),
           GSS_Accept_sec_context() indicates GSS_S_CONTINUE_NEEDED.
           The acceptor MUST output a negotiation token containing a
           request-mic state.

==============================================================================
Reference 6:
============

Re: ThisMech: NtlmSsp (1.3.6.1.4.1.311.2.2.10)

Object IDs associated with Microsoft cryptography
http://support.microsoft.com/kb/287547

     CTL for Software Publishers Trusted CAs    1.3.6.1.4.1.311.2.2
     (sub-subtree is defined for Software Publishing trusted CAs)
        ...
        szOID_TRUSTED_CLIENT_AUTH_CA_LIST       1.3.6.1.4.1.311.2.2.2

[MS-SPNG]: Simple and Protected Generic Security Service Application Program
           Interface Negotiation Mechanism (SPNEGO) Protocol Extensions
...
Protocol Examples
http://msdn.microsoft.com/en-us/library/cc247074.aspx
...
The protocol variation is a single message addition, as specified in [RFC4178], so only a sample message can be shown.

NegTokenInit message, a constructed sequence, at byte offsets 0x10 through 0x3f
inclusive, is the following.

 [a0] [Context Specific 0]
   [30] Sequence
      [6] Object ID 1.2.840.48018.1.2.2
      [6] Object ID 1.2.840.113554.1.2.2
      [6] Object ID 1.2.840.113554.1.2.2.3
      [6] Object ID 1.3.6.1.4.1.311.2.2.10



More information about the cifs-protocol mailing list