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