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