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