Add support for NTLMv2 (tested!) with NTLMSSP.
authorAndrew Bartlett <abartlet@samba.org>
Sun, 26 May 2002 14:59:57 +0000 (14:59 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 26 May 2002 14:59:57 +0000 (14:59 +0000)
The problem was the NTLMv2 uses extra data in order to make reply/lookup
more difficult.  That extra data includes the hostname, and the domain.

This matches Win2k (sort of) by sending this information.

Win2k connects with LMCompatibilityLevel=5 without a problem.

We can change the negotiation bits if we want, this should allow us to make
NTLMv2 the default for other clients as well.

Some of the extra #defines were found in the squid source.

Andrew Bartlett
(This used to be commit 17a5f67b3d1935baf6197ae967624eb847b66ac8)

source3/include/rpc_dce.h
source3/libsmb/clispnego.c
source3/smbd/sesssetup.c

index 01d974d41dd78c7c7469acee81dd8fb95ab4662e..d46f9def39367bce473f5d79591acef6c3175c80 100644 (file)
@@ -61,15 +61,22 @@ enum NTLM_MESSAGE_TYPE
 #define NTLMSSP_REQUEST_TARGET             0x00000004
 #define NTLMSSP_NEGOTIATE_SIGN             0x00000010
 #define NTLMSSP_NEGOTIATE_SEAL             0x00000020
+#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE   0x00000040
 #define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
+#define NTLMSSP_NEGOTIATE_NETWARE          0x00000100
 #define NTLMSSP_NEGOTIATE_NTLM             0x00000200
-#define NTLMSSP_NEGOTIATE_00001000         0x00001000
-#define NTLMSSP_NEGOTIATE_00002000         0x00002000
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED  0x00001000
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
+#define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL  0x00004000
 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
+#define NTLMSSP_CHAL_INIT_RESPONSE         0x00010000
+#define NTLMSSP_CHAL_ACCEPT_RESPONSE       0x00020000
+#define NTLMSSP_CHAL_NON_NT_SESSION_KEY    0x00040000
 #define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
-#define NTLMSSP_NEGOTIATE_TARGET_INFO      0x00800000
+#define NTLMSSP_CHAL_TARGET_INFO           0x00800000
 #define NTLMSSP_NEGOTIATE_128              0x20000000
 #define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
+#define NTLMSSP_NEGOTIATE_080000000        0x80000000
 
 #define SMBD_NTLMSSP_NEG_FLAGS 0x000082b1
 
index a4fcfa5d9a98f34af549da1c85dd253f9bed0d65..469b946088c22a24819b48b841477f477a229bc3 100644 (file)
@@ -549,7 +549,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
 
   format specifiers are:
 
-  U = unicode string (input is unix string)
+  U = unicode string (output is unix string)
   B = data blob
   b = data blob in header
   d = word (4 bytes)
@@ -620,3 +620,44 @@ BOOL msrpc_parse(DATA_BLOB *blob,
 
        return True;
 }
+
+/**
+ * Print out the NTLMSSP flags for debugging 
+ */
+
+void debug_ntlmssp_flags(uint32 neg_flags)
+{
+       if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
+       if (neg_flags & NTLMSSP_REQUEST_TARGET) 
+               DEBUG(4, ("  NTLMSSP_REQUEST_TARGET\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
+       if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) 
+               DEBUG(4, ("  NTLMSSP_CHAL_TARGET_INFO\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_128) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_128\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 
+               DEBUG(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+}
+
index 66eb6a2d92b9e89e954fcda9117fb341589f8a06..cdddb37932985c164cf2305022c3b1684c29f3f3 100644 (file)
@@ -235,11 +235,13 @@ static int reply_spnego_negotiate(connection_struct *conn,
        char *OIDs[ASN1_MAX_OIDS];
        DATA_BLOB secblob;
        int i;
-       uint32 ntlmssp_command, neg_flags;
-       DATA_BLOB sess_key, chal, spnego_chal;
+       uint32 ntlmssp_command, neg_flags, chal_flags;
+       DATA_BLOB sess_key, chal, spnego_chal, extra_data;
+       char *workstation, *domain;
        const uint8 *cryptkey;
        BOOL got_kerberos = False;
        NTSTATUS nt_status;
+       extern pstring global_myname;
 
        /* parse out the OIDs and the first sec blob */
        if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -274,18 +276,23 @@ static int reply_spnego_negotiate(connection_struct *conn,
                         "NTLMSSP",
                         &ntlmssp_command,
                         &neg_flags,
-                        &sess_key)) {
+                        &extra_data)) {
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
+       
+       DEBUG(5, ("Extra data: \n"));
+       dump_data(5, extra_data.data, extra_data.length);
 
        data_blob_free(&secblob);
-       data_blob_free(&sess_key);
+       data_blob_free(&extra_data);
 
        if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
-       DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
+       DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags));
+
+       debug_ntlmssp_flags(neg_flags);
 
        if (ntlmssp_auth_context) {
                (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
@@ -300,22 +307,47 @@ static int reply_spnego_negotiate(connection_struct *conn,
        /* Give them the challenge. For now, ignore neg_flags and just
           return the flags we want. Obviously this is not correct */
        
-       neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
+       chal_flags = NTLMSSP_NEGOTIATE_UNICODE | 
                NTLMSSP_NEGOTIATE_LM_KEY | 
-               NTLMSSP_NEGOTIATE_NTLM;
-
-       msrpc_gen(&chal, "Cddddbdddd",
-                 "NTLMSSP", 
-                 NTLMSSP_CHALLENGE,
-                 0,
-                 0x30, /* ?? */
-                 neg_flags,
-                 cryptkey, 8,
-                 0, 0, 0,
-                 0x3000); /* ?? */
+               NTLMSSP_NEGOTIATE_NTLM |
+               NTLMSSP_CHAL_TARGET_INFO;
+       
+       {
+               DATA_BLOB domain_blob, netbios_blob, realm_blob, ident_info_blob;
+               
+               msrpc_gen(&domain_blob, 
+                         "U",
+                         lp_workgroup());
+
+               msrpc_gen(&netbios_blob, 
+                         "U",
+                         global_myname);
+               
+               msrpc_gen(&realm_blob, 
+                         "U",
+                         lp_realm());
+               
+
+               msrpc_gen(&chal, "CddddbBBBB",
+                         "NTLMSSP", 
+                         NTLMSSP_CHALLENGE,
+                         0,
+                         0x30, /* ?? */
+                         chal_flags,
+                         cryptkey, 8,
+                         domain_blob.data, domain_blob.length,
+                         domain_blob.data, domain_blob.length,
+                         netbios_blob.data, netbios_blob.length,
+                         realm_blob.data, realm_blob.length);
+
+               data_blob_free(&domain_blob);
+               data_blob_free(&netbios_blob);
+               data_blob_free(&realm_blob);
+       }
 
        if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
                DEBUG(3,("Failed to generate challenge\n"));
+               data_blob_free(&chal);
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }