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