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