Fix bug #8882 - Broken processing of %U with vfs_full_audit when force user is set.
[ddiss/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 "../lib/tsocket/tsocket.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../librpc/gen_ndr/netlogon.h"
26 #include "../libcli/security/security.h"
27 #include "printing/pcap.h"
28 #include "passdb/lookup_sid.h"
29 #include "auth.h"
30
31 extern userdom_struct current_user_info;
32
33 static bool canonicalize_connect_path(connection_struct *conn)
34 {
35         bool ret;
36         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
37         if (!resolved_name) {
38                 return false;
39         }
40         ret = set_conn_connectpath(conn,resolved_name);
41         SAFE_FREE(resolved_name);
42         return ret;
43 }
44
45 /****************************************************************************
46  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
47  absolute path stating in / and not ending in /.
48  Observent people will notice a similarity between this and check_path_syntax :-).
49 ****************************************************************************/
50
51 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
52 {
53         char *destname;
54         char *d;
55         const char *s = connectpath;
56         bool start_of_name_component = true;
57
58         if (connectpath == NULL || connectpath[0] == '\0') {
59                 return false;
60         }
61
62         /* Allocate for strlen + '\0' + possible leading '/' */
63         destname = (char *)SMB_MALLOC(strlen(connectpath) + 2);
64         if (!destname) {
65                 return false;
66         }
67         d = destname;
68
69         *d++ = '/'; /* Always start with root. */
70
71         while (*s) {
72                 if (*s == '/') {
73                         /* Eat multiple '/' */
74                         while (*s == '/') {
75                                 s++;
76                         }
77                         if ((d > destname + 1) && (*s != '\0')) {
78                                 *d++ = '/';
79                         }
80                         start_of_name_component = True;
81                         continue;
82                 }
83
84                 if (start_of_name_component) {
85                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
86                                 /* Uh oh - "/../" or "/..\0" ! */
87
88                                 /* Go past the ../ or .. */
89                                 if (s[2] == '/') {
90                                         s += 3;
91                                 } else {
92                                         s += 2; /* Go past the .. */
93                                 }
94
95                                 /* If  we just added a '/' - delete it */
96                                 if ((d > destname) && (*(d-1) == '/')) {
97                                         *(d-1) = '\0';
98                                         d--;
99                                 }
100
101                                 /* Are we at the start ? Can't go back further if so. */
102                                 if (d <= destname) {
103                                         *d++ = '/'; /* Can't delete root */
104                                         continue;
105                                 }
106                                 /* Go back one level... */
107                                 /* Decrement d first as d points to the *next* char to write into. */
108                                 for (d--; d > destname; d--) {
109                                         if (*d == '/') {
110                                                 break;
111                                         }
112                                 }
113                                 /* We're still at the start of a name component, just the previous one. */
114                                 continue;
115                         } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
116                                 /* Component of pathname can't be "." only - skip the '.' . */
117                                 if (s[1] == '/') {
118                                         s += 2;
119                                 } else {
120                                         s++;
121                                 }
122                                 continue;
123                         }
124                 }
125
126                 if (!(*s & 0x80)) {
127                         *d++ = *s++;
128                 } else {
129                         size_t siz;
130                         /* Get the size of the next MB character. */
131                         next_codepoint(s,&siz);
132                         switch(siz) {
133                                 case 5:
134                                         *d++ = *s++;
135                                         /*fall through*/
136                                 case 4:
137                                         *d++ = *s++;
138                                         /*fall through*/
139                                 case 3:
140                                         *d++ = *s++;
141                                         /*fall through*/
142                                 case 2:
143                                         *d++ = *s++;
144                                         /*fall through*/
145                                 case 1:
146                                         *d++ = *s++;
147                                         break;
148                                 default:
149                                         break;
150                         }
151                 }
152                 start_of_name_component = false;
153         }
154         *d = '\0';
155
156         /* And must not end in '/' */
157         if (d > destname + 1 && (*(d-1) == '/')) {
158                 *(d-1) = '\0';
159         }
160
161         DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
162                 lp_servicename(SNUM(conn)), destname ));
163
164         string_set(&conn->connectpath, destname);
165         SAFE_FREE(destname);
166         return true;
167 }
168
169 /****************************************************************************
170  Load parameters specific to a connection/service.
171 ****************************************************************************/
172
173 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
174 {
175         int snum;
176
177         if (!conn)  {
178                 last_conn = NULL;
179                 return(False);
180         }
181
182         conn->lastused_count++;
183
184         snum = SNUM(conn);
185
186         if (do_chdir &&
187             vfs_ChDir(conn,conn->connectpath) != 0 &&
188             vfs_ChDir(conn,conn->origpath) != 0) {
189                 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
190                          conn->connectpath, strerror(errno)));
191                 return(False);
192         }
193
194         if ((conn == last_conn) && (last_flags == flags)) {
195                 return(True);
196         }
197
198         last_conn = conn;
199         last_flags = flags;
200
201         /* Obey the client case sensitivity requests - only for clients that support it. */
202         switch (lp_casesensitive(snum)) {
203                 case Auto:
204                         {
205                                 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
206                                 enum remote_arch_types ra_type = get_remote_arch();
207                                 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
208                                         /* Client can't support per-packet case sensitive pathnames. */
209                                         conn->case_sensitive = False;
210                                 } else {
211                                         conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
212                                 }
213                         }
214                         break;
215                 case True:
216                         conn->case_sensitive = True;
217                         break;
218                 default:
219                         conn->case_sensitive = False;
220                         break;
221         }
222         return(True);
223 }
224
225 static int load_registry_service(const char *servicename)
226 {
227         if (!lp_registry_shares()) {
228                 return -1;
229         }
230
231         if ((servicename == NULL) || (*servicename == '\0')) {
232                 return -1;
233         }
234
235         if (strequal(servicename, GLOBAL_NAME)) {
236                 return -2;
237         }
238
239         if (!process_registry_service(servicename)) {
240                 return -1;
241         }
242
243         return lp_servicenumber(servicename);
244 }
245
246 void load_registry_shares(void)
247 {
248         DEBUG(8, ("load_registry_shares()\n"));
249         if (!lp_registry_shares()) {
250                 return;
251         }
252
253         process_registry_shares();
254
255         return;
256 }
257
258 /****************************************************************************
259  Add a home service. Returns the new service number or -1 if fail.
260 ****************************************************************************/
261
262 int add_home_service(const char *service, const char *username, const char *homedir)
263 {
264         int iHomeService;
265
266         if (!service || !homedir || homedir[0] == '\0')
267                 return -1;
268
269         if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
270                 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
271                         return -1;
272                 }
273         }
274
275         /*
276          * If this is a winbindd provided username, remove
277          * the domain component before adding the service.
278          * Log a warning if the "path=" parameter does not
279          * include any macros.
280          */
281
282         {
283                 const char *p = strchr(service,*lp_winbind_separator());
284
285                 /* We only want the 'user' part of the string */
286                 if (p) {
287                         service = p + 1;
288                 }
289         }
290
291         if (!lp_add_home(service, iHomeService, username, homedir)) {
292                 return -1;
293         }
294
295         return lp_servicenumber(service);
296
297 }
298
299 /**
300  * Find a service entry.
301  *
302  * @param service is modified (to canonical form??)
303  **/
304
305 int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
306 {
307         int iService;
308
309         if (!service_in) {
310                 return -1;
311         }
312
313         /* First make a copy. */
314         *p_service_out = talloc_strdup(ctx, service_in);
315         if (!*p_service_out) {
316                 return -1;
317         }
318
319         all_string_sub(*p_service_out,"\\","/",0);
320
321         iService = lp_servicenumber(*p_service_out);
322
323         /* now handle the special case of a home directory */
324         if (iService < 0) {
325                 char *phome_dir = get_user_home_dir(ctx, *p_service_out);
326
327                 if(!phome_dir) {
328                         /*
329                          * Try mapping the servicename, it may
330                          * be a Windows to unix mapped user name.
331                          */
332                         if(map_username(ctx, *p_service_out, p_service_out)) {
333                                 if (*p_service_out == NULL) {
334                                         /* Out of memory. */
335                                         return -1;
336                                 }
337                                 phome_dir = get_user_home_dir(
338                                                 ctx, *p_service_out);
339                         }
340                 }
341
342                 DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
343                         phome_dir?phome_dir:"(NULL)"));
344
345                 iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir);
346         }
347
348         /* If we still don't have a service, attempt to add it as a printer. */
349         if (iService < 0) {
350                 int iPrinterService;
351
352                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
353                         iPrinterService = load_registry_service(PRINTERS_NAME);
354                 }
355                 if (iPrinterService >= 0) {
356                         DEBUG(3,("checking whether %s is a valid printer name...\n",
357                                 *p_service_out));
358                         if (pcap_printername_ok(*p_service_out)) {
359                                 DEBUG(3,("%s is a valid printer name\n",
360                                         *p_service_out));
361                                 DEBUG(3,("adding %s as a printer service\n",
362                                         *p_service_out));
363                                 lp_add_printer(*p_service_out, iPrinterService);
364                                 iService = lp_servicenumber(*p_service_out);
365                                 if (iService < 0) {
366                                         DEBUG(0,("failed to add %s as a printer service!\n",
367                                                 *p_service_out));
368                                 }
369                         } else {
370                                 DEBUG(3,("%s is not a valid printer name\n",
371                                         *p_service_out));
372                         }
373                 }
374         }
375
376         /* Check for default vfs service?  Unsure whether to implement this */
377         if (iService < 0) {
378         }
379
380         if (iService < 0) {
381                 iService = load_registry_service(*p_service_out);
382         }
383
384         /* Is it a usershare service ? */
385         if (iService < 0 && *lp_usershare_path()) {
386                 /* Ensure the name is canonicalized. */
387                 strlower_m(*p_service_out);
388                 iService = load_usershare_service(*p_service_out);
389         }
390
391         /* just possibly it's a default service? */
392         if (iService < 0) {
393                 char *pdefservice = lp_defaultservice();
394                 if (pdefservice &&
395                                 *pdefservice &&
396                                 !strequal(pdefservice, *p_service_out)
397                                 && !strstr_m(*p_service_out,"..")) {
398                         /*
399                          * We need to do a local copy here as lp_defaultservice() 
400                          * returns one of the rotating lp_string buffers that
401                          * could get overwritten by the recursive find_service() call
402                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
403                          */
404                         char *defservice = talloc_strdup(ctx, pdefservice);
405
406                         if (!defservice) {
407                                 goto fail;
408                         }
409
410                         /* Disallow anything except explicit share names. */
411                         if (strequal(defservice,HOMES_NAME) ||
412                                         strequal(defservice, PRINTERS_NAME) ||
413                                         strequal(defservice, "IPC$")) {
414                                 TALLOC_FREE(defservice);
415                                 goto fail;
416                         }
417
418                         iService = find_service(ctx, defservice, p_service_out);
419                         if (!*p_service_out) {
420                                 TALLOC_FREE(defservice);
421                                 iService = -1;
422                                 goto fail;
423                         }
424                         if (iService >= 0) {
425                                 all_string_sub(*p_service_out, "_","/",0);
426                                 iService = lp_add_service(*p_service_out, iService);
427                         }
428                         TALLOC_FREE(defservice);
429                 }
430         }
431
432         if (iService >= 0) {
433                 if (!VALID_SNUM(iService)) {
434                         DEBUG(0,("Invalid snum %d for %s\n",iService,
435                                 *p_service_out));
436                         iService = -1;
437                 }
438         }
439
440   fail:
441
442         if (iService < 0) {
443                 DEBUG(3,("find_service() failed to find service %s\n",
444                         *p_service_out));
445         }
446
447         return (iService);
448 }
449
450
451 /****************************************************************************
452  do some basic sainity checks on the share.  
453  This function modifies dev, ecode.
454 ****************************************************************************/
455
456 static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
457                                     fstring dev)
458 {
459         if (!lp_snum_ok(snum) || 
460             !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
461                           client_id->name, client_id->addr)) {
462                 return NT_STATUS_ACCESS_DENIED;
463         }
464
465         if (dev[0] == '?' || !dev[0]) {
466                 if (lp_print_ok(snum)) {
467                         fstrcpy(dev,"LPT1:");
468                 } else if (strequal(lp_fstype(snum), "IPC")) {
469                         fstrcpy(dev, "IPC");
470                 } else {
471                         fstrcpy(dev,"A:");
472                 }
473         }
474
475         strupper_m(dev);
476
477         if (lp_print_ok(snum)) {
478                 if (!strequal(dev, "LPT1:")) {
479                         return NT_STATUS_BAD_DEVICE_TYPE;
480                 }
481         } else if (strequal(lp_fstype(snum), "IPC")) {
482                 if (!strequal(dev, "IPC")) {
483                         return NT_STATUS_BAD_DEVICE_TYPE;
484                 }
485         } else if (!strequal(dev, "A:")) {
486                 return NT_STATUS_BAD_DEVICE_TYPE;
487         }
488
489         /* Behave as a printer if we are supposed to */
490         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
491                 fstrcpy(dev, "LPT1:");
492         }
493
494         return NT_STATUS_OK;
495 }
496
497 /*
498  * Go through lookup_name etc to find the force'd group.  
499  *
500  * Create a new token from src_token, replacing the primary group sid with the
501  * one found.
502  */
503
504 static NTSTATUS find_forced_group(bool force_user,
505                                   int snum, const char *username,
506                                   struct dom_sid *pgroup_sid,
507                                   gid_t *pgid)
508 {
509         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
510         TALLOC_CTX *frame = talloc_stackframe();
511         struct dom_sid group_sid;
512         enum lsa_SidType type;
513         char *groupname;
514         bool user_must_be_member = False;
515         gid_t gid;
516
517         groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
518         if (groupname == NULL) {
519                 DEBUG(1, ("talloc_strdup failed\n"));
520                 result = NT_STATUS_NO_MEMORY;
521                 goto done;
522         }
523
524         if (groupname[0] == '+') {
525                 user_must_be_member = True;
526                 groupname += 1;
527         }
528
529         groupname = talloc_string_sub(talloc_tos(), groupname,
530                                       "%S", lp_servicename(snum));
531         if (groupname == NULL) {
532                 DEBUG(1, ("talloc_string_sub failed\n"));
533                 result = NT_STATUS_NO_MEMORY;
534                 goto done;
535         }
536
537         if (!lookup_name_smbconf(talloc_tos(), groupname,
538                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
539                          NULL, NULL, &group_sid, &type)) {
540                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
541                            groupname));
542                 goto done;
543         }
544
545         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
546             (type != SID_NAME_WKN_GRP)) {
547                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
548                            sid_type_lookup(type)));
549                 goto done;
550         }
551
552         if (!sid_to_gid(&group_sid, &gid)) {
553                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
554                            sid_string_dbg(&group_sid), groupname));
555                 goto done;
556         }
557
558         /*
559          * If the user has been forced and the forced group starts with a '+',
560          * then we only set the group to be the forced group if the forced
561          * user is a member of that group.  Otherwise, the meaning of the '+'
562          * would be ignored.
563          */
564
565         if (force_user && user_must_be_member) {
566                 if (user_in_group_sid(username, &group_sid)) {
567                         sid_copy(pgroup_sid, &group_sid);
568                         *pgid = gid;
569                         DEBUG(3,("Forced group %s for member %s\n",
570                                  groupname, username));
571                 } else {
572                         DEBUG(0,("find_forced_group: forced user %s is not a member "
573                                 "of forced group %s. Disallowing access.\n",
574                                 username, groupname ));
575                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
576                         goto done;
577                 }
578         } else {
579                 sid_copy(pgroup_sid, &group_sid);
580                 *pgid = gid;
581                 DEBUG(3,("Forced group %s\n", groupname));
582         }
583
584         result = NT_STATUS_OK;
585  done:
586         TALLOC_FREE(frame);
587         return result;
588 }
589
590 /****************************************************************************
591   Create an auth_serversupplied_info structure for a connection_struct
592 ****************************************************************************/
593
594 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
595                                               TALLOC_CTX *mem_ctx, int snum,
596                                               struct auth_serversupplied_info *vuid_serverinfo,
597                                               DATA_BLOB password,
598                                               struct auth_serversupplied_info **presult)
599 {
600         if (lp_guest_only(snum)) {
601                 return make_server_info_guest(mem_ctx, presult);
602         }
603
604         if (vuid_serverinfo != NULL) {
605
606                 struct auth_serversupplied_info *result;
607
608                 /*
609                  * This is the normal security != share case where we have a
610                  * valid vuid from the session setup.                 */
611
612                 if (vuid_serverinfo->guest) {
613                         if (!lp_guest_ok(snum)) {
614                                 DEBUG(2, ("guest user (from session setup) "
615                                           "not permitted to access this share "
616                                           "(%s)\n", lp_servicename(snum)));
617                                 return NT_STATUS_ACCESS_DENIED;
618                         }
619                 } else {
620                         if (!user_ok_token(vuid_serverinfo->unix_name,
621                                            vuid_serverinfo->info3->base.domain.string,
622                                            vuid_serverinfo->security_token, snum)) {
623                                 DEBUG(2, ("user '%s' (from session setup) not "
624                                           "permitted to access this share "
625                                           "(%s)\n",
626                                           vuid_serverinfo->unix_name,
627                                           lp_servicename(snum)));
628                                 return NT_STATUS_ACCESS_DENIED;
629                         }
630                 }
631
632                 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
633                 if (result == NULL) {
634                         return NT_STATUS_NO_MEMORY;
635                 }
636
637                 *presult = result;
638                 return NT_STATUS_OK;
639         }
640
641         if (lp_security() == SEC_SHARE) {
642
643                 fstring user;
644                 bool guest;
645
646                 /* add the sharename as a possible user name if we
647                    are in share mode security */
648
649                 add_session_user(sconn, lp_servicename(snum));
650
651                 /* shall we let them in? */
652
653                 if (!authorise_login(sconn, snum,user,password,&guest)) {
654                         DEBUG( 2, ( "Invalid username/password for [%s]\n",
655                                     lp_servicename(snum)) );
656                         return NT_STATUS_WRONG_PASSWORD;
657                 }
658
659                 return make_serverinfo_from_username(mem_ctx, user, guest,
660                                                      presult);
661         }
662
663         DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
664         return NT_STATUS_ACCESS_DENIED;
665 }
666
667 /****************************************************************************
668   set relavent user and group settings corresponding to force user/group
669   configuration for the given snum.
670 ****************************************************************************/
671
672 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
673 {
674         NTSTATUS status;
675
676         if (*lp_force_user(snum)) {
677
678                 /*
679                  * Replace conn->session_info with a completely faked up one
680                  * from the username we are forced into :-)
681                  */
682
683                 char *fuser;
684                 struct auth_serversupplied_info *forced_serverinfo;
685
686                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
687                                           lp_const_servicename(snum));
688                 if (fuser == NULL) {
689                         return NT_STATUS_NO_MEMORY;
690                 }
691
692                 status = make_serverinfo_from_username(
693                         conn, fuser, conn->session_info->guest,
694                         &forced_serverinfo);
695                 if (!NT_STATUS_IS_OK(status)) {
696                         return status;
697                 }
698
699                 /* We don't want to replace the original sanitized_username
700                    as it is the original user given in the connect attempt.
701                    This is used in '%U' substitutions. */
702                 TALLOC_FREE(forced_serverinfo->sanitized_username);
703                 forced_serverinfo->sanitized_username =
704                         talloc_move(forced_serverinfo,
705                                 &conn->session_info->sanitized_username);
706
707                 TALLOC_FREE(conn->session_info);
708                 conn->session_info = forced_serverinfo;
709
710                 conn->force_user = true;
711                 DEBUG(3,("Forced user %s\n", fuser));
712         }
713
714         /*
715          * If force group is true, then override
716          * any groupid stored for the connecting user.
717          */
718
719         if (*lp_force_group(snum)) {
720
721                 status = find_forced_group(
722                         conn->force_user, snum, conn->session_info->unix_name,
723                         &conn->session_info->security_token->sids[1],
724                         &conn->session_info->utok.gid);
725
726                 if (!NT_STATUS_IS_OK(status)) {
727                         return status;
728                 }
729
730                 /*
731                  * We need to cache this gid, to use within
732                  * change_to_user() separately from the conn->session_info
733                  * struct. We only use conn->session_info directly if
734                  * "force_user" was set.
735                  */
736                 conn->force_group_gid = conn->session_info->utok.gid;
737         }
738
739         return NT_STATUS_OK;
740 }
741
742 /****************************************************************************
743   Setup the share access mask for a connection.
744 ****************************************************************************/
745
746 static void create_share_access_mask(connection_struct *conn, int snum)
747 {
748         const struct security_token *token = conn->session_info->security_token;
749
750         share_access_check(token,
751                         lp_servicename(snum),
752                         MAXIMUM_ALLOWED_ACCESS,
753                         &conn->share_access);
754
755         if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
756                 conn->share_access |= SEC_FLAG_SYSTEM_SECURITY;
757         }
758         if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
759                 conn->share_access |= (SEC_RIGHTS_PRIV_RESTORE);
760         }
761         if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
762                 conn->share_access |= (SEC_RIGHTS_PRIV_BACKUP);
763         }
764         if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
765                 conn->share_access |= (SEC_STD_WRITE_OWNER);
766         }
767 }
768
769 /****************************************************************************
770   Make a connection, given the snum to connect to, and the vuser of the
771   connecting user if appropriate.
772 ****************************************************************************/
773
774 static connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
775                                         connection_struct *conn,
776                                         int snum, user_struct *vuser,
777                                         DATA_BLOB password,
778                                         const char *pdev,
779                                         NTSTATUS *pstatus)
780 {
781         struct smb_filename *smb_fname_cpath = NULL;
782         fstring dev;
783         int ret;
784         bool on_err_call_dis_hook = false;
785         bool claimed_connection = false;
786         uid_t effuid;
787         gid_t effgid;
788         NTSTATUS status;
789
790         fstrcpy(dev, pdev);
791
792         *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
793         if (NT_STATUS_IS_ERR(*pstatus)) {
794                 goto err_root_exit;
795         }
796
797         conn->params->service = snum;
798
799         status = create_connection_session_info(sconn,
800                 conn, snum, vuser ? vuser->session_info : NULL, password,
801                 &conn->session_info);
802
803         if (!NT_STATUS_IS_OK(status)) {
804                 DEBUG(1, ("create_connection_session_info failed: %s\n",
805                           nt_errstr(status)));
806                 *pstatus = status;
807                 goto err_root_exit;
808         }
809
810         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
811                 conn->force_user = true;
812         }
813
814         add_session_user(sconn, conn->session_info->unix_name);
815
816         conn->num_files_open = 0;
817         conn->lastused = conn->lastused_count = time(NULL);
818         conn->used = True;
819         conn->printer = (strncmp(dev,"LPT",3) == 0);
820         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
821                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
822
823         /* Case options for the share. */
824         if (lp_casesensitive(snum) == Auto) {
825                 /* We will be setting this per packet. Set to be case
826                  * insensitive for now. */
827                 conn->case_sensitive = False;
828         } else {
829                 conn->case_sensitive = (bool)lp_casesensitive(snum);
830         }
831
832         conn->case_preserve = lp_preservecase(snum);
833         conn->short_case_preserve = lp_shortpreservecase(snum);
834
835         conn->encrypt_level = lp_smb_encrypt(snum);
836
837         conn->veto_list = NULL;
838         conn->hide_list = NULL;
839         conn->veto_oplock_list = NULL;
840         conn->aio_write_behind_list = NULL;
841
842         conn->read_only = lp_readonly(SNUM(conn));
843
844         status = set_conn_force_user_group(conn, snum);
845         if (!NT_STATUS_IS_OK(status)) {
846                 *pstatus = status;
847                 return NULL;
848         }
849
850         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
851
852         {
853                 char *s = talloc_sub_advanced(talloc_tos(),
854                                         lp_servicename(SNUM(conn)),
855                                         conn->session_info->unix_name,
856                                         conn->connectpath,
857                                         conn->session_info->utok.gid,
858                                         conn->session_info->sanitized_username,
859                                         conn->session_info->info3->base.domain.string,
860                                         lp_pathname(snum));
861                 if (!s) {
862                         *pstatus = NT_STATUS_NO_MEMORY;
863                         goto err_root_exit;
864                 }
865
866                 if (!set_conn_connectpath(conn,s)) {
867                         TALLOC_FREE(s);
868                         *pstatus = NT_STATUS_NO_MEMORY;
869                         goto err_root_exit;
870                 }
871                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
872                          lp_servicename(snum)));
873                 TALLOC_FREE(s);
874         }
875
876         /*
877          * New code to check if there's a share security descripter
878          * added from NT server manager. This is done after the
879          * smb.conf checks are done as we need a uid and token. JRA.
880          *
881          */
882
883         create_share_access_mask(conn, snum);
884
885         if ((conn->share_access & FILE_WRITE_DATA) == 0) {
886                 if ((conn->share_access & FILE_READ_DATA) == 0) {
887                         /* No access, read or write. */
888                         DEBUG(0,("make_connection: connection to %s "
889                                  "denied due to security "
890                                  "descriptor.\n",
891                                  lp_servicename(snum)));
892                         *pstatus = NT_STATUS_ACCESS_DENIED;
893                         goto err_root_exit;
894                 } else {
895                         conn->read_only = True;
896                 }
897         }
898         /* Initialise VFS function pointers */
899
900         if (!smbd_vfs_init(conn)) {
901                 DEBUG(0, ("vfs_init failed for service %s\n",
902                           lp_servicename(snum)));
903                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
904                 goto err_root_exit;
905         }
906
907 /* ROOT Activities: */
908         /* explicitly check widelinks here so that we can correctly warn
909          * in the logs. */
910         widelinks_warning(snum);
911
912         /*
913          * Enforce the max connections parameter.
914          */
915
916         if ((lp_max_connections(snum) > 0)
917             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
918                 lp_max_connections(snum))) {
919
920                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
921                           lp_max_connections(snum), lp_servicename(snum)));
922                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
923                 goto err_root_exit;
924         }
925
926         /*
927          * Get us an entry in the connections db
928          */
929         if (!claim_connection(conn, lp_servicename(snum))) {
930                 DEBUG(1, ("Could not store connections entry\n"));
931                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
932                 goto err_root_exit;
933         }
934         claimed_connection = true;
935
936         /* Invoke VFS make connection hook - this must be the first
937            filesystem operation that we do. */
938
939         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
940                             conn->session_info->unix_name) < 0) {
941                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
942                 *pstatus = NT_STATUS_UNSUCCESSFUL;
943                 goto err_root_exit;
944         }
945
946         /* Any error exit after here needs to call the disconnect hook. */
947         on_err_call_dis_hook = true;
948
949         if ((!conn->printer) && (!conn->ipc)) {
950                 conn->notify_ctx = notify_init(conn,
951                                                sconn_server_id(sconn),
952                                                sconn->msg_ctx,
953                                                smbd_event_context(),
954                                                conn);
955         }
956
957         /*
958          * Fix compatibility issue pointed out by Volker.
959          * We pass the conn->connectpath to the preexec
960          * scripts as a parameter, so attempt to canonicalize
961          * it here before calling the preexec scripts.
962          * We ignore errors here, as it is possible that
963          * the conn->connectpath doesn't exist yet and
964          * the preexec scripts will create them.
965          */
966
967         (void)canonicalize_connect_path(conn);
968
969         /* Preexecs are done here as they might make the dir we are to ChDir
970          * to below */
971         /* execute any "root preexec = " line */
972         if (*lp_rootpreexec(snum)) {
973                 char *cmd = talloc_sub_advanced(talloc_tos(),
974                                         lp_servicename(SNUM(conn)),
975                                         conn->session_info->unix_name,
976                                         conn->connectpath,
977                                         conn->session_info->utok.gid,
978                                         conn->session_info->sanitized_username,
979                                         conn->session_info->info3->base.domain.string,
980                                         lp_rootpreexec(snum));
981                 DEBUG(5,("cmd=%s\n",cmd));
982                 ret = smbrun(cmd,NULL);
983                 TALLOC_FREE(cmd);
984                 if (ret != 0 && lp_rootpreexec_close(snum)) {
985                         DEBUG(1,("root preexec gave %d - failing "
986                                  "connection\n", ret));
987                         *pstatus = NT_STATUS_ACCESS_DENIED;
988                         goto err_root_exit;
989                 }
990         }
991
992 /* USER Activites: */
993         if (!change_to_user(conn, conn->vuid)) {
994                 /* No point continuing if they fail the basic checks */
995                 DEBUG(0,("Can't become connected user!\n"));
996                 *pstatus = NT_STATUS_LOGON_FAILURE;
997                 goto err_root_exit;
998         }
999
1000         effuid = geteuid();
1001         effgid = getegid();
1002
1003         /* Remember that a different vuid can connect later without these
1004          * checks... */
1005
1006         /* Preexecs are done here as they might make the dir we are to ChDir
1007          * to below */
1008
1009         /* execute any "preexec = " line */
1010         if (*lp_preexec(snum)) {
1011                 char *cmd = talloc_sub_advanced(talloc_tos(),
1012                                         lp_servicename(SNUM(conn)),
1013                                         conn->session_info->unix_name,
1014                                         conn->connectpath,
1015                                         conn->session_info->utok.gid,
1016                                         conn->session_info->sanitized_username,
1017                                         conn->session_info->info3->base.domain.string,
1018                                         lp_preexec(snum));
1019                 ret = smbrun(cmd,NULL);
1020                 TALLOC_FREE(cmd);
1021                 if (ret != 0 && lp_preexec_close(snum)) {
1022                         DEBUG(1,("preexec gave %d - failing connection\n",
1023                                  ret));
1024                         *pstatus = NT_STATUS_ACCESS_DENIED;
1025                         goto err_root_exit;
1026                 }
1027         }
1028
1029 #ifdef WITH_FAKE_KASERVER
1030         if (lp_afs_share(snum)) {
1031                 afs_login(conn);
1032         }
1033 #endif
1034
1035         /*
1036          * we've finished with the user stuff - go back to root
1037          * so the SMB_VFS_STAT call will only fail on path errors,
1038          * not permission problems.
1039          */
1040         change_to_root_user();
1041 /* ROOT Activites: */
1042
1043         /*
1044          * If widelinks are disallowed we need to canonicalise the connect
1045          * path here to ensure we don't have any symlinks in the
1046          * connectpath. We will be checking all paths on this connection are
1047          * below this directory. We must do this after the VFS init as we
1048          * depend on the realpath() pointer in the vfs table. JRA.
1049          */
1050         if (!lp_widelinks(snum)) {
1051                 if (!canonicalize_connect_path(conn)) {
1052                         DEBUG(0, ("canonicalize_connect_path failed "
1053                         "for service %s, path %s\n",
1054                                 lp_servicename(snum),
1055                                 conn->connectpath));
1056                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1057                         goto err_root_exit;
1058                 }
1059         }
1060
1061         /* Add veto/hide lists */
1062         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1063                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1064                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1065                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1066                 set_namearray( &conn->aio_write_behind_list,
1067                                 lp_aio_write_behind(snum));
1068         }
1069         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1070                                             NULL, NULL, &smb_fname_cpath);
1071         if (!NT_STATUS_IS_OK(status)) {
1072                 *pstatus = status;
1073                 goto err_root_exit;
1074         }
1075
1076         /* win2000 does not check the permissions on the directory
1077            during the tree connect, instead relying on permission
1078            check during individual operations. To match this behaviour
1079            I have disabled this chdir check (tridge) */
1080         /* the alternative is just to check the directory exists */
1081
1082         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1083             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1084                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1085                         DEBUG(0,("'%s' is not a directory, when connecting to "
1086                                  "[%s]\n", conn->connectpath,
1087                                  lp_servicename(snum)));
1088                 } else {
1089                         DEBUG(0,("'%s' does not exist or permission denied "
1090                                  "when connecting to [%s] Error was %s\n",
1091                                  conn->connectpath, lp_servicename(snum),
1092                                  strerror(errno) ));
1093                 }
1094                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1095                 goto err_root_exit;
1096         }
1097         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1098
1099         string_set(&conn->origpath,conn->connectpath);
1100
1101         /* Figure out the characteristics of the underlying filesystem. This
1102          * assumes that all the filesystem mounted withing a share path have
1103          * the same characteristics, which is likely but not guaranteed.
1104          */
1105
1106         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1107
1108         /*
1109          * Print out the 'connected as' stuff here as we need
1110          * to know the effective uid and gid we will be using
1111          * (at least initially).
1112          */
1113
1114         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1115                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1116                          conn->sconn->client_id.addr );
1117                 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1118                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1119                 dbgtext( "initially as user %s ",
1120                          conn->session_info->unix_name );
1121                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1122                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1123         }
1124
1125         return(conn);
1126
1127   err_root_exit:
1128         TALLOC_FREE(smb_fname_cpath);
1129         /* We must exit this function as root. */
1130         if (geteuid() != 0) {
1131                 change_to_root_user();
1132         }
1133         if (on_err_call_dis_hook) {
1134                 /* Call VFS disconnect hook */
1135                 SMB_VFS_DISCONNECT(conn);
1136         }
1137         if (claimed_connection) {
1138                 yield_connection(conn, lp_servicename(snum));
1139         }
1140         return NULL;
1141 }
1142
1143 /****************************************************************************
1144  Make a connection to a service from SMB1. Internal interface.
1145 ****************************************************************************/
1146
1147 static connection_struct *make_connection_smb1(struct smbd_server_connection *sconn,
1148                                         int snum, user_struct *vuser,
1149                                         DATA_BLOB password,
1150                                         const char *pdev,
1151                                         NTSTATUS *pstatus)
1152 {
1153         connection_struct *ret_conn = NULL;
1154         connection_struct *conn = conn_new(sconn);
1155         if (!conn) {
1156                 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
1157                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1158                 return NULL;
1159         }
1160         ret_conn = make_connection_snum(sconn,
1161                                         conn,
1162                                         snum,
1163                                         vuser,
1164                                         password,
1165                                         pdev,
1166                                         pstatus);
1167         if (ret_conn != conn) {
1168                 conn_free(conn);
1169                 return NULL;
1170         }
1171         return conn;
1172 }
1173
1174 /****************************************************************************
1175  Make a connection to a service from SMB2. External SMB2 interface.
1176  We must set cnum before claiming connection.
1177 ****************************************************************************/
1178
1179 connection_struct *make_connection_smb2(struct smbd_server_connection *sconn,
1180                                         struct smbd_smb2_tcon *tcon,
1181                                         user_struct *vuser,
1182                                         DATA_BLOB password,
1183                                         const char *pdev,
1184                                         NTSTATUS *pstatus)
1185 {
1186         connection_struct *ret_conn = NULL;
1187         connection_struct *conn = conn_new(sconn);
1188         if (!conn) {
1189                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1190                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1191                 return NULL;
1192         }
1193         conn->cnum = tcon->tid;
1194         ret_conn = make_connection_snum(sconn,
1195                                         conn,
1196                                         tcon->snum,
1197                                         vuser,
1198                                         password,
1199                                         pdev,
1200                                         pstatus);
1201         if (ret_conn != conn) {
1202                 conn_free(conn);
1203                 return NULL;
1204         }
1205         return conn;
1206 }
1207
1208 /****************************************************************************
1209  Make a connection to a service. External SMB1 interface.
1210  *
1211  * @param service 
1212 ****************************************************************************/
1213
1214 connection_struct *make_connection(struct smbd_server_connection *sconn,
1215                                    const char *service_in, DATA_BLOB password,
1216                                    const char *pdev, uint16 vuid,
1217                                    NTSTATUS *status)
1218 {
1219         uid_t euid;
1220         user_struct *vuser = NULL;
1221         char *service = NULL;
1222         fstring dev;
1223         int snum = -1;
1224
1225         fstrcpy(dev, pdev);
1226
1227         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1228          * root. */
1229         if (!non_root_mode() && (euid = geteuid()) != 0) {
1230                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1231                          "(%u)\n", (unsigned int)euid ));
1232                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1233         }
1234
1235         if (conn_num_open(sconn) > 2047) {
1236                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1237                 return NULL;
1238         }
1239
1240         if(lp_security() != SEC_SHARE) {
1241                 vuser = get_valid_user_struct(sconn, vuid);
1242                 if (!vuser) {
1243                         DEBUG(1,("make_connection: refusing to connect with "
1244                                  "no session setup\n"));
1245                         *status = NT_STATUS_ACCESS_DENIED;
1246                         return NULL;
1247                 }
1248         }
1249
1250         /* Logic to try and connect to the correct [homes] share, preferably
1251            without too many getpwnam() lookups.  This is particulary nasty for
1252            winbind usernames, where the share name isn't the same as unix
1253            username.
1254
1255            The snum of the homes share is stored on the vuser at session setup
1256            time.
1257         */
1258
1259         if (strequal(service_in,HOMES_NAME)) {
1260                 if(lp_security() != SEC_SHARE) {
1261                         DATA_BLOB no_pw = data_blob_null;
1262                         if (vuser->homes_snum == -1) {
1263                                 DEBUG(2, ("[homes] share not available for "
1264                                           "this user because it was not found "
1265                                           "or created at session setup "
1266                                           "time\n"));
1267                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1268                                 return NULL;
1269                         }
1270                         DEBUG(5, ("making a connection to [homes] service "
1271                                   "created at session setup time\n"));
1272                         return make_connection_smb1(sconn,
1273                                                     vuser->homes_snum,
1274                                                     vuser, no_pw, 
1275                                                     dev, status);
1276                 } else {
1277                         /* Security = share. Try with
1278                          * current_user_info.smb_name as the username.  */
1279                         if (*current_user_info.smb_name) {
1280                                 char *unix_username = NULL;
1281                                 (void)map_username(talloc_tos(),
1282                                                 current_user_info.smb_name,
1283                                                 &unix_username);
1284                                 snum = find_service(talloc_tos(),
1285                                                 unix_username,
1286                                                 &unix_username);
1287                                 if (!unix_username) {
1288                                         *status = NT_STATUS_NO_MEMORY;
1289                                 }
1290                                 return NULL;
1291                         }
1292                         if (snum != -1) {
1293                                 DEBUG(5, ("making a connection to 'homes' "
1294                                           "service %s based on "
1295                                           "security=share\n", service_in));
1296                                 return make_connection_smb1(sconn,
1297                                                             snum, NULL,
1298                                                             password,
1299                                                             dev, status);
1300                         }
1301                 }
1302         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1303                    && strequal(service_in,
1304                                lp_servicename(vuser->homes_snum))) {
1305                 DATA_BLOB no_pw = data_blob_null;
1306                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1307                           "created at session setup time\n", service_in));
1308                 return make_connection_smb1(sconn,
1309                                             vuser->homes_snum,
1310                                             vuser, no_pw, 
1311                                             dev, status);
1312         }
1313
1314         service = talloc_strdup(talloc_tos(), service_in);
1315         if (!service) {
1316                 *status = NT_STATUS_NO_MEMORY;
1317                 return NULL;
1318         }
1319
1320         strlower_m(service);
1321
1322         snum = find_service(talloc_tos(), service, &service);
1323         if (!service) {
1324                 *status = NT_STATUS_NO_MEMORY;
1325                 return NULL;
1326         }
1327
1328         if (snum < 0) {
1329                 if (strequal(service,"IPC$") ||
1330                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1331                         DEBUG(3,("refusing IPC connection to %s\n", service));
1332                         *status = NT_STATUS_ACCESS_DENIED;
1333                         return NULL;
1334                 }
1335
1336                 DEBUG(3,("%s (%s) couldn't find service %s\n",
1337                         get_remote_machine_name(),
1338                         tsocket_address_string(
1339                                 sconn->remote_address, talloc_tos()),
1340                         service));
1341                 *status = NT_STATUS_BAD_NETWORK_NAME;
1342                 return NULL;
1343         }
1344
1345         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1346         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1347                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1348                           "(pointing to %s)\n", 
1349                         service, lp_msdfs_proxy(snum)));
1350                 *status = NT_STATUS_BAD_NETWORK_NAME;
1351                 return NULL;
1352         }
1353
1354         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1355
1356         return make_connection_smb1(sconn, snum, vuser,
1357                                     password,
1358                                     dev, status);
1359 }
1360
1361 /****************************************************************************
1362  Close a cnum.
1363 ****************************************************************************/
1364
1365 void close_cnum(connection_struct *conn, uint16 vuid)
1366 {
1367         file_close_conn(conn);
1368
1369         if (!IS_IPC(conn)) {
1370                 dptr_closecnum(conn);
1371         }
1372
1373         change_to_root_user();
1374
1375         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1376                                  get_remote_machine_name(),
1377                                  conn->sconn->client_id.addr,
1378                                  lp_servicename(SNUM(conn))));
1379
1380         /* Call VFS disconnect hook */    
1381         SMB_VFS_DISCONNECT(conn);
1382
1383         yield_connection(conn, lp_servicename(SNUM(conn)));
1384
1385         /* make sure we leave the directory available for unmount */
1386         vfs_ChDir(conn, "/");
1387
1388         /* execute any "postexec = " line */
1389         if (*lp_postexec(SNUM(conn)) && 
1390             change_to_user(conn, vuid))  {
1391                 char *cmd = talloc_sub_advanced(talloc_tos(),
1392                                         lp_servicename(SNUM(conn)),
1393                                         conn->session_info->unix_name,
1394                                         conn->connectpath,
1395                                         conn->session_info->utok.gid,
1396                                         conn->session_info->sanitized_username,
1397                                         conn->session_info->info3->base.domain.string,
1398                                         lp_postexec(SNUM(conn)));
1399                 smbrun(cmd,NULL);
1400                 TALLOC_FREE(cmd);
1401                 change_to_root_user();
1402         }
1403
1404         change_to_root_user();
1405         /* execute any "root postexec = " line */
1406         if (*lp_rootpostexec(SNUM(conn)))  {
1407                 char *cmd = talloc_sub_advanced(talloc_tos(),
1408                                         lp_servicename(SNUM(conn)),
1409                                         conn->session_info->unix_name,
1410                                         conn->connectpath,
1411                                         conn->session_info->utok.gid,
1412                                         conn->session_info->sanitized_username,
1413                                         conn->session_info->info3->base.domain.string,
1414                                         lp_rootpostexec(SNUM(conn)));
1415                 smbrun(cmd,NULL);
1416                 TALLOC_FREE(cmd);
1417         }
1418
1419         conn_free(conn);
1420 }