Merge from HEAD:
authorAndrew Bartlett <abartlet@samba.org>
Tue, 28 Jan 2003 12:07:02 +0000 (12:07 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 28 Jan 2003 12:07:02 +0000 (12:07 +0000)
 - NTLMSSP over SPENGO (sesssion-setup-and-x) cleanup and code refactor.
  - also consequential changes to the NTLMSSP and SPNEGO parsing functions
  - and the client code that uses the same functions
 - Add ntlm_auth, a NTLMSSP authentication interface for use by applications
   like Squid and Apache.
  - also consquential changes to use common code for base64 encode/decode.
 - Winbind changes to support ntlm_auth (I don't want this program to need
   to read smb.conf, instead getting all it's details over the pipe).
 - nmbd changes for fstrcat() instead of fstrcpy().

Andrew Bartlett

14 files changed:
source/Makefile.in
source/auth/auth.c
source/include/asn_1.h
source/include/auth.h
source/include/ntlmssp.h
source/lib/util_str.c
source/libsmb/cliconnect.c
source/libsmb/clispnego.c
source/nmbd/nmbd_processlogon.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd_misc.c
source/nsswitch/winbindd_nss.h
source/smbd/sesssetup.c
source/web/cgi.c

index db9203e7cbe5b2f8ecb32cd0bbf9b522d3264c18..1c9f94efb141df97a212c2fb9a1937f340ccb41c 100644 (file)
@@ -111,7 +111,7 @@ BIN_PROGS1 = bin/smbclient@EXEEXT@ bin/net@EXEEXT@ bin/smbspool@EXEEXT@ \
 BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
        bin/nmblookup@EXEEXT@ bin/pdbedit@EXEEXT@
 BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
-       bin/profiles@EXEEXT@ bin/smbgroupedit@EXEEXT@
+       bin/profiles@EXEEXT@ bin/smbgroupedit@EXEEXT@ bin/ntlm_auth@EXEEXT@ \
 
 TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
        bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
@@ -186,7 +186,8 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
              libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
             libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
             libsmb/passchange.o libsmb/unexpected.o libsmb/doserr.o \
-            libsmb/namecache.o $(RPC_PARSE_OBJ1)
+            libsmb/namecache.o libsmb/ntlmssp.o \
+            $(RPC_PARSE_OBJ1)
 
 LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
@@ -256,7 +257,7 @@ UNIGRP_OBJ = libsmb/netlogon_unigrp.o
 
 AUTH_OBJ = auth/auth.o auth/auth_sam.o auth/auth_server.o auth/auth_domain.o \
           auth/auth_rhosts.o auth/auth_unix.o auth/auth_util.o auth/auth_winbind.o \
-          auth/auth_builtin.o auth/auth_compat.o \
+          auth/auth_builtin.o auth/auth_compat.o auth/auth_ntlmssp.o \
           $(PLAINTEXT_AUTH_OBJ) $(UNIGRP_OBJ)
 
 MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
@@ -539,6 +540,8 @@ POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
 
 TDBBACKUP_OBJ = tdb/tdbbackup.o $(TDBBASE_OBJ)
 
+NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSMB_OBJ) $(POPT_LIB_OBJ)
+
 ######################################################################
 # now the rules...
 ######################################################################
@@ -869,6 +872,12 @@ bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
        @$(LINK) -o $@ $(WBINFO_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
                $(UBIQX_OBJ) $(SECRETS_OBJ) $(LIBS) @BUILD_POPT@
 
+bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
+               $(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
+       @echo Linking $@
+       @$(LINK) -o $@ $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
+               $(UBIQX_OBJ) $(LIBS) @BUILD_POPT@
+
 bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
        @echo "Linking shared library $@"
        $(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) -lc
index 3c4448445ab98bab840cba57c46bbe6938c712ed..5d56603b9fd57092a6fa5d80fe598bc22e63b4f2 100644 (file)
@@ -57,7 +57,8 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
        TALLOC_CTX *mem_ctx;
 
        if (auth_context->challenge.length) {
-               DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge (normal)\n"));
+               DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", 
+                         auth_context->challenge_set_by));
                return auth_context->challenge.data;
        }
 
@@ -190,6 +191,12 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
 
        DEBUG(3, ("check_ntlm_password:  mapped user is: [%s]\\[%s]@[%s]\n", 
                  user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
+
+       if (auth_context->challenge.length != 8) {
+               DEBUG(0, ("check_ntlm_password:  Invalid challenge stored for this auth context - cannot continue\n"));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
        if (auth_context->challenge_set_by)
                DEBUG(10, ("check_ntlm_password: auth_context challenge created by %s\n",
                                        auth_context->challenge_set_by));
@@ -441,6 +448,7 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[
        }
        
        (*auth_context)->challenge = data_blob(chal, 8);
+       (*auth_context)->challenge_set_by = "fixed";
        return nt_status;
 }
 
index 7783ab4c2f66dbe61ccff212fc059568e652726b..9cd873c18a21484fb60738f35d8405db48f5f6c7 100644 (file)
@@ -55,4 +55,8 @@ typedef struct {
 #define OID_KERBEROS5_OLD "1 2 840 48018 1 2 2"
 #define OID_KERBEROS5 "1 2 840 113554 1 2 2"
 
+#define SPNGEO_NEG_RESULT_ACCEPT 0
+#define SPNGEO_NEG_RESULT_INCOMPLETE 1
+#define SPNGEO_NEG_RESULT_REJECT 2
+
 #endif /* _ASN_1_H */
index 846662d17c4cc848dab647c52f1da8f22672874a..e37f181082e2d152b85085b52c58c7e9cfb2c546 100644 (file)
@@ -149,4 +149,13 @@ struct auth_init_function_entry {
 
        auth_init_function init;
 };
+
+typedef struct auth_ntlmssp_state
+{
+       TALLOC_CTX *mem_ctx;
+       struct auth_context *auth_context;
+       struct auth_serversupplied_info *server_info;
+       struct ntlmssp_state *ntlmssp_state;
+} AUTH_NTLMSSP_STATE;
+
 #endif /* _SMBAUTH_H_ */
index 673be83532f820dfd69ce14404f82dd23799ec30..79d0446a77131d57506e416823d5c4c314e687af 100644 (file)
@@ -71,9 +71,20 @@ typedef struct ntlmssp_state
 {
        TALLOC_CTX *mem_ctx;
        enum NTLMSSP_ROLE role;
-       struct auth_context *auth_context;
-       struct auth_serversupplied_info *server_info;
        BOOL unicode;
-       char *orig_user;
-       char *orig_domain;
+       char *user;
+       char *domain;
+       char *workstation;
+       DATA_BLOB lm_resp;
+       DATA_BLOB nt_resp;
+       DATA_BLOB chal;
+       void *auth_context;
+       const uint8 *(*get_challenge)(struct ntlmssp_state *ntlmssp_state);
+       NTSTATUS (*check_password)(struct ntlmssp_state *ntlmssp_state);
+
+       const char *(*get_global_myname)(void);
+       const char *(*get_domain)(void);
+
+       int server_role;
 } NTLMSSP_STATE;
+
index 799bc64cc618ac4afb71296e7396e40d7b722c7e..2a9ee0a868e70606e89c41f2484489d233c75489 100644 (file)
@@ -1535,6 +1535,100 @@ void rfc1738_unescape(char *buf)
        }
 }
 
+static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/***************************************************************************
+decode a base64 string into a DATA_BLOB - simple and slow algorithm
+  ***************************************************************************/
+DATA_BLOB base64_decode_data_blob(const char *s)
+{
+       int bit_offset, byte_offset, idx, i, n;
+       DATA_BLOB decoded = data_blob(s, strlen(s)+1);
+       unsigned char *d = decoded.data;
+       char *p;
+
+       n=i=0;
+
+       while (*s && (p=strchr_m(b64,*s))) {
+               idx = (int)(p - b64);
+               byte_offset = (i*6)/8;
+               bit_offset = (i*6)%8;
+               d[byte_offset] &= ~((1<<(8-bit_offset))-1);
+               if (bit_offset < 3) {
+                       d[byte_offset] |= (idx << (2-bit_offset));
+                       n = byte_offset+1;
+               } else {
+                       d[byte_offset] |= (idx >> (bit_offset-2));
+                       d[byte_offset+1] = 0;
+                       d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
+                       n = byte_offset+2;
+               }
+               s++; i++;
+       }
+
+       /* fix up length */
+       decoded.length = n;
+       return decoded;
+}
+
+/***************************************************************************
+decode a base64 string in-place - wrapper for the above
+***************************************************************************/
+void base64_decode(char *s)
+{
+       DATA_BLOB decoded = base64_decode_data_blob(s);
+       memcpy(s, decoded.data, decoded.length);
+       data_blob_free(&decoded);
+
+       /* null terminate */
+       s[decoded.length] = '\0';
+}
+
+/***************************************************************************
+encode a base64 string into a malloc()ed string caller to free.
+
+From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
+***************************************************************************/
+char * base64_encode_data_blob(DATA_BLOB data)
+{
+       int bits = 0;
+       int char_count = 0;
+       size_t out_cnt = 0;
+       size_t len = data.length;
+       size_t output_len = data.length * 2;
+       char *result = malloc(output_len); /* get us plenty of space */
+
+       while (len-- && out_cnt < (data.length * 2) - 5) {
+               int c = (unsigned char) *(data.data++);
+               bits += c;
+               char_count++;
+               if (char_count == 3) {
+                       result[out_cnt++] = b64[bits >> 18];
+                       result[out_cnt++] = b64[(bits >> 12) & 0x3f];
+                       result[out_cnt++] = b64[(bits >> 6) & 0x3f];
+           result[out_cnt++] = b64[bits & 0x3f];
+           bits = 0;
+           char_count = 0;
+       } else {
+           bits <<= 8;
+       }
+    }
+    if (char_count != 0) {
+       bits <<= 16 - (8 * char_count);
+       result[out_cnt++] = b64[bits >> 18];
+       result[out_cnt++] = b64[(bits >> 12) & 0x3f];
+       if (char_count == 1) {
+           result[out_cnt++] = '=';
+           result[out_cnt++] = '=';
+       } else {
+           result[out_cnt++] = b64[(bits >> 6) & 0x3f];
+           result[out_cnt++] = '=';
+       }
+    }
+    result[out_cnt] = '\0';    /* terminate */
+    return result;
+}
+
 #ifdef VALGRIND
 size_t valgrind_strlen(const char *s)
 {
index b758af41c46e36393937e81210515b55c016c8a1..389b7a1733218222b0a3f1413bd20f6e567ee15c 100644 (file)
@@ -465,7 +465,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
 
        neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
                NTLMSSP_NEGOTIATE_128 | 
-               NTLMSSP_NEGOTIATE_NTLM;
+               NTLMSSP_NEGOTIATE_NTLM |
+               NTLMSSP_REQUEST_TARGET;
 
        memset(sess_key, 0, 16);
 
@@ -476,8 +477,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
                  "NTLMSSP",
                  NTLMSSP_NEGOTIATE,
                  neg_flags,
-                 workgroup, strlen(workgroup),
-                 cli->calling.name, strlen(cli->calling.name) + 1);
+                 workgroup, 
+                 cli->calling.name);
        DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
                  neg_flags, workgroup, cli->calling.name));
        /* and wrap it in a SPNEGO wrapper */
index 55f49c5987111af4c1e8f1f9eb1fda6691b1a2c0..3e28baa417c8abda8fccc0e5f5633b07fde825be 100644 (file)
@@ -386,51 +386,6 @@ BOOL spnego_parse_challenge(DATA_BLOB blob,
 }
 
 
-/*
-  generate a spnego NTLMSSP challenge packet given two security blobs
-  The second challenge is optional
-*/
-BOOL spnego_gen_challenge(DATA_BLOB *blob,
-                         DATA_BLOB *chal1, DATA_BLOB *chal2)
-{
-       ASN1_DATA data;
-
-       ZERO_STRUCT(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,1);
-       asn1_pop_tag(&data);
-
-       asn1_push_tag(&data,ASN1_CONTEXT(1));
-       asn1_write_OID(&data, OID_NTLMSSP);
-       asn1_pop_tag(&data);
-
-       asn1_push_tag(&data,ASN1_CONTEXT(2));
-       asn1_write_OctetString(&data, chal1->data, chal1->length);
-       asn1_pop_tag(&data);
-
-       /* the second challenge is optional (XP doesn't send it) */
-       if (chal2) {
-               asn1_push_tag(&data,ASN1_CONTEXT(3));
-               asn1_write_OctetString(&data, chal2->data, chal2->length);
-               asn1_pop_tag(&data);
-       }
-
-       asn1_pop_tag(&data);
-       asn1_pop_tag(&data);
-
-       if (data.has_error) {
-               return False;
-       }
-
-       *blob = data_blob(data.data, data.length);
-       asn1_free(&data);
-       return True;
-}
-
 /*
  generate a SPNEGO NTLMSSP auth packet. This will contain the encrypted passwords
 */
@@ -485,18 +440,37 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
 /*
   generate a minimal SPNEGO NTLMSSP response packet.  Doesn't contain much.
 */
-DATA_BLOB spnego_gen_auth_response(void)
+DATA_BLOB spnego_gen_auth_response(DATA_BLOB *ntlmssp_reply, NTSTATUS nt_status)
 {
        ASN1_DATA data;
        DATA_BLOB ret;
+       uint8 negResult;
 
-       memset(&data, 0, sizeof(data));
+       if (NT_STATUS_IS_OK(nt_status)) {
+               negResult = SPNGEO_NEG_RESULT_ACCEPT;
+       } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               negResult = SPNGEO_NEG_RESULT_INCOMPLETE; 
+       } else {
+               negResult = SPNGEO_NEG_RESULT_REJECT; 
+       }
+
+       ZERO_STRUCT(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_write_enumerated(&data, negResult);
        asn1_pop_tag(&data);
+       if (negResult == SPNGEO_NEG_RESULT_INCOMPLETE) {
+               asn1_push_tag(&data,ASN1_CONTEXT(1));
+               asn1_write_OID(&data, OID_NTLMSSP);
+               asn1_pop_tag(&data);
+               
+               asn1_push_tag(&data,ASN1_CONTEXT(2));
+               asn1_write_OctetString(&data, ntlmssp_reply->data, ntlmssp_reply->length);
+               asn1_pop_tag(&data);
+       }
+
        asn1_pop_tag(&data);
        asn1_pop_tag(&data);
 
@@ -514,8 +488,9 @@ DATA_BLOB spnego_gen_auth_response(void)
   format specifiers are:
 
   U = unicode string (input is unix string)
-  a = address (1 byte type, 1 byte length, unicode string, all inline)
-  A = ASCII string (pointer + length) Actually same as B
+  a = address (input is BOOL unicode, char *unix_string)
+      (1 byte type, 1 byte length, unicode/ASCII string, all inline)
+  A = ASCII string (input is unix string)
   B = data blob (pointer + length)
   b = data blob in header (pointer + length)
   D
@@ -531,6 +506,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
        uint8 *b;
        int head_size=0, data_size=0;
        int head_ofs, data_ofs;
+       BOOL unicode;
 
        /* first scan the format to work out the header and body size */
        va_start(ap, format);
@@ -541,12 +517,21 @@ BOOL msrpc_gen(DATA_BLOB *blob,
                        head_size += 8;
                        data_size += str_charnum(s) * 2;
                        break;
+               case 'A':
+                       s = va_arg(ap, char *);
+                       head_size += 8;
+                       data_size += str_ascii_charnum(s);
+                       break;
                case 'a':
+                       unicode = va_arg(ap, BOOL);
                        n = va_arg(ap, int);
                        s = va_arg(ap, char *);
-                       data_size += (str_charnum(s) * 2) + 4;
+                       if (unicode) {
+                               data_size += (str_charnum(s) * 2) + 4;
+                       } else {
+                               data_size += (str_ascii_charnum(s)) + 4;
+                       }
                        break;
-               case 'A':
                case 'B':
                        b = va_arg(ap, uint8 *);
                        head_size += 8;
@@ -586,20 +571,39 @@ 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':
+                       s = va_arg(ap, char *);
+                       n = str_ascii_charnum(s);
+                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+                       SSVAL(blob->data, head_ofs, n); head_ofs += 2;
+                       SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4;
+                       push_string(NULL, blob->data+data_ofs, s, n, STR_ASCII|STR_NOALIGN);
+                       data_ofs += n;
+                       break;
                case 'a':
+                       unicode = va_arg(ap, BOOL);
                        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);
+                       if (unicode) {
+                               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;
+                       } else {
+                               n = str_ascii_charnum(s);
+                               SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+                               if (0 < n) {
+                                       push_string(NULL, blob->data+data_ofs, s, n,
+                                                   STR_ASCII|STR_NOALIGN);
+                               }
+                               data_ofs += n;
                        }
-                       data_ofs += n*2;
                        break;
 
-               case 'A':
                case 'B':
                        b = va_arg(ap, uint8 *);
                        n = va_arg(ap, int);
@@ -714,7 +718,7 @@ BOOL msrpc_parse(DATA_BLOB *blob,
                        break;
                case 'C':
                        s = va_arg(ap, char *);
-                       head_ofs += pull_string(NULL, p, blob->data+head_ofs, -1
+                       head_ofs += pull_string(NULL, p, blob->data+head_ofs, sizeof(p)
                                                blob->length - head_ofs, 
                                                STR_ASCII|STR_TERMINATE);
                        if (strcmp(s, p) != 0) {
index 39724921a42cfc6fb605b130b403edae0ce67c55..a702fc30156cc99a76ec6aef2d0f1bb4877e22eb 100644 (file)
@@ -272,8 +272,8 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
       pull_ucs2_fstring(asccomp, unicomp);
       DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
 
-      fstrcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */
-      fstrcpy(reply_name+2,my_name); 
+      fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */
+      fstrcat(reply_name, my_name);
 
       DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
               asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(),
index e1bb7179e5befe7328aaf42f0a53495380358574..b70a4dd3b4039fda8b8989930f803cb626b1288e 100644 (file)
@@ -264,6 +264,7 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_INFO, winbindd_info, "INFO" },
        { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
        { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
+       { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
 
        /* WINS functions */
 
index 6b7ef382ddf5091ac62bcb26e4a186723ac2c6da..0b283812b2198fa6543ff33fd729af6d20c7397a 100644 (file)
@@ -221,3 +221,15 @@ enum winbindd_result winbindd_domain_name(struct winbindd_cli_state *state)
 
        return WINBINDD_OK;
 }
+
+/* What's my name again? */
+
+enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state)
+{
+
+       DEBUG(3, ("[%5d]: request netbios name\n", state->pid));
+       
+       fstrcpy(state->response.data.netbios_name, global_myname());
+
+       return WINBINDD_OK;
+}
index 5c2db2ac2c0ab3234675c0ac8297b1060d32cf8c..2c87a771009a8d93bd8e8019d517c964d5d6aafc 100644 (file)
@@ -36,7 +36,7 @@
 
 /* Update this when you change the interface.  */
 
-#define WINBIND_INTERFACE_VERSION 6
+#define WINBIND_INTERFACE_VERSION 7
 
 /* Socket commands */
 
@@ -102,6 +102,7 @@ enum winbindd_cmd {
        /* this is like GETGRENT but gives an empty group list */
        WINBINDD_GETGRLST,
 
+       WINBINDD_NETBIOS_NAME,       /* The netbios name of the server */
        /* Placeholder for end of cmd list */
 
        WINBINDD_NUM_CMDS
@@ -221,6 +222,7 @@ struct winbindd_response {
                        fstring samba_version;
                } info;
                fstring domain_name;
+               fstring netbios_name;
 
                struct auth_reply {
                        uint32 nt_status;
index f8e8e017e01975dc0761b28703f50336306daab3..679f040b2cb5d9f07d9b97a9ffb7baf724088bcc 100644 (file)
@@ -23,7 +23,8 @@
 #include "includes.h"
 
 uint32 global_client_caps = 0;
-static struct auth_context *ntlmssp_auth_context = NULL;
+
+static struct auth_ntlmssp_state *global_ntlmssp_state;
 
 /*
   on a logon error possibly map the error to success if "map to guest"
@@ -67,6 +68,37 @@ static void add_signature(char *outbuf)
        set_message_end(outbuf,p);
 }
 
+/****************************************************************************
+send a security blob via a session setup reply
+****************************************************************************/
+static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
+                                DATA_BLOB blob, NTSTATUS nt_status)
+{
+       char *p;
+
+       set_message(outbuf,4,0,True);
+
+       /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
+          that we aren't finished yet */
+
+       nt_status = nt_status_squash(nt_status);
+       SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
+       SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
+       SSVAL(outbuf, smb_vwv3, blob.length);
+       p = smb_buf(outbuf);
+
+       /* should we cap this? */
+       memcpy(p, blob.data, blob.length);
+       p += blob.length;
+
+       p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
+       p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
+       p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
+       set_message_end(outbuf,p);
+
+       return send_smb(smbd_server_fd(),outbuf);
+}
+
 /****************************************************************************
  Do a 'guest' logon, getting back the 
 ****************************************************************************/
@@ -209,30 +241,54 @@ 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, uint32 errcode)
+ send a session setup reply, wrapped in SPNEGO.
+ get vuid and check first.
+ end the NTLMSSP exchange context if we are OK/complete fail
+***************************************************************************/
+static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
+                                AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
+                                DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) 
 {
-       char *p;
+       BOOL ret;
+       DATA_BLOB response;
+       struct auth_serversupplied_info *server_info;
+       server_info = (*auth_ntlmssp_state)->server_info;
 
-       set_message(outbuf,4,0,True);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               nt_status = do_map_to_guest(nt_status, 
+                                           &server_info, 
+                                           (*auth_ntlmssp_state)->ntlmssp_state->user, 
+                                           (*auth_ntlmssp_state)->ntlmssp_state->domain);
+       }
 
-       /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
-          that we aren't finished yet */
+       if (NT_STATUS_IS_OK(nt_status)) {
+               int sess_vuid;
+               sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */);
+               
+               if (sess_vuid == -1) {
+                       nt_status = NT_STATUS_LOGON_FAILURE;
+               } else {
+                       
+                       set_message(outbuf,4,0,True);
+                       SSVAL(outbuf, smb_vwv3, 0);
+                       
+                       if ((*auth_ntlmssp_state)->server_info->guest) {
+                               SSVAL(outbuf,smb_vwv2,1);
+                       }
+                       
+                       SSVAL(outbuf,smb_uid,sess_vuid);
+               }
+       }
 
-       SIVAL(outbuf, smb_rcls, errcode);
-       SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
-       SSVAL(outbuf, smb_vwv3, blob.length);
-       p = smb_buf(outbuf);
-       memcpy(p, blob.data, blob.length);
-       p += blob.length;
-       p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
-       p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
-       p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
-       set_message_end(outbuf,p);
-       
-       return send_smb(smbd_server_fd(),outbuf);
+        response = spnego_gen_auth_response(ntlmssp_blob, nt_status);
+       ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
+       data_blob_free(&response);
+
+       if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               auth_ntlmssp_end(&global_ntlmssp_state);
+       }
+
+       return ret;
 }
 
 /****************************************************************************
@@ -247,12 +303,9 @@ static int reply_spnego_negotiate(connection_struct *conn,
        char *OIDs[ASN1_MAX_OIDS];
        DATA_BLOB secblob;
        int i;
-       uint32 ntlmssp_command, neg_flags, chal_flags;
-       DATA_BLOB chal, spnego_chal;
-       const uint8 *cryptkey;
+       DATA_BLOB chal;
        BOOL got_kerberos = False;
        NTSTATUS nt_status;
-       char *cliname=NULL, *domname=NULL;
 
        /* parse out the OIDs and the first sec blob */
        if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -278,95 +331,26 @@ static int reply_spnego_negotiate(connection_struct *conn,
        }
 #endif
 
-       /* parse the NTLMSSP packet */
-#if 0
-       file_save("secblob.dat", secblob.data, secblob.length);
-#endif
-
-       if (!msrpc_parse(&secblob, "CddAA",
-                        "NTLMSSP",
-                        &ntlmssp_command,
-                        &neg_flags,
-                        &cliname,
-                        &domname)) {
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
-       
-       data_blob_free(&secblob);
-
-       if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
-
-       debug_ntlmssp_flags(neg_flags);
-
-       if (ntlmssp_auth_context) {
-               (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
+       if (global_ntlmssp_state) {
+               auth_ntlmssp_end(&global_ntlmssp_state);
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
+       nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return ERROR_NT(nt_status);
        }
 
-       cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
-
-       /* Give them the challenge. For now, ignore neg_flags and just
-          return the flags we want. Obviously this is not correct */
-       
-       chal_flags = NTLMSSP_NEGOTIATE_UNICODE | 
-               NTLMSSP_NEGOTIATE_128 | 
-               NTLMSSP_NEGOTIATE_NTLM |
-               NTLMSSP_CHAL_TARGET_INFO;
-       
-       {
-               DATA_BLOB domain_blob, struct_blob;
-               fstring dnsname, dnsdomname;
-               
-               msrpc_gen(&domain_blob, 
-                         "U",
-                         lp_workgroup());
-
-               fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():"");
-               strlower(dnsdomname);
-
-               fstrcpy(dnsname, global_myname());
-               fstrcat(dnsname, ".");
-               fstrcat(dnsname, dnsdomname);
-               strlower(dnsname);
-
-               msrpc_gen(&struct_blob, "aaaaa",
-                         2, lp_workgroup(),
-                         1, global_myname(),
-                         4, dnsdomname,
-                         3, dnsname,
-                         0, "");
-
-               msrpc_gen(&chal, "CdUdbddB",
-                         "NTLMSSP", 
-                         NTLMSSP_CHALLENGE,
-                         lp_workgroup(),
-                         chal_flags,
-                         cryptkey, 8,
-                         0, 0,
-                         struct_blob.data, struct_blob.length);
-
-               data_blob_free(&domain_blob);
-               data_blob_free(&struct_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);
-       }
+       nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
+                                       secblob, &chal);
 
-       /* now tell the client to send the auth packet */
-       reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
+       data_blob_free(&secblob);
 
+       reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
+                            &chal, nt_status);
+               
        data_blob_free(&chal);
-       data_blob_free(&spnego_chal);
 
-       /* and tell smbd that we have already replied to this packet */
+       /* already replied */
        return -1;
 }
 
@@ -378,23 +362,8 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                             int length, int bufsize,
                             DATA_BLOB blob1)
 {
-       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);
-       uint32 ntlmssp_command, neg_flags;
+       DATA_BLOB auth, auth_reply;
        NTSTATUS nt_status;
-       int sess_vuid;
-       BOOL as_guest;
-       uint32 auth_flags = AUTH_FLAG_NONE;
-       auth_usersupplied_info *user_info = NULL;
-       auth_serversupplied_info *server_info = NULL;
-
-       /* we must have setup the auth context by now */
-       if (!ntlmssp_auth_context) {
-               DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
 
        if (!spnego_parse_auth(blob1, &auth)) {
 #if 0
@@ -403,157 +372,32 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
-       /* now the NTLMSSP encoded auth hashes */
-       if (!msrpc_parse(&auth, "CdBBUUUBd", 
-                        "NTLMSSP", 
-                        &ntlmssp_command, 
-                        &lmhash,
-                        &nthash,
-                        &workgroup, 
-                        &user, 
-                        &machine,
-                        &sess_key,
-                        &neg_flags)) {
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
+       nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
+                                         auth, &auth_reply);
 
        data_blob_free(&auth);
-       data_blob_free(&sess_key);
-       
-       DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
-                user, workgroup, machine, lmhash.length, nthash.length));
-
-       /* the client has given us its machine name (which we otherwise would not get on port 445).
-          we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
-
-       set_remote_machine_name(machine);
-
-       /* setup the string used by %U */
-       sub_set_smb_name(user);
-
-       reload_services(True);
-
-#if 0
-       file_save("nthash1.dat", nthash.data, nthash.length);
-       file_save("lmhash1.dat", lmhash.data, lmhash.length);
-#endif
-
-       if (lmhash.length) {
-               auth_flags |= AUTH_FLAG_LM_RESP;
-       }
-
-       if (nthash.length == 24) {
-               auth_flags |= AUTH_FLAG_NTLM_RESP;
-       } else if (nthash.length > 24) {
-               auth_flags |= AUTH_FLAG_NTLMv2_RESP;
-       };
-
-       nt_status = make_user_info_map(&user_info, user, workgroup, machine, 
-                                      lmhash, nthash, plaintext_password, 
-                                      auth_flags, True);
-
-       /* it looks a bit weird, but this function returns int type... */
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
-       }
-
-       nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); 
-
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
-       }
-
-       SAFE_FREE(workgroup);
-       SAFE_FREE(machine);
-                       
-       (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
-
-       free_user_info(&user_info);
-       
-       data_blob_free(&lmhash);
-       
-       data_blob_free(&nthash);
-
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               SAFE_FREE(user);
-               return ERROR_NT(nt_status_squash(nt_status));
-       }
-
-       as_guest = server_info->guest;
-
-       sess_vuid = register_vuid(server_info, user);
-       free_server_info(&server_info);
-
-       SAFE_FREE(user);
-  
-       if (sess_vuid == -1) {
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
-
-       set_message(outbuf,4,0,True);
-       SSVAL(outbuf, smb_vwv3, 0);
 
-       if (as_guest) {
-               SSVAL(outbuf,smb_vwv2,1);
-       }
-
-       add_signature(outbuf);
-       SSVAL(outbuf,smb_uid,sess_vuid);
-       SSVAL(inbuf,smb_uid,sess_vuid);
-
-        response = spnego_gen_auth_response();
-       reply_sesssetup_blob(conn, outbuf, response, 0);
+       reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
+                            &auth_reply, nt_status);
+               
+       data_blob_free(&auth_reply);
 
        /* and tell smbd that we have already replied to this packet */
        return -1;
 }
 
 
-/****************************************************************************
-reply to a session setup spnego anonymous packet
-****************************************************************************/
-static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
-                                 int length, int bufsize)
-{
-       int sess_vuid;
-       auth_serversupplied_info *server_info = NULL;
-       NTSTATUS nt_status;
-
-       nt_status = check_guest_password(&server_info);
-
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return ERROR_NT(nt_status_squash(nt_status));
-       }
-
-       sess_vuid = register_vuid(server_info, lp_guestaccount());
-
-       free_server_info(&server_info);
-  
-       if (sess_vuid == -1) {
-               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
-       }
-
-       set_message(outbuf,4,0,True);
-       SSVAL(outbuf, smb_vwv3, 0);
-       add_signature(outbuf);
-       SSVAL(outbuf,smb_uid,sess_vuid);
-       SSVAL(inbuf,smb_uid,sess_vuid);
-       
-       return chain_reply(inbuf,outbuf,length,bufsize);
-}
-
-
 /****************************************************************************
 reply to a session setup command
 ****************************************************************************/
-static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
+static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
+                                       char *outbuf,
                                        int length,int bufsize)
 {
        uint8 *p;
        DATA_BLOB blob1;
        int ret;
+       size_t bufrem;
 
        DEBUG(3,("Doing spnego session setup\n"));
 
@@ -564,12 +408,13 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha
        p = (uint8 *)smb_buf(inbuf);
 
        if (SVAL(inbuf, smb_vwv7) == 0) {
-               /* an anonymous request */
-               return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
+               /* an invalid request */
+               return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
+       bufrem = smb_bufrem(inbuf, p);
        /* pull the spnego blob */
-       blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
+       blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7)));
 
 #if 0
        file_save("negotiate.dat", blob1.data, blob1.length);
@@ -786,6 +631,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
                nt_status = check_guest_password(&server_info);
 
        } else if (doencrypt) {
+               if (!negprot_global_auth_context) {
+                       DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
+                       return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+               }
                nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
                                                         lm_resp, nt_resp);
                if (NT_STATUS_IS_OK(nt_status)) {
@@ -830,10 +679,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
        }
        
        /* it's ok - setup a reply */
-       if (Protocol < PROTOCOL_NT1) {
-               set_message(outbuf,3,0,True);
-       } else {
-               set_message(outbuf,3,0,True);
+       set_message(outbuf,3,0,True);
+       if (Protocol >= PROTOCOL_NT1) {
                add_signature(outbuf);
                /* perhaps grab OS version here?? */
        }
index 018dd3602fd37f1e287406144a33bc3c1bec2622..35f32662833fb28c204105a489a7f699b48d301c 100644 (file)
@@ -291,37 +291,6 @@ static void cgi_web_auth(void)
        passwd_free(&pwd);
 }
 
-/***************************************************************************
-decode a base64 string in-place - simple and slow algorithm
-  ***************************************************************************/
-static void base64_decode(char *s)
-{
-       const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-       int bit_offset, byte_offset, idx, i, n;
-       unsigned char *d = (unsigned char *)s;
-       char *p;
-
-       n=i=0;
-
-       while (*s && (p=strchr_m(b64,*s))) {
-               idx = (int)(p - b64);
-               byte_offset = (i*6)/8;
-               bit_offset = (i*6)%8;
-               d[byte_offset] &= ~((1<<(8-bit_offset))-1);
-               if (bit_offset < 3) {
-                       d[byte_offset] |= (idx << (2-bit_offset));
-                       n = byte_offset+1;
-               } else {
-                       d[byte_offset] |= (idx >> (bit_offset-2));
-                       d[byte_offset+1] = 0;
-                       d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
-                       n = byte_offset+2;
-               }
-               s++; i++;
-       }
-       /* null terminate */
-       d[n] = 0;
-}
 
 /***************************************************************************
 handle a http authentication line