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