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