Removed version number from file header.
[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
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(NULL, NULL, NULL, NULL);
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
350         auth_usersupplied_info *user_info = NULL;
351         auth_serversupplied_info *server_info = NULL;
352
353         if (!spnego_parse_auth(blob1, &auth)) {
354 #if 0
355                 file_save("auth.dat", blob1.data, blob1.length);
356 #endif
357                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
358         }
359
360         /* now the NTLMSSP encoded auth hashes */
361         if (!msrpc_parse(&auth, "CdBBUUUBd", 
362                          "NTLMSSP", 
363                          &ntlmssp_command, 
364                          &lmhash,
365                          &nthash,
366                          &workgroup, 
367                          &user, 
368                          &machine,
369                          &sess_key,
370                          &neg_flags)) {
371                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
372         }
373
374         data_blob_free(&auth);
375         data_blob_free(&sess_key);
376         
377         DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
378                  user, workgroup, machine, lmhash.length, nthash.length));
379
380 #if 0
381         file_save("nthash1.dat", nthash.data, nthash.length);
382         file_save("lmhash1.dat", lmhash.data, lmhash.length);
383 #endif
384
385         if (lmhash.length) {
386                 auth_flags |= AUTH_FLAG_LM_RESP;
387         }
388
389         if (nthash.length == 24) {
390                 auth_flags |= AUTH_FLAG_NTLM_RESP;
391         } else if (nthash.length > 24) {
392                 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
393         }
394
395         if (!make_user_info_map(&user_info, 
396                                 user, workgroup, 
397                                 machine, 
398                                 lmhash, nthash,
399                                 plaintext_password, 
400                                 auth_flags, True)) {
401                 return ERROR_NT(NT_STATUS_NO_MEMORY);
402         }
403
404         nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); 
405
406         if (!NT_STATUS_IS_OK(nt_status)) {
407                 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
408         }
409
410         SAFE_FREE(workgroup);
411         SAFE_FREE(machine);
412                         
413         (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
414
415         free_user_info(&user_info);
416         
417         data_blob_free(&lmhash);
418         
419         data_blob_free(&nthash);
420
421         if (!NT_STATUS_IS_OK(nt_status)) {
422                 SAFE_FREE(user);
423                 return ERROR_NT(nt_status_squash(nt_status));
424         }
425
426         as_guest = server_info->guest;
427
428         sess_vuid = register_vuid(server_info, user);
429         free_server_info(&server_info);
430
431         SAFE_FREE(user);
432   
433         if (sess_vuid == -1) {
434                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
435         }
436
437         set_message(outbuf,4,0,True);
438         SSVAL(outbuf, smb_vwv3, 0);
439
440         if (as_guest) {
441                 SSVAL(outbuf,smb_vwv2,1);
442         }
443
444         add_signature(outbuf);
445  
446         SSVAL(outbuf,smb_uid,sess_vuid);
447         SSVAL(inbuf,smb_uid,sess_vuid);
448         
449         return chain_reply(inbuf,outbuf,length,bufsize);
450 }
451
452
453 /****************************************************************************
454 reply to a session setup spnego anonymous packet
455 ****************************************************************************/
456 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
457                                   int length, int bufsize)
458 {
459         int sess_vuid;
460         auth_serversupplied_info *server_info = NULL;
461         NTSTATUS nt_status;
462
463         nt_status = check_guest_password(&server_info);
464
465         if (!NT_STATUS_IS_OK(nt_status)) {
466                 return ERROR_NT(nt_status_squash(nt_status));
467         }
468
469         sess_vuid = register_vuid(server_info, lp_guestaccount());
470
471         free_server_info(&server_info);
472   
473         if (sess_vuid == -1) {
474                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
475         }
476
477         set_message(outbuf,4,0,True);
478         SSVAL(outbuf, smb_vwv3, 0);
479         add_signature(outbuf);
480  
481         SSVAL(outbuf,smb_uid,sess_vuid);
482         SSVAL(inbuf,smb_uid,sess_vuid);
483         
484         return chain_reply(inbuf,outbuf,length,bufsize);
485 }
486
487
488 /****************************************************************************
489 reply to a session setup command
490 ****************************************************************************/
491 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
492                                         int length,int bufsize)
493 {
494         uint8 *p;
495         DATA_BLOB blob1;
496         int ret;
497
498         DEBUG(3,("Doing spnego session setup\n"));
499
500         if (global_client_caps == 0) {
501                 global_client_caps = IVAL(inbuf,smb_vwv10);
502         }
503                 
504         p = (uint8 *)smb_buf(inbuf);
505
506         if (SVAL(inbuf, smb_vwv7) == 0) {
507                 /* an anonymous request */
508                 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
509         }
510
511         /* pull the spnego blob */
512         blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
513
514 #if 0
515         file_save("negotiate.dat", blob1.data, blob1.length);
516 #endif
517
518         if (blob1.data[0] == ASN1_APPLICATION(0)) {
519                 /* its a negTokenTarg packet */
520                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
521                 data_blob_free(&blob1);
522                 return ret;
523         }
524
525         if (blob1.data[0] == ASN1_CONTEXT(1)) {
526                 /* its a auth packet */
527                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
528                 data_blob_free(&blob1);
529                 return ret;
530         }
531
532         /* what sort of packet is this? */
533         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
534
535         data_blob_free(&blob1);
536
537         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
538 }
539
540
541 /****************************************************************************
542 reply to a session setup command
543 ****************************************************************************/
544 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
545                           int length,int bufsize)
546 {
547         int sess_vuid;
548         int   smb_bufsize;    
549         DATA_BLOB lm_resp;
550         DATA_BLOB nt_resp;
551         DATA_BLOB plaintext_password;
552         pstring user;
553         pstring sub_user; /* Sainitised username for substituion */
554         fstring domain;
555         fstring native_os;
556         fstring native_lanman;
557         static BOOL done_sesssetup = False;
558         extern BOOL global_encrypted_passwords_negotiated;
559         extern BOOL global_spnego_negotiated;
560         extern int Protocol;
561         extern fstring remote_machine;
562         extern userdom_struct current_user_info;
563         extern int max_send;
564
565         auth_usersupplied_info *user_info = NULL;
566         extern struct auth_context *negprot_global_auth_context;
567         auth_serversupplied_info *server_info = NULL;
568
569         NTSTATUS nt_status;
570
571         BOOL doencrypt = global_encrypted_passwords_negotiated;
572
573         START_PROFILE(SMBsesssetupX);
574
575         ZERO_STRUCT(lm_resp);
576         ZERO_STRUCT(nt_resp);
577         ZERO_STRUCT(plaintext_password);
578
579         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
580
581         /* a SPNEGO session setup has 12 command words, whereas a normal
582            NT1 session setup has 13. See the cifs spec. */
583         if (CVAL(inbuf, smb_wct) == 12 &&
584             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
585                 if (!global_spnego_negotiated) {
586                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
587                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
588                 }
589
590                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
591         }
592
593         smb_bufsize = SVAL(inbuf,smb_vwv2);
594
595         if (Protocol < PROTOCOL_NT1) {
596                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
597                 if (passlen1 > MAX_PASS_LEN) {
598                         return ERROR_DOS(ERRDOS,ERRbuftoosmall);
599                 }
600
601                 if (doencrypt) {
602                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
603                 } else {
604                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
605                         /* Ensure null termination */
606                         plaintext_password.data[passlen1] = 0;
607                 }
608
609                 srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE);
610                 *domain = 0;
611   
612         } else {
613                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
614                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
615                 enum remote_arch_types ra_type = get_remote_arch();
616                 char *p = smb_buf(inbuf);    
617
618                 if(global_client_caps == 0)
619                         global_client_caps = IVAL(inbuf,smb_vwv11);
620                 
621                 /* client_caps is used as final determination if client is NT or Win95. 
622                    This is needed to return the correct error codes in some
623                    circumstances.
624                 */
625                 
626                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
627                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
628                                 set_remote_arch( RA_WIN95);
629                         }
630                 }
631                 
632                 if (passlen1 > MAX_PASS_LEN) {
633                         return ERROR_DOS(ERRDOS,ERRbuftoosmall);
634                 }
635
636                 passlen1 = MIN(passlen1, MAX_PASS_LEN);
637                 passlen2 = MIN(passlen2, MAX_PASS_LEN);
638
639                 if (!doencrypt) {
640                         /* both Win95 and WinNT stuff up the password lengths for
641                            non-encrypting systems. Uggh. 
642                            
643                            if passlen1==24 its a win95 system, and its setting the
644                            password length incorrectly. Luckily it still works with the
645                            default code because Win95 will null terminate the password
646                            anyway 
647                            
648                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
649                            setting passlen2 to some random value which really stuffs
650                            things up. we need to fix that one.  */
651                         
652                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
653                                 passlen2 = 0;
654                 }
655                 
656                 /* Save the lanman2 password and the NT md4 password. */
657                 
658                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
659                         doencrypt = False;
660                 }
661                 
662                 if (doencrypt) {
663                         lm_resp = data_blob(p, passlen1);
664                         nt_resp = data_blob(p+passlen1, passlen2);
665                 } else {
666                         plaintext_password = data_blob(p, passlen1+1);
667                         /* Ensure null termination */
668                         plaintext_password.data[passlen1] = 0;
669                 }
670                 
671                 p += passlen1 + passlen2;
672                 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
673                                  STR_TERMINATE);
674                 p += srvstr_pull(inbuf, domain, p, sizeof(domain), 
675                                  -1, STR_TERMINATE);
676                 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os), 
677                                  -1, STR_TERMINATE);
678                 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
679                                  -1, STR_TERMINATE);
680                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
681                          domain,native_os,native_lanman));
682         }
683         
684         /* don't allow for weird usernames or domains */
685         alpha_strcpy(user, user, ". _-$", sizeof(user));
686         alpha_strcpy(domain, domain, ". _-", sizeof(domain));
687         if (strstr(user, "..") || strstr(domain,"..")) {
688                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
689         }
690
691         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine));
692
693         if (*user) {
694                 if (global_spnego_negotiated) {
695                         
696                         /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
697                         
698                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
699                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
700                 }
701                 pstrcpy(sub_user, user);
702         } else {
703                 pstrcpy(sub_user, lp_guestaccount());
704         }
705
706         pstrcpy(current_user_info.smb_name,sub_user);
707
708         reload_services(True);
709         
710         if (lp_security() == SEC_SHARE) {
711                 /* in share level we should ignore any passwords */
712
713                 data_blob_free(&lm_resp);
714                 data_blob_free(&nt_resp);
715                 data_blob_clear_free(&plaintext_password);
716
717                 map_username(sub_user);
718                 add_session_user(sub_user);
719                 /* Then force it to null for the benfit of the code below */
720                 *user = 0;
721         }
722         
723         if (!*user) {
724
725                 nt_status = check_guest_password(&server_info);
726
727         } else if (doencrypt) {
728                 if (!make_user_info_for_reply_enc(&user_info, 
729                                                   user, domain, 
730                                                   lm_resp, nt_resp)) {
731                         nt_status = NT_STATUS_NO_MEMORY;
732                 } else {
733                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
734                                                                                      user_info, 
735                                                                                      &server_info);
736                 }
737         } else {
738                 struct auth_context *plaintext_auth_context = NULL;
739                 const uint8 *chal;
740                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
741                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
742                         
743                         if (!make_user_info_for_reply(&user_info, 
744                                                       user, domain, chal,
745                                                       plaintext_password)) {
746                                 nt_status = NT_STATUS_NO_MEMORY;
747                         }
748                 
749                         if (NT_STATUS_IS_OK(nt_status)) {
750                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
751                                                                                         user_info, 
752                                                                                         &server_info); 
753                                 
754                                 (plaintext_auth_context->free)(&plaintext_auth_context);
755                         }
756                 }
757         }
758
759         free_user_info(&user_info);
760         
761         data_blob_free(&lm_resp);
762         data_blob_free(&nt_resp);
763         data_blob_clear_free(&plaintext_password);
764         
765         if (!NT_STATUS_IS_OK(nt_status)) {
766                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
767         }
768         
769         if (!NT_STATUS_IS_OK(nt_status)) {
770                 return ERROR_NT(nt_status_squash(nt_status));
771         }
772         
773         /* it's ok - setup a reply */
774         if (Protocol < PROTOCOL_NT1) {
775                 set_message(outbuf,3,0,True);
776         } else {
777                 set_message(outbuf,3,0,True);
778                 add_signature(outbuf);
779                 /* perhaps grab OS version here?? */
780         }
781         
782         if (server_info->guest) {
783                 SSVAL(outbuf,smb_vwv2,1);
784         }
785
786         /* register the name and uid as being validated, so further connections
787            to a uid can get through without a password, on the same VC */
788
789         sess_vuid = register_vuid(server_info, sub_user);
790
791         free_server_info(&server_info);
792   
793         if (sess_vuid == -1) {
794                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
795         }
796
797  
798         SSVAL(outbuf,smb_uid,sess_vuid);
799         SSVAL(inbuf,smb_uid,sess_vuid);
800         
801         if (!done_sesssetup)
802                 max_send = MIN(max_send,smb_bufsize);
803         
804         done_sesssetup = True;
805         
806         END_PROFILE(SMBsesssetupX);
807         return chain_reply(inbuf,outbuf,length,bufsize);
808 }