s3:smbd: remove dirptr and dirpath from connection_struct
[kai/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(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
186                          conn->connectpath, strerror(errno)));
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         struct smbd_server_connection *sconn = smbd_server_conn;
305
306         all_string_sub(service,"\\","/",0);
307
308         iService = lp_servicenumber(service);
309
310         /* now handle the special case of a home directory */
311         if (iService < 0) {
312                 char *phome_dir = get_user_home_dir(talloc_tos(), service);
313
314                 if(!phome_dir) {
315                         /*
316                          * Try mapping the servicename, it may
317                          * be a Windows to unix mapped user name.
318                          */
319                         if(map_username(sconn, service))
320                                 phome_dir = get_user_home_dir(
321                                         talloc_tos(), service);
322                 }
323
324                 DEBUG(3,("checking for home directory %s gave %s\n",service,
325                         phome_dir?phome_dir:"(NULL)"));
326
327                 iService = add_home_service(service,service /* 'username' */, phome_dir);
328         }
329
330         /* If we still don't have a service, attempt to add it as a printer. */
331         if (iService < 0) {
332                 int iPrinterService;
333
334                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
335                         iPrinterService = load_registry_service(PRINTERS_NAME);
336                 }
337                 if (iPrinterService) {
338                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
339                         if (pcap_printername_ok(service)) {
340                                 DEBUG(3,("%s is a valid printer name\n", service));
341                                 DEBUG(3,("adding %s as a printer service\n", service));
342                                 lp_add_printer(service, iPrinterService);
343                                 iService = lp_servicenumber(service);
344                                 if (iService < 0) {
345                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
346                                 }
347                         } else {
348                                 DEBUG(3,("%s is not a valid printer name\n", service));
349                         }
350                 }
351         }
352
353         /* Check for default vfs service?  Unsure whether to implement this */
354         if (iService < 0) {
355         }
356
357         if (iService < 0) {
358                 iService = load_registry_service(service);
359         }
360
361         /* Is it a usershare service ? */
362         if (iService < 0 && *lp_usershare_path()) {
363                 /* Ensure the name is canonicalized. */
364                 strlower_m(service);
365                 iService = load_usershare_service(service);
366         }
367
368         /* just possibly it's a default service? */
369         if (iService < 0) {
370                 char *pdefservice = lp_defaultservice();
371                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
372                         /*
373                          * We need to do a local copy here as lp_defaultservice() 
374                          * returns one of the rotating lp_string buffers that
375                          * could get overwritten by the recursive find_service() call
376                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
377                          */
378                         char *defservice = SMB_STRDUP(pdefservice);
379
380                         if (!defservice) {
381                                 goto fail;
382                         }
383
384                         /* Disallow anything except explicit share names. */
385                         if (strequal(defservice,HOMES_NAME) ||
386                                         strequal(defservice, PRINTERS_NAME) ||
387                                         strequal(defservice, "IPC$")) {
388                                 SAFE_FREE(defservice);
389                                 goto fail;
390                         }
391
392                         iService = find_service(defservice);
393                         if (iService >= 0) {
394                                 all_string_sub(service, "_","/",0);
395                                 iService = lp_add_service(service, iService);
396                         }
397                         SAFE_FREE(defservice);
398                 }
399         }
400
401         if (iService >= 0) {
402                 if (!VALID_SNUM(iService)) {
403                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
404                         iService = -1;
405                 }
406         }
407
408   fail:
409
410         if (iService < 0)
411                 DEBUG(3,("find_service() failed to find service %s\n", service));
412
413         return (iService);
414 }
415
416
417 /****************************************************************************
418  do some basic sainity checks on the share.  
419  This function modifies dev, ecode.
420 ****************************************************************************/
421
422 static NTSTATUS share_sanity_checks(int snum, fstring dev) 
423 {
424         
425         if (!lp_snum_ok(snum) || 
426             !check_access(smbd_server_fd(), 
427                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
428                 return NT_STATUS_ACCESS_DENIED;
429         }
430
431         if (dev[0] == '?' || !dev[0]) {
432                 if (lp_print_ok(snum)) {
433                         fstrcpy(dev,"LPT1:");
434                 } else if (strequal(lp_fstype(snum), "IPC")) {
435                         fstrcpy(dev, "IPC");
436                 } else {
437                         fstrcpy(dev,"A:");
438                 }
439         }
440
441         strupper_m(dev);
442
443         if (lp_print_ok(snum)) {
444                 if (!strequal(dev, "LPT1:")) {
445                         return NT_STATUS_BAD_DEVICE_TYPE;
446                 }
447         } else if (strequal(lp_fstype(snum), "IPC")) {
448                 if (!strequal(dev, "IPC")) {
449                         return NT_STATUS_BAD_DEVICE_TYPE;
450                 }
451         } else if (!strequal(dev, "A:")) {
452                 return NT_STATUS_BAD_DEVICE_TYPE;
453         }
454
455         /* Behave as a printer if we are supposed to */
456         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
457                 fstrcpy(dev, "LPT1:");
458         }
459
460         return NT_STATUS_OK;
461 }
462
463 /*
464  * Go through lookup_name etc to find the force'd group.  
465  *
466  * Create a new token from src_token, replacing the primary group sid with the
467  * one found.
468  */
469
470 static NTSTATUS find_forced_group(bool force_user,
471                                   int snum, const char *username,
472                                   DOM_SID *pgroup_sid,
473                                   gid_t *pgid)
474 {
475         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
476         TALLOC_CTX *frame = talloc_stackframe();
477         DOM_SID group_sid;
478         enum lsa_SidType type;
479         char *groupname;
480         bool user_must_be_member = False;
481         gid_t gid;
482
483         groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
484         if (groupname == NULL) {
485                 DEBUG(1, ("talloc_strdup failed\n"));
486                 result = NT_STATUS_NO_MEMORY;
487                 goto done;
488         }
489
490         if (groupname[0] == '+') {
491                 user_must_be_member = True;
492                 groupname += 1;
493         }
494
495         groupname = talloc_string_sub(talloc_tos(), groupname,
496                                       "%S", lp_servicename(snum));
497         if (groupname == NULL) {
498                 DEBUG(1, ("talloc_string_sub failed\n"));
499                 result = NT_STATUS_NO_MEMORY;
500                 goto done;
501         }
502
503         if (!lookup_name_smbconf(talloc_tos(), groupname,
504                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
505                          NULL, NULL, &group_sid, &type)) {
506                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
507                            groupname));
508                 goto done;
509         }
510
511         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
512             (type != SID_NAME_WKN_GRP)) {
513                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
514                            sid_type_lookup(type)));
515                 goto done;
516         }
517
518         if (!sid_to_gid(&group_sid, &gid)) {
519                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
520                            sid_string_dbg(&group_sid), groupname));
521                 goto done;
522         }
523
524         /*
525          * If the user has been forced and the forced group starts with a '+',
526          * then we only set the group to be the forced group if the forced
527          * user is a member of that group.  Otherwise, the meaning of the '+'
528          * would be ignored.
529          */
530
531         if (force_user && user_must_be_member) {
532                 if (user_in_group_sid(username, &group_sid)) {
533                         sid_copy(pgroup_sid, &group_sid);
534                         *pgid = gid;
535                         DEBUG(3,("Forced group %s for member %s\n",
536                                  groupname, username));
537                 } else {
538                         DEBUG(0,("find_forced_group: forced user %s is not a member "
539                                 "of forced group %s. Disallowing access.\n",
540                                 username, groupname ));
541                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
542                         goto done;
543                 }
544         } else {
545                 sid_copy(pgroup_sid, &group_sid);
546                 *pgid = gid;
547                 DEBUG(3,("Forced group %s\n", groupname));
548         }
549
550         result = NT_STATUS_OK;
551  done:
552         TALLOC_FREE(frame);
553         return result;
554 }
555
556 /****************************************************************************
557   Create an auth_serversupplied_info structure for a connection_struct
558 ****************************************************************************/
559
560 static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
561                                               TALLOC_CTX *mem_ctx, int snum,
562                                               struct auth_serversupplied_info *vuid_serverinfo,
563                                               DATA_BLOB password,
564                                               struct auth_serversupplied_info **presult)
565 {
566         if (lp_guest_only(snum)) {
567                 return make_server_info_guest(mem_ctx, presult);
568         }
569
570         if (vuid_serverinfo != NULL) {
571
572                 struct auth_serversupplied_info *result;
573
574                 /*
575                  * This is the normal security != share case where we have a
576                  * valid vuid from the session setup.                 */
577
578                 if (vuid_serverinfo->guest) {
579                         if (!lp_guest_ok(snum)) {
580                                 DEBUG(2, ("guest user (from session setup) "
581                                           "not permitted to access this share "
582                                           "(%s)\n", lp_servicename(snum)));
583                                 return NT_STATUS_ACCESS_DENIED;
584                         }
585                 } else {
586                         if (!user_ok_token(vuid_serverinfo->unix_name,
587                                            pdb_get_domain(vuid_serverinfo->sam_account),
588                                            vuid_serverinfo->ptok, snum)) {
589                                 DEBUG(2, ("user '%s' (from session setup) not "
590                                           "permitted to access this share "
591                                           "(%s)\n",
592                                           vuid_serverinfo->unix_name,
593                                           lp_servicename(snum)));
594                                 return NT_STATUS_ACCESS_DENIED;
595                         }
596                 }
597
598                 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
599                 if (result == NULL) {
600                         return NT_STATUS_NO_MEMORY;
601                 }
602
603                 *presult = result;
604                 return NT_STATUS_OK;
605         }
606
607         if (lp_security() == SEC_SHARE) {
608
609                 fstring user;
610                 bool guest;
611
612                 /* add the sharename as a possible user name if we
613                    are in share mode security */
614
615                 add_session_user(sconn, lp_servicename(snum));
616
617                 /* shall we let them in? */
618
619                 if (!authorise_login(sconn, snum,user,password,&guest)) {
620                         DEBUG( 2, ( "Invalid username/password for [%s]\n",
621                                     lp_servicename(snum)) );
622                         return NT_STATUS_WRONG_PASSWORD;
623                 }
624
625                 return make_serverinfo_from_username(mem_ctx, user, guest,
626                                                      presult);
627         }
628
629         DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
630         return NT_STATUS_ACCESS_DENIED;
631 }
632
633
634 /****************************************************************************
635   Make a connection, given the snum to connect to, and the vuser of the
636   connecting user if appropriate.
637 ****************************************************************************/
638
639 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
640                                         int snum, user_struct *vuser,
641                                         DATA_BLOB password,
642                                         const char *pdev,
643                                         NTSTATUS *pstatus)
644 {
645         connection_struct *conn;
646         struct smb_filename *smb_fname_cpath = NULL;
647         fstring dev;
648         int ret;
649         char addr[INET6_ADDRSTRLEN];
650         bool on_err_call_dis_hook = false;
651         NTSTATUS status;
652
653         fstrcpy(dev, pdev);
654
655         if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
656                 return NULL;
657         }       
658
659         conn = conn_new(sconn);
660         if (!conn) {
661                 DEBUG(0,("Couldn't find free connection.\n"));
662                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
663                 return NULL;
664         }
665
666         conn->params->service = snum;
667
668         status = create_connection_server_info(sconn,
669                 conn, snum, vuser ? vuser->server_info : NULL, password,
670                 &conn->server_info);
671
672         if (!NT_STATUS_IS_OK(status)) {
673                 DEBUG(1, ("create_connection_server_info failed: %s\n",
674                           nt_errstr(status)));
675                 *pstatus = status;
676                 conn_free(conn);
677                 return NULL;
678         }
679
680         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
681                 conn->force_user = true;
682         }
683
684         add_session_user(sconn, conn->server_info->unix_name);
685
686         safe_strcpy(conn->client_address,
687                         client_addr(get_client_fd(),addr,sizeof(addr)), 
688                         sizeof(conn->client_address)-1);
689         conn->num_files_open = 0;
690         conn->lastused = conn->lastused_count = time(NULL);
691         conn->used = True;
692         conn->printer = (strncmp(dev,"LPT",3) == 0);
693         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
694                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
695
696         /* Case options for the share. */
697         if (lp_casesensitive(snum) == Auto) {
698                 /* We will be setting this per packet. Set to be case
699                  * insensitive for now. */
700                 conn->case_sensitive = False;
701         } else {
702                 conn->case_sensitive = (bool)lp_casesensitive(snum);
703         }
704
705         conn->case_preserve = lp_preservecase(snum);
706         conn->short_case_preserve = lp_shortpreservecase(snum);
707
708         conn->encrypt_level = lp_smb_encrypt(snum);
709
710         conn->veto_list = NULL;
711         conn->hide_list = NULL;
712         conn->veto_oplock_list = NULL;
713         conn->aio_write_behind_list = NULL;
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         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
991                                             NULL, NULL, &smb_fname_cpath);
992         if (!NT_STATUS_IS_OK(status)) {
993                 *pstatus = status;
994                 goto err_root_exit;
995         }
996
997         /* win2000 does not check the permissions on the directory
998            during the tree connect, instead relying on permission
999            check during individual operations. To match this behaviour
1000            I have disabled this chdir check (tridge) */
1001         /* the alternative is just to check the directory exists */
1002         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1003             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1004                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1005                         DEBUG(0,("'%s' is not a directory, when connecting to "
1006                                  "[%s]\n", conn->connectpath,
1007                                  lp_servicename(snum)));
1008                 } else {
1009                         DEBUG(0,("'%s' does not exist or permission denied "
1010                                  "when connecting to [%s] Error was %s\n",
1011                                  conn->connectpath, lp_servicename(snum),
1012                                  strerror(errno) ));
1013                 }
1014                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1015                 goto err_root_exit;
1016         }
1017
1018         string_set(&conn->origpath,conn->connectpath);
1019
1020 #if SOFTLINK_OPTIMISATION
1021         /* resolve any soft links early if possible */
1022         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1023                 TALLOC_CTX *ctx = talloc_tos();
1024                 char *s = vfs_GetWd(ctx,s);
1025                 if (!s) {
1026                         *status = map_nt_error_from_unix(errno);
1027                         goto err_root_exit;
1028                 }
1029                 if (!set_conn_connectpath(conn,s)) {
1030                         *status = NT_STATUS_NO_MEMORY;
1031                         goto err_root_exit;
1032                 }
1033                 vfs_ChDir(conn,conn->connectpath);
1034         }
1035 #endif
1036
1037         /* Figure out the characteristics of the underlying filesystem. This
1038          * assumes that all the filesystem mounted withing a share path have
1039          * the same characteristics, which is likely but not guaranteed.
1040          */
1041
1042         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1043
1044         /*
1045          * Print out the 'connected as' stuff here as we need
1046          * to know the effective uid and gid we will be using
1047          * (at least initially).
1048          */
1049
1050         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1051                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1052                          conn->client_address );
1053                 dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
1054                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1055                 dbgtext( "initially as user %s ",
1056                          conn->server_info->unix_name );
1057                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1058                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1059         }
1060
1061         /* we've finished with the user stuff - go back to root */
1062         change_to_root_user();
1063         return(conn);
1064
1065   err_root_exit:
1066         TALLOC_FREE(smb_fname_cpath);
1067         change_to_root_user();
1068         if (on_err_call_dis_hook) {
1069                 /* Call VFS disconnect hook */
1070                 SMB_VFS_DISCONNECT(conn);
1071         }
1072         yield_connection(conn, lp_servicename(snum));
1073         conn_free(conn);
1074         return NULL;
1075 }
1076
1077 /****************************************************************************
1078  Make a connection to a service.
1079  *
1080  * @param service 
1081 ****************************************************************************/
1082
1083 connection_struct *make_connection(struct smbd_server_connection *sconn,
1084                                    const char *service_in, DATA_BLOB password,
1085                                    const char *pdev, uint16 vuid,
1086                                    NTSTATUS *status)
1087 {
1088         uid_t euid;
1089         user_struct *vuser = NULL;
1090         fstring service;
1091         fstring dev;
1092         int snum = -1;
1093         char addr[INET6_ADDRSTRLEN];
1094
1095         fstrcpy(dev, pdev);
1096
1097         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1098          * root. */
1099         if (!non_root_mode() && (euid = geteuid()) != 0) {
1100                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1101                          "(%u)\n", (unsigned int)euid ));
1102                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1103         }
1104
1105         if (conn_num_open(sconn) > 2047) {
1106                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1107                 return NULL;
1108         }
1109
1110         if(lp_security() != SEC_SHARE) {
1111                 vuser = get_valid_user_struct(sconn, vuid);
1112                 if (!vuser) {
1113                         DEBUG(1,("make_connection: refusing to connect with "
1114                                  "no session setup\n"));
1115                         *status = NT_STATUS_ACCESS_DENIED;
1116                         return NULL;
1117                 }
1118         }
1119
1120         /* Logic to try and connect to the correct [homes] share, preferably
1121            without too many getpwnam() lookups.  This is particulary nasty for
1122            winbind usernames, where the share name isn't the same as unix
1123            username.
1124
1125            The snum of the homes share is stored on the vuser at session setup
1126            time.
1127         */
1128
1129         if (strequal(service_in,HOMES_NAME)) {
1130                 if(lp_security() != SEC_SHARE) {
1131                         DATA_BLOB no_pw = data_blob_null;
1132                         if (vuser->homes_snum == -1) {
1133                                 DEBUG(2, ("[homes] share not available for "
1134                                           "this user because it was not found "
1135                                           "or created at session setup "
1136                                           "time\n"));
1137                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1138                                 return NULL;
1139                         }
1140                         DEBUG(5, ("making a connection to [homes] service "
1141                                   "created at session setup time\n"));
1142                         return make_connection_snum(sconn,
1143                                                     vuser->homes_snum,
1144                                                     vuser, no_pw, 
1145                                                     dev, status);
1146                 } else {
1147                         /* Security = share. Try with
1148                          * current_user_info.smb_name as the username.  */
1149                         if (*current_user_info.smb_name) {
1150                                 fstring unix_username;
1151                                 fstrcpy(unix_username,
1152                                         current_user_info.smb_name);
1153                                 map_username(sconn, unix_username);
1154                                 snum = find_service(unix_username);
1155                         } 
1156                         if (snum != -1) {
1157                                 DEBUG(5, ("making a connection to 'homes' "
1158                                           "service %s based on "
1159                                           "security=share\n", service_in));
1160                                 return make_connection_snum(sconn,
1161                                                             snum, NULL,
1162                                                             password,
1163                                                             dev, status);
1164                         }
1165                 }
1166         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1167                    && strequal(service_in,
1168                                lp_servicename(vuser->homes_snum))) {
1169                 DATA_BLOB no_pw = data_blob_null;
1170                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1171                           "created at session setup time\n", service_in));
1172                 return make_connection_snum(sconn,
1173                                             vuser->homes_snum,
1174                                             vuser, no_pw, 
1175                                             dev, status);
1176         }
1177         
1178         fstrcpy(service, service_in);
1179
1180         strlower_m(service);
1181
1182         snum = find_service(service);
1183
1184         if (snum < 0) {
1185                 if (strequal(service,"IPC$") ||
1186                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1187                         DEBUG(3,("refusing IPC connection to %s\n", service));
1188                         *status = NT_STATUS_ACCESS_DENIED;
1189                         return NULL;
1190                 }
1191
1192                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1193                         get_remote_machine_name(),
1194                         client_addr(get_client_fd(),addr,sizeof(addr)),
1195                         service));
1196                 *status = NT_STATUS_BAD_NETWORK_NAME;
1197                 return NULL;
1198         }
1199
1200         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1201         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1202                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1203                           "(pointing to %s)\n", 
1204                         service, lp_msdfs_proxy(snum)));
1205                 *status = NT_STATUS_BAD_NETWORK_NAME;
1206                 return NULL;
1207         }
1208
1209         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1210
1211         return make_connection_snum(sconn, snum, vuser,
1212                                     password,
1213                                     dev, status);
1214 }
1215
1216 /****************************************************************************
1217  Close a cnum.
1218 ****************************************************************************/
1219
1220 void close_cnum(connection_struct *conn, uint16 vuid)
1221 {
1222         file_close_conn(conn);
1223
1224         if (!IS_IPC(conn)) {
1225                 dptr_closecnum(conn);
1226         }
1227
1228         change_to_root_user();
1229
1230         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1231                                  get_remote_machine_name(),
1232                                  conn->client_address,
1233                                  lp_servicename(SNUM(conn))));
1234
1235         /* Call VFS disconnect hook */    
1236         SMB_VFS_DISCONNECT(conn);
1237
1238         yield_connection(conn, lp_servicename(SNUM(conn)));
1239
1240         /* make sure we leave the directory available for unmount */
1241         vfs_ChDir(conn, "/");
1242
1243         /* execute any "postexec = " line */
1244         if (*lp_postexec(SNUM(conn)) && 
1245             change_to_user(conn, vuid))  {
1246                 char *cmd = talloc_sub_advanced(talloc_tos(),
1247                                         lp_servicename(SNUM(conn)),
1248                                         conn->server_info->unix_name,
1249                                         conn->connectpath,
1250                                         conn->server_info->utok.gid,
1251                                         conn->server_info->sanitized_username,
1252                                         pdb_get_domain(conn->server_info->sam_account),
1253                                         lp_postexec(SNUM(conn)));
1254                 smbrun(cmd,NULL);
1255                 TALLOC_FREE(cmd);
1256                 change_to_root_user();
1257         }
1258
1259         change_to_root_user();
1260         /* execute any "root postexec = " line */
1261         if (*lp_rootpostexec(SNUM(conn)))  {
1262                 char *cmd = talloc_sub_advanced(talloc_tos(),
1263                                         lp_servicename(SNUM(conn)),
1264                                         conn->server_info->unix_name,
1265                                         conn->connectpath,
1266                                         conn->server_info->utok.gid,
1267                                         conn->server_info->sanitized_username,
1268                                         pdb_get_domain(conn->server_info->sam_account),
1269                                         lp_rootpostexec(SNUM(conn)));
1270                 smbrun(cmd,NULL);
1271                 TALLOC_FREE(cmd);
1272         }
1273
1274         conn_free(conn);
1275 }