Fix NTLMSSP challenge command and auth response. We can now service joins
authorJim McDonough <jmcd@samba.org>
Thu, 15 Aug 2002 12:18:25 +0000 (12:18 +0000)
committerJim McDonough <jmcd@samba.org>
Thu, 15 Aug 2002 12:18:25 +0000 (12:18 +0000)
from win2k AND still use SPNEGO (provided you don't build with kerberos...I
still have to fix that, as we are not properly falling back).
(This used to be commit 1f9b3d46c7c99e84b2983220f79613b7420c5ced)

source3/libsmb/clispnego.c
source3/smbd/sesssetup.c

index 469b946088c22a24819b48b841477f477a229bc3..16702c375b25d41c67b7ce7380ff15e8e3aca5bb 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    simple kerberos5/SPNEGO routines
    Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Jim McDonough   2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -439,6 +440,28 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
        return True;
 }
 
+/*
+  generate a minimal SPNEGO NTLMSSP response packet.  Doesn't contain much.
+*/
+DATA_BLOB spnego_gen_auth_response(void)
+{
+       ASN1_DATA data;
+       DATA_BLOB ret;
+
+       memset(&data, 0, sizeof(data));
+
+       asn1_push_tag(&data, ASN1_CONTEXT(1));
+       asn1_push_tag(&data, ASN1_SEQUENCE(0));
+       asn1_push_tag(&data, ASN1_CONTEXT(0));
+       asn1_write_enumerated(&data, 0);        
+       asn1_pop_tag(&data);
+       asn1_pop_tag(&data);
+       asn1_pop_tag(&data);
+
+       ret = data_blob(data.data, data.length);
+       asn1_free(&data);
+       return ret;
+}
 
 /*
   this is a tiny msrpc packet generator. I am only using this to
@@ -449,6 +472,7 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
   format specifiers are:
 
   U = unicode string (input is unix string)
+  a = address (1 byte type, 1 byte length, unicode string, all inline)
   B = data blob (pointer + length)
   b = data blob in header (pointer + length)
   d = word (4 bytes)
@@ -473,6 +497,11 @@ BOOL msrpc_gen(DATA_BLOB *blob,
                        head_size += 8;
                        data_size += str_charnum(s) * 2;
                        break;
+               case 'a':
+                       n = va_arg(ap, int);
+                       s = va_arg(ap, char *);
+                       data_size += (str_charnum(s) * 2) + 4;
+                       break;
                case 'B':
                        b = va_arg(ap, uint8 *);
                        head_size += 8;
@@ -512,6 +541,19 @@ BOOL msrpc_gen(DATA_BLOB *blob,
                        push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
                        data_ofs += n*2;
                        break;
+               case 'a':
+                       n = va_arg(ap, int);
+                       SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+                       s = va_arg(ap, char *);
+                       n = str_charnum(s);
+                       SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
+                       if (0 < n) {
+                               push_string(NULL, blob->data+data_ofs, s, n*2,
+                                           STR_UNICODE|STR_NOALIGN);
+                       }
+                       data_ofs += n*2;
+                       break;
+                       
                case 'B':
                        b = va_arg(ap, uint8 *);
                        n = va_arg(ap, int);
@@ -550,6 +592,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
   format specifiers are:
 
   U = unicode string (output is unix string)
+  A = ascii string
   B = data blob
   b = data blob in header
   d = word (4 bytes)
@@ -584,6 +627,24 @@ BOOL msrpc_parse(DATA_BLOB *blob,
                                    STR_UNICODE|STR_NOALIGN);
                        (*ps) = strdup(p);
                        break;
+               case 'A':
+                       len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+                       len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+                       ptr =  IVAL(blob->data, head_ofs); head_ofs += 4;
+
+                       /* make sure its in the right format - be strict */
+                       if (len1 != len2 || ptr + len1 > blob->length) {
+                               return False;
+                       }
+                       ps = va_arg(ap, char **);
+                       if (0 < len1) {
+                               pull_string(NULL, p, blob->data + ptr, -1, 
+                                           len1, STR_ASCII|STR_NOALIGN);
+                               (*ps) = strdup(p);
+                       } else {
+                               (*ps) = NULL;
+                       }
+                       break;
                case 'B':
                        len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
                        len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
index d45b04202e97f1a7e025281db2adf3768e792338..bb78129667cd3ed84e83b4af213362717bd7c07f 100644 (file)
@@ -3,6 +3,7 @@
    handle SMBsessionsetup
    Copyright (C) Andrew Tridgell 1998-2001
    Copyright (C) Andrew Bartlett      2001
+   Copyright (C) Jim McDonough        2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -206,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
 send a security blob via a session setup reply
 ****************************************************************************/
 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
-                                DATA_BLOB blob)
+                                DATA_BLOB blob, uint32 errcode)
 {
        char *p;
 
@@ -215,7 +216,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
        /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
           that we aren't finished yet */
 
-       SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
+       SIVAL(outbuf, smb_rcls, errcode);
        SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
        SSVAL(outbuf, smb_vwv3, blob.length);
        p = smb_buf(outbuf);
@@ -242,11 +243,12 @@ static int reply_spnego_negotiate(connection_struct *conn,
        DATA_BLOB secblob;
        int i;
        uint32 ntlmssp_command, neg_flags, chal_flags;
-       DATA_BLOB chal, spnego_chal, extra_data;
+       DATA_BLOB chal, spnego_chal;
        const uint8 *cryptkey;
        BOOL got_kerberos = False;
        NTSTATUS nt_status;
        extern pstring global_myname;
+       char *cliname=NULL, *domname=NULL;
 
        /* parse out the OIDs and the first sec blob */
        if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -277,19 +279,16 @@ static int reply_spnego_negotiate(connection_struct *conn,
        file_save("secblob.dat", secblob.data, secblob.length);
 #endif
 
-       if (!msrpc_parse(&secblob, "CddB",
+       if (!msrpc_parse(&secblob, "CddAA",
                         "NTLMSSP",
                         &ntlmssp_command,
                         &neg_flags,
-                        &extra_data)) {
+                        &cliname,
+                        &domname)) {
                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(&extra_data);
 
        if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
@@ -318,36 +317,39 @@ static int reply_spnego_negotiate(connection_struct *conn,
                NTLMSSP_CHAL_TARGET_INFO;
        
        {
-               DATA_BLOB domain_blob, netbios_blob, realm_blob;
+               DATA_BLOB domain_blob, struct_blob;
+               fstring dnsname, dnsdomname;
                
                msrpc_gen(&domain_blob, 
                          "U",
                          lp_workgroup());
 
-               msrpc_gen(&netbios_blob, 
-                         "U",
-                         global_myname);
-               
-               msrpc_gen(&realm_blob, 
-                         "U",
-                         lp_realm());
-               
+               fstrcpy(dnsdomname, lp_realm());
+               strlower(dnsdomname);
+
+               fstrcpy(dnsname, global_myname);
+               fstrcat(dnsname, ".");
+               fstrcat(dnsname, lp_realm());
+               strlower(dnsname);
+
+               msrpc_gen(&struct_blob, "aaaaa",
+                         2, lp_workgroup(),
+                         1, global_myname,
+                         4, dnsdomname,
+                         3, dnsname,
+                         0, NULL);
 
-               msrpc_gen(&chal, "CddddbBBBB",
+               msrpc_gen(&chal, "CdUdbddB",
                          "NTLMSSP", 
                          NTLMSSP_CHALLENGE,
-                         0,
-                         0x30, /* ?? */
+                         lp_workgroup(),
                          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);
+                         0, 0,
+                         struct_blob.data, struct_blob.length);
 
                data_blob_free(&domain_blob);
-               data_blob_free(&netbios_blob);
-               data_blob_free(&realm_blob);
+               data_blob_free(&struct_blob);
        }
 
        if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
@@ -357,7 +359,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
        }
 
        /* now tell the client to send the auth packet */
-       reply_sesssetup_blob(conn, outbuf, spnego_chal);
+       reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
 
        data_blob_free(&chal);
        data_blob_free(&spnego_chal);
@@ -374,7 +376,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                             int length, int bufsize,
                             DATA_BLOB blob1)
 {
-       DATA_BLOB auth;
+       DATA_BLOB auth, response;
        char *workgroup = NULL, *user = NULL, *machine = NULL;
        DATA_BLOB lmhash, nthash, sess_key;
        DATA_BLOB plaintext_password = data_blob(NULL, 0);
@@ -494,8 +496,12 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
  
        SSVAL(outbuf,smb_uid,sess_vuid);
        SSVAL(inbuf,smb_uid,sess_vuid);
-       
-       return chain_reply(inbuf,outbuf,length,bufsize);
+
+        response = spnego_gen_auth_response();
+       reply_sesssetup_blob(conn, outbuf, response, 0);
+
+       /* and tell smbd that we have already replied to this packet */
+       return -1;
 }