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