s3:smbd: make make_connection_snum() non static
[abartlet/samba.git/.git] / source3 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smbd/globals.h"
22
23 extern userdom_struct current_user_info;
24
25 static bool canonicalize_connect_path(connection_struct *conn)
26 {
27 #ifdef REALPATH_TAKES_NULL
28         bool ret;
29         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
30         if (!resolved_name) {
31                 return false;
32         }
33         ret = set_conn_connectpath(conn,resolved_name);
34         SAFE_FREE(resolved_name);
35         return ret;
36 #else
37         char resolved_name_buf[PATH_MAX+1];
38         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
39         if (!resolved_name) {
40                 return false;
41         }
42         return set_conn_connectpath(conn,resolved_name);
43 #endif /* REALPATH_TAKES_NULL */
44 }
45
46 /****************************************************************************
47  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
48  absolute path stating in / and not ending in /.
49  Observent people will notice a similarity between this and check_path_syntax :-).
50 ****************************************************************************/
51
52 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
53 {
54         char *destname;
55         char *d;
56         const char *s = connectpath;
57         bool start_of_name_component = true;
58
59         destname = SMB_STRDUP(connectpath);
60         if (!destname) {
61                 return false;
62         }
63         d = destname;
64
65         *d++ = '/'; /* Always start with root. */
66
67         while (*s) {
68                 if (*s == '/') {
69                         /* Eat multiple '/' */
70                         while (*s == '/') {
71                                 s++;
72                         }
73                         if ((d > destname + 1) && (*s != '\0')) {
74                                 *d++ = '/';
75                         }
76                         start_of_name_component = True;
77                         continue;
78                 }
79
80                 if (start_of_name_component) {
81                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
82                                 /* Uh oh - "/../" or "/..\0" ! */
83
84                                 /* Go past the ../ or .. */
85                                 if (s[2] == '/') {
86                                         s += 3;
87                                 } else {
88                                         s += 2; /* Go past the .. */
89                                 }
90
91                                 /* If  we just added a '/' - delete it */
92                                 if ((d > destname) && (*(d-1) == '/')) {
93                                         *(d-1) = '\0';
94                                         d--;
95                                 }
96
97                                 /* Are we at the start ? Can't go back further if so. */
98                                 if (d <= destname) {
99                                         *d++ = '/'; /* Can't delete root */
100                                         continue;
101                                 }
102                                 /* Go back one level... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > destname; d--) {
105                                         if (*d == '/') {
106                                                 break;
107                                         }
108                                 }
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111                         } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
112                                 /* Component of pathname can't be "." only - skip the '.' . */
113                                 if (s[1] == '/') {
114                                         s += 2;
115                                 } else {
116                                         s++;
117                                 }
118                                 continue;
119                         }
120                 }
121
122                 if (!(*s & 0x80)) {
123                         *d++ = *s++;
124                 } else {
125                         size_t siz;
126                         /* Get the size of the next MB character. */
127                         next_codepoint(s,&siz);
128                         switch(siz) {
129                                 case 5:
130                                         *d++ = *s++;
131                                         /*fall through*/
132                                 case 4:
133                                         *d++ = *s++;
134                                         /*fall through*/
135                                 case 3:
136                                         *d++ = *s++;
137                                         /*fall through*/
138                                 case 2:
139                                         *d++ = *s++;
140                                         /*fall through*/
141                                 case 1:
142                                         *d++ = *s++;
143                                         break;
144                                 default:
145                                         break;
146                         }
147                 }
148                 start_of_name_component = false;
149         }
150         *d = '\0';
151
152         /* And must not end in '/' */
153         if (d > destname + 1 && (*(d-1) == '/')) {
154                 *(d-1) = '\0';
155         }
156
157         DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
158                 lp_servicename(SNUM(conn)), destname ));
159
160         string_set(&conn->connectpath, destname);
161         SAFE_FREE(destname);
162         return true;
163 }
164
165 /****************************************************************************
166  Load parameters specific to a connection/service.
167 ****************************************************************************/
168
169 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
170 {
171         int snum;
172
173         if (!conn)  {
174                 last_conn = NULL;
175                 return(False);
176         }
177
178         conn->lastused_count++;
179
180         snum = SNUM(conn);
181   
182         if (do_chdir &&
183             vfs_ChDir(conn,conn->connectpath) != 0 &&
184             vfs_ChDir(conn,conn->origpath) != 0) {
185                 DEBUG(0,("chdir (%s) failed\n",
186                          conn->connectpath));
187                 return(False);
188         }
189
190         if ((conn == last_conn) && (last_flags == flags)) {
191                 return(True);
192         }
193
194         last_conn = conn;
195         last_flags = flags;
196         
197         /* Obey the client case sensitivity requests - only for clients that support it. */
198         switch (lp_casesensitive(snum)) {
199                 case Auto:
200                         {
201                                 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
202                                 enum remote_arch_types ra_type = get_remote_arch();
203                                 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
204                                         /* Client can't support per-packet case sensitive pathnames. */
205                                         conn->case_sensitive = False;
206                                 } else {
207                                         conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
208                                 }
209                         }
210                         break;
211                 case True:
212                         conn->case_sensitive = True;
213                         break;
214                 default:
215                         conn->case_sensitive = False;
216                         break;
217         }
218         return(True);
219 }
220
221 static int load_registry_service(const char *servicename)
222 {
223         if (!lp_registry_shares()) {
224                 return -1;
225         }
226
227         if ((servicename == NULL) || (*servicename == '\0')) {
228                 return -1;
229         }
230
231         if (strequal(servicename, GLOBAL_NAME)) {
232                 return -2;
233         }
234
235         if (!process_registry_service(servicename)) {
236                 return -1;
237         }
238
239         return lp_servicenumber(servicename);
240 }
241
242 void load_registry_shares(void)
243 {
244         DEBUG(8, ("load_registry_shares()\n"));
245         if (!lp_registry_shares()) {
246                 return;
247         }
248
249         process_registry_shares();
250
251         return;
252 }
253
254 /****************************************************************************
255  Add a home service. Returns the new service number or -1 if fail.
256 ****************************************************************************/
257
258 int add_home_service(const char *service, const char *username, const char *homedir)
259 {
260         int iHomeService;
261
262         if (!service || !homedir)
263                 return -1;
264
265         if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
266                 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
267                         return -1;
268                 }
269         }
270
271         /*
272          * If this is a winbindd provided username, remove
273          * the domain component before adding the service.
274          * Log a warning if the "path=" parameter does not
275          * include any macros.
276          */
277
278         {
279                 const char *p = strchr(service,*lp_winbind_separator());
280
281                 /* We only want the 'user' part of the string */
282                 if (p) {
283                         service = p + 1;
284                 }
285         }
286
287         if (!lp_add_home(service, iHomeService, username, homedir)) {
288                 return -1;
289         }
290         
291         return lp_servicenumber(service);
292
293 }
294
295 /**
296  * Find a service entry.
297  *
298  * @param service is modified (to canonical form??)
299  **/
300
301 int find_service(fstring service)
302 {
303         int iService;
304         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         SMB_STRUCT_STAT st;
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         SET_STAT_INVALID(st);
655
656         if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
657                 return NULL;
658         }       
659
660         conn = conn_new(sconn);
661         if (!conn) {
662                 DEBUG(0,("Couldn't find free connection.\n"));
663                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
664                 return NULL;
665         }
666
667         conn->params->service = snum;
668
669         status = create_connection_server_info(sconn,
670                 conn, snum, vuser ? vuser->server_info : NULL, password,
671                 &conn->server_info);
672
673         if (!NT_STATUS_IS_OK(status)) {
674                 DEBUG(1, ("create_connection_server_info failed: %s\n",
675                           nt_errstr(status)));
676                 *pstatus = status;
677                 conn_free(sconn, conn);
678                 return NULL;
679         }
680
681         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
682                 conn->force_user = true;
683         }
684
685         add_session_user(sconn, conn->server_info->unix_name);
686
687         safe_strcpy(conn->client_address,
688                         client_addr(get_client_fd(),addr,sizeof(addr)), 
689                         sizeof(conn->client_address)-1);
690         conn->num_files_open = 0;
691         conn->lastused = conn->lastused_count = time(NULL);
692         conn->used = True;
693         conn->printer = (strncmp(dev,"LPT",3) == 0);
694         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
695                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
696         conn->dirptr = NULL;
697
698         /* Case options for the share. */
699         if (lp_casesensitive(snum) == Auto) {
700                 /* We will be setting this per packet. Set to be case
701                  * insensitive for now. */
702                 conn->case_sensitive = False;
703         } else {
704                 conn->case_sensitive = (bool)lp_casesensitive(snum);
705         }
706
707         conn->case_preserve = lp_preservecase(snum);
708         conn->short_case_preserve = lp_shortpreservecase(snum);
709
710         conn->encrypt_level = lp_smb_encrypt(snum);
711
712         conn->veto_list = NULL;
713         conn->hide_list = NULL;
714         conn->veto_oplock_list = NULL;
715         conn->aio_write_behind_list = NULL;
716         string_set(&conn->dirpath,"");
717
718         conn->read_only = lp_readonly(SNUM(conn));
719         conn->admin_user = False;
720
721         if (*lp_force_user(snum)) {
722
723                 /*
724                  * Replace conn->server_info with a completely faked up one
725                  * from the username we are forced into :-)
726                  */
727
728                 char *fuser;
729                 struct auth_serversupplied_info *forced_serverinfo;
730
731                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
732                                           lp_servicename(snum));
733                 if (fuser == NULL) {
734                         conn_free(sconn, conn);
735                         *pstatus = NT_STATUS_NO_MEMORY;
736                         return NULL;
737                 }
738
739                 status = make_serverinfo_from_username(
740                         conn, fuser, conn->server_info->guest,
741                         &forced_serverinfo);
742                 if (!NT_STATUS_IS_OK(status)) {
743                         conn_free(sconn, conn);
744                         *pstatus = status;
745                         return NULL;
746                 }
747
748                 TALLOC_FREE(conn->server_info);
749                 conn->server_info = forced_serverinfo;
750
751                 conn->force_user = True;
752                 DEBUG(3,("Forced user %s\n", fuser));
753         }
754
755         /*
756          * If force group is true, then override
757          * any groupid stored for the connecting user.
758          */
759
760         if (*lp_force_group(snum)) {
761
762                 status = find_forced_group(
763                         conn->force_user, snum, conn->server_info->unix_name,
764                         &conn->server_info->ptok->user_sids[1],
765                         &conn->server_info->utok.gid);
766
767                 if (!NT_STATUS_IS_OK(status)) {
768                         conn_free(sconn, conn);
769                         *pstatus = status;
770                         return NULL;
771                 }
772
773                 /*
774                  * We need to cache this gid, to use within
775                  * change_to_user() separately from the conn->server_info
776                  * struct. We only use conn->server_info directly if
777                  * "force_user" was set.
778                  */
779                 conn->force_group_gid = conn->server_info->utok.gid;
780         }
781
782         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
783
784         {
785                 char *s = talloc_sub_advanced(talloc_tos(),
786                                         lp_servicename(SNUM(conn)),
787                                         conn->server_info->unix_name,
788                                         conn->connectpath,
789                                         conn->server_info->utok.gid,
790                                         conn->server_info->sanitized_username,
791                                         pdb_get_domain(conn->server_info->sam_account),
792                                         lp_pathname(snum));
793                 if (!s) {
794                         conn_free(sconn, conn);
795                         *pstatus = NT_STATUS_NO_MEMORY;
796                         return NULL;
797                 }
798
799                 if (!set_conn_connectpath(conn,s)) {
800                         TALLOC_FREE(s);
801                         conn_free(sconn, conn);
802                         *pstatus = NT_STATUS_NO_MEMORY;
803                         return NULL;
804                 }
805                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
806                          lp_servicename(snum)));
807                 TALLOC_FREE(s);
808         }
809
810         /*
811          * New code to check if there's a share security descripter
812          * added from NT server manager. This is done after the
813          * smb.conf checks are done as we need a uid and token. JRA.
814          *
815          */
816
817         {
818                 bool can_write = False;
819
820                 can_write = share_access_check(conn->server_info->ptok,
821                                                lp_servicename(snum),
822                                                FILE_WRITE_DATA);
823
824                 if (!can_write) {
825                         if (!share_access_check(conn->server_info->ptok,
826                                                 lp_servicename(snum),
827                                                 FILE_READ_DATA)) {
828                                 /* No access, read or write. */
829                                 DEBUG(0,("make_connection: connection to %s "
830                                          "denied due to security "
831                                          "descriptor.\n",
832                                           lp_servicename(snum)));
833                                 conn_free(sconn, conn);
834                                 *pstatus = NT_STATUS_ACCESS_DENIED;
835                                 return NULL;
836                         } else {
837                                 conn->read_only = True;
838                         }
839                 }
840         }
841         /* Initialise VFS function pointers */
842
843         if (!smbd_vfs_init(conn)) {
844                 DEBUG(0, ("vfs_init failed for service %s\n",
845                           lp_servicename(snum)));
846                 conn_free(sconn, conn);
847                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
848                 return NULL;
849         }
850
851         /*
852          * If widelinks are disallowed we need to canonicalise the connect
853          * path here to ensure we don't have any symlinks in the
854          * connectpath. We will be checking all paths on this connection are
855          * below this directory. We must do this after the VFS init as we
856          * depend on the realpath() pointer in the vfs table. JRA.
857          */
858         if (!lp_widelinks(snum)) {
859                 if (!canonicalize_connect_path(conn)) {
860                         DEBUG(0, ("canonicalize_connect_path failed "
861                         "for service %s, path %s\n",
862                                 lp_servicename(snum),
863                                 conn->connectpath));
864                         conn_free(sconn, conn);
865                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
866                         return NULL;
867                 }
868         }
869
870         if ((!conn->printer) && (!conn->ipc)) {
871                 conn->notify_ctx = notify_init(conn, server_id_self(),
872                                                smbd_messaging_context(),
873                                                smbd_event_context(),
874                                                conn);
875         }
876
877 /* ROOT Activities: */  
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(sconn, 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(sconn, conn);
899                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
900                 return NULL;
901         }  
902
903         /* Preexecs are done here as they might make the dir we are to ChDir
904          * to below */
905         /* execute any "root preexec = " line */
906         if (*lp_rootpreexec(snum)) {
907                 char *cmd = talloc_sub_advanced(talloc_tos(),
908                                         lp_servicename(SNUM(conn)),
909                                         conn->server_info->unix_name,
910                                         conn->connectpath,
911                                         conn->server_info->utok.gid,
912                                         conn->server_info->sanitized_username,
913                                         pdb_get_domain(conn->server_info->sam_account),
914                                         lp_rootpreexec(snum));
915                 DEBUG(5,("cmd=%s\n",cmd));
916                 ret = smbrun(cmd,NULL);
917                 TALLOC_FREE(cmd);
918                 if (ret != 0 && lp_rootpreexec_close(snum)) {
919                         DEBUG(1,("root preexec gave %d - failing "
920                                  "connection\n", ret));
921                         yield_connection(conn, lp_servicename(snum));
922                         conn_free(sconn, conn);
923                         *pstatus = NT_STATUS_ACCESS_DENIED;
924                         return NULL;
925                 }
926         }
927
928 /* USER Activites: */
929         if (!change_to_user(conn, conn->vuid)) {
930                 /* No point continuing if they fail the basic checks */
931                 DEBUG(0,("Can't become connected user!\n"));
932                 yield_connection(conn, lp_servicename(snum));
933                 conn_free(sconn, conn);
934                 *pstatus = NT_STATUS_LOGON_FAILURE;
935                 return NULL;
936         }
937
938         /* Remember that a different vuid can connect later without these
939          * checks... */
940         
941         /* Preexecs are done here as they might make the dir we are to ChDir
942          * to below */
943
944         /* execute any "preexec = " line */
945         if (*lp_preexec(snum)) {
946                 char *cmd = talloc_sub_advanced(talloc_tos(),
947                                         lp_servicename(SNUM(conn)),
948                                         conn->server_info->unix_name,
949                                         conn->connectpath,
950                                         conn->server_info->utok.gid,
951                                         conn->server_info->sanitized_username,
952                                         pdb_get_domain(conn->server_info->sam_account),
953                                         lp_preexec(snum));
954                 ret = smbrun(cmd,NULL);
955                 TALLOC_FREE(cmd);
956                 if (ret != 0 && lp_preexec_close(snum)) {
957                         DEBUG(1,("preexec gave %d - failing connection\n",
958                                  ret));
959                         *pstatus = NT_STATUS_ACCESS_DENIED;
960                         goto err_root_exit;
961                 }
962         }
963
964 #ifdef WITH_FAKE_KASERVER
965         if (lp_afs_share(snum)) {
966                 afs_login(conn);
967         }
968 #endif
969         
970         /* Add veto/hide lists */
971         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
972                 set_namearray( &conn->veto_list, lp_veto_files(snum));
973                 set_namearray( &conn->hide_list, lp_hide_files(snum));
974                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
975                 set_namearray( &conn->aio_write_behind_list,
976                                 lp_aio_write_behind(snum));
977         }
978         
979         /* Invoke VFS make connection hook - do this before the VFS_STAT call
980            to allow any filesystems needing user credentials to initialize
981            themselves. */
982
983         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
984                             conn->server_info->unix_name) < 0) {
985                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
986                 *pstatus = NT_STATUS_UNSUCCESSFUL;
987                 goto err_root_exit;
988         }
989
990         /* Any error exit after here needs to call the disconnect hook. */
991         on_err_call_dis_hook = true;
992
993         /* win2000 does not check the permissions on the directory
994            during the tree connect, instead relying on permission
995            check during individual operations. To match this behaviour
996            I have disabled this chdir check (tridge) */
997         /* the alternative is just to check the directory exists */
998         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
999             !S_ISDIR(st.st_ex_mode)) {
1000                 if (ret == 0 && !S_ISDIR(st.st_ex_mode)) {
1001                         DEBUG(0,("'%s' is not a directory, when connecting to "
1002                                  "[%s]\n", conn->connectpath,
1003                                  lp_servicename(snum)));
1004                 } else {
1005                         DEBUG(0,("'%s' does not exist or permission denied "
1006                                  "when connecting to [%s] Error was %s\n",
1007                                  conn->connectpath, lp_servicename(snum),
1008                                  strerror(errno) ));
1009                 }
1010                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1011                 goto err_root_exit;
1012         }
1013
1014         string_set(&conn->origpath,conn->connectpath);
1015
1016 #if SOFTLINK_OPTIMISATION
1017         /* resolve any soft links early if possible */
1018         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1019                 TALLOC_CTX *ctx = talloc_tos();
1020                 char *s = vfs_GetWd(ctx,s);
1021                 if (!s) {
1022                         *status = map_nt_error_from_unix(errno);
1023                         goto err_root_exit;
1024                 }
1025                 if (!set_conn_connectpath(conn,s)) {
1026                         *status = NT_STATUS_NO_MEMORY;
1027                         goto err_root_exit;
1028                 }
1029                 vfs_ChDir(conn,conn->connectpath);
1030         }
1031 #endif
1032
1033         /* Figure out the characteristics of the underlying filesystem. This
1034          * assumes that all the filesystem mounted withing a share path have
1035          * the same characteristics, which is likely but not guaranteed.
1036          */
1037
1038         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1039
1040         /*
1041          * Print out the 'connected as' stuff here as we need
1042          * to know the effective uid and gid we will be using
1043          * (at least initially).
1044          */
1045
1046         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1047                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1048                          conn->client_address );
1049                 dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
1050                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1051                 dbgtext( "initially as user %s ",
1052                          conn->server_info->unix_name );
1053                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1054                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1055         }
1056
1057         /* we've finished with the user stuff - go back to root */
1058         change_to_root_user();
1059         return(conn);
1060
1061   err_root_exit:
1062
1063         change_to_root_user();
1064         if (on_err_call_dis_hook) {
1065                 /* Call VFS disconnect hook */
1066                 SMB_VFS_DISCONNECT(conn);
1067         }
1068         yield_connection(conn, lp_servicename(snum));
1069         conn_free(sconn, conn);
1070         return NULL;
1071 }
1072
1073 /****************************************************************************
1074  Make a connection to a service.
1075  *
1076  * @param service 
1077 ****************************************************************************/
1078
1079 connection_struct *make_connection(struct smbd_server_connection *sconn,
1080                                    const char *service_in, DATA_BLOB password,
1081                                    const char *pdev, uint16 vuid,
1082                                    NTSTATUS *status)
1083 {
1084         uid_t euid;
1085         user_struct *vuser = NULL;
1086         fstring service;
1087         fstring dev;
1088         int snum = -1;
1089         char addr[INET6_ADDRSTRLEN];
1090
1091         fstrcpy(dev, pdev);
1092
1093         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1094          * root. */
1095         if (!non_root_mode() && (euid = geteuid()) != 0) {
1096                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1097                          "(%u)\n", (unsigned int)euid ));
1098                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1099         }
1100
1101         if (conn_num_open(sconn) > 2047) {
1102                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1103                 return NULL;
1104         }
1105
1106         if(lp_security() != SEC_SHARE) {
1107                 vuser = get_valid_user_struct(sconn, vuid);
1108                 if (!vuser) {
1109                         DEBUG(1,("make_connection: refusing to connect with "
1110                                  "no session setup\n"));
1111                         *status = NT_STATUS_ACCESS_DENIED;
1112                         return NULL;
1113                 }
1114         }
1115
1116         /* Logic to try and connect to the correct [homes] share, preferably
1117            without too many getpwnam() lookups.  This is particulary nasty for
1118            winbind usernames, where the share name isn't the same as unix
1119            username.
1120
1121            The snum of the homes share is stored on the vuser at session setup
1122            time.
1123         */
1124
1125         if (strequal(service_in,HOMES_NAME)) {
1126                 if(lp_security() != SEC_SHARE) {
1127                         DATA_BLOB no_pw = data_blob_null;
1128                         if (vuser->homes_snum == -1) {
1129                                 DEBUG(2, ("[homes] share not available for "
1130                                           "this user because it was not found "
1131                                           "or created at session setup "
1132                                           "time\n"));
1133                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1134                                 return NULL;
1135                         }
1136                         DEBUG(5, ("making a connection to [homes] service "
1137                                   "created at session setup time\n"));
1138                         return make_connection_snum(sconn,
1139                                                     vuser->homes_snum,
1140                                                     vuser, no_pw, 
1141                                                     dev, status);
1142                 } else {
1143                         /* Security = share. Try with
1144                          * current_user_info.smb_name as the username.  */
1145                         if (*current_user_info.smb_name) {
1146                                 fstring unix_username;
1147                                 fstrcpy(unix_username,
1148                                         current_user_info.smb_name);
1149                                 map_username(sconn, unix_username);
1150                                 snum = find_service(unix_username);
1151                         } 
1152                         if (snum != -1) {
1153                                 DEBUG(5, ("making a connection to 'homes' "
1154                                           "service %s based on "
1155                                           "security=share\n", service_in));
1156                                 return make_connection_snum(sconn,
1157                                                             snum, NULL,
1158                                                             password,
1159                                                             dev, status);
1160                         }
1161                 }
1162         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1163                    && strequal(service_in,
1164                                lp_servicename(vuser->homes_snum))) {
1165                 DATA_BLOB no_pw = data_blob_null;
1166                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1167                           "created at session setup time\n", service_in));
1168                 return make_connection_snum(sconn,
1169                                             vuser->homes_snum,
1170                                             vuser, no_pw, 
1171                                             dev, status);
1172         }
1173         
1174         fstrcpy(service, service_in);
1175
1176         strlower_m(service);
1177
1178         snum = find_service(service);
1179
1180         if (snum < 0) {
1181                 if (strequal(service,"IPC$") ||
1182                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1183                         DEBUG(3,("refusing IPC connection to %s\n", service));
1184                         *status = NT_STATUS_ACCESS_DENIED;
1185                         return NULL;
1186                 }
1187
1188                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1189                         get_remote_machine_name(),
1190                         client_addr(get_client_fd(),addr,sizeof(addr)),
1191                         service));
1192                 *status = NT_STATUS_BAD_NETWORK_NAME;
1193                 return NULL;
1194         }
1195
1196         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1197         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1198                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1199                           "(pointing to %s)\n", 
1200                         service, lp_msdfs_proxy(snum)));
1201                 *status = NT_STATUS_BAD_NETWORK_NAME;
1202                 return NULL;
1203         }
1204
1205         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1206
1207         return make_connection_snum(sconn, snum, vuser,
1208                                     password,
1209                                     dev, status);
1210 }
1211
1212 /****************************************************************************
1213  Close a cnum.
1214 ****************************************************************************/
1215
1216 void close_cnum(struct smbd_server_connection *sconn,
1217                 connection_struct *conn, uint16 vuid)
1218 {
1219         file_close_conn(conn);
1220
1221         if (!IS_IPC(conn)) {
1222                 dptr_closecnum(conn);
1223         }
1224
1225         change_to_root_user();
1226
1227         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1228                                  get_remote_machine_name(),
1229                                  conn->client_address,
1230                                  lp_servicename(SNUM(conn))));
1231
1232         /* Call VFS disconnect hook */    
1233         SMB_VFS_DISCONNECT(conn);
1234
1235         yield_connection(conn, lp_servicename(SNUM(conn)));
1236
1237         /* make sure we leave the directory available for unmount */
1238         vfs_ChDir(conn, "/");
1239
1240         /* execute any "postexec = " line */
1241         if (*lp_postexec(SNUM(conn)) && 
1242             change_to_user(conn, vuid))  {
1243                 char *cmd = talloc_sub_advanced(talloc_tos(),
1244                                         lp_servicename(SNUM(conn)),
1245                                         conn->server_info->unix_name,
1246                                         conn->connectpath,
1247                                         conn->server_info->utok.gid,
1248                                         conn->server_info->sanitized_username,
1249                                         pdb_get_domain(conn->server_info->sam_account),
1250                                         lp_postexec(SNUM(conn)));
1251                 smbrun(cmd,NULL);
1252                 TALLOC_FREE(cmd);
1253                 change_to_root_user();
1254         }
1255
1256         change_to_root_user();
1257         /* execute any "root postexec = " line */
1258         if (*lp_rootpostexec(SNUM(conn)))  {
1259                 char *cmd = talloc_sub_advanced(talloc_tos(),
1260                                         lp_servicename(SNUM(conn)),
1261                                         conn->server_info->unix_name,
1262                                         conn->connectpath,
1263                                         conn->server_info->utok.gid,
1264                                         conn->server_info->sanitized_username,
1265                                         pdb_get_domain(conn->server_info->sam_account),
1266                                         lp_rootpostexec(SNUM(conn)));
1267                 smbrun(cmd,NULL);
1268                 TALLOC_FREE(cmd);
1269         }
1270
1271         conn_free(sconn, conn);
1272 }