r11909: Implement 'reset on zero vc'. This kills other connections when a session
[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 /*
29   on a logon error possibly map the error to success if "map to guest"
30   is set approriately
31 */
32 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
33                                 const char *user, const char *domain)
34 {
35         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
36                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
37                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
38                         DEBUG(3,("No such user %s [%s] - using guest account\n",
39                                  user, domain));
40                         status = make_server_info_guest(server_info);
41                 }
42         }
43
44         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
45                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
46                         DEBUG(3,("Registered username %s for guest access\n",user));
47                         status = make_server_info_guest(server_info);
48                 }
49         }
50
51         return status;
52 }
53
54 /****************************************************************************
55  Add the standard 'Samba' signature to the end of the session setup.
56 ****************************************************************************/
57
58 static int add_signature(char *outbuf, char *p)
59 {
60         char *start = p;
61         fstring lanman;
62
63         fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
64
65         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
66         p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
67         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
68
69         return PTR_DIFF(p, start);
70 }
71
72 /****************************************************************************
73  Send a security blob via a session setup reply.
74 ****************************************************************************/
75
76 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
77                                  DATA_BLOB blob, NTSTATUS nt_status)
78 {
79         char *p;
80
81         set_message(outbuf,4,0,True);
82
83         nt_status = nt_status_squash(nt_status);
84         SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86         SSVAL(outbuf, smb_vwv3, blob.length);
87         p = smb_buf(outbuf);
88
89         /* should we cap this? */
90         memcpy(p, blob.data, blob.length);
91         p += blob.length;
92
93         p += add_signature( outbuf, p );
94
95         set_message_end(outbuf,p);
96
97         show_msg(outbuf);
98         return send_smb(smbd_server_fd(),outbuf);
99 }
100
101 /****************************************************************************
102  Do a 'guest' logon, getting back the 
103 ****************************************************************************/
104
105 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
106 {
107         struct auth_context *auth_context;
108         auth_usersupplied_info *user_info = NULL;
109         
110         NTSTATUS nt_status;
111         unsigned char chal[8];
112
113         ZERO_STRUCT(chal);
114
115         DEBUG(3,("Got anonymous request\n"));
116
117         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
118                 return nt_status;
119         }
120
121         if (!make_user_info_guest(&user_info)) {
122                 (auth_context->free)(&auth_context);
123                 return NT_STATUS_NO_MEMORY;
124         }
125         
126         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
127         (auth_context->free)(&auth_context);
128         free_user_info(&user_info);
129         return nt_status;
130 }
131
132
133 #ifdef HAVE_KRB5
134 /****************************************************************************
135 reply to a session setup spnego negotiate packet for kerberos
136 ****************************************************************************/
137 static int reply_spnego_kerberos(connection_struct *conn, 
138                                  char *inbuf, char *outbuf,
139                                  int length, int bufsize,
140                                  DATA_BLOB *secblob)
141 {
142         TALLOC_CTX *mem_ctx;
143         DATA_BLOB ticket;
144         char *client, *p, *domain;
145         fstring netbios_domain_name;
146         struct passwd *pw;
147         fstring user;
148         int sess_vuid;
149         NTSTATUS ret;
150         PAC_DATA *pac_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         BOOL map_domainuser_to_guest = False;
158         PAC_LOGON_INFO *logon_info = NULL;
159
160         ZERO_STRUCT(ticket);
161         ZERO_STRUCT(pac_data);
162         ZERO_STRUCT(ap_rep);
163         ZERO_STRUCT(ap_rep_wrapped);
164         ZERO_STRUCT(response);
165
166         mem_ctx = talloc_init("reply_spnego_kerberos");
167         if (mem_ctx == NULL)
168                 return ERROR_NT(NT_STATUS_NO_MEMORY);
169
170         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
171                 talloc_destroy(mem_ctx);
172                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
173         }
174
175         ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
176
177         data_blob_free(&ticket);
178
179         if (!NT_STATUS_IS_OK(ret)) {
180                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
181                 talloc_destroy(mem_ctx);
182                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
183         }
184
185         DEBUG(3,("Ticket name is [%s]\n", client));
186
187         p = strchr_m(client, '@');
188         if (!p) {
189                 DEBUG(3,("Doesn't look like a valid principal\n"));
190                 data_blob_free(&ap_rep);
191                 data_blob_free(&session_key);
192                 SAFE_FREE(client);
193                 talloc_destroy(mem_ctx);
194                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
195         }
196
197         *p = 0;
198
199         /* save the PAC data if we have it */
200
201         if (pac_data) {
202                 logon_info = get_logon_info_from_pac(pac_data);
203                 netsamlogon_cache_store( client, &logon_info->info3 );
204         }
205
206         if (!strequal(p+1, lp_realm())) {
207                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
208                 if (!lp_allow_trusted_domains()) {
209                         data_blob_free(&ap_rep);
210                         data_blob_free(&session_key);
211                         SAFE_FREE(client);
212                         talloc_destroy(mem_ctx);
213                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
214                 }
215         }
216
217         /* this gives a fully qualified user name (ie. with full realm).
218            that leads to very long usernames, but what else can we do? */
219
220         domain = p+1;
221
222         if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
223
224                 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
225                 domain = netbios_domain_name;
226                 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
227
228         } else {
229
230                 /* If we have winbind running, we can (and must) shorten the
231                    username by using the short netbios name. Otherwise we will
232                    have inconsistent user names. With Kerberos, we get the
233                    fully qualified realm, with ntlmssp we get the short
234                    name. And even w2k3 does use ntlmssp if you for example
235                    connect to an ip address. */
236
237                 struct winbindd_request wb_request;
238                 struct winbindd_response wb_response;
239                 NSS_STATUS wb_result;
240
241                 ZERO_STRUCT(wb_request);
242                 ZERO_STRUCT(wb_response);
243
244                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
245
246                 fstrcpy(wb_request.domain_name, domain);
247
248                 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
249                                              &wb_request, &wb_response);
250
251                 if (wb_result == NSS_STATUS_SUCCESS) {
252
253                         fstrcpy(netbios_domain_name,
254                                 wb_response.data.domain_info.name);
255                         domain = netbios_domain_name;
256
257                         DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
258                 } else {
259                         DEBUG(3, ("Could not find short name -- winbind "
260                                   "not running?\n"));
261                 }
262         }
263
264         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
265         
266         /* lookup the passwd struct, create a new user if necessary */
267
268         map_username( user );
269
270         pw = smb_getpwnam( user, real_username, True );
271         if (!pw) {
272
273                 /* this was originally the behavior of Samba 2.2, if a user
274                    did not have a local uid but has been authenticated, then 
275                    map them to a guest account */
276
277                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ 
278                         map_domainuser_to_guest = True;
279                         fstrcpy(user,lp_guestaccount());
280                         pw = smb_getpwnam( user, real_username, True );
281                 } 
282
283                 /* extra sanity check that the guest account is valid */
284
285                 if ( !pw ) {
286                         DEBUG(1,("Username %s is invalid on this system\n", user));
287                         SAFE_FREE(client);
288                         data_blob_free(&ap_rep);
289                         data_blob_free(&session_key);
290                         talloc_destroy(mem_ctx);
291                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
292                 }
293         }
294
295         /* setup the string used by %U */
296         
297         sub_set_smb_name( real_username );
298         reload_services(True);
299         if ( map_domainuser_to_guest ) {
300                 make_server_info_guest(&server_info);
301         } else if (logon_info) {
302                 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
303
304                 if ( !NT_STATUS_IS_OK(ret) ) {
305                         DEBUG(1,("make_server_info_pac failed!\n"));
306                         SAFE_FREE(client);
307                         data_blob_free(&ap_rep);
308                         data_blob_free(&session_key);
309                         passwd_free(&pw);
310                         talloc_destroy(mem_ctx);
311                         return ERROR_NT(ret);
312                 }
313
314         } else {
315                 ret = make_server_info_pw(&server_info, real_username, pw);
316
317                 if ( !NT_STATUS_IS_OK(ret) ) {
318                         DEBUG(1,("make_server_info_from_pw failed!\n"));
319                         SAFE_FREE(client);
320                         data_blob_free(&ap_rep);
321                         data_blob_free(&session_key);
322                         passwd_free(&pw);
323                         talloc_destroy(mem_ctx);
324                         return ERROR_NT(ret);
325                 }
326
327                 /* make_server_info_pw does not set the domain. Without this we end up
328                  * with the local netbios name in substitutions for %D. */
329
330                 if (server_info->sam_account != NULL) {
331                         pdb_set_domain(server_info->sam_account, domain, PDB_SET);
332                 }
333         }
334
335
336         passwd_free(&pw);
337
338         /* register_vuid keeps the server info */
339         /* register_vuid takes ownership of session_key, no need to free after this.
340            A better interface would copy it.... */
341         sess_vuid = register_vuid(server_info, session_key, nullblob, client);
342
343         SAFE_FREE(client);
344
345         if (sess_vuid == -1) {
346                 ret = NT_STATUS_LOGON_FAILURE;
347         } else {
348                 /* current_user_info is changed on new vuid */
349                 reload_services( True );
350
351                 set_message(outbuf,4,0,True);
352                 SSVAL(outbuf, smb_vwv3, 0);
353                         
354                 if (server_info->guest) {
355                         SSVAL(outbuf,smb_vwv2,1);
356                 }
357                 
358                 SSVAL(outbuf, smb_uid, sess_vuid);
359
360                 if (!server_info->guest && !srv_signing_started()) {
361                         /* We need to start the signing engine
362                          * here but a W2K client sends the old
363                          * "BSRSPYL " signature instead of the
364                          * correct one. Subsequent packets will
365                          * be correct.
366                          */
367                         srv_check_sign_mac(inbuf, False);
368                 }
369         }
370
371         /* wrap that up in a nice GSS-API wrapping */
372         if (NT_STATUS_IS_OK(ret)) {
373                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
374         } else {
375                 ap_rep_wrapped = data_blob(NULL, 0);
376         }
377         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
378         reply_sesssetup_blob(conn, outbuf, response, ret);
379
380         data_blob_free(&ap_rep);
381         data_blob_free(&ap_rep_wrapped);
382         data_blob_free(&response);
383         talloc_destroy(mem_ctx);
384
385         return -1; /* already replied */
386 }
387 #endif
388
389 /****************************************************************************
390  Send a session setup reply, wrapped in SPNEGO.
391  Get vuid and check first.
392  End the NTLMSSP exchange context if we are OK/complete fail
393  This should be split into two functions, one to handle each
394  leg of the NTLM auth steps.
395 ***************************************************************************/
396
397 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
398                                  uint16 vuid,
399                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
400                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, 
401                                  BOOL wrap) 
402 {
403         BOOL ret;
404         DATA_BLOB response;
405         struct auth_serversupplied_info *server_info = NULL;
406
407         if (NT_STATUS_IS_OK(nt_status)) {
408                 server_info = (*auth_ntlmssp_state)->server_info;
409         } else {
410                 nt_status = do_map_to_guest(nt_status, 
411                                             &server_info, 
412                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
413                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
414         }
415
416         if (NT_STATUS_IS_OK(nt_status)) {
417                 int sess_vuid;
418                 DATA_BLOB nullblob = data_blob(NULL, 0);
419                 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
420
421                 /* register_vuid keeps the server info */
422                 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
423                 (*auth_ntlmssp_state)->server_info = NULL;
424
425                 if (sess_vuid == -1) {
426                         nt_status = NT_STATUS_LOGON_FAILURE;
427                 } else {
428                         
429                         /* current_user_info is changed on new vuid */
430                         reload_services( True );
431
432                         set_message(outbuf,4,0,True);
433                         SSVAL(outbuf, smb_vwv3, 0);
434                         
435                         if (server_info->guest) {
436                                 SSVAL(outbuf,smb_vwv2,1);
437                         }
438                         
439                         SSVAL(outbuf,smb_uid,sess_vuid);
440
441                         if (!server_info->guest && !srv_signing_started()) {
442                                 /* We need to start the signing engine
443                                  * here but a W2K client sends the old
444                                  * "BSRSPYL " signature instead of the
445                                  * correct one. Subsequent packets will
446                                  * be correct.
447                                  */
448
449                                 srv_check_sign_mac(inbuf, False);
450                         }
451                 }
452         }
453
454         if (wrap) {
455                 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
456         } else {
457                 response = *ntlmssp_blob;
458         }
459
460         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
461         if (wrap) {
462                 data_blob_free(&response);
463         }
464
465         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
466            and the other end, that we are not finished yet. */
467
468         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
469                 /* NB. This is *NOT* an error case. JRA */
470                 auth_ntlmssp_end(auth_ntlmssp_state);
471                 /* Kill the intermediate vuid */
472                 invalidate_vuid(vuid);
473         }
474
475         return ret;
476 }
477
478 /****************************************************************************
479  Reply to a session setup spnego negotiate packet.
480 ****************************************************************************/
481
482 static int reply_spnego_negotiate(connection_struct *conn, 
483                                   char *inbuf,
484                                   char *outbuf,
485                                   uint16 vuid,
486                                   int length, int bufsize,
487                                   DATA_BLOB blob1,
488                                   AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
489 {
490         char *OIDs[ASN1_MAX_OIDS];
491         DATA_BLOB secblob;
492         int i;
493         DATA_BLOB chal;
494 #ifdef HAVE_KRB5
495         BOOL got_kerberos_mechanism = False;
496 #endif
497         NTSTATUS nt_status;
498
499         /* parse out the OIDs and the first sec blob */
500         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
501                 /* Kill the intermediate vuid */
502                 invalidate_vuid(vuid);
503
504                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
505         }
506
507         /* only look at the first OID for determining the mechToken --
508            accoirding to RFC2478, we should choose the one we want 
509            and renegotiate, but i smell a client bug here..  
510            
511            Problem observed when connecting to a member (samba box) 
512            of an AD domain as a user in a Samba domain.  Samba member 
513            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 
514            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 
515            NTLMSSP mechtoken.                 --jerry              */
516
517 #ifdef HAVE_KRB5        
518         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
519             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
520                 got_kerberos_mechanism = True;
521         }
522 #endif
523                 
524         for (i=0;OIDs[i];i++) {
525                 DEBUG(3,("Got OID %s\n", OIDs[i]));
526                 free(OIDs[i]);
527         }
528         DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
529
530 #ifdef HAVE_KRB5
531         if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
532                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
533                                                 length, bufsize, &secblob);
534                 data_blob_free(&secblob);
535                 /* Kill the intermediate vuid */
536                 invalidate_vuid(vuid);
537
538                 return ret;
539         }
540 #endif
541
542         if (*auth_ntlmssp_state) {
543                 auth_ntlmssp_end(auth_ntlmssp_state);
544         }
545
546         nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
547         if (!NT_STATUS_IS_OK(nt_status)) {
548                 /* Kill the intermediate vuid */
549                 invalidate_vuid(vuid);
550
551                 return ERROR_NT(nt_status);
552         }
553
554         nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
555                                         secblob, &chal);
556
557         data_blob_free(&secblob);
558
559         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
560                              &chal, nt_status, True);
561
562         data_blob_free(&chal);
563
564         /* already replied */
565         return -1;
566 }
567         
568 /****************************************************************************
569  Reply to a session setup spnego auth packet.
570 ****************************************************************************/
571
572 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
573                              uint16 vuid,
574                              int length, int bufsize,
575                              DATA_BLOB blob1,
576                              AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
577 {
578         DATA_BLOB auth, auth_reply;
579         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
580
581         if (!spnego_parse_auth(blob1, &auth)) {
582 #if 0
583                 file_save("auth.dat", blob1.data, blob1.length);
584 #endif
585                 /* Kill the intermediate vuid */
586                 invalidate_vuid(vuid);
587
588                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
589         }
590         
591         if (!*auth_ntlmssp_state) {
592                 /* Kill the intermediate vuid */
593                 invalidate_vuid(vuid);
594
595                 /* auth before negotiatiate? */
596                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
597         }
598         
599         nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
600                                         auth, &auth_reply);
601
602         data_blob_free(&auth);
603
604         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
605                              auth_ntlmssp_state,
606                              &auth_reply, nt_status, True);
607                 
608         data_blob_free(&auth_reply);
609
610         /* and tell smbd that we have already replied to this packet */
611         return -1;
612 }
613
614 /****************************************************************************
615  Reply to a session setup command.
616 ****************************************************************************/
617
618 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
619                                         char *outbuf,
620                                         int length,int bufsize)
621 {
622         uint8 *p;
623         DATA_BLOB blob1;
624         int ret;
625         size_t bufrem;
626         fstring native_os, native_lanman, primary_domain;
627         char *p2;
628         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
629         enum remote_arch_types ra_type = get_remote_arch();
630         int vuid = SVAL(inbuf,smb_uid);
631         user_struct *vuser = NULL;
632
633         DEBUG(3,("Doing spnego session setup\n"));
634
635         if (global_client_caps == 0) {
636                 global_client_caps = IVAL(inbuf,smb_vwv10);
637
638                 if (!(global_client_caps & CAP_STATUS32)) {
639                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
640                 }
641
642         }
643                 
644         p = (uint8 *)smb_buf(inbuf);
645
646         if (data_blob_len == 0) {
647                 /* an invalid request */
648                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
649         }
650
651         bufrem = smb_bufrem(inbuf, p);
652         /* pull the spnego blob */
653         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
654
655 #if 0
656         file_save("negotiate.dat", blob1.data, blob1.length);
657 #endif
658
659         p2 = inbuf + smb_vwv13 + data_blob_len;
660         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
661         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
662         p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
663         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
664                 native_os, native_lanman, primary_domain));
665
666         if ( ra_type == RA_WIN2K ) {
667                 /* Windows 2003 doesn't set the native lanman string, 
668                    but does set primary domain which is a bug I think */
669                            
670                 if ( !strlen(native_lanman) )
671                         ra_lanman_string( primary_domain );
672                 else
673                         ra_lanman_string( native_lanman );
674         }
675                 
676         vuser = get_partial_auth_user_struct(vuid);
677         if (!vuser) {
678                 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
679                 if (vuid == -1) {
680                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
681                 }
682         
683                 vuser = get_partial_auth_user_struct(vuid);
684         }
685
686         if (!vuser) {
687                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
688         }
689         
690         SSVAL(outbuf,smb_uid,vuid);
691         
692         if (blob1.data[0] == ASN1_APPLICATION(0)) {
693                 /* its a negTokenTarg packet */
694                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
695                                              &vuser->auth_ntlmssp_state);
696                 data_blob_free(&blob1);
697                 return ret;
698         }
699
700         if (blob1.data[0] == ASN1_CONTEXT(1)) {
701                 /* its a auth packet */
702                 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
703                                         &vuser->auth_ntlmssp_state);
704                 data_blob_free(&blob1);
705                 return ret;
706         }
707
708         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
709                 DATA_BLOB chal;
710                 NTSTATUS nt_status;
711                 if (!vuser->auth_ntlmssp_state) {
712                         nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
713                         if (!NT_STATUS_IS_OK(nt_status)) {
714                                 /* Kill the intermediate vuid */
715                                 invalidate_vuid(vuid);
716                                 
717                                 return ERROR_NT(nt_status);
718                         }
719                 }
720
721                 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
722                                                 blob1, &chal);
723                 
724                 data_blob_free(&blob1);
725                 
726                 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
727                                            &vuser->auth_ntlmssp_state,
728                                            &chal, nt_status, False);
729                 data_blob_free(&chal);
730                 return -1;
731         }
732
733         /* what sort of packet is this? */
734         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
735
736         data_blob_free(&blob1);
737
738         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
739 }
740
741 /****************************************************************************
742  On new VC == 0, shutdown *all* old connections and users.
743  It seems that only NT4.x does this. At W2K and above (XP etc.).
744  a new session setup with VC==0 is ignored.
745 ****************************************************************************/
746
747 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
748                                 void *p)
749 {
750         struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
751         const char *ip = (const char *)p;
752
753         if (!process_exists(pid_to_procid(sessionid->pid))) {
754                 return 0;
755         }
756
757         if (sessionid->pid == sys_getpid()) {
758                 return 0;
759         }
760
761         if (strcmp(ip, sessionid->ip_addr) != 0) {
762                 return 0;
763         }
764
765         message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
766                          NULL, 0, True);
767         return 0;
768 }
769
770 static void setup_new_vc_session(void)
771 {
772         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
773 #if 0
774         conn_close_all();
775         invalidate_all_vuids();
776 #endif
777         if (lp_reset_on_zero_vc()) {
778                 session_traverse(shutdown_other_smbds, client_addr());
779         }
780 }
781
782 /****************************************************************************
783  Reply to a session setup command.
784 ****************************************************************************/
785
786 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
787                           int length,int bufsize)
788 {
789         int sess_vuid;
790         int   smb_bufsize;    
791         DATA_BLOB lm_resp;
792         DATA_BLOB nt_resp;
793         DATA_BLOB plaintext_password;
794         fstring user;
795         fstring sub_user; /* Sainitised username for substituion */
796         fstring domain;
797         fstring native_os;
798         fstring native_lanman;
799         fstring primary_domain;
800         static BOOL done_sesssetup = False;
801         extern BOOL global_encrypted_passwords_negotiated;
802         extern BOOL global_spnego_negotiated;
803         extern enum protocol_types Protocol;
804         extern int max_send;
805
806         auth_usersupplied_info *user_info = NULL;
807         extern struct auth_context *negprot_global_auth_context;
808         auth_serversupplied_info *server_info = NULL;
809
810         NTSTATUS nt_status;
811
812         BOOL doencrypt = global_encrypted_passwords_negotiated;
813
814         DATA_BLOB session_key;
815         
816         START_PROFILE(SMBsesssetupX);
817
818         ZERO_STRUCT(lm_resp);
819         ZERO_STRUCT(nt_resp);
820         ZERO_STRUCT(plaintext_password);
821
822         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
823
824         /* a SPNEGO session setup has 12 command words, whereas a normal
825            NT1 session setup has 13. See the cifs spec. */
826         if (CVAL(inbuf, smb_wct) == 12 &&
827             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
828                 if (!global_spnego_negotiated) {
829                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
830                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
831                 }
832
833                 if (SVAL(inbuf,smb_vwv4) == 0) {
834                         setup_new_vc_session();
835                 }
836                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
837         }
838
839         smb_bufsize = SVAL(inbuf,smb_vwv2);
840
841         if (Protocol < PROTOCOL_NT1) {
842                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
843
844                 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
845                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
846
847                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
848                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
849                 }
850
851                 if (doencrypt) {
852                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
853                 } else {
854                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
855                         /* Ensure null termination */
856                         plaintext_password.data[passlen1] = 0;
857                 }
858
859                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
860                 *domain = 0;
861
862         } else {
863                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
864                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
865                 enum remote_arch_types ra_type = get_remote_arch();
866                 char *p = smb_buf(inbuf);    
867                 char *save_p = smb_buf(inbuf);
868                 uint16 byte_count;
869                         
870
871                 if(global_client_caps == 0) {
872                         global_client_caps = IVAL(inbuf,smb_vwv11);
873                 
874                         if (!(global_client_caps & CAP_STATUS32)) {
875                                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
876                         }
877
878                         /* client_caps is used as final determination if client is NT or Win95. 
879                            This is needed to return the correct error codes in some
880                            circumstances.
881                         */
882                 
883                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
884                                 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
885                                         set_remote_arch( RA_WIN95);
886                                 }
887                         }
888                 }
889
890                 if (!doencrypt) {
891                         /* both Win95 and WinNT stuff up the password lengths for
892                            non-encrypting systems. Uggh. 
893                            
894                            if passlen1==24 its a win95 system, and its setting the
895                            password length incorrectly. Luckily it still works with the
896                            default code because Win95 will null terminate the password
897                            anyway 
898                            
899                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
900                            setting passlen2 to some random value which really stuffs
901                            things up. we need to fix that one.  */
902                         
903                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
904                                 passlen2 = 0;
905                 }
906                 
907                 /* check for nasty tricks */
908                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
909                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
910                 }
911
912                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
913                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
914                 }
915
916                 /* Save the lanman2 password and the NT md4 password. */
917                 
918                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
919                         doencrypt = False;
920                 }
921
922                 if (doencrypt) {
923                         lm_resp = data_blob(p, passlen1);
924                         nt_resp = data_blob(p+passlen1, passlen2);
925                 } else {
926                         pstring pass;
927                         BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
928
929 #if 0
930                         /* This was the previous fix. Not sure if it's still valid. JRA. */
931                         if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
932                                 /* NT4.0 stuffs up plaintext unicode password lengths... */
933                                 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
934                                         sizeof(pass), passlen1, STR_TERMINATE);
935 #endif
936
937                         if (unic && (passlen2 == 0) && passlen1) {
938                                 /* Only a ascii plaintext password was sent. */
939                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
940                                         passlen1, STR_TERMINATE|STR_ASCII);
941                         } else {
942                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), 
943                                         sizeof(pass),  unic ? passlen2 : passlen1, 
944                                         STR_TERMINATE);
945                         }
946                         plaintext_password = data_blob(pass, strlen(pass)+1);
947                 }
948                 
949                 p += passlen1 + passlen2;
950                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
951                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
952                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
953                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
954
955                 /* not documented or decoded by Ethereal but there is one more string 
956                    in the extra bytes which is the same as the PrimaryDomain when using 
957                    extended security.  Windows NT 4 and 2003 use this string to store 
958                    the native lanman string. Windows 9x does not include a string here 
959                    at all so we have to check if we have any extra bytes left */
960                 
961                 byte_count = SVAL(inbuf, smb_vwv13);
962                 if ( PTR_DIFF(p, save_p) < byte_count)
963                         p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
964                 else 
965                         fstrcpy( primary_domain, "null" );
966
967                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
968                          domain, native_os, native_lanman, primary_domain));
969
970                 if ( ra_type == RA_WIN2K ) {
971                         if ( strlen(native_lanman) == 0 )
972                                 ra_lanman_string( primary_domain );
973                         else
974                                 ra_lanman_string( native_lanman );
975                 }
976
977         }
978
979         if (SVAL(inbuf,smb_vwv4) == 0) {
980                 setup_new_vc_session();
981         }
982
983         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
984
985         if (*user) {
986                 if (global_spnego_negotiated) {
987                         
988                         /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
989                         
990                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
991                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
992                 }
993                 fstrcpy(sub_user, user);
994         } else {
995                 fstrcpy(sub_user, lp_guestaccount());
996         }
997
998         sub_set_smb_name(sub_user);
999
1000         reload_services(True);
1001         
1002         if (lp_security() == SEC_SHARE) {
1003                 /* in share level we should ignore any passwords */
1004
1005                 data_blob_free(&lm_resp);
1006                 data_blob_free(&nt_resp);
1007                 data_blob_clear_free(&plaintext_password);
1008
1009                 map_username(sub_user);
1010                 add_session_user(sub_user);
1011                 /* Then force it to null for the benfit of the code below */
1012                 *user = 0;
1013         }
1014         
1015         if (!*user) {
1016
1017                 nt_status = check_guest_password(&server_info);
1018
1019         } else if (doencrypt) {
1020                 if (!negprot_global_auth_context) {
1021                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
1022                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1023                 }
1024                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1025                                                          lm_resp, nt_resp);
1026                 if (NT_STATUS_IS_OK(nt_status)) {
1027                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
1028                                                                                      user_info, 
1029                                                                                      &server_info);
1030                 }
1031         } else {
1032                 struct auth_context *plaintext_auth_context = NULL;
1033                 const uint8 *chal;
1034                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1035                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1036                         
1037                         if (!make_user_info_for_reply(&user_info, 
1038                                                       user, domain, chal,
1039                                                       plaintext_password)) {
1040                                 nt_status = NT_STATUS_NO_MEMORY;
1041                         }
1042                 
1043                         if (NT_STATUS_IS_OK(nt_status)) {
1044                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
1045                                                                                         user_info, 
1046                                                                                         &server_info); 
1047                                 
1048                                 (plaintext_auth_context->free)(&plaintext_auth_context);
1049                         }
1050                 }
1051         }
1052
1053         free_user_info(&user_info);
1054         
1055         if (!NT_STATUS_IS_OK(nt_status)) {
1056                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1057         }
1058         
1059         if (!NT_STATUS_IS_OK(nt_status)) {
1060                 data_blob_free(&nt_resp);
1061                 data_blob_free(&lm_resp);
1062                 data_blob_clear_free(&plaintext_password);
1063                 return ERROR_NT(nt_status_squash(nt_status));
1064         }
1065
1066         if (server_info->user_session_key.data) {
1067                 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1068         } else {
1069                 session_key = data_blob(NULL, 0);
1070         }
1071
1072         data_blob_clear_free(&plaintext_password);
1073         
1074         /* it's ok - setup a reply */
1075         set_message(outbuf,3,0,True);
1076         if (Protocol >= PROTOCOL_NT1) {
1077                 char *p = smb_buf( outbuf );
1078                 p += add_signature( outbuf, p );
1079                 set_message_end( outbuf, p );
1080                 /* perhaps grab OS version here?? */
1081         }
1082         
1083         if (server_info->guest) {
1084                 SSVAL(outbuf,smb_vwv2,1);
1085         }
1086
1087         /* register the name and uid as being validated, so further connections
1088            to a uid can get through without a password, on the same VC */
1089
1090         /* register_vuid keeps the server info */
1091         sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1092         data_blob_free(&nt_resp);
1093         data_blob_free(&lm_resp);
1094
1095         if (sess_vuid == -1) {
1096                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1097         }
1098
1099         /* current_user_info is changed on new vuid */
1100         reload_services( True );
1101
1102         if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
1103                 exit_server("reply_sesssetup_and_X: bad smb signature");
1104         }
1105
1106         SSVAL(outbuf,smb_uid,sess_vuid);
1107         SSVAL(inbuf,smb_uid,sess_vuid);
1108         
1109         if (!done_sesssetup)
1110                 max_send = MIN(max_send,smb_bufsize);
1111         
1112         done_sesssetup = True;
1113         
1114         END_PROFILE(SMBsesssetupX);
1115         return chain_reply(inbuf,outbuf,length,bufsize);
1116 }