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