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