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