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