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