Merge commit 'origin/v3-2-test' into v3-2-stable
[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                         SAFE_FREE(client);
543                         data_blob_free(&ap_rep);
544                         data_blob_free(&session_key);
545                         TALLOC_FREE( mem_ctx );
546                         TALLOC_FREE( server_info );
547                         reply_nterror(req, nt_status_squash(ret));
548                         return;
549                 }
550         }
551
552         /* register_existing_vuid keeps the server info */
553         /* register_existing_vuid takes ownership of session_key on success,
554          * no need to free after this on success. A better interface would copy
555          * it.... */
556
557         if (!is_partial_auth_vuid(sess_vuid)) {
558                 sess_vuid = register_initial_vuid();
559         }
560         sess_vuid = register_existing_vuid(sess_vuid,
561                                         server_info,
562                                         session_key,
563                                         nullblob,
564                                         client);
565
566         SAFE_FREE(client);
567
568         reply_outbuf(req, 4, 0);
569         SSVAL(req->outbuf,smb_uid,sess_vuid);
570
571         if (sess_vuid == UID_FIELD_INVALID ) {
572                 ret = NT_STATUS_LOGON_FAILURE;
573                 data_blob_free(&session_key);
574         } else {
575                 /* current_user_info is changed on new vuid */
576                 reload_services( True );
577
578                 SSVAL(req->outbuf, smb_vwv3, 0);
579
580                 if (server_info->guest) {
581                         SSVAL(req->outbuf,smb_vwv2,1);
582                 }
583
584                 SSVAL(req->outbuf, smb_uid, sess_vuid);
585
586                 sessionsetup_start_signing_engine(server_info, req->inbuf);
587                 /* Successful logon. Keep this vuid. */
588                 *p_invalidate_vuid = False;
589         }
590
591         /* wrap that up in a nice GSS-API wrapping */
592         if (NT_STATUS_IS_OK(ret)) {
593                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
594                                 TOK_ID_KRB_AP_REP);
595         } else {
596                 ap_rep_wrapped = data_blob_null;
597         }
598         response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
599                         OID_KERBEROS5_OLD);
600         reply_sesssetup_blob(req, response, ret);
601
602         data_blob_free(&ap_rep);
603         data_blob_free(&ap_rep_wrapped);
604         data_blob_free(&response);
605         TALLOC_FREE(mem_ctx);
606 }
607
608 #endif
609
610 /****************************************************************************
611  Send a session setup reply, wrapped in SPNEGO.
612  Get vuid and check first.
613  End the NTLMSSP exchange context if we are OK/complete fail
614  This should be split into two functions, one to handle each
615  leg of the NTLM auth steps.
616 ***************************************************************************/
617
618 static void reply_spnego_ntlmssp(struct smb_request *req,
619                                  uint16 vuid,
620                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
621                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
622                                  const char *OID,
623                                  bool wrap)
624 {
625         DATA_BLOB response;
626         struct auth_serversupplied_info *server_info = NULL;
627
628         if (NT_STATUS_IS_OK(nt_status)) {
629                 server_info = (*auth_ntlmssp_state)->server_info;
630         } else {
631                 nt_status = do_map_to_guest(nt_status,
632                             &server_info,
633                             (*auth_ntlmssp_state)->ntlmssp_state->user,
634                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
635         }
636
637         reply_outbuf(req, 4, 0);
638
639         SSVAL(req->outbuf, smb_uid, vuid);
640
641         if (NT_STATUS_IS_OK(nt_status)) {
642                 DATA_BLOB nullblob = data_blob_null;
643                 DATA_BLOB session_key =
644                         data_blob(
645                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
646                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
647
648                 if (!is_partial_auth_vuid(vuid)) {
649                         data_blob_free(&session_key);
650                         nt_status = NT_STATUS_LOGON_FAILURE;
651                         goto out;
652                 }
653                 /* register_existing_vuid keeps the server info */
654                 if (register_existing_vuid(vuid,
655                                 server_info,
656                                 session_key, nullblob,
657                                 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
658                                         vuid) {
659                         data_blob_free(&session_key);
660                         nt_status = NT_STATUS_LOGON_FAILURE;
661                         goto out;
662                 }
663
664                 (*auth_ntlmssp_state)->server_info = NULL;
665
666                 /* current_user_info is changed on new vuid */
667                 reload_services( True );
668
669                 SSVAL(req->outbuf, smb_vwv3, 0);
670
671                 if (server_info->guest) {
672                         SSVAL(req->outbuf,smb_vwv2,1);
673                 }
674
675                 sessionsetup_start_signing_engine(server_info,
676                                                   (uint8 *)req->inbuf);
677         }
678
679   out:
680
681         if (wrap) {
682                 response = spnego_gen_auth_response(ntlmssp_blob,
683                                 nt_status, OID);
684         } else {
685                 response = *ntlmssp_blob;
686         }
687
688         reply_sesssetup_blob(req, response, nt_status);
689         if (wrap) {
690                 data_blob_free(&response);
691         }
692
693         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
694            and the other end, that we are not finished yet. */
695
696         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
697                 /* NB. This is *NOT* an error case. JRA */
698                 auth_ntlmssp_end(auth_ntlmssp_state);
699                 if (!NT_STATUS_IS_OK(nt_status)) {
700                         /* Kill the intermediate vuid */
701                         invalidate_vuid(vuid);
702                 }
703         }
704 }
705
706 /****************************************************************************
707  Is this a krb5 mechanism ?
708 ****************************************************************************/
709
710 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
711                 bool *p_is_krb5)
712 {
713         char *OIDs[ASN1_MAX_OIDS];
714         int i;
715
716         *p_is_krb5 = False;
717
718         /* parse out the OIDs and the first sec blob */
719         if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
720                 return NT_STATUS_LOGON_FAILURE;
721         }
722
723         /* only look at the first OID for determining the mechToken --
724            according to RFC2478, we should choose the one we want
725            and renegotiate, but i smell a client bug here..
726
727            Problem observed when connecting to a member (samba box)
728            of an AD domain as a user in a Samba domain.  Samba member
729            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
730            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
731            NTLMSSP mechtoken.                 --jerry              */
732
733 #ifdef HAVE_KRB5
734         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
735             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
736                 *p_is_krb5 = True;
737         }
738 #endif
739
740         for (i=0;OIDs[i];i++) {
741                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
742                 free(OIDs[i]);
743         }
744         return NT_STATUS_OK;
745 }
746
747 /****************************************************************************
748  Fall back from krb5 to NTLMSSP.
749 ****************************************************************************/
750
751 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
752                                                 uint16 vuid)
753 {
754         DATA_BLOB response;
755
756         reply_outbuf(req, 4, 0);
757         SSVAL(req->outbuf,smb_uid,vuid);
758
759         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
760                 "but set to downgrade to NTLMSSP\n"));
761
762         response = spnego_gen_auth_response(NULL,
763                         NT_STATUS_MORE_PROCESSING_REQUIRED,
764                         OID_NTLMSSP);
765         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
766         data_blob_free(&response);
767 }
768
769 /****************************************************************************
770  Reply to a session setup spnego negotiate packet.
771 ****************************************************************************/
772
773 static void reply_spnego_negotiate(struct smb_request *req,
774                                    uint16 vuid,
775                                    DATA_BLOB blob1,
776                                    AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
777 {
778         DATA_BLOB secblob;
779         DATA_BLOB chal;
780         bool got_kerberos_mechanism = False;
781         NTSTATUS status;
782
783         status = parse_spnego_mechanisms(blob1, &secblob,
784                         &got_kerberos_mechanism);
785         if (!NT_STATUS_IS_OK(status)) {
786                 /* Kill the intermediate vuid */
787                 invalidate_vuid(vuid);
788                 reply_nterror(req, nt_status_squash(status));
789                 return;
790         }
791
792         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
793                                 (unsigned long)secblob.length));
794
795 #ifdef HAVE_KRB5
796         if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
797                                 lp_use_kerberos_keytab()) ) {
798                 bool destroy_vuid = True;
799                 reply_spnego_kerberos(req, &secblob, vuid,
800                                       &destroy_vuid);
801                 data_blob_free(&secblob);
802                 if (destroy_vuid) {
803                         /* Kill the intermediate vuid */
804                         invalidate_vuid(vuid);
805                 }
806                 return;
807         }
808 #endif
809
810         if (*auth_ntlmssp_state) {
811                 auth_ntlmssp_end(auth_ntlmssp_state);
812         }
813
814         if (got_kerberos_mechanism) {
815                 data_blob_free(&secblob);
816                 /* The mechtoken is a krb5 ticket, but
817                  * we need to fall back to NTLM. */
818                 reply_spnego_downgrade_to_ntlmssp(req,
819                                         vuid);
820                 return;
821         }
822
823         status = auth_ntlmssp_start(auth_ntlmssp_state);
824         if (!NT_STATUS_IS_OK(status)) {
825                 /* Kill the intermediate vuid */
826                 invalidate_vuid(vuid);
827                 reply_nterror(req, nt_status_squash(status));
828                 return;
829         }
830
831         status = auth_ntlmssp_update(*auth_ntlmssp_state,
832                                         secblob, &chal);
833
834         data_blob_free(&secblob);
835
836         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
837                              &chal, status, OID_NTLMSSP, true);
838
839         data_blob_free(&chal);
840
841         /* already replied */
842         return;
843 }
844
845 /****************************************************************************
846  Reply to a session setup spnego auth packet.
847 ****************************************************************************/
848
849 static void reply_spnego_auth(struct smb_request *req,
850                               uint16 vuid,
851                               DATA_BLOB blob1,
852                               AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
853 {
854         DATA_BLOB auth = data_blob_null;
855         DATA_BLOB auth_reply = data_blob_null;
856         DATA_BLOB secblob = data_blob_null;
857         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
858
859         if (!spnego_parse_auth(blob1, &auth)) {
860 #if 0
861                 file_save("auth.dat", blob1.data, blob1.length);
862 #endif
863                 /* Kill the intermediate vuid */
864                 invalidate_vuid(vuid);
865
866                 reply_nterror(req, nt_status_squash(
867                                       NT_STATUS_LOGON_FAILURE));
868                 return;
869         }
870
871         if (auth.data[0] == ASN1_APPLICATION(0)) {
872                 /* Might be a second negTokenTarg packet */
873
874                 bool got_krb5_mechanism = False;
875                 status = parse_spnego_mechanisms(auth, &secblob,
876                                 &got_krb5_mechanism);
877
878                 if (!NT_STATUS_IS_OK(status)) {
879                         /* Kill the intermediate vuid */
880                         invalidate_vuid(vuid);
881                         reply_nterror(req, nt_status_squash(status));
882                         return;
883                 }
884
885                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
886                                 (unsigned long)secblob.length));
887 #ifdef HAVE_KRB5
888                 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
889                                         lp_use_kerberos_keytab()) ) {
890                         bool destroy_vuid = True;
891                         reply_spnego_kerberos(req, &secblob,
892                                               vuid, &destroy_vuid);
893                         data_blob_free(&secblob);
894                         data_blob_free(&auth);
895                         if (destroy_vuid) {
896                                 /* Kill the intermediate vuid */
897                                 invalidate_vuid(vuid);
898                         }
899                         return;
900                 }
901 #endif
902                 /* Can't blunder into NTLMSSP auth if we have
903                  * a krb5 ticket. */
904
905                 if (got_krb5_mechanism) {
906                         /* Kill the intermediate vuid */
907                         invalidate_vuid(vuid);
908                         DEBUG(3,("reply_spnego_auth: network "
909                                 "misconfiguration, client sent us a "
910                                 "krb5 ticket and kerberos security "
911                                 "not enabled"));
912                         reply_nterror(req, nt_status_squash(
913                                         NT_STATUS_LOGON_FAILURE));
914                 }
915         }
916
917         /* If we get here it wasn't a negTokenTarg auth packet. */
918         data_blob_free(&secblob);
919
920         if (!*auth_ntlmssp_state) {
921                 status = auth_ntlmssp_start(auth_ntlmssp_state);
922                 if (!NT_STATUS_IS_OK(status)) {
923                         /* Kill the intermediate vuid */
924                         invalidate_vuid(vuid);
925                         reply_nterror(req, nt_status_squash(status));
926                         return;
927                 }
928         }
929
930         status = auth_ntlmssp_update(*auth_ntlmssp_state,
931                                         auth, &auth_reply);
932
933         data_blob_free(&auth);
934
935         /* Don't send the mechid as we've already sent this (RFC4178). */
936
937         reply_spnego_ntlmssp(req, vuid,
938                              auth_ntlmssp_state,
939                              &auth_reply, status, NULL, true);
940
941         data_blob_free(&auth_reply);
942
943         /* and tell smbd that we have already replied to this packet */
944         return;
945 }
946
947 /****************************************************************************
948  List to store partial SPNEGO auth fragments.
949 ****************************************************************************/
950
951 static struct pending_auth_data *pd_list;
952
953 /****************************************************************************
954  Delete an entry on the list.
955 ****************************************************************************/
956
957 static void delete_partial_auth(struct pending_auth_data *pad)
958 {
959         if (!pad) {
960                 return;
961         }
962         DLIST_REMOVE(pd_list, pad);
963         data_blob_free(&pad->partial_data);
964         SAFE_FREE(pad);
965 }
966
967 /****************************************************************************
968  Search for a partial SPNEGO auth fragment matching an smbpid.
969 ****************************************************************************/
970
971 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
972 {
973         struct pending_auth_data *pad;
974
975         for (pad = pd_list; pad; pad = pad->next) {
976                 if (pad->smbpid == smbpid) {
977                         break;
978                 }
979         }
980         return pad;
981 }
982
983 /****************************************************************************
984  Check the size of an SPNEGO blob. If we need more return
985  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
986  the blob to be more than 64k.
987 ****************************************************************************/
988
989 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
990                 DATA_BLOB *pblob)
991 {
992         struct pending_auth_data *pad = NULL;
993         ASN1_DATA data;
994         size_t needed_len = 0;
995
996         pad = get_pending_auth_data(smbpid);
997
998         /* Ensure we have some data. */
999         if (pblob->length == 0) {
1000                 /* Caller can cope. */
1001                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1002                 delete_partial_auth(pad);
1003                 return NT_STATUS_OK;
1004         }
1005
1006         /* Were we waiting for more data ? */
1007         if (pad) {
1008                 DATA_BLOB tmp_blob;
1009                 size_t copy_len = MIN(65536, pblob->length);
1010
1011                 /* Integer wrap paranoia.... */
1012
1013                 if (pad->partial_data.length + copy_len <
1014                                 pad->partial_data.length ||
1015                     pad->partial_data.length + copy_len < copy_len) {
1016
1017                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
1018                                 "pad->partial_data.length = %u, "
1019                                 "copy_len = %u\n",
1020                                 (unsigned int)pad->partial_data.length,
1021                                 (unsigned int)copy_len ));
1022
1023                         delete_partial_auth(pad);
1024                         return NT_STATUS_INVALID_PARAMETER;
1025                 }
1026
1027                 DEBUG(10,("check_spnego_blob_complete: "
1028                         "pad->partial_data.length = %u, "
1029                         "pad->needed_len = %u, "
1030                         "copy_len = %u, "
1031                         "pblob->length = %u,\n",
1032                         (unsigned int)pad->partial_data.length,
1033                         (unsigned int)pad->needed_len,
1034                         (unsigned int)copy_len,
1035                         (unsigned int)pblob->length ));
1036
1037                 tmp_blob = data_blob(NULL,
1038                                 pad->partial_data.length + copy_len);
1039
1040                 /* Concatenate the two (up to copy_len) bytes. */
1041                 memcpy(tmp_blob.data,
1042                         pad->partial_data.data,
1043                         pad->partial_data.length);
1044                 memcpy(tmp_blob.data + pad->partial_data.length,
1045                         pblob->data,
1046                         copy_len);
1047
1048                 /* Replace the partial data. */
1049                 data_blob_free(&pad->partial_data);
1050                 pad->partial_data = tmp_blob;
1051                 ZERO_STRUCT(tmp_blob);
1052
1053                 /* Are we done ? */
1054                 if (pblob->length >= pad->needed_len) {
1055                         /* Yes, replace pblob. */
1056                         data_blob_free(pblob);
1057                         *pblob = pad->partial_data;
1058                         ZERO_STRUCT(pad->partial_data);
1059                         delete_partial_auth(pad);
1060                         return NT_STATUS_OK;
1061                 }
1062
1063                 /* Still need more data. */
1064                 pad->needed_len -= copy_len;
1065                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1066         }
1067
1068         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1069             (pblob->data[0] != ASN1_CONTEXT(1))) {
1070                 /* Not something we can determine the
1071                  * length of.
1072                  */
1073                 return NT_STATUS_OK;
1074         }
1075
1076         /* This is a new SPNEGO sessionsetup - see if
1077          * the data given in this blob is enough.
1078          */
1079
1080         asn1_load(&data, *pblob);
1081         asn1_start_tag(&data, pblob->data[0]);
1082         if (data.has_error || data.nesting == NULL) {
1083                 asn1_free(&data);
1084                 /* Let caller catch. */
1085                 return NT_STATUS_OK;
1086         }
1087
1088         /* Integer wrap paranoia.... */
1089
1090         if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1091             data.nesting->taglen + data.nesting->start < data.nesting->start) {
1092
1093                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1094                         "data.nesting->taglen = %u, "
1095                         "data.nesting->start = %u\n",
1096                         (unsigned int)data.nesting->taglen,
1097                         (unsigned int)data.nesting->start ));
1098
1099                 asn1_free(&data);
1100                 return NT_STATUS_INVALID_PARAMETER;
1101         }
1102
1103         /* Total length of the needed asn1 is the tag length
1104          * plus the current offset. */
1105
1106         needed_len = data.nesting->taglen + data.nesting->start;
1107         asn1_free(&data);
1108
1109         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1110                 "pblob->length = %u\n",
1111                 (unsigned int)needed_len,
1112                 (unsigned int)pblob->length ));
1113
1114         if (needed_len <= pblob->length) {
1115                 /* Nothing to do - blob is complete. */
1116                 return NT_STATUS_OK;
1117         }
1118
1119         /* Refuse the blob if it's bigger than 64k. */
1120         if (needed_len > 65536) {
1121                 DEBUG(2,("check_spnego_blob_complete: needed_len "
1122                         "too large (%u)\n",
1123                         (unsigned int)needed_len ));
1124                 return NT_STATUS_INVALID_PARAMETER;
1125         }
1126
1127         /* We must store this blob until complete. */
1128         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1129                 return NT_STATUS_NO_MEMORY;
1130         }
1131         pad->needed_len = needed_len - pblob->length;
1132         pad->partial_data = data_blob(pblob->data, pblob->length);
1133         if (pad->partial_data.data == NULL) {
1134                 SAFE_FREE(pad);
1135                 return NT_STATUS_NO_MEMORY;
1136         }
1137         pad->smbpid = smbpid;
1138         pad->vuid = vuid;
1139         DLIST_ADD(pd_list, pad);
1140
1141         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1142 }
1143
1144 /****************************************************************************
1145  Reply to a session setup command.
1146  conn POINTER CAN BE NULL HERE !
1147 ****************************************************************************/
1148
1149 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1150 {
1151         uint8 *p;
1152         DATA_BLOB blob1;
1153         size_t bufrem;
1154         fstring native_os, native_lanman, primary_domain;
1155         const char *p2;
1156         uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1157         enum remote_arch_types ra_type = get_remote_arch();
1158         int vuid = SVAL(req->inbuf,smb_uid);
1159         user_struct *vuser = NULL;
1160         NTSTATUS status = NT_STATUS_OK;
1161         uint16 smbpid = req->smbpid;
1162         uint16 smb_flag2 = req->flags2;
1163
1164         DEBUG(3,("Doing spnego session setup\n"));
1165
1166         if (global_client_caps == 0) {
1167                 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1168
1169                 if (!(global_client_caps & CAP_STATUS32)) {
1170                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1171                 }
1172
1173         }
1174
1175         p = (uint8 *)smb_buf(req->inbuf);
1176
1177         if (data_blob_len == 0) {
1178                 /* an invalid request */
1179                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1180                 return;
1181         }
1182
1183         bufrem = smb_bufrem(req->inbuf, p);
1184         /* pull the spnego blob */
1185         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1186
1187 #if 0
1188         file_save("negotiate.dat", blob1.data, blob1.length);
1189 #endif
1190
1191         p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1192         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1193                               sizeof(native_os), STR_TERMINATE);
1194         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1195                               sizeof(native_lanman), STR_TERMINATE);
1196         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1197                               sizeof(primary_domain), STR_TERMINATE);
1198         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1199                 native_os, native_lanman, primary_domain));
1200
1201         if ( ra_type == RA_WIN2K ) {
1202                 /* Vista sets neither the OS or lanman strings */
1203
1204                 if ( !strlen(native_os) && !strlen(native_lanman) )
1205                         set_remote_arch(RA_VISTA);
1206
1207                 /* Windows 2003 doesn't set the native lanman string,
1208                    but does set primary domain which is a bug I think */
1209
1210                 if ( !strlen(native_lanman) ) {
1211                         ra_lanman_string( primary_domain );
1212                 } else {
1213                         ra_lanman_string( native_lanman );
1214                 }
1215         }
1216
1217         /* Did we get a valid vuid ? */
1218         if (!is_partial_auth_vuid(vuid)) {
1219                 /* No, then try and see if this is an intermediate sessionsetup
1220                  * for a large SPNEGO packet. */
1221                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1222                 if (pad) {
1223                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1224                                 "pending vuid %u\n",
1225                                 (unsigned int)pad->vuid ));
1226                         vuid = pad->vuid;
1227                 }
1228         }
1229
1230         /* Do we have a valid vuid now ? */
1231         if (!is_partial_auth_vuid(vuid)) {
1232                 /* No, start a new authentication setup. */
1233                 vuid = register_initial_vuid();
1234                 if (vuid == UID_FIELD_INVALID) {
1235                         data_blob_free(&blob1);
1236                         reply_nterror(req, nt_status_squash(
1237                                               NT_STATUS_INVALID_PARAMETER));
1238                         return;
1239                 }
1240         }
1241
1242         vuser = get_partial_auth_user_struct(vuid);
1243         /* This MUST be valid. */
1244         if (!vuser) {
1245                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1246         }
1247
1248         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1249          * sessionsetup requests as the Windows limit on the security blob
1250          * field is 4k. Bug #4400. JRA.
1251          */
1252
1253         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1254         if (!NT_STATUS_IS_OK(status)) {
1255                 if (!NT_STATUS_EQUAL(status,
1256                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1257                         /* Real error - kill the intermediate vuid */
1258                         invalidate_vuid(vuid);
1259                 }
1260                 data_blob_free(&blob1);
1261                 reply_nterror(req, nt_status_squash(status));
1262                 return;
1263         }
1264
1265         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1266
1267                 /* its a negTokenTarg packet */
1268
1269                 reply_spnego_negotiate(req, vuid, blob1,
1270                                        &vuser->auth_ntlmssp_state);
1271                 data_blob_free(&blob1);
1272                 return;
1273         }
1274
1275         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1276
1277                 /* its a auth packet */
1278
1279                 reply_spnego_auth(req, vuid, blob1,
1280                                   &vuser->auth_ntlmssp_state);
1281                 data_blob_free(&blob1);
1282                 return;
1283         }
1284
1285         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1286                 DATA_BLOB chal;
1287
1288                 if (!vuser->auth_ntlmssp_state) {
1289                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1290                         if (!NT_STATUS_IS_OK(status)) {
1291                                 /* Kill the intermediate vuid */
1292                                 invalidate_vuid(vuid);
1293                                 data_blob_free(&blob1);
1294                                 reply_nterror(req, nt_status_squash(status));
1295                                 return;
1296                         }
1297                 }
1298
1299                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1300                                                 blob1, &chal);
1301
1302                 data_blob_free(&blob1);
1303
1304                 reply_spnego_ntlmssp(req, vuid,
1305                                      &vuser->auth_ntlmssp_state,
1306                                      &chal, status, OID_NTLMSSP, false);
1307                 data_blob_free(&chal);
1308                 return;
1309         }
1310
1311         /* what sort of packet is this? */
1312         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1313
1314         data_blob_free(&blob1);
1315
1316         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1317 }
1318
1319 /****************************************************************************
1320  On new VC == 0, shutdown *all* old connections and users.
1321  It seems that only NT4.x does this. At W2K and above (XP etc.).
1322  a new session setup with VC==0 is ignored.
1323 ****************************************************************************/
1324
1325 static int shutdown_other_smbds(struct db_record *rec,
1326                                 const struct connections_key *key,
1327                                 const struct connections_data *crec,
1328                                 void *private_data)
1329 {
1330         const char *ip = (const char *)private_data;
1331
1332         if (!process_exists(crec->pid)) {
1333                 return 0;
1334         }
1335
1336         if (procid_is_me(&crec->pid)) {
1337                 return 0;
1338         }
1339
1340         if (strcmp(ip, crec->addr) != 0) {
1341                 return 0;
1342         }
1343
1344         messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1345                        &data_blob_null);
1346         return 0;
1347 }
1348
1349 static void setup_new_vc_session(void)
1350 {
1351         char addr[INET6_ADDRSTRLEN];
1352
1353         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1354                 "compatible we would close all old resources.\n"));
1355 #if 0
1356         conn_close_all();
1357         invalidate_all_vuids();
1358 #endif
1359         if (lp_reset_on_zero_vc()) {
1360                 connections_forall(shutdown_other_smbds,
1361                         CONST_DISCARD(void *,
1362                         client_addr(get_client_fd(),addr,sizeof(addr))));
1363         }
1364 }
1365
1366 /****************************************************************************
1367  Reply to a session setup command.
1368 ****************************************************************************/
1369
1370 void reply_sesssetup_and_X(struct smb_request *req)
1371 {
1372         int sess_vuid;
1373         int smb_bufsize;
1374         DATA_BLOB lm_resp;
1375         DATA_BLOB nt_resp;
1376         DATA_BLOB plaintext_password;
1377         fstring user;
1378         fstring sub_user; /* Sainitised username for substituion */
1379         fstring domain;
1380         fstring native_os;
1381         fstring native_lanman;
1382         fstring primary_domain;
1383         static bool done_sesssetup = False;
1384         auth_usersupplied_info *user_info = NULL;
1385         auth_serversupplied_info *server_info = NULL;
1386         uint16 smb_flag2 = req->flags2;
1387
1388         NTSTATUS nt_status;
1389
1390         bool doencrypt = global_encrypted_passwords_negotiated;
1391
1392         DATA_BLOB session_key;
1393
1394         START_PROFILE(SMBsesssetupX);
1395
1396         ZERO_STRUCT(lm_resp);
1397         ZERO_STRUCT(nt_resp);
1398         ZERO_STRUCT(plaintext_password);
1399
1400         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1401
1402         /* a SPNEGO session setup has 12 command words, whereas a normal
1403            NT1 session setup has 13. See the cifs spec. */
1404         if (req->wct == 12 &&
1405             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1406
1407                 if (!global_spnego_negotiated) {
1408                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1409                                  "at SPNEGO session setup when it was not "
1410                                  "negotiated.\n"));
1411                         reply_nterror(req, nt_status_squash(
1412                                               NT_STATUS_LOGON_FAILURE));
1413                         END_PROFILE(SMBsesssetupX);
1414                         return;
1415                 }
1416
1417                 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1418                         setup_new_vc_session();
1419                 }
1420
1421                 reply_sesssetup_and_X_spnego(req);
1422                 END_PROFILE(SMBsesssetupX);
1423                 return;
1424         }
1425
1426         smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1427
1428         if (Protocol < PROTOCOL_NT1) {
1429                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1430
1431                 /* Never do NT status codes with protocols before NT1 as we
1432                  * don't get client caps. */
1433                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1434
1435                 if ((passlen1 > MAX_PASS_LEN)
1436                     || (passlen1 > smb_bufrem(req->inbuf,
1437                                               smb_buf(req->inbuf)))) {
1438                         reply_nterror(req, nt_status_squash(
1439                                               NT_STATUS_INVALID_PARAMETER));
1440                         END_PROFILE(SMBsesssetupX);
1441                         return;
1442                 }
1443
1444                 if (doencrypt) {
1445                         lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1446                 } else {
1447                         plaintext_password = data_blob(smb_buf(req->inbuf),
1448                                                        passlen1+1);
1449                         /* Ensure null termination */
1450                         plaintext_password.data[passlen1] = 0;
1451                 }
1452
1453                 srvstr_pull_buf(req->inbuf, req->flags2, user,
1454                                 smb_buf(req->inbuf)+passlen1, sizeof(user),
1455                                 STR_TERMINATE);
1456                 *domain = 0;
1457
1458         } else {
1459                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1460                 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1461                 enum remote_arch_types ra_type = get_remote_arch();
1462                 char *p = smb_buf(req->inbuf);
1463                 char *save_p = smb_buf(req->inbuf);
1464                 uint16 byte_count;
1465
1466
1467                 if(global_client_caps == 0) {
1468                         global_client_caps = IVAL(req->inbuf,smb_vwv11);
1469
1470                         if (!(global_client_caps & CAP_STATUS32)) {
1471                                 remove_from_common_flags2(
1472                                                 FLAGS2_32_BIT_ERROR_CODES);
1473                         }
1474
1475                         /* client_caps is used as final determination if
1476                          * client is NT or Win95. This is needed to return
1477                          * the correct error codes in some circumstances.
1478                         */
1479
1480                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1481                                         ra_type == RA_WIN95) {
1482                                 if(!(global_client_caps & (CAP_NT_SMBS|
1483                                                         CAP_STATUS32))) {
1484                                         set_remote_arch( RA_WIN95);
1485                                 }
1486                         }
1487                 }
1488
1489                 if (!doencrypt) {
1490                         /* both Win95 and WinNT stuff up the password
1491                          * lengths for non-encrypting systems. Uggh.
1492
1493                            if passlen1==24 its a win95 system, and its setting
1494                            the password length incorrectly. Luckily it still
1495                            works with the default code because Win95 will null
1496                            terminate the password anyway
1497
1498                            if passlen1>0 and passlen2>0 then maybe its a NT box
1499                            and its setting passlen2 to some random value which
1500                            really stuffs things up. we need to fix that one.  */
1501
1502                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1503                                         passlen2 != 1) {
1504                                 passlen2 = 0;
1505                         }
1506                 }
1507
1508                 /* check for nasty tricks */
1509                 if (passlen1 > MAX_PASS_LEN
1510                     || passlen1 > smb_bufrem(req->inbuf, p)) {
1511                         reply_nterror(req, nt_status_squash(
1512                                               NT_STATUS_INVALID_PARAMETER));
1513                         END_PROFILE(SMBsesssetupX);
1514                         return;
1515                 }
1516
1517                 if (passlen2 > MAX_PASS_LEN
1518                     || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1519                         reply_nterror(req, nt_status_squash(
1520                                               NT_STATUS_INVALID_PARAMETER));
1521                         END_PROFILE(SMBsesssetupX);
1522                         return;
1523                 }
1524
1525                 /* Save the lanman2 password and the NT md4 password. */
1526
1527                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1528                         doencrypt = False;
1529                 }
1530
1531                 if (doencrypt) {
1532                         lm_resp = data_blob(p, passlen1);
1533                         nt_resp = data_blob(p+passlen1, passlen2);
1534                 } else {
1535                         char *pass = NULL;
1536                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1537
1538                         if (unic && (passlen2 == 0) && passlen1) {
1539                                 /* Only a ascii plaintext password was sent. */
1540                                 (void)srvstr_pull_talloc(talloc_tos(),
1541                                                         req->inbuf,
1542                                                         req->flags2,
1543                                                         &pass,
1544                                                         smb_buf(req->inbuf),
1545                                                         passlen1,
1546                                                         STR_TERMINATE|STR_ASCII);
1547                         } else {
1548                                 (void)srvstr_pull_talloc(talloc_tos(),
1549                                                         req->inbuf,
1550                                                         req->flags2,
1551                                                         &pass,
1552                                                         smb_buf(req->inbuf),
1553                                                         unic ? passlen2 : passlen1,
1554                                                         STR_TERMINATE);
1555                         }
1556                         if (!pass) {
1557                                 reply_nterror(req, nt_status_squash(
1558                                               NT_STATUS_INVALID_PARAMETER));
1559                                 END_PROFILE(SMBsesssetupX);
1560                                 return;
1561                         }
1562                         plaintext_password = data_blob(pass, strlen(pass)+1);
1563                 }
1564
1565                 p += passlen1 + passlen2;
1566                 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1567                                      sizeof(user), STR_TERMINATE);
1568                 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1569                                      sizeof(domain), STR_TERMINATE);
1570                 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1571                                      p, sizeof(native_os), STR_TERMINATE);
1572                 p += srvstr_pull_buf(req->inbuf, req->flags2,
1573                                      native_lanman, p, sizeof(native_lanman),
1574                                      STR_TERMINATE);
1575
1576                 /* not documented or decoded by Ethereal but there is one more
1577                  * string in the extra bytes which is the same as the
1578                  * PrimaryDomain when using extended security.  Windows NT 4
1579                  * and 2003 use this string to store the native lanman string.
1580                  * Windows 9x does not include a string here at all so we have
1581                  * to check if we have any extra bytes left */
1582
1583                 byte_count = SVAL(req->inbuf, smb_vwv13);
1584                 if ( PTR_DIFF(p, save_p) < byte_count) {
1585                         p += srvstr_pull_buf(req->inbuf, req->flags2,
1586                                              primary_domain, p,
1587                                              sizeof(primary_domain),
1588                                              STR_TERMINATE);
1589                 } else {
1590                         fstrcpy( primary_domain, "null" );
1591                 }
1592
1593                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1594                         "PrimaryDomain=[%s]\n",
1595                         domain, native_os, native_lanman, primary_domain));
1596
1597                 if ( ra_type == RA_WIN2K ) {
1598                         if ( strlen(native_lanman) == 0 )
1599                                 ra_lanman_string( primary_domain );
1600                         else
1601                                 ra_lanman_string( native_lanman );
1602                 }
1603
1604         }
1605
1606         if (SVAL(req->inbuf,smb_vwv4) == 0) {
1607                 setup_new_vc_session();
1608         }
1609
1610         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1611                                 domain, user, get_remote_machine_name()));
1612
1613         if (*user) {
1614                 if (global_spnego_negotiated) {
1615
1616                         /* This has to be here, because this is a perfectly
1617                          * valid behaviour for guest logons :-( */
1618
1619                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1620                                 "at 'normal' session setup after "
1621                                 "negotiating spnego.\n"));
1622                         reply_nterror(req, nt_status_squash(
1623                                               NT_STATUS_LOGON_FAILURE));
1624                         END_PROFILE(SMBsesssetupX);
1625                         return;
1626                 }
1627                 fstrcpy(sub_user, user);
1628         } else {
1629                 fstrcpy(sub_user, lp_guestaccount());
1630         }
1631
1632         sub_set_smb_name(sub_user);
1633
1634         reload_services(True);
1635
1636         if (lp_security() == SEC_SHARE) {
1637                 /* in share level we should ignore any passwords */
1638
1639                 data_blob_free(&lm_resp);
1640                 data_blob_free(&nt_resp);
1641                 data_blob_clear_free(&plaintext_password);
1642
1643                 map_username(sub_user);
1644                 add_session_user(sub_user);
1645                 add_session_workgroup(domain);
1646                 /* Then force it to null for the benfit of the code below */
1647                 *user = 0;
1648         }
1649
1650         if (!*user) {
1651
1652                 nt_status = check_guest_password(&server_info);
1653
1654         } else if (doencrypt) {
1655                 if (!negprot_global_auth_context) {
1656                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1657                                 "session setup without negprot denied!\n"));
1658                         reply_nterror(req, nt_status_squash(
1659                                               NT_STATUS_LOGON_FAILURE));
1660                         END_PROFILE(SMBsesssetupX);
1661                         return;
1662                 }
1663                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1664                                                 domain,
1665                                                 lm_resp, nt_resp);
1666                 if (NT_STATUS_IS_OK(nt_status)) {
1667                         nt_status = negprot_global_auth_context->check_ntlm_password(
1668                                         negprot_global_auth_context,
1669                                         user_info,
1670                                         &server_info);
1671                 }
1672         } else {
1673                 struct auth_context *plaintext_auth_context = NULL;
1674                 const uint8 *chal;
1675
1676                 nt_status = make_auth_context_subsystem(
1677                                 &plaintext_auth_context);
1678
1679                 if (NT_STATUS_IS_OK(nt_status)) {
1680                         chal = plaintext_auth_context->get_ntlm_challenge(
1681                                         plaintext_auth_context);
1682
1683                         if (!make_user_info_for_reply(&user_info,
1684                                                       user, domain, chal,
1685                                                       plaintext_password)) {
1686                                 nt_status = NT_STATUS_NO_MEMORY;
1687                         }
1688
1689                         if (NT_STATUS_IS_OK(nt_status)) {
1690                                 nt_status = plaintext_auth_context->check_ntlm_password(
1691                                                 plaintext_auth_context,
1692                                                 user_info,
1693                                                 &server_info);
1694
1695                                 (plaintext_auth_context->free)(
1696                                                 &plaintext_auth_context);
1697                         }
1698                 }
1699         }
1700
1701         free_user_info(&user_info);
1702
1703         if (!NT_STATUS_IS_OK(nt_status)) {
1704                 nt_status = do_map_to_guest(nt_status, &server_info,
1705                                 user, domain);
1706         }
1707
1708         if (!NT_STATUS_IS_OK(nt_status)) {
1709                 data_blob_free(&nt_resp);
1710                 data_blob_free(&lm_resp);
1711                 data_blob_clear_free(&plaintext_password);
1712                 reply_nterror(req, nt_status_squash(nt_status));
1713                 END_PROFILE(SMBsesssetupX);
1714                 return;
1715         }
1716
1717         /* Ensure we can't possible take a code path leading to a
1718          * null defref. */
1719         if (!server_info) {
1720                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1721                 END_PROFILE(SMBsesssetupX);
1722                 return;
1723         }
1724
1725         nt_status = create_local_token(server_info);
1726         if (!NT_STATUS_IS_OK(nt_status)) {
1727                 DEBUG(10, ("create_local_token failed: %s\n",
1728                            nt_errstr(nt_status)));
1729                 data_blob_free(&nt_resp);
1730                 data_blob_free(&lm_resp);
1731                 data_blob_clear_free(&plaintext_password);
1732                 reply_nterror(req, nt_status_squash(nt_status));
1733                 END_PROFILE(SMBsesssetupX);
1734                 return;
1735         }
1736
1737         if (server_info->user_session_key.data) {
1738                 session_key = data_blob(server_info->user_session_key.data,
1739                                 server_info->user_session_key.length);
1740         } else {
1741                 session_key = data_blob_null;
1742         }
1743
1744         data_blob_clear_free(&plaintext_password);
1745
1746         /* it's ok - setup a reply */
1747         reply_outbuf(req, 3, 0);
1748         if (Protocol >= PROTOCOL_NT1) {
1749                 push_signature(&req->outbuf);
1750                 /* perhaps grab OS version here?? */
1751         }
1752
1753         if (server_info->guest) {
1754                 SSVAL(req->outbuf,smb_vwv2,1);
1755         }
1756
1757         /* register the name and uid as being validated, so further connections
1758            to a uid can get through without a password, on the same VC */
1759
1760         if (lp_security() == SEC_SHARE) {
1761                 sess_vuid = UID_FIELD_INVALID;
1762                 data_blob_free(&session_key);
1763                 TALLOC_FREE(server_info);
1764         } else {
1765                 /* Ignore the initial vuid. */
1766                 sess_vuid = register_initial_vuid();
1767                 if (sess_vuid == UID_FIELD_INVALID) {
1768                         data_blob_free(&nt_resp);
1769                         data_blob_free(&lm_resp);
1770                         data_blob_free(&session_key);
1771                         reply_nterror(req, nt_status_squash(
1772                                               NT_STATUS_LOGON_FAILURE));
1773                         END_PROFILE(SMBsesssetupX);
1774                         return;
1775                 }
1776                 /* register_existing_vuid keeps the server info */
1777                 sess_vuid = register_existing_vuid(sess_vuid,
1778                                         server_info,
1779                                         session_key,
1780                                         nt_resp.data ? nt_resp : lm_resp,
1781                                         sub_user);
1782                 if (sess_vuid == UID_FIELD_INVALID) {
1783                         data_blob_free(&nt_resp);
1784                         data_blob_free(&lm_resp);
1785                         data_blob_free(&session_key);
1786                         reply_nterror(req, nt_status_squash(
1787                                               NT_STATUS_LOGON_FAILURE));
1788                         END_PROFILE(SMBsesssetupX);
1789                         return;
1790                 }
1791
1792                 /* current_user_info is changed on new vuid */
1793                 reload_services( True );
1794
1795                 sessionsetup_start_signing_engine(server_info, req->inbuf);
1796         }
1797
1798         data_blob_free(&nt_resp);
1799         data_blob_free(&lm_resp);
1800
1801         SSVAL(req->outbuf,smb_uid,sess_vuid);
1802         SSVAL(req->inbuf,smb_uid,sess_vuid);
1803
1804         if (!done_sesssetup)
1805                 max_send = MIN(max_send,smb_bufsize);
1806
1807         done_sesssetup = True;
1808
1809         END_PROFILE(SMBsesssetupX);
1810         chain_reply(req);
1811         return;
1812 }