r21279: Get rid of 'aio write behind', this is broken.
[jerry/samba.git] / source / 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         string_set(&conn->dirpath,"");
776         string_set(&conn->user,user);
777
778         conn->read_only = lp_readonly(SNUM(conn));
779         conn->admin_user = False;
780
781         /*
782          * If force user is true, then store the given userid and the gid of
783          * the user we're forcing.
784          * For auxiliary groups see below.
785          */
786         
787         if (*lp_force_user(snum)) {
788                 NTSTATUS status2;
789
790                 status2 = find_forced_user(conn,
791                                 (vuser != NULL) && vuser->guest,
792                                 user);
793                 if (!NT_STATUS_IS_OK(status2)) {
794                         conn_free(conn);
795                         *status = status2;
796                         return NULL;
797                 }
798                 string_set(&conn->user,user);
799                 conn->force_user = True;
800                 DEBUG(3,("Forced user %s\n",user));       
801         }
802
803         /*
804          * If force group is true, then override
805          * any groupid stored for the connecting user.
806          */
807         
808         if (*lp_force_group(snum)) {
809                 NTSTATUS status2;
810                 DOM_SID group_sid;
811
812                 status2 = find_forced_group(conn->force_user,
813                                             snum, user,
814                                             &group_sid, &conn->gid);
815                 if (!NT_STATUS_IS_OK(status2)) {
816                         conn_free(conn);
817                         *status = status2;
818                         return NULL;
819                 }
820
821                 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
822
823                         /* Not force user and not security=share, but force
824                          * group. vuser has a token to copy */
825                         
826                         conn->nt_user_token = dup_nt_token(
827                                 NULL, vuser->nt_user_token);
828                         if (conn->nt_user_token == NULL) {
829                                 DEBUG(0, ("dup_nt_token failed\n"));
830                                 conn_free(conn);
831                                 *status = NT_STATUS_NO_MEMORY;
832                                 return NULL;
833                         }
834                 }
835
836                 /* If conn->nt_user_token is still NULL, we have
837                  * security=share. This means ignore the SID, as we had no
838                  * vuser to copy from */
839
840                 if (conn->nt_user_token != NULL) {
841                         /* Overwrite the primary group sid */
842                         sid_copy(&conn->nt_user_token->user_sids[1],
843                                  &group_sid);
844
845                 }
846                 conn->force_group = True;
847         }
848
849         if (conn->nt_user_token != NULL) {
850                 size_t i;
851
852                 /* We have a share-specific token from force [user|group].
853                  * This means we have to create the list of unix groups from
854                  * the list of sids. */
855
856                 conn->ngroups = 0;
857                 conn->groups = NULL;
858
859                 for (i=0; i<conn->nt_user_token->num_sids; i++) {
860                         gid_t gid;
861                         DOM_SID *sid = &conn->nt_user_token->user_sids[i];
862
863                         if (!sid_to_gid(sid, &gid)) {
864                                 DEBUG(10, ("Could not convert SID %s to gid, "
865                                            "ignoring it\n",
866                                            sid_string_static(sid)));
867                                 continue;
868                         }
869                         if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
870                                                 &conn->ngroups)) {
871                                 DEBUG(0, ("add_gid_to_array_unique failed\n"));
872                                 conn_free(conn);
873                                 *status = NT_STATUS_NO_MEMORY;
874                                 return NULL;
875                         }
876                 }
877         }
878
879         {
880                 pstring s;
881                 pstrcpy(s,lp_pathname(snum));
882                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
883                                       conn->connectpath, conn->gid,
884                                       get_current_username(),
885                                       current_user_info.domain,
886                                       s, sizeof(s));
887                 set_conn_connectpath(conn,s);
888                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
889                          lp_servicename(snum)));
890         }
891
892         /*
893          * New code to check if there's a share security descripter
894          * added from NT server manager. This is done after the
895          * smb.conf checks are done as we need a uid and token. JRA.
896          *
897          */
898
899         {
900                 NT_USER_TOKEN *token = conn->nt_user_token ?
901                         conn->nt_user_token : vuser->nt_user_token;
902
903                 BOOL can_write = share_access_check(token,
904                                                     lp_servicename(snum),
905                                                     FILE_WRITE_DATA);
906
907                 if (!can_write) {
908                         if (!share_access_check(token,
909                                                 lp_servicename(snum),
910                                                 FILE_READ_DATA)) {
911                                 /* No access, read or write. */
912                                 DEBUG(0,("make_connection: connection to %s "
913                                          "denied due to security "
914                                          "descriptor.\n",
915                                           lp_servicename(snum)));
916                                 conn_free(conn);
917                                 *status = NT_STATUS_ACCESS_DENIED;
918                                 return NULL;
919                         } else {
920                                 conn->read_only = True;
921                         }
922                 }
923         }
924         /* Initialise VFS function pointers */
925
926         if (!smbd_vfs_init(conn)) {
927                 DEBUG(0, ("vfs_init failed for service %s\n",
928                           lp_servicename(snum)));
929                 conn_free(conn);
930                 *status = NT_STATUS_BAD_NETWORK_NAME;
931                 return NULL;
932         }
933
934         /*
935          * If widelinks are disallowed we need to canonicalise the connect
936          * path here to ensure we don't have any symlinks in the
937          * connectpath. We will be checking all paths on this connection are
938          * below this directory. We must do this after the VFS init as we
939          * depend on the realpath() pointer in the vfs table. JRA.
940          */
941         if (!lp_widelinks(snum)) {
942                 pstring s;
943                 pstrcpy(s,conn->connectpath);
944                 canonicalize_path(conn, s);
945                 set_conn_connectpath(conn,s);
946         }
947
948         if ((!conn->printer) && (!conn->ipc)) {
949                 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
950                                                smbd_messaging_context(),
951                                                smbd_event_context(),
952                                                conn);
953         }
954
955 /* ROOT Activities: */  
956         /* check number of connections */
957         if (!claim_connection(conn,
958                               lp_servicename(snum),
959                               lp_max_connections(snum),
960                               False,0)) {
961                 DEBUG(1,("too many connections - rejected\n"));
962                 conn_free(conn);
963                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
964                 return NULL;
965         }  
966
967         /* Preexecs are done here as they might make the dir we are to ChDir
968          * to below */
969         /* execute any "root preexec = " line */
970         if (*lp_rootpreexec(snum)) {
971                 pstring cmd;
972                 pstrcpy(cmd,lp_rootpreexec(snum));
973                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
974                                       conn->connectpath, conn->gid,
975                                       get_current_username(),
976                                       current_user_info.domain,
977                                       cmd, sizeof(cmd));
978                 DEBUG(5,("cmd=%s\n",cmd));
979                 ret = smbrun(cmd,NULL);
980                 if (ret != 0 && lp_rootpreexec_close(snum)) {
981                         DEBUG(1,("root preexec gave %d - failing "
982                                  "connection\n", ret));
983                         yield_connection(conn, lp_servicename(snum));
984                         conn_free(conn);
985                         *status = NT_STATUS_ACCESS_DENIED;
986                         return NULL;
987                 }
988         }
989
990 /* USER Activites: */
991         if (!change_to_user(conn, conn->vuid)) {
992                 /* No point continuing if they fail the basic checks */
993                 DEBUG(0,("Can't become connected user!\n"));
994                 yield_connection(conn, lp_servicename(snum));
995                 conn_free(conn);
996                 *status = NT_STATUS_LOGON_FAILURE;
997                 return NULL;
998         }
999
1000         /* Remember that a different vuid can connect later without these
1001          * checks... */
1002         
1003         /* Preexecs are done here as they might make the dir we are to ChDir
1004          * to below */
1005
1006         /* execute any "preexec = " line */
1007         if (*lp_preexec(snum)) {
1008                 pstring cmd;
1009                 pstrcpy(cmd,lp_preexec(snum));
1010                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1011                                       conn->connectpath, conn->gid,
1012                                       get_current_username(),
1013                                       current_user_info.domain,
1014                                       cmd, sizeof(cmd));
1015                 ret = smbrun(cmd,NULL);
1016                 if (ret != 0 && lp_preexec_close(snum)) {
1017                         DEBUG(1,("preexec gave %d - failing connection\n",
1018                                  ret));
1019                         change_to_root_user();
1020                         yield_connection(conn, lp_servicename(snum));
1021                         conn_free(conn);
1022                         *status = NT_STATUS_ACCESS_DENIED;
1023                         return NULL;
1024                 }
1025         }
1026
1027 #ifdef WITH_FAKE_KASERVER
1028         if (lp_afs_share(snum)) {
1029                 afs_login(conn);
1030         }
1031 #endif
1032         
1033         /* Add veto/hide lists */
1034         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1035                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1036                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1037                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1038         }
1039         
1040         /* Invoke VFS make connection hook - do this before the VFS_STAT call
1041            to allow any filesystems needing user credentials to initialize
1042            themselves. */
1043
1044         if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1045                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1046                 change_to_root_user();
1047                 yield_connection(conn, lp_servicename(snum));
1048                 conn_free(conn);
1049                 *status = NT_STATUS_UNSUCCESSFUL;
1050                 return NULL;
1051         }
1052
1053         /* win2000 does not check the permissions on the directory
1054            during the tree connect, instead relying on permission
1055            check during individual operations. To match this behaviour
1056            I have disabled this chdir check (tridge) */
1057         /* the alternative is just to check the directory exists */
1058         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1059             !S_ISDIR(st.st_mode)) {
1060                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1061                         DEBUG(0,("'%s' is not a directory, when connecting to "
1062                                  "[%s]\n", conn->connectpath,
1063                                  lp_servicename(snum)));
1064                 } else {
1065                         DEBUG(0,("'%s' does not exist or permission denied "
1066                                  "when connecting to [%s] Error was %s\n",
1067                                  conn->connectpath, lp_servicename(snum),
1068                                  strerror(errno) ));
1069                 }
1070                 change_to_root_user();
1071                 /* Call VFS disconnect hook */    
1072                 SMB_VFS_DISCONNECT(conn);
1073                 yield_connection(conn, lp_servicename(snum));
1074                 conn_free(conn);
1075                 *status = NT_STATUS_BAD_NETWORK_NAME;
1076                 return NULL;
1077         }
1078         
1079         string_set(&conn->origpath,conn->connectpath);
1080         
1081 #if SOFTLINK_OPTIMISATION
1082         /* resolve any soft links early if possible */
1083         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1084                 pstring s;
1085                 pstrcpy(s,conn->connectpath);
1086                 vfs_GetWd(conn,s);
1087                 set_conn_connectpath(conn,s);
1088                 vfs_ChDir(conn,conn->connectpath);
1089         }
1090 #endif
1091         
1092         /*
1093          * Print out the 'connected as' stuff here as we need
1094          * to know the effective uid and gid we will be using
1095          * (at least initially).
1096          */
1097
1098         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1099                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1100                          conn->client_address );
1101                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1102                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1103                 dbgtext( "initially as user %s ", user );
1104                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1105                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1106         }
1107         
1108         /* we've finished with the user stuff - go back to root */
1109         change_to_root_user();
1110         return(conn);
1111 }
1112
1113 /***************************************************************************************
1114  Simple wrapper function for make_connection() to include a call to 
1115  vfs_chdir()
1116  **************************************************************************************/
1117  
1118 connection_struct *make_connection_with_chdir(const char *service_in,
1119                                               DATA_BLOB password, 
1120                                               const char *dev, uint16 vuid,
1121                                               NTSTATUS *status)
1122 {
1123         connection_struct *conn = NULL;
1124         
1125         conn = make_connection(service_in, password, dev, vuid, status);
1126         
1127         /*
1128          * make_connection() does not change the directory for us any more
1129          * so we have to do it as a separate step  --jerry
1130          */
1131          
1132         if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1133                 DEBUG(0,("move_driver_to_download_area: Can't change "
1134                          "directory to %s for [print$] (%s)\n",
1135                          conn->connectpath,strerror(errno)));
1136                 yield_connection(conn, lp_servicename(SNUM(conn)));
1137                 conn_free(conn);
1138                 *status = NT_STATUS_UNSUCCESSFUL;
1139                 return NULL;
1140         }
1141         
1142         return conn;
1143 }
1144
1145 /****************************************************************************
1146  Make a connection to a service.
1147  *
1148  * @param service 
1149 ****************************************************************************/
1150
1151 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
1152                                    const char *pdev, uint16 vuid,
1153                                    NTSTATUS *status)
1154 {
1155         uid_t euid;
1156         user_struct *vuser = NULL;
1157         fstring service;
1158         fstring dev;
1159         int snum = -1;
1160
1161         fstrcpy(dev, pdev);
1162
1163         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1164          * root. */
1165         if (!non_root_mode() && (euid = geteuid()) != 0) {
1166                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1167                          "(%u)\n", (unsigned int)euid ));
1168                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1169         }
1170
1171         if (conn_num_open() > 2047) {
1172                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1173                 return NULL;
1174         }
1175
1176         if(lp_security() != SEC_SHARE) {
1177                 vuser = get_valid_user_struct(vuid);
1178                 if (!vuser) {
1179                         DEBUG(1,("make_connection: refusing to connect with "
1180                                  "no session setup\n"));
1181                         *status = NT_STATUS_ACCESS_DENIED;
1182                         return NULL;
1183                 }
1184         }
1185
1186         /* Logic to try and connect to the correct [homes] share, preferably
1187            without too many getpwnam() lookups.  This is particulary nasty for
1188            winbind usernames, where the share name isn't the same as unix
1189            username.
1190
1191            The snum of the homes share is stored on the vuser at session setup
1192            time.
1193         */
1194
1195         if (strequal(service_in,HOMES_NAME)) {
1196                 if(lp_security() != SEC_SHARE) {
1197                         DATA_BLOB no_pw = data_blob(NULL, 0);
1198                         if (vuser->homes_snum == -1) {
1199                                 DEBUG(2, ("[homes] share not available for "
1200                                           "this user because it was not found "
1201                                           "or created at session setup "
1202                                           "time\n"));
1203                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1204                                 return NULL;
1205                         }
1206                         DEBUG(5, ("making a connection to [homes] service "
1207                                   "created at session setup time\n"));
1208                         return make_connection_snum(vuser->homes_snum,
1209                                                     vuser, no_pw, 
1210                                                     dev, status);
1211                 } else {
1212                         /* Security = share. Try with
1213                          * current_user_info.smb_name as the username.  */
1214                         if (*current_user_info.smb_name) {
1215                                 fstring unix_username;
1216                                 fstrcpy(unix_username,
1217                                         current_user_info.smb_name);
1218                                 map_username(unix_username);
1219                                 snum = find_service(unix_username);
1220                         } 
1221                         if (snum != -1) {
1222                                 DEBUG(5, ("making a connection to 'homes' "
1223                                           "service %s based on "
1224                                           "security=share\n", service_in));
1225                                 return make_connection_snum(snum, NULL,
1226                                                             password,
1227                                                             dev, status);
1228                         }
1229                 }
1230         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1231                    && strequal(service_in,
1232                                lp_servicename(vuser->homes_snum))) {
1233                 DATA_BLOB no_pw = data_blob(NULL, 0);
1234                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1235                           "created at session setup time\n", service_in));
1236                 return make_connection_snum(vuser->homes_snum,
1237                                             vuser, no_pw, 
1238                                             dev, status);
1239         }
1240         
1241         fstrcpy(service, service_in);
1242
1243         strlower_m(service);
1244
1245         snum = find_service(service);
1246
1247         if (snum < 0) {
1248                 if (strequal(service,"IPC$") ||
1249                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1250                         DEBUG(3,("refusing IPC connection to %s\n", service));
1251                         *status = NT_STATUS_ACCESS_DENIED;
1252                         return NULL;
1253                 }
1254
1255                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1256                          get_remote_machine_name(), client_addr(), service));
1257                 *status = NT_STATUS_BAD_NETWORK_NAME;
1258                 return NULL;
1259         }
1260
1261         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1262         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1263                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1264                           "(pointing to %s)\n", 
1265                         service, lp_msdfs_proxy(snum)));
1266                 *status = NT_STATUS_BAD_NETWORK_NAME;
1267                 return NULL;
1268         }
1269
1270         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1271
1272         return make_connection_snum(snum, vuser,
1273                                     password,
1274                                     dev, status);
1275 }
1276
1277 /****************************************************************************
1278  Close a cnum.
1279 ****************************************************************************/
1280
1281 void close_cnum(connection_struct *conn, uint16 vuid)
1282 {
1283         if (IS_IPC(conn)) {
1284                 pipe_close_conn(conn);
1285         } else {
1286                 file_close_conn(conn);
1287                 dptr_closecnum(conn);
1288         }
1289
1290         change_to_root_user();
1291
1292         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1293                                  get_remote_machine_name(),
1294                                  conn->client_address,
1295                                  lp_servicename(SNUM(conn))));
1296
1297         /* Call VFS disconnect hook */    
1298         SMB_VFS_DISCONNECT(conn);
1299
1300         yield_connection(conn, lp_servicename(SNUM(conn)));
1301
1302         /* make sure we leave the directory available for unmount */
1303         vfs_ChDir(conn, "/");
1304
1305         /* execute any "postexec = " line */
1306         if (*lp_postexec(SNUM(conn)) && 
1307             change_to_user(conn, vuid))  {
1308                 pstring cmd;
1309                 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1310                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1311                                       conn->connectpath, conn->gid,
1312                                       get_current_username(),
1313                                       current_user_info.domain,
1314                                       cmd, sizeof(cmd));
1315                 smbrun(cmd,NULL);
1316                 change_to_root_user();
1317         }
1318
1319         change_to_root_user();
1320         /* execute any "root postexec = " line */
1321         if (*lp_rootpostexec(SNUM(conn)))  {
1322                 pstring cmd;
1323                 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1324                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1325                                       conn->connectpath, conn->gid,
1326                                       get_current_username(),
1327                                       current_user_info.domain,
1328                                       cmd, sizeof(cmd));
1329                 smbrun(cmd,NULL);
1330         }
1331
1332         conn_free(conn);
1333 }