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