s3:lib/afs move afs.c to common lib dir
[samba.git] / source3 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
4    Copyright (C) Andrew Tridgell 1992-1998
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "system/passwd.h" /* uid_wrapper */
23 #include "../lib/tsocket/tsocket.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../librpc/gen_ndr/netlogon.h"
27 #include "../libcli/security/security.h"
28 #include "printing/pcap.h"
29 #include "passdb/lookup_sid.h"
30 #include "auth.h"
31 #include "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 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 smbd_server_connection *sconn,
521                                         connection_struct *conn,
522                                         int snum, struct user_struct *vuser,
523                                         const char *pdev)
524 {
525         struct smb_filename *smb_fname_cpath = NULL;
526         fstring dev;
527         int ret;
528         bool on_err_call_dis_hook = false;
529         uid_t effuid;
530         gid_t effgid;
531         NTSTATUS status;
532
533         fstrcpy(dev, pdev);
534
535         status = share_sanity_checks(sconn->remote_address,
536                                        sconn->remote_hostname,
537                                        snum,
538                                        dev);
539         if (NT_STATUS_IS_ERR(status)) {
540                 goto err_root_exit;
541         }
542
543         conn->params->service = snum;
544
545         status = create_connection_session_info(sconn,
546                 conn, snum, vuser->session_info,
547                 &conn->session_info);
548
549         if (!NT_STATUS_IS_OK(status)) {
550                 DEBUG(1, ("create_connection_session_info failed: %s\n",
551                           nt_errstr(status)));
552                 goto err_root_exit;
553         }
554
555         if (lp_guest_only(snum)) {
556                 conn->force_user = true;
557         }
558
559         conn->num_files_open = 0;
560         conn->lastused = conn->lastused_count = time(NULL);
561         conn->printer = (strncmp(dev,"LPT",3) == 0);
562         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
563                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
564
565         /* Case options for the share. */
566         if (lp_case_sensitive(snum) == Auto) {
567                 /* We will be setting this per packet. Set to be case
568                  * insensitive for now. */
569                 conn->case_sensitive = False;
570         } else {
571                 conn->case_sensitive = (bool)lp_case_sensitive(snum);
572         }
573
574         conn->case_preserve = lp_preserve_case(snum);
575         conn->short_case_preserve = lp_short_preserve_case(snum);
576
577         conn->encrypt_level = lp_smb_encrypt(snum);
578
579         conn->veto_list = NULL;
580         conn->hide_list = NULL;
581         conn->veto_oplock_list = NULL;
582         conn->aio_write_behind_list = NULL;
583
584         conn->read_only = lp_read_only(SNUM(conn));
585
586         status = set_conn_force_user_group(conn, snum);
587         if (!NT_STATUS_IS_OK(status)) {
588                 goto err_root_exit;
589         }
590
591         conn->vuid = vuser->vuid;
592
593         {
594                 char *s = talloc_sub_advanced(talloc_tos(),
595                                         lp_servicename(talloc_tos(), SNUM(conn)),
596                                         conn->session_info->unix_info->unix_name,
597                                         conn->connectpath,
598                                         conn->session_info->unix_token->gid,
599                                         conn->session_info->unix_info->sanitized_username,
600                                         conn->session_info->info->domain_name,
601                                         lp_path(talloc_tos(), snum));
602                 if (!s) {
603                         status = NT_STATUS_NO_MEMORY;
604                         goto err_root_exit;
605                 }
606
607                 if (!set_conn_connectpath(conn,s)) {
608                         TALLOC_FREE(s);
609                         status = NT_STATUS_NO_MEMORY;
610                         goto err_root_exit;
611                 }
612                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
613                          lp_servicename(talloc_tos(), snum)));
614                 TALLOC_FREE(s);
615         }
616
617         /*
618          * Set up the share security descriptor.
619          * NOTE - we use the *INCOMING USER* session_info
620          * here, as does (indirectly) change_to_user(),
621          * which can be called on any incoming packet.
622          * This way we set up the share access based
623          * on the authenticated user, not the forced
624          * user. See bug:
625          *
626          * https://bugzilla.samba.org/show_bug.cgi?id=9878
627          */
628
629         status = check_user_share_access(conn,
630                                         vuser->session_info,
631                                         &conn->share_access,
632                                         &conn->read_only);
633         if (!NT_STATUS_IS_OK(status)) {
634                 goto err_root_exit;
635         }
636
637         /* Initialise VFS function pointers */
638
639         if (!smbd_vfs_init(conn)) {
640                 DEBUG(0, ("vfs_init failed for service %s\n",
641                           lp_servicename(talloc_tos(), snum)));
642                 status = NT_STATUS_BAD_NETWORK_NAME;
643                 goto err_root_exit;
644         }
645
646 /* ROOT Activities: */
647         /* explicitly check widelinks here so that we can correctly warn
648          * in the logs. */
649         widelinks_warning(snum);
650
651         /*
652          * Enforce the max connections parameter.
653          */
654
655         if ((lp_max_connections(snum) > 0)
656             && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
657                 lp_max_connections(snum))) {
658
659                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
660                           lp_max_connections(snum),
661                           lp_servicename(talloc_tos(), snum)));
662                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
663                 goto err_root_exit;
664         }
665
666         /* Invoke VFS make connection hook - this must be the first
667            filesystem operation that we do. */
668
669         if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
670                             conn->session_info->unix_info->unix_name) < 0) {
671                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
672                 status = NT_STATUS_UNSUCCESSFUL;
673                 goto err_root_exit;
674         }
675
676         /* Any error exit after here needs to call the disconnect hook. */
677         on_err_call_dis_hook = true;
678
679         if ((!conn->printer) && (!conn->ipc) &&
680             lp_change_notify(conn->params)) {
681                 if (sconn->notify_ctx == NULL) {
682                         sconn->notify_ctx = notify_init(
683                                 sconn, sconn->msg_ctx, sconn->ev_ctx);
684                 }
685                 if (sconn->sys_notify_ctx == NULL) {
686                         sconn->sys_notify_ctx = sys_notify_context_create(
687                                 sconn, sconn->ev_ctx);
688                 }
689         }
690
691         if (lp_kernel_oplocks(snum)) {
692                 init_kernel_oplocks(conn->sconn);
693         }
694
695         /*
696          * Fix compatibility issue pointed out by Volker.
697          * We pass the conn->connectpath to the preexec
698          * scripts as a parameter, so attempt to canonicalize
699          * it here before calling the preexec scripts.
700          * We ignore errors here, as it is possible that
701          * the conn->connectpath doesn't exist yet and
702          * the preexec scripts will create them.
703          */
704
705         (void)canonicalize_connect_path(conn);
706
707         /* Preexecs are done here as they might make the dir we are to ChDir
708          * to below */
709         /* execute any "root preexec = " line */
710         if (*lp_root_preexec(talloc_tos(), snum)) {
711                 char *cmd = talloc_sub_advanced(talloc_tos(),
712                                         lp_servicename(talloc_tos(), SNUM(conn)),
713                                         conn->session_info->unix_info->unix_name,
714                                         conn->connectpath,
715                                         conn->session_info->unix_token->gid,
716                                         conn->session_info->unix_info->sanitized_username,
717                                         conn->session_info->info->domain_name,
718                                         lp_root_preexec(talloc_tos(), snum));
719                 DEBUG(5,("cmd=%s\n",cmd));
720                 ret = smbrun(cmd,NULL);
721                 TALLOC_FREE(cmd);
722                 if (ret != 0 && lp_root_preexec_close(snum)) {
723                         DEBUG(1,("root preexec gave %d - failing "
724                                  "connection\n", ret));
725                         status = NT_STATUS_ACCESS_DENIED;
726                         goto err_root_exit;
727                 }
728         }
729
730 /* USER Activites: */
731         if (!change_to_user(conn, conn->vuid)) {
732                 /* No point continuing if they fail the basic checks */
733                 DEBUG(0,("Can't become connected user!\n"));
734                 status = NT_STATUS_LOGON_FAILURE;
735                 goto err_root_exit;
736         }
737
738         effuid = geteuid();
739         effgid = getegid();
740
741         /* Remember that a different vuid can connect later without these
742          * checks... */
743
744         /* Preexecs are done here as they might make the dir we are to ChDir
745          * to below */
746
747         /* execute any "preexec = " line */
748         if (*lp_preexec(talloc_tos(), snum)) {
749                 char *cmd = talloc_sub_advanced(talloc_tos(),
750                                         lp_servicename(talloc_tos(), SNUM(conn)),
751                                         conn->session_info->unix_info->unix_name,
752                                         conn->connectpath,
753                                         conn->session_info->unix_token->gid,
754                                         conn->session_info->unix_info->sanitized_username,
755                                         conn->session_info->info->domain_name,
756                                         lp_preexec(talloc_tos(), snum));
757                 ret = smbrun(cmd,NULL);
758                 TALLOC_FREE(cmd);
759                 if (ret != 0 && lp_preexec_close(snum)) {
760                         DEBUG(1,("preexec gave %d - failing connection\n",
761                                  ret));
762                         status = NT_STATUS_ACCESS_DENIED;
763                         goto err_root_exit;
764                 }
765         }
766
767 #ifdef WITH_FAKE_KASERVER
768         if (lp_afs_share(snum)) {
769                 afs_login(conn);
770         }
771 #endif
772
773         /*
774          * we've finished with the user stuff - go back to root
775          * so the SMB_VFS_STAT call will only fail on path errors,
776          * not permission problems.
777          */
778         change_to_root_user();
779 /* ROOT Activites: */
780
781         /*
782          * If widelinks are disallowed we need to canonicalise the connect
783          * path here to ensure we don't have any symlinks in the
784          * connectpath. We will be checking all paths on this connection are
785          * below this directory. We must do this after the VFS init as we
786          * depend on the realpath() pointer in the vfs table. JRA.
787          */
788         if (!lp_widelinks(snum)) {
789                 if (!canonicalize_connect_path(conn)) {
790                         DEBUG(0, ("canonicalize_connect_path failed "
791                         "for service %s, path %s\n",
792                                 lp_servicename(talloc_tos(), snum),
793                                 conn->connectpath));
794                         status = NT_STATUS_BAD_NETWORK_NAME;
795                         goto err_root_exit;
796                 }
797         }
798
799         /* Add veto/hide lists */
800         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
801                 set_namearray( &conn->veto_list,
802                                lp_veto_files(talloc_tos(), snum));
803                 set_namearray( &conn->hide_list,
804                                lp_hide_files(talloc_tos(), snum));
805                 set_namearray( &conn->veto_oplock_list,
806                                lp_veto_oplock_files(talloc_tos(), snum));
807                 set_namearray( &conn->aio_write_behind_list,
808                                 lp_aio_write_behind(talloc_tos(), snum));
809         }
810         smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
811                                               NULL, NULL);
812         if (smb_fname_cpath == NULL) {
813                 status = NT_STATUS_NO_MEMORY;
814                 goto err_root_exit;
815         }
816
817         /* win2000 does not check the permissions on the directory
818            during the tree connect, instead relying on permission
819            check during individual operations. To match this behaviour
820            I have disabled this chdir check (tridge) */
821         /* the alternative is just to check the directory exists */
822
823         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
824             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
825                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
826                         DEBUG(0,("'%s' is not a directory, when connecting to "
827                                  "[%s]\n", conn->connectpath,
828                                  lp_servicename(talloc_tos(), snum)));
829                 } else {
830                         DEBUG(0,("'%s' does not exist or permission denied "
831                                  "when connecting to [%s] Error was %s\n",
832                                  conn->connectpath,
833                                  lp_servicename(talloc_tos(), snum),
834                                  strerror(errno) ));
835                 }
836                 status = NT_STATUS_BAD_NETWORK_NAME;
837                 goto err_root_exit;
838         }
839         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
840
841         talloc_free(conn->origpath);
842         conn->origpath = talloc_strdup(conn, conn->connectpath);
843
844         /* Figure out the characteristics of the underlying filesystem. This
845          * assumes that all the filesystem mounted withing a share path have
846          * the same characteristics, which is likely but not guaranteed.
847          */
848
849         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
850
851         /*
852          * Print out the 'connected as' stuff here as we need
853          * to know the effective uid and gid we will be using
854          * (at least initially).
855          */
856
857         if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
858                 dbgtext( "%s (%s) ", get_remote_machine_name(),
859                          tsocket_address_string(conn->sconn->remote_address,
860                                                 talloc_tos()) );
861                 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
862                 dbgtext( "connect to service %s ",
863                          lp_servicename(talloc_tos(), snum) );
864                 dbgtext( "initially as user %s ",
865                          conn->session_info->unix_info->unix_name );
866                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
867                 dbgtext( "(pid %d)\n", (int)getpid() );
868         }
869
870         return status;
871
872   err_root_exit:
873
874         TALLOC_FREE(smb_fname_cpath);
875         /* We must exit this function as root. */
876         if (geteuid() != 0) {
877                 change_to_root_user();
878         }
879         if (on_err_call_dis_hook) {
880                 /* Call VFS disconnect hook */
881                 SMB_VFS_DISCONNECT(conn);
882         }
883         return status;
884 }
885
886 /****************************************************************************
887  Make a connection to a service from SMB1. Internal interface.
888 ****************************************************************************/
889
890 static connection_struct *make_connection_smb1(struct smbd_server_connection *sconn,
891                                         NTTIME now,
892                                         int snum, struct user_struct *vuser,
893                                         const char *pdev,
894                                         NTSTATUS *pstatus)
895 {
896         struct smbXsrv_tcon *tcon;
897         NTSTATUS status;
898         struct connection_struct *conn;
899
900         status = smb1srv_tcon_create(sconn->conn, now, &tcon);
901         if (!NT_STATUS_IS_OK(status)) {
902                 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
903                          nt_errstr(status)));
904                 *pstatus = status;
905                 return NULL;
906         }
907
908         conn = conn_new(sconn);
909         if (!conn) {
910                 TALLOC_FREE(tcon);
911
912                 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
913                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
914                 return NULL;
915         }
916
917         conn->cnum = tcon->global->tcon_wire_id;
918         conn->tcon = tcon;
919
920         *pstatus = make_connection_snum(sconn,
921                                         conn,
922                                         snum,
923                                         vuser,
924                                         pdev);
925         if (!NT_STATUS_IS_OK(*pstatus)) {
926                 conn_free(conn);
927                 TALLOC_FREE(tcon);
928                 return NULL;
929         }
930
931         tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
932         if (tcon->global->share_name == NULL) {
933                 conn_free(conn);
934                 TALLOC_FREE(tcon);
935                 *pstatus = NT_STATUS_NO_MEMORY;
936                 return NULL;
937         }
938         tcon->global->session_global_id =
939                 vuser->session->global->session_global_id;
940
941         tcon->compat = talloc_move(tcon, &conn);
942         tcon->status = NT_STATUS_OK;
943
944         *pstatus = smbXsrv_tcon_update(tcon);
945         if (!NT_STATUS_IS_OK(*pstatus)) {
946                 TALLOC_FREE(tcon);
947                 return NULL;
948         }
949
950         return tcon->compat;
951 }
952
953 /****************************************************************************
954  Make a connection to a service from SMB2. External SMB2 interface.
955  We must set cnum before claiming connection.
956 ****************************************************************************/
957
958 connection_struct *make_connection_smb2(struct smbd_server_connection *sconn,
959                                         struct smbXsrv_tcon *tcon,
960                                         int snum,
961                                         struct user_struct *vuser,
962                                         const char *pdev,
963                                         NTSTATUS *pstatus)
964 {
965         connection_struct *conn = conn_new(sconn);
966         if (!conn) {
967                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
968                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
969                 return NULL;
970         }
971
972         conn->cnum = tcon->global->tcon_wire_id;
973         conn->tcon = tcon;
974
975         *pstatus = make_connection_snum(sconn,
976                                         conn,
977                                         snum,
978                                         vuser,
979                                         pdev);
980         if (!NT_STATUS_IS_OK(*pstatus)) {
981                 conn_free(conn);
982                 return NULL;
983         }
984         return conn;
985 }
986
987 /****************************************************************************
988  Make a connection to a service. External SMB1 interface.
989  *
990  * @param service 
991 ****************************************************************************/
992
993 connection_struct *make_connection(struct smbd_server_connection *sconn,
994                                    NTTIME now,
995                                    const char *service_in,
996                                    const char *pdev, uint64_t vuid,
997                                    NTSTATUS *status)
998 {
999         uid_t euid;
1000         struct user_struct *vuser = NULL;
1001         char *service = NULL;
1002         fstring dev;
1003         int snum = -1;
1004
1005         fstrcpy(dev, pdev);
1006
1007         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1008          * root. */
1009         if (!non_root_mode() && (euid = geteuid()) != 0) {
1010                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1011                          "(%u)\n", (unsigned int)euid ));
1012                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1013         }
1014
1015         if (conn_num_open(sconn) > 2047) {
1016                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1017                 return NULL;
1018         }
1019
1020         vuser = get_valid_user_struct(sconn, vuid);
1021         if (!vuser) {
1022                 DEBUG(1,("make_connection: refusing to connect with "
1023                          "no session setup\n"));
1024                 *status = NT_STATUS_ACCESS_DENIED;
1025                 return NULL;
1026         }
1027
1028         /* Logic to try and connect to the correct [homes] share, preferably
1029            without too many getpwnam() lookups.  This is particulary nasty for
1030            winbind usernames, where the share name isn't the same as unix
1031            username.
1032
1033            The snum of the homes share is stored on the vuser at session setup
1034            time.
1035         */
1036
1037         if (strequal(service_in,HOMES_NAME)) {
1038                 if (vuser->homes_snum == -1) {
1039                         DEBUG(2, ("[homes] share not available for "
1040                                   "this user because it was not found "
1041                                   "or created at session setup "
1042                                   "time\n"));
1043                         *status = NT_STATUS_BAD_NETWORK_NAME;
1044                         return NULL;
1045                 }
1046                 DEBUG(5, ("making a connection to [homes] service "
1047                           "created at session setup time\n"));
1048                 return make_connection_smb1(sconn, now,
1049                                             vuser->homes_snum,
1050                                             vuser,
1051                                             dev, status);
1052         } else if ((vuser->homes_snum != -1)
1053                    && strequal(service_in,
1054                                lp_servicename(talloc_tos(), vuser->homes_snum))) {
1055                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1056                           "created at session setup time\n", service_in));
1057                 return make_connection_smb1(sconn, now,
1058                                             vuser->homes_snum,
1059                                             vuser,
1060                                             dev, status);
1061         }
1062
1063         service = talloc_strdup(talloc_tos(), service_in);
1064         if (!service) {
1065                 *status = NT_STATUS_NO_MEMORY;
1066                 return NULL;
1067         }
1068
1069         if (!strlower_m(service)) {
1070                 DEBUG(2, ("strlower_m %s failed\n", service));
1071                 *status = NT_STATUS_INVALID_PARAMETER;
1072                 return NULL;
1073         }
1074
1075         snum = find_service(talloc_tos(), service, &service);
1076         if (!service) {
1077                 *status = NT_STATUS_NO_MEMORY;
1078                 return NULL;
1079         }
1080
1081         if (snum < 0) {
1082                 if (strequal(service,"IPC$") ||
1083                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1084                         DEBUG(3,("refusing IPC connection to %s\n", service));
1085                         *status = NT_STATUS_ACCESS_DENIED;
1086                         return NULL;
1087                 }
1088
1089                 DEBUG(3,("%s (%s) couldn't find service %s\n",
1090                         get_remote_machine_name(),
1091                         tsocket_address_string(
1092                                 sconn->remote_address, talloc_tos()),
1093                         service));
1094                 *status = NT_STATUS_BAD_NETWORK_NAME;
1095                 return NULL;
1096         }
1097
1098         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1099         if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0'))  {
1100                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1101                           "(pointing to %s)\n", 
1102                         service, lp_msdfs_proxy(talloc_tos(), snum)));
1103                 *status = NT_STATUS_BAD_NETWORK_NAME;
1104                 return NULL;
1105         }
1106
1107         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1108
1109         return make_connection_smb1(sconn, now, snum, vuser,
1110                                     dev, status);
1111 }
1112
1113 /****************************************************************************
1114  Close a cnum.
1115 ****************************************************************************/
1116
1117 void close_cnum(connection_struct *conn, uint64_t vuid)
1118 {
1119         file_close_conn(conn);
1120
1121         if (!IS_IPC(conn)) {
1122                 dptr_closecnum(conn);
1123         }
1124
1125         change_to_root_user();
1126
1127         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1128                                  get_remote_machine_name(),
1129                                  tsocket_address_string(conn->sconn->remote_address,
1130                                                         talloc_tos()),
1131                                  lp_servicename(talloc_tos(), SNUM(conn))));
1132
1133         /* Call VFS disconnect hook */    
1134         SMB_VFS_DISCONNECT(conn);
1135
1136         /* make sure we leave the directory available for unmount */
1137         vfs_ChDir(conn, "/");
1138
1139         /* execute any "postexec = " line */
1140         if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1141             change_to_user(conn, vuid))  {
1142                 char *cmd = talloc_sub_advanced(talloc_tos(),
1143                                         lp_servicename(talloc_tos(), SNUM(conn)),
1144                                         conn->session_info->unix_info->unix_name,
1145                                         conn->connectpath,
1146                                         conn->session_info->unix_token->gid,
1147                                         conn->session_info->unix_info->sanitized_username,
1148                                         conn->session_info->info->domain_name,
1149                                         lp_postexec(talloc_tos(), SNUM(conn)));
1150                 smbrun(cmd,NULL);
1151                 TALLOC_FREE(cmd);
1152                 change_to_root_user();
1153         }
1154
1155         change_to_root_user();
1156         /* execute any "root postexec = " line */
1157         if (*lp_root_postexec(talloc_tos(), SNUM(conn)))  {
1158                 char *cmd = talloc_sub_advanced(talloc_tos(),
1159                                         lp_servicename(talloc_tos(), SNUM(conn)),
1160                                         conn->session_info->unix_info->unix_name,
1161                                         conn->connectpath,
1162                                         conn->session_info->unix_token->gid,
1163                                         conn->session_info->unix_info->sanitized_username,
1164                                         conn->session_info->info->domain_name,
1165                                         lp_root_postexec(talloc_tos(), SNUM(conn)));
1166                 smbrun(cmd,NULL);
1167                 TALLOC_FREE(cmd);
1168         }
1169
1170         conn_free(conn);
1171 }