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