smbd: fix session setup with security = share.
[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    Copyright (C) Volker Lendecke      2007
9    Copyright (C) Jeremy Allison       2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26
27 extern struct auth_context *negprot_global_auth_context;
28 extern bool global_encrypted_passwords_negotiated;
29 extern bool global_spnego_negotiated;
30 extern enum protocol_types Protocol;
31 extern int max_send;
32
33 uint32 global_client_caps = 0;
34
35 /*
36   on a logon error possibly map the error to success if "map to guest"
37   is set approriately
38 */
39 static NTSTATUS do_map_to_guest(NTSTATUS status,
40                                 auth_serversupplied_info **server_info,
41                                 const char *user, const char *domain)
42 {
43         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46                         DEBUG(3,("No such user %s [%s] - using guest account\n",
47                                  user, domain));
48                         status = make_server_info_guest(server_info);
49                 }
50         }
51
52         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54                         DEBUG(3,("Registered username %s for guest access\n",
55                                 user));
56                         status = make_server_info_guest(server_info);
57                 }
58         }
59
60         return status;
61 }
62
63 /****************************************************************************
64  Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
66
67 static int push_signature(uint8 **outbuf)
68 {
69         char *lanman;
70         int result, tmp;
71
72         result = 0;
73
74         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
75
76         if (tmp == -1) return -1;
77         result += tmp;
78
79         if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
81                 SAFE_FREE(lanman);
82         }
83         else {
84                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
85         }
86
87         if (tmp == -1) return -1;
88         result += tmp;
89
90         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
91
92         if (tmp == -1) return -1;
93         result += tmp;
94
95         return result;
96 }
97
98 /****************************************************************************
99  Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
101
102 static void sessionsetup_start_signing_engine(
103                         const auth_serversupplied_info *server_info,
104                         const uint8 *inbuf)
105 {
106         if (!server_info->guest && !srv_signing_started()) {
107                 /* We need to start the signing engine
108                  * here but a W2K client sends the old
109                  * "BSRSPYL " signature instead of the
110                  * correct one. Subsequent packets will
111                  * be correct.
112                  */
113                 srv_check_sign_mac((char *)inbuf, False);
114         }
115 }
116
117 /****************************************************************************
118  Send a security blob via a session setup reply.
119 ****************************************************************************/
120
121 static void reply_sesssetup_blob(struct smb_request *req,
122                                  DATA_BLOB blob,
123                                  NTSTATUS nt_status)
124 {
125         if (!NT_STATUS_IS_OK(nt_status) &&
126             !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
127                 reply_nterror(req, nt_status_squash(nt_status));
128         } else {
129                 nt_status = nt_status_squash(nt_status);
130                 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
131                 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
132                 SSVAL(req->outbuf, smb_vwv3, blob.length);
133
134                 if ((message_push_blob(&req->outbuf, blob) == -1)
135                     || (push_signature(&req->outbuf) == -1)) {
136                         reply_nterror(req, NT_STATUS_NO_MEMORY);
137                 }
138         }
139
140         show_msg((char *)req->outbuf);
141         srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
142         TALLOC_FREE(req->outbuf);
143 }
144
145 /****************************************************************************
146  Do a 'guest' logon, getting back the
147 ****************************************************************************/
148
149 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
150 {
151         struct auth_context *auth_context;
152         auth_usersupplied_info *user_info = NULL;
153
154         NTSTATUS nt_status;
155         unsigned char chal[8];
156
157         ZERO_STRUCT(chal);
158
159         DEBUG(3,("Got anonymous request\n"));
160
161         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
162                                         chal))) {
163                 return nt_status;
164         }
165
166         if (!make_user_info_guest(&user_info)) {
167                 (auth_context->free)(&auth_context);
168                 return NT_STATUS_NO_MEMORY;
169         }
170
171         nt_status = auth_context->check_ntlm_password(auth_context,
172                                                 user_info,
173                                                 server_info);
174         (auth_context->free)(&auth_context);
175         free_user_info(&user_info);
176         return nt_status;
177 }
178
179
180 #ifdef HAVE_KRB5
181
182 #if 0
183 /* Experiment that failed. See "only happens with a KDC" comment below. */
184 /****************************************************************************
185  Cerate a clock skew error blob for a Windows client.
186 ****************************************************************************/
187
188 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
189 {
190         krb5_context context = NULL;
191         krb5_error_code kerr = 0;
192         krb5_data reply;
193         krb5_principal host_princ = NULL;
194         char *host_princ_s = NULL;
195         bool ret = False;
196
197         *pblob_out = data_blob_null;
198
199         initialize_krb5_error_table();
200         kerr = krb5_init_context(&context);
201         if (kerr) {
202                 return False;
203         }
204         /* Create server principal. */
205         asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
206         if (!host_princ_s) {
207                 goto out;
208         }
209         strlower_m(host_princ_s);
210
211         kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
212         if (kerr) {
213                 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
214                         "for name %s: Error %s\n",
215                         host_princ_s, error_message(kerr) ));
216                 goto out;
217         }
218
219         kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
220                         host_princ, &reply);
221         if (kerr) {
222                 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
223                         "failed: Error %s\n",
224                         error_message(kerr) ));
225                 goto out;
226         }
227
228         *pblob_out = data_blob(reply.data, reply.length);
229         kerberos_free_data_contents(context,&reply);
230         ret = True;
231
232   out:
233
234         if (host_princ_s) {
235                 SAFE_FREE(host_princ_s);
236         }
237         if (host_princ) {
238                 krb5_free_principal(context, host_princ);
239         }
240         krb5_free_context(context);
241         return ret;
242 }
243 #endif
244
245 /****************************************************************************
246  Reply to a session setup spnego negotiate packet for kerberos.
247 ****************************************************************************/
248
249 static void reply_spnego_kerberos(struct smb_request *req,
250                                   DATA_BLOB *secblob,
251                                   uint16 vuid,
252                                   bool *p_invalidate_vuid)
253 {
254         TALLOC_CTX *mem_ctx;
255         DATA_BLOB ticket;
256         char *client, *p, *domain;
257         fstring netbios_domain_name;
258         struct passwd *pw;
259         fstring user;
260         int sess_vuid = req->vuid;
261         NTSTATUS ret = NT_STATUS_OK;
262         struct PAC_DATA *pac_data = NULL;
263         DATA_BLOB ap_rep, ap_rep_wrapped, response;
264         auth_serversupplied_info *server_info = NULL;
265         DATA_BLOB session_key = data_blob_null;
266         uint8 tok_id[2];
267         DATA_BLOB nullblob = data_blob_null;
268         fstring real_username;
269         bool map_domainuser_to_guest = False;
270         bool username_was_mapped;
271         struct PAC_LOGON_INFO *logon_info = NULL;
272
273         ZERO_STRUCT(ticket);
274         ZERO_STRUCT(ap_rep);
275         ZERO_STRUCT(ap_rep_wrapped);
276         ZERO_STRUCT(response);
277
278         /* Normally we will always invalidate the intermediate vuid. */
279         *p_invalidate_vuid = True;
280
281         mem_ctx = talloc_init("reply_spnego_kerberos");
282         if (mem_ctx == NULL) {
283                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
284                 return;
285         }
286
287         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
288                 talloc_destroy(mem_ctx);
289                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
290                 return;
291         }
292
293         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
294                                 &client, &pac_data, &ap_rep,
295                                 &session_key, True);
296
297         data_blob_free(&ticket);
298
299         if (!NT_STATUS_IS_OK(ret)) {
300 #if 0
301                 /* Experiment that failed.
302                  * See "only happens with a KDC" comment below. */
303
304                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
305
306                         /*
307                          * Windows in this case returns
308                          * NT_STATUS_MORE_PROCESSING_REQUIRED
309                          * with a negTokenTarg blob containing an krb5_error
310                          * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
311                          * The client then fixes its clock and continues rather
312                          * than giving an error. JRA.
313                          * -- Looks like this only happens with a KDC. JRA.
314                          */
315
316                         bool ok = make_krb5_skew_error(&ap_rep);
317                         if (!ok) {
318                                 talloc_destroy(mem_ctx);
319                                 return ERROR_NT(nt_status_squash(
320                                                 NT_STATUS_LOGON_FAILURE));
321                         }
322                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
323                                         TOK_ID_KRB_ERROR);
324                         response = spnego_gen_auth_response(&ap_rep_wrapped,
325                                         ret, OID_KERBEROS5_OLD);
326                         reply_sesssetup_blob(conn, inbuf, outbuf, response,
327                                         NT_STATUS_MORE_PROCESSING_REQUIRED);
328
329                         /*
330                          * In this one case we don't invalidate the
331                          * intermediate vuid as we're expecting the client
332                          * to re-use it for the next sessionsetupX packet. JRA.
333                          */
334
335                         *p_invalidate_vuid = False;
336
337                         data_blob_free(&ap_rep);
338                         data_blob_free(&ap_rep_wrapped);
339                         data_blob_free(&response);
340                         talloc_destroy(mem_ctx);
341                         return -1; /* already replied */
342                 }
343 #else
344                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
345                         ret = NT_STATUS_LOGON_FAILURE;
346                 }
347 #endif
348                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
349                                 nt_errstr(ret)));
350                 talloc_destroy(mem_ctx);
351                 reply_nterror(req, nt_status_squash(ret));
352                 return;
353         }
354
355         DEBUG(3,("Ticket name is [%s]\n", client));
356
357         p = strchr_m(client, '@');
358         if (!p) {
359                 DEBUG(3,("Doesn't look like a valid principal\n"));
360                 data_blob_free(&ap_rep);
361                 data_blob_free(&session_key);
362                 SAFE_FREE(client);
363                 talloc_destroy(mem_ctx);
364                 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
365                 return;
366         }
367
368         *p = 0;
369
370         /* save the PAC data if we have it */
371
372         if (pac_data) {
373                 logon_info = get_logon_info_from_pac(pac_data);
374                 if (logon_info) {
375                         netsamlogon_cache_store( client, &logon_info->info3 );
376                 }
377         }
378
379         if (!strequal(p+1, lp_realm())) {
380                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
381                 if (!lp_allow_trusted_domains()) {
382                         data_blob_free(&ap_rep);
383                         data_blob_free(&session_key);
384                         SAFE_FREE(client);
385                         talloc_destroy(mem_ctx);
386                         reply_nterror(req, nt_status_squash(
387                                               NT_STATUS_LOGON_FAILURE));
388                         return;
389                 }
390         }
391
392         /* this gives a fully qualified user name (ie. with full realm).
393            that leads to very long usernames, but what else can we do? */
394
395         domain = p+1;
396
397         if (logon_info && logon_info->info3.base.domain.string) {
398                 fstrcpy(netbios_domain_name,
399                         logon_info->info3.base.domain.string);
400                 domain = netbios_domain_name;
401                 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
402
403         } else {
404
405                 /* If we have winbind running, we can (and must) shorten the
406                    username by using the short netbios name. Otherwise we will
407                    have inconsistent user names. With Kerberos, we get the
408                    fully qualified realm, with ntlmssp we get the short
409                    name. And even w2k3 does use ntlmssp if you for example
410                    connect to an ip address. */
411
412                 wbcErr wbc_status;
413                 struct wbcDomainInfo *info = NULL;
414
415                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
416
417                 wbc_status = wbcDomainInfo(domain, &info);
418
419                 if (WBC_ERROR_IS_OK(wbc_status)) {
420
421                         fstrcpy(netbios_domain_name,
422                                 info->short_name);
423
424                         wbcFreeMemory(info);
425                         domain = netbios_domain_name;
426                         DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
427                 } else {
428                         DEBUG(3, ("Could not find short name: %s\n",
429                                 wbcErrorString(wbc_status)));
430                 }
431         }
432
433         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
434
435         /* lookup the passwd struct, create a new user if necessary */
436
437         username_was_mapped = map_username( user );
438
439         pw = smb_getpwnam( mem_ctx, user, real_username, True );
440
441         if (pw) {
442                 /* if a real user check pam account restrictions */
443                 /* only really perfomed if "obey pam restriction" is true */
444                 /* do this before an eventual mappign to guest occurs */
445                 ret = smb_pam_accountcheck(pw->pw_name);
446                 if (  !NT_STATUS_IS_OK(ret)) {
447                         DEBUG(1,("PAM account restriction "
448                                 "prevents user login\n"));
449                         data_blob_free(&ap_rep);
450                         data_blob_free(&session_key);
451                         TALLOC_FREE(mem_ctx);
452                         reply_nterror(req, nt_status_squash(ret));
453                         return;
454                 }
455         }
456
457         if (!pw) {
458
459                 /* this was originally the behavior of Samba 2.2, if a user
460                    did not have a local uid but has been authenticated, then
461                    map them to a guest account */
462
463                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
464                         map_domainuser_to_guest = True;
465                         fstrcpy(user,lp_guestaccount());
466                         pw = smb_getpwnam( mem_ctx, user, real_username, True );
467                 }
468
469                 /* extra sanity check that the guest account is valid */
470
471                 if ( !pw ) {
472                         DEBUG(1,("Username %s is invalid on this system\n",
473                                 user));
474                         SAFE_FREE(client);
475                         data_blob_free(&ap_rep);
476                         data_blob_free(&session_key);
477                         TALLOC_FREE(mem_ctx);
478                         reply_nterror(req, nt_status_squash(
479                                               NT_STATUS_LOGON_FAILURE));
480                         return;
481                 }
482         }
483
484         /* setup the string used by %U */
485
486         sub_set_smb_name( real_username );
487         reload_services(True);
488
489         if ( map_domainuser_to_guest ) {
490                 make_server_info_guest(&server_info);
491         } else if (logon_info) {
492                 /* pass the unmapped username here since map_username()
493                    will be called again from inside make_server_info_info3() */
494
495                 ret = make_server_info_info3(mem_ctx, client, domain,
496                                              &server_info, &logon_info->info3);
497                 if ( !NT_STATUS_IS_OK(ret) ) {
498                         DEBUG(1,("make_server_info_info3 failed: %s!\n",
499                                  nt_errstr(ret)));
500                         SAFE_FREE(client);
501                         data_blob_free(&ap_rep);
502                         data_blob_free(&session_key);
503                         TALLOC_FREE(mem_ctx);
504                         reply_nterror(req, nt_status_squash(ret));
505                         return;
506                 }
507
508         } else {
509                 ret = make_server_info_pw(&server_info, real_username, pw);
510
511                 if ( !NT_STATUS_IS_OK(ret) ) {
512                         DEBUG(1,("make_server_info_pw failed: %s!\n",
513                                  nt_errstr(ret)));
514                         SAFE_FREE(client);
515                         data_blob_free(&ap_rep);
516                         data_blob_free(&session_key);
517                         TALLOC_FREE(mem_ctx);
518                         reply_nterror(req, nt_status_squash(ret));
519                         return;
520                 }
521
522                 /* make_server_info_pw does not set the domain. Without this
523                  * we end up with the local netbios name in substitutions for
524                  * %D. */
525
526                 if (server_info->sam_account != NULL) {
527                         pdb_set_domain(server_info->sam_account,
528                                         domain, PDB_SET);
529                 }
530         }
531
532         if (username_was_mapped) {
533                 server_info->was_mapped = username_was_mapped;
534         }
535
536         /* we need to build the token for the user. make_server_info_guest()
537            already does this */
538
539         if ( !server_info->ptok ) {
540                 ret = create_local_token( server_info );
541                 if ( !NT_STATUS_IS_OK(ret) ) {
542                         DEBUG(10,("failed to create local token: %s\n",
543                                 nt_errstr(ret)));
544                         SAFE_FREE(client);
545                         data_blob_free(&ap_rep);
546                         data_blob_free(&session_key);
547                         TALLOC_FREE( mem_ctx );
548                         TALLOC_FREE( server_info );
549                         reply_nterror(req, nt_status_squash(ret));
550                         return;
551                 }
552         }
553
554         /* register_existing_vuid keeps the server info */
555         /* register_existing_vuid takes ownership of session_key on success,
556          * no need to free after this on success. A better interface would copy
557          * it.... */
558
559         if (!is_partial_auth_vuid(sess_vuid)) {
560                 sess_vuid = register_initial_vuid();
561         }
562         sess_vuid = register_existing_vuid(sess_vuid,
563                                         server_info,
564                                         session_key,
565                                         nullblob,
566                                         client);
567
568         SAFE_FREE(client);
569
570         reply_outbuf(req, 4, 0);
571         SSVAL(req->outbuf,smb_uid,sess_vuid);
572
573         if (sess_vuid == UID_FIELD_INVALID ) {
574                 ret = NT_STATUS_LOGON_FAILURE;
575                 data_blob_free(&session_key);
576         } else {
577                 /* current_user_info is changed on new vuid */
578                 reload_services( True );
579
580                 SSVAL(req->outbuf, smb_vwv3, 0);
581
582                 if (server_info->guest) {
583                         SSVAL(req->outbuf,smb_vwv2,1);
584                 }
585
586                 SSVAL(req->outbuf, smb_uid, sess_vuid);
587
588                 sessionsetup_start_signing_engine(server_info, req->inbuf);
589                 /* Successful logon. Keep this vuid. */
590                 *p_invalidate_vuid = False;
591         }
592
593         /* wrap that up in a nice GSS-API wrapping */
594         if (NT_STATUS_IS_OK(ret)) {
595                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
596                                 TOK_ID_KRB_AP_REP);
597         } else {
598                 ap_rep_wrapped = data_blob_null;
599         }
600         response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
601                         OID_KERBEROS5_OLD);
602         reply_sesssetup_blob(req, response, ret);
603
604         data_blob_free(&ap_rep);
605         data_blob_free(&ap_rep_wrapped);
606         data_blob_free(&response);
607         TALLOC_FREE(mem_ctx);
608 }
609
610 #endif
611
612 /****************************************************************************
613  Send a session setup reply, wrapped in SPNEGO.
614  Get vuid and check first.
615  End the NTLMSSP exchange context if we are OK/complete fail
616  This should be split into two functions, one to handle each
617  leg of the NTLM auth steps.
618 ***************************************************************************/
619
620 static void reply_spnego_ntlmssp(struct smb_request *req,
621                                  uint16 vuid,
622                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
623                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
624                                  const char *OID,
625                                  bool wrap)
626 {
627         DATA_BLOB response;
628         struct auth_serversupplied_info *server_info = NULL;
629
630         if (NT_STATUS_IS_OK(nt_status)) {
631                 server_info = (*auth_ntlmssp_state)->server_info;
632         } else {
633                 nt_status = do_map_to_guest(nt_status,
634                             &server_info,
635                             (*auth_ntlmssp_state)->ntlmssp_state->user,
636                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
637         }
638
639         reply_outbuf(req, 4, 0);
640
641         SSVAL(req->outbuf, smb_uid, vuid);
642
643         if (NT_STATUS_IS_OK(nt_status)) {
644                 DATA_BLOB nullblob = data_blob_null;
645                 DATA_BLOB session_key =
646                         data_blob(
647                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
648                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
649
650                 if (!is_partial_auth_vuid(vuid)) {
651                         data_blob_free(&session_key);
652                         nt_status = NT_STATUS_LOGON_FAILURE;
653                         goto out;
654                 }
655                 /* register_existing_vuid keeps the server info */
656                 if (register_existing_vuid(vuid,
657                                 server_info,
658                                 session_key, nullblob,
659                                 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
660                                         vuid) {
661                         data_blob_free(&session_key);
662                         nt_status = NT_STATUS_LOGON_FAILURE;
663                         goto out;
664                 }
665
666                 (*auth_ntlmssp_state)->server_info = NULL;
667
668                 /* current_user_info is changed on new vuid */
669                 reload_services( True );
670
671                 SSVAL(req->outbuf, smb_vwv3, 0);
672
673                 if (server_info->guest) {
674                         SSVAL(req->outbuf,smb_vwv2,1);
675                 }
676
677                 sessionsetup_start_signing_engine(server_info,
678                                                   (uint8 *)req->inbuf);
679         }
680
681   out:
682
683         if (wrap) {
684                 response = spnego_gen_auth_response(ntlmssp_blob,
685                                 nt_status, OID);
686         } else {
687                 response = *ntlmssp_blob;
688         }
689
690         reply_sesssetup_blob(req, response, nt_status);
691         if (wrap) {
692                 data_blob_free(&response);
693         }
694
695         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
696            and the other end, that we are not finished yet. */
697
698         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
699                 /* NB. This is *NOT* an error case. JRA */
700                 auth_ntlmssp_end(auth_ntlmssp_state);
701                 if (!NT_STATUS_IS_OK(nt_status)) {
702                         /* Kill the intermediate vuid */
703                         invalidate_vuid(vuid);
704                 }
705         }
706 }
707
708 /****************************************************************************
709  Is this a krb5 mechanism ?
710 ****************************************************************************/
711
712 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
713                 bool *p_is_krb5)
714 {
715         char *OIDs[ASN1_MAX_OIDS];
716         int i;
717
718         *p_is_krb5 = False;
719
720         /* parse out the OIDs and the first sec blob */
721         if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
722                 return NT_STATUS_LOGON_FAILURE;
723         }
724
725         /* only look at the first OID for determining the mechToken --
726            according to RFC2478, we should choose the one we want
727            and renegotiate, but i smell a client bug here..
728
729            Problem observed when connecting to a member (samba box)
730            of an AD domain as a user in a Samba domain.  Samba member
731            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
732            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
733            NTLMSSP mechtoken.                 --jerry              */
734
735 #ifdef HAVE_KRB5
736         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
737             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
738                 *p_is_krb5 = True;
739         }
740 #endif
741
742         for (i=0;OIDs[i];i++) {
743                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
744                 free(OIDs[i]);
745         }
746         return NT_STATUS_OK;
747 }
748
749 /****************************************************************************
750  Fall back from krb5 to NTLMSSP.
751 ****************************************************************************/
752
753 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
754                                                 uint16 vuid)
755 {
756         DATA_BLOB response;
757
758         reply_outbuf(req, 4, 0);
759         SSVAL(req->outbuf,smb_uid,vuid);
760
761         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
762                 "but set to downgrade to NTLMSSP\n"));
763
764         response = spnego_gen_auth_response(NULL,
765                         NT_STATUS_MORE_PROCESSING_REQUIRED,
766                         OID_NTLMSSP);
767         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
768         data_blob_free(&response);
769 }
770
771 /****************************************************************************
772  Reply to a session setup spnego negotiate packet.
773 ****************************************************************************/
774
775 static void reply_spnego_negotiate(struct smb_request *req,
776                                    uint16 vuid,
777                                    DATA_BLOB blob1,
778                                    AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
779 {
780         DATA_BLOB secblob;
781         DATA_BLOB chal;
782         bool got_kerberos_mechanism = False;
783         NTSTATUS status;
784
785         status = parse_spnego_mechanisms(blob1, &secblob,
786                         &got_kerberos_mechanism);
787         if (!NT_STATUS_IS_OK(status)) {
788                 /* Kill the intermediate vuid */
789                 invalidate_vuid(vuid);
790                 reply_nterror(req, nt_status_squash(status));
791                 return;
792         }
793
794         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
795                                 (unsigned long)secblob.length));
796
797 #ifdef HAVE_KRB5
798         if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
799                                 lp_use_kerberos_keytab()) ) {
800                 bool destroy_vuid = True;
801                 reply_spnego_kerberos(req, &secblob, vuid,
802                                       &destroy_vuid);
803                 data_blob_free(&secblob);
804                 if (destroy_vuid) {
805                         /* Kill the intermediate vuid */
806                         invalidate_vuid(vuid);
807                 }
808                 return;
809         }
810 #endif
811
812         if (*auth_ntlmssp_state) {
813                 auth_ntlmssp_end(auth_ntlmssp_state);
814         }
815
816         if (got_kerberos_mechanism) {
817                 data_blob_free(&secblob);
818                 /* The mechtoken is a krb5 ticket, but
819                  * we need to fall back to NTLM. */
820                 reply_spnego_downgrade_to_ntlmssp(req,
821                                         vuid);
822                 return;
823         }
824
825         status = auth_ntlmssp_start(auth_ntlmssp_state);
826         if (!NT_STATUS_IS_OK(status)) {
827                 /* Kill the intermediate vuid */
828                 invalidate_vuid(vuid);
829                 reply_nterror(req, nt_status_squash(status));
830                 return;
831         }
832
833         status = auth_ntlmssp_update(*auth_ntlmssp_state,
834                                         secblob, &chal);
835
836         data_blob_free(&secblob);
837
838         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
839                              &chal, status, OID_NTLMSSP, true);
840
841         data_blob_free(&chal);
842
843         /* already replied */
844         return;
845 }
846
847 /****************************************************************************
848  Reply to a session setup spnego auth packet.
849 ****************************************************************************/
850
851 static void reply_spnego_auth(struct smb_request *req,
852                               uint16 vuid,
853                               DATA_BLOB blob1,
854                               AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
855 {
856         DATA_BLOB auth = data_blob_null;
857         DATA_BLOB auth_reply = data_blob_null;
858         DATA_BLOB secblob = data_blob_null;
859         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
860
861         if (!spnego_parse_auth(blob1, &auth)) {
862 #if 0
863                 file_save("auth.dat", blob1.data, blob1.length);
864 #endif
865                 /* Kill the intermediate vuid */
866                 invalidate_vuid(vuid);
867
868                 reply_nterror(req, nt_status_squash(
869                                       NT_STATUS_LOGON_FAILURE));
870                 return;
871         }
872
873         if (auth.data[0] == ASN1_APPLICATION(0)) {
874                 /* Might be a second negTokenTarg packet */
875
876                 bool got_krb5_mechanism = False;
877                 status = parse_spnego_mechanisms(auth, &secblob,
878                                 &got_krb5_mechanism);
879
880                 if (!NT_STATUS_IS_OK(status)) {
881                         /* Kill the intermediate vuid */
882                         invalidate_vuid(vuid);
883                         reply_nterror(req, nt_status_squash(status));
884                         return;
885                 }
886
887                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
888                                 (unsigned long)secblob.length));
889 #ifdef HAVE_KRB5
890                 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
891                                         lp_use_kerberos_keytab()) ) {
892                         bool destroy_vuid = True;
893                         reply_spnego_kerberos(req, &secblob,
894                                               vuid, &destroy_vuid);
895                         data_blob_free(&secblob);
896                         data_blob_free(&auth);
897                         if (destroy_vuid) {
898                                 /* Kill the intermediate vuid */
899                                 invalidate_vuid(vuid);
900                         }
901                         return;
902                 }
903 #endif
904                 /* Can't blunder into NTLMSSP auth if we have
905                  * a krb5 ticket. */
906
907                 if (got_krb5_mechanism) {
908                         /* Kill the intermediate vuid */
909                         invalidate_vuid(vuid);
910                         DEBUG(3,("reply_spnego_auth: network "
911                                 "misconfiguration, client sent us a "
912                                 "krb5 ticket and kerberos security "
913                                 "not enabled"));
914                         reply_nterror(req, nt_status_squash(
915                                         NT_STATUS_LOGON_FAILURE));
916                 }
917         }
918
919         /* If we get here it wasn't a negTokenTarg auth packet. */
920         data_blob_free(&secblob);
921
922         if (!*auth_ntlmssp_state) {
923                 status = auth_ntlmssp_start(auth_ntlmssp_state);
924                 if (!NT_STATUS_IS_OK(status)) {
925                         /* Kill the intermediate vuid */
926                         invalidate_vuid(vuid);
927                         reply_nterror(req, nt_status_squash(status));
928                         return;
929                 }
930         }
931
932         status = auth_ntlmssp_update(*auth_ntlmssp_state,
933                                         auth, &auth_reply);
934
935         data_blob_free(&auth);
936
937         /* Don't send the mechid as we've already sent this (RFC4178). */
938
939         reply_spnego_ntlmssp(req, vuid,
940                              auth_ntlmssp_state,
941                              &auth_reply, status, NULL, true);
942
943         data_blob_free(&auth_reply);
944
945         /* and tell smbd that we have already replied to this packet */
946         return;
947 }
948
949 /****************************************************************************
950  List to store partial SPNEGO auth fragments.
951 ****************************************************************************/
952
953 static struct pending_auth_data *pd_list;
954
955 /****************************************************************************
956  Delete an entry on the list.
957 ****************************************************************************/
958
959 static void delete_partial_auth(struct pending_auth_data *pad)
960 {
961         if (!pad) {
962                 return;
963         }
964         DLIST_REMOVE(pd_list, pad);
965         data_blob_free(&pad->partial_data);
966         SAFE_FREE(pad);
967 }
968
969 /****************************************************************************
970  Search for a partial SPNEGO auth fragment matching an smbpid.
971 ****************************************************************************/
972
973 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
974 {
975         struct pending_auth_data *pad;
976
977         for (pad = pd_list; pad; pad = pad->next) {
978                 if (pad->smbpid == smbpid) {
979                         break;
980                 }
981         }
982         return pad;
983 }
984
985 /****************************************************************************
986  Check the size of an SPNEGO blob. If we need more return
987  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
988  the blob to be more than 64k.
989 ****************************************************************************/
990
991 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
992                 DATA_BLOB *pblob)
993 {
994         struct pending_auth_data *pad = NULL;
995         ASN1_DATA data;
996         size_t needed_len = 0;
997
998         pad = get_pending_auth_data(smbpid);
999
1000         /* Ensure we have some data. */
1001         if (pblob->length == 0) {
1002                 /* Caller can cope. */
1003                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1004                 delete_partial_auth(pad);
1005                 return NT_STATUS_OK;
1006         }
1007
1008         /* Were we waiting for more data ? */
1009         if (pad) {
1010                 DATA_BLOB tmp_blob;
1011                 size_t copy_len = MIN(65536, pblob->length);
1012
1013                 /* Integer wrap paranoia.... */
1014
1015                 if (pad->partial_data.length + copy_len <
1016                                 pad->partial_data.length ||
1017                     pad->partial_data.length + copy_len < copy_len) {
1018
1019                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
1020                                 "pad->partial_data.length = %u, "
1021                                 "copy_len = %u\n",
1022                                 (unsigned int)pad->partial_data.length,
1023                                 (unsigned int)copy_len ));
1024
1025                         delete_partial_auth(pad);
1026                         return NT_STATUS_INVALID_PARAMETER;
1027                 }
1028
1029                 DEBUG(10,("check_spnego_blob_complete: "
1030                         "pad->partial_data.length = %u, "
1031                         "pad->needed_len = %u, "
1032                         "copy_len = %u, "
1033                         "pblob->length = %u,\n",
1034                         (unsigned int)pad->partial_data.length,
1035                         (unsigned int)pad->needed_len,
1036                         (unsigned int)copy_len,
1037                         (unsigned int)pblob->length ));
1038
1039                 tmp_blob = data_blob(NULL,
1040                                 pad->partial_data.length + copy_len);
1041
1042                 /* Concatenate the two (up to copy_len) bytes. */
1043                 memcpy(tmp_blob.data,
1044                         pad->partial_data.data,
1045                         pad->partial_data.length);
1046                 memcpy(tmp_blob.data + pad->partial_data.length,
1047                         pblob->data,
1048                         copy_len);
1049
1050                 /* Replace the partial data. */
1051                 data_blob_free(&pad->partial_data);
1052                 pad->partial_data = tmp_blob;
1053                 ZERO_STRUCT(tmp_blob);
1054
1055                 /* Are we done ? */
1056                 if (pblob->length >= pad->needed_len) {
1057                         /* Yes, replace pblob. */
1058                         data_blob_free(pblob);
1059                         *pblob = pad->partial_data;
1060                         ZERO_STRUCT(pad->partial_data);
1061                         delete_partial_auth(pad);
1062                         return NT_STATUS_OK;
1063                 }
1064
1065                 /* Still need more data. */
1066                 pad->needed_len -= copy_len;
1067                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1068         }
1069
1070         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1071             (pblob->data[0] != ASN1_CONTEXT(1))) {
1072                 /* Not something we can determine the
1073                  * length of.
1074                  */
1075                 return NT_STATUS_OK;
1076         }
1077
1078         /* This is a new SPNEGO sessionsetup - see if
1079          * the data given in this blob is enough.
1080          */
1081
1082         asn1_load(&data, *pblob);
1083         asn1_start_tag(&data, pblob->data[0]);
1084         if (data.has_error || data.nesting == NULL) {
1085                 asn1_free(&data);
1086                 /* Let caller catch. */
1087                 return NT_STATUS_OK;
1088         }
1089
1090         /* Integer wrap paranoia.... */
1091
1092         if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1093             data.nesting->taglen + data.nesting->start < data.nesting->start) {
1094
1095                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1096                         "data.nesting->taglen = %u, "
1097                         "data.nesting->start = %u\n",
1098                         (unsigned int)data.nesting->taglen,
1099                         (unsigned int)data.nesting->start ));
1100
1101                 asn1_free(&data);
1102                 return NT_STATUS_INVALID_PARAMETER;
1103         }
1104
1105         /* Total length of the needed asn1 is the tag length
1106          * plus the current offset. */
1107
1108         needed_len = data.nesting->taglen + data.nesting->start;
1109         asn1_free(&data);
1110
1111         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1112                 "pblob->length = %u\n",
1113                 (unsigned int)needed_len,
1114                 (unsigned int)pblob->length ));
1115
1116         if (needed_len <= pblob->length) {
1117                 /* Nothing to do - blob is complete. */
1118                 return NT_STATUS_OK;
1119         }
1120
1121         /* Refuse the blob if it's bigger than 64k. */
1122         if (needed_len > 65536) {
1123                 DEBUG(2,("check_spnego_blob_complete: needed_len "
1124                         "too large (%u)\n",
1125                         (unsigned int)needed_len ));
1126                 return NT_STATUS_INVALID_PARAMETER;
1127         }
1128
1129         /* We must store this blob until complete. */
1130         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1131                 return NT_STATUS_NO_MEMORY;
1132         }
1133         pad->needed_len = needed_len - pblob->length;
1134         pad->partial_data = data_blob(pblob->data, pblob->length);
1135         if (pad->partial_data.data == NULL) {
1136                 SAFE_FREE(pad);
1137                 return NT_STATUS_NO_MEMORY;
1138         }
1139         pad->smbpid = smbpid;
1140         pad->vuid = vuid;
1141         DLIST_ADD(pd_list, pad);
1142
1143         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1144 }
1145
1146 /****************************************************************************
1147  Reply to a session setup command.
1148  conn POINTER CAN BE NULL HERE !
1149 ****************************************************************************/
1150
1151 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1152 {
1153         uint8 *p;
1154         DATA_BLOB blob1;
1155         size_t bufrem;
1156         fstring native_os, native_lanman, primary_domain;
1157         const char *p2;
1158         uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1159         enum remote_arch_types ra_type = get_remote_arch();
1160         int vuid = SVAL(req->inbuf,smb_uid);
1161         user_struct *vuser = NULL;
1162         NTSTATUS status = NT_STATUS_OK;
1163         uint16 smbpid = req->smbpid;
1164         uint16 smb_flag2 = req->flags2;
1165
1166         DEBUG(3,("Doing spnego session setup\n"));
1167
1168         if (global_client_caps == 0) {
1169                 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1170
1171                 if (!(global_client_caps & CAP_STATUS32)) {
1172                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1173                 }
1174
1175         }
1176
1177         p = (uint8 *)smb_buf(req->inbuf);
1178
1179         if (data_blob_len == 0) {
1180                 /* an invalid request */
1181                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1182                 return;
1183         }
1184
1185         bufrem = smb_bufrem(req->inbuf, p);
1186         /* pull the spnego blob */
1187         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1188
1189 #if 0
1190         file_save("negotiate.dat", blob1.data, blob1.length);
1191 #endif
1192
1193         p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1194         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1195                               sizeof(native_os), STR_TERMINATE);
1196         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1197                               sizeof(native_lanman), STR_TERMINATE);
1198         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1199                               sizeof(primary_domain), STR_TERMINATE);
1200         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1201                 native_os, native_lanman, primary_domain));
1202
1203         if ( ra_type == RA_WIN2K ) {
1204                 /* Vista sets neither the OS or lanman strings */
1205
1206                 if ( !strlen(native_os) && !strlen(native_lanman) )
1207                         set_remote_arch(RA_VISTA);
1208
1209                 /* Windows 2003 doesn't set the native lanman string,
1210                    but does set primary domain which is a bug I think */
1211
1212                 if ( !strlen(native_lanman) ) {
1213                         ra_lanman_string( primary_domain );
1214                 } else {
1215                         ra_lanman_string( native_lanman );
1216                 }
1217         }
1218
1219         /* Did we get a valid vuid ? */
1220         if (!is_partial_auth_vuid(vuid)) {
1221                 /* No, then try and see if this is an intermediate sessionsetup
1222                  * for a large SPNEGO packet. */
1223                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1224                 if (pad) {
1225                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1226                                 "pending vuid %u\n",
1227                                 (unsigned int)pad->vuid ));
1228                         vuid = pad->vuid;
1229                 }
1230         }
1231
1232         /* Do we have a valid vuid now ? */
1233         if (!is_partial_auth_vuid(vuid)) {
1234                 /* No, start a new authentication setup. */
1235                 vuid = register_initial_vuid();
1236                 if (vuid == UID_FIELD_INVALID) {
1237                         data_blob_free(&blob1);
1238                         reply_nterror(req, nt_status_squash(
1239                                               NT_STATUS_INVALID_PARAMETER));
1240                         return;
1241                 }
1242         }
1243
1244         vuser = get_partial_auth_user_struct(vuid);
1245         /* This MUST be valid. */
1246         if (!vuser) {
1247                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1248         }
1249
1250         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1251          * sessionsetup requests as the Windows limit on the security blob
1252          * field is 4k. Bug #4400. JRA.
1253          */
1254
1255         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1256         if (!NT_STATUS_IS_OK(status)) {
1257                 if (!NT_STATUS_EQUAL(status,
1258                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1259                         /* Real error - kill the intermediate vuid */
1260                         invalidate_vuid(vuid);
1261                 }
1262                 data_blob_free(&blob1);
1263                 reply_nterror(req, nt_status_squash(status));
1264                 return;
1265         }
1266
1267         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1268
1269                 /* its a negTokenTarg packet */
1270
1271                 reply_spnego_negotiate(req, vuid, blob1,
1272                                        &vuser->auth_ntlmssp_state);
1273                 data_blob_free(&blob1);
1274                 return;
1275         }
1276
1277         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1278
1279                 /* its a auth packet */
1280
1281                 reply_spnego_auth(req, vuid, blob1,
1282                                   &vuser->auth_ntlmssp_state);
1283                 data_blob_free(&blob1);
1284                 return;
1285         }
1286
1287         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1288                 DATA_BLOB chal;
1289
1290                 if (!vuser->auth_ntlmssp_state) {
1291                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1292                         if (!NT_STATUS_IS_OK(status)) {
1293                                 /* Kill the intermediate vuid */
1294                                 invalidate_vuid(vuid);
1295                                 data_blob_free(&blob1);
1296                                 reply_nterror(req, nt_status_squash(status));
1297                                 return;
1298                         }
1299                 }
1300
1301                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1302                                                 blob1, &chal);
1303
1304                 data_blob_free(&blob1);
1305
1306                 reply_spnego_ntlmssp(req, vuid,
1307                                      &vuser->auth_ntlmssp_state,
1308                                      &chal, status, OID_NTLMSSP, false);
1309                 data_blob_free(&chal);
1310                 return;
1311         }
1312
1313         /* what sort of packet is this? */
1314         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1315
1316         data_blob_free(&blob1);
1317
1318         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1319 }
1320
1321 /****************************************************************************
1322  On new VC == 0, shutdown *all* old connections and users.
1323  It seems that only NT4.x does this. At W2K and above (XP etc.).
1324  a new session setup with VC==0 is ignored.
1325 ****************************************************************************/
1326
1327 static int shutdown_other_smbds(struct db_record *rec,
1328                                 const struct connections_key *key,
1329                                 const struct connections_data *crec,
1330                                 void *private_data)
1331 {
1332         const char *ip = (const char *)private_data;
1333
1334         if (!process_exists(crec->pid)) {
1335                 return 0;
1336         }
1337
1338         if (procid_is_me(&crec->pid)) {
1339                 return 0;
1340         }
1341
1342         if (strcmp(ip, crec->addr) != 0) {
1343                 return 0;
1344         }
1345
1346         messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1347                        &data_blob_null);
1348         return 0;
1349 }
1350
1351 static void setup_new_vc_session(void)
1352 {
1353         char addr[INET6_ADDRSTRLEN];
1354
1355         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1356                 "compatible we would close all old resources.\n"));
1357 #if 0
1358         conn_close_all();
1359         invalidate_all_vuids();
1360 #endif
1361         if (lp_reset_on_zero_vc()) {
1362                 connections_forall(shutdown_other_smbds,
1363                         CONST_DISCARD(void *,
1364                         client_addr(get_client_fd(),addr,sizeof(addr))));
1365         }
1366 }
1367
1368 /****************************************************************************
1369  Reply to a session setup command.
1370 ****************************************************************************/
1371
1372 void reply_sesssetup_and_X(struct smb_request *req)
1373 {
1374         int sess_vuid;
1375         int smb_bufsize;
1376         DATA_BLOB lm_resp;
1377         DATA_BLOB nt_resp;
1378         DATA_BLOB plaintext_password;
1379         fstring user;
1380         fstring sub_user; /* Sainitised username for substituion */
1381         fstring domain;
1382         fstring native_os;
1383         fstring native_lanman;
1384         fstring primary_domain;
1385         static bool done_sesssetup = False;
1386         auth_usersupplied_info *user_info = NULL;
1387         auth_serversupplied_info *server_info = NULL;
1388         uint16 smb_flag2 = req->flags2;
1389
1390         NTSTATUS nt_status;
1391
1392         bool doencrypt = global_encrypted_passwords_negotiated;
1393
1394         DATA_BLOB session_key;
1395
1396         START_PROFILE(SMBsesssetupX);
1397
1398         ZERO_STRUCT(lm_resp);
1399         ZERO_STRUCT(nt_resp);
1400         ZERO_STRUCT(plaintext_password);
1401
1402         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1403
1404         /* a SPNEGO session setup has 12 command words, whereas a normal
1405            NT1 session setup has 13. See the cifs spec. */
1406         if (req->wct == 12 &&
1407             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1408
1409                 if (!global_spnego_negotiated) {
1410                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1411                                  "at SPNEGO session setup when it was not "
1412                                  "negotiated.\n"));
1413                         reply_nterror(req, nt_status_squash(
1414                                               NT_STATUS_LOGON_FAILURE));
1415                         END_PROFILE(SMBsesssetupX);
1416                         return;
1417                 }
1418
1419                 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1420                         setup_new_vc_session();
1421                 }
1422
1423                 reply_sesssetup_and_X_spnego(req);
1424                 END_PROFILE(SMBsesssetupX);
1425                 return;
1426         }
1427
1428         smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1429
1430         if (Protocol < PROTOCOL_NT1) {
1431                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1432
1433                 /* Never do NT status codes with protocols before NT1 as we
1434                  * don't get client caps. */
1435                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1436
1437                 if ((passlen1 > MAX_PASS_LEN)
1438                     || (passlen1 > smb_bufrem(req->inbuf,
1439                                               smb_buf(req->inbuf)))) {
1440                         reply_nterror(req, nt_status_squash(
1441                                               NT_STATUS_INVALID_PARAMETER));
1442                         END_PROFILE(SMBsesssetupX);
1443                         return;
1444                 }
1445
1446                 if (doencrypt) {
1447                         lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1448                 } else {
1449                         plaintext_password = data_blob(smb_buf(req->inbuf),
1450                                                        passlen1+1);
1451                         /* Ensure null termination */
1452                         plaintext_password.data[passlen1] = 0;
1453                 }
1454
1455                 srvstr_pull_buf(req->inbuf, req->flags2, user,
1456                                 smb_buf(req->inbuf)+passlen1, sizeof(user),
1457                                 STR_TERMINATE);
1458                 *domain = 0;
1459
1460         } else {
1461                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1462                 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1463                 enum remote_arch_types ra_type = get_remote_arch();
1464                 char *p = smb_buf(req->inbuf);
1465                 char *save_p = smb_buf(req->inbuf);
1466                 uint16 byte_count;
1467
1468
1469                 if(global_client_caps == 0) {
1470                         global_client_caps = IVAL(req->inbuf,smb_vwv11);
1471
1472                         if (!(global_client_caps & CAP_STATUS32)) {
1473                                 remove_from_common_flags2(
1474                                                 FLAGS2_32_BIT_ERROR_CODES);
1475                         }
1476
1477                         /* client_caps is used as final determination if
1478                          * client is NT or Win95. This is needed to return
1479                          * the correct error codes in some circumstances.
1480                         */
1481
1482                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1483                                         ra_type == RA_WIN95) {
1484                                 if(!(global_client_caps & (CAP_NT_SMBS|
1485                                                         CAP_STATUS32))) {
1486                                         set_remote_arch( RA_WIN95);
1487                                 }
1488                         }
1489                 }
1490
1491                 if (!doencrypt) {
1492                         /* both Win95 and WinNT stuff up the password
1493                          * lengths for non-encrypting systems. Uggh.
1494
1495                            if passlen1==24 its a win95 system, and its setting
1496                            the password length incorrectly. Luckily it still
1497                            works with the default code because Win95 will null
1498                            terminate the password anyway
1499
1500                            if passlen1>0 and passlen2>0 then maybe its a NT box
1501                            and its setting passlen2 to some random value which
1502                            really stuffs things up. we need to fix that one.  */
1503
1504                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1505                                         passlen2 != 1) {
1506                                 passlen2 = 0;
1507                         }
1508                 }
1509
1510                 /* check for nasty tricks */
1511                 if (passlen1 > MAX_PASS_LEN
1512                     || passlen1 > smb_bufrem(req->inbuf, p)) {
1513                         reply_nterror(req, nt_status_squash(
1514                                               NT_STATUS_INVALID_PARAMETER));
1515                         END_PROFILE(SMBsesssetupX);
1516                         return;
1517                 }
1518
1519                 if (passlen2 > MAX_PASS_LEN
1520                     || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1521                         reply_nterror(req, nt_status_squash(
1522                                               NT_STATUS_INVALID_PARAMETER));
1523                         END_PROFILE(SMBsesssetupX);
1524                         return;
1525                 }
1526
1527                 /* Save the lanman2 password and the NT md4 password. */
1528
1529                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1530                         doencrypt = False;
1531                 }
1532
1533                 if (doencrypt) {
1534                         lm_resp = data_blob(p, passlen1);
1535                         nt_resp = data_blob(p+passlen1, passlen2);
1536                 } else if (lp_security() != SEC_SHARE) {
1537                         char *pass = NULL;
1538                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1539
1540                         if (unic && (passlen2 == 0) && passlen1) {
1541                                 /* Only a ascii plaintext password was sent. */
1542                                 (void)srvstr_pull_talloc(talloc_tos(),
1543                                                         req->inbuf,
1544                                                         req->flags2,
1545                                                         &pass,
1546                                                         smb_buf(req->inbuf),
1547                                                         passlen1,
1548                                                         STR_TERMINATE|STR_ASCII);
1549                         } else {
1550                                 (void)srvstr_pull_talloc(talloc_tos(),
1551                                                         req->inbuf,
1552                                                         req->flags2,
1553                                                         &pass,
1554                                                         smb_buf(req->inbuf),
1555                                                         unic ? passlen2 : passlen1,
1556                                                         STR_TERMINATE);
1557                         }
1558                         if (!pass) {
1559                                 reply_nterror(req, nt_status_squash(
1560                                               NT_STATUS_INVALID_PARAMETER));
1561                                 END_PROFILE(SMBsesssetupX);
1562                                 return;
1563                         }
1564                         plaintext_password = data_blob(pass, strlen(pass)+1);
1565                 }
1566
1567                 p += passlen1 + passlen2;
1568                 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1569                                      sizeof(user), STR_TERMINATE);
1570                 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1571                                      sizeof(domain), STR_TERMINATE);
1572                 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1573                                      p, sizeof(native_os), STR_TERMINATE);
1574                 p += srvstr_pull_buf(req->inbuf, req->flags2,
1575                                      native_lanman, p, sizeof(native_lanman),
1576                                      STR_TERMINATE);
1577
1578                 /* not documented or decoded by Ethereal but there is one more
1579                  * string in the extra bytes which is the same as the
1580                  * PrimaryDomain when using extended security.  Windows NT 4
1581                  * and 2003 use this string to store the native lanman string.
1582                  * Windows 9x does not include a string here at all so we have
1583                  * to check if we have any extra bytes left */
1584
1585                 byte_count = SVAL(req->inbuf, smb_vwv13);
1586                 if ( PTR_DIFF(p, save_p) < byte_count) {
1587                         p += srvstr_pull_buf(req->inbuf, req->flags2,
1588                                              primary_domain, p,
1589                                              sizeof(primary_domain),
1590                                              STR_TERMINATE);
1591                 } else {
1592                         fstrcpy( primary_domain, "null" );
1593                 }
1594
1595                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1596                         "PrimaryDomain=[%s]\n",
1597                         domain, native_os, native_lanman, primary_domain));
1598
1599                 if ( ra_type == RA_WIN2K ) {
1600                         if ( strlen(native_lanman) == 0 )
1601                                 ra_lanman_string( primary_domain );
1602                         else
1603                                 ra_lanman_string( native_lanman );
1604                 }
1605
1606         }
1607
1608         if (SVAL(req->inbuf,smb_vwv4) == 0) {
1609                 setup_new_vc_session();
1610         }
1611
1612         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1613                                 domain, user, get_remote_machine_name()));
1614
1615         if (*user) {
1616                 if (global_spnego_negotiated) {
1617
1618                         /* This has to be here, because this is a perfectly
1619                          * valid behaviour for guest logons :-( */
1620
1621                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1622                                 "at 'normal' session setup after "
1623                                 "negotiating spnego.\n"));
1624                         reply_nterror(req, nt_status_squash(
1625                                               NT_STATUS_LOGON_FAILURE));
1626                         END_PROFILE(SMBsesssetupX);
1627                         return;
1628                 }
1629                 fstrcpy(sub_user, user);
1630         } else {
1631                 fstrcpy(sub_user, lp_guestaccount());
1632         }
1633
1634         sub_set_smb_name(sub_user);
1635
1636         reload_services(True);
1637
1638         if (lp_security() == SEC_SHARE) {
1639                 /* in share level we should ignore any passwords */
1640
1641                 data_blob_free(&lm_resp);
1642                 data_blob_free(&nt_resp);
1643                 data_blob_clear_free(&plaintext_password);
1644
1645                 map_username(sub_user);
1646                 add_session_user(sub_user);
1647                 add_session_workgroup(domain);
1648                 /* Then force it to null for the benfit of the code below */
1649                 *user = 0;
1650         }
1651
1652         if (!*user) {
1653
1654                 nt_status = check_guest_password(&server_info);
1655
1656         } else if (doencrypt) {
1657                 if (!negprot_global_auth_context) {
1658                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1659                                 "session setup without negprot denied!\n"));
1660                         reply_nterror(req, nt_status_squash(
1661                                               NT_STATUS_LOGON_FAILURE));
1662                         END_PROFILE(SMBsesssetupX);
1663                         return;
1664                 }
1665                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1666                                                 domain,
1667                                                 lm_resp, nt_resp);
1668                 if (NT_STATUS_IS_OK(nt_status)) {
1669                         nt_status = negprot_global_auth_context->check_ntlm_password(
1670                                         negprot_global_auth_context,
1671                                         user_info,
1672                                         &server_info);
1673                 }
1674         } else {
1675                 struct auth_context *plaintext_auth_context = NULL;
1676                 const uint8 *chal;
1677
1678                 nt_status = make_auth_context_subsystem(
1679                                 &plaintext_auth_context);
1680
1681                 if (NT_STATUS_IS_OK(nt_status)) {
1682                         chal = plaintext_auth_context->get_ntlm_challenge(
1683                                         plaintext_auth_context);
1684
1685                         if (!make_user_info_for_reply(&user_info,
1686                                                       user, domain, chal,
1687                                                       plaintext_password)) {
1688                                 nt_status = NT_STATUS_NO_MEMORY;
1689                         }
1690
1691                         if (NT_STATUS_IS_OK(nt_status)) {
1692                                 nt_status = plaintext_auth_context->check_ntlm_password(
1693                                                 plaintext_auth_context,
1694                                                 user_info,
1695                                                 &server_info);
1696
1697                                 (plaintext_auth_context->free)(
1698                                                 &plaintext_auth_context);
1699                         }
1700                 }
1701         }
1702
1703         free_user_info(&user_info);
1704
1705         if (!NT_STATUS_IS_OK(nt_status)) {
1706                 nt_status = do_map_to_guest(nt_status, &server_info,
1707                                 user, domain);
1708         }
1709
1710         if (!NT_STATUS_IS_OK(nt_status)) {
1711                 data_blob_free(&nt_resp);
1712                 data_blob_free(&lm_resp);
1713                 data_blob_clear_free(&plaintext_password);
1714                 reply_nterror(req, nt_status_squash(nt_status));
1715                 END_PROFILE(SMBsesssetupX);
1716                 return;
1717         }
1718
1719         /* Ensure we can't possible take a code path leading to a
1720          * null defref. */
1721         if (!server_info) {
1722                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1723                 END_PROFILE(SMBsesssetupX);
1724                 return;
1725         }
1726
1727         nt_status = create_local_token(server_info);
1728         if (!NT_STATUS_IS_OK(nt_status)) {
1729                 DEBUG(10, ("create_local_token failed: %s\n",
1730                            nt_errstr(nt_status)));
1731                 data_blob_free(&nt_resp);
1732                 data_blob_free(&lm_resp);
1733                 data_blob_clear_free(&plaintext_password);
1734                 reply_nterror(req, nt_status_squash(nt_status));
1735                 END_PROFILE(SMBsesssetupX);
1736                 return;
1737         }
1738
1739         if (server_info->user_session_key.data) {
1740                 session_key = data_blob(server_info->user_session_key.data,
1741                                 server_info->user_session_key.length);
1742         } else {
1743                 session_key = data_blob_null;
1744         }
1745
1746         data_blob_clear_free(&plaintext_password);
1747
1748         /* it's ok - setup a reply */
1749         reply_outbuf(req, 3, 0);
1750         if (Protocol >= PROTOCOL_NT1) {
1751                 push_signature(&req->outbuf);
1752                 /* perhaps grab OS version here?? */
1753         }
1754
1755         if (server_info->guest) {
1756                 SSVAL(req->outbuf,smb_vwv2,1);
1757         }
1758
1759         /* register the name and uid as being validated, so further connections
1760            to a uid can get through without a password, on the same VC */
1761
1762         if (lp_security() == SEC_SHARE) {
1763                 sess_vuid = UID_FIELD_INVALID;
1764                 data_blob_free(&session_key);
1765                 TALLOC_FREE(server_info);
1766         } else {
1767                 /* Ignore the initial vuid. */
1768                 sess_vuid = register_initial_vuid();
1769                 if (sess_vuid == UID_FIELD_INVALID) {
1770                         data_blob_free(&nt_resp);
1771                         data_blob_free(&lm_resp);
1772                         data_blob_free(&session_key);
1773                         reply_nterror(req, nt_status_squash(
1774                                               NT_STATUS_LOGON_FAILURE));
1775                         END_PROFILE(SMBsesssetupX);
1776                         return;
1777                 }
1778                 /* register_existing_vuid keeps the server info */
1779                 sess_vuid = register_existing_vuid(sess_vuid,
1780                                         server_info,
1781                                         session_key,
1782                                         nt_resp.data ? nt_resp : lm_resp,
1783                                         sub_user);
1784                 if (sess_vuid == UID_FIELD_INVALID) {
1785                         data_blob_free(&nt_resp);
1786                         data_blob_free(&lm_resp);
1787                         data_blob_free(&session_key);
1788                         reply_nterror(req, nt_status_squash(
1789                                               NT_STATUS_LOGON_FAILURE));
1790                         END_PROFILE(SMBsesssetupX);
1791                         return;
1792                 }
1793
1794                 /* current_user_info is changed on new vuid */
1795                 reload_services( True );
1796
1797                 sessionsetup_start_signing_engine(server_info, req->inbuf);
1798         }
1799
1800         data_blob_free(&nt_resp);
1801         data_blob_free(&lm_resp);
1802
1803         SSVAL(req->outbuf,smb_uid,sess_vuid);
1804         SSVAL(req->inbuf,smb_uid,sess_vuid);
1805
1806         if (!done_sesssetup)
1807                 max_send = MIN(max_send,smb_bufsize);
1808
1809         done_sesssetup = True;
1810
1811         END_PROFILE(SMBsesssetupX);
1812         chain_reply(req);
1813         return;
1814 }