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