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