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