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