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