Fix Kerberos interop with Mac OS X 10.5 clients.
[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(server_info);
49                 }
50         }
51
52         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54                         DEBUG(3,("Registered username %s for guest access\n",
55                                 user));
56                         status = make_server_info_guest(server_info);
57                 }
58         }
59
60         return status;
61 }
62
63 /****************************************************************************
64  Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
66
67 static int push_signature(uint8 **outbuf)
68 {
69         char *lanman;
70         int result, tmp;
71
72         result = 0;
73
74         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
75
76         if (tmp == -1) return -1;
77         result += tmp;
78
79         if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
81                 SAFE_FREE(lanman);
82         }
83         else {
84                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
85         }
86
87         if (tmp == -1) return -1;
88         result += tmp;
89
90         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
91
92         if (tmp == -1) return -1;
93         result += tmp;
94
95         return result;
96 }
97
98 /****************************************************************************
99  Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
101
102 static void sessionsetup_start_signing_engine(
103                         const auth_serversupplied_info *server_info,
104                         const uint8 *inbuf)
105 {
106         if (!server_info->guest && !srv_signing_started()) {
107                 /* We need to start the signing engine
108                  * here but a W2K client sends the old
109                  * "BSRSPYL " signature instead of the
110                  * correct one. Subsequent packets will
111                  * be correct.
112                  */
113                 srv_check_sign_mac((char *)inbuf, False);
114         }
115 }
116
117 /****************************************************************************
118  Send a security blob via a session setup reply.
119 ****************************************************************************/
120
121 static void reply_sesssetup_blob(struct smb_request *req,
122                                  DATA_BLOB blob,
123                                  NTSTATUS nt_status)
124 {
125         if (!NT_STATUS_IS_OK(nt_status) &&
126             !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
127                 reply_nterror(req, nt_status_squash(nt_status));
128         } else {
129                 nt_status = nt_status_squash(nt_status);
130                 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
131                 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
132                 SSVAL(req->outbuf, smb_vwv3, blob.length);
133
134                 if ((message_push_blob(&req->outbuf, blob) == -1)
135                     || (push_signature(&req->outbuf) == -1)) {
136                         reply_nterror(req, NT_STATUS_NO_MEMORY);
137                 }
138         }
139
140         show_msg((char *)req->outbuf);
141         srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
142         TALLOC_FREE(req->outbuf);
143 }
144
145 /****************************************************************************
146  Do a 'guest' logon, getting back the
147 ****************************************************************************/
148
149 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
150 {
151         struct auth_context *auth_context;
152         auth_usersupplied_info *user_info = NULL;
153
154         NTSTATUS nt_status;
155         unsigned char chal[8];
156
157         ZERO_STRUCT(chal);
158
159         DEBUG(3,("Got anonymous request\n"));
160
161         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
162                                         chal))) {
163                 return nt_status;
164         }
165
166         if (!make_user_info_guest(&user_info)) {
167                 (auth_context->free)(&auth_context);
168                 return NT_STATUS_NO_MEMORY;
169         }
170
171         nt_status = auth_context->check_ntlm_password(auth_context,
172                                                 user_info,
173                                                 server_info);
174         (auth_context->free)(&auth_context);
175         free_user_info(&user_info);
176         return nt_status;
177 }
178
179
180 #ifdef HAVE_KRB5
181
182 #if 0
183 /* Experiment that failed. See "only happens with a KDC" comment below. */
184 /****************************************************************************
185  Cerate a clock skew error blob for a Windows client.
186 ****************************************************************************/
187
188 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
189 {
190         krb5_context context = NULL;
191         krb5_error_code kerr = 0;
192         krb5_data reply;
193         krb5_principal host_princ = NULL;
194         char *host_princ_s = NULL;
195         bool ret = False;
196
197         *pblob_out = data_blob_null;
198
199         initialize_krb5_error_table();
200         kerr = krb5_init_context(&context);
201         if (kerr) {
202                 return False;
203         }
204         /* Create server principal. */
205         asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
206         if (!host_princ_s) {
207                 goto out;
208         }
209         strlower_m(host_princ_s);
210
211         kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
212         if (kerr) {
213                 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
214                         "for name %s: Error %s\n",
215                         host_princ_s, error_message(kerr) ));
216                 goto out;
217         }
218
219         kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
220                         host_princ, &reply);
221         if (kerr) {
222                 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
223                         "failed: Error %s\n",
224                         error_message(kerr) ));
225                 goto out;
226         }
227
228         *pblob_out = data_blob(reply.data, reply.length);
229         kerberos_free_data_contents(context,&reply);
230         ret = True;
231
232   out:
233
234         if (host_princ_s) {
235                 SAFE_FREE(host_princ_s);
236         }
237         if (host_princ) {
238                 krb5_free_principal(context, host_princ);
239         }
240         krb5_free_context(context);
241         return ret;
242 }
243 #endif
244
245 /****************************************************************************
246  Reply to a session setup spnego negotiate packet for kerberos.
247 ****************************************************************************/
248
249 static void reply_spnego_kerberos(struct smb_request *req,
250                                   DATA_BLOB *secblob,
251                                   const char *mechOID,
252                                   uint16 vuid,
253                                   bool *p_invalidate_vuid)
254 {
255         TALLOC_CTX *mem_ctx;
256         DATA_BLOB ticket;
257         char *client, *p, *domain;
258         fstring netbios_domain_name;
259         struct passwd *pw;
260         fstring user;
261         int sess_vuid = req->vuid;
262         NTSTATUS ret = NT_STATUS_OK;
263         struct PAC_DATA *pac_data = NULL;
264         DATA_BLOB ap_rep, ap_rep_wrapped, response;
265         auth_serversupplied_info *server_info = NULL;
266         DATA_BLOB session_key = data_blob_null;
267         uint8 tok_id[2];
268         DATA_BLOB nullblob = data_blob_null;
269         fstring real_username;
270         bool map_domainuser_to_guest = False;
271         bool username_was_mapped;
272         struct PAC_LOGON_INFO *logon_info = NULL;
273
274         ZERO_STRUCT(ticket);
275         ZERO_STRUCT(ap_rep);
276         ZERO_STRUCT(ap_rep_wrapped);
277         ZERO_STRUCT(response);
278
279         /* Normally we will always invalidate the intermediate vuid. */
280         *p_invalidate_vuid = True;
281
282         mem_ctx = talloc_init("reply_spnego_kerberos");
283         if (mem_ctx == NULL) {
284                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
285                 return;
286         }
287
288         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
289                 talloc_destroy(mem_ctx);
290                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
291                 return;
292         }
293
294         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
295                                 &client, &pac_data, &ap_rep,
296                                 &session_key, True);
297
298         data_blob_free(&ticket);
299
300         if (!NT_STATUS_IS_OK(ret)) {
301 #if 0
302                 /* Experiment that failed.
303                  * See "only happens with a KDC" comment below. */
304
305                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
306
307                         /*
308                          * Windows in this case returns
309                          * NT_STATUS_MORE_PROCESSING_REQUIRED
310                          * with a negTokenTarg blob containing an krb5_error
311                          * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
312                          * The client then fixes its clock and continues rather
313                          * than giving an error. JRA.
314                          * -- Looks like this only happens with a KDC. JRA.
315                          */
316
317                         bool ok = make_krb5_skew_error(&ap_rep);
318                         if (!ok) {
319                                 talloc_destroy(mem_ctx);
320                                 return ERROR_NT(nt_status_squash(
321                                                 NT_STATUS_LOGON_FAILURE));
322                         }
323                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
324                                         TOK_ID_KRB_ERROR);
325                         response = spnego_gen_auth_response(&ap_rep_wrapped,
326                                         ret, OID_KERBEROS5_OLD);
327                         reply_sesssetup_blob(conn, inbuf, outbuf, response,
328                                         NT_STATUS_MORE_PROCESSING_REQUIRED);
329
330                         /*
331                          * In this one case we don't invalidate the
332                          * intermediate vuid as we're expecting the client
333                          * to re-use it for the next sessionsetupX packet. JRA.
334                          */
335
336                         *p_invalidate_vuid = False;
337
338                         data_blob_free(&ap_rep);
339                         data_blob_free(&ap_rep_wrapped);
340                         data_blob_free(&response);
341                         talloc_destroy(mem_ctx);
342                         return -1; /* already replied */
343                 }
344 #else
345                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
346                         ret = NT_STATUS_LOGON_FAILURE;
347                 }
348 #endif
349                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
350                                 nt_errstr(ret)));
351                 talloc_destroy(mem_ctx);
352                 reply_nterror(req, nt_status_squash(ret));
353                 return;
354         }
355
356         DEBUG(3,("Ticket name is [%s]\n", client));
357
358         p = strchr_m(client, '@');
359         if (!p) {
360                 DEBUG(3,("Doesn't look like a valid principal\n"));
361                 data_blob_free(&ap_rep);
362                 data_blob_free(&session_key);
363                 SAFE_FREE(client);
364                 talloc_destroy(mem_ctx);
365                 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
366                 return;
367         }
368
369         *p = 0;
370
371         /* save the PAC data if we have it */
372
373         if (pac_data) {
374                 logon_info = get_logon_info_from_pac(pac_data);
375                 if (logon_info) {
376                         netsamlogon_cache_store( client, &logon_info->info3 );
377                 }
378         }
379
380         if (!strequal(p+1, lp_realm())) {
381                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
382                 if (!lp_allow_trusted_domains()) {
383                         data_blob_free(&ap_rep);
384                         data_blob_free(&session_key);
385                         SAFE_FREE(client);
386                         talloc_destroy(mem_ctx);
387                         reply_nterror(req, nt_status_squash(
388                                               NT_STATUS_LOGON_FAILURE));
389                         return;
390                 }
391         }
392
393         /* this gives a fully qualified user name (ie. with full realm).
394            that leads to very long usernames, but what else can we do? */
395
396         domain = p+1;
397
398         if (logon_info && logon_info->info3.base.domain.string) {
399                 fstrcpy(netbios_domain_name,
400                         logon_info->info3.base.domain.string);
401                 domain = netbios_domain_name;
402                 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
403
404         } else {
405
406                 /* If we have winbind running, we can (and must) shorten the
407                    username by using the short netbios name. Otherwise we will
408                    have inconsistent user names. With Kerberos, we get the
409                    fully qualified realm, with ntlmssp we get the short
410                    name. And even w2k3 does use ntlmssp if you for example
411                    connect to an ip address. */
412
413                 wbcErr wbc_status;
414                 struct wbcDomainInfo *info = NULL;
415
416                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
417
418                 wbc_status = wbcDomainInfo(domain, &info);
419
420                 if (WBC_ERROR_IS_OK(wbc_status)) {
421
422                         fstrcpy(netbios_domain_name,
423                                 info->short_name);
424
425                         wbcFreeMemory(info);
426                         domain = netbios_domain_name;
427                         DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
428                 } else {
429                         DEBUG(3, ("Could not find short name: %s\n",
430                                 wbcErrorString(wbc_status)));
431                 }
432         }
433
434         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
435
436         /* lookup the passwd struct, create a new user if necessary */
437
438         username_was_mapped = map_username( user );
439
440         pw = smb_getpwnam( mem_ctx, user, real_username, True );
441
442         if (pw) {
443                 /* if a real user check pam account restrictions */
444                 /* only really perfomed if "obey pam restriction" is true */
445                 /* do this before an eventual mappign to guest occurs */
446                 ret = smb_pam_accountcheck(pw->pw_name);
447                 if (  !NT_STATUS_IS_OK(ret)) {
448                         DEBUG(1,("PAM account restriction "
449                                 "prevents user login\n"));
450                         data_blob_free(&ap_rep);
451                         data_blob_free(&session_key);
452                         TALLOC_FREE(mem_ctx);
453                         reply_nterror(req, nt_status_squash(ret));
454                         return;
455                 }
456         }
457
458         if (!pw) {
459
460                 /* this was originally the behavior of Samba 2.2, if a user
461                    did not have a local uid but has been authenticated, then
462                    map them to a guest account */
463
464                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
465                         map_domainuser_to_guest = True;
466                         fstrcpy(user,lp_guestaccount());
467                         pw = smb_getpwnam( mem_ctx, user, real_username, True );
468                 }
469
470                 /* extra sanity check that the guest account is valid */
471
472                 if ( !pw ) {
473                         DEBUG(1,("Username %s is invalid on this system\n",
474                                 user));
475                         SAFE_FREE(client);
476                         data_blob_free(&ap_rep);
477                         data_blob_free(&session_key);
478                         TALLOC_FREE(mem_ctx);
479                         reply_nterror(req, nt_status_squash(
480                                               NT_STATUS_LOGON_FAILURE));
481                         return;
482                 }
483         }
484
485         /* setup the string used by %U */
486
487         sub_set_smb_name( real_username );
488         reload_services(True);
489
490         if ( map_domainuser_to_guest ) {
491                 make_server_info_guest(&server_info);
492         } else if (logon_info) {
493                 /* pass the unmapped username here since map_username()
494                    will be called again from inside make_server_info_info3() */
495
496                 ret = make_server_info_info3(mem_ctx, client, domain,
497                                              &server_info, &logon_info->info3);
498                 if ( !NT_STATUS_IS_OK(ret) ) {
499                         DEBUG(1,("make_server_info_info3 failed: %s!\n",
500                                  nt_errstr(ret)));
501                         SAFE_FREE(client);
502                         data_blob_free(&ap_rep);
503                         data_blob_free(&session_key);
504                         TALLOC_FREE(mem_ctx);
505                         reply_nterror(req, nt_status_squash(ret));
506                         return;
507                 }
508
509         } else {
510                 ret = make_server_info_pw(&server_info, real_username, pw);
511
512                 if ( !NT_STATUS_IS_OK(ret) ) {
513                         DEBUG(1,("make_server_info_pw failed: %s!\n",
514                                  nt_errstr(ret)));
515                         SAFE_FREE(client);
516                         data_blob_free(&ap_rep);
517                         data_blob_free(&session_key);
518                         TALLOC_FREE(mem_ctx);
519                         reply_nterror(req, nt_status_squash(ret));
520                         return;
521                 }
522
523                 /* make_server_info_pw does not set the domain. Without this
524                  * we end up with the local netbios name in substitutions for
525                  * %D. */
526
527                 if (server_info->sam_account != NULL) {
528                         pdb_set_domain(server_info->sam_account,
529                                         domain, PDB_SET);
530                 }
531         }
532
533         if (username_was_mapped) {
534                 server_info->was_mapped = username_was_mapped;
535         }
536
537         /* we need to build the token for the user. make_server_info_guest()
538            already does this */
539
540         if ( !server_info->ptok ) {
541                 ret = create_local_token( server_info );
542                 if ( !NT_STATUS_IS_OK(ret) ) {
543                         DEBUG(10,("failed to create local token: %s\n",
544                                 nt_errstr(ret)));
545                         SAFE_FREE(client);
546                         data_blob_free(&ap_rep);
547                         data_blob_free(&session_key);
548                         TALLOC_FREE( mem_ctx );
549                         TALLOC_FREE( server_info );
550                         reply_nterror(req, nt_status_squash(ret));
551                         return;
552                 }
553         }
554
555         /* register_existing_vuid keeps the server info */
556         /* register_existing_vuid takes ownership of session_key on success,
557          * no need to free after this on success. A better interface would copy
558          * it.... */
559
560         if (!is_partial_auth_vuid(sess_vuid)) {
561                 sess_vuid = register_initial_vuid();
562         }
563         sess_vuid = register_existing_vuid(sess_vuid,
564                                         server_info,
565                                         session_key,
566                                         nullblob,
567                                         client);
568
569         SAFE_FREE(client);
570
571         reply_outbuf(req, 4, 0);
572         SSVAL(req->outbuf,smb_uid,sess_vuid);
573
574         if (sess_vuid == UID_FIELD_INVALID ) {
575                 ret = NT_STATUS_LOGON_FAILURE;
576                 data_blob_free(&session_key);
577         } else {
578                 /* current_user_info is changed on new vuid */
579                 reload_services( True );
580
581                 SSVAL(req->outbuf, smb_vwv3, 0);
582
583                 if (server_info->guest) {
584                         SSVAL(req->outbuf,smb_vwv2,1);
585                 }
586
587                 SSVAL(req->outbuf, smb_uid, sess_vuid);
588
589                 sessionsetup_start_signing_engine(server_info, req->inbuf);
590                 /* Successful logon. Keep this vuid. */
591                 *p_invalidate_vuid = False;
592         }
593
594         /* wrap that up in a nice GSS-API wrapping */
595         if (NT_STATUS_IS_OK(ret)) {
596                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
597                                 TOK_ID_KRB_AP_REP);
598         } else {
599                 ap_rep_wrapped = data_blob_null;
600         }
601         response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
602                         mechOID);
603         reply_sesssetup_blob(req, response, ret);
604
605         data_blob_free(&ap_rep);
606         data_blob_free(&ap_rep_wrapped);
607         data_blob_free(&response);
608         TALLOC_FREE(mem_ctx);
609 }
610
611 #endif
612
613 /****************************************************************************
614  Send a session setup reply, wrapped in SPNEGO.
615  Get vuid and check first.
616  End the NTLMSSP exchange context if we are OK/complete fail
617  This should be split into two functions, one to handle each
618  leg of the NTLM auth steps.
619 ***************************************************************************/
620
621 static void reply_spnego_ntlmssp(struct smb_request *req,
622                                  uint16 vuid,
623                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
624                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
625                                  const char *OID,
626                                  bool wrap)
627 {
628         DATA_BLOB response;
629         struct auth_serversupplied_info *server_info = NULL;
630
631         if (NT_STATUS_IS_OK(nt_status)) {
632                 server_info = (*auth_ntlmssp_state)->server_info;
633         } else {
634                 nt_status = do_map_to_guest(nt_status,
635                             &server_info,
636                             (*auth_ntlmssp_state)->ntlmssp_state->user,
637                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
638         }
639
640         reply_outbuf(req, 4, 0);
641
642         SSVAL(req->outbuf, smb_uid, vuid);
643
644         if (NT_STATUS_IS_OK(nt_status)) {
645                 DATA_BLOB nullblob = data_blob_null;
646                 DATA_BLOB session_key =
647                         data_blob(
648                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
649                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
650
651                 if (!is_partial_auth_vuid(vuid)) {
652                         data_blob_free(&session_key);
653                         nt_status = NT_STATUS_LOGON_FAILURE;
654                         goto out;
655                 }
656                 /* register_existing_vuid keeps the server info */
657                 if (register_existing_vuid(vuid,
658                                 server_info,
659                                 session_key, nullblob,
660                                 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
661                                         vuid) {
662                         data_blob_free(&session_key);
663                         nt_status = NT_STATUS_LOGON_FAILURE;
664                         goto out;
665                 }
666
667                 (*auth_ntlmssp_state)->server_info = NULL;
668
669                 /* current_user_info is changed on new vuid */
670                 reload_services( True );
671
672                 SSVAL(req->outbuf, smb_vwv3, 0);
673
674                 if (server_info->guest) {
675                         SSVAL(req->outbuf,smb_vwv2,1);
676                 }
677
678                 sessionsetup_start_signing_engine(server_info,
679                                                   (uint8 *)req->inbuf);
680         }
681
682   out:
683
684         if (wrap) {
685                 response = spnego_gen_auth_response(ntlmssp_blob,
686                                 nt_status, OID);
687         } else {
688                 response = *ntlmssp_blob;
689         }
690
691         reply_sesssetup_blob(req, response, nt_status);
692         if (wrap) {
693                 data_blob_free(&response);
694         }
695
696         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
697            and the other end, that we are not finished yet. */
698
699         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
700                 /* NB. This is *NOT* an error case. JRA */
701                 auth_ntlmssp_end(auth_ntlmssp_state);
702                 if (!NT_STATUS_IS_OK(nt_status)) {
703                         /* Kill the intermediate vuid */
704                         invalidate_vuid(vuid);
705                 }
706         }
707 }
708
709 /****************************************************************************
710  Is this a krb5 mechanism ?
711 ****************************************************************************/
712
713 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
714                 DATA_BLOB *pblob_out,
715                 char **kerb_mechOID)
716 {
717         char *OIDs[ASN1_MAX_OIDS];
718         int i;
719         NTSTATUS ret = NT_STATUS_OK;
720
721         *kerb_mechOID = NULL;
722
723         /* parse out the OIDs and the first sec blob */
724         if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
725                 return NT_STATUS_LOGON_FAILURE;
726         }
727
728         /* only look at the first OID for determining the mechToken --
729            according to RFC2478, we should choose the one we want
730            and renegotiate, but i smell a client bug here..
731
732            Problem observed when connecting to a member (samba box)
733            of an AD domain as a user in a Samba domain.  Samba member
734            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
735            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
736            NTLMSSP mechtoken.                 --jerry              */
737
738 #ifdef HAVE_KRB5
739         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
740             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
741                 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
742                 if (*kerb_mechOID == NULL) {
743                         ret = NT_STATUS_NO_MEMORY;
744                 }
745         }
746 #endif
747
748         for (i=0;OIDs[i];i++) {
749                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
750                 free(OIDs[i]);
751         }
752         return ret;
753 }
754
755 /****************************************************************************
756  Fall back from krb5 to NTLMSSP.
757 ****************************************************************************/
758
759 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
760                                                 uint16 vuid)
761 {
762         DATA_BLOB response;
763
764         reply_outbuf(req, 4, 0);
765         SSVAL(req->outbuf,smb_uid,vuid);
766
767         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
768                 "but set to downgrade to NTLMSSP\n"));
769
770         response = spnego_gen_auth_response(NULL,
771                         NT_STATUS_MORE_PROCESSING_REQUIRED,
772                         OID_NTLMSSP);
773         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
774         data_blob_free(&response);
775 }
776
777 /****************************************************************************
778  Reply to a session setup spnego negotiate packet.
779 ****************************************************************************/
780
781 static void reply_spnego_negotiate(struct smb_request *req,
782                                    uint16 vuid,
783                                    DATA_BLOB blob1,
784                                    AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
785 {
786         DATA_BLOB secblob;
787         DATA_BLOB chal;
788         char *kerb_mech = NULL;
789         NTSTATUS status;
790
791         status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
792         if (!NT_STATUS_IS_OK(status)) {
793                 /* Kill the intermediate vuid */
794                 invalidate_vuid(vuid);
795                 reply_nterror(req, nt_status_squash(status));
796                 return;
797         }
798
799         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
800                                 (unsigned long)secblob.length));
801
802 #ifdef HAVE_KRB5
803         if (kerb_mech && ((lp_security()==SEC_ADS) ||
804                                 lp_use_kerberos_keytab()) ) {
805                 bool destroy_vuid = True;
806                 reply_spnego_kerberos(req, &secblob, kerb_mech,
807                                       vuid, &destroy_vuid);
808                 data_blob_free(&secblob);
809                 if (destroy_vuid) {
810                         /* Kill the intermediate vuid */
811                         invalidate_vuid(vuid);
812                 }
813                 SAFE_FREE(kerb_mech);
814                 return;
815         }
816 #endif
817
818         if (*auth_ntlmssp_state) {
819                 auth_ntlmssp_end(auth_ntlmssp_state);
820         }
821
822         if (kerb_mech) {
823                 data_blob_free(&secblob);
824                 /* The mechtoken is a krb5 ticket, but
825                  * we need to fall back to NTLM. */
826                 reply_spnego_downgrade_to_ntlmssp(req, vuid);
827                 SAFE_FREE(kerb_mech);
828                 return;
829         }
830
831         status = auth_ntlmssp_start(auth_ntlmssp_state);
832         if (!NT_STATUS_IS_OK(status)) {
833                 /* Kill the intermediate vuid */
834                 invalidate_vuid(vuid);
835                 reply_nterror(req, nt_status_squash(status));
836                 return;
837         }
838
839         status = auth_ntlmssp_update(*auth_ntlmssp_state,
840                                         secblob, &chal);
841
842         data_blob_free(&secblob);
843
844         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
845                              &chal, status, OID_NTLMSSP, true);
846
847         data_blob_free(&chal);
848
849         /* already replied */
850         return;
851 }
852
853 /****************************************************************************
854  Reply to a session setup spnego auth packet.
855 ****************************************************************************/
856
857 static void reply_spnego_auth(struct smb_request *req,
858                               uint16 vuid,
859                               DATA_BLOB blob1,
860                               AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
861 {
862         DATA_BLOB auth = data_blob_null;
863         DATA_BLOB auth_reply = data_blob_null;
864         DATA_BLOB secblob = data_blob_null;
865         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
866
867         if (!spnego_parse_auth(blob1, &auth)) {
868 #if 0
869                 file_save("auth.dat", blob1.data, blob1.length);
870 #endif
871                 /* Kill the intermediate vuid */
872                 invalidate_vuid(vuid);
873
874                 reply_nterror(req, nt_status_squash(
875                                       NT_STATUS_LOGON_FAILURE));
876                 return;
877         }
878
879         if (auth.data[0] == ASN1_APPLICATION(0)) {
880                 /* Might be a second negTokenTarg packet */
881                 char *kerb_mech = NULL;
882
883                 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
884
885                 if (!NT_STATUS_IS_OK(status)) {
886                         /* Kill the intermediate vuid */
887                         invalidate_vuid(vuid);
888                         reply_nterror(req, nt_status_squash(status));
889                         return;
890                 }
891
892                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
893                                 (unsigned long)secblob.length));
894 #ifdef HAVE_KRB5
895                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
896                                         lp_use_kerberos_keytab()) ) {
897                         bool destroy_vuid = True;
898                         reply_spnego_kerberos(req, &secblob, kerb_mech,
899                                               vuid, &destroy_vuid);
900                         data_blob_free(&secblob);
901                         data_blob_free(&auth);
902                         if (destroy_vuid) {
903                                 /* Kill the intermediate vuid */
904                                 invalidate_vuid(vuid);
905                         }
906                         SAFE_FREE(kerb_mech);
907                         return;
908                 }
909 #endif
910                 /* Can't blunder into NTLMSSP auth if we have
911                  * a krb5 ticket. */
912
913                 if (kerb_mech) {
914                         /* Kill the intermediate vuid */
915                         invalidate_vuid(vuid);
916                         DEBUG(3,("reply_spnego_auth: network "
917                                 "misconfiguration, client sent us a "
918                                 "krb5 ticket and kerberos security "
919                                 "not enabled"));
920                         reply_nterror(req, nt_status_squash(
921                                         NT_STATUS_LOGON_FAILURE));
922                         SAFE_FREE(kerb_mech);
923                 }
924         }
925
926         /* If we get here it wasn't a negTokenTarg auth packet. */
927         data_blob_free(&secblob);
928
929         if (!*auth_ntlmssp_state) {
930                 status = auth_ntlmssp_start(auth_ntlmssp_state);
931                 if (!NT_STATUS_IS_OK(status)) {
932                         /* Kill the intermediate vuid */
933                         invalidate_vuid(vuid);
934                         reply_nterror(req, nt_status_squash(status));
935                         return;
936                 }
937         }
938
939         status = auth_ntlmssp_update(*auth_ntlmssp_state,
940                                         auth, &auth_reply);
941
942         data_blob_free(&auth);
943
944         /* Don't send the mechid as we've already sent this (RFC4178). */
945
946         reply_spnego_ntlmssp(req, vuid,
947                              auth_ntlmssp_state,
948                              &auth_reply, status, NULL, true);
949
950         data_blob_free(&auth_reply);
951
952         /* and tell smbd that we have already replied to this packet */
953         return;
954 }
955
956 /****************************************************************************
957  List to store partial SPNEGO auth fragments.
958 ****************************************************************************/
959
960 static struct pending_auth_data *pd_list;
961
962 /****************************************************************************
963  Delete an entry on the list.
964 ****************************************************************************/
965
966 static void delete_partial_auth(struct pending_auth_data *pad)
967 {
968         if (!pad) {
969                 return;
970         }
971         DLIST_REMOVE(pd_list, pad);
972         data_blob_free(&pad->partial_data);
973         SAFE_FREE(pad);
974 }
975
976 /****************************************************************************
977  Search for a partial SPNEGO auth fragment matching an smbpid.
978 ****************************************************************************/
979
980 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
981 {
982         struct pending_auth_data *pad;
983
984         for (pad = pd_list; pad; pad = pad->next) {
985                 if (pad->smbpid == smbpid) {
986                         break;
987                 }
988         }
989         return pad;
990 }
991
992 /****************************************************************************
993  Check the size of an SPNEGO blob. If we need more return
994  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
995  the blob to be more than 64k.
996 ****************************************************************************/
997
998 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
999                 DATA_BLOB *pblob)
1000 {
1001         struct pending_auth_data *pad = NULL;
1002         ASN1_DATA data;
1003         size_t needed_len = 0;
1004
1005         pad = get_pending_auth_data(smbpid);
1006
1007         /* Ensure we have some data. */
1008         if (pblob->length == 0) {
1009                 /* Caller can cope. */
1010                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1011                 delete_partial_auth(pad);
1012                 return NT_STATUS_OK;
1013         }
1014
1015         /* Were we waiting for more data ? */
1016         if (pad) {
1017                 DATA_BLOB tmp_blob;
1018                 size_t copy_len = MIN(65536, pblob->length);
1019
1020                 /* Integer wrap paranoia.... */
1021
1022                 if (pad->partial_data.length + copy_len <
1023                                 pad->partial_data.length ||
1024                     pad->partial_data.length + copy_len < copy_len) {
1025
1026                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
1027                                 "pad->partial_data.length = %u, "
1028                                 "copy_len = %u\n",
1029                                 (unsigned int)pad->partial_data.length,
1030                                 (unsigned int)copy_len ));
1031
1032                         delete_partial_auth(pad);
1033                         return NT_STATUS_INVALID_PARAMETER;
1034                 }
1035
1036                 DEBUG(10,("check_spnego_blob_complete: "
1037                         "pad->partial_data.length = %u, "
1038                         "pad->needed_len = %u, "
1039                         "copy_len = %u, "
1040                         "pblob->length = %u,\n",
1041                         (unsigned int)pad->partial_data.length,
1042                         (unsigned int)pad->needed_len,
1043                         (unsigned int)copy_len,
1044                         (unsigned int)pblob->length ));
1045
1046                 tmp_blob = data_blob(NULL,
1047                                 pad->partial_data.length + copy_len);
1048
1049                 /* Concatenate the two (up to copy_len) bytes. */
1050                 memcpy(tmp_blob.data,
1051                         pad->partial_data.data,
1052                         pad->partial_data.length);
1053                 memcpy(tmp_blob.data + pad->partial_data.length,
1054                         pblob->data,
1055                         copy_len);
1056
1057                 /* Replace the partial data. */
1058                 data_blob_free(&pad->partial_data);
1059                 pad->partial_data = tmp_blob;
1060                 ZERO_STRUCT(tmp_blob);
1061
1062                 /* Are we done ? */
1063                 if (pblob->length >= pad->needed_len) {
1064                         /* Yes, replace pblob. */
1065                         data_blob_free(pblob);
1066                         *pblob = pad->partial_data;
1067                         ZERO_STRUCT(pad->partial_data);
1068                         delete_partial_auth(pad);
1069                         return NT_STATUS_OK;
1070                 }
1071
1072                 /* Still need more data. */
1073                 pad->needed_len -= copy_len;
1074                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1075         }
1076
1077         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1078             (pblob->data[0] != ASN1_CONTEXT(1))) {
1079                 /* Not something we can determine the
1080                  * length of.
1081                  */
1082                 return NT_STATUS_OK;
1083         }
1084
1085         /* This is a new SPNEGO sessionsetup - see if
1086          * the data given in this blob is enough.
1087          */
1088
1089         asn1_load(&data, *pblob);
1090         asn1_start_tag(&data, pblob->data[0]);
1091         if (data.has_error || data.nesting == NULL) {
1092                 asn1_free(&data);
1093                 /* Let caller catch. */
1094                 return NT_STATUS_OK;
1095         }
1096
1097         /* Integer wrap paranoia.... */
1098
1099         if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1100             data.nesting->taglen + data.nesting->start < data.nesting->start) {
1101
1102                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1103                         "data.nesting->taglen = %u, "
1104                         "data.nesting->start = %u\n",
1105                         (unsigned int)data.nesting->taglen,
1106                         (unsigned int)data.nesting->start ));
1107
1108                 asn1_free(&data);
1109                 return NT_STATUS_INVALID_PARAMETER;
1110         }
1111
1112         /* Total length of the needed asn1 is the tag length
1113          * plus the current offset. */
1114
1115         needed_len = data.nesting->taglen + data.nesting->start;
1116         asn1_free(&data);
1117
1118         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1119                 "pblob->length = %u\n",
1120                 (unsigned int)needed_len,
1121                 (unsigned int)pblob->length ));
1122
1123         if (needed_len <= pblob->length) {
1124                 /* Nothing to do - blob is complete. */
1125                 return NT_STATUS_OK;
1126         }
1127
1128         /* Refuse the blob if it's bigger than 64k. */
1129         if (needed_len > 65536) {
1130                 DEBUG(2,("check_spnego_blob_complete: needed_len "
1131                         "too large (%u)\n",
1132                         (unsigned int)needed_len ));
1133                 return NT_STATUS_INVALID_PARAMETER;
1134         }
1135
1136         /* We must store this blob until complete. */
1137         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1138                 return NT_STATUS_NO_MEMORY;
1139         }
1140         pad->needed_len = needed_len - pblob->length;
1141         pad->partial_data = data_blob(pblob->data, pblob->length);
1142         if (pad->partial_data.data == NULL) {
1143                 SAFE_FREE(pad);
1144                 return NT_STATUS_NO_MEMORY;
1145         }
1146         pad->smbpid = smbpid;
1147         pad->vuid = vuid;
1148         DLIST_ADD(pd_list, pad);
1149
1150         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1151 }
1152
1153 /****************************************************************************
1154  Reply to a session setup command.
1155  conn POINTER CAN BE NULL HERE !
1156 ****************************************************************************/
1157
1158 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1159 {
1160         uint8 *p;
1161         DATA_BLOB blob1;
1162         size_t bufrem;
1163         fstring native_os, native_lanman, primary_domain;
1164         const char *p2;
1165         uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1166         enum remote_arch_types ra_type = get_remote_arch();
1167         int vuid = SVAL(req->inbuf,smb_uid);
1168         user_struct *vuser = NULL;
1169         NTSTATUS status = NT_STATUS_OK;
1170         uint16 smbpid = req->smbpid;
1171         uint16 smb_flag2 = req->flags2;
1172
1173         DEBUG(3,("Doing spnego session setup\n"));
1174
1175         if (global_client_caps == 0) {
1176                 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1177
1178                 if (!(global_client_caps & CAP_STATUS32)) {
1179                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1180                 }
1181
1182         }
1183
1184         p = (uint8 *)smb_buf(req->inbuf);
1185
1186         if (data_blob_len == 0) {
1187                 /* an invalid request */
1188                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1189                 return;
1190         }
1191
1192         bufrem = smb_bufrem(req->inbuf, p);
1193         /* pull the spnego blob */
1194         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1195
1196 #if 0
1197         file_save("negotiate.dat", blob1.data, blob1.length);
1198 #endif
1199
1200         p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1201         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1202                               sizeof(native_os), STR_TERMINATE);
1203         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1204                               sizeof(native_lanman), STR_TERMINATE);
1205         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1206                               sizeof(primary_domain), STR_TERMINATE);
1207         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1208                 native_os, native_lanman, primary_domain));
1209
1210         if ( ra_type == RA_WIN2K ) {
1211                 /* Vista sets neither the OS or lanman strings */
1212
1213                 if ( !strlen(native_os) && !strlen(native_lanman) )
1214                         set_remote_arch(RA_VISTA);
1215
1216                 /* Windows 2003 doesn't set the native lanman string,
1217                    but does set primary domain which is a bug I think */
1218
1219                 if ( !strlen(native_lanman) ) {
1220                         ra_lanman_string( primary_domain );
1221                 } else {
1222                         ra_lanman_string( native_lanman );
1223                 }
1224         }
1225
1226         /* Did we get a valid vuid ? */
1227         if (!is_partial_auth_vuid(vuid)) {
1228                 /* No, then try and see if this is an intermediate sessionsetup
1229                  * for a large SPNEGO packet. */
1230                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1231                 if (pad) {
1232                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1233                                 "pending vuid %u\n",
1234                                 (unsigned int)pad->vuid ));
1235                         vuid = pad->vuid;
1236                 }
1237         }
1238
1239         /* Do we have a valid vuid now ? */
1240         if (!is_partial_auth_vuid(vuid)) {
1241                 /* No, start a new authentication setup. */
1242                 vuid = register_initial_vuid();
1243                 if (vuid == UID_FIELD_INVALID) {
1244                         data_blob_free(&blob1);
1245                         reply_nterror(req, nt_status_squash(
1246                                               NT_STATUS_INVALID_PARAMETER));
1247                         return;
1248                 }
1249         }
1250
1251         vuser = get_partial_auth_user_struct(vuid);
1252         /* This MUST be valid. */
1253         if (!vuser) {
1254                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1255         }
1256
1257         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1258          * sessionsetup requests as the Windows limit on the security blob
1259          * field is 4k. Bug #4400. JRA.
1260          */
1261
1262         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1263         if (!NT_STATUS_IS_OK(status)) {
1264                 if (!NT_STATUS_EQUAL(status,
1265                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1266                         /* Real error - kill the intermediate vuid */
1267                         invalidate_vuid(vuid);
1268                 }
1269                 data_blob_free(&blob1);
1270                 reply_nterror(req, nt_status_squash(status));
1271                 return;
1272         }
1273
1274         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1275
1276                 /* its a negTokenTarg packet */
1277
1278                 reply_spnego_negotiate(req, vuid, blob1,
1279                                        &vuser->auth_ntlmssp_state);
1280                 data_blob_free(&blob1);
1281                 return;
1282         }
1283
1284         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1285
1286                 /* its a auth packet */
1287
1288                 reply_spnego_auth(req, vuid, blob1,
1289                                   &vuser->auth_ntlmssp_state);
1290                 data_blob_free(&blob1);
1291                 return;
1292         }
1293
1294         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1295                 DATA_BLOB chal;
1296
1297                 if (!vuser->auth_ntlmssp_state) {
1298                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1299                         if (!NT_STATUS_IS_OK(status)) {
1300                                 /* Kill the intermediate vuid */
1301                                 invalidate_vuid(vuid);
1302                                 data_blob_free(&blob1);
1303                                 reply_nterror(req, nt_status_squash(status));
1304                                 return;
1305                         }
1306                 }
1307
1308                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1309                                                 blob1, &chal);
1310
1311                 data_blob_free(&blob1);
1312
1313                 reply_spnego_ntlmssp(req, vuid,
1314                                      &vuser->auth_ntlmssp_state,
1315                                      &chal, status, OID_NTLMSSP, false);
1316                 data_blob_free(&chal);
1317                 return;
1318         }
1319
1320         /* what sort of packet is this? */
1321         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1322
1323         data_blob_free(&blob1);
1324
1325         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1326 }
1327
1328 /****************************************************************************
1329  On new VC == 0, shutdown *all* old connections and users.
1330  It seems that only NT4.x does this. At W2K and above (XP etc.).
1331  a new session setup with VC==0 is ignored.
1332 ****************************************************************************/
1333
1334 static int shutdown_other_smbds(struct db_record *rec,
1335                                 const struct connections_key *key,
1336                                 const struct connections_data *crec,
1337                                 void *private_data)
1338 {
1339         const char *ip = (const char *)private_data;
1340
1341         if (!process_exists(crec->pid)) {
1342                 return 0;
1343         }
1344
1345         if (procid_is_me(&crec->pid)) {
1346                 return 0;
1347         }
1348
1349         if (strcmp(ip, crec->addr) != 0) {
1350                 return 0;
1351         }
1352
1353         messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1354                        &data_blob_null);
1355         return 0;
1356 }
1357
1358 static void setup_new_vc_session(void)
1359 {
1360         char addr[INET6_ADDRSTRLEN];
1361
1362         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1363                 "compatible we would close all old resources.\n"));
1364 #if 0
1365         conn_close_all();
1366         invalidate_all_vuids();
1367 #endif
1368         if (lp_reset_on_zero_vc()) {
1369                 connections_forall(shutdown_other_smbds,
1370                         CONST_DISCARD(void *,
1371                         client_addr(get_client_fd(),addr,sizeof(addr))));
1372         }
1373 }
1374
1375 /****************************************************************************
1376  Reply to a session setup command.
1377 ****************************************************************************/
1378
1379 void reply_sesssetup_and_X(struct smb_request *req)
1380 {
1381         int sess_vuid;
1382         int smb_bufsize;
1383         DATA_BLOB lm_resp;
1384         DATA_BLOB nt_resp;
1385         DATA_BLOB plaintext_password;
1386         fstring user;
1387         fstring sub_user; /* Sainitised username for substituion */
1388         fstring domain;
1389         fstring native_os;
1390         fstring native_lanman;
1391         fstring primary_domain;
1392         static bool done_sesssetup = False;
1393         auth_usersupplied_info *user_info = NULL;
1394         auth_serversupplied_info *server_info = NULL;
1395         uint16 smb_flag2 = req->flags2;
1396
1397         NTSTATUS nt_status;
1398
1399         bool doencrypt = global_encrypted_passwords_negotiated;
1400
1401         DATA_BLOB session_key;
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         nt_status = create_local_token(server_info);
1739         if (!NT_STATUS_IS_OK(nt_status)) {
1740                 DEBUG(10, ("create_local_token failed: %s\n",
1741                            nt_errstr(nt_status)));
1742                 data_blob_free(&nt_resp);
1743                 data_blob_free(&lm_resp);
1744                 data_blob_clear_free(&plaintext_password);
1745                 reply_nterror(req, nt_status_squash(nt_status));
1746                 END_PROFILE(SMBsesssetupX);
1747                 return;
1748         }
1749
1750         if (server_info->user_session_key.data) {
1751                 session_key = data_blob(server_info->user_session_key.data,
1752                                 server_info->user_session_key.length);
1753         } else {
1754                 session_key = data_blob_null;
1755         }
1756
1757         data_blob_clear_free(&plaintext_password);
1758
1759         /* it's ok - setup a reply */
1760         reply_outbuf(req, 3, 0);
1761         if (Protocol >= PROTOCOL_NT1) {
1762                 push_signature(&req->outbuf);
1763                 /* perhaps grab OS version here?? */
1764         }
1765
1766         if (server_info->guest) {
1767                 SSVAL(req->outbuf,smb_vwv2,1);
1768         }
1769
1770         /* register the name and uid as being validated, so further connections
1771            to a uid can get through without a password, on the same VC */
1772
1773         if (lp_security() == SEC_SHARE) {
1774                 sess_vuid = UID_FIELD_INVALID;
1775                 data_blob_free(&session_key);
1776                 TALLOC_FREE(server_info);
1777         } else {
1778                 /* Ignore the initial vuid. */
1779                 sess_vuid = register_initial_vuid();
1780                 if (sess_vuid == UID_FIELD_INVALID) {
1781                         data_blob_free(&nt_resp);
1782                         data_blob_free(&lm_resp);
1783                         data_blob_free(&session_key);
1784                         reply_nterror(req, nt_status_squash(
1785                                               NT_STATUS_LOGON_FAILURE));
1786                         END_PROFILE(SMBsesssetupX);
1787                         return;
1788                 }
1789                 /* register_existing_vuid keeps the server info */
1790                 sess_vuid = register_existing_vuid(sess_vuid,
1791                                         server_info,
1792                                         session_key,
1793                                         nt_resp.data ? nt_resp : lm_resp,
1794                                         sub_user);
1795                 if (sess_vuid == UID_FIELD_INVALID) {
1796                         data_blob_free(&nt_resp);
1797                         data_blob_free(&lm_resp);
1798                         data_blob_free(&session_key);
1799                         reply_nterror(req, nt_status_squash(
1800                                               NT_STATUS_LOGON_FAILURE));
1801                         END_PROFILE(SMBsesssetupX);
1802                         return;
1803                 }
1804
1805                 /* current_user_info is changed on new vuid */
1806                 reload_services( True );
1807
1808                 sessionsetup_start_signing_engine(server_info, req->inbuf);
1809         }
1810
1811         data_blob_free(&nt_resp);
1812         data_blob_free(&lm_resp);
1813
1814         SSVAL(req->outbuf,smb_uid,sess_vuid);
1815         SSVAL(req->inbuf,smb_uid,sess_vuid);
1816
1817         if (!done_sesssetup)
1818                 max_send = MIN(max_send,smb_bufsize);
1819
1820         done_sesssetup = True;
1821
1822         END_PROFILE(SMBsesssetupX);
1823         chain_reply(req);
1824         return;
1825 }