import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / smbd / sesssetup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <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", SAMBA_VERSION_STRING);
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, *domain;
145         fstring netbios_domain_name;
146         struct passwd *pw;
147         char *user;
148         int sess_vuid;
149         NTSTATUS ret;
150         DATA_BLOB auth_data;
151         DATA_BLOB ap_rep, ap_rep_wrapped, response;
152         auth_serversupplied_info *server_info = NULL;
153         DATA_BLOB session_key;
154         uint8 tok_id[2];
155         BOOL foreign = False;
156         DATA_BLOB nullblob = data_blob(NULL, 0);
157         fstring real_username;
158
159         ZERO_STRUCT(ticket);
160         ZERO_STRUCT(auth_data);
161         ZERO_STRUCT(ap_rep);
162         ZERO_STRUCT(ap_rep_wrapped);
163         ZERO_STRUCT(response);
164
165         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
166                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
167         }
168
169         ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
170
171         data_blob_free(&ticket);
172
173         if (!NT_STATUS_IS_OK(ret)) {
174                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
175                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
176         }
177
178         data_blob_free(&auth_data);
179
180         DEBUG(3,("Ticket name is [%s]\n", client));
181
182         p = strchr_m(client, '@');
183         if (!p) {
184                 DEBUG(3,("Doesn't look like a valid principal\n"));
185                 data_blob_free(&ap_rep);
186                 SAFE_FREE(client);
187                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
188         }
189
190         *p = 0;
191         if (!strequal(p+1, lp_realm())) {
192                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
193                 if (!lp_allow_trusted_domains()) {
194                         data_blob_free(&ap_rep);
195                         SAFE_FREE(client);
196                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
197                 }
198                 foreign = True;
199         }
200
201         /* this gives a fully qualified user name (ie. with full realm).
202            that leads to very long usernames, but what else can we do? */
203
204         domain = p+1;
205
206         {
207                 /* If we have winbind running, we can (and must) shorten the
208                    username by using the short netbios name. Otherwise we will
209                    have inconsistent user names. With Kerberos, we get the
210                    fully qualified realm, with ntlmssp we get the short
211                    name. And even w2k3 does use ntlmssp if you for example
212                    connect to an ip address. */
213
214                 struct winbindd_request wb_request;
215                 struct winbindd_response wb_response;
216                 NSS_STATUS wb_result;
217
218                 ZERO_STRUCT(wb_request);
219                 ZERO_STRUCT(wb_response);
220
221                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
222
223                 fstrcpy(wb_request.domain_name, domain);
224
225                 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
226                                              &wb_request, &wb_response);
227
228                 if (wb_result == NSS_STATUS_SUCCESS) {
229
230                         fstrcpy(netbios_domain_name,
231                                 wb_response.data.domain_info.name);
232                         domain = netbios_domain_name;
233
234                         DEBUG(10, ("Mapped to [%s]\n", domain));
235                 } else {
236                         DEBUG(3, ("Could not find short name -- winbind "
237                                   "not running?\n"));
238                 }
239         }
240
241         asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
242         
243         /* lookup the passwd struct, create a new user if necessary */
244
245         pw = smb_getpwnam( user, real_username, True );
246         
247         if (!pw) {
248                 DEBUG(1,("Username %s is invalid on this system\n",user));
249                 SAFE_FREE(user);
250                 SAFE_FREE(client);
251                 data_blob_free(&ap_rep);
252                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
253         }
254
255         /* setup the string used by %U */
256         
257         sub_set_smb_name( real_username );
258         reload_services(True);
259         
260         if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) 
261         {
262                 DEBUG(1,("make_server_info_from_pw failed!\n"));
263                 SAFE_FREE(user);
264                 SAFE_FREE(client);
265                 data_blob_free(&ap_rep);
266                 return ERROR_NT(ret);
267         }
268
269         /* make_server_info_pw does not set the domain. Without this we end up
270          * with the local netbios name in substitutions for %D. */
271
272         if (server_info->sam_account != NULL) {
273                 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
274         }
275
276         /* register_vuid keeps the server info */
277         sess_vuid = register_vuid(server_info, session_key, nullblob, client);
278
279         SAFE_FREE(user);
280         SAFE_FREE(client);
281
282         if (sess_vuid == -1) {
283                 ret = NT_STATUS_LOGON_FAILURE;
284         } else {
285                 /* current_user_info is changed on new vuid */
286                 reload_services( True );
287
288                 set_message(outbuf,4,0,True);
289                 SSVAL(outbuf, smb_vwv3, 0);
290                         
291                 if (server_info->guest) {
292                         SSVAL(outbuf,smb_vwv2,1);
293                 }
294                 
295                 SSVAL(outbuf, smb_uid, sess_vuid);
296
297                 if (!server_info->guest && !srv_signing_started()) {
298                         /* We need to start the signing engine
299                          * here but a W2K client sends the old
300                          * "BSRSPYL " signature instead of the
301                          * correct one. Subsequent packets will
302                          * be correct.
303                          */
304                         srv_check_sign_mac(inbuf, False);
305                 }
306         }
307
308         /* wrap that up in a nice GSS-API wrapping */
309         if (NT_STATUS_IS_OK(ret)) {
310                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
311         } else {
312                 ap_rep_wrapped = data_blob(NULL, 0);
313         }
314         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
315         reply_sesssetup_blob(conn, outbuf, response, ret);
316
317         data_blob_free(&ap_rep);
318         data_blob_free(&ap_rep_wrapped);
319         data_blob_free(&response);
320
321         return -1; /* already replied */
322 }
323 #endif
324
325 /****************************************************************************
326  Send a session setup reply, wrapped in SPNEGO.
327  Get vuid and check first.
328  End the NTLMSSP exchange context if we are OK/complete fail
329 ***************************************************************************/
330
331 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
332                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
333                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) 
334 {
335         BOOL ret;
336         DATA_BLOB response;
337         struct auth_serversupplied_info *server_info = NULL;
338
339         if (NT_STATUS_IS_OK(nt_status)) {
340                 server_info = (*auth_ntlmssp_state)->server_info;
341         } else {
342                 nt_status = do_map_to_guest(nt_status, 
343                                             &server_info, 
344                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
345                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
346         }
347
348         if (NT_STATUS_IS_OK(nt_status)) {
349                 int sess_vuid;
350                 DATA_BLOB nullblob = data_blob(NULL, 0);
351                 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
352
353                 /* register_vuid keeps the server info */
354                 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
355                 (*auth_ntlmssp_state)->server_info = NULL;
356
357                 if (sess_vuid == -1) {
358                         nt_status = NT_STATUS_LOGON_FAILURE;
359                 } else {
360                         
361                         /* current_user_info is changed on new vuid */
362                         reload_services( True );
363
364                         set_message(outbuf,4,0,True);
365                         SSVAL(outbuf, smb_vwv3, 0);
366                         
367                         if (server_info->guest) {
368                                 SSVAL(outbuf,smb_vwv2,1);
369                         }
370                         
371                         SSVAL(outbuf,smb_uid,sess_vuid);
372
373                         if (!server_info->guest && !srv_signing_started()) {
374                                 /* We need to start the signing engine
375                                  * here but a W2K client sends the old
376                                  * "BSRSPYL " signature instead of the
377                                  * correct one. Subsequent packets will
378                                  * be correct.
379                                  */
380
381                                 srv_check_sign_mac(inbuf, False);
382                         }
383                 }
384         }
385
386         response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
387         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
388         data_blob_free(&response);
389
390         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
391            and the other end, that we are not finished yet. */
392
393         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
394                 auth_ntlmssp_end(auth_ntlmssp_state);
395         }
396
397         return ret;
398 }
399
400 /****************************************************************************
401  Reply to a session setup spnego negotiate packet.
402 ****************************************************************************/
403
404 static int reply_spnego_negotiate(connection_struct *conn, 
405                                   char *inbuf,
406                                   char *outbuf,
407                                   int length, int bufsize,
408                                   DATA_BLOB blob1)
409 {
410         char *OIDs[ASN1_MAX_OIDS];
411         DATA_BLOB secblob;
412         int i;
413         DATA_BLOB chal;
414         BOOL got_kerberos = False;
415         NTSTATUS nt_status;
416
417         /* parse out the OIDs and the first sec blob */
418         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
419                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
420         }
421
422         /* only look at the first OID for determining the mechToken --
423            accoirding to RFC2478, we should choose the one we want 
424            and renegotiate, but i smell a client bug here..  
425            
426            Problem observed when connecting to a member (samba box) 
427            of an AD domain as a user in a Samba domain.  Samba member 
428            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 
429            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 
430            NTLMSSP mechtoken.                 --jerry              */
431         
432         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
433             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
434                 got_kerberos = True;
435         }
436                 
437         for (i=0;OIDs[i];i++) {
438                 DEBUG(3,("Got OID %s\n", OIDs[i]));
439                 free(OIDs[i]);
440         }
441         DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
442
443 #ifdef HAVE_KRB5
444         if (got_kerberos && (SEC_ADS == lp_security())) {
445                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
446                                                 length, bufsize, &secblob);
447                 data_blob_free(&secblob);
448                 return ret;
449         }
450 #endif
451
452         if (global_ntlmssp_state) {
453                 auth_ntlmssp_end(&global_ntlmssp_state);
454         }
455
456         nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
457         if (!NT_STATUS_IS_OK(nt_status)) {
458                 return ERROR_NT(nt_status);
459         }
460
461         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
462                                         secblob, &chal);
463
464         data_blob_free(&secblob);
465
466         reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
467                              &chal, nt_status);
468                 
469         data_blob_free(&chal);
470
471         /* already replied */
472         return -1;
473 }
474         
475 /****************************************************************************
476  Reply to a session setup spnego auth packet.
477 ****************************************************************************/
478
479 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
480                              int length, int bufsize,
481                              DATA_BLOB blob1)
482 {
483         DATA_BLOB auth, auth_reply;
484         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
485
486         if (!spnego_parse_auth(blob1, &auth)) {
487 #if 0
488                 file_save("auth.dat", blob1.data, blob1.length);
489 #endif
490                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
491         }
492         
493         if (!global_ntlmssp_state) {
494                 /* auth before negotiatiate? */
495                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
496         }
497         
498         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
499                                                 auth, &auth_reply);
500
501         data_blob_free(&auth);
502
503         reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
504                              &auth_reply, nt_status);
505                 
506         data_blob_free(&auth_reply);
507
508         /* and tell smbd that we have already replied to this packet */
509         return -1;
510 }
511
512 /****************************************************************************
513  Reply to a session setup command.
514 ****************************************************************************/
515
516 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
517                                         char *outbuf,
518                                         int length,int bufsize)
519 {
520         uint8 *p;
521         DATA_BLOB blob1;
522         int ret;
523         size_t bufrem;
524         fstring native_os, native_lanman, primary_domain;
525         char *p2;
526         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
527         enum remote_arch_types ra_type = get_remote_arch();
528
529         DEBUG(3,("Doing spnego session setup\n"));
530
531         if (global_client_caps == 0) {
532                 global_client_caps = IVAL(inbuf,smb_vwv10);
533
534                 if (!(global_client_caps & CAP_STATUS32)) {
535                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
536                 }
537
538         }
539                 
540         p = (uint8 *)smb_buf(inbuf);
541
542         if (data_blob_len == 0) {
543                 /* an invalid request */
544                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
545         }
546
547         bufrem = smb_bufrem(inbuf, p);
548         /* pull the spnego blob */
549         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
550
551 #if 0
552         file_save("negotiate.dat", blob1.data, blob1.length);
553 #endif
554
555         p2 = inbuf + smb_vwv13 + data_blob_len;
556         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
557         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
558         p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
559         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
560                 native_os, native_lanman, primary_domain));
561
562         if ( ra_type == RA_WIN2K ) {
563                 /* Windows 2003 doesn't set the native lanman string, 
564                    but does set primary domain which is a bug I think */
565                            
566                 if ( !strlen(native_lanman) )
567                         ra_lanman_string( primary_domain );
568                 else
569                         ra_lanman_string( native_lanman );
570         }
571                 
572         if (blob1.data[0] == ASN1_APPLICATION(0)) {
573                 /* its a negTokenTarg packet */
574                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
575                 data_blob_free(&blob1);
576                 return ret;
577         }
578
579         if (blob1.data[0] == ASN1_CONTEXT(1)) {
580                 /* its a auth packet */
581                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
582                 data_blob_free(&blob1);
583                 return ret;
584         }
585
586         /* what sort of packet is this? */
587         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
588
589         data_blob_free(&blob1);
590
591         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
592 }
593
594 /****************************************************************************
595  On new VC == 0, shutdown *all* old connections and users.
596  It seems that only NT4.x does this. At W2K and above (XP etc.).
597  a new session setup with VC==0 is ignored.
598 ****************************************************************************/
599
600 static void setup_new_vc_session(void)
601 {
602         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
603 #if 0
604         conn_close_all();
605         invalidate_all_vuids();
606 #endif
607 }
608
609 /****************************************************************************
610  Reply to a session setup command.
611 ****************************************************************************/
612
613 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
614                           int length,int bufsize)
615 {
616         int sess_vuid;
617         int   smb_bufsize;    
618         DATA_BLOB lm_resp;
619         DATA_BLOB nt_resp;
620         DATA_BLOB plaintext_password;
621         fstring user;
622         fstring sub_user; /* Sainitised username for substituion */
623         fstring domain;
624         fstring native_os;
625         fstring native_lanman;
626         fstring primary_domain;
627         static BOOL done_sesssetup = False;
628         extern BOOL global_encrypted_passwords_negotiated;
629         extern BOOL global_spnego_negotiated;
630         extern int Protocol;
631         extern int max_send;
632
633         auth_usersupplied_info *user_info = NULL;
634         extern struct auth_context *negprot_global_auth_context;
635         auth_serversupplied_info *server_info = NULL;
636
637         NTSTATUS nt_status;
638
639         BOOL doencrypt = global_encrypted_passwords_negotiated;
640
641         DATA_BLOB session_key;
642         
643         START_PROFILE(SMBsesssetupX);
644
645         ZERO_STRUCT(lm_resp);
646         ZERO_STRUCT(nt_resp);
647         ZERO_STRUCT(plaintext_password);
648
649         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
650
651         /* a SPNEGO session setup has 12 command words, whereas a normal
652            NT1 session setup has 13. See the cifs spec. */
653         if (CVAL(inbuf, smb_wct) == 12 &&
654             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
655                 if (!global_spnego_negotiated) {
656                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
657                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
658                 }
659
660                 if (SVAL(inbuf,smb_vwv4) == 0) {
661                         setup_new_vc_session();
662                 }
663                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
664         }
665
666         smb_bufsize = SVAL(inbuf,smb_vwv2);
667
668         if (Protocol < PROTOCOL_NT1) {
669                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
670                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
671                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
672                 }
673
674                 if (doencrypt) {
675                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
676                 } else {
677                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
678                         /* Ensure null termination */
679                         plaintext_password.data[passlen1] = 0;
680                 }
681
682                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
683                 *domain = 0;
684
685         } else {
686                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
687                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
688                 enum remote_arch_types ra_type = get_remote_arch();
689                 char *p = smb_buf(inbuf);    
690                 char *save_p = smb_buf(inbuf);
691                 uint16 byte_count;
692                         
693
694                 if(global_client_caps == 0) {
695                         global_client_caps = IVAL(inbuf,smb_vwv11);
696                 
697                         if (!(global_client_caps & CAP_STATUS32)) {
698                                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
699                         }
700
701                         /* client_caps is used as final determination if client is NT or Win95. 
702                            This is needed to return the correct error codes in some
703                            circumstances.
704                         */
705                 
706                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
707                                 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
708                                         set_remote_arch( RA_WIN95);
709                                 }
710                         }
711                 }
712
713                 if (!doencrypt) {
714                         /* both Win95 and WinNT stuff up the password lengths for
715                            non-encrypting systems. Uggh. 
716                            
717                            if passlen1==24 its a win95 system, and its setting the
718                            password length incorrectly. Luckily it still works with the
719                            default code because Win95 will null terminate the password
720                            anyway 
721                            
722                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
723                            setting passlen2 to some random value which really stuffs
724                            things up. we need to fix that one.  */
725                         
726                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
727                                 passlen2 = 0;
728                 }
729                 
730                 /* check for nasty tricks */
731                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
732                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
733                 }
734
735                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
736                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
737                 }
738
739                 /* Save the lanman2 password and the NT md4 password. */
740                 
741                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
742                         doencrypt = False;
743                 }
744
745                 if (doencrypt) {
746                         lm_resp = data_blob(p, passlen1);
747                         nt_resp = data_blob(p+passlen1, passlen2);
748                 } else {
749                         pstring pass;
750                         BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
751
752                         if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
753                                 /* NT4.0 stuffs up plaintext unicode password lengths... */
754                                 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
755                                         sizeof(pass), passlen1, STR_TERMINATE);
756                         } else {
757                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), 
758                                         sizeof(pass),  unic ? passlen2 : passlen1, 
759                                         STR_TERMINATE);
760                         }
761                         plaintext_password = data_blob(pass, strlen(pass)+1);
762                 }
763                 
764                 p += passlen1 + passlen2;
765                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
766                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
767                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
768                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
769
770                 /* not documented or decoded by Ethereal but there is one more string 
771                    in the extra bytes which is the same as the PrimaryDomain when using 
772                    extended security.  Windows NT 4 and 2003 use this string to store 
773                    the native lanman string. Windows 9x does not include a string here 
774                    at all so we have to check if we have any extra bytes left */
775                 
776                 byte_count = SVAL(inbuf, smb_vwv13);
777                 if ( PTR_DIFF(p, save_p) < byte_count)
778                         p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
779                 else 
780                         fstrcpy( primary_domain, "null" );
781
782                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
783                          domain, native_os, native_lanman, primary_domain));
784
785                 if ( ra_type == RA_WIN2K ) {
786                         if ( strlen(native_lanman) == 0 )
787                                 ra_lanman_string( primary_domain );
788                         else
789                                 ra_lanman_string( native_lanman );
790                 }
791
792         }
793
794         if (SVAL(inbuf,smb_vwv4) == 0) {
795                 setup_new_vc_session();
796         }
797
798         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
799
800         if (*user) {
801                 if (global_spnego_negotiated) {
802                         
803                         /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
804                         
805                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
806                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
807                 }
808                 fstrcpy(sub_user, user);
809
810                 /* setup the string used by %U */
811                 sub_set_smb_name(user);
812         } else {
813                 fstrcpy(sub_user, lp_guestaccount());
814         }
815
816         sub_set_smb_name(sub_user);
817
818         reload_services(True);
819         
820         if (lp_security() == SEC_SHARE) {
821                 /* in share level we should ignore any passwords */
822
823                 data_blob_free(&lm_resp);
824                 data_blob_free(&nt_resp);
825                 data_blob_clear_free(&plaintext_password);
826
827                 map_username(sub_user);
828                 add_session_user(sub_user);
829                 /* Then force it to null for the benfit of the code below */
830                 *user = 0;
831         }
832         
833         if (!*user) {
834
835                 nt_status = check_guest_password(&server_info);
836
837         } else if (doencrypt) {
838                 if (!negprot_global_auth_context) {
839                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
840                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
841                 }
842                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
843                                                          lm_resp, nt_resp);
844                 if (NT_STATUS_IS_OK(nt_status)) {
845                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
846                                                                                      user_info, 
847                                                                                      &server_info);
848                 }
849         } else {
850                 struct auth_context *plaintext_auth_context = NULL;
851                 const uint8 *chal;
852                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
853                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
854                         
855                         if (!make_user_info_for_reply(&user_info, 
856                                                       user, domain, chal,
857                                                       plaintext_password)) {
858                                 nt_status = NT_STATUS_NO_MEMORY;
859                         }
860                 
861                         if (NT_STATUS_IS_OK(nt_status)) {
862                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
863                                                                                         user_info, 
864                                                                                         &server_info); 
865                                 
866                                 (plaintext_auth_context->free)(&plaintext_auth_context);
867                         }
868                 }
869         }
870
871         free_user_info(&user_info);
872         
873         if (!NT_STATUS_IS_OK(nt_status)) {
874                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
875         }
876         
877         if (!NT_STATUS_IS_OK(nt_status)) {
878                 data_blob_free(&nt_resp);
879                 data_blob_free(&lm_resp);
880                 data_blob_clear_free(&plaintext_password);
881                 return ERROR_NT(nt_status_squash(nt_status));
882         }
883
884         if (server_info->nt_session_key.data) {
885                 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
886         } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
887                 session_key = data_blob(NULL, 16);
888                 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data, 
889                                    session_key.data);
890         } else {
891                 session_key = data_blob(NULL, 0);
892         }
893
894         data_blob_free(&lm_resp);
895         data_blob_clear_free(&plaintext_password);
896         
897         /* it's ok - setup a reply */
898         set_message(outbuf,3,0,True);
899         if (Protocol >= PROTOCOL_NT1) {
900                 char *p = smb_buf( outbuf );
901                 p += add_signature( outbuf, p );
902                 set_message_end( outbuf, p );
903                 /* perhaps grab OS version here?? */
904         }
905         
906         if (server_info->guest) {
907                 SSVAL(outbuf,smb_vwv2,1);
908         }
909
910         /* register the name and uid as being validated, so further connections
911            to a uid can get through without a password, on the same VC */
912
913         /* register_vuid keeps the server info */
914         sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
915         data_blob_free(&nt_resp);
916
917         if (sess_vuid == -1) {
918                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
919         }
920
921         /* current_user_info is changed on new vuid */
922         reload_services( True );
923
924         if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
925                 exit_server("reply_sesssetup_and_X: bad smb signature");
926         }
927
928         SSVAL(outbuf,smb_uid,sess_vuid);
929         SSVAL(inbuf,smb_uid,sess_vuid);
930         
931         if (!done_sesssetup)
932                 max_send = MIN(max_send,smb_bufsize);
933         
934         done_sesssetup = True;
935         
936         END_PROFILE(SMBsesssetupX);
937         return chain_reply(inbuf,outbuf,length,bufsize);
938 }