libcli/security Provide a common, top level libcli/security/security.h
[ab/samba.git/.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(fstring service)
309 {
310         int iService;
311
312         all_string_sub(service,"\\","/",0);
313
314         iService = lp_servicenumber(service);
315
316         /* now handle the special case of a home directory */
317         if (iService < 0) {
318                 char *phome_dir = get_user_home_dir(talloc_tos(), service);
319
320                 if(!phome_dir) {
321                         /*
322                          * Try mapping the servicename, it may
323                          * be a Windows to unix mapped user name.
324                          */
325                         if(map_username(service))
326                                 phome_dir = get_user_home_dir(
327                                         talloc_tos(), service);
328                 }
329
330                 DEBUG(3,("checking for home directory %s gave %s\n",service,
331                         phome_dir?phome_dir:"(NULL)"));
332
333                 iService = add_home_service(service,service /* 'username' */, phome_dir);
334         }
335
336         /* If we still don't have a service, attempt to add it as a printer. */
337         if (iService < 0) {
338                 int iPrinterService;
339
340                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
341                         iPrinterService = load_registry_service(PRINTERS_NAME);
342                 }
343                 if (iPrinterService >= 0) {
344                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
345                         if (pcap_printername_ok(service)) {
346                                 DEBUG(3,("%s is a valid printer name\n", service));
347                                 DEBUG(3,("adding %s as a printer service\n", service));
348                                 lp_add_printer(service, iPrinterService);
349                                 iService = lp_servicenumber(service);
350                                 if (iService < 0) {
351                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
352                                 }
353                         } else {
354                                 DEBUG(3,("%s is not a valid printer name\n", service));
355                         }
356                 }
357         }
358
359         /* Check for default vfs service?  Unsure whether to implement this */
360         if (iService < 0) {
361         }
362
363         if (iService < 0) {
364                 iService = load_registry_service(service);
365         }
366
367         /* Is it a usershare service ? */
368         if (iService < 0 && *lp_usershare_path()) {
369                 /* Ensure the name is canonicalized. */
370                 strlower_m(service);
371                 iService = load_usershare_service(service);
372         }
373
374         /* just possibly it's a default service? */
375         if (iService < 0) {
376                 char *pdefservice = lp_defaultservice();
377                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
378                         /*
379                          * We need to do a local copy here as lp_defaultservice() 
380                          * returns one of the rotating lp_string buffers that
381                          * could get overwritten by the recursive find_service() call
382                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
383                          */
384                         char *defservice = SMB_STRDUP(pdefservice);
385
386                         if (!defservice) {
387                                 goto fail;
388                         }
389
390                         /* Disallow anything except explicit share names. */
391                         if (strequal(defservice,HOMES_NAME) ||
392                                         strequal(defservice, PRINTERS_NAME) ||
393                                         strequal(defservice, "IPC$")) {
394                                 SAFE_FREE(defservice);
395                                 goto fail;
396                         }
397
398                         iService = find_service(defservice);
399                         if (iService >= 0) {
400                                 all_string_sub(service, "_","/",0);
401                                 iService = lp_add_service(service, iService);
402                         }
403                         SAFE_FREE(defservice);
404                 }
405         }
406
407         if (iService >= 0) {
408                 if (!VALID_SNUM(iService)) {
409                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
410                         iService = -1;
411                 }
412         }
413
414   fail:
415
416         if (iService < 0)
417                 DEBUG(3,("find_service() failed to find service %s\n", service));
418
419         return (iService);
420 }
421
422
423 /****************************************************************************
424  do some basic sainity checks on the share.  
425  This function modifies dev, ecode.
426 ****************************************************************************/
427
428 static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
429                                     fstring dev)
430 {
431         if (!lp_snum_ok(snum) || 
432             !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
433                           client_id->name, client_id->addr)) {
434                 return NT_STATUS_ACCESS_DENIED;
435         }
436
437         if (dev[0] == '?' || !dev[0]) {
438                 if (lp_print_ok(snum)) {
439                         fstrcpy(dev,"LPT1:");
440                 } else if (strequal(lp_fstype(snum), "IPC")) {
441                         fstrcpy(dev, "IPC");
442                 } else {
443                         fstrcpy(dev,"A:");
444                 }
445         }
446
447         strupper_m(dev);
448
449         if (lp_print_ok(snum)) {
450                 if (!strequal(dev, "LPT1:")) {
451                         return NT_STATUS_BAD_DEVICE_TYPE;
452                 }
453         } else if (strequal(lp_fstype(snum), "IPC")) {
454                 if (!strequal(dev, "IPC")) {
455                         return NT_STATUS_BAD_DEVICE_TYPE;
456                 }
457         } else if (!strequal(dev, "A:")) {
458                 return NT_STATUS_BAD_DEVICE_TYPE;
459         }
460
461         /* Behave as a printer if we are supposed to */
462         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
463                 fstrcpy(dev, "LPT1:");
464         }
465
466         return NT_STATUS_OK;
467 }
468
469 /*
470  * Go through lookup_name etc to find the force'd group.  
471  *
472  * Create a new token from src_token, replacing the primary group sid with the
473  * one found.
474  */
475
476 static NTSTATUS find_forced_group(bool force_user,
477                                   int snum, const char *username,
478                                   struct dom_sid *pgroup_sid,
479                                   gid_t *pgid)
480 {
481         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
482         TALLOC_CTX *frame = talloc_stackframe();
483         struct dom_sid group_sid;
484         enum lsa_SidType type;
485         char *groupname;
486         bool user_must_be_member = False;
487         gid_t gid;
488
489         groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
490         if (groupname == NULL) {
491                 DEBUG(1, ("talloc_strdup failed\n"));
492                 result = NT_STATUS_NO_MEMORY;
493                 goto done;
494         }
495
496         if (groupname[0] == '+') {
497                 user_must_be_member = True;
498                 groupname += 1;
499         }
500
501         groupname = talloc_string_sub(talloc_tos(), groupname,
502                                       "%S", lp_servicename(snum));
503         if (groupname == NULL) {
504                 DEBUG(1, ("talloc_string_sub failed\n"));
505                 result = NT_STATUS_NO_MEMORY;
506                 goto done;
507         }
508
509         if (!lookup_name_smbconf(talloc_tos(), groupname,
510                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
511                          NULL, NULL, &group_sid, &type)) {
512                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
513                            groupname));
514                 goto done;
515         }
516
517         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
518             (type != SID_NAME_WKN_GRP)) {
519                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
520                            sid_type_lookup(type)));
521                 goto done;
522         }
523
524         if (!sid_to_gid(&group_sid, &gid)) {
525                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
526                            sid_string_dbg(&group_sid), groupname));
527                 goto done;
528         }
529
530         /*
531          * If the user has been forced and the forced group starts with a '+',
532          * then we only set the group to be the forced group if the forced
533          * user is a member of that group.  Otherwise, the meaning of the '+'
534          * would be ignored.
535          */
536
537         if (force_user && user_must_be_member) {
538                 if (user_in_group_sid(username, &group_sid)) {
539                         sid_copy(pgroup_sid, &group_sid);
540                         *pgid = gid;
541                         DEBUG(3,("Forced group %s for member %s\n",
542                                  groupname, username));
543                 } else {
544                         DEBUG(0,("find_forced_group: forced user %s is not a member "
545                                 "of forced group %s. Disallowing access.\n",
546                                 username, groupname ));
547                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
548                         goto done;
549                 }
550         } else {
551                 sid_copy(pgroup_sid, &group_sid);
552                 *pgid = gid;
553                 DEBUG(3,("Forced group %s\n", groupname));
554         }
555
556         result = NT_STATUS_OK;
557  done:
558         TALLOC_FREE(frame);
559         return result;
560 }
561
562 /****************************************************************************
563   Create an auth_serversupplied_info structure for a connection_struct
564 ****************************************************************************/
565
566 static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
567                                               TALLOC_CTX *mem_ctx, int snum,
568                                               struct auth_serversupplied_info *vuid_serverinfo,
569                                               DATA_BLOB password,
570                                               struct auth_serversupplied_info **presult)
571 {
572         if (lp_guest_only(snum)) {
573                 return make_server_info_guest(mem_ctx, presult);
574         }
575
576         if (vuid_serverinfo != NULL) {
577
578                 struct auth_serversupplied_info *result;
579
580                 /*
581                  * This is the normal security != share case where we have a
582                  * valid vuid from the session setup.                 */
583
584                 if (vuid_serverinfo->guest) {
585                         if (!lp_guest_ok(snum)) {
586                                 DEBUG(2, ("guest user (from session setup) "
587                                           "not permitted to access this share "
588                                           "(%s)\n", lp_servicename(snum)));
589                                 return NT_STATUS_ACCESS_DENIED;
590                         }
591                 } else {
592                         if (!user_ok_token(vuid_serverinfo->unix_name,
593                                            vuid_serverinfo->info3->base.domain.string,
594                                            vuid_serverinfo->ptok, snum)) {
595                                 DEBUG(2, ("user '%s' (from session setup) not "
596                                           "permitted to access this share "
597                                           "(%s)\n",
598                                           vuid_serverinfo->unix_name,
599                                           lp_servicename(snum)));
600                                 return NT_STATUS_ACCESS_DENIED;
601                         }
602                 }
603
604                 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
605                 if (result == NULL) {
606                         return NT_STATUS_NO_MEMORY;
607                 }
608
609                 *presult = result;
610                 return NT_STATUS_OK;
611         }
612
613         if (lp_security() == SEC_SHARE) {
614
615                 fstring user;
616                 bool guest;
617
618                 /* add the sharename as a possible user name if we
619                    are in share mode security */
620
621                 add_session_user(sconn, lp_servicename(snum));
622
623                 /* shall we let them in? */
624
625                 if (!authorise_login(sconn, snum,user,password,&guest)) {
626                         DEBUG( 2, ( "Invalid username/password for [%s]\n",
627                                     lp_servicename(snum)) );
628                         return NT_STATUS_WRONG_PASSWORD;
629                 }
630
631                 return make_serverinfo_from_username(mem_ctx, user, guest,
632                                                      presult);
633         }
634
635         DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
636         return NT_STATUS_ACCESS_DENIED;
637 }
638
639
640 /****************************************************************************
641   Make a connection, given the snum to connect to, and the vuser of the
642   connecting user if appropriate.
643 ****************************************************************************/
644
645 connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
646                                         int snum, user_struct *vuser,
647                                         DATA_BLOB password,
648                                         const char *pdev,
649                                         NTSTATUS *pstatus)
650 {
651         connection_struct *conn = NULL;
652         struct smb_filename *smb_fname_cpath = NULL;
653         fstring dev;
654         int ret;
655         bool on_err_call_dis_hook = false;
656         bool claimed_connection = false;
657         uid_t effuid;
658         gid_t effgid;
659         NTSTATUS status;
660
661         fstrcpy(dev, pdev);
662
663         *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
664         if (NT_STATUS_IS_ERR(*pstatus)) {
665                 goto err_root_exit;
666         }
667
668         conn = conn_new(sconn);
669         if (!conn) {
670                 DEBUG(0,("Couldn't find free connection.\n"));
671                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
672                 goto err_root_exit;
673         }
674
675         conn->params->service = snum;
676
677         status = create_connection_server_info(sconn,
678                 conn, snum, vuser ? vuser->server_info : NULL, password,
679                 &conn->server_info);
680
681         if (!NT_STATUS_IS_OK(status)) {
682                 DEBUG(1, ("create_connection_server_info failed: %s\n",
683                           nt_errstr(status)));
684                 *pstatus = status;
685                 goto err_root_exit;
686         }
687
688         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
689                 conn->force_user = true;
690         }
691
692         add_session_user(sconn, conn->server_info->unix_name);
693
694         conn->num_files_open = 0;
695         conn->lastused = conn->lastused_count = time(NULL);
696         conn->used = True;
697         conn->printer = (strncmp(dev,"LPT",3) == 0);
698         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
699                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
700
701         /* Case options for the share. */
702         if (lp_casesensitive(snum) == Auto) {
703                 /* We will be setting this per packet. Set to be case
704                  * insensitive for now. */
705                 conn->case_sensitive = False;
706         } else {
707                 conn->case_sensitive = (bool)lp_casesensitive(snum);
708         }
709
710         conn->case_preserve = lp_preservecase(snum);
711         conn->short_case_preserve = lp_shortpreservecase(snum);
712
713         conn->encrypt_level = lp_smb_encrypt(snum);
714
715         conn->veto_list = NULL;
716         conn->hide_list = NULL;
717         conn->veto_oplock_list = NULL;
718         conn->aio_write_behind_list = NULL;
719
720         conn->read_only = lp_readonly(SNUM(conn));
721
722         if (*lp_force_user(snum)) {
723
724                 /*
725                  * Replace conn->server_info with a completely faked up one
726                  * from the username we are forced into :-)
727                  */
728
729                 char *fuser;
730                 struct auth_serversupplied_info *forced_serverinfo;
731
732                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
733                                           lp_servicename(snum));
734                 if (fuser == NULL) {
735                         *pstatus = NT_STATUS_NO_MEMORY;
736                         goto err_root_exit;
737                 }
738
739                 status = make_serverinfo_from_username(
740                         conn, fuser, conn->server_info->guest,
741                         &forced_serverinfo);
742                 if (!NT_STATUS_IS_OK(status)) {
743                         *pstatus = status;
744                         goto err_root_exit;
745                 }
746
747                 TALLOC_FREE(conn->server_info);
748                 conn->server_info = forced_serverinfo;
749
750                 conn->force_user = True;
751                 DEBUG(3,("Forced user %s\n", fuser));
752         }
753
754         /*
755          * If force group is true, then override
756          * any groupid stored for the connecting user.
757          */
758
759         if (*lp_force_group(snum)) {
760
761                 status = find_forced_group(
762                         conn->force_user, snum, conn->server_info->unix_name,
763                         &conn->server_info->ptok->sids[1],
764                         &conn->server_info->utok.gid);
765
766                 if (!NT_STATUS_IS_OK(status)) {
767                         *pstatus = status;
768                         goto err_root_exit;
769                 }
770
771                 /*
772                  * We need to cache this gid, to use within
773                  * change_to_user() separately from the conn->server_info
774                  * struct. We only use conn->server_info directly if
775                  * "force_user" was set.
776                  */
777                 conn->force_group_gid = conn->server_info->utok.gid;
778         }
779
780         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
781
782         {
783                 char *s = talloc_sub_advanced(talloc_tos(),
784                                         lp_servicename(SNUM(conn)),
785                                         conn->server_info->unix_name,
786                                         conn->connectpath,
787                                         conn->server_info->utok.gid,
788                                         conn->server_info->sanitized_username,
789                                         conn->server_info->info3->base.domain.string,
790                                         lp_pathname(snum));
791                 if (!s) {
792                         *pstatus = NT_STATUS_NO_MEMORY;
793                         goto err_root_exit;
794                 }
795
796                 if (!set_conn_connectpath(conn,s)) {
797                         TALLOC_FREE(s);
798                         *pstatus = NT_STATUS_NO_MEMORY;
799                         goto err_root_exit;
800                 }
801                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
802                          lp_servicename(snum)));
803                 TALLOC_FREE(s);
804         }
805
806         /*
807          * New code to check if there's a share security descripter
808          * added from NT server manager. This is done after the
809          * smb.conf checks are done as we need a uid and token. JRA.
810          *
811          */
812
813         {
814                 bool can_write = False;
815
816                 can_write = share_access_check(conn->server_info->ptok,
817                                                lp_servicename(snum),
818                                                FILE_WRITE_DATA);
819
820                 if (!can_write) {
821                         if (!share_access_check(conn->server_info->ptok,
822                                                 lp_servicename(snum),
823                                                 FILE_READ_DATA)) {
824                                 /* No access, read or write. */
825                                 DEBUG(0,("make_connection: connection to %s "
826                                          "denied due to security "
827                                          "descriptor.\n",
828                                           lp_servicename(snum)));
829                                 *pstatus = NT_STATUS_ACCESS_DENIED;
830                                 goto err_root_exit;
831                         } else {
832                                 conn->read_only = True;
833                         }
834                 }
835         }
836         /* Initialise VFS function pointers */
837
838         if (!smbd_vfs_init(conn)) {
839                 DEBUG(0, ("vfs_init failed for service %s\n",
840                           lp_servicename(snum)));
841                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
842                 goto err_root_exit;
843         }
844
845 /* ROOT Activities: */
846         /* explicitly check widelinks here so that we can correctly warn
847          * in the logs. */
848         widelinks_warning(snum);
849
850         /*
851          * Enforce the max connections parameter.
852          */
853
854         if ((lp_max_connections(snum) > 0)
855             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
856                 lp_max_connections(snum))) {
857
858                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
859                           lp_max_connections(snum), lp_servicename(snum)));
860                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
861                 goto err_root_exit;
862         }
863
864         /*
865          * Get us an entry in the connections db
866          */
867         if (!claim_connection(conn, lp_servicename(snum))) {
868                 DEBUG(1, ("Could not store connections entry\n"));
869                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
870                 goto err_root_exit;
871         }
872         claimed_connection = true;
873
874         /* Invoke VFS make connection hook - this must be the first
875            filesystem operation that we do. */
876
877         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
878                             conn->server_info->unix_name) < 0) {
879                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
880                 *pstatus = NT_STATUS_UNSUCCESSFUL;
881                 goto err_root_exit;
882         }
883
884         /* Any error exit after here needs to call the disconnect hook. */
885         on_err_call_dis_hook = true;
886
887         if ((!conn->printer) && (!conn->ipc)) {
888                 conn->notify_ctx = notify_init(conn,
889                                                sconn_server_id(sconn),
890                                                sconn->msg_ctx,
891                                                smbd_event_context(),
892                                                conn);
893         }
894
895         /*
896          * Fix compatibility issue pointed out by Volker.
897          * We pass the conn->connectpath to the preexec
898          * scripts as a parameter, so attempt to canonicalize
899          * it here before calling the preexec scripts.
900          * We ignore errors here, as it is possible that
901          * the conn->connectpath doesn't exist yet and
902          * the preexec scripts will create them.
903          */
904
905         (void)canonicalize_connect_path(conn);
906
907         /* Preexecs are done here as they might make the dir we are to ChDir
908          * to below */
909         /* execute any "root preexec = " line */
910         if (*lp_rootpreexec(snum)) {
911                 char *cmd = talloc_sub_advanced(talloc_tos(),
912                                         lp_servicename(SNUM(conn)),
913                                         conn->server_info->unix_name,
914                                         conn->connectpath,
915                                         conn->server_info->utok.gid,
916                                         conn->server_info->sanitized_username,
917                                         conn->server_info->info3->base.domain.string,
918                                         lp_rootpreexec(snum));
919                 DEBUG(5,("cmd=%s\n",cmd));
920                 ret = smbrun(cmd,NULL);
921                 TALLOC_FREE(cmd);
922                 if (ret != 0 && lp_rootpreexec_close(snum)) {
923                         DEBUG(1,("root preexec gave %d - failing "
924                                  "connection\n", ret));
925                         *pstatus = NT_STATUS_ACCESS_DENIED;
926                         goto err_root_exit;
927                 }
928         }
929
930 /* USER Activites: */
931         if (!change_to_user(conn, conn->vuid)) {
932                 /* No point continuing if they fail the basic checks */
933                 DEBUG(0,("Can't become connected user!\n"));
934                 *pstatus = NT_STATUS_LOGON_FAILURE;
935                 goto err_root_exit;
936         }
937
938         effuid = geteuid();
939         effgid = getegid();
940
941         /* Remember that a different vuid can connect later without these
942          * checks... */
943
944         /* Preexecs are done here as they might make the dir we are to ChDir
945          * to below */
946
947         /* execute any "preexec = " line */
948         if (*lp_preexec(snum)) {
949                 char *cmd = talloc_sub_advanced(talloc_tos(),
950                                         lp_servicename(SNUM(conn)),
951                                         conn->server_info->unix_name,
952                                         conn->connectpath,
953                                         conn->server_info->utok.gid,
954                                         conn->server_info->sanitized_username,
955                                         conn->server_info->info3->base.domain.string,
956                                         lp_preexec(snum));
957                 ret = smbrun(cmd,NULL);
958                 TALLOC_FREE(cmd);
959                 if (ret != 0 && lp_preexec_close(snum)) {
960                         DEBUG(1,("preexec gave %d - failing connection\n",
961                                  ret));
962                         *pstatus = NT_STATUS_ACCESS_DENIED;
963                         goto err_root_exit;
964                 }
965         }
966
967 #ifdef WITH_FAKE_KASERVER
968         if (lp_afs_share(snum)) {
969                 afs_login(conn);
970         }
971 #endif
972
973         /*
974          * we've finished with the user stuff - go back to root
975          * so the SMB_VFS_STAT call will only fail on path errors,
976          * not permission problems.
977          */
978         change_to_root_user();
979 /* ROOT Activites: */
980
981         /*
982          * If widelinks are disallowed we need to canonicalise the connect
983          * path here to ensure we don't have any symlinks in the
984          * connectpath. We will be checking all paths on this connection are
985          * below this directory. We must do this after the VFS init as we
986          * depend on the realpath() pointer in the vfs table. JRA.
987          */
988         if (!lp_widelinks(snum)) {
989                 if (!canonicalize_connect_path(conn)) {
990                         DEBUG(0, ("canonicalize_connect_path failed "
991                         "for service %s, path %s\n",
992                                 lp_servicename(snum),
993                                 conn->connectpath));
994                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
995                         goto err_root_exit;
996                 }
997         }
998
999         /* Add veto/hide lists */
1000         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1001                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1002                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1003                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1004                 set_namearray( &conn->aio_write_behind_list,
1005                                 lp_aio_write_behind(snum));
1006         }
1007         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1008                                             NULL, NULL, &smb_fname_cpath);
1009         if (!NT_STATUS_IS_OK(status)) {
1010                 *pstatus = status;
1011                 goto err_root_exit;
1012         }
1013
1014         /* win2000 does not check the permissions on the directory
1015            during the tree connect, instead relying on permission
1016            check during individual operations. To match this behaviour
1017            I have disabled this chdir check (tridge) */
1018         /* the alternative is just to check the directory exists */
1019
1020         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1021             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1022                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1023                         DEBUG(0,("'%s' is not a directory, when connecting to "
1024                                  "[%s]\n", conn->connectpath,
1025                                  lp_servicename(snum)));
1026                 } else {
1027                         DEBUG(0,("'%s' does not exist or permission denied "
1028                                  "when connecting to [%s] Error was %s\n",
1029                                  conn->connectpath, lp_servicename(snum),
1030                                  strerror(errno) ));
1031                 }
1032                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1033                 goto err_root_exit;
1034         }
1035         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1036
1037         string_set(&conn->origpath,conn->connectpath);
1038
1039         /* Figure out the characteristics of the underlying filesystem. This
1040          * assumes that all the filesystem mounted withing a share path have
1041          * the same characteristics, which is likely but not guaranteed.
1042          */
1043
1044         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1045
1046         /*
1047          * Print out the 'connected as' stuff here as we need
1048          * to know the effective uid and gid we will be using
1049          * (at least initially).
1050          */
1051
1052         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1053                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1054                          conn->sconn->client_id.addr );
1055                 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1056                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1057                 dbgtext( "initially as user %s ",
1058                          conn->server_info->unix_name );
1059                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1060                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1061         }
1062
1063         return(conn);
1064
1065   err_root_exit:
1066         TALLOC_FREE(smb_fname_cpath);
1067         /* We must exit this function as root. */
1068         if (geteuid() != 0) {
1069                 change_to_root_user();
1070         }
1071         if (on_err_call_dis_hook) {
1072                 /* Call VFS disconnect hook */
1073                 SMB_VFS_DISCONNECT(conn);
1074         }
1075         if (claimed_connection) {
1076                 yield_connection(conn, lp_servicename(snum));
1077         }
1078         if (conn) {
1079                 conn_free(conn);
1080         }
1081         return NULL;
1082 }
1083
1084 /****************************************************************************
1085  Make a connection to a service.
1086  *
1087  * @param service 
1088 ****************************************************************************/
1089
1090 connection_struct *make_connection(struct smbd_server_connection *sconn,
1091                                    const char *service_in, DATA_BLOB password,
1092                                    const char *pdev, uint16 vuid,
1093                                    NTSTATUS *status)
1094 {
1095         uid_t euid;
1096         user_struct *vuser = NULL;
1097         fstring service;
1098         fstring dev;
1099         int snum = -1;
1100
1101         fstrcpy(dev, pdev);
1102
1103         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1104          * root. */
1105         if (!non_root_mode() && (euid = geteuid()) != 0) {
1106                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1107                          "(%u)\n", (unsigned int)euid ));
1108                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1109         }
1110
1111         if (conn_num_open(sconn) > 2047) {
1112                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1113                 return NULL;
1114         }
1115
1116         if(lp_security() != SEC_SHARE) {
1117                 vuser = get_valid_user_struct(sconn, vuid);
1118                 if (!vuser) {
1119                         DEBUG(1,("make_connection: refusing to connect with "
1120                                  "no session setup\n"));
1121                         *status = NT_STATUS_ACCESS_DENIED;
1122                         return NULL;
1123                 }
1124         }
1125
1126         /* Logic to try and connect to the correct [homes] share, preferably
1127            without too many getpwnam() lookups.  This is particulary nasty for
1128            winbind usernames, where the share name isn't the same as unix
1129            username.
1130
1131            The snum of the homes share is stored on the vuser at session setup
1132            time.
1133         */
1134
1135         if (strequal(service_in,HOMES_NAME)) {
1136                 if(lp_security() != SEC_SHARE) {
1137                         DATA_BLOB no_pw = data_blob_null;
1138                         if (vuser->homes_snum == -1) {
1139                                 DEBUG(2, ("[homes] share not available for "
1140                                           "this user because it was not found "
1141                                           "or created at session setup "
1142                                           "time\n"));
1143                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1144                                 return NULL;
1145                         }
1146                         DEBUG(5, ("making a connection to [homes] service "
1147                                   "created at session setup time\n"));
1148                         return make_connection_snum(sconn,
1149                                                     vuser->homes_snum,
1150                                                     vuser, no_pw, 
1151                                                     dev, status);
1152                 } else {
1153                         /* Security = share. Try with
1154                          * current_user_info.smb_name as the username.  */
1155                         if (*current_user_info.smb_name) {
1156                                 fstring unix_username;
1157                                 fstrcpy(unix_username,
1158                                         current_user_info.smb_name);
1159                                 map_username(unix_username);
1160                                 snum = find_service(unix_username);
1161                         } 
1162                         if (snum != -1) {
1163                                 DEBUG(5, ("making a connection to 'homes' "
1164                                           "service %s based on "
1165                                           "security=share\n", service_in));
1166                                 return make_connection_snum(sconn,
1167                                                             snum, NULL,
1168                                                             password,
1169                                                             dev, status);
1170                         }
1171                 }
1172         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1173                    && strequal(service_in,
1174                                lp_servicename(vuser->homes_snum))) {
1175                 DATA_BLOB no_pw = data_blob_null;
1176                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1177                           "created at session setup time\n", service_in));
1178                 return make_connection_snum(sconn,
1179                                             vuser->homes_snum,
1180                                             vuser, no_pw, 
1181                                             dev, status);
1182         }
1183
1184         fstrcpy(service, service_in);
1185
1186         strlower_m(service);
1187
1188         snum = find_service(service);
1189
1190         if (snum < 0) {
1191                 if (strequal(service,"IPC$") ||
1192                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1193                         DEBUG(3,("refusing IPC connection to %s\n", service));
1194                         *status = NT_STATUS_ACCESS_DENIED;
1195                         return NULL;
1196                 }
1197
1198                 DEBUG(3,("%s (%s) couldn't find service %s\n",
1199                         get_remote_machine_name(),
1200                         tsocket_address_string(
1201                                 sconn->remote_address, talloc_tos()),
1202                         service));
1203                 *status = NT_STATUS_BAD_NETWORK_NAME;
1204                 return NULL;
1205         }
1206
1207         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1208         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1209                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1210                           "(pointing to %s)\n", 
1211                         service, lp_msdfs_proxy(snum)));
1212                 *status = NT_STATUS_BAD_NETWORK_NAME;
1213                 return NULL;
1214         }
1215
1216         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1217
1218         return make_connection_snum(sconn, snum, vuser,
1219                                     password,
1220                                     dev, status);
1221 }
1222
1223 /****************************************************************************
1224  Close a cnum.
1225 ****************************************************************************/
1226
1227 void close_cnum(connection_struct *conn, uint16 vuid)
1228 {
1229         file_close_conn(conn);
1230
1231         if (!IS_IPC(conn)) {
1232                 dptr_closecnum(conn);
1233         }
1234
1235         change_to_root_user();
1236
1237         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1238                                  get_remote_machine_name(),
1239                                  conn->sconn->client_id.addr,
1240                                  lp_servicename(SNUM(conn))));
1241
1242         /* Call VFS disconnect hook */    
1243         SMB_VFS_DISCONNECT(conn);
1244
1245         yield_connection(conn, lp_servicename(SNUM(conn)));
1246
1247         /* make sure we leave the directory available for unmount */
1248         vfs_ChDir(conn, "/");
1249
1250         /* execute any "postexec = " line */
1251         if (*lp_postexec(SNUM(conn)) && 
1252             change_to_user(conn, vuid))  {
1253                 char *cmd = talloc_sub_advanced(talloc_tos(),
1254                                         lp_servicename(SNUM(conn)),
1255                                         conn->server_info->unix_name,
1256                                         conn->connectpath,
1257                                         conn->server_info->utok.gid,
1258                                         conn->server_info->sanitized_username,
1259                                         conn->server_info->info3->base.domain.string,
1260                                         lp_postexec(SNUM(conn)));
1261                 smbrun(cmd,NULL);
1262                 TALLOC_FREE(cmd);
1263                 change_to_root_user();
1264         }
1265
1266         change_to_root_user();
1267         /* execute any "root postexec = " line */
1268         if (*lp_rootpostexec(SNUM(conn)))  {
1269                 char *cmd = talloc_sub_advanced(talloc_tos(),
1270                                         lp_servicename(SNUM(conn)),
1271                                         conn->server_info->unix_name,
1272                                         conn->connectpath,
1273                                         conn->server_info->utok.gid,
1274                                         conn->server_info->sanitized_username,
1275                                         conn->server_info->info3->base.domain.string,
1276                                         lp_rootpostexec(SNUM(conn)));
1277                 smbrun(cmd,NULL);
1278                 TALLOC_FREE(cmd);
1279         }
1280
1281         conn_free(conn);
1282 }