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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "auth/auth.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "libcli/security/security.h"
29 /* the list of currently registered ACL backends */
30 static struct pvfs_acl_backend {
31 const struct pvfs_acl_ops *ops;
33 static int num_backends;
36 register a pvfs acl backend.
38 The 'name' can be later used by other backends to find the operations
39 structure for this backend.
41 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
43 struct pvfs_acl_ops *new_ops;
45 if (pvfs_acl_backend_byname(ops->name) != NULL) {
46 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
47 return NT_STATUS_OBJECT_NAME_COLLISION;
50 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
51 NT_STATUS_HAVE_NO_MEMORY(backends);
53 new_ops = talloc_memdup(backends, ops, sizeof(*ops));
54 new_ops->name = talloc_strdup(new_ops, ops->name);
56 backends[num_backends].ops = new_ops;
60 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
67 return the operations structure for a named backend
69 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
73 for (i=0;i<num_backends;i++) {
74 if (strcmp(backends[i].ops->name, name) == 0) {
75 return backends[i].ops;
84 map a single access_mask from generic to specific bits for files/dirs
86 static uint32_t pvfs_translate_mask(uint32_t access_mask)
88 if (access_mask & SEC_MASK_GENERIC) {
89 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
90 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
91 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
92 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
93 access_mask &= ~SEC_MASK_GENERIC;
100 map any generic access bits in the given acl
101 this relies on the fact that the mappings for files and directories
104 static void pvfs_translate_generic_bits(struct security_acl *acl)
110 for (i=0;i<acl->num_aces;i++) {
111 struct security_ace *ace = &acl->aces[i];
112 ace->access_mask = pvfs_translate_mask(ace->access_mask);
118 setup a default ACL for a file
120 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
121 struct ntvfs_request *req,
122 struct pvfs_filename *name, int fd,
123 struct security_descriptor **psd)
125 struct security_descriptor *sd;
127 struct security_ace ace;
129 struct id_mapping *ids;
130 struct composite_context *ctx;
132 *psd = security_descriptor_initialise(req);
134 return NT_STATUS_NO_MEMORY;
138 ids = talloc_array(sd, struct id_mapping, 2);
139 NT_STATUS_HAVE_NO_MEMORY(ids);
141 ids[0].unixid = talloc(ids, struct unixid);
142 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
144 ids[0].unixid->id = name->st.st_uid;
145 ids[0].unixid->type = ID_TYPE_UID;
148 ids[1].unixid = talloc(ids, struct unixid);
149 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
151 ids[1].unixid->id = name->st.st_gid;
152 ids[1].unixid->type = ID_TYPE_GID;
155 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
156 NT_STATUS_HAVE_NO_MEMORY(ctx);
158 status = wbc_xids_to_sids_recv(ctx, &ids);
159 NT_STATUS_NOT_OK_RETURN(status);
161 sd->owner_sid = talloc_steal(sd, ids[0].sid);
162 sd->group_sid = talloc_steal(sd, ids[1].sid);
165 sd->type |= SEC_DESC_DACL_PRESENT;
167 mode = name->st.st_mode;
170 we provide up to 4 ACEs
178 /* setup owner ACE */
179 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
181 ace.trustee = *sd->owner_sid;
184 if (mode & S_IRUSR) {
185 if (mode & S_IWUSR) {
186 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
188 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
191 if (mode & S_IWUSR) {
192 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
194 if (ace.access_mask) {
195 security_descriptor_dacl_add(sd, &ace);
199 /* setup group ACE */
200 ace.trustee = *sd->group_sid;
202 if (mode & S_IRGRP) {
203 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
205 if (mode & S_IWGRP) {
206 /* note that delete is not granted - this matches posix behaviour */
207 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
209 if (ace.access_mask) {
210 security_descriptor_dacl_add(sd, &ace);
213 /* setup other ACE */
214 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
216 if (mode & S_IROTH) {
217 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
219 if (mode & S_IWOTH) {
220 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
222 if (ace.access_mask) {
223 security_descriptor_dacl_add(sd, &ace);
226 /* setup system ACE */
227 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
228 ace.access_mask = SEC_RIGHTS_FILE_ALL;
229 security_descriptor_dacl_add(sd, &ace);
236 omit any security_descriptor elements not specified in the given
239 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
241 if (!(secinfo_flags & SECINFO_OWNER)) {
242 sd->owner_sid = NULL;
244 if (!(secinfo_flags & SECINFO_GROUP)) {
245 sd->group_sid = NULL;
247 if (!(secinfo_flags & SECINFO_DACL)) {
250 if (!(secinfo_flags & SECINFO_SACL)) {
256 answer a setfileinfo for an ACL
258 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
259 struct ntvfs_request *req,
260 struct pvfs_filename *name, int fd,
261 uint32_t access_mask,
262 union smb_setfileinfo *info)
264 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
265 struct security_descriptor *new_sd, *sd, orig_sd;
266 NTSTATUS status = NT_STATUS_NOT_FOUND;
271 struct id_mapping *ids;
272 struct composite_context *ctx;
274 if (pvfs->acl_ops != NULL) {
275 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
277 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
278 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
280 if (!NT_STATUS_IS_OK(status)) {
284 ids = talloc(req, struct id_mapping);
285 NT_STATUS_HAVE_NO_MEMORY(ids);
288 ids->status = NT_STATUS_NONE_MAPPED;
290 new_sd = info->set_secdesc.in.sd;
293 old_uid = name->st.st_uid;
294 old_gid = name->st.st_gid;
296 /* only set the elements that have been specified */
297 if (secinfo_flags & SECINFO_OWNER) {
298 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
299 return NT_STATUS_ACCESS_DENIED;
301 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
302 ids->sid = new_sd->owner_sid;
303 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
304 NT_STATUS_HAVE_NO_MEMORY(ctx);
305 status = wbc_sids_to_xids_recv(ctx, &ids);
306 NT_STATUS_NOT_OK_RETURN(status);
308 if (ids->unixid->type == ID_TYPE_BOTH ||
309 ids->unixid->type == ID_TYPE_UID) {
310 new_uid = ids->unixid->id;
313 sd->owner_sid = new_sd->owner_sid;
315 if (secinfo_flags & SECINFO_GROUP) {
316 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
317 return NT_STATUS_ACCESS_DENIED;
319 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
320 ids->sid = new_sd->group_sid;
321 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
322 NT_STATUS_HAVE_NO_MEMORY(ctx);
323 status = wbc_sids_to_xids_recv(ctx, &ids);
324 NT_STATUS_NOT_OK_RETURN(status);
326 if (ids->unixid->type == ID_TYPE_BOTH ||
327 ids->unixid->type == ID_TYPE_GID) {
328 new_gid = ids->unixid->id;
332 sd->group_sid = new_sd->group_sid;
334 if (secinfo_flags & SECINFO_DACL) {
335 if (!(access_mask & SEC_STD_WRITE_DAC)) {
336 return NT_STATUS_ACCESS_DENIED;
338 sd->dacl = new_sd->dacl;
339 pvfs_translate_generic_bits(sd->dacl);
341 if (secinfo_flags & SECINFO_SACL) {
342 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
343 return NT_STATUS_ACCESS_DENIED;
345 sd->sacl = new_sd->sacl;
346 pvfs_translate_generic_bits(sd->sacl);
349 if (new_uid == old_uid) {
353 if (new_gid == old_gid) {
357 /* if there's something to change try it */
358 if (new_uid != -1 || new_gid != -1) {
361 ret = chown(name->full_name, new_uid, new_gid);
363 ret = fchown(fd, new_uid, new_gid);
366 return pvfs_map_errno(pvfs, errno);
370 /* we avoid saving if the sd is the same. This means when clients
371 copy files and end up copying the default sd that we don't
372 needlessly use xattrs */
373 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
374 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
382 answer a fileinfo query for the ACL
384 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
385 struct ntvfs_request *req,
386 struct pvfs_filename *name, int fd,
387 union smb_fileinfo *info)
389 NTSTATUS status = NT_STATUS_NOT_FOUND;
390 struct security_descriptor *sd;
393 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
395 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
396 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
398 if (!NT_STATUS_IS_OK(status)) {
402 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
404 info->query_secdesc.out.sd = sd;
411 check the read only bit against any of the write access bits
413 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
415 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
416 (access_mask & (SEC_FILE_WRITE_DATA |
417 SEC_FILE_APPEND_DATA |
419 SEC_FILE_WRITE_ATTRIBUTE |
422 SEC_STD_WRITE_OWNER |
423 SEC_DIR_DELETE_CHILD))) {
430 default access check function based on unix permissions
431 doing this saves on building a full security descriptor
432 for the common case of access check on files with no
435 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
436 struct ntvfs_request *req,
437 struct pvfs_filename *name,
438 uint32_t *access_mask)
440 uid_t uid = geteuid();
441 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
443 if (pvfs_read_only(pvfs, *access_mask)) {
444 return NT_STATUS_ACCESS_DENIED;
447 /* owner and root get extra permissions */
449 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
450 } else if (uid == name->st.st_uid) {
451 max_bits |= SEC_STD_ALL;
454 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
455 *access_mask = max_bits;
459 if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
460 return NT_STATUS_PRIVILEGE_NOT_HELD;
463 if (*access_mask & ~max_bits) {
464 return NT_STATUS_ACCESS_DENIED;
467 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
474 check the security descriptor on a file, if any
476 *access_mask is modified with the access actually granted
478 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
479 struct ntvfs_request *req,
480 struct pvfs_filename *name,
481 uint32_t *access_mask)
483 struct security_token *token = req->session_info->security_token;
484 struct xattr_NTACL *acl;
486 struct security_descriptor *sd;
488 if (pvfs_read_only(pvfs, *access_mask)) {
489 return NT_STATUS_ACCESS_DENIED;
492 acl = talloc(req, struct xattr_NTACL);
494 return NT_STATUS_NO_MEMORY;
497 /* expand the generic access bits to file specific bits */
498 *access_mask = pvfs_translate_mask(*access_mask);
499 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
501 status = pvfs_acl_load(pvfs, name, -1, acl);
502 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
504 return pvfs_access_check_unix(pvfs, req, name, access_mask);
506 if (!NT_STATUS_IS_OK(status)) {
510 switch (acl->version) {
515 return NT_STATUS_INVALID_ACL;
518 /* check the acl against the required access mask */
519 status = sec_access_check(sd, token, *access_mask, access_mask);
521 /* this bit is always granted, even if not asked for */
522 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
531 a simplified interface to access check, designed for calls that
532 do not take or return an access check mask
534 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
535 struct ntvfs_request *req,
536 struct pvfs_filename *name,
537 uint32_t access_needed)
539 if (access_needed == 0) {
542 return pvfs_access_check(pvfs, req, name, &access_needed);
546 access check for creating a new file/directory
548 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
549 struct ntvfs_request *req,
550 struct pvfs_filename *name,
551 uint32_t *access_mask)
553 struct pvfs_filename *parent;
556 status = pvfs_resolve_parent(pvfs, req, name, &parent);
557 if (!NT_STATUS_IS_OK(status)) {
561 status = pvfs_access_check(pvfs, req, parent, access_mask);
562 if (!NT_STATUS_IS_OK(status)) {
566 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
567 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
574 access check for creating a new file/directory - no access mask supplied
576 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
577 struct ntvfs_request *req,
578 struct pvfs_filename *name,
579 uint32_t access_mask)
581 struct pvfs_filename *parent;
584 status = pvfs_resolve_parent(pvfs, req, name, &parent);
585 if (!NT_STATUS_IS_OK(status)) {
589 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
594 determine if an ACE is inheritable
596 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
597 const struct security_ace *ace,
601 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
604 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
608 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
609 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
617 this is the core of ACL inheritance. It copies any inheritable
618 aces from the parent SD to the child SD. Note that the algorithm
619 depends on whether the child is a container or not
621 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
622 struct security_descriptor *parent_sd,
623 struct security_descriptor *sd,
628 for (i=0;i<parent_sd->dacl->num_aces;i++) {
629 struct security_ace ace = parent_sd->dacl->aces[i];
631 const struct dom_sid *creator = NULL, *new_id = NULL;
634 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
638 orig_flags = ace.flags;
640 /* see the RAW-ACLS inheritance test for details on these rules */
644 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
646 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
647 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
649 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
654 /* the CREATOR sids are special when inherited */
655 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
656 creator = pvfs->sid_cache.creator_owner;
657 new_id = sd->owner_sid;
658 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
659 creator = pvfs->sid_cache.creator_group;
660 new_id = sd->group_sid;
662 new_id = &ace.trustee;
665 if (creator && container &&
666 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
667 uint32_t flags = ace.flags;
669 ace.trustee = *new_id;
671 status = security_descriptor_dacl_add(sd, &ace);
672 if (!NT_STATUS_IS_OK(status)) {
676 ace.trustee = *creator;
677 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
678 status = security_descriptor_dacl_add(sd, &ace);
679 } else if (container &&
680 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
681 status = security_descriptor_dacl_add(sd, &ace);
683 ace.trustee = *new_id;
684 status = security_descriptor_dacl_add(sd, &ace);
687 if (!NT_STATUS_IS_OK(status)) {
698 setup an ACL on a new file/directory based on the inherited ACL from
699 the parent. If there is no inherited ACL then we don't set anything,
700 as the default ACL applies anyway
702 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
703 struct ntvfs_request *req,
704 struct pvfs_filename *name,
707 struct xattr_NTACL *acl;
709 struct pvfs_filename *parent;
710 struct security_descriptor *parent_sd, *sd;
712 struct id_mapping *ids;
713 struct composite_context *ctx;
715 /* form the parents path */
716 status = pvfs_resolve_parent(pvfs, req, name, &parent);
717 if (!NT_STATUS_IS_OK(status)) {
721 acl = talloc(req, struct xattr_NTACL);
723 return NT_STATUS_NO_MEMORY;
726 status = pvfs_acl_load(pvfs, parent, -1, acl);
727 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
730 if (!NT_STATUS_IS_OK(status)) {
734 switch (acl->version) {
736 parent_sd = acl->info.sd;
739 return NT_STATUS_INVALID_ACL;
742 if (parent_sd == NULL ||
743 parent_sd->dacl == NULL ||
744 parent_sd->dacl->num_aces == 0) {
745 /* go with the default ACL */
749 /* create the new sd */
750 sd = security_descriptor_initialise(req);
752 return NT_STATUS_NO_MEMORY;
755 ids = talloc_array(sd, struct id_mapping, 2);
756 NT_STATUS_HAVE_NO_MEMORY(ids);
758 ids[0].unixid = talloc(ids, struct unixid);
759 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
760 ids[0].unixid->id = name->st.st_uid;
761 ids[0].unixid->type = ID_TYPE_UID;
763 ids[0].status = NT_STATUS_NONE_MAPPED;
765 ids[1].unixid = talloc(ids, struct unixid);
766 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
767 ids[1].unixid->id = name->st.st_gid;
768 ids[1].unixid->type = ID_TYPE_GID;
770 ids[1].status = NT_STATUS_NONE_MAPPED;
772 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
773 NT_STATUS_HAVE_NO_MEMORY(ctx);
775 status = wbc_xids_to_sids_recv(ctx, &ids);
776 NT_STATUS_NOT_OK_RETURN(status);
778 sd->owner_sid = talloc_steal(sd, ids[0].sid);
779 sd->group_sid = talloc_steal(sd, ids[1].sid);
781 sd->type |= SEC_DESC_DACL_PRESENT;
783 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
785 /* fill in the aces from the parent */
786 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
787 if (!NT_STATUS_IS_OK(status)) {
791 /* if there is nothing to inherit then we fallback to the
793 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
799 status = pvfs_acl_save(pvfs, name, fd, acl);