Make use of talloc_pool in the main codepaths. Remove the sub-contexts.
[kai/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
361         all_string_sub(service,"\\","/",0);
362
363         iService = lp_servicenumber(service);
364
365         /* now handle the special case of a home directory */
366         if (iService < 0) {
367                 char *phome_dir = get_user_home_dir(talloc_tos(), service);
368
369                 if(!phome_dir) {
370                         /*
371                          * Try mapping the servicename, it may
372                          * be a Windows to unix mapped user name.
373                          */
374                         if(map_username(service))
375                                 phome_dir = get_user_home_dir(
376                                         talloc_tos(), service);
377                 }
378
379                 DEBUG(3,("checking for home directory %s gave %s\n",service,
380                         phome_dir?phome_dir:"(NULL)"));
381
382                 iService = add_home_service(service,service /* 'username' */, phome_dir);
383         }
384
385         /* If we still don't have a service, attempt to add it as a printer. */
386         if (iService < 0) {
387                 int iPrinterService;
388
389                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
390                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
391                         if (pcap_printername_ok(service)) {
392                                 DEBUG(3,("%s is a valid printer name\n", service));
393                                 DEBUG(3,("adding %s as a printer service\n", service));
394                                 lp_add_printer(service, iPrinterService);
395                                 iService = lp_servicenumber(service);
396                                 if (iService < 0) {
397                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
398                                 }
399                         } else {
400                                 DEBUG(3,("%s is not a valid printer name\n", service));
401                         }
402                 }
403         }
404
405         /* Check for default vfs service?  Unsure whether to implement this */
406         if (iService < 0) {
407         }
408
409         if (iService < 0) {
410                 iService = load_registry_service(service);
411         }
412
413         /* Is it a usershare service ? */
414         if (iService < 0 && *lp_usershare_path()) {
415                 /* Ensure the name is canonicalized. */
416                 strlower_m(service);
417                 iService = load_usershare_service(service);
418         }
419
420         /* just possibly it's a default service? */
421         if (iService < 0) {
422                 char *pdefservice = lp_defaultservice();
423                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
424                         /*
425                          * We need to do a local copy here as lp_defaultservice() 
426                          * returns one of the rotating lp_string buffers that
427                          * could get overwritten by the recursive find_service() call
428                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
429                          */
430                         char *defservice = SMB_STRDUP(pdefservice);
431
432                         if (!defservice) {
433                                 goto fail;
434                         }
435
436                         /* Disallow anything except explicit share names. */
437                         if (strequal(defservice,HOMES_NAME) ||
438                                         strequal(defservice, PRINTERS_NAME) ||
439                                         strequal(defservice, "IPC$")) {
440                                 SAFE_FREE(defservice);
441                                 goto fail;
442                         }
443
444                         iService = find_service(defservice);
445                         if (iService >= 0) {
446                                 all_string_sub(service, "_","/",0);
447                                 iService = lp_add_service(service, iService);
448                         }
449                         SAFE_FREE(defservice);
450                 }
451         }
452
453         if (iService >= 0) {
454                 if (!VALID_SNUM(iService)) {
455                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
456                         iService = -1;
457                 }
458         }
459
460   fail:
461
462         if (iService < 0)
463                 DEBUG(3,("find_service() failed to find service %s\n", service));
464
465         return (iService);
466 }
467
468
469 /****************************************************************************
470  do some basic sainity checks on the share.  
471  This function modifies dev, ecode.
472 ****************************************************************************/
473
474 static NTSTATUS share_sanity_checks(int snum, fstring dev) 
475 {
476         
477         if (!lp_snum_ok(snum) || 
478             !check_access(smbd_server_fd(), 
479                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
480                 return NT_STATUS_ACCESS_DENIED;
481         }
482
483         if (dev[0] == '?' || !dev[0]) {
484                 if (lp_print_ok(snum)) {
485                         fstrcpy(dev,"LPT1:");
486                 } else if (strequal(lp_fstype(snum), "IPC")) {
487                         fstrcpy(dev, "IPC");
488                 } else {
489                         fstrcpy(dev,"A:");
490                 }
491         }
492
493         strupper_m(dev);
494
495         if (lp_print_ok(snum)) {
496                 if (!strequal(dev, "LPT1:")) {
497                         return NT_STATUS_BAD_DEVICE_TYPE;
498                 }
499         } else if (strequal(lp_fstype(snum), "IPC")) {
500                 if (!strequal(dev, "IPC")) {
501                         return NT_STATUS_BAD_DEVICE_TYPE;
502                 }
503         } else if (!strequal(dev, "A:")) {
504                 return NT_STATUS_BAD_DEVICE_TYPE;
505         }
506
507         /* Behave as a printer if we are supposed to */
508         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
509                 fstrcpy(dev, "LPT1:");
510         }
511
512         return NT_STATUS_OK;
513 }
514
515 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
516 {
517         int snum = conn->params->service;
518         char *fuser, *found_username;
519         NTSTATUS result;
520
521         if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
522                                         lp_servicename(snum)))) {
523                 return NT_STATUS_NO_MEMORY;
524         }
525
526         result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
527                                             &conn->uid, &conn->gid, &found_username,
528                                             &conn->nt_user_token);
529         if (!NT_STATUS_IS_OK(result)) {
530                 return result;
531         }
532
533         fstrcpy(username, found_username);
534
535         TALLOC_FREE(fuser);
536         TALLOC_FREE(found_username);
537         return NT_STATUS_OK;
538 }
539
540 /*
541  * Go through lookup_name etc to find the force'd group.  
542  *
543  * Create a new token from src_token, replacing the primary group sid with the
544  * one found.
545  */
546
547 static NTSTATUS find_forced_group(bool force_user,
548                                   int snum, const char *username,
549                                   DOM_SID *pgroup_sid,
550                                   gid_t *pgid)
551 {
552         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
553         TALLOC_CTX *mem_ctx;
554         DOM_SID group_sid;
555         enum lsa_SidType type;
556         char *groupname;
557         bool user_must_be_member = False;
558         gid_t gid;
559
560         ZERO_STRUCTP(pgroup_sid);
561         *pgid = (gid_t)-1;
562
563         mem_ctx = talloc_new(NULL);
564         if (mem_ctx == NULL) {
565                 DEBUG(0, ("talloc_new failed\n"));
566                 return NT_STATUS_NO_MEMORY;
567         }
568
569         groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
570         if (groupname == NULL) {
571                 DEBUG(1, ("talloc_strdup failed\n"));
572                 result = NT_STATUS_NO_MEMORY;
573                 goto done;
574         }
575
576         if (groupname[0] == '+') {
577                 user_must_be_member = True;
578                 groupname += 1;
579         }
580
581         groupname = talloc_string_sub(mem_ctx, groupname,
582                                       "%S", lp_servicename(snum));
583
584         if (!lookup_name_smbconf(mem_ctx, groupname,
585                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
586                          NULL, NULL, &group_sid, &type)) {
587                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
588                            groupname));
589                 goto done;
590         }
591
592         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
593             (type != SID_NAME_WKN_GRP)) {
594                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
595                            sid_type_lookup(type)));
596                 goto done;
597         }
598
599         if (!sid_to_gid(&group_sid, &gid)) {
600                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
601                            sid_string_dbg(&group_sid), groupname));
602                 goto done;
603         }
604
605         /*
606          * If the user has been forced and the forced group starts with a '+',
607          * then we only set the group to be the forced group if the forced
608          * user is a member of that group.  Otherwise, the meaning of the '+'
609          * would be ignored.
610          */
611
612         if (force_user && user_must_be_member) {
613                 if (user_in_group_sid(username, &group_sid)) {
614                         sid_copy(pgroup_sid, &group_sid);
615                         *pgid = gid;
616                         DEBUG(3,("Forced group %s for member %s\n",
617                                  groupname, username));
618                 } else {
619                         DEBUG(0,("find_forced_group: forced user %s is not a member "
620                                 "of forced group %s. Disallowing access.\n",
621                                 username, groupname ));
622                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
623                         goto done;
624                 }
625         } else {
626                 sid_copy(pgroup_sid, &group_sid);
627                 *pgid = gid;
628                 DEBUG(3,("Forced group %s\n", groupname));
629         }
630
631         result = NT_STATUS_OK;
632  done:
633         TALLOC_FREE(mem_ctx);
634         return result;
635 }
636
637 /****************************************************************************
638   Make a connection, given the snum to connect to, and the vuser of the
639   connecting user if appropriate.
640 ****************************************************************************/
641
642 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
643                                                DATA_BLOB password, 
644                                                const char *pdev,
645                                                NTSTATUS *status)
646 {
647         struct passwd *pass = NULL;
648         bool guest = False;
649         connection_struct *conn;
650         SMB_STRUCT_STAT st;
651         fstring user;
652         fstring dev;
653         int ret;
654         char addr[INET6_ADDRSTRLEN];
655         bool on_err_call_dis_hook = false;
656
657         *user = 0;
658         fstrcpy(dev, pdev);
659         SET_STAT_INVALID(st);
660
661         if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
662                 return NULL;
663         }       
664
665         conn = conn_new();
666         if (!conn) {
667                 DEBUG(0,("Couldn't find free connection.\n"));
668                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
669                 return NULL;
670         }
671
672         conn->params->service = snum;
673         conn->nt_user_token = NULL;
674
675         if (lp_guest_only(snum)) {
676                 const char *guestname = lp_guestaccount();
677                 NTSTATUS status2;
678                 char *found_username = NULL;
679
680                 guest = True;
681                 pass = getpwnam_alloc(NULL, guestname);
682                 if (!pass) {
683                         DEBUG(0,("make_connection_snum: Invalid guest "
684                                  "account %s??\n",guestname));
685                         conn_free(conn);
686                         *status = NT_STATUS_NO_SUCH_USER;
687                         return NULL;
688                 }
689                 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
690                                                      &conn->uid, &conn->gid,
691                                                      &found_username,
692                                                      &conn->nt_user_token);
693                 if (!NT_STATUS_IS_OK(status2)) {
694                         TALLOC_FREE(pass);
695                         conn_free(conn);
696                         *status = status2;
697                         return NULL;
698                 }
699                 fstrcpy(user, found_username);
700                 string_set(&conn->user,user);
701                 conn->force_user = True;
702                 TALLOC_FREE(found_username);
703                 TALLOC_FREE(pass);
704                 DEBUG(3,("Guest only user %s\n",user));
705         } else if (vuser) {
706                 if (vuser->guest) {
707                         if (!lp_guest_ok(snum)) {
708                                 DEBUG(2, ("guest user (from session setup) "
709                                           "not permitted to access this share "
710                                           "(%s)\n", lp_servicename(snum)));
711                                       conn_free(conn);
712                                       *status = NT_STATUS_ACCESS_DENIED;
713                                       return NULL;
714                         }
715                 } else {
716                         if (!user_ok_token(vuser->user.unix_name,
717                                            vuser->nt_user_token, snum)) {
718                                 DEBUG(2, ("user '%s' (from session setup) not "
719                                           "permitted to access this share "
720                                           "(%s)\n", vuser->user.unix_name,
721                                           lp_servicename(snum)));
722                                 conn_free(conn);
723                                 *status = NT_STATUS_ACCESS_DENIED;
724                                 return NULL;
725                         }
726                 }
727                 conn->vuid = vuser->vuid;
728                 conn->uid = vuser->uid;
729                 conn->gid = vuser->gid;
730                 string_set(&conn->user,vuser->user.unix_name);
731                 fstrcpy(user,vuser->user.unix_name);
732                 guest = vuser->guest; 
733         } else if (lp_security() == SEC_SHARE) {
734                 NTSTATUS status2;
735                 char *found_username = NULL;
736
737                 /* add it as a possible user name if we 
738                    are in share mode security */
739                 add_session_user(lp_servicename(snum));
740                 /* shall we let them in? */
741                 if (!authorise_login(snum,user,password,&guest)) {
742                         DEBUG( 2, ( "Invalid username/password for [%s]\n", 
743                                     lp_servicename(snum)) );
744                         conn_free(conn);
745                         *status = NT_STATUS_WRONG_PASSWORD;
746                         return NULL;
747                 }
748                 pass = Get_Pwnam_alloc(talloc_tos(), user);
749                 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
750                                                      &conn->uid, &conn->gid,
751                                                      &found_username,
752                                                      &conn->nt_user_token);
753                 TALLOC_FREE(pass);
754                 if (!NT_STATUS_IS_OK(status2)) {
755                         conn_free(conn);
756                         *status = status2;
757                         return NULL;
758                 }
759                 fstrcpy(user, found_username);
760                 string_set(&conn->user,user);
761                 TALLOC_FREE(found_username);
762                 conn->force_user = True;
763         } else {
764                 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
765                 conn_free(conn);
766                 *status = NT_STATUS_ACCESS_DENIED;
767                 return NULL;
768         }
769
770         add_session_user(user);
771
772         safe_strcpy(conn->client_address,
773                         client_addr(get_client_fd(),addr,sizeof(addr)), 
774                         sizeof(conn->client_address)-1);
775         conn->num_files_open = 0;
776         conn->lastused = conn->lastused_count = time(NULL);
777         conn->used = True;
778         conn->printer = (strncmp(dev,"LPT",3) == 0);
779         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
780                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
781         conn->dirptr = NULL;
782
783         /* Case options for the share. */
784         if (lp_casesensitive(snum) == Auto) {
785                 /* We will be setting this per packet. Set to be case
786                  * insensitive for now. */
787                 conn->case_sensitive = False;
788         } else {
789                 conn->case_sensitive = (bool)lp_casesensitive(snum);
790         }
791
792         conn->case_preserve = lp_preservecase(snum);
793         conn->short_case_preserve = lp_shortpreservecase(snum);
794
795         conn->encrypt_level = lp_smb_encrypt(snum);
796
797         conn->veto_list = NULL;
798         conn->hide_list = NULL;
799         conn->veto_oplock_list = NULL;
800         conn->aio_write_behind_list = NULL;
801         string_set(&conn->dirpath,"");
802         string_set(&conn->user,user);
803
804         conn->read_only = lp_readonly(SNUM(conn));
805         conn->admin_user = False;
806
807         /*
808          * If force user is true, then store the given userid and the gid of
809          * the user we're forcing.
810          * For auxiliary groups see below.
811          */
812         
813         if (*lp_force_user(snum)) {
814                 NTSTATUS status2;
815
816                 status2 = find_forced_user(conn,
817                                 (vuser != NULL) && vuser->guest,
818                                 user);
819                 if (!NT_STATUS_IS_OK(status2)) {
820                         conn_free(conn);
821                         *status = status2;
822                         return NULL;
823                 }
824                 string_set(&conn->user,user);
825                 conn->force_user = True;
826                 DEBUG(3,("Forced user %s\n",user));       
827         }
828
829         /*
830          * If force group is true, then override
831          * any groupid stored for the connecting user.
832          */
833         
834         if (*lp_force_group(snum)) {
835                 NTSTATUS status2;
836                 DOM_SID group_sid;
837
838                 status2 = find_forced_group(conn->force_user,
839                                             snum, user,
840                                             &group_sid, &conn->gid);
841                 if (!NT_STATUS_IS_OK(status2)) {
842                         conn_free(conn);
843                         *status = status2;
844                         return NULL;
845                 }
846
847                 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
848
849                         /* Not force user and not security=share, but force
850                          * group. vuser has a token to copy */
851                         
852                         conn->nt_user_token = dup_nt_token(
853                                 NULL, vuser->nt_user_token);
854                         if (conn->nt_user_token == NULL) {
855                                 DEBUG(0, ("dup_nt_token failed\n"));
856                                 conn_free(conn);
857                                 *status = NT_STATUS_NO_MEMORY;
858                                 return NULL;
859                         }
860                 }
861
862                 /* If conn->nt_user_token is still NULL, we have
863                  * security=share. This means ignore the SID, as we had no
864                  * vuser to copy from */
865
866                 if (conn->nt_user_token != NULL) {
867                         /* Overwrite the primary group sid */
868                         sid_copy(&conn->nt_user_token->user_sids[1],
869                                  &group_sid);
870
871                 }
872                 conn->force_group = True;
873         }
874
875         if (conn->nt_user_token != NULL) {
876                 size_t i;
877
878                 /* We have a share-specific token from force [user|group].
879                  * This means we have to create the list of unix groups from
880                  * the list of sids. */
881
882                 conn->ngroups = 0;
883                 conn->groups = NULL;
884
885                 for (i=0; i<conn->nt_user_token->num_sids; i++) {
886                         gid_t gid;
887                         DOM_SID *sid = &conn->nt_user_token->user_sids[i];
888
889                         if (!sid_to_gid(sid, &gid)) {
890                                 DEBUG(10, ("Could not convert SID %s to gid, "
891                                            "ignoring it\n",
892                                            sid_string_dbg(sid)));
893                                 continue;
894                         }
895                         if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
896                                                 &conn->ngroups)) {
897                                 DEBUG(0, ("add_gid_to_array_unique failed\n"));
898                                 conn_free(conn);
899                                 *status = NT_STATUS_NO_MEMORY;
900                                 return NULL;
901                         }
902                 }
903         }
904
905         {
906                 char *s = talloc_sub_advanced(talloc_tos(),
907                                         lp_servicename(SNUM(conn)), conn->user,
908                                         conn->connectpath, conn->gid,
909                                         get_current_username(),
910                                         current_user_info.domain,
911                                         lp_pathname(snum));
912                 if (!s) {
913                         conn_free(conn);
914                         *status = NT_STATUS_NO_MEMORY;
915                         return NULL;
916                 }
917
918                 if (!set_conn_connectpath(conn,s)) {
919                         TALLOC_FREE(s);
920                         conn_free(conn);
921                         *status = NT_STATUS_NO_MEMORY;
922                         return NULL;
923                 }
924                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
925                          lp_servicename(snum)));
926                 TALLOC_FREE(s);
927         }
928
929         /*
930          * New code to check if there's a share security descripter
931          * added from NT server manager. This is done after the
932          * smb.conf checks are done as we need a uid and token. JRA.
933          *
934          */
935
936         {
937                 bool can_write = False;
938                 NT_USER_TOKEN *token = conn->nt_user_token ?
939                         conn->nt_user_token :
940                         (vuser ? vuser->nt_user_token : NULL);
941
942                 /*
943                  * I don't believe this can happen. But the
944                  * logic above is convoluted enough to confuse
945                  * automated checkers, so be sure. JRA.
946                  */
947
948                 if (token == NULL) {
949                         DEBUG(0,("make_connection: connection to %s "
950                                  "denied due to missing "
951                                  "NT token.\n",
952                                   lp_servicename(snum)));
953                         conn_free(conn);
954                         *status = NT_STATUS_ACCESS_DENIED;
955                         return NULL;
956                 }
957
958                 can_write = share_access_check(token,
959                                                     lp_servicename(snum),
960                                                     FILE_WRITE_DATA);
961
962                 if (!can_write) {
963                         if (!share_access_check(token,
964                                                 lp_servicename(snum),
965                                                 FILE_READ_DATA)) {
966                                 /* No access, read or write. */
967                                 DEBUG(0,("make_connection: connection to %s "
968                                          "denied due to security "
969                                          "descriptor.\n",
970                                           lp_servicename(snum)));
971                                 conn_free(conn);
972                                 *status = NT_STATUS_ACCESS_DENIED;
973                                 return NULL;
974                         } else {
975                                 conn->read_only = True;
976                         }
977                 }
978         }
979         /* Initialise VFS function pointers */
980
981         if (!smbd_vfs_init(conn)) {
982                 DEBUG(0, ("vfs_init failed for service %s\n",
983                           lp_servicename(snum)));
984                 conn_free(conn);
985                 *status = NT_STATUS_BAD_NETWORK_NAME;
986                 return NULL;
987         }
988
989         /*
990          * If widelinks are disallowed we need to canonicalise the connect
991          * path here to ensure we don't have any symlinks in the
992          * connectpath. We will be checking all paths on this connection are
993          * below this directory. We must do this after the VFS init as we
994          * depend on the realpath() pointer in the vfs table. JRA.
995          */
996         if (!lp_widelinks(snum)) {
997                 if (!canonicalize_connect_path(conn)) {
998                         DEBUG(0, ("canonicalize_connect_path failed "
999                         "for service %s, path %s\n",
1000                                 lp_servicename(snum),
1001                                 conn->connectpath));
1002                         conn_free(conn);
1003                         *status = NT_STATUS_BAD_NETWORK_NAME;
1004                         return NULL;
1005                 }
1006         }
1007
1008         if ((!conn->printer) && (!conn->ipc)) {
1009                 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
1010                                                smbd_messaging_context(),
1011                                                smbd_event_context(),
1012                                                conn);
1013         }
1014
1015 /* ROOT Activities: */  
1016         /*
1017          * Enforce the max connections parameter.
1018          */
1019
1020         if ((lp_max_connections(snum) > 0)
1021             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1022                 lp_max_connections(snum))) {
1023
1024                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1025                           lp_max_connections(snum), lp_servicename(snum)));
1026                 conn_free(conn);
1027                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1028                 return NULL;
1029         }  
1030
1031         /*
1032          * Get us an entry in the connections db
1033          */
1034         if (!claim_connection(conn, lp_servicename(snum), 0)) {
1035                 DEBUG(1, ("Could not store connections entry\n"));
1036                 conn_free(conn);
1037                 *status = NT_STATUS_INTERNAL_DB_ERROR;
1038                 return NULL;
1039         }  
1040
1041         /* Preexecs are done here as they might make the dir we are to ChDir
1042          * to below */
1043         /* execute any "root preexec = " line */
1044         if (*lp_rootpreexec(snum)) {
1045                 char *cmd = talloc_sub_advanced(talloc_tos(),
1046                                         lp_servicename(SNUM(conn)), conn->user,
1047                                         conn->connectpath, conn->gid,
1048                                         get_current_username(),
1049                                         current_user_info.domain,
1050                                         lp_rootpreexec(snum));
1051                 DEBUG(5,("cmd=%s\n",cmd));
1052                 ret = smbrun(cmd,NULL);
1053                 TALLOC_FREE(cmd);
1054                 if (ret != 0 && lp_rootpreexec_close(snum)) {
1055                         DEBUG(1,("root preexec gave %d - failing "
1056                                  "connection\n", ret));
1057                         yield_connection(conn, lp_servicename(snum));
1058                         conn_free(conn);
1059                         *status = NT_STATUS_ACCESS_DENIED;
1060                         return NULL;
1061                 }
1062         }
1063
1064 /* USER Activites: */
1065         if (!change_to_user(conn, conn->vuid)) {
1066                 /* No point continuing if they fail the basic checks */
1067                 DEBUG(0,("Can't become connected user!\n"));
1068                 yield_connection(conn, lp_servicename(snum));
1069                 conn_free(conn);
1070                 *status = NT_STATUS_LOGON_FAILURE;
1071                 return NULL;
1072         }
1073
1074         /* Remember that a different vuid can connect later without these
1075          * checks... */
1076         
1077         /* Preexecs are done here as they might make the dir we are to ChDir
1078          * to below */
1079
1080         /* execute any "preexec = " line */
1081         if (*lp_preexec(snum)) {
1082                 char *cmd = talloc_sub_advanced(talloc_tos(),
1083                                         lp_servicename(SNUM(conn)), conn->user,
1084                                         conn->connectpath, conn->gid,
1085                                         get_current_username(),
1086                                         current_user_info.domain,
1087                                         lp_preexec(snum));
1088                 ret = smbrun(cmd,NULL);
1089                 TALLOC_FREE(cmd);
1090                 if (ret != 0 && lp_preexec_close(snum)) {
1091                         DEBUG(1,("preexec gave %d - failing connection\n",
1092                                  ret));
1093                         *status = NT_STATUS_ACCESS_DENIED;
1094                         goto err_root_exit;
1095                 }
1096         }
1097
1098 #ifdef WITH_FAKE_KASERVER
1099         if (lp_afs_share(snum)) {
1100                 afs_login(conn);
1101         }
1102 #endif
1103         
1104         /* Add veto/hide lists */
1105         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1106                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1107                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1108                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1109         }
1110         
1111         /* Invoke VFS make connection hook - do this before the VFS_STAT call
1112            to allow any filesystems needing user credentials to initialize
1113            themselves. */
1114
1115         if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1116                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1117                 *status = NT_STATUS_UNSUCCESSFUL;
1118                 goto err_root_exit;
1119         }
1120
1121         /* Any error exit after here needs to call the disconnect hook. */
1122         on_err_call_dis_hook = true;
1123
1124         /* win2000 does not check the permissions on the directory
1125            during the tree connect, instead relying on permission
1126            check during individual operations. To match this behaviour
1127            I have disabled this chdir check (tridge) */
1128         /* the alternative is just to check the directory exists */
1129         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1130             !S_ISDIR(st.st_mode)) {
1131                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1132                         DEBUG(0,("'%s' is not a directory, when connecting to "
1133                                  "[%s]\n", conn->connectpath,
1134                                  lp_servicename(snum)));
1135                 } else {
1136                         DEBUG(0,("'%s' does not exist or permission denied "
1137                                  "when connecting to [%s] Error was %s\n",
1138                                  conn->connectpath, lp_servicename(snum),
1139                                  strerror(errno) ));
1140                 }
1141                 *status = NT_STATUS_BAD_NETWORK_NAME;
1142                 goto err_root_exit;
1143         }
1144
1145         string_set(&conn->origpath,conn->connectpath);
1146
1147 #if SOFTLINK_OPTIMISATION
1148         /* resolve any soft links early if possible */
1149         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1150                 TALLOC_CTX *ctx = talloc_tos();
1151                 char *s = vfs_GetWd(ctx,s);
1152                 if (!s) {
1153                         *status = map_nt_error_from_unix(errno);
1154                         goto err_root_exit;
1155                 }
1156                 if (!set_conn_connectpath(conn,s)) {
1157                         *status = NT_STATUS_NO_MEMORY;
1158                         goto err_root_exit;
1159                 }
1160                 vfs_ChDir(conn,conn->connectpath);
1161         }
1162 #endif
1163
1164         /* Figure out the characteristics of the underlying filesystem. This
1165          * assumes that all the filesystem mounted withing a share path have
1166          * the same characteristics, which is likely but not guaranteed.
1167          */
1168         {
1169                 vfs_statvfs_struct svfs;
1170
1171                 conn->fs_capabilities =
1172                     FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
1173
1174                 if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) {
1175                         conn->fs_capabilities = svfs.FsCapabilities;
1176                 }
1177         }
1178
1179         /*
1180          * Print out the 'connected as' stuff here as we need
1181          * to know the effective uid and gid we will be using
1182          * (at least initially).
1183          */
1184
1185         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1186                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1187                          conn->client_address );
1188                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1189                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1190                 dbgtext( "initially as user %s ", user );
1191                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1192                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1193         }
1194
1195         /* we've finished with the user stuff - go back to root */
1196         change_to_root_user();
1197         return(conn);
1198
1199   err_root_exit:
1200
1201         change_to_root_user();
1202         if (on_err_call_dis_hook) {
1203                 /* Call VFS disconnect hook */
1204                 SMB_VFS_DISCONNECT(conn);
1205         }
1206         yield_connection(conn, lp_servicename(snum));
1207         conn_free(conn);
1208         return NULL;
1209 }
1210
1211 /***************************************************************************************
1212  Simple wrapper function for make_connection() to include a call to 
1213  vfs_chdir()
1214  **************************************************************************************/
1215  
1216 connection_struct *make_connection_with_chdir(const char *service_in,
1217                                               DATA_BLOB password, 
1218                                               const char *dev, uint16 vuid,
1219                                               NTSTATUS *status)
1220 {
1221         connection_struct *conn = NULL;
1222         
1223         conn = make_connection(service_in, password, dev, vuid, status);
1224         
1225         /*
1226          * make_connection() does not change the directory for us any more
1227          * so we have to do it as a separate step  --jerry
1228          */
1229          
1230         if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1231                 DEBUG(0,("move_driver_to_download_area: Can't change "
1232                          "directory to %s for [print$] (%s)\n",
1233                          conn->connectpath,strerror(errno)));
1234                 yield_connection(conn, lp_servicename(SNUM(conn)));
1235                 conn_free(conn);
1236                 *status = NT_STATUS_UNSUCCESSFUL;
1237                 return NULL;
1238         }
1239         
1240         return conn;
1241 }
1242
1243 /****************************************************************************
1244  Make a connection to a service.
1245  *
1246  * @param service 
1247 ****************************************************************************/
1248
1249 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
1250                                    const char *pdev, uint16 vuid,
1251                                    NTSTATUS *status)
1252 {
1253         uid_t euid;
1254         user_struct *vuser = NULL;
1255         fstring service;
1256         fstring dev;
1257         int snum = -1;
1258         char addr[INET6_ADDRSTRLEN];
1259
1260         fstrcpy(dev, pdev);
1261
1262         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1263          * root. */
1264         if (!non_root_mode() && (euid = geteuid()) != 0) {
1265                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1266                          "(%u)\n", (unsigned int)euid ));
1267                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1268         }
1269
1270         if (conn_num_open() > 2047) {
1271                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1272                 return NULL;
1273         }
1274
1275         if(lp_security() != SEC_SHARE) {
1276                 vuser = get_valid_user_struct(vuid);
1277                 if (!vuser) {
1278                         DEBUG(1,("make_connection: refusing to connect with "
1279                                  "no session setup\n"));
1280                         *status = NT_STATUS_ACCESS_DENIED;
1281                         return NULL;
1282                 }
1283         }
1284
1285         /* Logic to try and connect to the correct [homes] share, preferably
1286            without too many getpwnam() lookups.  This is particulary nasty for
1287            winbind usernames, where the share name isn't the same as unix
1288            username.
1289
1290            The snum of the homes share is stored on the vuser at session setup
1291            time.
1292         */
1293
1294         if (strequal(service_in,HOMES_NAME)) {
1295                 if(lp_security() != SEC_SHARE) {
1296                         DATA_BLOB no_pw = data_blob_null;
1297                         if (vuser->homes_snum == -1) {
1298                                 DEBUG(2, ("[homes] share not available for "
1299                                           "this user because it was not found "
1300                                           "or created at session setup "
1301                                           "time\n"));
1302                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1303                                 return NULL;
1304                         }
1305                         DEBUG(5, ("making a connection to [homes] service "
1306                                   "created at session setup time\n"));
1307                         return make_connection_snum(vuser->homes_snum,
1308                                                     vuser, no_pw, 
1309                                                     dev, status);
1310                 } else {
1311                         /* Security = share. Try with
1312                          * current_user_info.smb_name as the username.  */
1313                         if (*current_user_info.smb_name) {
1314                                 fstring unix_username;
1315                                 fstrcpy(unix_username,
1316                                         current_user_info.smb_name);
1317                                 map_username(unix_username);
1318                                 snum = find_service(unix_username);
1319                         } 
1320                         if (snum != -1) {
1321                                 DEBUG(5, ("making a connection to 'homes' "
1322                                           "service %s based on "
1323                                           "security=share\n", service_in));
1324                                 return make_connection_snum(snum, NULL,
1325                                                             password,
1326                                                             dev, status);
1327                         }
1328                 }
1329         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1330                    && strequal(service_in,
1331                                lp_servicename(vuser->homes_snum))) {
1332                 DATA_BLOB no_pw = data_blob_null;
1333                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1334                           "created at session setup time\n", service_in));
1335                 return make_connection_snum(vuser->homes_snum,
1336                                             vuser, no_pw, 
1337                                             dev, status);
1338         }
1339         
1340         fstrcpy(service, service_in);
1341
1342         strlower_m(service);
1343
1344         snum = find_service(service);
1345
1346         if (snum < 0) {
1347                 if (strequal(service,"IPC$") ||
1348                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1349                         DEBUG(3,("refusing IPC connection to %s\n", service));
1350                         *status = NT_STATUS_ACCESS_DENIED;
1351                         return NULL;
1352                 }
1353
1354                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1355                         get_remote_machine_name(),
1356                         client_addr(get_client_fd(),addr,sizeof(addr)),
1357                         service));
1358                 *status = NT_STATUS_BAD_NETWORK_NAME;
1359                 return NULL;
1360         }
1361
1362         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1363         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1364                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1365                           "(pointing to %s)\n", 
1366                         service, lp_msdfs_proxy(snum)));
1367                 *status = NT_STATUS_BAD_NETWORK_NAME;
1368                 return NULL;
1369         }
1370
1371         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1372
1373         return make_connection_snum(snum, vuser,
1374                                     password,
1375                                     dev, status);
1376 }
1377
1378 /****************************************************************************
1379  Close a cnum.
1380 ****************************************************************************/
1381
1382 void close_cnum(connection_struct *conn, uint16 vuid)
1383 {
1384         if (IS_IPC(conn)) {
1385                 pipe_close_conn(conn);
1386         } else {
1387                 file_close_conn(conn);
1388                 dptr_closecnum(conn);
1389         }
1390
1391         change_to_root_user();
1392
1393         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1394                                  get_remote_machine_name(),
1395                                  conn->client_address,
1396                                  lp_servicename(SNUM(conn))));
1397
1398         /* Call VFS disconnect hook */    
1399         SMB_VFS_DISCONNECT(conn);
1400
1401         yield_connection(conn, lp_servicename(SNUM(conn)));
1402
1403         /* make sure we leave the directory available for unmount */
1404         vfs_ChDir(conn, "/");
1405
1406         /* execute any "postexec = " line */
1407         if (*lp_postexec(SNUM(conn)) && 
1408             change_to_user(conn, vuid))  {
1409                 char *cmd = talloc_sub_advanced(talloc_tos(),
1410                                         lp_servicename(SNUM(conn)), conn->user,
1411                                         conn->connectpath, conn->gid,
1412                                         get_current_username(),
1413                                         current_user_info.domain,
1414                                         lp_postexec(SNUM(conn)));
1415                 smbrun(cmd,NULL);
1416                 TALLOC_FREE(cmd);
1417                 change_to_root_user();
1418         }
1419
1420         change_to_root_user();
1421         /* execute any "root postexec = " line */
1422         if (*lp_rootpostexec(SNUM(conn)))  {
1423                 char *cmd = talloc_sub_advanced(talloc_tos(),
1424                                         lp_servicename(SNUM(conn)), conn->user,
1425                                         conn->connectpath, conn->gid,
1426                                         get_current_username(),
1427                                         current_user_info.domain,
1428                                         lp_rootpostexec(SNUM(conn)));
1429                 smbrun(cmd,NULL);
1430                 TALLOC_FREE(cmd);
1431         }
1432
1433         conn_free(conn);
1434 }