r4464: added pvfs backend support for the special CREATOR_OWNER and CREATOR_GROUP...
[samba.git] / source4 / ntvfs / posix / pvfs_acl.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - ACL support
5
6    Copyright (C) Andrew Tridgell 2004
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "system/filesys.h"
26 #include "vfs_posix.h"
27 #include "librpc/gen_ndr/ndr_xattr.h"
28
29
30 /*
31   map a single access_mask from generic to specific bits for files/dirs
32 */
33 static uint32_t pvfs_translate_mask(uint32_t access_mask)
34 {
35         if (access_mask & SEC_MASK_GENERIC) {
36                 if (access_mask & SEC_GENERIC_READ)    access_mask |= SEC_RIGHTS_FILE_READ;
37                 if (access_mask & SEC_GENERIC_WRITE)   access_mask |= SEC_RIGHTS_FILE_WRITE;
38                 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
39                 if (access_mask & SEC_GENERIC_ALL)     access_mask |= SEC_RIGHTS_FILE_ALL;
40                 access_mask &= ~SEC_MASK_GENERIC;
41         }
42         return access_mask;
43 }
44
45
46 /*
47   map any generic access bits in the given acl
48   this relies on the fact that the mappings for files and directories
49   are the same
50 */
51 static void pvfs_translate_generic_bits(struct security_acl *acl)
52 {
53         unsigned i;
54
55         for (i=0;i<acl->num_aces;i++) {
56                 struct security_ace *ace = &acl->aces[i];
57                 ace->access_mask = pvfs_translate_mask(ace->access_mask);
58         }
59 }
60
61
62 /*
63   setup a default ACL for a file
64 */
65 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
66                                  struct smbsrv_request *req,
67                                  struct pvfs_filename *name, int fd, 
68                                  struct xattr_NTACL *acl)
69 {
70         struct security_descriptor *sd;
71         NTSTATUS status;
72         struct security_ace ace;
73         mode_t mode;
74
75         sd = security_descriptor_initialise(req);
76         if (sd == NULL) {
77                 return NT_STATUS_NO_MEMORY;
78         }
79
80         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
81         if (!NT_STATUS_IS_OK(status)) {
82                 return status;
83         }
84         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
85         if (!NT_STATUS_IS_OK(status)) {
86                 return status;
87         }
88
89         sd->type |= SEC_DESC_DACL_PRESENT;
90
91         mode = name->st.st_mode;
92
93         /*
94           we provide up to 4 ACEs
95             - Owner
96             - Group
97             - Everyone
98             - Administrator
99          */
100
101
102         /* setup owner ACE */
103         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
104         ace.flags = 0;
105         ace.trustee = *sd->owner_sid;
106         ace.access_mask = 0;
107
108         if (mode & S_IRUSR) {
109                 if (mode & S_IWUSR) {
110                         ace.access_mask |= SEC_RIGHTS_FILE_ALL;
111                 } else {
112                         ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
113                 }
114         }
115         if (mode & S_IWUSR) {
116                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
117         }
118         if (ace.access_mask) {
119                 security_descriptor_dacl_add(sd, &ace);
120         }
121
122
123         /* setup group ACE */
124         ace.trustee = *sd->group_sid;
125         ace.access_mask = 0;
126         if (mode & S_IRGRP) {
127                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
128         }
129         if (mode & S_IWGRP) {
130                 /* note that delete is not granted - this matches posix behaviour */
131                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
132         }
133         if (ace.access_mask) {
134                 security_descriptor_dacl_add(sd, &ace);
135         }
136
137         /* setup other ACE */
138         ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
139         ace.access_mask = 0;
140         if (mode & S_IROTH) {
141                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
142         }
143         if (mode & S_IWOTH) {
144                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
145         }
146         if (ace.access_mask) {
147                 security_descriptor_dacl_add(sd, &ace);
148         }
149
150         /* setup system ACE */
151         ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
152         ace.access_mask = SEC_RIGHTS_FILE_ALL;
153         security_descriptor_dacl_add(sd, &ace);
154         
155         acl->version = 1;
156         acl->info.sd = sd;
157
158         return NT_STATUS_OK;
159 }
160                                  
161
162 /*
163   omit any security_descriptor elements not specified in the given
164   secinfo flags
165 */
166 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
167 {
168         if (!(secinfo_flags & SECINFO_OWNER)) {
169                 sd->owner_sid = NULL;
170         }
171         if (!(secinfo_flags & SECINFO_GROUP)) {
172                 sd->group_sid = NULL;
173         }
174         if (!(secinfo_flags & SECINFO_DACL)) {
175                 sd->dacl = NULL;
176         }
177         if (!(secinfo_flags & SECINFO_SACL)) {
178                 sd->sacl = NULL;
179         }
180 }
181
182 /*
183   answer a setfileinfo for an ACL
184 */
185 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
186                       struct smbsrv_request *req,
187                       struct pvfs_filename *name, int fd, 
188                       uint32_t access_mask,
189                       union smb_setfileinfo *info)
190 {
191         struct xattr_NTACL *acl;
192         uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
193         struct security_descriptor *new_sd, *sd;
194         NTSTATUS status;
195         uid_t uid = -1;
196         gid_t gid = -1;
197
198         acl = talloc_p(req, struct xattr_NTACL);
199         if (acl == NULL) {
200                 return NT_STATUS_NO_MEMORY;
201         }
202
203         status = pvfs_acl_load(pvfs, name, fd, acl);
204         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
205                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
206         }
207         if (!NT_STATUS_IS_OK(status)) {
208                 return status;
209         }
210
211         switch (acl->version) {
212         case 1:
213                 sd = acl->info.sd;
214                 break;
215         default:
216                 return NT_STATUS_INVALID_ACL;
217         }
218
219         new_sd = info->set_secdesc.in.sd;
220
221         uid = name->st.st_uid;
222         gid = name->st.st_gid;
223
224         /* only set the elements that have been specified */
225         if ((secinfo_flags & SECINFO_OWNER) && 
226             !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
227                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
228                         return NT_STATUS_ACCESS_DENIED;
229                 }
230                 sd->owner_sid = new_sd->owner_sid;
231                 status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid);
232                 if (!NT_STATUS_IS_OK(status)) {
233                         return status;
234                 }
235         }
236         if ((secinfo_flags & SECINFO_GROUP) &&
237             !dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
238                 sd->group_sid = new_sd->group_sid;
239                 status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid);
240                 if (!NT_STATUS_IS_OK(status)) {
241                         return status;
242                 }
243         }
244         if (secinfo_flags & SECINFO_DACL) {
245                 sd->dacl = new_sd->dacl;
246                 pvfs_translate_generic_bits(sd->dacl);
247         }
248         if (secinfo_flags & SECINFO_SACL) {
249                 sd->sacl = new_sd->sacl;
250                 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
251                         return NT_STATUS_ACCESS_DENIED;
252                 }
253                 pvfs_translate_generic_bits(sd->sacl);
254         }
255
256         if (uid != -1 || gid != -1) {
257                 int ret;
258                 if (fd == -1) {
259                         ret = chown(name->full_name, uid, gid);
260                 } else {
261                         ret = fchown(fd, uid, gid);
262                 }
263                 if (ret == -1) {
264                         return pvfs_map_errno(pvfs, errno);
265                 }
266         }
267
268         status = pvfs_acl_save(pvfs, name, fd, acl);
269
270         return status;
271 }
272
273
274 /*
275   answer a fileinfo query for the ACL
276 */
277 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
278                         struct smbsrv_request *req,
279                         struct pvfs_filename *name, int fd, 
280                         union smb_fileinfo *info)
281 {
282         struct xattr_NTACL *acl;
283         NTSTATUS status;
284         struct security_descriptor *sd;
285
286         acl = talloc_p(req, struct xattr_NTACL);
287         if (acl == NULL) {
288                 return NT_STATUS_NO_MEMORY;
289         }
290
291         status = pvfs_acl_load(pvfs, name, fd, acl);
292         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
293                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
294         }
295         if (!NT_STATUS_IS_OK(status)) {
296                 return status;
297         }
298
299         switch (acl->version) {
300         case 1:
301                 sd = acl->info.sd;
302                 break;
303         default:
304                 return NT_STATUS_INVALID_ACL;
305         }
306
307         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
308
309         info->query_secdesc.out.sd = sd;
310
311         return NT_STATUS_OK;
312 }
313
314
315 /*
316   default access check function based on unix permissions
317   doing this saves on building a full security descriptor
318   for the common case of access check on files with no 
319   specific NT ACL
320 */
321 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
322                                 struct smbsrv_request *req,
323                                 struct pvfs_filename *name,
324                                 uint32_t *access_mask)
325 {
326         uid_t uid = geteuid();
327         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
328
329         /* owner and root get extra permissions */
330         if (uid == 0 || uid == name->st.st_uid) {
331                 max_bits |= SEC_STD_ALL;
332         }
333
334         if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
335                 *access_mask = max_bits;
336                 return NT_STATUS_OK;
337         }
338
339         if (*access_mask & ~max_bits) {
340                 return NT_STATUS_ACCESS_DENIED;
341         }
342
343         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
344
345         return NT_STATUS_OK;
346 }
347
348
349 /*
350   check the security descriptor on a file, if any
351   
352   *access_mask is modified with the access actually granted
353 */
354 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
355                            struct smbsrv_request *req,
356                            struct pvfs_filename *name,
357                            uint32_t *access_mask)
358 {
359         struct security_token *token = req->session->session_info->security_token;
360         struct xattr_NTACL *acl;
361         NTSTATUS status;
362         struct security_descriptor *sd;
363
364         acl = talloc_p(req, struct xattr_NTACL);
365         if (acl == NULL) {
366                 return NT_STATUS_NO_MEMORY;
367         }
368
369         status = pvfs_acl_load(pvfs, name, -1, acl);
370         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
371                 talloc_free(acl);
372                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
373         }
374         if (!NT_STATUS_IS_OK(status)) {
375                 return status;
376         }
377
378         switch (acl->version) {
379         case 1:
380                 sd = acl->info.sd;
381                 break;
382         default:
383                 return NT_STATUS_INVALID_ACL;
384         }
385
386         /* expand the generic access bits to file specific bits */
387         *access_mask = pvfs_translate_mask(*access_mask);
388
389         /* check the acl against the required access mask */
390         status = sec_access_check(sd, token, *access_mask, access_mask);
391
392         /* this bit is always granted, even if not asked for */
393         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
394
395         talloc_free(acl);
396         
397         return status;
398 }
399
400
401 /*
402   a simplified interface to access check, designed for calls that
403   do not take or return an access check mask
404 */
405 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
406                                   struct smbsrv_request *req,
407                                   struct pvfs_filename *name,
408                                   uint32_t access_needed)
409 {
410         if (access_needed == 0) {
411                 return NT_STATUS_OK;
412         }
413         return pvfs_access_check(pvfs, req, name, &access_needed);
414 }
415
416 /*
417   access check for creating a new file/directory
418 */
419 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
420                                   struct smbsrv_request *req,
421                                   struct pvfs_filename *name)
422 {
423         struct pvfs_filename *parent;
424         NTSTATUS status;
425
426         status = pvfs_resolve_parent(pvfs, req, name, &parent);
427         if (!NT_STATUS_IS_OK(status)) {
428                 return status;
429         }
430
431         return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
432 }
433
434
435 /*
436   determine if an ACE is inheritable
437 */
438 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
439                                  const struct security_ace *ace,
440                                  BOOL container)
441 {
442         if (!container) {
443                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
444         }
445
446         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
447                 return True;
448         }
449
450         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
451             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
452                 return True;
453         }
454
455         return False;
456 }
457
458 /*
459   this is the core of ACL inheritance. It copies any inheritable
460   aces from the parent SD to the child SD. Note that the algorithm 
461   depends on whether the child is a container or not
462 */
463 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
464                                       struct security_descriptor *parent_sd,
465                                       struct security_descriptor *sd,
466                                       BOOL container)
467 {
468         int i;
469         
470         for (i=0;i<parent_sd->dacl->num_aces;i++) {
471                 struct security_ace ace = parent_sd->dacl->aces[i];
472                 NTSTATUS status;
473                 const struct dom_sid *creator = NULL, *new_id = NULL;
474                 uint32_t orig_flags;
475
476                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
477                         continue;
478                 }
479
480                 orig_flags = ace.flags;
481
482                 /* see the RAW-ACLS inheritance test for details on these rules */
483                 if (!container) {
484                         ace.flags = 0;
485                 } else {
486                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
487
488                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
489                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
490                         }
491                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
492                                 ace.flags = 0;
493                         }
494                 }
495
496                 /* the CREATOR sids are special when inherited */
497                 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
498                         creator = pvfs->sid_cache.creator_owner;
499                         new_id = sd->owner_sid;
500                 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
501                         creator = pvfs->sid_cache.creator_group;
502                         new_id = sd->group_sid;
503                 } else {
504                         new_id = &ace.trustee;
505                 }
506
507                 if (creator && container && 
508                     (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
509                         uint32_t flags = ace.flags;
510
511                         ace.trustee = *new_id;
512                         ace.flags = 0;
513                         status = security_descriptor_dacl_add(sd, &ace);
514                         if (!NT_STATUS_IS_OK(status)) {
515                                 return status;
516                         }
517
518                         ace.trustee = *creator;
519                         ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
520                         status = security_descriptor_dacl_add(sd, &ace);
521                 } else if (container && 
522                            !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
523                         status = security_descriptor_dacl_add(sd, &ace);
524                 } else {
525                         ace.trustee = *new_id;
526                         status = security_descriptor_dacl_add(sd, &ace);
527                 }
528
529                 if (!NT_STATUS_IS_OK(status)) {
530                         return status;
531                 }
532         }
533
534         return NT_STATUS_OK;
535 }
536
537
538
539 /*
540   setup an ACL on a new file/directory based on the inherited ACL from
541   the parent. If there is no inherited ACL then we don't set anything,
542   as the default ACL applies anyway
543 */
544 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
545                           struct smbsrv_request *req,
546                           struct pvfs_filename *name,
547                           int fd)
548 {
549         struct xattr_NTACL *acl;
550         NTSTATUS status;
551         struct pvfs_filename *parent;
552         struct security_descriptor *parent_sd, *sd;
553         BOOL container;
554
555         /* form the parents path */
556         status = pvfs_resolve_parent(pvfs, req, name, &parent);
557         if (!NT_STATUS_IS_OK(status)) {
558                 return status;
559         }
560
561         acl = talloc_p(req, struct xattr_NTACL);
562         if (acl == NULL) {
563                 return NT_STATUS_NO_MEMORY;
564         }
565
566         status = pvfs_acl_load(pvfs, parent, -1, acl);
567         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
568                 return NT_STATUS_OK;
569         }
570         if (!NT_STATUS_IS_OK(status)) {
571                 return status;
572         }
573
574         switch (acl->version) {
575         case 1:
576                 parent_sd = acl->info.sd;
577                 break;
578         default:
579                 return NT_STATUS_INVALID_ACL;
580         }
581
582         if (parent_sd == NULL ||
583             parent_sd->dacl == NULL ||
584             parent_sd->dacl->num_aces == 0) {
585                 /* go with the default ACL */
586                 return NT_STATUS_OK;
587         }
588
589         /* create the new sd */
590         sd = security_descriptor_initialise(req);
591         if (sd == NULL) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594
595         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
596         if (!NT_STATUS_IS_OK(status)) {
597                 return status;
598         }
599         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
600         if (!NT_STATUS_IS_OK(status)) {
601                 return status;
602         }
603
604         sd->type |= SEC_DESC_DACL_PRESENT;
605
606         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
607
608         /* fill in the aces from the parent */
609         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
610         if (!NT_STATUS_IS_OK(status)) {
611                 return status;
612         }
613
614         /* if there is nothing to inherit then we fallback to the
615            default acl */
616         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
617                 return NT_STATUS_OK;
618         }
619
620         acl->info.sd = sd;
621
622         status = pvfs_acl_save(pvfs, name, fd, acl);
623         
624         return status;
625 }