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