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"
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;
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;
61 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
68 return the operations structure for a named backend
70 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
74 for (i=0;i<num_backends;i++) {
75 if (strcmp(backends[i].ops->name, name) == 0) {
76 return backends[i].ops;
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;
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);
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;
122 map any generic access bits in the given acl
123 this relies on the fact that the mappings for files and directories
126 static void pvfs_translate_generic_bits(struct security_acl *acl)
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;
149 struct security_ace ace;
151 struct id_mapping *ids;
152 struct composite_context *ctx;
154 *psd = security_descriptor_initialise(req);
156 return NT_STATUS_NO_MEMORY;
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;
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;
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);
187 sd->type |= SEC_DESC_DACL_PRESENT;
189 mode = name->st.st_mode;
192 we provide up to 4 ACEs
200 /* setup owner ACE */
201 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
203 ace.trustee = *sd->owner_sid;
206 if (mode & S_IRUSR) {
207 if (mode & S_IWUSR) {
208 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
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;
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);
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);
258 omit any security_descriptor elements not specified in the given
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)) {
272 if (!(secinfo_flags & SECINFO_SACL)) {
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;
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)) {
306 ids = talloc(req, struct id_mapping);
307 NT_STATUS_HAVE_NO_MEMORY(ids);
310 ids->status = NT_STATUS_NONE_MAPPED;
312 new_sd = info->set_secdesc.in.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) {
375 if (new_gid == old_gid) {
379 /* if there's something to change try it */
380 if (new_uid != -1 || new_gid != -1) {
383 ret = chown(name->full_name, new_uid, new_gid);
385 ret = fchown(fd, new_uid, new_gid);
387 if (errno == EPERM && uwrap_enabled()) {
391 return pvfs_map_errno(pvfs, errno);
395 /* we avoid saving if the sd is the same. This means when clients
396 copy files and end up copying the default sd that we don't
397 needlessly use xattrs */
398 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
399 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
407 answer a fileinfo query for the ACL
409 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
410 struct ntvfs_request *req,
411 struct pvfs_filename *name, int fd,
412 union smb_fileinfo *info)
414 NTSTATUS status = NT_STATUS_NOT_FOUND;
415 struct security_descriptor *sd;
418 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
420 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
421 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
423 if (!NT_STATUS_IS_OK(status)) {
427 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
429 info->query_secdesc.out.sd = sd;
436 check the read only bit against any of the write access bits
438 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
440 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
441 (access_mask & (SEC_FILE_WRITE_DATA |
442 SEC_FILE_APPEND_DATA |
444 SEC_FILE_WRITE_ATTRIBUTE |
447 SEC_STD_WRITE_OWNER |
448 SEC_DIR_DELETE_CHILD))) {
455 see if we are a member of the appropriate unix group
457 static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
461 if (getegid() == gid) {
464 ngroups = getgroups(0, NULL);
468 groups = talloc_array(pvfs, gid_t, ngroups);
469 if (groups == NULL) {
472 if (getgroups(ngroups, groups) != ngroups) {
476 for (i=0; i<ngroups; i++) {
477 if (groups[i] == gid) break;
484 default access check function based on unix permissions
485 doing this saves on building a full security descriptor
486 for the common case of access check on files with no
489 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
490 struct ntvfs_request *req,
491 struct pvfs_filename *name,
492 uint32_t *access_mask)
494 uid_t uid = geteuid();
495 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
496 struct security_token *token = req->session_info->security_token;
498 if (pvfs_read_only(pvfs, *access_mask)) {
499 return NT_STATUS_ACCESS_DENIED;
502 if (uid == name->st.st_uid) {
503 max_bits |= SEC_STD_ALL;
504 } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
505 max_bits |= SEC_STD_DELETE;
508 if ((name->st.st_mode & S_IWOTH) ||
509 ((name->st.st_mode & S_IWGRP) &&
510 pvfs_group_member(pvfs, name->st.st_gid))) {
511 max_bits |= SEC_STD_ALL;
514 if (uwrap_enabled()) {
515 /* when running with the uid wrapper, files will be created
516 owned by the ruid, but we may have a different simulated
517 euid. We need to force the permission bits as though the
518 files owner matches the euid */
519 max_bits |= SEC_STD_ALL;
522 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
523 *access_mask |= max_bits;
524 *access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
527 if ((*access_mask & SEC_FLAG_SYSTEM_SECURITY) &&
528 security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
529 max_bits |= SEC_FLAG_SYSTEM_SECURITY;
532 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_RESTORE) &&
533 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
534 max_bits |= ~(SEC_RIGHTS_PRIV_RESTORE);
536 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_BACKUP) &&
537 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
538 max_bits |= ~(SEC_RIGHTS_PRIV_BACKUP);
541 if (*access_mask & ~max_bits) {
542 DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
543 name->full_name, *access_mask, max_bits, *access_mask & ~max_bits));
544 return NT_STATUS_ACCESS_DENIED;
547 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
548 /* on SMB, this bit is always granted, even if not
550 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
558 check the security descriptor on a file, if any
560 *access_mask is modified with the access actually granted
562 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
563 struct ntvfs_request *req,
564 struct pvfs_filename *name,
565 uint32_t *access_mask)
567 struct security_token *token = req->session_info->security_token;
568 struct xattr_NTACL *acl;
570 struct security_descriptor *sd;
572 /* on SMB2 a blank access mask is always denied */
573 if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
575 return NT_STATUS_ACCESS_DENIED;
578 if (pvfs_read_only(pvfs, *access_mask)) {
579 return NT_STATUS_ACCESS_DENIED;
582 acl = talloc(req, struct xattr_NTACL);
584 return NT_STATUS_NO_MEMORY;
587 /* expand the generic access bits to file specific bits */
588 *access_mask = pvfs_translate_mask(*access_mask);
589 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
590 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
593 status = pvfs_acl_load(pvfs, name, -1, acl);
594 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
596 return pvfs_access_check_unix(pvfs, req, name, access_mask);
598 if (!NT_STATUS_IS_OK(status)) {
602 switch (acl->version) {
607 return NT_STATUS_INVALID_ACL;
610 /* check the acl against the required access mask */
611 status = sec_access_check(sd, token, *access_mask, access_mask);
613 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
614 /* on SMB, this bit is always granted, even if not
616 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
626 a simplified interface to access check, designed for calls that
627 do not take or return an access check mask
629 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
630 struct ntvfs_request *req,
631 struct pvfs_filename *name,
632 uint32_t access_needed)
634 if (access_needed == 0) {
637 return pvfs_access_check(pvfs, req, name, &access_needed);
641 access check for creating a new file/directory
643 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
644 struct ntvfs_request *req,
645 struct pvfs_filename *name,
646 uint32_t *access_mask)
648 struct pvfs_filename *parent;
651 status = pvfs_resolve_parent(pvfs, req, name, &parent);
652 if (!NT_STATUS_IS_OK(status)) {
656 status = pvfs_access_check(pvfs, req, parent, access_mask);
657 if (!NT_STATUS_IS_OK(status)) {
661 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
662 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
669 access check for creating a new file/directory - no access mask supplied
671 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
672 struct ntvfs_request *req,
673 struct pvfs_filename *name,
674 uint32_t access_mask)
676 struct pvfs_filename *parent;
679 status = pvfs_resolve_parent(pvfs, req, name, &parent);
680 if (!NT_STATUS_IS_OK(status)) {
684 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
689 determine if an ACE is inheritable
691 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
692 const struct security_ace *ace,
696 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
699 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
703 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
704 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
712 this is the core of ACL inheritance. It copies any inheritable
713 aces from the parent SD to the child SD. Note that the algorithm
714 depends on whether the child is a container or not
716 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
717 struct security_descriptor *parent_sd,
718 struct security_descriptor *sd,
723 for (i=0;i<parent_sd->dacl->num_aces;i++) {
724 struct security_ace ace = parent_sd->dacl->aces[i];
726 const struct dom_sid *creator = NULL, *new_id = NULL;
729 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
733 orig_flags = ace.flags;
735 /* see the RAW-ACLS inheritance test for details on these rules */
739 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
741 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
742 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
744 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
749 /* the CREATOR sids are special when inherited */
750 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
751 creator = pvfs->sid_cache.creator_owner;
752 new_id = sd->owner_sid;
753 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
754 creator = pvfs->sid_cache.creator_group;
755 new_id = sd->group_sid;
757 new_id = &ace.trustee;
760 if (creator && container &&
761 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
762 uint32_t flags = ace.flags;
764 ace.trustee = *new_id;
766 status = security_descriptor_dacl_add(sd, &ace);
767 if (!NT_STATUS_IS_OK(status)) {
771 ace.trustee = *creator;
772 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
773 status = security_descriptor_dacl_add(sd, &ace);
774 } else if (container &&
775 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
776 status = security_descriptor_dacl_add(sd, &ace);
778 ace.trustee = *new_id;
779 status = security_descriptor_dacl_add(sd, &ace);
782 if (!NT_STATUS_IS_OK(status)) {
793 setup an ACL on a new file/directory based on the inherited ACL from
794 the parent. If there is no inherited ACL then we don't set anything,
795 as the default ACL applies anyway
797 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
798 struct ntvfs_request *req,
799 struct pvfs_filename *name,
802 struct xattr_NTACL *acl;
804 struct pvfs_filename *parent;
805 struct security_descriptor *parent_sd, *sd;
807 struct id_mapping *ids;
808 struct composite_context *ctx;
810 /* form the parents path */
811 status = pvfs_resolve_parent(pvfs, req, name, &parent);
812 if (!NT_STATUS_IS_OK(status)) {
816 acl = talloc(req, struct xattr_NTACL);
818 return NT_STATUS_NO_MEMORY;
821 status = pvfs_acl_load(pvfs, parent, -1, acl);
822 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
825 if (!NT_STATUS_IS_OK(status)) {
829 switch (acl->version) {
831 parent_sd = acl->info.sd;
834 return NT_STATUS_INVALID_ACL;
837 if (parent_sd == NULL ||
838 parent_sd->dacl == NULL ||
839 parent_sd->dacl->num_aces == 0) {
840 /* go with the default ACL */
844 /* create the new sd */
845 sd = security_descriptor_initialise(req);
847 return NT_STATUS_NO_MEMORY;
850 ids = talloc_array(sd, struct id_mapping, 2);
851 NT_STATUS_HAVE_NO_MEMORY(ids);
853 ids[0].unixid = talloc(ids, struct unixid);
854 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
855 ids[0].unixid->id = name->st.st_uid;
856 ids[0].unixid->type = ID_TYPE_UID;
858 ids[0].status = NT_STATUS_NONE_MAPPED;
860 ids[1].unixid = talloc(ids, struct unixid);
861 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
862 ids[1].unixid->id = name->st.st_gid;
863 ids[1].unixid->type = ID_TYPE_GID;
865 ids[1].status = NT_STATUS_NONE_MAPPED;
867 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
868 NT_STATUS_HAVE_NO_MEMORY(ctx);
870 status = wbc_xids_to_sids_recv(ctx, &ids);
871 NT_STATUS_NOT_OK_RETURN(status);
873 sd->owner_sid = talloc_steal(sd, ids[0].sid);
874 sd->group_sid = talloc_steal(sd, ids[1].sid);
876 sd->type |= SEC_DESC_DACL_PRESENT;
878 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
880 /* fill in the aces from the parent */
881 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
882 if (!NT_STATUS_IS_OK(status)) {
886 /* if there is nothing to inherit then we fallback to the
888 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
894 status = pvfs_acl_save(pvfs, name, fd, acl);
900 return the maximum allowed access mask
902 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
903 struct ntvfs_request *req,
904 struct pvfs_filename *name,
905 uint32_t *maximal_access)
907 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
908 return pvfs_access_check(pvfs, req, name, maximal_access);