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