s3: smbd: Add "enum file_close_type close_type" parameter to close_cnum().
[samba.git] / source3 / smbd / smb2_service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
4    Copyright (C) Andrew Tridgell 1992-1998
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "system/passwd.h" /* uid_wrapper */
23 #include "../lib/tsocket/tsocket.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../librpc/gen_ndr/netlogon.h"
27 #include "../libcli/security/security.h"
28 #include "printing/pcap.h"
29 #include "passdb/lookup_sid.h"
30 #include "auth.h"
31 #include "../auth/auth_util.h"
32 #include "lib/param/loadparm.h"
33 #include "messages.h"
34 #include "lib/afs/afs_funcs.h"
35 #include "lib/util_path.h"
36 #include "lib/util/string_wrappers.h"
37 #include "source3/lib/substitute.h"
38
39 bool canonicalize_connect_path(connection_struct *conn)
40 {
41         bool ret;
42         struct smb_filename con_fname = { .base_name = conn->connectpath };
43         struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
44                                                 &con_fname);
45         if (resolved_fname == NULL) {
46                 return false;
47         }
48         ret = set_conn_connectpath(conn,resolved_fname->base_name);
49         TALLOC_FREE(resolved_fname);
50         return ret;
51 }
52
53 /****************************************************************************
54  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
55  absolute path stating in / and not ending in /.
56 ****************************************************************************/
57
58 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
59 {
60         char *destname;
61
62         if (connectpath == NULL || connectpath[0] == '\0') {
63                 return false;
64         }
65
66         destname = canonicalize_absolute_path(conn, connectpath);
67         if (destname == NULL) {
68                 return false;
69         }
70
71         DBG_DEBUG("service %s, connectpath = %s\n",
72                   lp_const_servicename(SNUM(conn)), destname);
73
74         talloc_free(conn->connectpath);
75         conn->connectpath = destname;
76         /*
77          * Ensure conn->cwd_fsp->fsp_name is initialized.
78          * start as conn->connectpath.
79          */
80         TALLOC_FREE(conn->cwd_fsp->fsp_name);
81         conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
82                                 conn->connectpath,
83                                 NULL,
84                                 NULL,
85                                 0,
86                                 0);
87         if (conn->cwd_fsp->fsp_name == NULL) {
88                 return false;
89         }
90         return true;
91 }
92
93 /****************************************************************************
94  Load parameters specific to a connection/service.
95 ****************************************************************************/
96
97 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
98 {
99         int snum;
100         enum remote_arch_types ra_type;
101
102         SMB_ASSERT(conn != NULL);
103
104         snum = SNUM(conn);
105
106         if ((conn == last_conn) && (last_flags == flags)) {
107                 return;
108         }
109
110         last_conn = conn;
111         last_flags = flags;
112
113         /*
114          * Obey the client case sensitivity requests - only for clients that
115          * support it. */
116         switch (lp_case_sensitive(snum)) {
117         case Auto:
118                 /*
119                  * We need this uglyness due to DOS/Win9x clients that lie
120                  * about case insensitivity. */
121                 ra_type = get_remote_arch();
122                 if (conn->sconn->using_smb2) {
123                         conn->case_sensitive = false;
124                 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
125                         /*
126                          * Client can't support per-packet case sensitive
127                          * pathnames. */
128                         conn->case_sensitive = false;
129                 } else {
130                         conn->case_sensitive =
131                                         !(flags & FLAG_CASELESS_PATHNAMES);
132                 }
133         break;
134         case True:
135                 conn->case_sensitive = true;
136                 break;
137         default:
138                 conn->case_sensitive = false;
139                 break;
140         }
141         return;
142 }
143
144 bool chdir_current_service(connection_struct *conn)
145 {
146         const struct smb_filename connectpath_fname = {
147                 .base_name = conn->connectpath,
148         };
149         int saved_errno = 0;
150         char *utok_str = NULL;
151         int ret;
152
153         conn->lastused_count++;
154
155         ret = vfs_ChDir(conn, &connectpath_fname);
156         if (ret == 0) {
157                 return true;
158         }
159         saved_errno = errno;
160
161         utok_str = utok_string(talloc_tos(),
162                                conn->session_info->unix_token);
163         if (utok_str == NULL) {
164                 errno = saved_errno;
165                 return false;
166         }
167
168         DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
169                 conn->connectpath,
170                 strerror(saved_errno),
171                 utok_str);
172
173         if (saved_errno != 0) {
174                 errno = saved_errno;
175         }
176         return false;
177 }
178
179 /****************************************************************************
180  do some basic sainity checks on the share.  
181  This function modifies dev, ecode.
182 ****************************************************************************/
183
184 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
185                                     const char *rhost,
186                                     int snum,
187                                     fstring dev)
188 {
189         char *raddr;
190
191         raddr = tsocket_address_inet_addr_string(remote_address,
192                                                  talloc_tos());
193         if (raddr == NULL) {
194                 return NT_STATUS_NO_MEMORY;
195         }
196
197         if (!lp_snum_ok(snum) ||
198             !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
199                           rhost, raddr)) {
200                 return NT_STATUS_ACCESS_DENIED;
201         }
202
203         if (dev[0] == '?' || !dev[0]) {
204                 if (lp_printable(snum)) {
205                         fstrcpy(dev,"LPT1:");
206                 } else if (strequal(lp_fstype(snum), "IPC")) {
207                         fstrcpy(dev, "IPC");
208                 } else {
209                         fstrcpy(dev,"A:");
210                 }
211         }
212
213         if (!strupper_m(dev)) {
214                 DEBUG(2,("strupper_m %s failed\n", dev));
215                 return NT_STATUS_INVALID_PARAMETER;
216         }
217
218         if (lp_printable(snum)) {
219                 if (!strequal(dev, "LPT1:")) {
220                         return NT_STATUS_BAD_DEVICE_TYPE;
221                 }
222         } else if (strequal(lp_fstype(snum), "IPC")) {
223                 if (!strequal(dev, "IPC")) {
224                         return NT_STATUS_BAD_DEVICE_TYPE;
225                 }
226         } else if (!strequal(dev, "A:")) {
227                 return NT_STATUS_BAD_DEVICE_TYPE;
228         }
229
230         /* Behave as a printer if we are supposed to */
231         if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
232                 fstrcpy(dev, "LPT1:");
233         }
234
235         return NT_STATUS_OK;
236 }
237
238 /*
239  * Go through lookup_name etc to find the force'd group.  
240  *
241  * Create a new token from src_token, replacing the primary group sid with the
242  * one found.
243  */
244
245 static NTSTATUS find_forced_group(bool force_user,
246                                   int snum, const char *username,
247                                   struct dom_sid *pgroup_sid,
248                                   gid_t *pgid)
249 {
250         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
251         TALLOC_CTX *frame = talloc_stackframe();
252         const struct loadparm_substitution *lp_sub =
253                 loadparm_s3_global_substitution();
254         struct dom_sid group_sid;
255         enum lsa_SidType type;
256         char *groupname;
257         bool user_must_be_member = False;
258         gid_t gid;
259
260         groupname = lp_force_group(talloc_tos(), lp_sub, snum);
261         if (groupname == NULL) {
262                 DEBUG(1, ("talloc_strdup failed\n"));
263                 result = NT_STATUS_NO_MEMORY;
264                 goto done;
265         }
266
267         if (groupname[0] == '+') {
268                 user_must_be_member = True;
269                 groupname += 1;
270         }
271
272         groupname = talloc_string_sub(talloc_tos(), groupname,
273                                       "%S", lp_const_servicename(snum));
274         if (groupname == NULL) {
275                 DEBUG(1, ("talloc_string_sub failed\n"));
276                 result = NT_STATUS_NO_MEMORY;
277                 goto done;
278         }
279
280         if (!lookup_name_smbconf(talloc_tos(), groupname,
281                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
282                          NULL, NULL, &group_sid, &type)) {
283                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
284                            groupname));
285                 goto done;
286         }
287
288         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
289             (type != SID_NAME_WKN_GRP)) {
290                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
291                            sid_type_lookup(type)));
292                 goto done;
293         }
294
295         if (!sid_to_gid(&group_sid, &gid)) {
296                 struct dom_sid_buf buf;
297                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
298                            dom_sid_str_buf(&group_sid, &buf), groupname));
299                 goto done;
300         }
301
302         /*
303          * If the user has been forced and the forced group starts with a '+',
304          * then we only set the group to be the forced group if the forced
305          * user is a member of that group.  Otherwise, the meaning of the '+'
306          * would be ignored.
307          */
308
309         if (force_user && user_must_be_member) {
310                 if (user_in_group_sid(username, &group_sid)) {
311                         sid_copy(pgroup_sid, &group_sid);
312                         *pgid = gid;
313                         DEBUG(3,("Forced group %s for member %s\n",
314                                  groupname, username));
315                 } else {
316                         DEBUG(0,("find_forced_group: forced user %s is not a member "
317                                 "of forced group %s. Disallowing access.\n",
318                                 username, groupname ));
319                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
320                         goto done;
321                 }
322         } else {
323                 sid_copy(pgroup_sid, &group_sid);
324                 *pgid = gid;
325                 DEBUG(3,("Forced group %s\n", groupname));
326         }
327
328         result = NT_STATUS_OK;
329  done:
330         TALLOC_FREE(frame);
331         return result;
332 }
333
334 /****************************************************************************
335   Create an auth_session_info structure for a connection_struct
336 ****************************************************************************/
337
338 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
339                                               TALLOC_CTX *mem_ctx, int snum,
340                                               struct auth_session_info *session_info,
341                                               struct auth_session_info **presult)
342 {
343         struct auth_session_info *result;
344
345         if (lp_guest_only(snum)) {
346                 return make_session_info_guest(mem_ctx, presult);
347         }
348
349         /*
350          * This is the normal security != share case where we have a
351          * valid vuid from the session setup.                 */
352
353         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
354                 if (!lp_guest_ok(snum)) {
355                         DBG_WARNING("guest user (from session setup) "
356                                   "not permitted to access this share "
357                                   "(%s)\n", lp_const_servicename(snum));
358                         return NT_STATUS_ACCESS_DENIED;
359                 }
360         } else {
361                 if (!user_ok_token(session_info->unix_info->unix_name,
362                                    session_info->info->domain_name,
363                                    session_info->security_token, snum)) {
364                         DBG_WARNING("user '%s' (from session setup) not "
365                                   "permitted to access this share "
366                                   "(%s)\n",
367                                   session_info->unix_info->unix_name,
368                                   lp_const_servicename(snum));
369                         return NT_STATUS_ACCESS_DENIED;
370                 }
371         }
372
373         result = copy_session_info(mem_ctx, session_info);
374         if (result == NULL) {
375                 return NT_STATUS_NO_MEMORY;
376         }
377
378         *presult = result;
379         return NT_STATUS_OK;
380 }
381
382 /****************************************************************************
383   Set relevant user and group settings corresponding to force user/group
384   configuration for the given snum.
385 ****************************************************************************/
386
387 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
388 {
389         const struct loadparm_substitution *lp_sub =
390                 loadparm_s3_global_substitution();
391         NTSTATUS status;
392
393         if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
394
395                 /*
396                  * Replace conn->session_info with a completely faked up one
397                  * from the username we are forced into :-)
398                  */
399
400                 char *fuser;
401                 char *sanitized_username;
402                 struct auth_session_info *forced_serverinfo;
403                 bool guest;
404
405                 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
406                                           lp_const_servicename(snum));
407                 if (fuser == NULL) {
408                         return NT_STATUS_NO_MEMORY;
409                 }
410
411                 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
412
413                 status = make_session_info_from_username(
414                         conn, fuser,
415                         guest,
416                         &forced_serverinfo);
417                 if (!NT_STATUS_IS_OK(status)) {
418                         return status;
419                 }
420
421                 /* We don't want to replace the original sanitized_username
422                    as it is the original user given in the connect attempt.
423                    This is used in '%U' substitutions. */
424                 sanitized_username = discard_const_p(char,
425                         forced_serverinfo->unix_info->sanitized_username);
426                 TALLOC_FREE(sanitized_username);
427                 forced_serverinfo->unix_info->sanitized_username =
428                         talloc_move(forced_serverinfo->unix_info,
429                                 &conn->session_info->unix_info->sanitized_username);
430
431                 TALLOC_FREE(conn->session_info);
432                 conn->session_info = forced_serverinfo;
433
434                 conn->force_user = true;
435                 DEBUG(3,("Forced user %s\n", fuser));
436         }
437
438         /*
439          * If force group is true, then override
440          * any groupid stored for the connecting user.
441          */
442
443         if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
444
445                 status = find_forced_group(
446                         conn->force_user, snum, conn->session_info->unix_info->unix_name,
447                         &conn->session_info->security_token->sids[1],
448                         &conn->session_info->unix_token->gid);
449
450                 if (!NT_STATUS_IS_OK(status)) {
451                         return status;
452                 }
453
454                 /*
455                  * We need to cache this gid, to use within
456                  * change_to_user() separately from the conn->session_info
457                  * struct. We only use conn->session_info directly if
458                  * "force_user" was set.
459                  */
460                 conn->force_group_gid = conn->session_info->unix_token->gid;
461         }
462
463         return NT_STATUS_OK;
464 }
465
466 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
467 {
468         NTSTATUS status;
469
470         if (sconn->notify_ctx != NULL) {
471                 return NT_STATUS_OK;
472         }
473
474         sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
475                                         sconn, notify_callback);
476         if (sconn->notify_ctx == NULL) {
477                 return NT_STATUS_NO_MEMORY;
478         }
479
480         status = messaging_register(sconn->msg_ctx, sconn,
481                                     MSG_SMB_NOTIFY_CANCEL_DELETED,
482                                     smbd_notify_cancel_deleted);
483         if (!NT_STATUS_IS_OK(status)) {
484                 DBG_DEBUG("messaging_register failed: %s\n",
485                           nt_errstr(status));
486                 TALLOC_FREE(sconn->notify_ctx);
487                 return status;
488         }
489
490         status = messaging_register(sconn->msg_ctx, sconn,
491                                     MSG_SMB_NOTIFY_STARTED,
492                                     smbd_notifyd_restarted);
493         if (!NT_STATUS_IS_OK(status)) {
494                 DBG_DEBUG("messaging_register failed: %s\n",
495                           nt_errstr(status));
496                 messaging_deregister(sconn->msg_ctx,
497                                      MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
498                 TALLOC_FREE(sconn->notify_ctx);
499                 return status;
500         }
501
502         return NT_STATUS_OK;
503 }
504
505 /****************************************************************************
506   Make a connection, given the snum to connect to, and the vuser of the
507   connecting user if appropriate.
508 ****************************************************************************/
509
510 NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
511                               connection_struct *conn,
512                               int snum,
513                               struct smbXsrv_session *session,
514                               const char *pdev)
515 {
516         struct smbd_server_connection *sconn = xconn->client->sconn;
517         const struct loadparm_substitution *lp_sub =
518                 loadparm_s3_global_substitution();
519         struct smb_filename *smb_fname_cpath = NULL;
520         fstring dev;
521         int ret;
522         bool on_err_call_dis_hook = false;
523         uid_t effuid;
524         gid_t effgid;
525         NTSTATUS status;
526         bool ok;
527
528         fstrcpy(dev, pdev);
529
530         status = share_sanity_checks(sconn->remote_address,
531                                        sconn->remote_hostname,
532                                        snum,
533                                        dev);
534         if (NT_STATUS_IS_ERR(status)) {
535                 goto err_root_exit;
536         }
537
538         conn->params->service = snum;
539
540         status = create_connection_session_info(sconn,
541                 conn, snum, session->global->auth_session_info,
542                 &conn->session_info);
543
544         if (!NT_STATUS_IS_OK(status)) {
545                 DEBUG(1, ("create_connection_session_info failed: %s\n",
546                           nt_errstr(status)));
547                 goto err_root_exit;
548         }
549
550         if (lp_guest_only(snum)) {
551                 conn->force_user = true;
552         }
553
554         conn->num_files_open = 0;
555         conn->lastused = conn->lastused_count = time(NULL);
556         conn->printer = (strncmp(dev,"LPT",3) == 0);
557         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
558                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
559
560         /* Case options for the share. */
561         conn_setup_case_options(conn);
562
563         conn->encrypt_level = lp_server_smb_encrypt(snum);
564         if (conn->encrypt_level > SMB_ENCRYPTION_OFF) {
565                 if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF) {
566                         if (conn->encrypt_level == SMB_ENCRYPTION_REQUIRED) {
567                                 DBG_ERR("Service [%s] requires encryption, but "
568                                         "it is disabled globally!\n",
569                                         lp_const_servicename(snum));
570                                 status = NT_STATUS_ACCESS_DENIED;
571                                 goto err_root_exit;
572                         }
573                         conn->encrypt_level = SMB_ENCRYPTION_OFF;
574                 }
575         }
576
577         conn->veto_list = NULL;
578         conn->hide_list = NULL;
579         conn->veto_oplock_list = NULL;
580         conn->aio_write_behind_list = NULL;
581
582         conn->read_only = lp_read_only(SNUM(conn));
583
584         status = set_conn_force_user_group(conn, snum);
585         if (!NT_STATUS_IS_OK(status)) {
586                 goto err_root_exit;
587         }
588
589         conn->vuid = session->global->session_wire_id;
590
591         {
592                 char *s = talloc_sub_full(talloc_tos(),
593                                         lp_const_servicename(SNUM(conn)),
594                                         conn->session_info->unix_info->unix_name,
595                                         conn->connectpath,
596                                         conn->session_info->unix_token->gid,
597                                         conn->session_info->unix_info->sanitized_username,
598                                         conn->session_info->info->domain_name,
599                                         lp_path(talloc_tos(), lp_sub, snum));
600                 if (!s) {
601                         status = NT_STATUS_NO_MEMORY;
602                         goto err_root_exit;
603                 }
604
605                 if (!set_conn_connectpath(conn,s)) {
606                         TALLOC_FREE(s);
607                         status = NT_STATUS_NO_MEMORY;
608                         goto err_root_exit;
609                 }
610                 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
611                            lp_const_servicename(snum));
612                 TALLOC_FREE(s);
613         }
614
615         /*
616          * Set up the share security descriptor.
617          * NOTE - we use the *INCOMING USER* session_info
618          * here, as does (indirectly) change_to_user(),
619          * which can be called on any incoming packet.
620          * This way we set up the share access based
621          * on the authenticated user, not the forced
622          * user. See bug:
623          *
624          * https://bugzilla.samba.org/show_bug.cgi?id=9878
625          */
626
627         status = check_user_share_access(conn,
628                                         session->global->auth_session_info,
629                                         &conn->share_access,
630                                         &conn->read_only);
631         if (!NT_STATUS_IS_OK(status)) {
632                 goto err_root_exit;
633         }
634
635         /* Initialise VFS function pointers */
636
637         if (!smbd_vfs_init(conn)) {
638                 DBG_ERR("vfs_init failed for service %s\n",
639                         lp_const_servicename(snum));
640                 status = NT_STATUS_BAD_NETWORK_NAME;
641                 goto err_root_exit;
642         }
643
644 /* ROOT Activities: */
645         /* explicitly check widelinks here so that we can correctly warn
646          * in the logs. */
647         widelinks_warning(snum);
648
649         /*
650          * Enforce the max connections parameter.
651          */
652
653         if ((lp_max_connections(snum) > 0)
654             && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
655                 lp_max_connections(snum))) {
656
657                 DBG_WARNING("Max connections (%d) exceeded for %s\n",
658                           lp_max_connections(snum),
659                           lp_const_servicename(snum));
660                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
661                 goto err_root_exit;
662         }
663
664         /* Invoke VFS make connection hook - this must be the first
665            filesystem operation that we do. */
666
667         if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
668                             conn->session_info->unix_info->unix_name) < 0) {
669                 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
670                             lp_const_servicename(snum), conn->connectpath,
671                             strerror(errno));
672                 status = NT_STATUS_UNSUCCESSFUL;
673                 goto err_root_exit;
674         }
675
676         /* Any error exit after here needs to call the disconnect hook. */
677         on_err_call_dis_hook = true;
678
679         if ((!conn->printer) && (!conn->ipc) &&
680             lp_change_notify()) {
681
682                 status = notify_init_sconn(sconn);
683                 if (!NT_STATUS_IS_OK(status)) {
684                         goto err_root_exit;
685                 }
686         }
687
688         if (lp_kernel_oplocks(snum)) {
689                 init_kernel_oplocks(conn->sconn);
690         }
691
692         /*
693          * Fix compatibility issue pointed out by Volker.
694          * We pass the conn->connectpath to the preexec
695          * scripts as a parameter, so attempt to canonicalize
696          * it here before calling the preexec scripts.
697          * We ignore errors here, as it is possible that
698          * the conn->connectpath doesn't exist yet and
699          * the preexec scripts will create them.
700          */
701
702         (void)canonicalize_connect_path(conn);
703
704         /* Preexecs are done here as they might make the dir we are to ChDir
705          * to below */
706         /* execute any "root preexec = " line */
707         if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
708                 char *cmd = talloc_sub_full(talloc_tos(),
709                                         lp_const_servicename(SNUM(conn)),
710                                         conn->session_info->unix_info->unix_name,
711                                         conn->connectpath,
712                                         conn->session_info->unix_token->gid,
713                                         conn->session_info->unix_info->sanitized_username,
714                                         conn->session_info->info->domain_name,
715                                         lp_root_preexec(talloc_tos(), lp_sub, snum));
716                 DEBUG(5,("cmd=%s\n",cmd));
717                 ret = smbrun(cmd, NULL, NULL);
718                 TALLOC_FREE(cmd);
719                 if (ret != 0 && lp_root_preexec_close(snum)) {
720                         DEBUG(1,("root preexec gave %d - failing "
721                                  "connection\n", ret));
722                         status = NT_STATUS_ACCESS_DENIED;
723                         goto err_root_exit;
724                 }
725         }
726
727 /* USER Activites: */
728         if (!change_to_user_and_service(conn, conn->vuid)) {
729                 /* No point continuing if they fail the basic checks */
730                 DEBUG(0,("Can't become connected user!\n"));
731                 status = NT_STATUS_LOGON_FAILURE;
732                 goto err_root_exit;
733         }
734
735         effuid = geteuid();
736         effgid = getegid();
737
738         /* Remember that a different vuid can connect later without these
739          * checks... */
740
741         /* Preexecs are done here as they might make the dir we are to ChDir
742          * to below */
743
744         /* execute any "preexec = " line */
745         if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
746                 char *cmd = talloc_sub_full(talloc_tos(),
747                                         lp_const_servicename(SNUM(conn)),
748                                         conn->session_info->unix_info->unix_name,
749                                         conn->connectpath,
750                                         conn->session_info->unix_token->gid,
751                                         conn->session_info->unix_info->sanitized_username,
752                                         conn->session_info->info->domain_name,
753                                         lp_preexec(talloc_tos(), lp_sub, snum));
754                 ret = smbrun(cmd, NULL, NULL);
755                 TALLOC_FREE(cmd);
756                 if (ret != 0 && lp_preexec_close(snum)) {
757                         DEBUG(1,("preexec gave %d - failing connection\n",
758                                  ret));
759                         status = NT_STATUS_ACCESS_DENIED;
760                         goto err_root_exit;
761                 }
762         }
763
764 #ifdef WITH_FAKE_KASERVER
765         if (lp_afs_share(snum)) {
766                 afs_login(conn);
767         }
768 #endif
769
770         /*
771          * we've finished with the user stuff - go back to root
772          * so the SMB_VFS_STAT call will only fail on path errors,
773          * not permission problems.
774          */
775         change_to_root_user();
776 /* ROOT Activites: */
777
778         /*
779          * Canonicalise the connect
780          * path here to ensure we don't have any symlinks in the
781          * connectpath. We will be checking all paths on this connection are
782          * below this directory. We must do this after the VFS init as we
783          * depend on the realpath() pointer in the vfs table. JRA.
784          */
785         ok = canonicalize_connect_path(conn);
786         if (!ok) {
787                 DBG_ERR("canonicalize_connect_path failed "
788                 "for service %s, path %s\n",
789                         lp_const_servicename(snum),
790                         conn->connectpath);
791                 status = NT_STATUS_BAD_NETWORK_NAME;
792                 goto err_root_exit;
793         }
794
795         /* Add veto/hide lists */
796         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
797                 set_namearray( &conn->veto_list,
798                                lp_veto_files(talloc_tos(), lp_sub, snum));
799                 set_namearray( &conn->hide_list,
800                                lp_hide_files(talloc_tos(), lp_sub, snum));
801                 set_namearray( &conn->veto_oplock_list,
802                                lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
803                 set_namearray( &conn->aio_write_behind_list,
804                                 lp_aio_write_behind(talloc_tos(), lp_sub, snum));
805         }
806         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
807                                         conn->connectpath,
808                                         NULL,
809                                         NULL,
810                                         0,
811                                         0);
812         if (smb_fname_cpath == NULL) {
813                 status = NT_STATUS_NO_MEMORY;
814                 goto err_root_exit;
815         }
816
817         /* win2000 does not check the permissions on the directory
818            during the tree connect, instead relying on permission
819            check during individual operations. To match this behaviour
820            I have disabled this chdir check (tridge) */
821         /* the alternative is just to check the directory exists */
822
823         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
824             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
825                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
826                         DBG_ERR("'%s' is not a directory, when connecting to "
827                                  "[%s]\n", conn->connectpath,
828                                  lp_const_servicename(snum));
829                 } else {
830                         DBG_ERR("'%s' does not exist or permission denied "
831                                  "when connecting to [%s] Error was %s\n",
832                                  conn->connectpath,
833                                  lp_const_servicename(snum),
834                                  strerror(errno));
835                 }
836                 status = NT_STATUS_BAD_NETWORK_NAME;
837                 goto err_root_exit;
838         }
839         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
840
841         /* Figure out the characteristics of the underlying filesystem. This
842          * assumes that all the filesystem mounted within a share path have
843          * the same characteristics, which is likely but not guaranteed.
844          */
845
846         if(!IS_IPC(conn) ){
847                 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
848         }
849         /*
850          * Print out the 'connected as' stuff here as we need
851          * to know the effective uid and gid we will be using
852          * (at least initially).
853          */
854
855         if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
856                 bool signing_active;
857
858                 dbgtext( "%s (%s) ", get_remote_machine_name(),
859                          tsocket_address_string(conn->sconn->remote_address,
860                                                 talloc_tos()) );
861 #if defined(WITH_SMB1SERVER)
862                 if (sconn->using_smb2) {
863 #endif
864                         signing_active = smb2_signing_key_valid(
865                                                 session->global->encryption_key);
866 #if defined(WITH_SMB1SERVER)
867                 } else {
868                         signing_active = smb1_srv_is_signing_active(xconn);
869                 }
870 #endif
871                 dbgtext( "%s", signing_active ? "signed " : "");
872                 dbgtext( "connect to service %s ",
873                          lp_const_servicename(snum) );
874                 dbgtext( "initially as user %s ",
875                          conn->session_info->unix_info->unix_name );
876                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
877                 dbgtext( "(pid %d)\n", (int)getpid() );
878         }
879
880         conn->tcon_done = true;
881         return NT_STATUS_OK;
882
883   err_root_exit:
884
885         TALLOC_FREE(smb_fname_cpath);
886         /* We must exit this function as root. */
887         if (geteuid() != 0) {
888                 change_to_root_user();
889         }
890         if (on_err_call_dis_hook) {
891                 /* Call VFS disconnect hook */
892                 SMB_VFS_DISCONNECT(conn);
893         }
894         return status;
895 }
896
897 /****************************************************************************
898  Make a connection to a service from SMB2. External SMB2 interface.
899  We must set cnum before claiming connection.
900 ****************************************************************************/
901
902 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
903                                         struct smbXsrv_tcon *tcon,
904                                         int snum,
905                                         const char *pdev,
906                                         NTSTATUS *pstatus)
907 {
908         struct smbd_server_connection *sconn = req->sconn;
909         connection_struct *conn = conn_new(sconn);
910         if (!conn) {
911                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
912                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
913                 return NULL;
914         }
915
916         conn->cnum = tcon->global->tcon_wire_id;
917         conn->tcon = tcon;
918
919         *pstatus = make_connection_snum(req->xconn,
920                                         conn,
921                                         snum,
922                                         req->session,
923                                         pdev);
924         if (!NT_STATUS_IS_OK(*pstatus)) {
925                 conn_free(conn);
926                 return NULL;
927         }
928         return conn;
929 }
930
931 /****************************************************************************
932  Close a cnum.
933 ****************************************************************************/
934
935 void close_cnum(connection_struct *conn,
936                 uint64_t vuid,
937                 enum file_close_type close_type)
938 {
939         char rootpath[2] = { '/', '\0'};
940         struct smb_filename root_fname = { .base_name = rootpath };
941         const struct loadparm_substitution *lp_sub =
942                 loadparm_s3_global_substitution();
943
944         file_close_conn(conn);
945
946         change_to_root_user();
947
948         DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
949                                  get_remote_machine_name(),
950                                  tsocket_address_string(conn->sconn->remote_address,
951                                                         talloc_tos()),
952                                  lp_const_servicename(SNUM(conn))));
953
954         /* make sure we leave the directory available for unmount */
955         vfs_ChDir(conn, &root_fname);
956
957         /* Call VFS disconnect hook */
958         SMB_VFS_DISCONNECT(conn);
959
960         /* execute any "postexec = " line */
961         if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
962             change_to_user_and_service(conn, vuid))  {
963                 char *cmd = talloc_sub_full(talloc_tos(),
964                                         lp_const_servicename(SNUM(conn)),
965                                         conn->session_info->unix_info->unix_name,
966                                         conn->connectpath,
967                                         conn->session_info->unix_token->gid,
968                                         conn->session_info->unix_info->sanitized_username,
969                                         conn->session_info->info->domain_name,
970                                         lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
971                 smbrun(cmd, NULL, NULL);
972                 TALLOC_FREE(cmd);
973                 change_to_root_user();
974         }
975
976         change_to_root_user();
977         /* execute any "root postexec = " line */
978         if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)))  {
979                 char *cmd = talloc_sub_full(talloc_tos(),
980                                         lp_const_servicename(SNUM(conn)),
981                                         conn->session_info->unix_info->unix_name,
982                                         conn->connectpath,
983                                         conn->session_info->unix_token->gid,
984                                         conn->session_info->unix_info->sanitized_username,
985                                         conn->session_info->info->domain_name,
986                                         lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
987                 smbrun(cmd, NULL, NULL);
988                 TALLOC_FREE(cmd);
989         }
990
991         conn_free(conn);
992 }