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