BUG 417: fix %UuGg variables expansion in include lines setging the current_user_info...
[samba.git] / source / smbd / sesssetup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 uint32 global_client_caps = 0;
27
28 static struct auth_ntlmssp_state *global_ntlmssp_state;
29
30 /*
31   on a logon error possibly map the error to success if "map to guest"
32   is set approriately
33 */
34 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
35                                 const char *user, const char *domain)
36 {
37         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
38                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
39                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
40                         DEBUG(3,("No such user %s [%s] - using guest account\n",
41                                  user, domain));
42                         status = make_server_info_guest(server_info);
43                 }
44         }
45
46         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
47                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
48                         DEBUG(3,("Registered username %s for guest access\n",user));
49                         status = make_server_info_guest(server_info);
50                 }
51         }
52
53         return status;
54 }
55
56 /****************************************************************************
57  Add the standard 'Samba' signature to the end of the session setup.
58 ****************************************************************************/
59
60 static int add_signature(char *outbuf, char *p)
61 {
62         char *start = p;
63         fstring lanman;
64
65         fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
66
67         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
68         p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
69         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
70
71         return PTR_DIFF(p, start);
72 }
73
74 /****************************************************************************
75  Send a security blob via a session setup reply.
76 ****************************************************************************/
77
78 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
79                                  DATA_BLOB blob, NTSTATUS nt_status)
80 {
81         char *p;
82
83         set_message(outbuf,4,0,True);
84
85         nt_status = nt_status_squash(nt_status);
86         SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
87         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
88         SSVAL(outbuf, smb_vwv3, blob.length);
89         p = smb_buf(outbuf);
90
91         /* should we cap this? */
92         memcpy(p, blob.data, blob.length);
93         p += blob.length;
94
95         p += add_signature( outbuf, p );
96
97         set_message_end(outbuf,p);
98
99         return send_smb(smbd_server_fd(),outbuf);
100 }
101
102 /****************************************************************************
103  Do a 'guest' logon, getting back the 
104 ****************************************************************************/
105
106 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
107 {
108         struct auth_context *auth_context;
109         auth_usersupplied_info *user_info = NULL;
110         
111         NTSTATUS nt_status;
112         unsigned char chal[8];
113
114         ZERO_STRUCT(chal);
115
116         DEBUG(3,("Got anonymous request\n"));
117
118         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
119                 return nt_status;
120         }
121
122         if (!make_user_info_guest(&user_info)) {
123                 (auth_context->free)(&auth_context);
124                 return NT_STATUS_NO_MEMORY;
125         }
126         
127         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
128         (auth_context->free)(&auth_context);
129         free_user_info(&user_info);
130         return nt_status;
131 }
132
133
134 #ifdef HAVE_KRB5
135 /****************************************************************************
136 reply to a session setup spnego negotiate packet for kerberos
137 ****************************************************************************/
138 static int reply_spnego_kerberos(connection_struct *conn, 
139                                  char *inbuf, char *outbuf,
140                                  int length, int bufsize,
141                                  DATA_BLOB *secblob)
142 {
143         DATA_BLOB ticket;
144         char *client, *p, *domain;
145         fstring netbios_domain_name;
146         struct passwd *pw;
147         char *user;
148         int sess_vuid;
149         NTSTATUS ret;
150         DATA_BLOB auth_data;
151         DATA_BLOB ap_rep, ap_rep_wrapped, response;
152         auth_serversupplied_info *server_info = NULL;
153         DATA_BLOB session_key;
154         uint8 tok_id[2];
155         BOOL foreign = False;
156         DATA_BLOB nullblob = data_blob(NULL, 0);
157         fstring real_username;
158
159         ZERO_STRUCT(ticket);
160         ZERO_STRUCT(auth_data);
161         ZERO_STRUCT(ap_rep);
162         ZERO_STRUCT(ap_rep_wrapped);
163         ZERO_STRUCT(response);
164
165         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
166                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
167         }
168
169         ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
170
171         data_blob_free(&ticket);
172
173         if (!NT_STATUS_IS_OK(ret)) {
174                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
175                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
176         }
177
178         data_blob_free(&auth_data);
179
180         DEBUG(3,("Ticket name is [%s]\n", client));
181
182         p = strchr_m(client, '@');
183         if (!p) {
184                 DEBUG(3,("Doesn't look like a valid principal\n"));
185                 data_blob_free(&ap_rep);
186                 SAFE_FREE(client);
187                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
188         }
189
190         *p = 0;
191         if (!strequal(p+1, lp_realm())) {
192                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
193                 if (!lp_allow_trusted_domains()) {
194                         data_blob_free(&ap_rep);
195                         SAFE_FREE(client);
196                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
197                 }
198                 foreign = True;
199         }
200
201         /* this gives a fully qualified user name (ie. with full realm).
202            that leads to very long usernames, but what else can we do? */
203
204         domain = p+1;
205
206         {
207                 /* If we have winbind running, we can (and must) shorten the
208                    username by using the short netbios name. Otherwise we will
209                    have inconsistent user names. With Kerberos, we get the
210                    fully qualified realm, with ntlmssp we get the short
211                    name. And even w2k3 does use ntlmssp if you for example
212                    connect to an ip address. */
213
214                 struct winbindd_request wb_request;
215                 struct winbindd_response wb_response;
216                 NSS_STATUS wb_result;
217
218                 ZERO_STRUCT(wb_request);
219                 ZERO_STRUCT(wb_response);
220
221                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
222
223                 fstrcpy(wb_request.domain_name, domain);
224
225                 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
226                                              &wb_request, &wb_response);
227
228                 if (wb_result == NSS_STATUS_SUCCESS) {
229
230                         fstrcpy(netbios_domain_name,
231                                 wb_response.data.domain_info.name);
232                         domain = netbios_domain_name;
233
234                         DEBUG(10, ("Mapped to [%s]\n", domain));
235                 } else {
236                         DEBUG(3, ("Could not find short name -- winbind "
237                                   "not running?\n"));
238                 }
239         }
240
241         asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
242         
243         /* lookup the passwd struct, create a new user if necessary */
244
245         pw = smb_getpwnam( user, real_username, True );
246         
247         if (!pw) {
248                 DEBUG(1,("Username %s is invalid on this system\n",user));
249                 SAFE_FREE(user);
250                 SAFE_FREE(client);
251                 data_blob_free(&ap_rep);
252                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
253         }
254
255         /* setup the string used by %U */
256         
257         sub_set_smb_name( real_username );
258         reload_services(True);
259         
260         if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) 
261         {
262                 DEBUG(1,("make_server_info_from_pw failed!\n"));
263                 SAFE_FREE(user);
264                 SAFE_FREE(client);
265                 data_blob_free(&ap_rep);
266                 return ERROR_NT(ret);
267         }
268
269         /* make_server_info_pw does not set the domain. Without this we end up
270          * with the local netbios name in substitutions for %D. */
271
272         if (server_info->sam_account != NULL) {
273                 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
274         }
275
276         /* register_vuid keeps the server info */
277         sess_vuid = register_vuid(server_info, session_key, nullblob, client);
278
279         SAFE_FREE(user);
280         SAFE_FREE(client);
281
282         if (sess_vuid == -1) {
283                 ret = NT_STATUS_LOGON_FAILURE;
284         } else {
285                 /* current_user_info is changed on new vuid */
286                 reload_services( True );
287
288                 set_message(outbuf,4,0,True);
289                 SSVAL(outbuf, smb_vwv3, 0);
290                         
291                 if (server_info->guest) {
292                         SSVAL(outbuf,smb_vwv2,1);
293                 }
294                 
295                 SSVAL(outbuf, smb_uid, sess_vuid);
296
297                 if (!server_info->guest) {
298                         /* We need to start the signing engine
299                          * here but a W2K client sends the old
300                          * "BSRSPYL " signature instead of the
301                          * correct one. Subsequent packets will
302                          * be correct.
303                          */
304                         srv_check_sign_mac(inbuf);
305                 }
306         }
307
308         /* wrap that up in a nice GSS-API wrapping */
309         if (NT_STATUS_IS_OK(ret)) {
310                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
311         } else {
312                 ap_rep_wrapped = data_blob(NULL, 0);
313         }
314         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
315         reply_sesssetup_blob(conn, outbuf, response, ret);
316
317         data_blob_free(&ap_rep);
318         data_blob_free(&ap_rep_wrapped);
319         data_blob_free(&response);
320
321         return -1; /* already replied */
322 }
323 #endif
324
325 /****************************************************************************
326  Send a session setup reply, wrapped in SPNEGO.
327  Get vuid and check first.
328  End the NTLMSSP exchange context if we are OK/complete fail
329 ***************************************************************************/
330
331 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
332                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
333                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) 
334 {
335         BOOL ret;
336         DATA_BLOB response;
337         struct auth_serversupplied_info *server_info = NULL;
338
339         if (NT_STATUS_IS_OK(nt_status)) {
340                 server_info = (*auth_ntlmssp_state)->server_info;
341         } else {
342                 nt_status = do_map_to_guest(nt_status, 
343                                             &server_info, 
344                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
345                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
346         }
347
348         if (NT_STATUS_IS_OK(nt_status)) {
349                 int sess_vuid;
350                 DATA_BLOB nullblob = data_blob(NULL, 0);
351                 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
352
353                 /* register_vuid keeps the server info */
354                 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
355                 (*auth_ntlmssp_state)->server_info = NULL;
356
357                 if (sess_vuid == -1) {
358                         nt_status = NT_STATUS_LOGON_FAILURE;
359                 } else {
360                         
361                         /* current_user_info is changed on new vuid */
362                         reload_services( True );
363
364                         set_message(outbuf,4,0,True);
365                         SSVAL(outbuf, smb_vwv3, 0);
366                         
367                         if (server_info->guest) {
368                                 SSVAL(outbuf,smb_vwv2,1);
369                         }
370                         
371                         SSVAL(outbuf,smb_uid,sess_vuid);
372
373                         if (!server_info->guest) {
374                                 /* We need to start the signing engine
375                                  * here but a W2K client sends the old
376                                  * "BSRSPYL " signature instead of the
377                                  * correct one. Subsequent packets will
378                                  * be correct.
379                                  */
380                                 srv_check_sign_mac(inbuf);
381                         }
382                 }
383         }
384
385         response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
386         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
387         data_blob_free(&response);
388
389         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
390            and the other end, that we are not finished yet. */
391
392         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
393                 auth_ntlmssp_end(auth_ntlmssp_state);
394         }
395
396         return ret;
397 }
398
399 /****************************************************************************
400  Reply to a session setup spnego negotiate packet.
401 ****************************************************************************/
402
403 static int reply_spnego_negotiate(connection_struct *conn, 
404                                   char *inbuf,
405                                   char *outbuf,
406                                   int length, int bufsize,
407                                   DATA_BLOB blob1)
408 {
409         char *OIDs[ASN1_MAX_OIDS];
410         DATA_BLOB secblob;
411         int i;
412         DATA_BLOB chal;
413         BOOL got_kerberos = False;
414         NTSTATUS nt_status;
415
416         /* parse out the OIDs and the first sec blob */
417         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
418                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
419         }
420
421         /* only look at the first OID for determining the mechToken --
422            accoirding to RFC2478, we should choose the one we want 
423            and renegotiate, but i smell a client bug here..  
424            
425            Problem observed when connecting to a member (samba box) 
426            of an AD domain as a user in a Samba domain.  Samba member 
427            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 
428            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 
429            NTLMSSP mechtoken.                 --jerry              */
430         
431         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
432             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
433                 got_kerberos = True;
434         }
435                 
436         for (i=0;OIDs[i];i++) {
437                 DEBUG(3,("Got OID %s\n", OIDs[i]));
438                 free(OIDs[i]);
439         }
440         DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
441
442 #ifdef HAVE_KRB5
443         if (got_kerberos && (SEC_ADS == lp_security())) {
444                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
445                                                 length, bufsize, &secblob);
446                 data_blob_free(&secblob);
447                 return ret;
448         }
449 #endif
450
451         if (global_ntlmssp_state) {
452                 auth_ntlmssp_end(&global_ntlmssp_state);
453         }
454
455         nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
456         if (!NT_STATUS_IS_OK(nt_status)) {
457                 return ERROR_NT(nt_status);
458         }
459
460         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
461                                         secblob, &chal);
462
463         data_blob_free(&secblob);
464
465         reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
466                              &chal, nt_status);
467                 
468         data_blob_free(&chal);
469
470         /* already replied */
471         return -1;
472 }
473         
474 /****************************************************************************
475  Reply to a session setup spnego auth packet.
476 ****************************************************************************/
477
478 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
479                              int length, int bufsize,
480                              DATA_BLOB blob1)
481 {
482         DATA_BLOB auth, auth_reply;
483         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
484
485         if (!spnego_parse_auth(blob1, &auth)) {
486 #if 0
487                 file_save("auth.dat", blob1.data, blob1.length);
488 #endif
489                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
490         }
491         
492         if (!global_ntlmssp_state) {
493                 /* auth before negotiatiate? */
494                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
495         }
496         
497         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
498                                                 auth, &auth_reply);
499
500         data_blob_free(&auth);
501
502         reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
503                              &auth_reply, nt_status);
504                 
505         data_blob_free(&auth_reply);
506
507         /* and tell smbd that we have already replied to this packet */
508         return -1;
509 }
510
511 /****************************************************************************
512  Reply to a session setup command.
513 ****************************************************************************/
514
515 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
516                                         char *outbuf,
517                                         int length,int bufsize)
518 {
519         uint8 *p;
520         DATA_BLOB blob1;
521         int ret;
522         size_t bufrem;
523         fstring native_os, native_lanman, primary_domain;
524         char *p2;
525         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
526         enum remote_arch_types ra_type = get_remote_arch();
527
528         DEBUG(3,("Doing spnego session setup\n"));
529
530         if (global_client_caps == 0) {
531                 global_client_caps = IVAL(inbuf,smb_vwv10);
532
533                 if (!(global_client_caps & CAP_STATUS32)) {
534                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
535                 }
536
537         }
538                 
539         p = (uint8 *)smb_buf(inbuf);
540
541         if (data_blob_len == 0) {
542                 /* an invalid request */
543                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
544         }
545
546         bufrem = smb_bufrem(inbuf, p);
547         /* pull the spnego blob */
548         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
549
550 #if 0
551         file_save("negotiate.dat", blob1.data, blob1.length);
552 #endif
553
554         p2 = inbuf + smb_vwv13 + data_blob_len;
555         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
556         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
557         p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
558         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
559                 native_os, native_lanman, primary_domain));
560
561         if ( ra_type == RA_WIN2K ) {
562                 /* Windows 2003 doesn't set the native lanman string, 
563                    but does set primary domain which is a bug I think */
564                            
565                 if ( !strlen(native_lanman) )
566                         ra_lanman_string( primary_domain );
567                 else
568                         ra_lanman_string( native_lanman );
569         }
570                 
571         if (blob1.data[0] == ASN1_APPLICATION(0)) {
572                 /* its a negTokenTarg packet */
573                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
574                 data_blob_free(&blob1);
575                 return ret;
576         }
577
578         if (blob1.data[0] == ASN1_CONTEXT(1)) {
579                 /* its a auth packet */
580                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
581                 data_blob_free(&blob1);
582                 return ret;
583         }
584
585         /* what sort of packet is this? */
586         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
587
588         data_blob_free(&blob1);
589
590         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
591 }
592
593 /****************************************************************************
594  On new VC == 0, shutdown *all* old connections and users.
595  It seems that only NT4.x does this. At W2K and above (XP etc.).
596  a new session setup with VC==0 is ignored.
597 ****************************************************************************/
598
599 static void setup_new_vc_session(void)
600 {
601         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
602 #if 0
603         conn_close_all();
604         invalidate_all_vuids();
605 #endif
606 }
607
608 /****************************************************************************
609  Reply to a session setup command.
610 ****************************************************************************/
611
612 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
613                           int length,int bufsize)
614 {
615         int sess_vuid;
616         int   smb_bufsize;    
617         DATA_BLOB lm_resp;
618         DATA_BLOB nt_resp;
619         DATA_BLOB plaintext_password;
620         fstring user;
621         fstring sub_user; /* Sainitised username for substituion */
622         fstring domain;
623         fstring native_os;
624         fstring native_lanman;
625         fstring primary_domain;
626         static BOOL done_sesssetup = False;
627         extern BOOL global_encrypted_passwords_negotiated;
628         extern BOOL global_spnego_negotiated;
629         extern int Protocol;
630         extern int max_send;
631
632         auth_usersupplied_info *user_info = NULL;
633         extern struct auth_context *negprot_global_auth_context;
634         auth_serversupplied_info *server_info = NULL;
635
636         NTSTATUS nt_status;
637
638         BOOL doencrypt = global_encrypted_passwords_negotiated;
639
640         DATA_BLOB session_key;
641         
642         START_PROFILE(SMBsesssetupX);
643
644         ZERO_STRUCT(lm_resp);
645         ZERO_STRUCT(nt_resp);
646         ZERO_STRUCT(plaintext_password);
647
648         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
649
650         /* a SPNEGO session setup has 12 command words, whereas a normal
651            NT1 session setup has 13. See the cifs spec. */
652         if (CVAL(inbuf, smb_wct) == 12 &&
653             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
654                 if (!global_spnego_negotiated) {
655                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
656                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
657                 }
658
659                 if (SVAL(inbuf,smb_vwv4) == 0) {
660                         setup_new_vc_session();
661                 }
662                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
663         }
664
665         smb_bufsize = SVAL(inbuf,smb_vwv2);
666
667         if (Protocol < PROTOCOL_NT1) {
668                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
669                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
670                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
671                 }
672
673                 if (doencrypt) {
674                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
675                 } else {
676                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
677                         /* Ensure null termination */
678                         plaintext_password.data[passlen1] = 0;
679                 }
680
681                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
682                 *domain = 0;
683
684         } else {
685                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
686                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
687                 enum remote_arch_types ra_type = get_remote_arch();
688                 char *p = smb_buf(inbuf);    
689                 char *save_p = smb_buf(inbuf);
690                 uint16 byte_count;
691                         
692
693                 if(global_client_caps == 0) {
694                         global_client_caps = IVAL(inbuf,smb_vwv11);
695                 
696                         if (!(global_client_caps & CAP_STATUS32)) {
697                                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
698                         }
699
700                         /* client_caps is used as final determination if client is NT or Win95. 
701                            This is needed to return the correct error codes in some
702                            circumstances.
703                         */
704                 
705                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
706                                 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
707                                         set_remote_arch( RA_WIN95);
708                                 }
709                         }
710                 }
711
712                 if (!doencrypt) {
713                         /* both Win95 and WinNT stuff up the password lengths for
714                            non-encrypting systems. Uggh. 
715                            
716                            if passlen1==24 its a win95 system, and its setting the
717                            password length incorrectly. Luckily it still works with the
718                            default code because Win95 will null terminate the password
719                            anyway 
720                            
721                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
722                            setting passlen2 to some random value which really stuffs
723                            things up. we need to fix that one.  */
724                         
725                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
726                                 passlen2 = 0;
727                 }
728                 
729                 /* check for nasty tricks */
730                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
731                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
732                 }
733
734                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
735                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
736                 }
737
738                 /* Save the lanman2 password and the NT md4 password. */
739                 
740                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
741                         doencrypt = False;
742                 }
743
744                 if (doencrypt) {
745                         lm_resp = data_blob(p, passlen1);
746                         nt_resp = data_blob(p+passlen1, passlen2);
747                 } else {
748                         pstring pass;
749                         BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
750
751                         if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
752                                 /* NT4.0 stuffs up plaintext unicode password lengths... */
753                                 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
754                                         sizeof(pass), passlen1, STR_TERMINATE);
755                         } else {
756                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), 
757                                         sizeof(pass),  unic ? passlen2 : passlen1, 
758                                         STR_TERMINATE);
759                         }
760                         plaintext_password = data_blob(pass, strlen(pass)+1);
761                 }
762                 
763                 p += passlen1 + passlen2;
764                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
765                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
766                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
767                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
768
769                 /* not documented or decoded by Ethereal but there is one more string 
770                    in the extra bytes which is the same as the PrimaryDomain when using 
771                    extended security.  Windows NT 4 and 2003 use this string to store 
772                    the native lanman string. Windows 9x does not include a string here 
773                    at all so we have to check if we have any extra bytes left */
774                 
775                 byte_count = SVAL(inbuf, smb_vwv13);
776                 if ( PTR_DIFF(p, save_p) < byte_count)
777                         p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
778                 else 
779                         fstrcpy( primary_domain, "null" );
780
781                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
782                          domain, native_os, native_lanman, primary_domain));
783
784                 if ( ra_type == RA_WIN2K ) {
785                         if ( strlen(native_lanman) == 0 )
786                                 ra_lanman_string( primary_domain );
787                         else
788                                 ra_lanman_string( native_lanman );
789                 }
790
791         }
792
793         if (SVAL(inbuf,smb_vwv4) == 0) {
794                 setup_new_vc_session();
795         }
796
797         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
798
799         if (*user) {
800                 if (global_spnego_negotiated) {
801                         
802                         /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
803                         
804                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
805                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
806                 }
807                 fstrcpy(sub_user, user);
808
809                 /* setup the string used by %U */
810                 sub_set_smb_name(user);
811         } else {
812                 fstrcpy(sub_user, lp_guestaccount());
813         }
814
815         sub_set_smb_name(sub_user);
816
817         reload_services(True);
818         
819         if (lp_security() == SEC_SHARE) {
820                 /* in share level we should ignore any passwords */
821
822                 data_blob_free(&lm_resp);
823                 data_blob_free(&nt_resp);
824                 data_blob_clear_free(&plaintext_password);
825
826                 map_username(sub_user);
827                 add_session_user(sub_user);
828                 /* Then force it to null for the benfit of the code below */
829                 *user = 0;
830         }
831         
832         if (!*user) {
833
834                 nt_status = check_guest_password(&server_info);
835
836         } else if (doencrypt) {
837                 if (!negprot_global_auth_context) {
838                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
839                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
840                 }
841                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
842                                                          lm_resp, nt_resp);
843                 if (NT_STATUS_IS_OK(nt_status)) {
844                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
845                                                                                      user_info, 
846                                                                                      &server_info);
847                 }
848         } else {
849                 struct auth_context *plaintext_auth_context = NULL;
850                 const uint8 *chal;
851                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
852                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
853                         
854                         if (!make_user_info_for_reply(&user_info, 
855                                                       user, domain, chal,
856                                                       plaintext_password)) {
857                                 nt_status = NT_STATUS_NO_MEMORY;
858                         }
859                 
860                         if (NT_STATUS_IS_OK(nt_status)) {
861                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
862                                                                                         user_info, 
863                                                                                         &server_info); 
864                                 
865                                 (plaintext_auth_context->free)(&plaintext_auth_context);
866                         }
867                 }
868         }
869
870         free_user_info(&user_info);
871         
872         if (!NT_STATUS_IS_OK(nt_status)) {
873                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
874         }
875         
876         if (!NT_STATUS_IS_OK(nt_status)) {
877                 data_blob_free(&nt_resp);
878                 data_blob_free(&lm_resp);
879                 data_blob_clear_free(&plaintext_password);
880                 return ERROR_NT(nt_status_squash(nt_status));
881         }
882
883         if (server_info->nt_session_key.data) {
884                 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
885         } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
886                 session_key = data_blob(NULL, 16);
887                 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, 
888                                    session_key.data);
889         } else {
890                 session_key = data_blob(NULL, 0);
891         }
892
893         data_blob_free(&lm_resp);
894         data_blob_clear_free(&plaintext_password);
895         
896         /* it's ok - setup a reply */
897         set_message(outbuf,3,0,True);
898         if (Protocol >= PROTOCOL_NT1) {
899                 char *p = smb_buf( outbuf );
900                 p += add_signature( outbuf, p );
901                 set_message_end( outbuf, p );
902                 /* perhaps grab OS version here?? */
903         }
904         
905         if (server_info->guest) {
906                 SSVAL(outbuf,smb_vwv2,1);
907         }
908
909         /* register the name and uid as being validated, so further connections
910            to a uid can get through without a password, on the same VC */
911
912         /* register_vuid keeps the server info */
913         sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
914         data_blob_free(&nt_resp);
915
916         if (sess_vuid == -1) {
917                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
918         }
919
920         /* current_user_info is changed on new vuid */
921         reload_services( True );
922
923         if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
924                 exit_server("reply_sesssetup_and_X: bad smb signature");
925         }
926
927         SSVAL(outbuf,smb_uid,sess_vuid);
928         SSVAL(inbuf,smb_uid,sess_vuid);
929         
930         if (!done_sesssetup)
931                 max_send = MIN(max_send,smb_bufsize);
932         
933         done_sesssetup = True;
934         
935         END_PROFILE(SMBsesssetupX);
936         return chain_reply(inbuf,outbuf,length,bufsize);
937 }