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