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