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