s3:param: make "servicename" a substituted option
[samba.git] / source3 / smbd / 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
37 static bool canonicalize_connect_path(connection_struct *conn)
38 {
39         bool ret;
40         struct smb_filename con_fname = { .base_name = conn->connectpath };
41         struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
42                                                 &con_fname);
43         if (resolved_fname == NULL) {
44                 return false;
45         }
46         ret = set_conn_connectpath(conn,resolved_fname->base_name);
47         TALLOC_FREE(resolved_fname);
48         return ret;
49 }
50
51 /****************************************************************************
52  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
53  absolute path stating in / and not ending in /.
54 ****************************************************************************/
55
56 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
57 {
58         char *destname;
59
60         if (connectpath == NULL || connectpath[0] == '\0') {
61                 return false;
62         }
63
64         destname = canonicalize_absolute_path(conn, connectpath);
65         if (destname == NULL) {
66                 return false;
67         }
68
69         DBG_DEBUG("service %s, connectpath = %s\n",
70                   lp_const_servicename(SNUM(conn)), destname);
71
72         talloc_free(conn->connectpath);
73         conn->connectpath = destname;
74         /*
75          * Ensure conn->cwd_fsp->fsp_name is initialized.
76          * start as conn->connectpath.
77          */
78         TALLOC_FREE(conn->cwd_fsp->fsp_name);
79         conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
80                                 conn->connectpath,
81                                 NULL,
82                                 NULL,
83                                 0);
84         if (conn->cwd_fsp->fsp_name == NULL) {
85                 return false;
86         }
87         return true;
88 }
89
90 /****************************************************************************
91  Load parameters specific to a connection/service.
92 ****************************************************************************/
93
94 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
95 {
96         int snum;
97         enum remote_arch_types ra_type;
98
99         SMB_ASSERT(conn != NULL);
100
101         snum = SNUM(conn);
102
103         if ((conn == last_conn) && (last_flags == flags)) {
104                 return;
105         }
106
107         last_conn = conn;
108         last_flags = flags;
109
110         /*
111          * Obey the client case sensitivity requests - only for clients that
112          * support it. */
113         switch (lp_case_sensitive(snum)) {
114         case Auto:
115                 /*
116                  * We need this uglyness due to DOS/Win9x clients that lie
117                  * about case insensitivity. */
118                 ra_type = get_remote_arch();
119                 if (conn->sconn->using_smb2) {
120                         conn->case_sensitive = false;
121                 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
122                         /*
123                          * Client can't support per-packet case sensitive
124                          * pathnames. */
125                         conn->case_sensitive = false;
126                 } else {
127                         conn->case_sensitive =
128                                         !(flags & FLAG_CASELESS_PATHNAMES);
129                 }
130         break;
131         case True:
132                 conn->case_sensitive = true;
133                 break;
134         default:
135                 conn->case_sensitive = false;
136                 break;
137         }
138         return;
139 }
140
141 bool chdir_current_service(connection_struct *conn)
142 {
143         const struct smb_filename connectpath_fname = {
144                 .base_name = conn->connectpath,
145         };
146         const struct smb_filename origpath_fname = {
147                 .base_name = conn->origpath,
148         };
149         int ret;
150
151         conn->lastused_count++;
152
153         ret = vfs_ChDir(conn, &connectpath_fname);
154         if (ret != 0) {
155                 int saved_errno = errno;
156
157                 if (saved_errno == EACCES) {
158                         char *str = utok_string(
159                                 talloc_tos(),
160                                 conn->session_info->unix_token);
161                         DBG_WARNING("vfs_ChDir(%s) got "
162                                     "permission denied, current "
163                                     "token: %s\n",
164                                     conn->connectpath, str);
165                         TALLOC_FREE(str);
166                 } else {
167                         DBG_ERR("vfs_ChDir(%s) failed: "
168                                 "%s!\n",
169                                 conn->connectpath,
170                                 strerror(saved_errno));
171                 }
172                 return false;
173         }
174
175         ret = vfs_ChDir(conn, &origpath_fname);
176         if (ret != 0) {
177                 int saved_errno = errno;
178
179                 if (saved_errno == EACCES) {
180                         char *str = utok_string(
181                                 talloc_tos(),
182                                 conn->session_info->unix_token);
183                         DBG_WARNING("vfs_ChDir(%s) got "
184                                     "permission denied, current "
185                                     "token: %s\n",
186                                     conn->origpath, str);
187                         TALLOC_FREE(str);
188                 } else {
189                         DBG_ERR("vfs_ChDir(%s) failed: "
190                                 "%s!\n",
191                                 conn->origpath,
192                                 strerror(saved_errno));
193                 }
194                 return false;
195         }
196
197         return true;
198 }
199
200 /****************************************************************************
201  do some basic sainity checks on the share.  
202  This function modifies dev, ecode.
203 ****************************************************************************/
204
205 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
206                                     const char *rhost,
207                                     int snum,
208                                     fstring dev)
209 {
210         char *raddr;
211
212         raddr = tsocket_address_inet_addr_string(remote_address,
213                                                  talloc_tos());
214         if (raddr == NULL) {
215                 return NT_STATUS_NO_MEMORY;
216         }
217
218         if (!lp_snum_ok(snum) ||
219             !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
220                           rhost, raddr)) {
221                 return NT_STATUS_ACCESS_DENIED;
222         }
223
224         if (dev[0] == '?' || !dev[0]) {
225                 if (lp_printable(snum)) {
226                         fstrcpy(dev,"LPT1:");
227                 } else if (strequal(lp_fstype(snum), "IPC")) {
228                         fstrcpy(dev, "IPC");
229                 } else {
230                         fstrcpy(dev,"A:");
231                 }
232         }
233
234         if (!strupper_m(dev)) {
235                 DEBUG(2,("strupper_m %s failed\n", dev));
236                 return NT_STATUS_INVALID_PARAMETER;
237         }
238
239         if (lp_printable(snum)) {
240                 if (!strequal(dev, "LPT1:")) {
241                         return NT_STATUS_BAD_DEVICE_TYPE;
242                 }
243         } else if (strequal(lp_fstype(snum), "IPC")) {
244                 if (!strequal(dev, "IPC")) {
245                         return NT_STATUS_BAD_DEVICE_TYPE;
246                 }
247         } else if (!strequal(dev, "A:")) {
248                 return NT_STATUS_BAD_DEVICE_TYPE;
249         }
250
251         /* Behave as a printer if we are supposed to */
252         if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
253                 fstrcpy(dev, "LPT1:");
254         }
255
256         return NT_STATUS_OK;
257 }
258
259 /*
260  * Go through lookup_name etc to find the force'd group.  
261  *
262  * Create a new token from src_token, replacing the primary group sid with the
263  * one found.
264  */
265
266 static NTSTATUS find_forced_group(bool force_user,
267                                   int snum, const char *username,
268                                   struct dom_sid *pgroup_sid,
269                                   gid_t *pgid)
270 {
271         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
272         TALLOC_CTX *frame = talloc_stackframe();
273         const struct loadparm_substitution *lp_sub =
274                 loadparm_s3_global_substitution();
275         struct dom_sid group_sid;
276         enum lsa_SidType type;
277         char *groupname;
278         bool user_must_be_member = False;
279         gid_t gid;
280
281         groupname = lp_force_group(talloc_tos(), lp_sub, snum);
282         if (groupname == NULL) {
283                 DEBUG(1, ("talloc_strdup failed\n"));
284                 result = NT_STATUS_NO_MEMORY;
285                 goto done;
286         }
287
288         if (groupname[0] == '+') {
289                 user_must_be_member = True;
290                 groupname += 1;
291         }
292
293         groupname = talloc_string_sub(talloc_tos(), groupname,
294                                       "%S", lp_const_servicename(snum));
295         if (groupname == NULL) {
296                 DEBUG(1, ("talloc_string_sub failed\n"));
297                 result = NT_STATUS_NO_MEMORY;
298                 goto done;
299         }
300
301         if (!lookup_name_smbconf(talloc_tos(), groupname,
302                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
303                          NULL, NULL, &group_sid, &type)) {
304                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
305                            groupname));
306                 goto done;
307         }
308
309         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
310             (type != SID_NAME_WKN_GRP)) {
311                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
312                            sid_type_lookup(type)));
313                 goto done;
314         }
315
316         if (!sid_to_gid(&group_sid, &gid)) {
317                 struct dom_sid_buf buf;
318                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
319                            dom_sid_str_buf(&group_sid, &buf), groupname));
320                 goto done;
321         }
322
323         /*
324          * If the user has been forced and the forced group starts with a '+',
325          * then we only set the group to be the forced group if the forced
326          * user is a member of that group.  Otherwise, the meaning of the '+'
327          * would be ignored.
328          */
329
330         if (force_user && user_must_be_member) {
331                 if (user_in_group_sid(username, &group_sid)) {
332                         sid_copy(pgroup_sid, &group_sid);
333                         *pgid = gid;
334                         DEBUG(3,("Forced group %s for member %s\n",
335                                  groupname, username));
336                 } else {
337                         DEBUG(0,("find_forced_group: forced user %s is not a member "
338                                 "of forced group %s. Disallowing access.\n",
339                                 username, groupname ));
340                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
341                         goto done;
342                 }
343         } else {
344                 sid_copy(pgroup_sid, &group_sid);
345                 *pgid = gid;
346                 DEBUG(3,("Forced group %s\n", groupname));
347         }
348
349         result = NT_STATUS_OK;
350  done:
351         TALLOC_FREE(frame);
352         return result;
353 }
354
355 /****************************************************************************
356   Create an auth_session_info structure for a connection_struct
357 ****************************************************************************/
358
359 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
360                                               TALLOC_CTX *mem_ctx, int snum,
361                                               struct auth_session_info *session_info,
362                                               struct auth_session_info **presult)
363 {
364         struct auth_session_info *result;
365
366         if (lp_guest_only(snum)) {
367                 return make_session_info_guest(mem_ctx, presult);
368         }
369
370         /*
371          * This is the normal security != share case where we have a
372          * valid vuid from the session setup.                 */
373
374         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
375                 if (!lp_guest_ok(snum)) {
376                         DBG_WARNING("guest user (from session setup) "
377                                   "not permitted to access this share "
378                                   "(%s)\n", lp_const_servicename(snum));
379                         return NT_STATUS_ACCESS_DENIED;
380                 }
381         } else {
382                 if (!user_ok_token(session_info->unix_info->unix_name,
383                                    session_info->info->domain_name,
384                                    session_info->security_token, snum)) {
385                         DBG_WARNING("user '%s' (from session setup) not "
386                                   "permitted to access this share "
387                                   "(%s)\n",
388                                   session_info->unix_info->unix_name,
389                                   lp_const_servicename(snum));
390                         return NT_STATUS_ACCESS_DENIED;
391                 }
392         }
393
394         result = copy_session_info(mem_ctx, session_info);
395         if (result == NULL) {
396                 return NT_STATUS_NO_MEMORY;
397         }
398
399         *presult = result;
400         return NT_STATUS_OK;
401 }
402
403 /****************************************************************************
404   Set relevant user and group settings corresponding to force user/group
405   configuration for the given snum.
406 ****************************************************************************/
407
408 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
409 {
410         const struct loadparm_substitution *lp_sub =
411                 loadparm_s3_global_substitution();
412         NTSTATUS status;
413
414         if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
415
416                 /*
417                  * Replace conn->session_info with a completely faked up one
418                  * from the username we are forced into :-)
419                  */
420
421                 char *fuser;
422                 char *sanitized_username;
423                 struct auth_session_info *forced_serverinfo;
424                 bool guest;
425
426                 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
427                                           lp_const_servicename(snum));
428                 if (fuser == NULL) {
429                         return NT_STATUS_NO_MEMORY;
430                 }
431
432                 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
433
434                 status = make_session_info_from_username(
435                         conn, fuser,
436                         guest,
437                         &forced_serverinfo);
438                 if (!NT_STATUS_IS_OK(status)) {
439                         return status;
440                 }
441
442                 /* We don't want to replace the original sanitized_username
443                    as it is the original user given in the connect attempt.
444                    This is used in '%U' substitutions. */
445                 sanitized_username = discard_const_p(char,
446                         forced_serverinfo->unix_info->sanitized_username);
447                 TALLOC_FREE(sanitized_username);
448                 forced_serverinfo->unix_info->sanitized_username =
449                         talloc_move(forced_serverinfo->unix_info,
450                                 &conn->session_info->unix_info->sanitized_username);
451
452                 TALLOC_FREE(conn->session_info);
453                 conn->session_info = forced_serverinfo;
454
455                 conn->force_user = true;
456                 DEBUG(3,("Forced user %s\n", fuser));
457         }
458
459         /*
460          * If force group is true, then override
461          * any groupid stored for the connecting user.
462          */
463
464         if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
465
466                 status = find_forced_group(
467                         conn->force_user, snum, conn->session_info->unix_info->unix_name,
468                         &conn->session_info->security_token->sids[1],
469                         &conn->session_info->unix_token->gid);
470
471                 if (!NT_STATUS_IS_OK(status)) {
472                         return status;
473                 }
474
475                 /*
476                  * We need to cache this gid, to use within
477                  * change_to_user() separately from the conn->session_info
478                  * struct. We only use conn->session_info directly if
479                  * "force_user" was set.
480                  */
481                 conn->force_group_gid = conn->session_info->unix_token->gid;
482         }
483
484         return NT_STATUS_OK;
485 }
486
487 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
488 {
489         NTSTATUS status;
490
491         if (sconn->notify_ctx != NULL) {
492                 return NT_STATUS_OK;
493         }
494
495         sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
496                                         sconn, notify_callback);
497         if (sconn->notify_ctx == NULL) {
498                 return NT_STATUS_NO_MEMORY;
499         }
500
501         status = messaging_register(sconn->msg_ctx, sconn,
502                                     MSG_SMB_NOTIFY_CANCEL_DELETED,
503                                     smbd_notify_cancel_deleted);
504         if (!NT_STATUS_IS_OK(status)) {
505                 DBG_DEBUG("messaging_register failed: %s\n",
506                           nt_errstr(status));
507                 TALLOC_FREE(sconn->notify_ctx);
508                 return status;
509         }
510
511         status = messaging_register(sconn->msg_ctx, sconn,
512                                     MSG_SMB_NOTIFY_STARTED,
513                                     smbd_notifyd_restarted);
514         if (!NT_STATUS_IS_OK(status)) {
515                 DBG_DEBUG("messaging_register failed: %s\n",
516                           nt_errstr(status));
517                 messaging_deregister(sconn->msg_ctx,
518                                      MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
519                 TALLOC_FREE(sconn->notify_ctx);
520                 return status;
521         }
522
523         return NT_STATUS_OK;
524 }
525
526 /****************************************************************************
527   Make a connection, given the snum to connect to, and the vuser of the
528   connecting user if appropriate.
529 ****************************************************************************/
530
531 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
532                                         connection_struct *conn,
533                                         int snum, struct user_struct *vuser,
534                                         const char *pdev)
535 {
536         struct smbd_server_connection *sconn = xconn->client->sconn;
537         const struct loadparm_substitution *lp_sub =
538                 loadparm_s3_global_substitution();
539         struct smb_filename *smb_fname_cpath = NULL;
540         fstring dev;
541         int ret;
542         bool on_err_call_dis_hook = false;
543         uid_t effuid;
544         gid_t effgid;
545         NTSTATUS status;
546
547         fstrcpy(dev, pdev);
548
549         status = share_sanity_checks(sconn->remote_address,
550                                        sconn->remote_hostname,
551                                        snum,
552                                        dev);
553         if (NT_STATUS_IS_ERR(status)) {
554                 goto err_root_exit;
555         }
556
557         conn->params->service = snum;
558
559         status = create_connection_session_info(sconn,
560                 conn, snum, vuser->session_info,
561                 &conn->session_info);
562
563         if (!NT_STATUS_IS_OK(status)) {
564                 DEBUG(1, ("create_connection_session_info failed: %s\n",
565                           nt_errstr(status)));
566                 goto err_root_exit;
567         }
568
569         if (lp_guest_only(snum)) {
570                 conn->force_user = true;
571         }
572
573         conn->num_files_open = 0;
574         conn->lastused = conn->lastused_count = time(NULL);
575         conn->printer = (strncmp(dev,"LPT",3) == 0);
576         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
577                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
578
579         /* Case options for the share. */
580         if (lp_case_sensitive(snum) == Auto) {
581                 /* We will be setting this per packet. Set to be case
582                  * insensitive for now. */
583                 conn->case_sensitive = False;
584         } else {
585                 conn->case_sensitive = (bool)lp_case_sensitive(snum);
586         }
587
588         conn->case_preserve = lp_preserve_case(snum);
589         conn->short_case_preserve = lp_short_preserve_case(snum);
590
591         conn->encrypt_level = lp_smb_encrypt(snum);
592         if (conn->encrypt_level > SMB_SIGNING_OFF) {
593                 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
594                         if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
595                                 DBG_ERR("Service [%s] requires encryption, but "
596                                         "it is disabled globally!\n",
597                                         lp_const_servicename(snum));
598                                 status = NT_STATUS_ACCESS_DENIED;
599                                 goto err_root_exit;
600                         }
601                         conn->encrypt_level = SMB_SIGNING_OFF;
602                 }
603         }
604
605         conn->veto_list = NULL;
606         conn->hide_list = NULL;
607         conn->veto_oplock_list = NULL;
608         conn->aio_write_behind_list = NULL;
609
610         conn->read_only = lp_read_only(SNUM(conn));
611
612         status = set_conn_force_user_group(conn, snum);
613         if (!NT_STATUS_IS_OK(status)) {
614                 goto err_root_exit;
615         }
616
617         conn->vuid = vuser->vuid;
618
619         {
620                 char *s = talloc_sub_full(talloc_tos(),
621                                         lp_const_servicename(SNUM(conn)),
622                                         conn->session_info->unix_info->unix_name,
623                                         conn->connectpath,
624                                         conn->session_info->unix_token->gid,
625                                         conn->session_info->unix_info->sanitized_username,
626                                         conn->session_info->info->domain_name,
627                                         lp_path(talloc_tos(), lp_sub, snum));
628                 if (!s) {
629                         status = NT_STATUS_NO_MEMORY;
630                         goto err_root_exit;
631                 }
632
633                 if (!set_conn_connectpath(conn,s)) {
634                         TALLOC_FREE(s);
635                         status = NT_STATUS_NO_MEMORY;
636                         goto err_root_exit;
637                 }
638                 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
639                            lp_const_servicename(snum));
640                 TALLOC_FREE(s);
641         }
642
643         /*
644          * Set up the share security descriptor.
645          * NOTE - we use the *INCOMING USER* session_info
646          * here, as does (indirectly) change_to_user(),
647          * which can be called on any incoming packet.
648          * This way we set up the share access based
649          * on the authenticated user, not the forced
650          * user. See bug:
651          *
652          * https://bugzilla.samba.org/show_bug.cgi?id=9878
653          */
654
655         status = check_user_share_access(conn,
656                                         vuser->session_info,
657                                         &conn->share_access,
658                                         &conn->read_only);
659         if (!NT_STATUS_IS_OK(status)) {
660                 goto err_root_exit;
661         }
662
663         /* Initialise VFS function pointers */
664
665         if (!smbd_vfs_init(conn)) {
666                 DBG_ERR("vfs_init failed for service %s\n",
667                         lp_const_servicename(snum));
668                 status = NT_STATUS_BAD_NETWORK_NAME;
669                 goto err_root_exit;
670         }
671
672 /* ROOT Activities: */
673         /* explicitly check widelinks here so that we can correctly warn
674          * in the logs. */
675         widelinks_warning(snum);
676
677         /*
678          * Enforce the max connections parameter.
679          */
680
681         if ((lp_max_connections(snum) > 0)
682             && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
683                 lp_max_connections(snum))) {
684
685                 DBG_WARNING("Max connections (%d) exceeded for %s\n",
686                           lp_max_connections(snum),
687                           lp_const_servicename(snum));
688                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
689                 goto err_root_exit;
690         }
691
692         /* Invoke VFS make connection hook - this must be the first
693            filesystem operation that we do. */
694
695         if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
696                             conn->session_info->unix_info->unix_name) < 0) {
697                 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
698                             lp_const_servicename(snum), conn->connectpath,
699                             strerror(errno));
700                 status = NT_STATUS_UNSUCCESSFUL;
701                 goto err_root_exit;
702         }
703
704         /* Any error exit after here needs to call the disconnect hook. */
705         on_err_call_dis_hook = true;
706
707         if ((!conn->printer) && (!conn->ipc) &&
708             lp_change_notify()) {
709
710                 status = notify_init_sconn(sconn);
711                 if (!NT_STATUS_IS_OK(status)) {
712                         goto err_root_exit;
713                 }
714         }
715
716         if (lp_kernel_oplocks(snum)) {
717                 init_kernel_oplocks(conn->sconn);
718         }
719
720         /*
721          * Fix compatibility issue pointed out by Volker.
722          * We pass the conn->connectpath to the preexec
723          * scripts as a parameter, so attempt to canonicalize
724          * it here before calling the preexec scripts.
725          * We ignore errors here, as it is possible that
726          * the conn->connectpath doesn't exist yet and
727          * the preexec scripts will create them.
728          */
729
730         (void)canonicalize_connect_path(conn);
731
732         /* Preexecs are done here as they might make the dir we are to ChDir
733          * to below */
734         /* execute any "root preexec = " line */
735         if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
736                 char *cmd = talloc_sub_full(talloc_tos(),
737                                         lp_const_servicename(SNUM(conn)),
738                                         conn->session_info->unix_info->unix_name,
739                                         conn->connectpath,
740                                         conn->session_info->unix_token->gid,
741                                         conn->session_info->unix_info->sanitized_username,
742                                         conn->session_info->info->domain_name,
743                                         lp_root_preexec(talloc_tos(), lp_sub, snum));
744                 DEBUG(5,("cmd=%s\n",cmd));
745                 ret = smbrun(cmd, NULL, NULL);
746                 TALLOC_FREE(cmd);
747                 if (ret != 0 && lp_root_preexec_close(snum)) {
748                         DEBUG(1,("root preexec gave %d - failing "
749                                  "connection\n", ret));
750                         status = NT_STATUS_ACCESS_DENIED;
751                         goto err_root_exit;
752                 }
753         }
754
755 /* USER Activites: */
756         if (!change_to_user_and_service(conn, conn->vuid)) {
757                 /* No point continuing if they fail the basic checks */
758                 DEBUG(0,("Can't become connected user!\n"));
759                 status = NT_STATUS_LOGON_FAILURE;
760                 goto err_root_exit;
761         }
762
763         effuid = geteuid();
764         effgid = getegid();
765
766         /* Remember that a different vuid can connect later without these
767          * checks... */
768
769         /* Preexecs are done here as they might make the dir we are to ChDir
770          * to below */
771
772         /* execute any "preexec = " line */
773         if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
774                 char *cmd = talloc_sub_full(talloc_tos(),
775                                         lp_const_servicename(SNUM(conn)),
776                                         conn->session_info->unix_info->unix_name,
777                                         conn->connectpath,
778                                         conn->session_info->unix_token->gid,
779                                         conn->session_info->unix_info->sanitized_username,
780                                         conn->session_info->info->domain_name,
781                                         lp_preexec(talloc_tos(), lp_sub, snum));
782                 ret = smbrun(cmd, NULL, NULL);
783                 TALLOC_FREE(cmd);
784                 if (ret != 0 && lp_preexec_close(snum)) {
785                         DEBUG(1,("preexec gave %d - failing connection\n",
786                                  ret));
787                         status = NT_STATUS_ACCESS_DENIED;
788                         goto err_root_exit;
789                 }
790         }
791
792 #ifdef WITH_FAKE_KASERVER
793         if (lp_afs_share(snum)) {
794                 afs_login(conn);
795         }
796 #endif
797
798         /*
799          * we've finished with the user stuff - go back to root
800          * so the SMB_VFS_STAT call will only fail on path errors,
801          * not permission problems.
802          */
803         change_to_root_user();
804 /* ROOT Activites: */
805
806         /*
807          * If widelinks are disallowed we need to canonicalise the connect
808          * path here to ensure we don't have any symlinks in the
809          * connectpath. We will be checking all paths on this connection are
810          * below this directory. We must do this after the VFS init as we
811          * depend on the realpath() pointer in the vfs table. JRA.
812          */
813         if (!lp_widelinks(snum)) {
814                 if (!canonicalize_connect_path(conn)) {
815                         DBG_ERR("canonicalize_connect_path failed "
816                         "for service %s, path %s\n",
817                                 lp_const_servicename(snum),
818                                 conn->connectpath);
819                         status = NT_STATUS_BAD_NETWORK_NAME;
820                         goto err_root_exit;
821                 }
822         }
823
824         /* Add veto/hide lists */
825         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
826                 set_namearray( &conn->veto_list,
827                                lp_veto_files(talloc_tos(), lp_sub, snum));
828                 set_namearray( &conn->hide_list,
829                                lp_hide_files(talloc_tos(), lp_sub, snum));
830                 set_namearray( &conn->veto_oplock_list,
831                                lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
832                 set_namearray( &conn->aio_write_behind_list,
833                                 lp_aio_write_behind(talloc_tos(), lp_sub, snum));
834         }
835         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
836                                         conn->connectpath,
837                                         NULL,
838                                         NULL,
839                                         0);
840         if (smb_fname_cpath == NULL) {
841                 status = NT_STATUS_NO_MEMORY;
842                 goto err_root_exit;
843         }
844
845         /* win2000 does not check the permissions on the directory
846            during the tree connect, instead relying on permission
847            check during individual operations. To match this behaviour
848            I have disabled this chdir check (tridge) */
849         /* the alternative is just to check the directory exists */
850
851         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
852             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
853                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
854                         DBG_ERR("'%s' is not a directory, when connecting to "
855                                  "[%s]\n", conn->connectpath,
856                                  lp_const_servicename(snum));
857                 } else {
858                         DBG_ERR("'%s' does not exist or permission denied "
859                                  "when connecting to [%s] Error was %s\n",
860                                  conn->connectpath,
861                                  lp_const_servicename(snum),
862                                  strerror(errno));
863                 }
864                 status = NT_STATUS_BAD_NETWORK_NAME;
865                 goto err_root_exit;
866         }
867         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
868
869         talloc_free(conn->origpath);
870         conn->origpath = talloc_strdup(conn, conn->connectpath);
871
872         /* Figure out the characteristics of the underlying filesystem. This
873          * assumes that all the filesystem mounted within a share path have
874          * the same characteristics, which is likely but not guaranteed.
875          */
876
877         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
878
879         /*
880          * Print out the 'connected as' stuff here as we need
881          * to know the effective uid and gid we will be using
882          * (at least initially).
883          */
884
885         if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
886                 dbgtext( "%s (%s) ", get_remote_machine_name(),
887                          tsocket_address_string(conn->sconn->remote_address,
888                                                 talloc_tos()) );
889                 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
890                 dbgtext( "connect to service %s ",
891                          lp_const_servicename(snum) );
892                 dbgtext( "initially as user %s ",
893                          conn->session_info->unix_info->unix_name );
894                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
895                 dbgtext( "(pid %d)\n", (int)getpid() );
896         }
897
898         conn->tcon_done = true;
899         return NT_STATUS_OK;
900
901   err_root_exit:
902
903         TALLOC_FREE(smb_fname_cpath);
904         /* We must exit this function as root. */
905         if (geteuid() != 0) {
906                 change_to_root_user();
907         }
908         if (on_err_call_dis_hook) {
909                 /* Call VFS disconnect hook */
910                 SMB_VFS_DISCONNECT(conn);
911         }
912         return status;
913 }
914
915 /****************************************************************************
916  Make a connection to a service from SMB1. Internal interface.
917 ****************************************************************************/
918
919 static connection_struct *make_connection_smb1(struct smb_request *req,
920                                         NTTIME now,
921                                         int snum, struct user_struct *vuser,
922                                         const char *pdev,
923                                         NTSTATUS *pstatus)
924 {
925         const struct loadparm_substitution *lp_sub =
926                 loadparm_s3_global_substitution();
927         struct smbXsrv_tcon *tcon;
928         NTSTATUS status;
929         struct connection_struct *conn;
930
931         status = smb1srv_tcon_create(req->xconn, now, &tcon);
932         if (!NT_STATUS_IS_OK(status)) {
933                 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
934                          nt_errstr(status)));
935                 *pstatus = status;
936                 return NULL;
937         }
938
939         conn = conn_new(req->sconn);
940         if (!conn) {
941                 TALLOC_FREE(tcon);
942
943                 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
944                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
945                 return NULL;
946         }
947
948         conn->cnum = tcon->global->tcon_wire_id;
949         conn->tcon = tcon;
950
951         *pstatus = make_connection_snum(req->xconn,
952                                         conn,
953                                         snum,
954                                         vuser,
955                                         pdev);
956         if (!NT_STATUS_IS_OK(*pstatus)) {
957                 conn_free(conn);
958                 TALLOC_FREE(tcon);
959                 return NULL;
960         }
961
962         tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn));
963         if (tcon->global->share_name == NULL) {
964                 conn_free(conn);
965                 TALLOC_FREE(tcon);
966                 *pstatus = NT_STATUS_NO_MEMORY;
967                 return NULL;
968         }
969         tcon->global->session_global_id =
970                 vuser->session->global->session_global_id;
971
972         tcon->compat = talloc_move(tcon, &conn);
973         tcon->status = NT_STATUS_OK;
974
975         *pstatus = smbXsrv_tcon_update(tcon);
976         if (!NT_STATUS_IS_OK(*pstatus)) {
977                 TALLOC_FREE(tcon);
978                 return NULL;
979         }
980
981         return tcon->compat;
982 }
983
984 /****************************************************************************
985  Make a connection to a service from SMB2. External SMB2 interface.
986  We must set cnum before claiming connection.
987 ****************************************************************************/
988
989 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
990                                         struct smbXsrv_tcon *tcon,
991                                         int snum,
992                                         struct user_struct *vuser,
993                                         const char *pdev,
994                                         NTSTATUS *pstatus)
995 {
996         struct smbd_server_connection *sconn = req->sconn;
997         connection_struct *conn = conn_new(sconn);
998         if (!conn) {
999                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1000                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1001                 return NULL;
1002         }
1003
1004         conn->cnum = tcon->global->tcon_wire_id;
1005         conn->tcon = tcon;
1006
1007         *pstatus = make_connection_snum(req->xconn,
1008                                         conn,
1009                                         snum,
1010                                         vuser,
1011                                         pdev);
1012         if (!NT_STATUS_IS_OK(*pstatus)) {
1013                 conn_free(conn);
1014                 return NULL;
1015         }
1016         return conn;
1017 }
1018
1019 /****************************************************************************
1020  Make a connection to a service. External SMB1 interface.
1021  *
1022  * @param service 
1023 ****************************************************************************/
1024
1025 connection_struct *make_connection(struct smb_request *req,
1026                                    NTTIME now,
1027                                    const char *service_in,
1028                                    const char *pdev, uint64_t vuid,
1029                                    NTSTATUS *status)
1030 {
1031         struct smbd_server_connection *sconn = req->sconn;
1032         const struct loadparm_substitution *lp_sub =
1033                 loadparm_s3_global_substitution();
1034         uid_t euid;
1035         struct user_struct *vuser = NULL;
1036         char *service = NULL;
1037         fstring dev;
1038         int snum = -1;
1039
1040         fstrcpy(dev, pdev);
1041
1042         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1043          * root. */
1044         if (!non_root_mode() && (euid = geteuid()) != 0) {
1045                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1046                          "(%u)\n", (unsigned int)euid ));
1047                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1048         }
1049
1050         if (conn_num_open(sconn) > 2047) {
1051                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1052                 return NULL;
1053         }
1054
1055         vuser = get_valid_user_struct(sconn, vuid);
1056         if (!vuser) {
1057                 DEBUG(1,("make_connection: refusing to connect with "
1058                          "no session setup\n"));
1059                 *status = NT_STATUS_ACCESS_DENIED;
1060                 return NULL;
1061         }
1062
1063         /* Logic to try and connect to the correct [homes] share, preferably
1064            without too many getpwnam() lookups.  This is particulary nasty for
1065            winbind usernames, where the share name isn't the same as unix
1066            username.
1067
1068            The snum of the homes share is stored on the vuser at session setup
1069            time.
1070         */
1071
1072         if (strequal(service_in,HOMES_NAME)) {
1073                 if (vuser->homes_snum == -1) {
1074                         DEBUG(2, ("[homes] share not available for "
1075                                   "this user because it was not found "
1076                                   "or created at session setup "
1077                                   "time\n"));
1078                         *status = NT_STATUS_BAD_NETWORK_NAME;
1079                         return NULL;
1080                 }
1081                 DEBUG(5, ("making a connection to [homes] service "
1082                           "created at session setup time\n"));
1083                 return make_connection_smb1(req, now,
1084                                             vuser->homes_snum,
1085                                             vuser,
1086                                             dev, status);
1087         } else if ((vuser->homes_snum != -1)
1088                    && strequal(service_in,
1089                                lp_const_servicename(vuser->homes_snum))) {
1090                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1091                           "created at session setup time\n", service_in));
1092                 return make_connection_smb1(req, now,
1093                                             vuser->homes_snum,
1094                                             vuser,
1095                                             dev, status);
1096         }
1097
1098         service = talloc_strdup(talloc_tos(), service_in);
1099         if (!service) {
1100                 *status = NT_STATUS_NO_MEMORY;
1101                 return NULL;
1102         }
1103
1104         if (!strlower_m(service)) {
1105                 DEBUG(2, ("strlower_m %s failed\n", service));
1106                 *status = NT_STATUS_INVALID_PARAMETER;
1107                 return NULL;
1108         }
1109
1110         snum = find_service(talloc_tos(), service, &service);
1111         if (!service) {
1112                 *status = NT_STATUS_NO_MEMORY;
1113                 return NULL;
1114         }
1115
1116         if (snum < 0) {
1117                 if (strequal(service,"IPC$") ||
1118                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1119                         DEBUG(3,("refusing IPC connection to %s\n", service));
1120                         *status = NT_STATUS_ACCESS_DENIED;
1121                         return NULL;
1122                 }
1123
1124                 DEBUG(3,("%s (%s) couldn't find service %s\n",
1125                         get_remote_machine_name(),
1126                         tsocket_address_string(
1127                                 sconn->remote_address, talloc_tos()),
1128                         service));
1129                 *status = NT_STATUS_BAD_NETWORK_NAME;
1130                 return NULL;
1131         }
1132
1133         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1134         if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0'))  {
1135                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1136                           "(pointing to %s)\n", 
1137                         service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
1138                 *status = NT_STATUS_BAD_NETWORK_NAME;
1139                 return NULL;
1140         }
1141
1142         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1143
1144         return make_connection_smb1(req, now, snum, vuser,
1145                                     dev, status);
1146 }
1147
1148 /****************************************************************************
1149  Close a cnum.
1150 ****************************************************************************/
1151
1152 void close_cnum(connection_struct *conn, uint64_t vuid)
1153 {
1154         char rootpath[2] = { '/', '\0'};
1155         struct smb_filename root_fname = { .base_name = rootpath };
1156         const struct loadparm_substitution *lp_sub =
1157                 loadparm_s3_global_substitution();
1158
1159         file_close_conn(conn);
1160
1161         change_to_root_user();
1162
1163         DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1164                                  get_remote_machine_name(),
1165                                  tsocket_address_string(conn->sconn->remote_address,
1166                                                         talloc_tos()),
1167                                  lp_const_servicename(SNUM(conn))));
1168
1169         /* make sure we leave the directory available for unmount */
1170         vfs_ChDir(conn, &root_fname);
1171
1172         /* Call VFS disconnect hook */
1173         SMB_VFS_DISCONNECT(conn);
1174
1175         /* execute any "postexec = " line */
1176         if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
1177             change_to_user_and_service(conn, vuid))  {
1178                 char *cmd = talloc_sub_full(talloc_tos(),
1179                                         lp_const_servicename(SNUM(conn)),
1180                                         conn->session_info->unix_info->unix_name,
1181                                         conn->connectpath,
1182                                         conn->session_info->unix_token->gid,
1183                                         conn->session_info->unix_info->sanitized_username,
1184                                         conn->session_info->info->domain_name,
1185                                         lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1186                 smbrun(cmd, NULL, NULL);
1187                 TALLOC_FREE(cmd);
1188                 change_to_root_user();
1189         }
1190
1191         change_to_root_user();
1192         /* execute any "root postexec = " line */
1193         if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)))  {
1194                 char *cmd = talloc_sub_full(talloc_tos(),
1195                                         lp_const_servicename(SNUM(conn)),
1196                                         conn->session_info->unix_info->unix_name,
1197                                         conn->connectpath,
1198                                         conn->session_info->unix_token->gid,
1199                                         conn->session_info->unix_info->sanitized_username,
1200                                         conn->session_info->info->domain_name,
1201                                         lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1202                 smbrun(cmd, NULL, NULL);
1203                 TALLOC_FREE(cmd);
1204         }
1205
1206         conn_free(conn);
1207 }