ed2d5976aa07a6c5b19edfbbce8641ef75c68719
[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 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 static BOOL reply_spnego_ntlmssp_blob(connection_struct *conn, char *outbuf,
240                                          DATA_BLOB *ntlmssp_blob, NTSTATUS errcode) 
241 {
242         DATA_BLOB response;
243         response = spnego_gen_auth_response(ntlmssp_blob);
244         reply_sesssetup_blob(conn, outbuf, response, errcode);
245         data_blob_free(&response);
246         return True;
247 }
248
249 static BOOL reply_spnego_ntlmssp_ok(connection_struct *conn, char *outbuf,
250                                       NTLMSSP_STATE *ntlmssp_state) 
251 {
252         int sess_vuid;
253         DATA_BLOB null_blob = data_blob(NULL, 0);
254
255         sess_vuid = register_vuid(ntlmssp_state->server_info, ntlmssp_state->orig_user /* check this for weird */);
256
257         if (sess_vuid == -1) {
258                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
259         }
260
261         set_message(outbuf,4,0,True);
262         SSVAL(outbuf, smb_vwv3, 0);
263
264         if (ntlmssp_state->server_info->guest) {
265                 SSVAL(outbuf,smb_vwv2,1);
266         }
267
268         add_signature(outbuf);
269  
270         SSVAL(outbuf,smb_uid,sess_vuid);
271         reply_spnego_ntlmssp_blob(conn, outbuf, &null_blob, NT_STATUS_OK);
272         return True;
273 }
274
275 /****************************************************************************
276 reply to a session setup spnego negotiate packet
277 ****************************************************************************/
278 static int reply_spnego_negotiate(connection_struct *conn, 
279                                   char *inbuf,
280                                   char *outbuf,
281                                   int length, int bufsize,
282                                   DATA_BLOB blob1)
283 {
284         char *OIDs[ASN1_MAX_OIDS];
285         DATA_BLOB secblob;
286         int i;
287         DATA_BLOB chal, spnego_chal;
288         BOOL got_kerberos = False;
289         NTSTATUS nt_status;
290
291         /* parse out the OIDs and the first sec blob */
292         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
293                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
294         }
295         
296         for (i=0;OIDs[i];i++) {
297                 DEBUG(3,("Got OID %s\n", OIDs[i]));
298                 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
299                     strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
300                         got_kerberos = True;
301                 }
302                 free(OIDs[i]);
303         }
304         DEBUG(3,("Got secblob of size %d\n", secblob.length));
305
306 #ifdef HAVE_KRB5
307         if (got_kerberos && (SEC_ADS == lp_security())) {
308                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
309                                                 length, bufsize, &secblob);
310                 data_blob_free(&secblob);
311                 return ret;
312         }
313 #endif
314
315         if (global_ntlmssp_state) {
316                 ntlmssp_server_end(&global_ntlmssp_state);
317         }
318
319         nt_status = ntlmssp_server_start(&global_ntlmssp_state);
320         if (!NT_STATUS_IS_OK(nt_status)) {
321                 return ERROR_NT(nt_status);
322         }
323
324         nt_status = ntlmssp_server_update(global_ntlmssp_state, 
325                                           secblob, &chal);
326
327         data_blob_free(&secblob);
328
329         if (!NT_STATUS_IS_OK(nt_status)) {
330                 nt_status = do_map_to_guest(nt_status, 
331                                             &global_ntlmssp_state->server_info, 
332                                             global_ntlmssp_state->orig_user, 
333                                             global_ntlmssp_state->orig_domain);
334         }
335         
336         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
337                 if (!spnego_gen_challenge(&spnego_chal, &chal, NULL)) {
338                         DEBUG(3,("Failed to generate challenge\n"));
339                         data_blob_free(&chal);
340                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
341                 }
342
343                 /* now tell the client to send the auth packet */
344                 reply_sesssetup_blob(conn, outbuf, spnego_chal, nt_status);
345                 
346                 data_blob_free(&chal);
347                 data_blob_free(&spnego_chal);
348
349                 /* and tell smbd that we have already replied to this packet */
350                 return -1;
351
352         } else if (NT_STATUS_IS_OK(nt_status)) {
353                 reply_spnego_ntlmssp_ok(conn, outbuf, 
354                                                  global_ntlmssp_state);
355                 ntlmssp_server_end(&global_ntlmssp_state);
356
357                 data_blob_free(&chal);
358                 /* and tell smbd that we have already replied to this packet */
359                 return -1;
360         } 
361
362         return ERROR_NT(nt_status_squash(nt_status));
363 }
364
365         
366 /****************************************************************************
367 reply to a session setup spnego auth packet
368 ****************************************************************************/
369 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
370                              int length, int bufsize,
371                              DATA_BLOB blob1)
372 {
373         DATA_BLOB auth, auth_reply;
374         NTSTATUS nt_status;
375
376         if (!spnego_parse_auth(blob1, &auth)) {
377 #if 0
378                 file_save("auth.dat", blob1.data, blob1.length);
379 #endif
380                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
381         }
382
383         nt_status = ntlmssp_server_update(global_ntlmssp_state, 
384                                           auth, &auth_reply);
385
386         data_blob_free(&auth);
387         data_blob_free(&auth_reply);
388
389         if (NT_STATUS_IS_OK(nt_status)) {
390                 reply_spnego_ntlmssp_ok(conn, outbuf, 
391                                         global_ntlmssp_state);
392                 ntlmssp_server_end(&global_ntlmssp_state);
393
394         } else { /* !NT_STATUS_IS_OK(nt_status) */
395                 return ERROR_NT(nt_status_squash(nt_status));
396         }
397
398         /* and tell smbd that we have already replied to this packet */
399         return -1;
400 }
401
402
403 /****************************************************************************
404 reply to a session setup spnego anonymous packet
405 ****************************************************************************/
406 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
407                                   int length, int bufsize)
408 {
409         int sess_vuid;
410         auth_serversupplied_info *server_info = NULL;
411         NTSTATUS nt_status;
412
413         nt_status = check_guest_password(&server_info);
414
415         if (!NT_STATUS_IS_OK(nt_status)) {
416                 return ERROR_NT(nt_status_squash(nt_status));
417         }
418
419         sess_vuid = register_vuid(server_info, lp_guestaccount());
420
421         free_server_info(&server_info);
422   
423         if (sess_vuid == -1) {
424                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
425         }
426
427         set_message(outbuf,4,0,True);
428         SSVAL(outbuf, smb_vwv3, 0);
429         add_signature(outbuf);
430  
431         SSVAL(outbuf,smb_uid,sess_vuid);
432         SSVAL(inbuf,smb_uid,sess_vuid);
433         
434         return chain_reply(inbuf,outbuf,length,bufsize);
435 }
436
437
438 /****************************************************************************
439 reply to a session setup command
440 ****************************************************************************/
441 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
442                                         int length,int bufsize)
443 {
444         uint8 *p;
445         DATA_BLOB blob1;
446         int ret;
447
448         DEBUG(3,("Doing spnego session setup\n"));
449
450         if (global_client_caps == 0) {
451                 global_client_caps = IVAL(inbuf,smb_vwv10);
452         }
453                 
454         p = (uint8 *)smb_buf(inbuf);
455
456         if (SVAL(inbuf, smb_vwv7) == 0) {
457                 /* an anonymous request */
458                 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
459         }
460
461         /* pull the spnego blob */
462         blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
463
464 #if 0
465         file_save("negotiate.dat", blob1.data, blob1.length);
466 #endif
467
468         if (blob1.data[0] == ASN1_APPLICATION(0)) {
469                 /* its a negTokenTarg packet */
470                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
471                 data_blob_free(&blob1);
472                 return ret;
473         }
474
475         if (blob1.data[0] == ASN1_CONTEXT(1)) {
476                 /* its a auth packet */
477                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
478                 data_blob_free(&blob1);
479                 return ret;
480         }
481
482         /* what sort of packet is this? */
483         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
484
485         data_blob_free(&blob1);
486
487         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
488 }
489
490
491 /****************************************************************************
492 reply to a session setup command
493 ****************************************************************************/
494 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
495                           int length,int bufsize)
496 {
497         int sess_vuid;
498         int   smb_bufsize;    
499         DATA_BLOB lm_resp;
500         DATA_BLOB nt_resp;
501         DATA_BLOB plaintext_password;
502         fstring user;
503         fstring sub_user; /* Sainitised username for substituion */
504         fstring domain;
505         fstring native_os;
506         fstring native_lanman;
507         static BOOL done_sesssetup = False;
508         extern BOOL global_encrypted_passwords_negotiated;
509         extern BOOL global_spnego_negotiated;
510         extern int Protocol;
511         extern userdom_struct current_user_info;
512         extern int max_send;
513
514         auth_usersupplied_info *user_info = NULL;
515         extern struct auth_context *negprot_global_auth_context;
516         auth_serversupplied_info *server_info = NULL;
517
518         NTSTATUS nt_status;
519
520         BOOL doencrypt = global_encrypted_passwords_negotiated;
521         
522         START_PROFILE(SMBsesssetupX);
523
524         ZERO_STRUCT(lm_resp);
525         ZERO_STRUCT(nt_resp);
526         ZERO_STRUCT(plaintext_password);
527
528         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
529
530         /* a SPNEGO session setup has 12 command words, whereas a normal
531            NT1 session setup has 13. See the cifs spec. */
532         if (CVAL(inbuf, smb_wct) == 12 &&
533             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
534                 if (!global_spnego_negotiated) {
535                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
536                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
537                 }
538
539                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
540         }
541
542         smb_bufsize = SVAL(inbuf,smb_vwv2);
543
544         if (Protocol < PROTOCOL_NT1) {
545                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
546                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
547                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
548                 }
549
550                 if (doencrypt) {
551                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
552                 } else {
553                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
554                         /* Ensure null termination */
555                         plaintext_password.data[passlen1] = 0;
556                 }
557
558                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
559                 *domain = 0;
560   
561         } else {
562                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
563                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
564                 enum remote_arch_types ra_type = get_remote_arch();
565                 char *p = smb_buf(inbuf);    
566
567                 if(global_client_caps == 0)
568                         global_client_caps = IVAL(inbuf,smb_vwv11);
569                 
570                 /* client_caps is used as final determination if client is NT or Win95. 
571                    This is needed to return the correct error codes in some
572                    circumstances.
573                 */
574                 
575                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
576                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
577                                 set_remote_arch( RA_WIN95);
578                         }
579                 }
580                 
581                 if (!doencrypt) {
582                         /* both Win95 and WinNT stuff up the password lengths for
583                            non-encrypting systems. Uggh. 
584                            
585                            if passlen1==24 its a win95 system, and its setting the
586                            password length incorrectly. Luckily it still works with the
587                            default code because Win95 will null terminate the password
588                            anyway 
589                            
590                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
591                            setting passlen2 to some random value which really stuffs
592                            things up. we need to fix that one.  */
593                         
594                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
595                                 passlen2 = 0;
596                 }
597                 
598                 /* check for nasty tricks */
599                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
600                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
601                 }
602
603                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
604                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
605                 }
606
607                 /* Save the lanman2 password and the NT md4 password. */
608                 
609                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
610                         doencrypt = False;
611                 }
612
613                 if (doencrypt) {
614                         lm_resp = data_blob(p, passlen1);
615                         nt_resp = data_blob(p+passlen1, passlen2);
616                 } else {
617                         pstring pass;
618                         srvstr_pull(inbuf, pass, smb_buf(inbuf), 
619                                     sizeof(pass),  passlen1, STR_TERMINATE);
620                         plaintext_password = data_blob(pass, strlen(pass)+1);
621                 }
622                 
623                 p += passlen1 + passlen2;
624                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
625                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
626                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
627                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
628                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
629                          domain,native_os,native_lanman));
630         }
631         
632         /* don't allow for weird usernames or domains */
633         alpha_strcpy(user, user, ". _-$", sizeof(user));
634         alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
635         if (strstr(user, "..") || strstr(domain,"..")) {
636                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
637         }
638
639         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
640
641         if (*user) {
642                 if (global_spnego_negotiated) {
643                         
644                         /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
645                         
646                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
647                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
648                 }
649                 fstrcpy(sub_user, user);
650
651                 /* setup the string used by %U */
652                 sub_set_smb_name(user);
653         } else {
654                 fstrcpy(sub_user, lp_guestaccount());
655         }
656
657         fstrcpy(current_user_info.smb_name,sub_user);
658
659         reload_services(True);
660         
661         if (lp_security() == SEC_SHARE) {
662                 /* in share level we should ignore any passwords */
663
664                 data_blob_free(&lm_resp);
665                 data_blob_free(&nt_resp);
666                 data_blob_clear_free(&plaintext_password);
667
668                 map_username(sub_user);
669                 add_session_user(sub_user);
670                 /* Then force it to null for the benfit of the code below */
671                 *user = 0;
672         }
673         
674         if (!*user) {
675
676                 nt_status = check_guest_password(&server_info);
677
678         } else if (doencrypt) {
679                 if (!negprot_global_auth_context) {
680                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
681                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
682                 }
683                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
684                                                          lm_resp, nt_resp);
685                 if (NT_STATUS_IS_OK(nt_status)) {
686                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
687                                                                                      user_info, 
688                                                                                      &server_info);
689                 }
690         } else {
691                 struct auth_context *plaintext_auth_context = NULL;
692                 const uint8 *chal;
693                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
694                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
695                         
696                         if (!make_user_info_for_reply(&user_info, 
697                                                       user, domain, chal,
698                                                       plaintext_password)) {
699                                 nt_status = NT_STATUS_NO_MEMORY;
700                         }
701                 
702                         if (NT_STATUS_IS_OK(nt_status)) {
703                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
704                                                                                         user_info, 
705                                                                                         &server_info); 
706                                 
707                                 (plaintext_auth_context->free)(&plaintext_auth_context);
708                         }
709                 }
710         }
711
712         free_user_info(&user_info);
713         
714         data_blob_free(&lm_resp);
715         data_blob_free(&nt_resp);
716         data_blob_clear_free(&plaintext_password);
717         
718         if (!NT_STATUS_IS_OK(nt_status)) {
719                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
720         }
721         
722         if (!NT_STATUS_IS_OK(nt_status)) {
723                 return ERROR_NT(nt_status_squash(nt_status));
724         }
725         
726         /* it's ok - setup a reply */
727         set_message(outbuf,3,0,True);
728         if (Protocol == PROTOCOL_NT1) {
729                 add_signature(outbuf);
730                 /* perhaps grab OS version here?? */
731         }
732         
733         if (server_info->guest) {
734                 SSVAL(outbuf,smb_vwv2,1);
735         }
736
737         /* register the name and uid as being validated, so further connections
738            to a uid can get through without a password, on the same VC */
739
740         sess_vuid = register_vuid(server_info, sub_user);
741
742         free_server_info(&server_info);
743   
744         if (sess_vuid == -1) {
745                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
746         }
747
748  
749         SSVAL(outbuf,smb_uid,sess_vuid);
750         SSVAL(inbuf,smb_uid,sess_vuid);
751         
752         if (!done_sesssetup)
753                 max_send = MIN(max_send,smb_bufsize);
754         
755         done_sesssetup = True;
756         
757         END_PROFILE(SMBsesssetupX);
758         return chain_reply(inbuf,outbuf,length,bufsize);
759 }