Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.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         data = asn1_init(NULL);
1089         if (data == NULL) {
1090                 return NT_STATUS_NO_MEMORY;
1091         }
1092
1093         asn1_load(data, *pblob);
1094         asn1_start_tag(data, pblob->data[0]);
1095         if (data->has_error || data->nesting == NULL) {
1096                 asn1_free(data);
1097                 /* Let caller catch. */
1098                 return NT_STATUS_OK;
1099         }
1100
1101         /* Integer wrap paranoia.... */
1102
1103         if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1104             data->nesting->taglen + data->nesting->start < data->nesting->start) {
1105
1106                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1107                         "data.nesting->taglen = %u, "
1108                         "data.nesting->start = %u\n",
1109                         (unsigned int)data->nesting->taglen,
1110                         (unsigned int)data->nesting->start ));
1111
1112                 asn1_free(data);
1113                 return NT_STATUS_INVALID_PARAMETER;
1114         }
1115
1116         /* Total length of the needed asn1 is the tag length
1117          * plus the current offset. */
1118
1119         needed_len = data->nesting->taglen + data->nesting->start;
1120         asn1_free(data);
1121
1122         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1123                 "pblob->length = %u\n",
1124                 (unsigned int)needed_len,
1125                 (unsigned int)pblob->length ));
1126
1127         if (needed_len <= pblob->length) {
1128                 /* Nothing to do - blob is complete. */
1129                 return NT_STATUS_OK;
1130         }
1131
1132         /* Refuse the blob if it's bigger than 64k. */
1133         if (needed_len > 65536) {
1134                 DEBUG(2,("check_spnego_blob_complete: needed_len "
1135                         "too large (%u)\n",
1136                         (unsigned int)needed_len ));
1137                 return NT_STATUS_INVALID_PARAMETER;
1138         }
1139
1140         /* We must store this blob until complete. */
1141         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1142                 return NT_STATUS_NO_MEMORY;
1143         }
1144         pad->needed_len = needed_len - pblob->length;
1145         pad->partial_data = data_blob(pblob->data, pblob->length);
1146         if (pad->partial_data.data == NULL) {
1147                 SAFE_FREE(pad);
1148                 return NT_STATUS_NO_MEMORY;
1149         }
1150         pad->smbpid = smbpid;
1151         pad->vuid = vuid;
1152         DLIST_ADD(pd_list, pad);
1153
1154         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1155 }
1156
1157 /****************************************************************************
1158  Reply to a session setup command.
1159  conn POINTER CAN BE NULL HERE !
1160 ****************************************************************************/
1161
1162 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1163 {
1164         const uint8 *p;
1165         DATA_BLOB blob1;
1166         size_t bufrem;
1167         char *tmp;
1168         const char *native_os;
1169         const char *native_lanman;
1170         const char *primary_domain;
1171         const char *p2;
1172         uint16 data_blob_len = SVAL(req->vwv+7, 0);
1173         enum remote_arch_types ra_type = get_remote_arch();
1174         int vuid = req->vuid;
1175         user_struct *vuser = NULL;
1176         NTSTATUS status = NT_STATUS_OK;
1177         uint16 smbpid = req->smbpid;
1178
1179         DEBUG(3,("Doing spnego session setup\n"));
1180
1181         if (global_client_caps == 0) {
1182                 global_client_caps = IVAL(req->vwv+10, 0);
1183
1184                 if (!(global_client_caps & CAP_STATUS32)) {
1185                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1186                 }
1187
1188         }
1189
1190         p = req->buf;
1191
1192         if (data_blob_len == 0) {
1193                 /* an invalid request */
1194                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1195                 return;
1196         }
1197
1198         bufrem = smbreq_bufrem(req, p);
1199         /* pull the spnego blob */
1200         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1201
1202 #if 0
1203         file_save("negotiate.dat", blob1.data, blob1.length);
1204 #endif
1205
1206         p2 = (char *)req->buf + data_blob_len;
1207
1208         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1209                                      STR_TERMINATE);
1210         native_os = tmp ? tmp : "";
1211
1212         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1213                                      STR_TERMINATE);
1214         native_lanman = tmp ? tmp : "";
1215
1216         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1217                                      STR_TERMINATE);
1218         primary_domain = tmp ? tmp : "";
1219
1220         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1221                 native_os, native_lanman, primary_domain));
1222
1223         if ( ra_type == RA_WIN2K ) {
1224                 /* Vista sets neither the OS or lanman strings */
1225
1226                 if ( !strlen(native_os) && !strlen(native_lanman) )
1227                         set_remote_arch(RA_VISTA);
1228
1229                 /* Windows 2003 doesn't set the native lanman string,
1230                    but does set primary domain which is a bug I think */
1231
1232                 if ( !strlen(native_lanman) ) {
1233                         ra_lanman_string( primary_domain );
1234                 } else {
1235                         ra_lanman_string( native_lanman );
1236                 }
1237         }
1238
1239         /* Did we get a valid vuid ? */
1240         if (!is_partial_auth_vuid(vuid)) {
1241                 /* No, then try and see if this is an intermediate sessionsetup
1242                  * for a large SPNEGO packet. */
1243                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1244                 if (pad) {
1245                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1246                                 "pending vuid %u\n",
1247                                 (unsigned int)pad->vuid ));
1248                         vuid = pad->vuid;
1249                 }
1250         }
1251
1252         /* Do we have a valid vuid now ? */
1253         if (!is_partial_auth_vuid(vuid)) {
1254                 /* No, start a new authentication setup. */
1255                 vuid = register_initial_vuid();
1256                 if (vuid == UID_FIELD_INVALID) {
1257                         data_blob_free(&blob1);
1258                         reply_nterror(req, nt_status_squash(
1259                                               NT_STATUS_INVALID_PARAMETER));
1260                         return;
1261                 }
1262         }
1263
1264         vuser = get_partial_auth_user_struct(vuid);
1265         /* This MUST be valid. */
1266         if (!vuser) {
1267                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1268         }
1269
1270         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1271          * sessionsetup requests as the Windows limit on the security blob
1272          * field is 4k. Bug #4400. JRA.
1273          */
1274
1275         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1276         if (!NT_STATUS_IS_OK(status)) {
1277                 if (!NT_STATUS_EQUAL(status,
1278                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1279                         /* Real error - kill the intermediate vuid */
1280                         invalidate_vuid(vuid);
1281                 }
1282                 data_blob_free(&blob1);
1283                 reply_nterror(req, nt_status_squash(status));
1284                 return;
1285         }
1286
1287         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1288
1289                 /* its a negTokenTarg packet */
1290
1291                 reply_spnego_negotiate(req, vuid, blob1,
1292                                        &vuser->auth_ntlmssp_state);
1293                 data_blob_free(&blob1);
1294                 return;
1295         }
1296
1297         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1298
1299                 /* its a auth packet */
1300
1301                 reply_spnego_auth(req, vuid, blob1,
1302                                   &vuser->auth_ntlmssp_state);
1303                 data_blob_free(&blob1);
1304                 return;
1305         }
1306
1307         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1308                 DATA_BLOB chal;
1309
1310                 if (!vuser->auth_ntlmssp_state) {
1311                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1312                         if (!NT_STATUS_IS_OK(status)) {
1313                                 /* Kill the intermediate vuid */
1314                                 invalidate_vuid(vuid);
1315                                 data_blob_free(&blob1);
1316                                 reply_nterror(req, nt_status_squash(status));
1317                                 return;
1318                         }
1319                 }
1320
1321                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1322                                                 blob1, &chal);
1323
1324                 data_blob_free(&blob1);
1325
1326                 reply_spnego_ntlmssp(req, vuid,
1327                                      &vuser->auth_ntlmssp_state,
1328                                      &chal, status, OID_NTLMSSP, false);
1329                 data_blob_free(&chal);
1330                 return;
1331         }
1332
1333         /* what sort of packet is this? */
1334         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1335
1336         data_blob_free(&blob1);
1337
1338         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1339 }
1340
1341 /****************************************************************************
1342  On new VC == 0, shutdown *all* old connections and users.
1343  It seems that only NT4.x does this. At W2K and above (XP etc.).
1344  a new session setup with VC==0 is ignored.
1345 ****************************************************************************/
1346
1347 static int shutdown_other_smbds(struct db_record *rec,
1348                                 const struct connections_key *key,
1349                                 const struct connections_data *crec,
1350                                 void *private_data)
1351 {
1352         const char *ip = (const char *)private_data;
1353
1354         if (!process_exists(crec->pid)) {
1355                 return 0;
1356         }
1357
1358         if (procid_is_me(&crec->pid)) {
1359                 return 0;
1360         }
1361
1362         if (strcmp(ip, crec->addr) != 0) {
1363                 return 0;
1364         }
1365
1366         DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
1367                  "(IP %s)\n", procid_to_pid(&crec->pid), ip));
1368
1369         messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1370                        &data_blob_null);
1371         return 0;
1372 }
1373
1374 static void setup_new_vc_session(void)
1375 {
1376         char addr[INET6_ADDRSTRLEN];
1377
1378         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1379                 "compatible we would close all old resources.\n"));
1380 #if 0
1381         conn_close_all();
1382         invalidate_all_vuids();
1383 #endif
1384         if (lp_reset_on_zero_vc()) {
1385                 connections_forall(shutdown_other_smbds,
1386                         CONST_DISCARD(void *,
1387                         client_addr(get_client_fd(),addr,sizeof(addr))));
1388         }
1389 }
1390
1391 /****************************************************************************
1392  Reply to a session setup command.
1393 ****************************************************************************/
1394
1395 void reply_sesssetup_and_X(struct smb_request *req)
1396 {
1397         int sess_vuid;
1398         int smb_bufsize;
1399         DATA_BLOB lm_resp;
1400         DATA_BLOB nt_resp;
1401         DATA_BLOB plaintext_password;
1402         char *tmp;
1403         const char *user;
1404         fstring sub_user; /* Sainitised username for substituion */
1405         const char *domain;
1406         const char *native_os;
1407         const char *native_lanman;
1408         const char *primary_domain;
1409         static bool done_sesssetup = False;
1410         auth_usersupplied_info *user_info = NULL;
1411         auth_serversupplied_info *server_info = NULL;
1412         uint16 smb_flag2 = req->flags2;
1413
1414         NTSTATUS nt_status;
1415
1416         bool doencrypt = global_encrypted_passwords_negotiated;
1417
1418         START_PROFILE(SMBsesssetupX);
1419
1420         ZERO_STRUCT(lm_resp);
1421         ZERO_STRUCT(nt_resp);
1422         ZERO_STRUCT(plaintext_password);
1423
1424         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1425
1426         /* a SPNEGO session setup has 12 command words, whereas a normal
1427            NT1 session setup has 13. See the cifs spec. */
1428         if (req->wct == 12 &&
1429             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1430
1431                 if (!global_spnego_negotiated) {
1432                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1433                                  "at SPNEGO session setup when it was not "
1434                                  "negotiated.\n"));
1435                         reply_nterror(req, nt_status_squash(
1436                                               NT_STATUS_LOGON_FAILURE));
1437                         END_PROFILE(SMBsesssetupX);
1438                         return;
1439                 }
1440
1441                 if (SVAL(req->vwv+4, 0) == 0) {
1442                         setup_new_vc_session();
1443                 }
1444
1445                 reply_sesssetup_and_X_spnego(req);
1446                 END_PROFILE(SMBsesssetupX);
1447                 return;
1448         }
1449
1450         smb_bufsize = SVAL(req->vwv+2, 0);
1451
1452         if (Protocol < PROTOCOL_NT1) {
1453                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1454
1455                 /* Never do NT status codes with protocols before NT1 as we
1456                  * don't get client caps. */
1457                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1458
1459                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1460                         reply_nterror(req, nt_status_squash(
1461                                               NT_STATUS_INVALID_PARAMETER));
1462                         END_PROFILE(SMBsesssetupX);
1463                         return;
1464                 }
1465
1466                 if (doencrypt) {
1467                         lm_resp = data_blob(req->buf, passlen1);
1468                 } else {
1469                         plaintext_password = data_blob(req->buf, passlen1+1);
1470                         /* Ensure null termination */
1471                         plaintext_password.data[passlen1] = 0;
1472                 }
1473
1474                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1475                                        req->buf + passlen1, STR_TERMINATE);
1476                 user = tmp ? tmp : "";
1477
1478                 domain = "";
1479
1480         } else {
1481                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1482                 uint16 passlen2 = SVAL(req->vwv+8, 0);
1483                 enum remote_arch_types ra_type = get_remote_arch();
1484                 const uint8_t *p = req->buf;
1485                 const uint8_t *save_p = req->buf;
1486                 uint16 byte_count;
1487
1488
1489                 if(global_client_caps == 0) {
1490                         global_client_caps = IVAL(req->vwv+11, 0);
1491
1492                         if (!(global_client_caps & CAP_STATUS32)) {
1493                                 remove_from_common_flags2(
1494                                                 FLAGS2_32_BIT_ERROR_CODES);
1495                         }
1496
1497                         /* client_caps is used as final determination if
1498                          * client is NT or Win95. This is needed to return
1499                          * the correct error codes in some circumstances.
1500                         */
1501
1502                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1503                                         ra_type == RA_WIN95) {
1504                                 if(!(global_client_caps & (CAP_NT_SMBS|
1505                                                         CAP_STATUS32))) {
1506                                         set_remote_arch( RA_WIN95);
1507                                 }
1508                         }
1509                 }
1510
1511                 if (!doencrypt) {
1512                         /* both Win95 and WinNT stuff up the password
1513                          * lengths for non-encrypting systems. Uggh.
1514
1515                            if passlen1==24 its a win95 system, and its setting
1516                            the password length incorrectly. Luckily it still
1517                            works with the default code because Win95 will null
1518                            terminate the password anyway
1519
1520                            if passlen1>0 and passlen2>0 then maybe its a NT box
1521                            and its setting passlen2 to some random value which
1522                            really stuffs things up. we need to fix that one.  */
1523
1524                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1525                                         passlen2 != 1) {
1526                                 passlen2 = 0;
1527                         }
1528                 }
1529
1530                 /* check for nasty tricks */
1531                 if (passlen1 > MAX_PASS_LEN
1532                     || passlen1 > smbreq_bufrem(req, p)) {
1533                         reply_nterror(req, nt_status_squash(
1534                                               NT_STATUS_INVALID_PARAMETER));
1535                         END_PROFILE(SMBsesssetupX);
1536                         return;
1537                 }
1538
1539                 if (passlen2 > MAX_PASS_LEN
1540                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1541                         reply_nterror(req, nt_status_squash(
1542                                               NT_STATUS_INVALID_PARAMETER));
1543                         END_PROFILE(SMBsesssetupX);
1544                         return;
1545                 }
1546
1547                 /* Save the lanman2 password and the NT md4 password. */
1548
1549                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1550                         doencrypt = False;
1551                 }
1552
1553                 if (doencrypt) {
1554                         lm_resp = data_blob(p, passlen1);
1555                         nt_resp = data_blob(p+passlen1, passlen2);
1556                 } else if (lp_security() != SEC_SHARE) {
1557                         /*
1558                          * In share level we should ignore any passwords, so
1559                          * only read them if we're not.
1560                          */
1561                         char *pass = NULL;
1562                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1563
1564                         if (unic && (passlen2 == 0) && passlen1) {
1565                                 /* Only a ascii plaintext password was sent. */
1566                                 (void)srvstr_pull_talloc(talloc_tos(),
1567                                                         req->inbuf,
1568                                                         req->flags2,
1569                                                         &pass,
1570                                                         req->buf,
1571                                                         passlen1,
1572                                                         STR_TERMINATE|STR_ASCII);
1573                         } else {
1574                                 (void)srvstr_pull_talloc(talloc_tos(),
1575                                                         req->inbuf,
1576                                                         req->flags2,
1577                                                         &pass,
1578                                                         req->buf,
1579                                                         unic ? passlen2 : passlen1,
1580                                                         STR_TERMINATE);
1581                         }
1582                         if (!pass) {
1583                                 reply_nterror(req, nt_status_squash(
1584                                               NT_STATUS_INVALID_PARAMETER));
1585                                 END_PROFILE(SMBsesssetupX);
1586                                 return;
1587                         }
1588                         plaintext_password = data_blob(pass, strlen(pass)+1);
1589                 }
1590
1591                 p += passlen1 + passlen2;
1592
1593                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1594                                             STR_TERMINATE);
1595                 user = tmp ? tmp : "";
1596
1597                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1598                                             STR_TERMINATE);
1599                 domain = tmp ? tmp : "";
1600
1601                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1602                                             STR_TERMINATE);
1603                 native_os = tmp ? tmp : "";
1604
1605                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1606                                             STR_TERMINATE);
1607                 native_lanman = tmp ? tmp : "";
1608
1609                 /* not documented or decoded by Ethereal but there is one more
1610                  * string in the extra bytes which is the same as the
1611                  * PrimaryDomain when using extended security.  Windows NT 4
1612                  * and 2003 use this string to store the native lanman string.
1613                  * Windows 9x does not include a string here at all so we have
1614                  * to check if we have any extra bytes left */
1615
1616                 byte_count = SVAL(req->vwv+13, 0);
1617                 if ( PTR_DIFF(p, save_p) < byte_count) {
1618                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1619                                                     STR_TERMINATE);
1620                         primary_domain = tmp ? tmp : "";
1621                 } else {
1622                         primary_domain = talloc_strdup(talloc_tos(), "null");
1623                 }
1624
1625                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1626                         "PrimaryDomain=[%s]\n",
1627                         domain, native_os, native_lanman, primary_domain));
1628
1629                 if ( ra_type == RA_WIN2K ) {
1630                         if ( strlen(native_lanman) == 0 )
1631                                 ra_lanman_string( primary_domain );
1632                         else
1633                                 ra_lanman_string( native_lanman );
1634                 }
1635
1636         }
1637
1638         if (SVAL(req->vwv+4, 0) == 0) {
1639                 setup_new_vc_session();
1640         }
1641
1642         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1643                                 domain, user, get_remote_machine_name()));
1644
1645         if (*user) {
1646                 if (global_spnego_negotiated) {
1647
1648                         /* This has to be here, because this is a perfectly
1649                          * valid behaviour for guest logons :-( */
1650
1651                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1652                                 "at 'normal' session setup after "
1653                                 "negotiating spnego.\n"));
1654                         reply_nterror(req, nt_status_squash(
1655                                               NT_STATUS_LOGON_FAILURE));
1656                         END_PROFILE(SMBsesssetupX);
1657                         return;
1658                 }
1659                 fstrcpy(sub_user, user);
1660         } else {
1661                 fstrcpy(sub_user, lp_guestaccount());
1662         }
1663
1664         sub_set_smb_name(sub_user);
1665
1666         reload_services(True);
1667
1668         if (lp_security() == SEC_SHARE) {
1669                 /* In share level we should ignore any passwords */
1670
1671                 data_blob_free(&lm_resp);
1672                 data_blob_free(&nt_resp);
1673                 data_blob_clear_free(&plaintext_password);
1674
1675                 map_username(sub_user);
1676                 add_session_user(sub_user);
1677                 add_session_workgroup(domain);
1678                 /* Then force it to null for the benfit of the code below */
1679                 user = "";
1680         }
1681
1682         if (!*user) {
1683
1684                 nt_status = check_guest_password(&server_info);
1685
1686         } else if (doencrypt) {
1687                 if (!negprot_global_auth_context) {
1688                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1689                                 "session setup without negprot denied!\n"));
1690                         reply_nterror(req, nt_status_squash(
1691                                               NT_STATUS_LOGON_FAILURE));
1692                         END_PROFILE(SMBsesssetupX);
1693                         return;
1694                 }
1695                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1696                                                 domain,
1697                                                 lm_resp, nt_resp);
1698                 if (NT_STATUS_IS_OK(nt_status)) {
1699                         nt_status = negprot_global_auth_context->check_ntlm_password(
1700                                         negprot_global_auth_context,
1701                                         user_info,
1702                                         &server_info);
1703                 }
1704         } else {
1705                 struct auth_context *plaintext_auth_context = NULL;
1706                 const uint8 *chal;
1707
1708                 nt_status = make_auth_context_subsystem(
1709                                 &plaintext_auth_context);
1710
1711                 if (NT_STATUS_IS_OK(nt_status)) {
1712                         chal = plaintext_auth_context->get_ntlm_challenge(
1713                                         plaintext_auth_context);
1714
1715                         if (!make_user_info_for_reply(&user_info,
1716                                                       user, domain, chal,
1717                                                       plaintext_password)) {
1718                                 nt_status = NT_STATUS_NO_MEMORY;
1719                         }
1720
1721                         if (NT_STATUS_IS_OK(nt_status)) {
1722                                 nt_status = plaintext_auth_context->check_ntlm_password(
1723                                                 plaintext_auth_context,
1724                                                 user_info,
1725                                                 &server_info);
1726
1727                                 (plaintext_auth_context->free)(
1728                                                 &plaintext_auth_context);
1729                         }
1730                 }
1731         }
1732
1733         free_user_info(&user_info);
1734
1735         if (!NT_STATUS_IS_OK(nt_status)) {
1736                 nt_status = do_map_to_guest(nt_status, &server_info,
1737                                 user, domain);
1738         }
1739
1740         if (!NT_STATUS_IS_OK(nt_status)) {
1741                 data_blob_free(&nt_resp);
1742                 data_blob_free(&lm_resp);
1743                 data_blob_clear_free(&plaintext_password);
1744                 reply_nterror(req, nt_status_squash(nt_status));
1745                 END_PROFILE(SMBsesssetupX);
1746                 return;
1747         }
1748
1749         /* Ensure we can't possible take a code path leading to a
1750          * null defref. */
1751         if (!server_info) {
1752                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1753                 END_PROFILE(SMBsesssetupX);
1754                 return;
1755         }
1756
1757         if (!server_info->ptok) {
1758                 nt_status = create_local_token(server_info);
1759
1760                 if (!NT_STATUS_IS_OK(nt_status)) {
1761                         DEBUG(10, ("create_local_token failed: %s\n",
1762                                    nt_errstr(nt_status)));
1763                         data_blob_free(&nt_resp);
1764                         data_blob_free(&lm_resp);
1765                         data_blob_clear_free(&plaintext_password);
1766                         reply_nterror(req, nt_status_squash(nt_status));
1767                         END_PROFILE(SMBsesssetupX);
1768                         return;
1769                 }
1770         }
1771
1772         data_blob_clear_free(&plaintext_password);
1773
1774         /* it's ok - setup a reply */
1775         reply_outbuf(req, 3, 0);
1776         if (Protocol >= PROTOCOL_NT1) {
1777                 push_signature(&req->outbuf);
1778                 /* perhaps grab OS version here?? */
1779         }
1780
1781         if (server_info->guest) {
1782                 SSVAL(req->outbuf,smb_vwv2,1);
1783         }
1784
1785         /* register the name and uid as being validated, so further connections
1786            to a uid can get through without a password, on the same VC */
1787
1788         if (lp_security() == SEC_SHARE) {
1789                 sess_vuid = UID_FIELD_INVALID;
1790                 TALLOC_FREE(server_info);
1791         } else {
1792                 /* Ignore the initial vuid. */
1793                 sess_vuid = register_initial_vuid();
1794                 if (sess_vuid == UID_FIELD_INVALID) {
1795                         data_blob_free(&nt_resp);
1796                         data_blob_free(&lm_resp);
1797                         reply_nterror(req, nt_status_squash(
1798                                               NT_STATUS_LOGON_FAILURE));
1799                         END_PROFILE(SMBsesssetupX);
1800                         return;
1801                 }
1802                 /* register_existing_vuid keeps the server info */
1803                 sess_vuid = register_existing_vuid(sess_vuid,
1804                                         server_info,
1805                                         nt_resp.data ? nt_resp : lm_resp,
1806                                         sub_user);
1807                 if (sess_vuid == UID_FIELD_INVALID) {
1808                         data_blob_free(&nt_resp);
1809                         data_blob_free(&lm_resp);
1810                         reply_nterror(req, nt_status_squash(
1811                                               NT_STATUS_LOGON_FAILURE));
1812                         END_PROFILE(SMBsesssetupX);
1813                         return;
1814                 }
1815
1816                 /* current_user_info is changed on new vuid */
1817                 reload_services( True );
1818
1819                 sessionsetup_start_signing_engine(server_info, req->inbuf);
1820         }
1821
1822         data_blob_free(&nt_resp);
1823         data_blob_free(&lm_resp);
1824
1825         SSVAL(req->outbuf,smb_uid,sess_vuid);
1826         SSVAL(req->inbuf,smb_uid,sess_vuid);
1827
1828         if (!done_sesssetup)
1829                 max_send = MIN(max_send,smb_bufsize);
1830
1831         done_sesssetup = True;
1832
1833         END_PROFILE(SMBsesssetupX);
1834         chain_reply(req);
1835         return;
1836 }