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