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