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