Don't segfault on make_server_info_guest() failure - instead return the
[ira/wip.git] / source3 / 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         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
400                                           auth, &auth_reply);
401
402         data_blob_free(&auth);
403
404         reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
405                              &auth_reply, nt_status);
406                 
407         data_blob_free(&auth_reply);
408
409         /* and tell smbd that we have already replied to this packet */
410         return -1;
411 }
412
413
414 /****************************************************************************
415 reply to a session setup command
416 ****************************************************************************/
417 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
418                                         char *outbuf,
419                                         int length,int bufsize)
420 {
421         uint8 *p;
422         DATA_BLOB blob1;
423         int ret;
424         size_t bufrem;
425
426         DEBUG(3,("Doing spnego session setup\n"));
427
428         if (global_client_caps == 0) {
429                 global_client_caps = IVAL(inbuf,smb_vwv10);
430         }
431                 
432         p = (uint8 *)smb_buf(inbuf);
433
434         if (SVAL(inbuf, smb_vwv7) == 0) {
435                 /* an invalid request */
436                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
437         }
438
439         bufrem = smb_bufrem(inbuf, p);
440         /* pull the spnego blob */
441         blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7)));
442
443 #if 0
444         file_save("negotiate.dat", blob1.data, blob1.length);
445 #endif
446
447         if (blob1.data[0] == ASN1_APPLICATION(0)) {
448                 /* its a negTokenTarg packet */
449                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
450                 data_blob_free(&blob1);
451                 return ret;
452         }
453
454         if (blob1.data[0] == ASN1_CONTEXT(1)) {
455                 /* its a auth packet */
456                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
457                 data_blob_free(&blob1);
458                 return ret;
459         }
460
461         /* what sort of packet is this? */
462         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
463
464         data_blob_free(&blob1);
465
466         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
467 }
468
469
470 /****************************************************************************
471 reply to a session setup command
472 ****************************************************************************/
473 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
474                           int length,int bufsize)
475 {
476         int sess_vuid;
477         int   smb_bufsize;    
478         DATA_BLOB lm_resp;
479         DATA_BLOB nt_resp;
480         DATA_BLOB plaintext_password;
481         fstring user;
482         fstring sub_user; /* Sainitised username for substituion */
483         fstring domain;
484         fstring native_os;
485         fstring native_lanman;
486         static BOOL done_sesssetup = False;
487         extern BOOL global_encrypted_passwords_negotiated;
488         extern BOOL global_spnego_negotiated;
489         extern int Protocol;
490         extern int max_send;
491
492         auth_usersupplied_info *user_info = NULL;
493         extern struct auth_context *negprot_global_auth_context;
494         auth_serversupplied_info *server_info = NULL;
495
496         NTSTATUS nt_status;
497
498         BOOL doencrypt = global_encrypted_passwords_negotiated;
499         
500         START_PROFILE(SMBsesssetupX);
501
502         ZERO_STRUCT(lm_resp);
503         ZERO_STRUCT(nt_resp);
504         ZERO_STRUCT(plaintext_password);
505
506         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
507
508         /* a SPNEGO session setup has 12 command words, whereas a normal
509            NT1 session setup has 13. See the cifs spec. */
510         if (CVAL(inbuf, smb_wct) == 12 &&
511             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
512                 if (!global_spnego_negotiated) {
513                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
514                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
515                 }
516
517                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
518         }
519
520         smb_bufsize = SVAL(inbuf,smb_vwv2);
521
522         if (Protocol < PROTOCOL_NT1) {
523                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
524                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
525                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
526                 }
527
528                 if (doencrypt) {
529                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
530                 } else {
531                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
532                         /* Ensure null termination */
533                         plaintext_password.data[passlen1] = 0;
534                 }
535
536                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
537                 *domain = 0;
538   
539         } else {
540                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
541                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
542                 enum remote_arch_types ra_type = get_remote_arch();
543                 char *p = smb_buf(inbuf);    
544
545                 if(global_client_caps == 0)
546                         global_client_caps = IVAL(inbuf,smb_vwv11);
547                 
548                 /* client_caps is used as final determination if client is NT or Win95. 
549                    This is needed to return the correct error codes in some
550                    circumstances.
551                 */
552                 
553                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
554                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
555                                 set_remote_arch( RA_WIN95);
556                         }
557                 }
558
559                 if (!doencrypt) {
560                         /* both Win95 and WinNT stuff up the password lengths for
561                            non-encrypting systems. Uggh. 
562                            
563                            if passlen1==24 its a win95 system, and its setting the
564                            password length incorrectly. Luckily it still works with the
565                            default code because Win95 will null terminate the password
566                            anyway 
567                            
568                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
569                            setting passlen2 to some random value which really stuffs
570                            things up. we need to fix that one.  */
571                         
572                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
573                                 passlen2 = 0;
574                 }
575                 
576                 /* check for nasty tricks */
577                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
578                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
579                 }
580
581                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
582                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
583                 }
584
585                 /* Save the lanman2 password and the NT md4 password. */
586                 
587                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
588                         doencrypt = False;
589                 }
590
591                 if (doencrypt) {
592                         lm_resp = data_blob(p, passlen1);
593                         nt_resp = data_blob(p+passlen1, passlen2);
594                 } else {
595                         pstring pass;
596                         srvstr_pull(inbuf, pass, smb_buf(inbuf), 
597                                     sizeof(pass),  passlen1, STR_TERMINATE);
598                         plaintext_password = data_blob(pass, strlen(pass)+1);
599                 }
600                 
601                 p += passlen1 + passlen2;
602                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
603                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
604                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
605                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
606                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
607                          domain,native_os,native_lanman));
608
609                 /* 
610                  * we distinguish between 2K and XP by the "Native Lan Manager" string
611                  *   WinXP => "Windows 2002 5.1"
612                  *   Win2k => "Windows 2000 5.0"
613                  *   NT4   => "Windows NT 4.0" 
614                  *   Win9x => "Windows 4.0"
615                  */
616                  
617                 if ( ra_type == RA_WIN2K ) {
618                         if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) )
619                                 set_remote_arch( RA_WINXP );
620                 }
621                 
622
623         }
624         
625         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
626
627         if (*user) {
628                 if (global_spnego_negotiated) {
629                         
630                         /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
631                         
632                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
633                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
634                 }
635                 fstrcpy(sub_user, user);
636
637                 /* setup the string used by %U */
638                 sub_set_smb_name(user);
639         } else {
640                 fstrcpy(sub_user, lp_guestaccount());
641         }
642
643         sub_set_smb_name(sub_user);
644
645         reload_services(True);
646         
647         if (lp_security() == SEC_SHARE) {
648                 /* in share level we should ignore any passwords */
649
650                 data_blob_free(&lm_resp);
651                 data_blob_free(&nt_resp);
652                 data_blob_clear_free(&plaintext_password);
653
654                 map_username(sub_user);
655                 add_session_user(sub_user);
656                 /* Then force it to null for the benfit of the code below */
657                 *user = 0;
658         }
659         
660         if (!*user) {
661
662                 nt_status = check_guest_password(&server_info);
663
664         } else if (doencrypt) {
665                 if (!negprot_global_auth_context) {
666                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
667                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
668                 }
669                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
670                                                          lm_resp, nt_resp);
671                 if (NT_STATUS_IS_OK(nt_status)) {
672                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
673                                                                                      user_info, 
674                                                                                      &server_info);
675                 }
676         } else {
677                 struct auth_context *plaintext_auth_context = NULL;
678                 const uint8 *chal;
679                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
680                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
681                         
682                         if (!make_user_info_for_reply(&user_info, 
683                                                       user, domain, chal,
684                                                       plaintext_password)) {
685                                 nt_status = NT_STATUS_NO_MEMORY;
686                         }
687                 
688                         if (NT_STATUS_IS_OK(nt_status)) {
689                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
690                                                                                         user_info, 
691                                                                                         &server_info); 
692                                 
693                                 (plaintext_auth_context->free)(&plaintext_auth_context);
694                         }
695                 }
696         }
697
698         free_user_info(&user_info);
699         
700         data_blob_free(&lm_resp);
701         data_blob_free(&nt_resp);
702         data_blob_clear_free(&plaintext_password);
703         
704         if (!NT_STATUS_IS_OK(nt_status)) {
705                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
706         }
707         
708         if (!NT_STATUS_IS_OK(nt_status)) {
709                 return ERROR_NT(nt_status_squash(nt_status));
710         }
711         
712         /* it's ok - setup a reply */
713         set_message(outbuf,3,0,True);
714         if (Protocol >= PROTOCOL_NT1) {
715                 add_signature(outbuf);
716                 /* perhaps grab OS version here?? */
717         }
718         
719         if (server_info->guest) {
720                 SSVAL(outbuf,smb_vwv2,1);
721         }
722
723         /* register the name and uid as being validated, so further connections
724            to a uid can get through without a password, on the same VC */
725
726         /* register_vuid keeps the server info */
727         sess_vuid = register_vuid(server_info, sub_user);
728   
729         if (sess_vuid == -1) {
730                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
731         }
732
733         SSVAL(outbuf,smb_uid,sess_vuid);
734         SSVAL(inbuf,smb_uid,sess_vuid);
735         
736         if (!done_sesssetup)
737                 max_send = MIN(max_send,smb_bufsize);
738         
739         done_sesssetup = True;
740         
741         END_PROFILE(SMBsesssetupX);
742         return chain_reply(inbuf,outbuf,length,bufsize);
743 }