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