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