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