fixed a problem with group policy writes causing policy corruption
[Samba/aatanasov.git] / source4 / ntvfs / posix / pvfs_acl.c
blobad7ac5a7494a8f9dc9a8997cfc3a40a0613f103f
1 /*
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/>.
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "libcli/security/security.h"
27 #include "param/param.h"
30 /* the list of currently registered ACL backends */
31 static struct pvfs_acl_backend {
32 const struct pvfs_acl_ops *ops;
33 } *backends = NULL;
34 static int num_backends;
37 register a pvfs acl backend.
39 The 'name' can be later used by other backends to find the operations
40 structure for this backend.
42 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
44 struct pvfs_acl_ops *new_ops;
46 if (pvfs_acl_backend_byname(ops->name) != NULL) {
47 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
48 return NT_STATUS_OBJECT_NAME_COLLISION;
51 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
52 NT_STATUS_HAVE_NO_MEMORY(backends);
54 new_ops = (struct pvfs_acl_ops *)talloc_memdup(backends, ops, sizeof(*ops));
55 new_ops->name = talloc_strdup(new_ops, ops->name);
57 backends[num_backends].ops = new_ops;
59 num_backends++;
61 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
63 return NT_STATUS_OK;
68 return the operations structure for a named backend
70 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
72 int i;
74 for (i=0;i<num_backends;i++) {
75 if (strcmp(backends[i].ops->name, name) == 0) {
76 return backends[i].ops;
80 return NULL;
83 NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
85 static bool initialized = false;
86 extern NTSTATUS pvfs_acl_nfs4_init(void);
87 extern NTSTATUS pvfs_acl_xattr_init(void);
88 init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
89 init_module_fn *shared_init;
91 if (initialized) return NT_STATUS_OK;
92 initialized = true;
94 shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
96 run_init_functions(static_init);
97 run_init_functions(shared_init);
99 talloc_free(shared_init);
101 return NT_STATUS_OK;
106 map a single access_mask from generic to specific bits for files/dirs
108 static uint32_t pvfs_translate_mask(uint32_t access_mask)
110 if (access_mask & SEC_MASK_GENERIC) {
111 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
112 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
113 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
114 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
115 access_mask &= ~SEC_MASK_GENERIC;
117 return access_mask;
122 map any generic access bits in the given acl
123 this relies on the fact that the mappings for files and directories
124 are the same
126 static void pvfs_translate_generic_bits(struct security_acl *acl)
128 unsigned i;
130 if (!acl) return;
132 for (i=0;i<acl->num_aces;i++) {
133 struct security_ace *ace = &acl->aces[i];
134 ace->access_mask = pvfs_translate_mask(ace->access_mask);
140 setup a default ACL for a file
142 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
143 struct ntvfs_request *req,
144 struct pvfs_filename *name, int fd,
145 struct security_descriptor **psd)
147 struct security_descriptor *sd;
148 NTSTATUS status;
149 struct security_ace ace;
150 mode_t mode;
151 struct id_mapping *ids;
152 struct composite_context *ctx;
154 *psd = security_descriptor_initialise(req);
155 if (*psd == NULL) {
156 return NT_STATUS_NO_MEMORY;
158 sd = *psd;
160 ids = talloc_zero_array(sd, struct id_mapping, 2);
161 NT_STATUS_HAVE_NO_MEMORY(ids);
163 ids[0].unixid = talloc(ids, struct unixid);
164 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
166 ids[0].unixid->id = name->st.st_uid;
167 ids[0].unixid->type = ID_TYPE_UID;
168 ids[0].sid = NULL;
170 ids[1].unixid = talloc(ids, struct unixid);
171 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
173 ids[1].unixid->id = name->st.st_gid;
174 ids[1].unixid->type = ID_TYPE_GID;
175 ids[1].sid = NULL;
177 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
178 NT_STATUS_HAVE_NO_MEMORY(ctx);
180 status = wbc_xids_to_sids_recv(ctx, &ids);
181 NT_STATUS_NOT_OK_RETURN(status);
183 sd->owner_sid = talloc_steal(sd, ids[0].sid);
184 sd->group_sid = talloc_steal(sd, ids[1].sid);
186 talloc_free(ids);
187 sd->type |= SEC_DESC_DACL_PRESENT;
189 mode = name->st.st_mode;
192 we provide up to 4 ACEs
193 - Owner
194 - Group
195 - Everyone
196 - Administrator
200 /* setup owner ACE */
201 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
202 ace.flags = 0;
203 ace.trustee = *sd->owner_sid;
204 ace.access_mask = 0;
206 if (mode & S_IRUSR) {
207 if (mode & S_IWUSR) {
208 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
209 } else {
210 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
213 if (mode & S_IWUSR) {
214 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
216 if (ace.access_mask) {
217 security_descriptor_dacl_add(sd, &ace);
221 /* setup group ACE */
222 ace.trustee = *sd->group_sid;
223 ace.access_mask = 0;
224 if (mode & S_IRGRP) {
225 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
227 if (mode & S_IWGRP) {
228 /* note that delete is not granted - this matches posix behaviour */
229 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
231 if (ace.access_mask) {
232 security_descriptor_dacl_add(sd, &ace);
235 /* setup other ACE */
236 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
237 ace.access_mask = 0;
238 if (mode & S_IROTH) {
239 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
241 if (mode & S_IWOTH) {
242 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
244 if (ace.access_mask) {
245 security_descriptor_dacl_add(sd, &ace);
248 /* setup system ACE */
249 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
250 ace.access_mask = SEC_RIGHTS_FILE_ALL;
251 security_descriptor_dacl_add(sd, &ace);
253 return NT_STATUS_OK;
258 omit any security_descriptor elements not specified in the given
259 secinfo flags
261 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
263 if (!(secinfo_flags & SECINFO_OWNER)) {
264 sd->owner_sid = NULL;
266 if (!(secinfo_flags & SECINFO_GROUP)) {
267 sd->group_sid = NULL;
269 if (!(secinfo_flags & SECINFO_DACL)) {
270 sd->dacl = NULL;
272 if (!(secinfo_flags & SECINFO_SACL)) {
273 sd->sacl = NULL;
278 answer a setfileinfo for an ACL
280 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
281 struct ntvfs_request *req,
282 struct pvfs_filename *name, int fd,
283 uint32_t access_mask,
284 union smb_setfileinfo *info)
286 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
287 struct security_descriptor *new_sd, *sd, orig_sd;
288 NTSTATUS status = NT_STATUS_NOT_FOUND;
289 uid_t old_uid = -1;
290 gid_t old_gid = -1;
291 uid_t new_uid = -1;
292 gid_t new_gid = -1;
293 struct id_mapping *ids;
294 struct composite_context *ctx;
296 if (pvfs->acl_ops != NULL) {
297 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
299 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
300 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
302 if (!NT_STATUS_IS_OK(status)) {
303 return status;
306 ids = talloc(req, struct id_mapping);
307 NT_STATUS_HAVE_NO_MEMORY(ids);
308 ids->unixid = NULL;
309 ids->sid = NULL;
310 ids->status = NT_STATUS_NONE_MAPPED;
312 new_sd = info->set_secdesc.in.sd;
313 orig_sd = *sd;
315 old_uid = name->st.st_uid;
316 old_gid = name->st.st_gid;
318 /* only set the elements that have been specified */
319 if (secinfo_flags & SECINFO_OWNER) {
320 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
321 return NT_STATUS_ACCESS_DENIED;
323 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
324 ids->sid = new_sd->owner_sid;
325 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
326 NT_STATUS_HAVE_NO_MEMORY(ctx);
327 status = wbc_sids_to_xids_recv(ctx, &ids);
328 NT_STATUS_NOT_OK_RETURN(status);
330 if (ids->unixid->type == ID_TYPE_BOTH ||
331 ids->unixid->type == ID_TYPE_UID) {
332 new_uid = ids->unixid->id;
335 sd->owner_sid = new_sd->owner_sid;
337 if (secinfo_flags & SECINFO_GROUP) {
338 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
339 return NT_STATUS_ACCESS_DENIED;
341 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
342 ids->sid = new_sd->group_sid;
343 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
344 NT_STATUS_HAVE_NO_MEMORY(ctx);
345 status = wbc_sids_to_xids_recv(ctx, &ids);
346 NT_STATUS_NOT_OK_RETURN(status);
348 if (ids->unixid->type == ID_TYPE_BOTH ||
349 ids->unixid->type == ID_TYPE_GID) {
350 new_gid = ids->unixid->id;
354 sd->group_sid = new_sd->group_sid;
356 if (secinfo_flags & SECINFO_DACL) {
357 if (!(access_mask & SEC_STD_WRITE_DAC)) {
358 return NT_STATUS_ACCESS_DENIED;
360 sd->dacl = new_sd->dacl;
361 pvfs_translate_generic_bits(sd->dacl);
363 if (secinfo_flags & SECINFO_SACL) {
364 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
365 return NT_STATUS_ACCESS_DENIED;
367 sd->sacl = new_sd->sacl;
368 pvfs_translate_generic_bits(sd->sacl);
371 if (new_uid == old_uid) {
372 new_uid = -1;
375 if (new_gid == old_gid) {
376 new_gid = -1;
379 /* if there's something to change try it */
380 if (new_uid != -1 || new_gid != -1) {
381 int ret;
382 if (fd == -1) {
383 ret = chown(name->full_name, new_uid, new_gid);
384 } else {
385 ret = fchown(fd, new_uid, new_gid);
387 if (ret == -1) {
388 return pvfs_map_errno(pvfs, errno);
392 /* we avoid saving if the sd is the same. This means when clients
393 copy files and end up copying the default sd that we don't
394 needlessly use xattrs */
395 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
396 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
399 return status;
404 answer a fileinfo query for the ACL
406 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
407 struct ntvfs_request *req,
408 struct pvfs_filename *name, int fd,
409 union smb_fileinfo *info)
411 NTSTATUS status = NT_STATUS_NOT_FOUND;
412 struct security_descriptor *sd;
414 if (pvfs->acl_ops) {
415 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
417 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
418 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
420 if (!NT_STATUS_IS_OK(status)) {
421 return status;
424 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
426 info->query_secdesc.out.sd = sd;
428 return NT_STATUS_OK;
433 check the read only bit against any of the write access bits
435 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
437 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
438 (access_mask & (SEC_FILE_WRITE_DATA |
439 SEC_FILE_APPEND_DATA |
440 SEC_FILE_WRITE_EA |
441 SEC_FILE_WRITE_ATTRIBUTE |
442 SEC_STD_DELETE |
443 SEC_STD_WRITE_DAC |
444 SEC_STD_WRITE_OWNER |
445 SEC_DIR_DELETE_CHILD))) {
446 return true;
448 return false;
452 see if we are a member of the appropriate unix group
454 static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
456 int i, ngroups;
457 gid_t *groups;
458 if (getegid() == gid) {
459 return true;
461 ngroups = getgroups(0, NULL);
462 if (ngroups == 0) {
463 return false;
465 groups = talloc_array(pvfs, gid_t, ngroups);
466 if (groups == NULL) {
467 return false;
469 if (getgroups(ngroups, groups) != ngroups) {
470 talloc_free(groups);
471 return false;
473 for (i=0; i<ngroups; i++) {
474 if (groups[i] == gid) break;
476 talloc_free(groups);
477 return i < ngroups;
481 default access check function based on unix permissions
482 doing this saves on building a full security descriptor
483 for the common case of access check on files with no
484 specific NT ACL
486 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
487 struct ntvfs_request *req,
488 struct pvfs_filename *name,
489 uint32_t *access_mask)
491 uid_t uid = geteuid();
492 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
494 if (pvfs_read_only(pvfs, *access_mask)) {
495 return NT_STATUS_ACCESS_DENIED;
498 /* owner and root get extra permissions */
499 if (uid == 0) {
500 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
501 } else if (uid == name->st.st_uid) {
502 max_bits |= SEC_STD_ALL;
505 if ((name->st.st_mode & S_IWOTH) ||
506 ((name->st.st_mode & S_IWGRP) &&
507 pvfs_group_member(pvfs, name->st.st_gid))) {
508 max_bits |= SEC_STD_ALL;
511 if (uwrap_enabled()) {
512 /* when running with the uid wrapper, files will be created
513 owned by the ruid, but we may have a different simulated
514 euid. We need to force the permission bits as though the
515 files owner matches the euid */
516 max_bits |= SEC_STD_ALL;
519 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
520 *access_mask = max_bits;
521 return NT_STATUS_OK;
524 if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
525 return NT_STATUS_ACCESS_DENIED;
528 if (*access_mask & ~max_bits) {
529 DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
530 name->full_name, *access_mask, max_bits, *access_mask & ~max_bits));
531 return NT_STATUS_ACCESS_DENIED;
534 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
535 /* on SMB, this bit is always granted, even if not
536 asked for */
537 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
540 return NT_STATUS_OK;
545 check the security descriptor on a file, if any
547 *access_mask is modified with the access actually granted
549 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
550 struct ntvfs_request *req,
551 struct pvfs_filename *name,
552 uint32_t *access_mask)
554 struct security_token *token = req->session_info->security_token;
555 struct xattr_NTACL *acl;
556 NTSTATUS status;
557 struct security_descriptor *sd;
559 /* on SMB2 a blank access mask is always denied */
560 if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
561 *access_mask == 0) {
562 return NT_STATUS_ACCESS_DENIED;
565 if (pvfs_read_only(pvfs, *access_mask)) {
566 return NT_STATUS_ACCESS_DENIED;
569 acl = talloc(req, struct xattr_NTACL);
570 if (acl == NULL) {
571 return NT_STATUS_NO_MEMORY;
574 /* expand the generic access bits to file specific bits */
575 *access_mask = pvfs_translate_mask(*access_mask);
576 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
577 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
580 status = pvfs_acl_load(pvfs, name, -1, acl);
581 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
582 talloc_free(acl);
583 return pvfs_access_check_unix(pvfs, req, name, access_mask);
585 if (!NT_STATUS_IS_OK(status)) {
586 return status;
589 switch (acl->version) {
590 case 1:
591 sd = acl->info.sd;
592 break;
593 default:
594 return NT_STATUS_INVALID_ACL;
597 /* check the acl against the required access mask */
598 status = sec_access_check(sd, token, *access_mask, access_mask);
600 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
601 /* on SMB, this bit is always granted, even if not
602 asked for */
603 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
606 talloc_free(acl);
608 return status;
613 a simplified interface to access check, designed for calls that
614 do not take or return an access check mask
616 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
617 struct ntvfs_request *req,
618 struct pvfs_filename *name,
619 uint32_t access_needed)
621 if (access_needed == 0) {
622 return NT_STATUS_OK;
624 return pvfs_access_check(pvfs, req, name, &access_needed);
628 access check for creating a new file/directory
630 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
631 struct ntvfs_request *req,
632 struct pvfs_filename *name,
633 uint32_t *access_mask)
635 struct pvfs_filename *parent;
636 NTSTATUS status;
638 status = pvfs_resolve_parent(pvfs, req, name, &parent);
639 if (!NT_STATUS_IS_OK(status)) {
640 return status;
643 status = pvfs_access_check(pvfs, req, parent, access_mask);
644 if (!NT_STATUS_IS_OK(status)) {
645 return status;
648 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
649 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
652 return status;
656 access check for creating a new file/directory - no access mask supplied
658 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
659 struct ntvfs_request *req,
660 struct pvfs_filename *name,
661 uint32_t access_mask)
663 struct pvfs_filename *parent;
664 NTSTATUS status;
666 status = pvfs_resolve_parent(pvfs, req, name, &parent);
667 if (!NT_STATUS_IS_OK(status)) {
668 return status;
671 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
676 determine if an ACE is inheritable
678 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
679 const struct security_ace *ace,
680 bool container)
682 if (!container) {
683 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
686 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
687 return true;
690 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
691 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
692 return true;
695 return false;
699 this is the core of ACL inheritance. It copies any inheritable
700 aces from the parent SD to the child SD. Note that the algorithm
701 depends on whether the child is a container or not
703 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
704 struct security_descriptor *parent_sd,
705 struct security_descriptor *sd,
706 bool container)
708 int i;
710 for (i=0;i<parent_sd->dacl->num_aces;i++) {
711 struct security_ace ace = parent_sd->dacl->aces[i];
712 NTSTATUS status;
713 const struct dom_sid *creator = NULL, *new_id = NULL;
714 uint32_t orig_flags;
716 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
717 continue;
720 orig_flags = ace.flags;
722 /* see the RAW-ACLS inheritance test for details on these rules */
723 if (!container) {
724 ace.flags = 0;
725 } else {
726 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
728 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
729 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
731 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
732 ace.flags = 0;
736 /* the CREATOR sids are special when inherited */
737 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
738 creator = pvfs->sid_cache.creator_owner;
739 new_id = sd->owner_sid;
740 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
741 creator = pvfs->sid_cache.creator_group;
742 new_id = sd->group_sid;
743 } else {
744 new_id = &ace.trustee;
747 if (creator && container &&
748 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
749 uint32_t flags = ace.flags;
751 ace.trustee = *new_id;
752 ace.flags = 0;
753 status = security_descriptor_dacl_add(sd, &ace);
754 if (!NT_STATUS_IS_OK(status)) {
755 return status;
758 ace.trustee = *creator;
759 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
760 status = security_descriptor_dacl_add(sd, &ace);
761 } else if (container &&
762 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
763 status = security_descriptor_dacl_add(sd, &ace);
764 } else {
765 ace.trustee = *new_id;
766 status = security_descriptor_dacl_add(sd, &ace);
769 if (!NT_STATUS_IS_OK(status)) {
770 return status;
774 return NT_STATUS_OK;
780 setup an ACL on a new file/directory based on the inherited ACL from
781 the parent. If there is no inherited ACL then we don't set anything,
782 as the default ACL applies anyway
784 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
785 struct ntvfs_request *req,
786 struct pvfs_filename *name,
787 int fd)
789 struct xattr_NTACL *acl;
790 NTSTATUS status;
791 struct pvfs_filename *parent;
792 struct security_descriptor *parent_sd, *sd;
793 bool container;
794 struct id_mapping *ids;
795 struct composite_context *ctx;
797 /* form the parents path */
798 status = pvfs_resolve_parent(pvfs, req, name, &parent);
799 if (!NT_STATUS_IS_OK(status)) {
800 return status;
803 acl = talloc(req, struct xattr_NTACL);
804 if (acl == NULL) {
805 return NT_STATUS_NO_MEMORY;
808 status = pvfs_acl_load(pvfs, parent, -1, acl);
809 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
810 return NT_STATUS_OK;
812 if (!NT_STATUS_IS_OK(status)) {
813 return status;
816 switch (acl->version) {
817 case 1:
818 parent_sd = acl->info.sd;
819 break;
820 default:
821 return NT_STATUS_INVALID_ACL;
824 if (parent_sd == NULL ||
825 parent_sd->dacl == NULL ||
826 parent_sd->dacl->num_aces == 0) {
827 /* go with the default ACL */
828 return NT_STATUS_OK;
831 /* create the new sd */
832 sd = security_descriptor_initialise(req);
833 if (sd == NULL) {
834 return NT_STATUS_NO_MEMORY;
837 ids = talloc_array(sd, struct id_mapping, 2);
838 NT_STATUS_HAVE_NO_MEMORY(ids);
840 ids[0].unixid = talloc(ids, struct unixid);
841 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
842 ids[0].unixid->id = name->st.st_uid;
843 ids[0].unixid->type = ID_TYPE_UID;
844 ids[0].sid = NULL;
845 ids[0].status = NT_STATUS_NONE_MAPPED;
847 ids[1].unixid = talloc(ids, struct unixid);
848 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
849 ids[1].unixid->id = name->st.st_gid;
850 ids[1].unixid->type = ID_TYPE_GID;
851 ids[1].sid = NULL;
852 ids[1].status = NT_STATUS_NONE_MAPPED;
854 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
855 NT_STATUS_HAVE_NO_MEMORY(ctx);
857 status = wbc_xids_to_sids_recv(ctx, &ids);
858 NT_STATUS_NOT_OK_RETURN(status);
860 sd->owner_sid = talloc_steal(sd, ids[0].sid);
861 sd->group_sid = talloc_steal(sd, ids[1].sid);
863 sd->type |= SEC_DESC_DACL_PRESENT;
865 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
867 /* fill in the aces from the parent */
868 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
869 if (!NT_STATUS_IS_OK(status)) {
870 return status;
873 /* if there is nothing to inherit then we fallback to the
874 default acl */
875 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
876 return NT_STATUS_OK;
879 acl->info.sd = sd;
881 status = pvfs_acl_save(pvfs, name, fd, acl);
883 return status;
887 return the maximum allowed access mask
889 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
890 struct ntvfs_request *req,
891 struct pvfs_filename *name,
892 uint32_t *maximal_access)
894 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
895 return pvfs_access_check(pvfs, req, name, maximal_access);