fix WinXP & Win2K3 remote_arch and check pointer in ntlmssp code before dereferencing
[tprouty/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        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 /****************************************************************************
58  Add the standard 'Samba' signature to the end of the session setup.
59 ****************************************************************************/
60 static void add_signature(char *outbuf) 
61 {
62         char *p;
63         p = smb_buf(outbuf);
64         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
65         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
66         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
67         set_message_end(outbuf,p);
68 }
69
70 /****************************************************************************
71 send a security blob via a session setup reply
72 ****************************************************************************/
73 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
74                                  DATA_BLOB blob, NTSTATUS nt_status)
75 {
76         char *p;
77
78         set_message(outbuf,4,0,True);
79
80         /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
81            that we aren't finished yet */
82
83         nt_status = nt_status_squash(nt_status);
84         SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86         SSVAL(outbuf, smb_vwv3, blob.length);
87         p = smb_buf(outbuf);
88
89         /* should we cap this? */
90         memcpy(p, blob.data, blob.length);
91         p += blob.length;
92
93         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
94         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
95         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
96         set_message_end(outbuf,p);
97
98         return send_smb(smbd_server_fd(),outbuf);
99 }
100
101 /****************************************************************************
102  Do a 'guest' logon, getting back the 
103 ****************************************************************************/
104 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
105 {
106         struct auth_context *auth_context;
107         auth_usersupplied_info *user_info = NULL;
108         
109         NTSTATUS nt_status;
110         unsigned char chal[8];
111
112         ZERO_STRUCT(chal);
113
114         DEBUG(3,("Got anonymous request\n"));
115
116         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
117                 return nt_status;
118         }
119
120         if (!make_user_info_guest(&user_info)) {
121                 (auth_context->free)(&auth_context);
122                 return NT_STATUS_NO_MEMORY;
123         }
124         
125         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
126         (auth_context->free)(&auth_context);
127         free_user_info(&user_info);
128         return nt_status;
129 }
130
131
132 #ifdef HAVE_KRB5
133 /****************************************************************************
134 reply to a session setup spnego negotiate packet for kerberos
135 ****************************************************************************/
136 static int reply_spnego_kerberos(connection_struct *conn, 
137                                  char *inbuf, char *outbuf,
138                                  int length, int bufsize,
139                                  DATA_BLOB *secblob)
140 {
141         DATA_BLOB ticket;
142         char *client, *p;
143         const struct passwd *pw;
144         char *user;
145         int sess_vuid;
146         NTSTATUS ret;
147         DATA_BLOB auth_data;
148         DATA_BLOB ap_rep, ap_rep_wrapped, response;
149         auth_serversupplied_info *server_info = NULL;
150         ADS_STRUCT *ads;
151         uint8 session_key[16];
152         uint8 tok_id[2];
153         BOOL foreign = False;
154
155         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
156                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
157         }
158
159         ads = ads_init_simple();
160
161         if (!ads) {
162                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
163         }
164
165         ads->auth.realm = strdup(lp_realm());
166
167         ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key);
168         if (!NT_STATUS_IS_OK(ret)) {
169                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
170                 ads_destroy(&ads);
171                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
172         }
173
174         data_blob_free(&auth_data);
175
176         DEBUG(3,("Ticket name is [%s]\n", client));
177
178         p = strchr_m(client, '@');
179         if (!p) {
180                 DEBUG(3,("Doesn't look like a valid principal\n"));
181                 ads_destroy(&ads);
182                 data_blob_free(&ap_rep);
183                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
184         }
185
186         *p = 0;
187         if (strcasecmp(p+1, ads->auth.realm) != 0) {
188                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
189                 if (!lp_allow_trusted_domains()) {
190                         data_blob_free(&ap_rep);
191                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
192                 }
193                 foreign = True;
194         }
195
196         /* this gives a fully qualified user name (ie. with full realm).
197            that leads to very long usernames, but what else can we do? */
198         asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
199         
200         pw = Get_Pwnam(user);
201         if (!pw && !foreign) {
202                 pw = Get_Pwnam(client);
203                 SAFE_FREE(user);
204                 user = smb_xstrdup(client);
205         }
206
207         ads_destroy(&ads);
208
209         /* setup the string used by %U */
210         sub_set_smb_name(user);
211
212         reload_services(True);
213
214         if (!pw) {
215                 DEBUG(1,("Username %s is invalid on this system\n",user));
216                 data_blob_free(&ap_rep);
217                 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
218         }
219
220         if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
221                 DEBUG(1,("make_server_info_from_pw failed!\n"));
222                 data_blob_free(&ap_rep);
223                 return ERROR_NT(ret);
224         }
225
226         /* Copy out the session key from the AP_REQ. */
227         memcpy(server_info->session_key, session_key, sizeof(session_key));
228
229         /* register_vuid keeps the server info */
230         sess_vuid = register_vuid(server_info, user);
231
232         free(user);
233
234         if (sess_vuid == -1) {
235                 ret = NT_STATUS_LOGON_FAILURE;
236         } else {
237                 set_message(outbuf,4,0,True);
238                 SSVAL(outbuf, smb_vwv3, 0);
239                         
240                 if (server_info->guest) {
241                         SSVAL(outbuf,smb_vwv2,1);
242                 }
243                 
244                 SSVAL(outbuf, smb_uid, sess_vuid);
245         }
246
247         /* wrap that up in a nice GSS-API wrapping */
248         if (NT_STATUS_IS_OK(ret)) {
249                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
250         } else {
251                 ap_rep_wrapped = data_blob(NULL, 0);
252         }
253         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
254         reply_sesssetup_blob(conn, outbuf, response, ret);
255
256         data_blob_free(&ap_rep);
257         data_blob_free(&ap_rep_wrapped);
258         data_blob_free(&response);
259
260         return -1; /* already replied */
261 }
262 #endif
263
264
265 /****************************************************************************
266  send a session setup reply, wrapped in SPNEGO.
267  get vuid and check first.
268  end the NTLMSSP exchange context if we are OK/complete fail
269 ***************************************************************************/
270 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
271                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
272                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) 
273 {
274         BOOL ret;
275         DATA_BLOB response;
276         struct auth_serversupplied_info *server_info;
277         server_info = (*auth_ntlmssp_state)->server_info;
278
279         if (!NT_STATUS_IS_OK(nt_status)) {
280                 nt_status = do_map_to_guest(nt_status, 
281                                             &server_info, 
282                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
283                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
284         }
285
286         if (NT_STATUS_IS_OK(nt_status)) {
287                 int sess_vuid;
288                 /* register_vuid keeps the server info */
289                 sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user);
290                 (*auth_ntlmssp_state)->server_info = NULL;
291
292                 if (sess_vuid == -1) {
293                         nt_status = NT_STATUS_LOGON_FAILURE;
294                 } else {
295                         
296                         set_message(outbuf,4,0,True);
297                         SSVAL(outbuf, smb_vwv3, 0);
298                         
299                         if (server_info->guest) {
300                                 SSVAL(outbuf,smb_vwv2,1);
301                         }
302                         
303                         SSVAL(outbuf,smb_uid,sess_vuid);
304                 }
305         }
306
307         response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
308         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
309         data_blob_free(&response);
310
311         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
312                 auth_ntlmssp_end(auth_ntlmssp_state);
313         }
314
315         return ret;
316 }
317
318 /****************************************************************************
319 reply to a session setup spnego negotiate packet
320 ****************************************************************************/
321 static int reply_spnego_negotiate(connection_struct *conn, 
322                                   char *inbuf,
323                                   char *outbuf,
324                                   int length, int bufsize,
325                                   DATA_BLOB blob1)
326 {
327         char *OIDs[ASN1_MAX_OIDS];
328         DATA_BLOB secblob;
329         int i;
330         DATA_BLOB chal;
331         BOOL got_kerberos = False;
332         NTSTATUS nt_status;
333
334         /* parse out the OIDs and the first sec blob */
335         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
336                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
337         }
338         
339         for (i=0;OIDs[i];i++) {
340                 DEBUG(3,("Got OID %s\n", OIDs[i]));
341                 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
342                     strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
343                         got_kerberos = True;
344                 }
345                 free(OIDs[i]);
346         }
347         DEBUG(3,("Got secblob of size %d\n", secblob.length));
348
349 #ifdef HAVE_KRB5
350         if (got_kerberos && (SEC_ADS == lp_security())) {
351                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
352                                                 length, bufsize, &secblob);
353                 data_blob_free(&secblob);
354                 return ret;
355         }
356 #endif
357
358         if (global_ntlmssp_state) {
359                 auth_ntlmssp_end(&global_ntlmssp_state);
360         }
361
362         nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
363         if (!NT_STATUS_IS_OK(nt_status)) {
364                 return ERROR_NT(nt_status);
365         }
366
367         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
368                                         secblob, &chal);
369
370         data_blob_free(&secblob);
371
372         reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
373                              &chal, nt_status);
374                 
375         data_blob_free(&chal);
376
377         /* already replied */
378         return -1;
379 }
380
381         
382 /****************************************************************************
383 reply to a session setup spnego auth packet
384 ****************************************************************************/
385 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
386                              int length, int bufsize,
387                              DATA_BLOB blob1)
388 {
389         DATA_BLOB auth, auth_reply;
390         NTSTATUS nt_status;
391
392         if (!spnego_parse_auth(blob1, &auth)) {
393 #if 0
394                 file_save("auth.dat", blob1.data, blob1.length);
395 #endif
396                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
397         }
398
399         if ( global_ntlmssp_state ) {
400         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
401                                           auth, &auth_reply);
402         }
403
404         data_blob_free(&auth);
405
406         reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
407                              &auth_reply, nt_status);
408                 
409         data_blob_free(&auth_reply);
410
411         /* and tell smbd that we have already replied to this packet */
412         return -1;
413 }
414
415
416 /****************************************************************************
417 reply to a session setup command
418 ****************************************************************************/
419 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
420                                         char *outbuf,
421                                         int length,int bufsize)
422 {
423         uint8 *p;
424         DATA_BLOB blob1;
425         int ret;
426         size_t bufrem;
427         fstring native_os, native_lanman;
428         char *p2;
429         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
430         enum remote_arch_types ra_type = get_remote_arch();
431
432         DEBUG(3,("Doing spnego session setup\n"));
433
434         if (global_client_caps == 0) {
435                 global_client_caps = IVAL(inbuf,smb_vwv10);
436         }
437                 
438         p = (uint8 *)smb_buf(inbuf);
439
440         if (data_blob_len == 0) {
441                 /* an invalid request */
442                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
443         }
444
445         bufrem = smb_bufrem(inbuf, p);
446         /* pull the spnego blob */
447         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
448
449 #if 0
450         file_save("negotiate.dat", blob1.data, blob1.length);
451 #endif
452
453         p2 = inbuf + smb_vwv13 + data_blob_len;
454         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
455         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
456         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman));
457
458         if ( ra_type == RA_WIN2K )
459                 ra_lanman_string( native_lanman );
460
461         if (blob1.data[0] == ASN1_APPLICATION(0)) {
462                 /* its a negTokenTarg packet */
463                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
464                 data_blob_free(&blob1);
465                 return ret;
466         }
467
468         if (blob1.data[0] == ASN1_CONTEXT(1)) {
469                 /* its a auth packet */
470                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
471                 data_blob_free(&blob1);
472                 return ret;
473         }
474
475         /* what sort of packet is this? */
476         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
477
478         data_blob_free(&blob1);
479
480         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
481 }
482
483
484 /****************************************************************************
485 reply to a session setup command
486 ****************************************************************************/
487 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
488                           int length,int bufsize)
489 {
490         int sess_vuid;
491         int   smb_bufsize;    
492         DATA_BLOB lm_resp;
493         DATA_BLOB nt_resp;
494         DATA_BLOB plaintext_password;
495         fstring user;
496         fstring sub_user; /* Sainitised username for substituion */
497         fstring domain;
498         fstring native_os;
499         fstring native_lanman;
500         static BOOL done_sesssetup = False;
501         extern BOOL global_encrypted_passwords_negotiated;
502         extern BOOL global_spnego_negotiated;
503         extern int Protocol;
504         extern int max_send;
505
506         auth_usersupplied_info *user_info = NULL;
507         extern struct auth_context *negprot_global_auth_context;
508         auth_serversupplied_info *server_info = NULL;
509
510         NTSTATUS nt_status;
511
512         BOOL doencrypt = global_encrypted_passwords_negotiated;
513         
514         START_PROFILE(SMBsesssetupX);
515
516         ZERO_STRUCT(lm_resp);
517         ZERO_STRUCT(nt_resp);
518         ZERO_STRUCT(plaintext_password);
519
520         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
521
522         /* a SPNEGO session setup has 12 command words, whereas a normal
523            NT1 session setup has 13. See the cifs spec. */
524         if (CVAL(inbuf, smb_wct) == 12 &&
525             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
526                 if (!global_spnego_negotiated) {
527                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
528                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
529                 }
530
531                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
532         }
533
534         smb_bufsize = SVAL(inbuf,smb_vwv2);
535
536         if (Protocol < PROTOCOL_NT1) {
537                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
538                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
539                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
540                 }
541
542                 if (doencrypt) {
543                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
544                 } else {
545                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
546                         /* Ensure null termination */
547                         plaintext_password.data[passlen1] = 0;
548                 }
549
550                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
551                 *domain = 0;
552   
553         } else {
554                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
555                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
556                 enum remote_arch_types ra_type = get_remote_arch();
557                 char *p = smb_buf(inbuf);    
558
559                 if(global_client_caps == 0)
560                         global_client_caps = IVAL(inbuf,smb_vwv11);
561                 
562                 /* client_caps is used as final determination if client is NT or Win95. 
563                    This is needed to return the correct error codes in some
564                    circumstances.
565                 */
566                 
567                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
568                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
569                                 set_remote_arch( RA_WIN95);
570                         }
571                 }
572
573                 if (!doencrypt) {
574                         /* both Win95 and WinNT stuff up the password lengths for
575                            non-encrypting systems. Uggh. 
576                            
577                            if passlen1==24 its a win95 system, and its setting the
578                            password length incorrectly. Luckily it still works with the
579                            default code because Win95 will null terminate the password
580                            anyway 
581                            
582                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
583                            setting passlen2 to some random value which really stuffs
584                            things up. we need to fix that one.  */
585                         
586                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
587                                 passlen2 = 0;
588                 }
589                 
590                 /* check for nasty tricks */
591                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
592                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
593                 }
594
595                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
596                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
597                 }
598
599                 /* Save the lanman2 password and the NT md4 password. */
600                 
601                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
602                         doencrypt = False;
603                 }
604
605                 if (doencrypt) {
606                         lm_resp = data_blob(p, passlen1);
607                         nt_resp = data_blob(p+passlen1, passlen2);
608                 } else {
609                         pstring pass;
610                         srvstr_pull(inbuf, pass, smb_buf(inbuf), 
611                                     sizeof(pass),  passlen1, STR_TERMINATE);
612                         plaintext_password = data_blob(pass, strlen(pass)+1);
613                 }
614                 
615                 p += passlen1 + passlen2;
616                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
617                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
618                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
619                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
620                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
621                          domain,native_os,native_lanman));
622
623                 if ( ra_type == RA_WIN2K )
624                         ra_lanman_string( native_lanman );
625
626         }
627         
628         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
629
630         if (*user) {
631                 if (global_spnego_negotiated) {
632                         
633                         /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
634                         
635                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
636                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
637                 }
638                 fstrcpy(sub_user, user);
639
640                 /* setup the string used by %U */
641                 sub_set_smb_name(user);
642         } else {
643                 fstrcpy(sub_user, lp_guestaccount());
644         }
645
646         sub_set_smb_name(sub_user);
647
648         reload_services(True);
649         
650         if (lp_security() == SEC_SHARE) {
651                 /* in share level we should ignore any passwords */
652
653                 data_blob_free(&lm_resp);
654                 data_blob_free(&nt_resp);
655                 data_blob_clear_free(&plaintext_password);
656
657                 map_username(sub_user);
658                 add_session_user(sub_user);
659                 /* Then force it to null for the benfit of the code below */
660                 *user = 0;
661         }
662         
663         if (!*user) {
664
665                 nt_status = check_guest_password(&server_info);
666
667         } else if (doencrypt) {
668                 if (!negprot_global_auth_context) {
669                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
670                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
671                 }
672                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
673                                                          lm_resp, nt_resp);
674                 if (NT_STATUS_IS_OK(nt_status)) {
675                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
676                                                                                      user_info, 
677                                                                                      &server_info);
678                 }
679         } else {
680                 struct auth_context *plaintext_auth_context = NULL;
681                 const uint8 *chal;
682                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
683                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
684                         
685                         if (!make_user_info_for_reply(&user_info, 
686                                                       user, domain, chal,
687                                                       plaintext_password)) {
688                                 nt_status = NT_STATUS_NO_MEMORY;
689                         }
690                 
691                         if (NT_STATUS_IS_OK(nt_status)) {
692                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
693                                                                                         user_info, 
694                                                                                         &server_info); 
695                                 
696                                 (plaintext_auth_context->free)(&plaintext_auth_context);
697                         }
698                 }
699         }
700
701         free_user_info(&user_info);
702         
703         data_blob_free(&lm_resp);
704         data_blob_free(&nt_resp);
705         data_blob_clear_free(&plaintext_password);
706         
707         if (!NT_STATUS_IS_OK(nt_status)) {
708                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
709         }
710         
711         if (!NT_STATUS_IS_OK(nt_status)) {
712                 return ERROR_NT(nt_status_squash(nt_status));
713         }
714         
715         /* it's ok - setup a reply */
716         set_message(outbuf,3,0,True);
717         if (Protocol >= PROTOCOL_NT1) {
718                 add_signature(outbuf);
719                 /* perhaps grab OS version here?? */
720         }
721         
722         if (server_info->guest) {
723                 SSVAL(outbuf,smb_vwv2,1);
724         }
725
726         /* register the name and uid as being validated, so further connections
727            to a uid can get through without a password, on the same VC */
728
729         /* register_vuid keeps the server info */
730         sess_vuid = register_vuid(server_info, sub_user);
731   
732         if (sess_vuid == -1) {
733                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
734         }
735
736         SSVAL(outbuf,smb_uid,sess_vuid);
737         SSVAL(inbuf,smb_uid,sess_vuid);
738         
739         if (!done_sesssetup)
740                 max_send = MIN(max_send,smb_bufsize);
741         
742         done_sesssetup = True;
743         
744         END_PROFILE(SMBsesssetupX);
745         return chain_reply(inbuf,outbuf,length,bufsize);
746 }