2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - ACL support
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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.
24 #include "auth/auth.h"
25 #include "vfs_posix.h"
26 #include "librpc/gen_ndr/xattr.h"
27 #include "libcli/security/security.h"
31 map a single access_mask from generic to specific bits for files/dirs
33 static uint32_t pvfs_translate_mask(uint32_t access_mask)
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;
47 map any generic access bits in the given acl
48 this relies on the fact that the mappings for files and directories
51 static void pvfs_translate_generic_bits(struct security_acl *acl)
57 for (i=0;i<acl->num_aces;i++) {
58 struct security_ace *ace = &acl->aces[i];
59 ace->access_mask = pvfs_translate_mask(ace->access_mask);
65 setup a default ACL for a file
67 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
68 struct ntvfs_request *req,
69 struct pvfs_filename *name, int fd,
70 struct xattr_NTACL *acl)
72 struct security_descriptor *sd;
74 struct security_ace ace;
77 sd = security_descriptor_initialise(req);
79 return NT_STATUS_NO_MEMORY;
82 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
83 if (!NT_STATUS_IS_OK(status)) {
86 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
87 if (!NT_STATUS_IS_OK(status)) {
91 sd->type |= SEC_DESC_DACL_PRESENT;
93 mode = name->st.st_mode;
96 we provide up to 4 ACEs
104 /* setup owner ACE */
105 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
107 ace.trustee = *sd->owner_sid;
110 if (mode & S_IRUSR) {
111 if (mode & S_IWUSR) {
112 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
114 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
117 if (mode & S_IWUSR) {
118 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
120 if (ace.access_mask) {
121 security_descriptor_dacl_add(sd, &ace);
125 /* setup group ACE */
126 ace.trustee = *sd->group_sid;
128 if (mode & S_IRGRP) {
129 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
131 if (mode & S_IWGRP) {
132 /* note that delete is not granted - this matches posix behaviour */
133 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
135 if (ace.access_mask) {
136 security_descriptor_dacl_add(sd, &ace);
139 /* setup other ACE */
140 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
142 if (mode & S_IROTH) {
143 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
145 if (mode & S_IWOTH) {
146 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
148 if (ace.access_mask) {
149 security_descriptor_dacl_add(sd, &ace);
152 /* setup system ACE */
153 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
154 ace.access_mask = SEC_RIGHTS_FILE_ALL;
155 security_descriptor_dacl_add(sd, &ace);
165 omit any security_descriptor elements not specified in the given
168 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
170 if (!(secinfo_flags & SECINFO_OWNER)) {
171 sd->owner_sid = NULL;
173 if (!(secinfo_flags & SECINFO_GROUP)) {
174 sd->group_sid = NULL;
176 if (!(secinfo_flags & SECINFO_DACL)) {
179 if (!(secinfo_flags & SECINFO_SACL)) {
185 answer a setfileinfo for an ACL
187 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
188 struct ntvfs_request *req,
189 struct pvfs_filename *name, int fd,
190 uint32_t access_mask,
191 union smb_setfileinfo *info)
193 struct xattr_NTACL *acl;
194 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
195 struct security_descriptor *new_sd, *sd, orig_sd;
200 acl = talloc(req, struct xattr_NTACL);
202 return NT_STATUS_NO_MEMORY;
205 status = pvfs_acl_load(pvfs, name, fd, acl);
206 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
207 status = pvfs_default_acl(pvfs, req, name, fd, acl);
209 if (!NT_STATUS_IS_OK(status)) {
213 switch (acl->version) {
218 return NT_STATUS_INVALID_ACL;
221 new_sd = info->set_secdesc.in.sd;
224 uid = name->st.st_uid;
225 gid = name->st.st_gid;
227 /* only set the elements that have been specified */
228 if ((secinfo_flags & SECINFO_OWNER) &&
229 !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
230 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
231 return NT_STATUS_ACCESS_DENIED;
233 sd->owner_sid = new_sd->owner_sid;
234 status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid);
235 if (!NT_STATUS_IS_OK(status)) {
239 if ((secinfo_flags & SECINFO_GROUP) &&
240 !dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
241 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
242 return NT_STATUS_ACCESS_DENIED;
244 sd->group_sid = new_sd->group_sid;
245 status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid);
246 if (!NT_STATUS_IS_OK(status)) {
250 if (secinfo_flags & SECINFO_DACL) {
251 if (!(access_mask & SEC_STD_WRITE_DAC)) {
252 return NT_STATUS_ACCESS_DENIED;
254 sd->dacl = new_sd->dacl;
255 pvfs_translate_generic_bits(sd->dacl);
257 if (secinfo_flags & SECINFO_SACL) {
258 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
259 return NT_STATUS_ACCESS_DENIED;
261 sd->sacl = new_sd->sacl;
262 pvfs_translate_generic_bits(sd->sacl);
265 if (uid != -1 || gid != -1) {
268 ret = chown(name->full_name, uid, gid);
270 ret = fchown(fd, uid, gid);
273 return pvfs_map_errno(pvfs, errno);
277 /* we avoid saving if the sd is the same. This means when clients
278 copy files and end up copying the default sd that we don't
279 needlessly use xattrs */
280 if (!security_descriptor_equal(sd, &orig_sd)) {
281 status = pvfs_acl_save(pvfs, name, fd, acl);
289 answer a fileinfo query for the ACL
291 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
292 struct ntvfs_request *req,
293 struct pvfs_filename *name, int fd,
294 union smb_fileinfo *info)
296 struct xattr_NTACL *acl;
298 struct security_descriptor *sd;
300 acl = talloc(req, struct xattr_NTACL);
302 return NT_STATUS_NO_MEMORY;
305 status = pvfs_acl_load(pvfs, name, fd, acl);
306 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
307 status = pvfs_default_acl(pvfs, req, name, fd, acl);
309 if (!NT_STATUS_IS_OK(status)) {
313 switch (acl->version) {
318 return NT_STATUS_INVALID_ACL;
321 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
323 info->query_secdesc.out.sd = sd;
330 default access check function based on unix permissions
331 doing this saves on building a full security descriptor
332 for the common case of access check on files with no
335 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
336 struct ntvfs_request *req,
337 struct pvfs_filename *name,
338 uint32_t *access_mask)
340 uid_t uid = geteuid();
341 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
343 /* owner and root get extra permissions */
344 if (uid == 0 || uid == name->st.st_uid) {
345 max_bits |= SEC_STD_ALL;
348 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
349 *access_mask = max_bits;
353 if (*access_mask & ~max_bits) {
354 return NT_STATUS_ACCESS_DENIED;
357 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
364 check the security descriptor on a file, if any
366 *access_mask is modified with the access actually granted
368 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
369 struct ntvfs_request *req,
370 struct pvfs_filename *name,
371 uint32_t *access_mask)
373 struct security_token *token = req->session_info->security_token;
374 struct xattr_NTACL *acl;
376 struct security_descriptor *sd;
378 acl = talloc(req, struct xattr_NTACL);
380 return NT_STATUS_NO_MEMORY;
383 /* expand the generic access bits to file specific bits */
384 *access_mask = pvfs_translate_mask(*access_mask);
385 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
387 status = pvfs_acl_load(pvfs, name, -1, acl);
388 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
390 return pvfs_access_check_unix(pvfs, req, name, access_mask);
392 if (!NT_STATUS_IS_OK(status)) {
396 switch (acl->version) {
401 return NT_STATUS_INVALID_ACL;
404 /* check the acl against the required access mask */
405 status = sec_access_check(sd, token, *access_mask, access_mask);
407 /* this bit is always granted, even if not asked for */
408 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
417 a simplified interface to access check, designed for calls that
418 do not take or return an access check mask
420 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
421 struct ntvfs_request *req,
422 struct pvfs_filename *name,
423 uint32_t access_needed)
425 if (access_needed == 0) {
428 return pvfs_access_check(pvfs, req, name, &access_needed);
432 access check for creating a new file/directory
434 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
435 struct ntvfs_request *req,
436 struct pvfs_filename *name,
437 uint32_t *access_mask)
439 struct pvfs_filename *parent;
442 status = pvfs_resolve_parent(pvfs, req, name, &parent);
443 if (!NT_STATUS_IS_OK(status)) {
447 status = pvfs_access_check(pvfs, req, parent, access_mask);
448 if (!NT_STATUS_IS_OK(status)) {
452 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
453 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
460 access check for creating a new file/directory - no access mask supplied
462 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
463 struct ntvfs_request *req,
464 struct pvfs_filename *name,
465 uint32_t access_mask)
467 struct pvfs_filename *parent;
470 status = pvfs_resolve_parent(pvfs, req, name, &parent);
471 if (!NT_STATUS_IS_OK(status)) {
475 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
480 determine if an ACE is inheritable
482 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
483 const struct security_ace *ace,
487 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
490 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
494 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
495 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
503 this is the core of ACL inheritance. It copies any inheritable
504 aces from the parent SD to the child SD. Note that the algorithm
505 depends on whether the child is a container or not
507 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
508 struct security_descriptor *parent_sd,
509 struct security_descriptor *sd,
514 for (i=0;i<parent_sd->dacl->num_aces;i++) {
515 struct security_ace ace = parent_sd->dacl->aces[i];
517 const struct dom_sid *creator = NULL, *new_id = NULL;
520 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
524 orig_flags = ace.flags;
526 /* see the RAW-ACLS inheritance test for details on these rules */
530 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
532 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
533 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
535 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
540 /* the CREATOR sids are special when inherited */
541 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
542 creator = pvfs->sid_cache.creator_owner;
543 new_id = sd->owner_sid;
544 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
545 creator = pvfs->sid_cache.creator_group;
546 new_id = sd->group_sid;
548 new_id = &ace.trustee;
551 if (creator && container &&
552 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
553 uint32_t flags = ace.flags;
555 ace.trustee = *new_id;
557 status = security_descriptor_dacl_add(sd, &ace);
558 if (!NT_STATUS_IS_OK(status)) {
562 ace.trustee = *creator;
563 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
564 status = security_descriptor_dacl_add(sd, &ace);
565 } else if (container &&
566 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
567 status = security_descriptor_dacl_add(sd, &ace);
569 ace.trustee = *new_id;
570 status = security_descriptor_dacl_add(sd, &ace);
573 if (!NT_STATUS_IS_OK(status)) {
584 setup an ACL on a new file/directory based on the inherited ACL from
585 the parent. If there is no inherited ACL then we don't set anything,
586 as the default ACL applies anyway
588 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
589 struct ntvfs_request *req,
590 struct pvfs_filename *name,
593 struct xattr_NTACL *acl;
595 struct pvfs_filename *parent;
596 struct security_descriptor *parent_sd, *sd;
599 /* form the parents path */
600 status = pvfs_resolve_parent(pvfs, req, name, &parent);
601 if (!NT_STATUS_IS_OK(status)) {
605 acl = talloc(req, struct xattr_NTACL);
607 return NT_STATUS_NO_MEMORY;
610 status = pvfs_acl_load(pvfs, parent, -1, acl);
611 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
614 if (!NT_STATUS_IS_OK(status)) {
618 switch (acl->version) {
620 parent_sd = acl->info.sd;
623 return NT_STATUS_INVALID_ACL;
626 if (parent_sd == NULL ||
627 parent_sd->dacl == NULL ||
628 parent_sd->dacl->num_aces == 0) {
629 /* go with the default ACL */
633 /* create the new sd */
634 sd = security_descriptor_initialise(req);
636 return NT_STATUS_NO_MEMORY;
639 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
640 if (!NT_STATUS_IS_OK(status)) {
643 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
644 if (!NT_STATUS_IS_OK(status)) {
648 sd->type |= SEC_DESC_DACL_PRESENT;
650 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
652 /* fill in the aces from the parent */
653 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
654 if (!NT_STATUS_IS_OK(status)) {
658 /* if there is nothing to inherit then we fallback to the
660 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
666 status = pvfs_acl_save(pvfs, name, fd, acl);