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