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