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