s3:smbd: add a smbd_server_connection pointer to connection_struct
[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         conn->dirptr = NULL;
696
697         /* Case options for the share. */
698         if (lp_casesensitive(snum) == Auto) {
699                 /* We will be setting this per packet. Set to be case
700                  * insensitive for now. */
701                 conn->case_sensitive = False;
702         } else {
703                 conn->case_sensitive = (bool)lp_casesensitive(snum);
704         }
705
706         conn->case_preserve = lp_preservecase(snum);
707         conn->short_case_preserve = lp_shortpreservecase(snum);
708
709         conn->encrypt_level = lp_smb_encrypt(snum);
710
711         conn->veto_list = NULL;
712         conn->hide_list = NULL;
713         conn->veto_oplock_list = NULL;
714         conn->aio_write_behind_list = NULL;
715         string_set(&conn->dirpath,"");
716
717         conn->read_only = lp_readonly(SNUM(conn));
718         conn->admin_user = False;
719
720         if (*lp_force_user(snum)) {
721
722                 /*
723                  * Replace conn->server_info with a completely faked up one
724                  * from the username we are forced into :-)
725                  */
726
727                 char *fuser;
728                 struct auth_serversupplied_info *forced_serverinfo;
729
730                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
731                                           lp_servicename(snum));
732                 if (fuser == NULL) {
733                         conn_free(conn);
734                         *pstatus = NT_STATUS_NO_MEMORY;
735                         return NULL;
736                 }
737
738                 status = make_serverinfo_from_username(
739                         conn, fuser, conn->server_info->guest,
740                         &forced_serverinfo);
741                 if (!NT_STATUS_IS_OK(status)) {
742                         conn_free(conn);
743                         *pstatus = status;
744                         return NULL;
745                 }
746
747                 TALLOC_FREE(conn->server_info);
748                 conn->server_info = forced_serverinfo;
749
750                 conn->force_user = True;
751                 DEBUG(3,("Forced user %s\n", fuser));
752         }
753
754         /*
755          * If force group is true, then override
756          * any groupid stored for the connecting user.
757          */
758
759         if (*lp_force_group(snum)) {
760
761                 status = find_forced_group(
762                         conn->force_user, snum, conn->server_info->unix_name,
763                         &conn->server_info->ptok->user_sids[1],
764                         &conn->server_info->utok.gid);
765
766                 if (!NT_STATUS_IS_OK(status)) {
767                         conn_free(conn);
768                         *pstatus = status;
769                         return NULL;
770                 }
771
772                 /*
773                  * We need to cache this gid, to use within
774                  * change_to_user() separately from the conn->server_info
775                  * struct. We only use conn->server_info directly if
776                  * "force_user" was set.
777                  */
778                 conn->force_group_gid = conn->server_info->utok.gid;
779         }
780
781         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
782
783         {
784                 char *s = talloc_sub_advanced(talloc_tos(),
785                                         lp_servicename(SNUM(conn)),
786                                         conn->server_info->unix_name,
787                                         conn->connectpath,
788                                         conn->server_info->utok.gid,
789                                         conn->server_info->sanitized_username,
790                                         pdb_get_domain(conn->server_info->sam_account),
791                                         lp_pathname(snum));
792                 if (!s) {
793                         conn_free(conn);
794                         *pstatus = NT_STATUS_NO_MEMORY;
795                         return NULL;
796                 }
797
798                 if (!set_conn_connectpath(conn,s)) {
799                         TALLOC_FREE(s);
800                         conn_free(conn);
801                         *pstatus = NT_STATUS_NO_MEMORY;
802                         return NULL;
803                 }
804                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
805                          lp_servicename(snum)));
806                 TALLOC_FREE(s);
807         }
808
809         /*
810          * New code to check if there's a share security descripter
811          * added from NT server manager. This is done after the
812          * smb.conf checks are done as we need a uid and token. JRA.
813          *
814          */
815
816         {
817                 bool can_write = False;
818
819                 can_write = share_access_check(conn->server_info->ptok,
820                                                lp_servicename(snum),
821                                                FILE_WRITE_DATA);
822
823                 if (!can_write) {
824                         if (!share_access_check(conn->server_info->ptok,
825                                                 lp_servicename(snum),
826                                                 FILE_READ_DATA)) {
827                                 /* No access, read or write. */
828                                 DEBUG(0,("make_connection: connection to %s "
829                                          "denied due to security "
830                                          "descriptor.\n",
831                                           lp_servicename(snum)));
832                                 conn_free(conn);
833                                 *pstatus = NT_STATUS_ACCESS_DENIED;
834                                 return NULL;
835                         } else {
836                                 conn->read_only = True;
837                         }
838                 }
839         }
840         /* Initialise VFS function pointers */
841
842         if (!smbd_vfs_init(conn)) {
843                 DEBUG(0, ("vfs_init failed for service %s\n",
844                           lp_servicename(snum)));
845                 conn_free(conn);
846                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
847                 return NULL;
848         }
849
850         /*
851          * If widelinks are disallowed we need to canonicalise the connect
852          * path here to ensure we don't have any symlinks in the
853          * connectpath. We will be checking all paths on this connection are
854          * below this directory. We must do this after the VFS init as we
855          * depend on the realpath() pointer in the vfs table. JRA.
856          */
857         if (!lp_widelinks(snum)) {
858                 if (!canonicalize_connect_path(conn)) {
859                         DEBUG(0, ("canonicalize_connect_path failed "
860                         "for service %s, path %s\n",
861                                 lp_servicename(snum),
862                                 conn->connectpath));
863                         conn_free(conn);
864                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
865                         return NULL;
866                 }
867         }
868
869         if ((!conn->printer) && (!conn->ipc)) {
870                 conn->notify_ctx = notify_init(conn, server_id_self(),
871                                                smbd_messaging_context(),
872                                                smbd_event_context(),
873                                                conn);
874         }
875
876 /* ROOT Activities: */  
877         /*
878          * Enforce the max connections parameter.
879          */
880
881         if ((lp_max_connections(snum) > 0)
882             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
883                 lp_max_connections(snum))) {
884
885                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
886                           lp_max_connections(snum), lp_servicename(snum)));
887                 conn_free(conn);
888                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
889                 return NULL;
890         }  
891
892         /*
893          * Get us an entry in the connections db
894          */
895         if (!claim_connection(conn, lp_servicename(snum), 0)) {
896                 DEBUG(1, ("Could not store connections entry\n"));
897                 conn_free(conn);
898                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
899                 return NULL;
900         }  
901
902         /* Preexecs are done here as they might make the dir we are to ChDir
903          * to below */
904         /* execute any "root preexec = " line */
905         if (*lp_rootpreexec(snum)) {
906                 char *cmd = talloc_sub_advanced(talloc_tos(),
907                                         lp_servicename(SNUM(conn)),
908                                         conn->server_info->unix_name,
909                                         conn->connectpath,
910                                         conn->server_info->utok.gid,
911                                         conn->server_info->sanitized_username,
912                                         pdb_get_domain(conn->server_info->sam_account),
913                                         lp_rootpreexec(snum));
914                 DEBUG(5,("cmd=%s\n",cmd));
915                 ret = smbrun(cmd,NULL);
916                 TALLOC_FREE(cmd);
917                 if (ret != 0 && lp_rootpreexec_close(snum)) {
918                         DEBUG(1,("root preexec gave %d - failing "
919                                  "connection\n", ret));
920                         yield_connection(conn, lp_servicename(snum));
921                         conn_free(conn);
922                         *pstatus = NT_STATUS_ACCESS_DENIED;
923                         return NULL;
924                 }
925         }
926
927 /* USER Activites: */
928         if (!change_to_user(conn, conn->vuid)) {
929                 /* No point continuing if they fail the basic checks */
930                 DEBUG(0,("Can't become connected user!\n"));
931                 yield_connection(conn, lp_servicename(snum));
932                 conn_free(conn);
933                 *pstatus = NT_STATUS_LOGON_FAILURE;
934                 return NULL;
935         }
936
937         /* Remember that a different vuid can connect later without these
938          * checks... */
939         
940         /* Preexecs are done here as they might make the dir we are to ChDir
941          * to below */
942
943         /* execute any "preexec = " line */
944         if (*lp_preexec(snum)) {
945                 char *cmd = talloc_sub_advanced(talloc_tos(),
946                                         lp_servicename(SNUM(conn)),
947                                         conn->server_info->unix_name,
948                                         conn->connectpath,
949                                         conn->server_info->utok.gid,
950                                         conn->server_info->sanitized_username,
951                                         pdb_get_domain(conn->server_info->sam_account),
952                                         lp_preexec(snum));
953                 ret = smbrun(cmd,NULL);
954                 TALLOC_FREE(cmd);
955                 if (ret != 0 && lp_preexec_close(snum)) {
956                         DEBUG(1,("preexec gave %d - failing connection\n",
957                                  ret));
958                         *pstatus = NT_STATUS_ACCESS_DENIED;
959                         goto err_root_exit;
960                 }
961         }
962
963 #ifdef WITH_FAKE_KASERVER
964         if (lp_afs_share(snum)) {
965                 afs_login(conn);
966         }
967 #endif
968         
969         /* Add veto/hide lists */
970         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
971                 set_namearray( &conn->veto_list, lp_veto_files(snum));
972                 set_namearray( &conn->hide_list, lp_hide_files(snum));
973                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
974                 set_namearray( &conn->aio_write_behind_list,
975                                 lp_aio_write_behind(snum));
976         }
977         
978         /* Invoke VFS make connection hook - do this before the VFS_STAT call
979            to allow any filesystems needing user credentials to initialize
980            themselves. */
981
982         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
983                             conn->server_info->unix_name) < 0) {
984                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
985                 *pstatus = NT_STATUS_UNSUCCESSFUL;
986                 goto err_root_exit;
987         }
988
989         /* Any error exit after here needs to call the disconnect hook. */
990         on_err_call_dis_hook = true;
991
992         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
993                                             NULL, NULL, &smb_fname_cpath);
994         if (!NT_STATUS_IS_OK(status)) {
995                 *pstatus = status;
996                 goto err_root_exit;
997         }
998
999         /* win2000 does not check the permissions on the directory
1000            during the tree connect, instead relying on permission
1001            check during individual operations. To match this behaviour
1002            I have disabled this chdir check (tridge) */
1003         /* the alternative is just to check the directory exists */
1004         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1005             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1006                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1007                         DEBUG(0,("'%s' is not a directory, when connecting to "
1008                                  "[%s]\n", conn->connectpath,
1009                                  lp_servicename(snum)));
1010                 } else {
1011                         DEBUG(0,("'%s' does not exist or permission denied "
1012                                  "when connecting to [%s] Error was %s\n",
1013                                  conn->connectpath, lp_servicename(snum),
1014                                  strerror(errno) ));
1015                 }
1016                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1017                 goto err_root_exit;
1018         }
1019
1020         string_set(&conn->origpath,conn->connectpath);
1021
1022 #if SOFTLINK_OPTIMISATION
1023         /* resolve any soft links early if possible */
1024         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1025                 TALLOC_CTX *ctx = talloc_tos();
1026                 char *s = vfs_GetWd(ctx,s);
1027                 if (!s) {
1028                         *status = map_nt_error_from_unix(errno);
1029                         goto err_root_exit;
1030                 }
1031                 if (!set_conn_connectpath(conn,s)) {
1032                         *status = NT_STATUS_NO_MEMORY;
1033                         goto err_root_exit;
1034                 }
1035                 vfs_ChDir(conn,conn->connectpath);
1036         }
1037 #endif
1038
1039         /* Figure out the characteristics of the underlying filesystem. This
1040          * assumes that all the filesystem mounted withing a share path have
1041          * the same characteristics, which is likely but not guaranteed.
1042          */
1043
1044         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1045
1046         /*
1047          * Print out the 'connected as' stuff here as we need
1048          * to know the effective uid and gid we will be using
1049          * (at least initially).
1050          */
1051
1052         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1053                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1054                          conn->client_address );
1055                 dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
1056                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1057                 dbgtext( "initially as user %s ",
1058                          conn->server_info->unix_name );
1059                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1060                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1061         }
1062
1063         /* we've finished with the user stuff - go back to root */
1064         change_to_root_user();
1065         return(conn);
1066
1067   err_root_exit:
1068         TALLOC_FREE(smb_fname_cpath);
1069         change_to_root_user();
1070         if (on_err_call_dis_hook) {
1071                 /* Call VFS disconnect hook */
1072                 SMB_VFS_DISCONNECT(conn);
1073         }
1074         yield_connection(conn, lp_servicename(snum));
1075         conn_free(conn);
1076         return NULL;
1077 }
1078
1079 /****************************************************************************
1080  Make a connection to a service.
1081  *
1082  * @param service 
1083 ****************************************************************************/
1084
1085 connection_struct *make_connection(struct smbd_server_connection *sconn,
1086                                    const char *service_in, DATA_BLOB password,
1087                                    const char *pdev, uint16 vuid,
1088                                    NTSTATUS *status)
1089 {
1090         uid_t euid;
1091         user_struct *vuser = NULL;
1092         fstring service;
1093         fstring dev;
1094         int snum = -1;
1095         char addr[INET6_ADDRSTRLEN];
1096
1097         fstrcpy(dev, pdev);
1098
1099         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1100          * root. */
1101         if (!non_root_mode() && (euid = geteuid()) != 0) {
1102                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1103                          "(%u)\n", (unsigned int)euid ));
1104                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1105         }
1106
1107         if (conn_num_open(sconn) > 2047) {
1108                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1109                 return NULL;
1110         }
1111
1112         if(lp_security() != SEC_SHARE) {
1113                 vuser = get_valid_user_struct(sconn, vuid);
1114                 if (!vuser) {
1115                         DEBUG(1,("make_connection: refusing to connect with "
1116                                  "no session setup\n"));
1117                         *status = NT_STATUS_ACCESS_DENIED;
1118                         return NULL;
1119                 }
1120         }
1121
1122         /* Logic to try and connect to the correct [homes] share, preferably
1123            without too many getpwnam() lookups.  This is particulary nasty for
1124            winbind usernames, where the share name isn't the same as unix
1125            username.
1126
1127            The snum of the homes share is stored on the vuser at session setup
1128            time.
1129         */
1130
1131         if (strequal(service_in,HOMES_NAME)) {
1132                 if(lp_security() != SEC_SHARE) {
1133                         DATA_BLOB no_pw = data_blob_null;
1134                         if (vuser->homes_snum == -1) {
1135                                 DEBUG(2, ("[homes] share not available for "
1136                                           "this user because it was not found "
1137                                           "or created at session setup "
1138                                           "time\n"));
1139                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1140                                 return NULL;
1141                         }
1142                         DEBUG(5, ("making a connection to [homes] service "
1143                                   "created at session setup time\n"));
1144                         return make_connection_snum(sconn,
1145                                                     vuser->homes_snum,
1146                                                     vuser, no_pw, 
1147                                                     dev, status);
1148                 } else {
1149                         /* Security = share. Try with
1150                          * current_user_info.smb_name as the username.  */
1151                         if (*current_user_info.smb_name) {
1152                                 fstring unix_username;
1153                                 fstrcpy(unix_username,
1154                                         current_user_info.smb_name);
1155                                 map_username(sconn, unix_username);
1156                                 snum = find_service(unix_username);
1157                         } 
1158                         if (snum != -1) {
1159                                 DEBUG(5, ("making a connection to 'homes' "
1160                                           "service %s based on "
1161                                           "security=share\n", service_in));
1162                                 return make_connection_snum(sconn,
1163                                                             snum, NULL,
1164                                                             password,
1165                                                             dev, status);
1166                         }
1167                 }
1168         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1169                    && strequal(service_in,
1170                                lp_servicename(vuser->homes_snum))) {
1171                 DATA_BLOB no_pw = data_blob_null;
1172                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1173                           "created at session setup time\n", service_in));
1174                 return make_connection_snum(sconn,
1175                                             vuser->homes_snum,
1176                                             vuser, no_pw, 
1177                                             dev, status);
1178         }
1179         
1180         fstrcpy(service, service_in);
1181
1182         strlower_m(service);
1183
1184         snum = find_service(service);
1185
1186         if (snum < 0) {
1187                 if (strequal(service,"IPC$") ||
1188                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1189                         DEBUG(3,("refusing IPC connection to %s\n", service));
1190                         *status = NT_STATUS_ACCESS_DENIED;
1191                         return NULL;
1192                 }
1193
1194                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1195                         get_remote_machine_name(),
1196                         client_addr(get_client_fd(),addr,sizeof(addr)),
1197                         service));
1198                 *status = NT_STATUS_BAD_NETWORK_NAME;
1199                 return NULL;
1200         }
1201
1202         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1203         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1204                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1205                           "(pointing to %s)\n", 
1206                         service, lp_msdfs_proxy(snum)));
1207                 *status = NT_STATUS_BAD_NETWORK_NAME;
1208                 return NULL;
1209         }
1210
1211         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1212
1213         return make_connection_snum(sconn, snum, vuser,
1214                                     password,
1215                                     dev, status);
1216 }
1217
1218 /****************************************************************************
1219  Close a cnum.
1220 ****************************************************************************/
1221
1222 void close_cnum(connection_struct *conn, uint16 vuid)
1223 {
1224         file_close_conn(conn);
1225
1226         if (!IS_IPC(conn)) {
1227                 dptr_closecnum(conn);
1228         }
1229
1230         change_to_root_user();
1231
1232         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1233                                  get_remote_machine_name(),
1234                                  conn->client_address,
1235                                  lp_servicename(SNUM(conn))));
1236
1237         /* Call VFS disconnect hook */    
1238         SMB_VFS_DISCONNECT(conn);
1239
1240         yield_connection(conn, lp_servicename(SNUM(conn)));
1241
1242         /* make sure we leave the directory available for unmount */
1243         vfs_ChDir(conn, "/");
1244
1245         /* execute any "postexec = " line */
1246         if (*lp_postexec(SNUM(conn)) && 
1247             change_to_user(conn, vuid))  {
1248                 char *cmd = talloc_sub_advanced(talloc_tos(),
1249                                         lp_servicename(SNUM(conn)),
1250                                         conn->server_info->unix_name,
1251                                         conn->connectpath,
1252                                         conn->server_info->utok.gid,
1253                                         conn->server_info->sanitized_username,
1254                                         pdb_get_domain(conn->server_info->sam_account),
1255                                         lp_postexec(SNUM(conn)));
1256                 smbrun(cmd,NULL);
1257                 TALLOC_FREE(cmd);
1258                 change_to_root_user();
1259         }
1260
1261         change_to_root_user();
1262         /* execute any "root postexec = " line */
1263         if (*lp_rootpostexec(SNUM(conn)))  {
1264                 char *cmd = talloc_sub_advanced(talloc_tos(),
1265                                         lp_servicename(SNUM(conn)),
1266                                         conn->server_info->unix_name,
1267                                         conn->connectpath,
1268                                         conn->server_info->utok.gid,
1269                                         conn->server_info->sanitized_username,
1270                                         pdb_get_domain(conn->server_info->sam_account),
1271                                         lp_rootpostexec(SNUM(conn)));
1272                 smbrun(cmd,NULL);
1273                 TALLOC_FREE(cmd);
1274         }
1275
1276         conn_free(conn);
1277 }