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_zero_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_ACCESS_DENIED;
463 if (*access_mask & ~max_bits) {
464 return NT_STATUS_ACCESS_DENIED;
467 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
468 /* on SMB, this bit is always granted, even if not
470 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
478 check the security descriptor on a file, if any
480 *access_mask is modified with the access actually granted
482 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
483 struct ntvfs_request *req,
484 struct pvfs_filename *name,
485 uint32_t *access_mask)
487 struct security_token *token = req->session_info->security_token;
488 struct xattr_NTACL *acl;
490 struct security_descriptor *sd;
492 if (pvfs_read_only(pvfs, *access_mask)) {
493 return NT_STATUS_ACCESS_DENIED;
496 acl = talloc(req, struct xattr_NTACL);
498 return NT_STATUS_NO_MEMORY;
501 /* expand the generic access bits to file specific bits */
502 *access_mask = pvfs_translate_mask(*access_mask);
503 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
504 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
507 status = pvfs_acl_load(pvfs, name, -1, acl);
508 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
510 return pvfs_access_check_unix(pvfs, req, name, access_mask);
512 if (!NT_STATUS_IS_OK(status)) {
516 switch (acl->version) {
521 return NT_STATUS_INVALID_ACL;
524 /* check the acl against the required access mask */
525 status = sec_access_check(sd, token, *access_mask, access_mask);
527 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
528 /* on SMB, this bit is always granted, even if not
530 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
540 a simplified interface to access check, designed for calls that
541 do not take or return an access check mask
543 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
544 struct ntvfs_request *req,
545 struct pvfs_filename *name,
546 uint32_t access_needed)
548 if (access_needed == 0) {
551 return pvfs_access_check(pvfs, req, name, &access_needed);
555 access check for creating a new file/directory
557 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
558 struct ntvfs_request *req,
559 struct pvfs_filename *name,
560 uint32_t *access_mask)
562 struct pvfs_filename *parent;
565 status = pvfs_resolve_parent(pvfs, req, name, &parent);
566 if (!NT_STATUS_IS_OK(status)) {
570 status = pvfs_access_check(pvfs, req, parent, access_mask);
571 if (!NT_STATUS_IS_OK(status)) {
575 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
576 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
583 access check for creating a new file/directory - no access mask supplied
585 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
586 struct ntvfs_request *req,
587 struct pvfs_filename *name,
588 uint32_t access_mask)
590 struct pvfs_filename *parent;
593 status = pvfs_resolve_parent(pvfs, req, name, &parent);
594 if (!NT_STATUS_IS_OK(status)) {
598 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
603 determine if an ACE is inheritable
605 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
606 const struct security_ace *ace,
610 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
613 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
617 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
618 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
626 this is the core of ACL inheritance. It copies any inheritable
627 aces from the parent SD to the child SD. Note that the algorithm
628 depends on whether the child is a container or not
630 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
631 struct security_descriptor *parent_sd,
632 struct security_descriptor *sd,
637 for (i=0;i<parent_sd->dacl->num_aces;i++) {
638 struct security_ace ace = parent_sd->dacl->aces[i];
640 const struct dom_sid *creator = NULL, *new_id = NULL;
643 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
647 orig_flags = ace.flags;
649 /* see the RAW-ACLS inheritance test for details on these rules */
653 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
655 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
656 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
658 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
663 /* the CREATOR sids are special when inherited */
664 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
665 creator = pvfs->sid_cache.creator_owner;
666 new_id = sd->owner_sid;
667 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
668 creator = pvfs->sid_cache.creator_group;
669 new_id = sd->group_sid;
671 new_id = &ace.trustee;
674 if (creator && container &&
675 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
676 uint32_t flags = ace.flags;
678 ace.trustee = *new_id;
680 status = security_descriptor_dacl_add(sd, &ace);
681 if (!NT_STATUS_IS_OK(status)) {
685 ace.trustee = *creator;
686 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
687 status = security_descriptor_dacl_add(sd, &ace);
688 } else if (container &&
689 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
690 status = security_descriptor_dacl_add(sd, &ace);
692 ace.trustee = *new_id;
693 status = security_descriptor_dacl_add(sd, &ace);
696 if (!NT_STATUS_IS_OK(status)) {
707 setup an ACL on a new file/directory based on the inherited ACL from
708 the parent. If there is no inherited ACL then we don't set anything,
709 as the default ACL applies anyway
711 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
712 struct ntvfs_request *req,
713 struct pvfs_filename *name,
716 struct xattr_NTACL *acl;
718 struct pvfs_filename *parent;
719 struct security_descriptor *parent_sd, *sd;
721 struct id_mapping *ids;
722 struct composite_context *ctx;
724 /* form the parents path */
725 status = pvfs_resolve_parent(pvfs, req, name, &parent);
726 if (!NT_STATUS_IS_OK(status)) {
730 acl = talloc(req, struct xattr_NTACL);
732 return NT_STATUS_NO_MEMORY;
735 status = pvfs_acl_load(pvfs, parent, -1, acl);
736 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
739 if (!NT_STATUS_IS_OK(status)) {
743 switch (acl->version) {
745 parent_sd = acl->info.sd;
748 return NT_STATUS_INVALID_ACL;
751 if (parent_sd == NULL ||
752 parent_sd->dacl == NULL ||
753 parent_sd->dacl->num_aces == 0) {
754 /* go with the default ACL */
758 /* create the new sd */
759 sd = security_descriptor_initialise(req);
761 return NT_STATUS_NO_MEMORY;
764 ids = talloc_array(sd, struct id_mapping, 2);
765 NT_STATUS_HAVE_NO_MEMORY(ids);
767 ids[0].unixid = talloc(ids, struct unixid);
768 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
769 ids[0].unixid->id = name->st.st_uid;
770 ids[0].unixid->type = ID_TYPE_UID;
772 ids[0].status = NT_STATUS_NONE_MAPPED;
774 ids[1].unixid = talloc(ids, struct unixid);
775 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
776 ids[1].unixid->id = name->st.st_gid;
777 ids[1].unixid->type = ID_TYPE_GID;
779 ids[1].status = NT_STATUS_NONE_MAPPED;
781 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
782 NT_STATUS_HAVE_NO_MEMORY(ctx);
784 status = wbc_xids_to_sids_recv(ctx, &ids);
785 NT_STATUS_NOT_OK_RETURN(status);
787 sd->owner_sid = talloc_steal(sd, ids[0].sid);
788 sd->group_sid = talloc_steal(sd, ids[1].sid);
790 sd->type |= SEC_DESC_DACL_PRESENT;
792 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
794 /* fill in the aces from the parent */
795 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
796 if (!NT_STATUS_IS_OK(status)) {
800 /* if there is nothing to inherit then we fallback to the
802 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
808 status = pvfs_acl_save(pvfs, name, fd, acl);
814 return the maximum allowed access mask
816 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
817 struct ntvfs_request *req,
818 struct pvfs_filename *name,
819 uint32_t *maximal_access)
821 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
822 return pvfs_access_check(pvfs, req, name, maximal_access);