Merge from appliance-head: when creating a default security descriptor
[samba.git] / source3 / smbd / sesssetup.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle SMBsessionsetup
5    Copyright (C) Andrew Tridgell 1998-2001
6    Copyright (C) Andrew Bartlett      2001
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 uint32 global_client_caps = 0;
26 static auth_authsupplied_info *ntlmssp_auth_info;
27
28 /****************************************************************************
29  Add the standard 'Samba' signature to the end of the session setup.
30 ****************************************************************************/
31 static void add_signature(char *outbuf) 
32 {
33         char *p;
34         p = smb_buf(outbuf);
35         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
36         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
37         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
38         set_message_end(outbuf,p);
39 }
40
41 /****************************************************************************
42  Do a 'guest' logon, getting back the 
43 ****************************************************************************/
44 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
45 {
46
47         auth_authsupplied_info *auth_info;
48         auth_usersupplied_info *user_info = NULL;
49         
50         NTSTATUS nt_status;
51         char chal[8];
52
53         ZERO_STRUCT(chal);
54
55         DEBUG(3,("Got anonymous request\n"));
56
57         make_user_info_guest(&user_info);
58         make_auth_info_fixed(&auth_info, chal);
59         
60         nt_status = check_password(user_info, auth_info, server_info);
61         free_auth_info(&auth_info);
62         return nt_status;
63 }
64
65
66 #if HAVE_KRB5
67 /****************************************************************************
68 reply to a session setup spnego negotiate packet for kerberos
69 ****************************************************************************/
70 static int reply_spnego_kerberos(connection_struct *conn, 
71                                  char *inbuf, char *outbuf,
72                                  int length, int bufsize,
73                                  DATA_BLOB *secblob)
74 {
75         DATA_BLOB ticket;
76         char *realm, *client, *p;
77         const struct passwd *pw;
78         char *user;
79         int sess_vuid;
80         NTSTATUS ret;
81         DATA_BLOB auth_data;
82         auth_serversupplied_info *server_info = NULL;
83
84         realm = lp_realm();
85
86         if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
87                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
88         }
89
90         ret = ads_verify_ticket(&ticket, &client, &auth_data);
91         if (!NT_STATUS_IS_OK(ret)) {
92                 DEBUG(1,("Failed to verify incoming ticket!\n"));
93                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
94         }
95
96         DEBUG(3,("Ticket name is [%s]\n", client));
97
98         p = strchr_m(client, '@');
99         if (!p) {
100                 DEBUG(3,("Doesn't look like a valid principal\n"));
101                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
102         }
103
104         *p = 0;
105         if (strcasecmp(p+1, realm) != 0) {
106                 DEBUG(3,("Ticket for incorrect realm %s\n", p+1));
107                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
108         }
109         
110         user = client;
111
112         /* the password is good - let them in */
113         pw = smb_getpwnam(user,False);
114         if (!pw) {
115                 DEBUG(1,("Username %s is invalid on this system\n",user));
116                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
117         }
118
119         if (!make_server_info_pw(&server_info,pw)) {
120                 DEBUG(1,("make_server_info_from_pw failed!\n"));
121                 return ERROR_NT(NT_STATUS_NO_MEMORY);
122         }
123         
124         sess_vuid = register_vuid(server_info, user);
125
126         free_server_info(&server_info);
127
128         if (sess_vuid == -1) {
129                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
130         }
131
132         set_message(outbuf,4,0,True);
133         SSVAL(outbuf, smb_vwv3, 0);
134         add_signature(outbuf);
135  
136         SSVAL(outbuf,smb_uid,sess_vuid);
137         SSVAL(inbuf,smb_uid,sess_vuid);
138         
139         return chain_reply(inbuf,outbuf,length,bufsize);
140 }
141 #endif
142
143
144 /****************************************************************************
145 send a security blob via a session setup reply
146 ****************************************************************************/
147 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
148                                  DATA_BLOB blob)
149 {
150         char *p;
151
152         set_message(outbuf,4,0,True);
153
154         /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
155            that we aren't finished yet */
156
157         SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
158         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
159         SSVAL(outbuf, smb_vwv3, blob.length);
160         p = smb_buf(outbuf);
161         memcpy(p, blob.data, blob.length);
162         p += blob.length;
163         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
164         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
165         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
166         set_message_end(outbuf,p);
167         
168         return send_smb(smbd_server_fd(),outbuf);
169 }
170
171 /****************************************************************************
172 reply to a session setup spnego negotiate packet
173 ****************************************************************************/
174 static int reply_spnego_negotiate(connection_struct *conn, 
175                                   char *inbuf,
176                                   char *outbuf,
177                                   int length, int bufsize,
178                                   DATA_BLOB blob1)
179 {
180         char *OIDs[ASN1_MAX_OIDS];
181         DATA_BLOB secblob;
182         int i;
183         uint32 ntlmssp_command, neg_flags;
184         DATA_BLOB sess_key, chal, spnego_chal;
185         DATA_BLOB cryptkey;
186         BOOL got_kerberos = False;
187
188         /* parse out the OIDs and the first sec blob */
189         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
190                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
191         }
192         
193         for (i=0;OIDs[i];i++) {
194                 DEBUG(3,("Got OID %s\n", OIDs[i]));
195                 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
196                     strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
197                         got_kerberos = True;
198                 }
199                 free(OIDs[i]);
200         }
201         DEBUG(3,("Got secblob of size %d\n", secblob.length));
202
203 #if HAVE_KRB5
204         if (got_kerberos) {
205                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
206                                                 length, bufsize, &secblob);
207                 data_blob_free(&secblob);
208                 return ret;
209         }
210 #endif
211
212         /* parse the NTLMSSP packet */
213 #if 0
214         file_save("secblob.dat", secblob.data, secblob.length);
215 #endif
216
217         if (!msrpc_parse(&secblob, "CddB",
218                          "NTLMSSP",
219                          &ntlmssp_command,
220                          &neg_flags,
221                          &sess_key)) {
222                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
223         }
224
225         data_blob_free(&secblob);
226         data_blob_free(&sess_key);
227
228         if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
229                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
230         }
231
232         DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
233
234         if (!make_auth_info_subsystem(&ntlmssp_auth_info)) {
235                 return ERROR_NT(NT_STATUS_NO_MEMORY);
236         }
237
238         cryptkey = auth_get_challange(ntlmssp_auth_info);
239
240         /* Give them the challenge. For now, ignore neg_flags and just
241            return the flags we want. Obviously this is not correct */
242         
243         neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
244                 NTLMSSP_NEGOTIATE_LM_KEY | 
245                 NTLMSSP_NEGOTIATE_NTLM;
246
247         msrpc_gen(&chal, "Cddddbdddd",
248                   "NTLMSSP", 
249                   NTLMSSP_CHALLENGE,
250                   0,
251                   0x30, /* ?? */
252                   neg_flags,
253                   cryptkey.data, cryptkey.length,
254                   0, 0, 0,
255                   0x3000); /* ?? */
256
257         if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
258                 DEBUG(3,("Failed to generate challenge\n"));
259                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
260         }
261
262         /* now tell the client to send the auth packet */
263         reply_sesssetup_blob(conn, outbuf, spnego_chal);
264
265         data_blob_free(&chal);
266         data_blob_free(&cryptkey);
267         data_blob_free(&spnego_chal);
268
269         /* and tell smbd that we have already replied to this packet */
270         return -1;
271 }
272
273         
274 /****************************************************************************
275 reply to a session setup spnego auth packet
276 ****************************************************************************/
277 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
278                              int length, int bufsize,
279                              DATA_BLOB blob1)
280 {
281         DATA_BLOB auth;
282         char *workgroup, *user, *machine;
283         DATA_BLOB lmhash, nthash, sess_key;
284         DATA_BLOB plaintext_password = data_blob(NULL, 0);
285         uint32 ntlmssp_command, neg_flags;
286         NTSTATUS nt_status;
287         int sess_vuid;
288
289         auth_usersupplied_info *user_info = NULL;
290         auth_serversupplied_info *server_info = NULL;
291
292         if (!spnego_parse_auth(blob1, &auth)) {
293 #if 0
294                 file_save("auth.dat", blob1.data, blob1.length);
295 #endif
296                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
297         }
298
299         /* now the NTLMSSP encoded auth hashes */
300         if (!msrpc_parse(&auth, "CdBBUUUBd", 
301                          "NTLMSSP", 
302                          &ntlmssp_command, 
303                          &lmhash,
304                          &nthash,
305                          &workgroup, 
306                          &user, 
307                          &machine,
308                          &sess_key,
309                          &neg_flags)) {
310                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
311         }
312
313         data_blob_free(&auth);
314         data_blob_free(&sess_key);
315         
316         DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
317                  user, workgroup, machine, lmhash.length, nthash.length));
318
319 #if 0
320         file_save("nthash1.dat", nthash.data, nthash.length);
321         file_save("lmhash1.dat", lmhash.data, lmhash.length);
322 #endif
323
324         if (!make_user_info_map(&user_info, 
325                                 user, workgroup, 
326                                 machine, 
327                                 lmhash, nthash,
328                                 plaintext_password, 
329                                 neg_flags, True)) {
330                 return ERROR_NT(NT_STATUS_NO_MEMORY);
331         }
332         
333         nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); 
334         
335         free_auth_info(&ntlmssp_auth_info);
336
337         free_user_info(&user_info);
338         
339         data_blob_free(&lmhash);
340         
341         data_blob_free(&nthash);
342         
343         if (!NT_STATUS_IS_OK(nt_status)) {
344                 return ERROR_NT(nt_status_squash(nt_status));
345         }
346
347         sess_vuid = register_vuid(server_info, user);
348
349         free_server_info(&server_info);
350   
351         if (sess_vuid == -1) {
352                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
353         }
354
355         set_message(outbuf,4,0,True);
356         SSVAL(outbuf, smb_vwv3, 0);
357         add_signature(outbuf);
358  
359         SSVAL(outbuf,smb_uid,sess_vuid);
360         SSVAL(inbuf,smb_uid,sess_vuid);
361         
362         return chain_reply(inbuf,outbuf,length,bufsize);
363 }
364
365
366 /****************************************************************************
367 reply to a session setup spnego anonymous packet
368 ****************************************************************************/
369 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
370                                   int length, int bufsize)
371 {
372         int sess_vuid;
373         auth_serversupplied_info *server_info = NULL;
374         NTSTATUS nt_status;
375
376         nt_status = check_guest_password(&server_info);
377
378         if (!NT_STATUS_IS_OK(nt_status)) {
379                 return ERROR_NT(nt_status_squash(nt_status));
380         }
381
382         sess_vuid = register_vuid(server_info, lp_guestaccount());
383
384         free_server_info(&server_info);
385   
386         if (sess_vuid == -1) {
387                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
388         }
389
390         set_message(outbuf,4,0,True);
391         SSVAL(outbuf, smb_vwv3, 0);
392         add_signature(outbuf);
393  
394         SSVAL(outbuf,smb_uid,sess_vuid);
395         SSVAL(inbuf,smb_uid,sess_vuid);
396         
397         return chain_reply(inbuf,outbuf,length,bufsize);
398 }
399
400
401 /****************************************************************************
402 reply to a session setup command
403 ****************************************************************************/
404 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
405                                         int length,int bufsize)
406 {
407         uint8 *p;
408         DATA_BLOB blob1;
409         int ret;
410
411         DEBUG(3,("Doing spnego session setup\n"));
412
413         if (global_client_caps == 0) {
414                 global_client_caps = IVAL(inbuf,smb_vwv10);
415         }
416                 
417         p = (uint8 *)smb_buf(inbuf);
418
419         if (SVAL(inbuf, smb_vwv7) == 0) {
420                 /* an anonymous request */
421                 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
422         }
423
424         /* pull the spnego blob */
425         blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
426
427 #if 0
428         file_save("negotiate.dat", blob1.data, blob1.length);
429 #endif
430
431         if (blob1.data[0] == ASN1_APPLICATION(0)) {
432                 /* its a negTokenTarg packet */
433                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
434                 data_blob_free(&blob1);
435                 return ret;
436         }
437
438         if (blob1.data[0] == ASN1_CONTEXT(1)) {
439                 /* its a auth packet */
440                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
441                 data_blob_free(&blob1);
442                 return ret;
443         }
444
445         /* what sort of packet is this? */
446         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
447
448         data_blob_free(&blob1);
449
450         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
451 }
452
453
454 /****************************************************************************
455 reply to a session setup command
456 ****************************************************************************/
457 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
458                           int length,int bufsize)
459 {
460         int sess_vuid;
461         int   smb_bufsize;    
462         DATA_BLOB lm_resp;
463         DATA_BLOB nt_resp;
464         DATA_BLOB plaintext_password;
465         pstring user;
466         pstring sub_user; /* Sainitised username for substituion */
467         fstring domain;
468         fstring native_os;
469         fstring native_lanman;
470         static BOOL done_sesssetup = False;
471         extern BOOL global_encrypted_passwords_negotiated;
472         extern BOOL global_spnego_negotiated;
473         extern int Protocol;
474         extern fstring remote_machine;
475         extern userdom_struct current_user_info;
476         extern int max_send;
477
478         auth_usersupplied_info *user_info = NULL;
479         extern auth_authsupplied_info *negprot_global_auth_info;
480         auth_serversupplied_info *server_info = NULL;
481
482         NTSTATUS nt_status;
483
484         BOOL doencrypt = global_encrypted_passwords_negotiated;
485
486         START_PROFILE(SMBsesssetupX);
487
488         ZERO_STRUCT(lm_resp);
489         ZERO_STRUCT(nt_resp);
490         ZERO_STRUCT(plaintext_password);
491
492         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
493         
494         /* a SPNEGO session setup has 12 command words, whereas a normal
495            NT1 session setup has 13. See the cifs spec. */
496         if (CVAL(inbuf, smb_wct) == 12 &&
497             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
498                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
499         }
500
501         smb_bufsize = SVAL(inbuf,smb_vwv2);
502
503         if (Protocol < PROTOCOL_NT1) {
504                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
505                 if (passlen1 > MAX_PASS_LEN) {
506                         return ERROR_DOS(ERRDOS,ERRbuftoosmall);
507                 }
508
509                 if (doencrypt) {
510                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
511                 } else {
512                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
513                         /* Ensure null termination */
514                         plaintext_password.data[passlen1] = 0;
515                 }
516
517                 srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE);
518                 *domain = 0;
519   
520         } else {
521                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
522                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
523                 enum remote_arch_types ra_type = get_remote_arch();
524                 char *p = smb_buf(inbuf);    
525
526                 if(global_client_caps == 0)
527                         global_client_caps = IVAL(inbuf,smb_vwv11);
528                 
529                 /* client_caps is used as final determination if client is NT or Win95. 
530                    This is needed to return the correct error codes in some
531                    circumstances.
532                 */
533                 
534                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
535                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
536                                 set_remote_arch( RA_WIN95);
537                         }
538                 }
539                 
540                 if (passlen1 > MAX_PASS_LEN) {
541                         return ERROR_DOS(ERRDOS,ERRbuftoosmall);
542                 }
543
544                 passlen1 = MIN(passlen1, MAX_PASS_LEN);
545                 passlen2 = MIN(passlen2, MAX_PASS_LEN);
546
547                 if (!doencrypt) {
548                         /* both Win95 and WinNT stuff up the password lengths for
549                            non-encrypting systems. Uggh. 
550                            
551                            if passlen1==24 its a win95 system, and its setting the
552                            password length incorrectly. Luckily it still works with the
553                            default code because Win95 will null terminate the password
554                            anyway 
555                            
556                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
557                            setting passlen2 to some random value which really stuffs
558                            things up. we need to fix that one.  */
559                         
560                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
561                                 passlen2 = 0;
562                 }
563                 
564                 /* Save the lanman2 password and the NT md4 password. */
565                 
566                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
567                         doencrypt = False;
568                 }
569                 
570                 if (doencrypt) {
571                         lm_resp = data_blob(p, passlen1);
572                         nt_resp = data_blob(p+passlen1, passlen2);
573                 } else {
574                         plaintext_password = data_blob(p, passlen1+1);
575                         /* Ensure null termination */
576                         plaintext_password.data[passlen1] = 0;
577                 }
578                 
579                 p += passlen1 + passlen2;
580                 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
581                                  STR_TERMINATE);
582                 p += srvstr_pull(inbuf, domain, p, sizeof(domain), 
583                                  -1, STR_TERMINATE);
584                 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), 
585                                  -1, STR_TERMINATE);
586                 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
587                                  -1, STR_TERMINATE);
588                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
589                          domain,native_os,native_lanman));
590         }
591         
592         /* don't allow for weird usernames or domains */
593         alpha_strcpy(user, user, ". _-$", sizeof(user));
594         alpha_strcpy(domain, domain, ". _-", sizeof(domain));
595         if (strstr(user, "..") || strstr(domain,"..")) {
596                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
597         }
598
599         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine));
600
601         if (*user) {
602                 if (global_spnego_negotiated) {
603                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
604                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
605                 }
606         }
607
608         if (*user) {
609                 pstrcpy(sub_user, user);
610         } else {
611                 pstrcpy(sub_user, lp_guestaccount());
612         }
613
614         pstrcpy(current_user_info.smb_name,sub_user);
615
616         reload_services(True);
617         
618         if (lp_security() == SEC_SHARE) {
619                 /* in share level we should ignore any passwords */
620
621                 data_blob_free(&lm_resp);
622                 data_blob_free(&nt_resp);
623                 data_blob_clear_free(&plaintext_password);
624
625                 map_username(sub_user);
626                 add_session_user(sub_user);
627                 /* Then force it to null for the benfit of the code below */
628                 *user = 0;
629         }
630         
631         if (!*user) {
632
633                 nt_status = check_guest_password(&server_info);
634
635         } else if (doencrypt) {
636                 if (!make_user_info_for_reply_enc(&user_info, 
637                                                   user, domain, 
638                                                   lm_resp, nt_resp,
639                                                   plaintext_password)) {
640                         return ERROR_NT(NT_STATUS_NO_MEMORY);
641                 }
642                 
643                 nt_status = check_password(user_info, negprot_global_auth_info, &server_info); 
644
645         } else {
646                 auth_authsupplied_info *plaintext_auth_info = NULL;
647                 DATA_BLOB chal;
648                 if (!make_auth_info_subsystem(&plaintext_auth_info)) {
649                         return ERROR_NT(NT_STATUS_NO_MEMORY);
650                 }
651
652                 chal = auth_get_challange(plaintext_auth_info);
653
654                 if (!make_user_info_for_reply(&user_info, 
655                                               user, domain, chal.data,
656                                               plaintext_password)) {
657                         return ERROR_NT(NT_STATUS_NO_MEMORY);
658                 }
659                 
660                 nt_status = check_password(user_info, plaintext_auth_info, &server_info); 
661                 
662                 data_blob_free(&chal);
663                 free_auth_info(&plaintext_auth_info);
664         }
665
666         free_user_info(&user_info);
667         
668         data_blob_free(&lm_resp);
669         data_blob_free(&nt_resp);
670         data_blob_clear_free(&plaintext_password);
671         
672         if (!NT_STATUS_IS_OK(nt_status)) {
673                 if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
674                         if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
675                             (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
676                                 
677                                 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
678                                 make_server_info_guest(&server_info);
679                                 nt_status = NT_STATUS_OK;
680                         }
681
682                 } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {                        
683                         if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {                                
684                                 DEBUG(3,("Registered username %s for guest access\n",user));
685                                 make_server_info_guest(&server_info);
686                                 nt_status = NT_STATUS_OK;
687                         }
688                 }
689         }
690         
691         if (!NT_STATUS_IS_OK(nt_status)) {
692                 return ERROR_NT(nt_status_squash(nt_status));
693         }
694         
695         /* it's ok - setup a reply */
696         if (Protocol < PROTOCOL_NT1) {
697                 set_message(outbuf,3,0,True);
698         } else {
699                 set_message(outbuf,3,0,True);
700                 add_signature(outbuf);
701                 /* perhaps grab OS version here?? */
702         }
703         
704         if (server_info->guest) {
705                 SSVAL(outbuf,smb_vwv2,1);
706         } else {
707                 const char *home_dir = pdb_get_homedir(server_info->sam_account);
708                 const char *username = pdb_get_username(server_info->sam_account);
709                 if ((home_dir && *home_dir)
710                     && (lp_servicenumber(username) < 0)) {
711                         add_home_service(username, home_dir);     
712                 }
713         }
714
715         /* register the name and uid as being validated, so further connections
716            to a uid can get through without a password, on the same VC */
717
718         sess_vuid = register_vuid(server_info, sub_user);
719
720         free_server_info(&server_info);
721   
722         if (sess_vuid == -1) {
723                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
724         }
725
726  
727         SSVAL(outbuf,smb_uid,sess_vuid);
728         SSVAL(inbuf,smb_uid,sess_vuid);
729         
730         if (!done_sesssetup)
731                 max_send = MIN(max_send,smb_bufsize);
732         
733         done_sesssetup = True;
734         
735         END_PROFILE(SMBsesssetupX);
736         return chain_reply(inbuf,outbuf,length,bufsize);
737 }
738
739
740
741
742