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