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