Remove "userdom_struct user" from "struct user_struct"
[ira/wip.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->server_info->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->server_info->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",
732                                           vuser->server_info->unix_name,
733                                           lp_servicename(snum)));
734                                 conn_free(conn);
735                                 *status = NT_STATUS_ACCESS_DENIED;
736                                 return NULL;
737                         }
738                 }
739                 conn->vuid = vuser->vuid;
740                 conn->uid = vuser->server_info->uid;
741                 conn->gid = vuser->server_info->gid;
742                 string_set(&conn->user,vuser->server_info->unix_name);
743                 fstrcpy(user,vuser->server_info->unix_name);
744                 guest = vuser->server_info->guest;
745         } else if (lp_security() == SEC_SHARE) {
746                 NTSTATUS status2;
747                 char *found_username = NULL;
748
749                 /* add it as a possible user name if we 
750                    are in share mode security */
751                 add_session_user(lp_servicename(snum));
752                 /* shall we let them in? */
753                 if (!authorise_login(snum,user,password,&guest)) {
754                         DEBUG( 2, ( "Invalid username/password for [%s]\n", 
755                                     lp_servicename(snum)) );
756                         conn_free(conn);
757                         *status = NT_STATUS_WRONG_PASSWORD;
758                         return NULL;
759                 }
760                 pass = Get_Pwnam_alloc(talloc_tos(), user);
761                 status2 = create_token_from_username(conn, pass->pw_name, True,
762                                                      &conn->uid, &conn->gid,
763                                                      &found_username,
764                                                      &conn->nt_user_token);
765                 TALLOC_FREE(pass);
766                 if (!NT_STATUS_IS_OK(status2)) {
767                         conn_free(conn);
768                         *status = status2;
769                         return NULL;
770                 }
771                 fstrcpy(user, found_username);
772                 string_set(&conn->user,user);
773                 TALLOC_FREE(found_username);
774                 conn->force_user = True;
775         } else {
776                 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
777                 conn_free(conn);
778                 *status = NT_STATUS_ACCESS_DENIED;
779                 return NULL;
780         }
781
782         add_session_user(user);
783
784         safe_strcpy(conn->client_address,
785                         client_addr(get_client_fd(),addr,sizeof(addr)), 
786                         sizeof(conn->client_address)-1);
787         conn->num_files_open = 0;
788         conn->lastused = conn->lastused_count = time(NULL);
789         conn->used = True;
790         conn->printer = (strncmp(dev,"LPT",3) == 0);
791         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
792                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
793         conn->dirptr = NULL;
794
795         /* Case options for the share. */
796         if (lp_casesensitive(snum) == Auto) {
797                 /* We will be setting this per packet. Set to be case
798                  * insensitive for now. */
799                 conn->case_sensitive = False;
800         } else {
801                 conn->case_sensitive = (bool)lp_casesensitive(snum);
802         }
803
804         conn->case_preserve = lp_preservecase(snum);
805         conn->short_case_preserve = lp_shortpreservecase(snum);
806
807         conn->encrypt_level = lp_smb_encrypt(snum);
808
809         conn->veto_list = NULL;
810         conn->hide_list = NULL;
811         conn->veto_oplock_list = NULL;
812         conn->aio_write_behind_list = NULL;
813         string_set(&conn->dirpath,"");
814         string_set(&conn->user,user);
815
816         conn->read_only = lp_readonly(SNUM(conn));
817         conn->admin_user = False;
818
819         /*
820          * If force user is true, then store the given userid and the gid of
821          * the user we're forcing.
822          * For auxiliary groups see below.
823          */
824         
825         if (*lp_force_user(snum)) {
826                 NTSTATUS status2;
827
828                 status2 = find_forced_user(conn,
829                                 (vuser != NULL) && vuser->server_info->guest,
830                                 user);
831                 if (!NT_STATUS_IS_OK(status2)) {
832                         conn_free(conn);
833                         *status = status2;
834                         return NULL;
835                 }
836                 string_set(&conn->user,user);
837                 conn->force_user = True;
838                 DEBUG(3,("Forced user %s\n",user));       
839         }
840
841         /*
842          * If force group is true, then override
843          * any groupid stored for the connecting user.
844          */
845         
846         if (*lp_force_group(snum)) {
847                 NTSTATUS status2;
848                 DOM_SID group_sid;
849
850                 status2 = find_forced_group(conn->force_user,
851                                             snum, user,
852                                             &group_sid, &conn->gid);
853                 if (!NT_STATUS_IS_OK(status2)) {
854                         conn_free(conn);
855                         *status = status2;
856                         return NULL;
857                 }
858
859                 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
860
861                         /* Not force user and not security=share, but force
862                          * group. vuser has a token to copy */
863                         
864                         conn->nt_user_token = dup_nt_token(
865                                 NULL, vuser->server_info->ptok);
866                         if (conn->nt_user_token == NULL) {
867                                 DEBUG(0, ("dup_nt_token failed\n"));
868                                 conn_free(conn);
869                                 *status = NT_STATUS_NO_MEMORY;
870                                 return NULL;
871                         }
872                 }
873
874                 /* If conn->nt_user_token is still NULL, we have
875                  * security=share. This means ignore the SID, as we had no
876                  * vuser to copy from */
877
878                 if (conn->nt_user_token != NULL) {
879                         /* Overwrite the primary group sid */
880                         sid_copy(&conn->nt_user_token->user_sids[1],
881                                  &group_sid);
882
883                 }
884                 conn->force_group = True;
885         }
886
887         if (conn->nt_user_token != NULL) {
888                 size_t i;
889
890                 /* We have a share-specific token from force [user|group].
891                  * This means we have to create the list of unix groups from
892                  * the list of sids. */
893
894                 conn->ngroups = 0;
895                 conn->groups = NULL;
896
897                 for (i=0; i<conn->nt_user_token->num_sids; i++) {
898                         gid_t gid;
899                         DOM_SID *sid = &conn->nt_user_token->user_sids[i];
900
901                         if (!sid_to_gid(sid, &gid)) {
902                                 DEBUG(10, ("Could not convert SID %s to gid, "
903                                            "ignoring it\n",
904                                            sid_string_dbg(sid)));
905                                 continue;
906                         }
907                         if (!add_gid_to_array_unique(conn, gid, &conn->groups,
908                                                 &conn->ngroups)) {
909                                 DEBUG(0, ("add_gid_to_array_unique failed\n"));
910                                 conn_free(conn);
911                                 *status = NT_STATUS_NO_MEMORY;
912                                 return NULL;
913                         }
914                 }
915         }
916
917         {
918                 char *s = talloc_sub_advanced(talloc_tos(),
919                                         lp_servicename(SNUM(conn)), conn->user,
920                                         conn->connectpath, conn->gid,
921                                         get_current_username(),
922                                         current_user_info.domain,
923                                         lp_pathname(snum));
924                 if (!s) {
925                         conn_free(conn);
926                         *status = NT_STATUS_NO_MEMORY;
927                         return NULL;
928                 }
929
930                 if (!set_conn_connectpath(conn,s)) {
931                         TALLOC_FREE(s);
932                         conn_free(conn);
933                         *status = NT_STATUS_NO_MEMORY;
934                         return NULL;
935                 }
936                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
937                          lp_servicename(snum)));
938                 TALLOC_FREE(s);
939         }
940
941         /*
942          * New code to check if there's a share security descripter
943          * added from NT server manager. This is done after the
944          * smb.conf checks are done as we need a uid and token. JRA.
945          *
946          */
947
948         {
949                 bool can_write = False;
950                 NT_USER_TOKEN *token = conn->nt_user_token ?
951                         conn->nt_user_token :
952                         (vuser ? vuser->server_info->ptok : NULL);
953
954                 /*
955                  * I don't believe this can happen. But the
956                  * logic above is convoluted enough to confuse
957                  * automated checkers, so be sure. JRA.
958                  */
959
960                 if (token == NULL) {
961                         DEBUG(0,("make_connection: connection to %s "
962                                  "denied due to missing "
963                                  "NT token.\n",
964                                   lp_servicename(snum)));
965                         conn_free(conn);
966                         *status = NT_STATUS_ACCESS_DENIED;
967                         return NULL;
968                 }
969
970                 can_write = share_access_check(token,
971                                                     lp_servicename(snum),
972                                                     FILE_WRITE_DATA);
973
974                 if (!can_write) {
975                         if (!share_access_check(token,
976                                                 lp_servicename(snum),
977                                                 FILE_READ_DATA)) {
978                                 /* No access, read or write. */
979                                 DEBUG(0,("make_connection: connection to %s "
980                                          "denied due to security "
981                                          "descriptor.\n",
982                                           lp_servicename(snum)));
983                                 conn_free(conn);
984                                 *status = NT_STATUS_ACCESS_DENIED;
985                                 return NULL;
986                         } else {
987                                 conn->read_only = True;
988                         }
989                 }
990         }
991         /* Initialise VFS function pointers */
992
993         if (!smbd_vfs_init(conn)) {
994                 DEBUG(0, ("vfs_init failed for service %s\n",
995                           lp_servicename(snum)));
996                 conn_free(conn);
997                 *status = NT_STATUS_BAD_NETWORK_NAME;
998                 return NULL;
999         }
1000
1001         /*
1002          * If widelinks are disallowed we need to canonicalise the connect
1003          * path here to ensure we don't have any symlinks in the
1004          * connectpath. We will be checking all paths on this connection are
1005          * below this directory. We must do this after the VFS init as we
1006          * depend on the realpath() pointer in the vfs table. JRA.
1007          */
1008         if (!lp_widelinks(snum)) {
1009                 if (!canonicalize_connect_path(conn)) {
1010                         DEBUG(0, ("canonicalize_connect_path failed "
1011                         "for service %s, path %s\n",
1012                                 lp_servicename(snum),
1013                                 conn->connectpath));
1014                         conn_free(conn);
1015                         *status = NT_STATUS_BAD_NETWORK_NAME;
1016                         return NULL;
1017                 }
1018         }
1019
1020         if ((!conn->printer) && (!conn->ipc)) {
1021                 conn->notify_ctx = notify_init(conn, server_id_self(),
1022                                                smbd_messaging_context(),
1023                                                smbd_event_context(),
1024                                                conn);
1025         }
1026
1027 /* ROOT Activities: */  
1028         /*
1029          * Enforce the max connections parameter.
1030          */
1031
1032         if ((lp_max_connections(snum) > 0)
1033             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1034                 lp_max_connections(snum))) {
1035
1036                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1037                           lp_max_connections(snum), lp_servicename(snum)));
1038                 conn_free(conn);
1039                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1040                 return NULL;
1041         }  
1042
1043         /*
1044          * Get us an entry in the connections db
1045          */
1046         if (!claim_connection(conn, lp_servicename(snum), 0)) {
1047                 DEBUG(1, ("Could not store connections entry\n"));
1048                 conn_free(conn);
1049                 *status = NT_STATUS_INTERNAL_DB_ERROR;
1050                 return NULL;
1051         }  
1052
1053         /* Preexecs are done here as they might make the dir we are to ChDir
1054          * to below */
1055         /* execute any "root preexec = " line */
1056         if (*lp_rootpreexec(snum)) {
1057                 char *cmd = talloc_sub_advanced(talloc_tos(),
1058                                         lp_servicename(SNUM(conn)), conn->user,
1059                                         conn->connectpath, conn->gid,
1060                                         get_current_username(),
1061                                         current_user_info.domain,
1062                                         lp_rootpreexec(snum));
1063                 DEBUG(5,("cmd=%s\n",cmd));
1064                 ret = smbrun(cmd,NULL);
1065                 TALLOC_FREE(cmd);
1066                 if (ret != 0 && lp_rootpreexec_close(snum)) {
1067                         DEBUG(1,("root preexec gave %d - failing "
1068                                  "connection\n", ret));
1069                         yield_connection(conn, lp_servicename(snum));
1070                         conn_free(conn);
1071                         *status = NT_STATUS_ACCESS_DENIED;
1072                         return NULL;
1073                 }
1074         }
1075
1076 /* USER Activites: */
1077         if (!change_to_user(conn, conn->vuid)) {
1078                 /* No point continuing if they fail the basic checks */
1079                 DEBUG(0,("Can't become connected user!\n"));
1080                 yield_connection(conn, lp_servicename(snum));
1081                 conn_free(conn);
1082                 *status = NT_STATUS_LOGON_FAILURE;
1083                 return NULL;
1084         }
1085
1086         /* Remember that a different vuid can connect later without these
1087          * checks... */
1088         
1089         /* Preexecs are done here as they might make the dir we are to ChDir
1090          * to below */
1091
1092         /* execute any "preexec = " line */
1093         if (*lp_preexec(snum)) {
1094                 char *cmd = talloc_sub_advanced(talloc_tos(),
1095                                         lp_servicename(SNUM(conn)), conn->user,
1096                                         conn->connectpath, conn->gid,
1097                                         get_current_username(),
1098                                         current_user_info.domain,
1099                                         lp_preexec(snum));
1100                 ret = smbrun(cmd,NULL);
1101                 TALLOC_FREE(cmd);
1102                 if (ret != 0 && lp_preexec_close(snum)) {
1103                         DEBUG(1,("preexec gave %d - failing connection\n",
1104                                  ret));
1105                         *status = NT_STATUS_ACCESS_DENIED;
1106                         goto err_root_exit;
1107                 }
1108         }
1109
1110 #ifdef WITH_FAKE_KASERVER
1111         if (lp_afs_share(snum)) {
1112                 afs_login(conn);
1113         }
1114 #endif
1115         
1116         /* Add veto/hide lists */
1117         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1118                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1119                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1120                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1121         }
1122         
1123         /* Invoke VFS make connection hook - do this before the VFS_STAT call
1124            to allow any filesystems needing user credentials to initialize
1125            themselves. */
1126
1127         if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1128                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1129                 *status = NT_STATUS_UNSUCCESSFUL;
1130                 goto err_root_exit;
1131         }
1132
1133         /* Any error exit after here needs to call the disconnect hook. */
1134         on_err_call_dis_hook = true;
1135
1136         /* win2000 does not check the permissions on the directory
1137            during the tree connect, instead relying on permission
1138            check during individual operations. To match this behaviour
1139            I have disabled this chdir check (tridge) */
1140         /* the alternative is just to check the directory exists */
1141         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1142             !S_ISDIR(st.st_mode)) {
1143                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1144                         DEBUG(0,("'%s' is not a directory, when connecting to "
1145                                  "[%s]\n", conn->connectpath,
1146                                  lp_servicename(snum)));
1147                 } else {
1148                         DEBUG(0,("'%s' does not exist or permission denied "
1149                                  "when connecting to [%s] Error was %s\n",
1150                                  conn->connectpath, lp_servicename(snum),
1151                                  strerror(errno) ));
1152                 }
1153                 *status = NT_STATUS_BAD_NETWORK_NAME;
1154                 goto err_root_exit;
1155         }
1156
1157         string_set(&conn->origpath,conn->connectpath);
1158
1159 #if SOFTLINK_OPTIMISATION
1160         /* resolve any soft links early if possible */
1161         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1162                 TALLOC_CTX *ctx = talloc_tos();
1163                 char *s = vfs_GetWd(ctx,s);
1164                 if (!s) {
1165                         *status = map_nt_error_from_unix(errno);
1166                         goto err_root_exit;
1167                 }
1168                 if (!set_conn_connectpath(conn,s)) {
1169                         *status = NT_STATUS_NO_MEMORY;
1170                         goto err_root_exit;
1171                 }
1172                 vfs_ChDir(conn,conn->connectpath);
1173         }
1174 #endif
1175
1176         /* Figure out the characteristics of the underlying filesystem. This
1177          * assumes that all the filesystem mounted withing a share path have
1178          * the same characteristics, which is likely but not guaranteed.
1179          */
1180
1181         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1182
1183         /*
1184          * Print out the 'connected as' stuff here as we need
1185          * to know the effective uid and gid we will be using
1186          * (at least initially).
1187          */
1188
1189         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1190                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1191                          conn->client_address );
1192                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1193                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1194                 dbgtext( "initially as user %s ", user );
1195                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1196                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1197         }
1198
1199         /* we've finished with the user stuff - go back to root */
1200         change_to_root_user();
1201         return(conn);
1202
1203   err_root_exit:
1204
1205         change_to_root_user();
1206         if (on_err_call_dis_hook) {
1207                 /* Call VFS disconnect hook */
1208                 SMB_VFS_DISCONNECT(conn);
1209         }
1210         yield_connection(conn, lp_servicename(snum));
1211         conn_free(conn);
1212         return NULL;
1213 }
1214
1215 /***************************************************************************************
1216  Simple wrapper function for make_connection() to include a call to 
1217  vfs_chdir()
1218  **************************************************************************************/
1219  
1220 connection_struct *make_connection_with_chdir(const char *service_in,
1221                                               DATA_BLOB password, 
1222                                               const char *dev, uint16 vuid,
1223                                               NTSTATUS *status)
1224 {
1225         connection_struct *conn = NULL;
1226         
1227         conn = make_connection(service_in, password, dev, vuid, status);
1228         
1229         /*
1230          * make_connection() does not change the directory for us any more
1231          * so we have to do it as a separate step  --jerry
1232          */
1233          
1234         if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1235                 DEBUG(0,("move_driver_to_download_area: Can't change "
1236                          "directory to %s for [print$] (%s)\n",
1237                          conn->connectpath,strerror(errno)));
1238                 yield_connection(conn, lp_servicename(SNUM(conn)));
1239                 conn_free(conn);
1240                 *status = NT_STATUS_UNSUCCESSFUL;
1241                 return NULL;
1242         }
1243         
1244         return conn;
1245 }
1246
1247 /****************************************************************************
1248  Make a connection to a service.
1249  *
1250  * @param service 
1251 ****************************************************************************/
1252
1253 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
1254                                    const char *pdev, uint16 vuid,
1255                                    NTSTATUS *status)
1256 {
1257         uid_t euid;
1258         user_struct *vuser = NULL;
1259         fstring service;
1260         fstring dev;
1261         int snum = -1;
1262         char addr[INET6_ADDRSTRLEN];
1263
1264         fstrcpy(dev, pdev);
1265
1266         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1267          * root. */
1268         if (!non_root_mode() && (euid = geteuid()) != 0) {
1269                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1270                          "(%u)\n", (unsigned int)euid ));
1271                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1272         }
1273
1274         if (conn_num_open() > 2047) {
1275                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1276                 return NULL;
1277         }
1278
1279         if(lp_security() != SEC_SHARE) {
1280                 vuser = get_valid_user_struct(vuid);
1281                 if (!vuser) {
1282                         DEBUG(1,("make_connection: refusing to connect with "
1283                                  "no session setup\n"));
1284                         *status = NT_STATUS_ACCESS_DENIED;
1285                         return NULL;
1286                 }
1287         }
1288
1289         /* Logic to try and connect to the correct [homes] share, preferably
1290            without too many getpwnam() lookups.  This is particulary nasty for
1291            winbind usernames, where the share name isn't the same as unix
1292            username.
1293
1294            The snum of the homes share is stored on the vuser at session setup
1295            time.
1296         */
1297
1298         if (strequal(service_in,HOMES_NAME)) {
1299                 if(lp_security() != SEC_SHARE) {
1300                         DATA_BLOB no_pw = data_blob_null;
1301                         if (vuser->homes_snum == -1) {
1302                                 DEBUG(2, ("[homes] share not available for "
1303                                           "this user because it was not found "
1304                                           "or created at session setup "
1305                                           "time\n"));
1306                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1307                                 return NULL;
1308                         }
1309                         DEBUG(5, ("making a connection to [homes] service "
1310                                   "created at session setup time\n"));
1311                         return make_connection_snum(vuser->homes_snum,
1312                                                     vuser, no_pw, 
1313                                                     dev, status);
1314                 } else {
1315                         /* Security = share. Try with
1316                          * current_user_info.smb_name as the username.  */
1317                         if (*current_user_info.smb_name) {
1318                                 fstring unix_username;
1319                                 fstrcpy(unix_username,
1320                                         current_user_info.smb_name);
1321                                 map_username(unix_username);
1322                                 snum = find_service(unix_username);
1323                         } 
1324                         if (snum != -1) {
1325                                 DEBUG(5, ("making a connection to 'homes' "
1326                                           "service %s based on "
1327                                           "security=share\n", service_in));
1328                                 return make_connection_snum(snum, NULL,
1329                                                             password,
1330                                                             dev, status);
1331                         }
1332                 }
1333         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1334                    && strequal(service_in,
1335                                lp_servicename(vuser->homes_snum))) {
1336                 DATA_BLOB no_pw = data_blob_null;
1337                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1338                           "created at session setup time\n", service_in));
1339                 return make_connection_snum(vuser->homes_snum,
1340                                             vuser, no_pw, 
1341                                             dev, status);
1342         }
1343         
1344         fstrcpy(service, service_in);
1345
1346         strlower_m(service);
1347
1348         snum = find_service(service);
1349
1350         if (snum < 0) {
1351                 if (strequal(service,"IPC$") ||
1352                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1353                         DEBUG(3,("refusing IPC connection to %s\n", service));
1354                         *status = NT_STATUS_ACCESS_DENIED;
1355                         return NULL;
1356                 }
1357
1358                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1359                         get_remote_machine_name(),
1360                         client_addr(get_client_fd(),addr,sizeof(addr)),
1361                         service));
1362                 *status = NT_STATUS_BAD_NETWORK_NAME;
1363                 return NULL;
1364         }
1365
1366         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1367         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1368                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1369                           "(pointing to %s)\n", 
1370                         service, lp_msdfs_proxy(snum)));
1371                 *status = NT_STATUS_BAD_NETWORK_NAME;
1372                 return NULL;
1373         }
1374
1375         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1376
1377         return make_connection_snum(snum, vuser,
1378                                     password,
1379                                     dev, status);
1380 }
1381
1382 /****************************************************************************
1383  Close a cnum.
1384 ****************************************************************************/
1385
1386 void close_cnum(connection_struct *conn, uint16 vuid)
1387 {
1388         if (IS_IPC(conn)) {
1389                 pipe_close_conn(conn);
1390         } else {
1391                 file_close_conn(conn);
1392                 dptr_closecnum(conn);
1393         }
1394
1395         change_to_root_user();
1396
1397         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1398                                  get_remote_machine_name(),
1399                                  conn->client_address,
1400                                  lp_servicename(SNUM(conn))));
1401
1402         /* Call VFS disconnect hook */    
1403         SMB_VFS_DISCONNECT(conn);
1404
1405         yield_connection(conn, lp_servicename(SNUM(conn)));
1406
1407         /* make sure we leave the directory available for unmount */
1408         vfs_ChDir(conn, "/");
1409
1410         /* execute any "postexec = " line */
1411         if (*lp_postexec(SNUM(conn)) && 
1412             change_to_user(conn, vuid))  {
1413                 char *cmd = talloc_sub_advanced(talloc_tos(),
1414                                         lp_servicename(SNUM(conn)), conn->user,
1415                                         conn->connectpath, conn->gid,
1416                                         get_current_username(),
1417                                         current_user_info.domain,
1418                                         lp_postexec(SNUM(conn)));
1419                 smbrun(cmd,NULL);
1420                 TALLOC_FREE(cmd);
1421                 change_to_root_user();
1422         }
1423
1424         change_to_root_user();
1425         /* execute any "root postexec = " line */
1426         if (*lp_rootpostexec(SNUM(conn)))  {
1427                 char *cmd = talloc_sub_advanced(talloc_tos(),
1428                                         lp_servicename(SNUM(conn)), conn->user,
1429                                         conn->connectpath, conn->gid,
1430                                         get_current_username(),
1431                                         current_user_info.domain,
1432                                         lp_rootpostexec(SNUM(conn)));
1433                 smbrun(cmd,NULL);
1434                 TALLOC_FREE(cmd);
1435         }
1436
1437         conn_free(conn);
1438 }