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