Revert "source4: Use wbc_sids_to_xids"
[Samba.git] / source4 / ntvfs / posix / pvfs_acl.c
blob730ad484ce8165026698ac84c37be745c389acc2
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 "system/passwd.h"
24 #include "auth/auth.h"
25 #include "vfs_posix.h"
26 #include "librpc/gen_ndr/xattr.h"
27 #include "libcli/security/security.h"
28 #include "param/param.h"
29 #include "../lib/util/unix_privs.h"
30 #include "lib/util/samba_modules.h"
32 /* the list of currently registered ACL backends */
33 static struct pvfs_acl_backend {
34 const struct pvfs_acl_ops *ops;
35 } *backends = NULL;
36 static int num_backends;
39 register a pvfs acl backend.
41 The 'name' can be later used by other backends to find the operations
42 structure for this backend.
44 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
46 struct pvfs_acl_ops *new_ops;
48 if (pvfs_acl_backend_byname(ops->name) != NULL) {
49 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
50 return NT_STATUS_OBJECT_NAME_COLLISION;
53 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
54 NT_STATUS_HAVE_NO_MEMORY(backends);
56 new_ops = (struct pvfs_acl_ops *)talloc_memdup(backends, ops, sizeof(*ops));
57 new_ops->name = talloc_strdup(new_ops, ops->name);
59 backends[num_backends].ops = new_ops;
61 num_backends++;
63 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
65 return NT_STATUS_OK;
70 return the operations structure for a named backend
72 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
74 int i;
76 for (i=0;i<num_backends;i++) {
77 if (strcmp(backends[i].ops->name, name) == 0) {
78 return backends[i].ops;
82 return NULL;
85 NTSTATUS pvfs_acl_init(void)
87 static bool initialized = false;
88 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
89 STATIC_pvfs_acl_MODULES_PROTO;
90 init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
91 init_module_fn *shared_init;
93 if (initialized) return NT_STATUS_OK;
94 initialized = true;
96 shared_init = load_samba_modules(NULL, "pvfs_acl");
98 run_init_functions(static_init);
99 run_init_functions(shared_init);
101 talloc_free(shared_init);
103 return NT_STATUS_OK;
108 map a single access_mask from generic to specific bits for files/dirs
110 static uint32_t pvfs_translate_mask(uint32_t access_mask)
112 if (access_mask & SEC_MASK_GENERIC) {
113 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
114 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
115 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
116 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
117 access_mask &= ~SEC_MASK_GENERIC;
119 return access_mask;
124 map any generic access bits in the given acl
125 this relies on the fact that the mappings for files and directories
126 are the same
128 static void pvfs_translate_generic_bits(struct security_acl *acl)
130 unsigned i;
132 if (!acl) return;
134 for (i=0;i<acl->num_aces;i++) {
135 struct security_ace *ace = &acl->aces[i];
136 ace->access_mask = pvfs_translate_mask(ace->access_mask);
142 setup a default ACL for a file
144 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
145 struct ntvfs_request *req,
146 struct pvfs_filename *name, int fd,
147 struct security_descriptor **psd)
149 struct security_descriptor *sd;
150 NTSTATUS status;
151 struct security_ace ace;
152 mode_t mode;
153 struct id_map *ids;
154 struct composite_context *ctx;
156 *psd = security_descriptor_initialise(req);
157 if (*psd == NULL) {
158 return NT_STATUS_NO_MEMORY;
160 sd = *psd;
162 ids = talloc_zero_array(sd, struct id_map, 2);
163 NT_STATUS_HAVE_NO_MEMORY(ids);
165 ids[0].xid.id = name->st.st_uid;
166 ids[0].xid.type = ID_TYPE_UID;
167 ids[0].sid = NULL;
169 ids[1].xid.id = name->st.st_gid;
170 ids[1].xid.type = ID_TYPE_GID;
171 ids[1].sid = NULL;
173 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
174 NT_STATUS_HAVE_NO_MEMORY(ctx);
176 status = wbc_xids_to_sids_recv(ctx, &ids);
177 NT_STATUS_NOT_OK_RETURN(status);
179 sd->owner_sid = talloc_steal(sd, ids[0].sid);
180 sd->group_sid = talloc_steal(sd, ids[1].sid);
182 talloc_free(ids);
183 sd->type |= SEC_DESC_DACL_PRESENT;
185 mode = name->st.st_mode;
188 we provide up to 4 ACEs
189 - Owner
190 - Group
191 - Everyone
192 - Administrator
196 /* setup owner ACE */
197 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
198 ace.flags = 0;
199 ace.trustee = *sd->owner_sid;
200 ace.access_mask = 0;
202 if (mode & S_IRUSR) {
203 if (mode & S_IWUSR) {
204 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
205 } else {
206 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
209 if (mode & S_IWUSR) {
210 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
212 if (ace.access_mask) {
213 security_descriptor_dacl_add(sd, &ace);
217 /* setup group ACE */
218 ace.trustee = *sd->group_sid;
219 ace.access_mask = 0;
220 if (mode & S_IRGRP) {
221 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
223 if (mode & S_IWGRP) {
224 /* note that delete is not granted - this matches posix behaviour */
225 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
227 if (ace.access_mask) {
228 security_descriptor_dacl_add(sd, &ace);
231 /* setup other ACE */
232 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
233 ace.access_mask = 0;
234 if (mode & S_IROTH) {
235 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
237 if (mode & S_IWOTH) {
238 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
240 if (ace.access_mask) {
241 security_descriptor_dacl_add(sd, &ace);
244 /* setup system ACE */
245 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
246 ace.access_mask = SEC_RIGHTS_FILE_ALL;
247 security_descriptor_dacl_add(sd, &ace);
249 return NT_STATUS_OK;
254 omit any security_descriptor elements not specified in the given
255 secinfo flags
257 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
259 if (!(secinfo_flags & SECINFO_OWNER)) {
260 sd->owner_sid = NULL;
262 if (!(secinfo_flags & SECINFO_GROUP)) {
263 sd->group_sid = NULL;
265 if (!(secinfo_flags & SECINFO_DACL)) {
266 sd->dacl = NULL;
268 if (!(secinfo_flags & SECINFO_SACL)) {
269 sd->sacl = NULL;
274 answer a setfileinfo for an ACL
276 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
277 struct ntvfs_request *req,
278 struct pvfs_filename *name, int fd,
279 uint32_t access_mask,
280 union smb_setfileinfo *info)
282 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
283 struct security_descriptor *new_sd, *sd, orig_sd;
284 NTSTATUS status = NT_STATUS_NOT_FOUND;
285 uid_t old_uid = -1;
286 gid_t old_gid = -1;
287 uid_t new_uid = -1;
288 gid_t new_gid = -1;
289 struct id_map *ids;
290 struct composite_context *ctx;
292 if (pvfs->acl_ops != NULL) {
293 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
295 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
296 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
298 if (!NT_STATUS_IS_OK(status)) {
299 return status;
302 ids = talloc(req, struct id_map);
303 NT_STATUS_HAVE_NO_MEMORY(ids);
304 ZERO_STRUCT(ids->xid);
305 ids->sid = NULL;
306 ids->status = ID_UNKNOWN;
308 new_sd = info->set_secdesc.in.sd;
309 orig_sd = *sd;
311 old_uid = name->st.st_uid;
312 old_gid = name->st.st_gid;
314 /* only set the elements that have been specified */
315 if (secinfo_flags & SECINFO_OWNER) {
316 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
317 return NT_STATUS_ACCESS_DENIED;
319 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
320 ids->sid = new_sd->owner_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->xid.type == ID_TYPE_BOTH ||
327 ids->xid.type == ID_TYPE_UID) {
328 new_uid = ids->xid.id;
331 sd->owner_sid = new_sd->owner_sid;
334 if (secinfo_flags & SECINFO_GROUP) {
335 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
336 return NT_STATUS_ACCESS_DENIED;
338 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
339 ids->sid = new_sd->group_sid;
340 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
341 NT_STATUS_HAVE_NO_MEMORY(ctx);
342 status = wbc_sids_to_xids_recv(ctx, &ids);
343 NT_STATUS_NOT_OK_RETURN(status);
345 if (ids->xid.type == ID_TYPE_BOTH ||
346 ids->xid.type == ID_TYPE_GID) {
347 new_gid = ids->xid.id;
351 sd->group_sid = new_sd->group_sid;
354 if (secinfo_flags & SECINFO_DACL) {
355 if (!(access_mask & SEC_STD_WRITE_DAC)) {
356 return NT_STATUS_ACCESS_DENIED;
358 sd->dacl = new_sd->dacl;
359 pvfs_translate_generic_bits(sd->dacl);
360 sd->type |= SEC_DESC_DACL_PRESENT;
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);
369 sd->type |= SEC_DESC_SACL_PRESENT;
372 if (secinfo_flags & SECINFO_PROTECTED_DACL) {
373 if (new_sd->type & SEC_DESC_DACL_PROTECTED) {
374 sd->type |= SEC_DESC_DACL_PROTECTED;
375 } else {
376 sd->type &= ~SEC_DESC_DACL_PROTECTED;
380 if (secinfo_flags & SECINFO_PROTECTED_SACL) {
381 if (new_sd->type & SEC_DESC_SACL_PROTECTED) {
382 sd->type |= SEC_DESC_SACL_PROTECTED;
383 } else {
384 sd->type &= ~SEC_DESC_SACL_PROTECTED;
388 if (new_uid == old_uid) {
389 new_uid = -1;
392 if (new_gid == old_gid) {
393 new_gid = -1;
396 /* if there's something to change try it */
397 if (new_uid != -1 || new_gid != -1) {
398 int ret;
399 if (fd == -1) {
400 ret = chown(name->full_name, new_uid, new_gid);
401 } else {
402 ret = fchown(fd, new_uid, new_gid);
404 if (errno == EPERM) {
405 if (uwrap_enabled()) {
406 ret = 0;
407 } else {
408 /* try again as root if we have SEC_PRIV_RESTORE or
409 SEC_PRIV_TAKE_OWNERSHIP */
410 if (security_token_has_privilege(req->session_info->security_token,
411 SEC_PRIV_RESTORE) ||
412 security_token_has_privilege(req->session_info->security_token,
413 SEC_PRIV_TAKE_OWNERSHIP)) {
414 void *privs;
415 privs = root_privileges();
416 if (fd == -1) {
417 ret = chown(name->full_name, new_uid, new_gid);
418 } else {
419 ret = fchown(fd, new_uid, new_gid);
421 talloc_free(privs);
425 if (ret == -1) {
426 return pvfs_map_errno(pvfs, errno);
430 /* we avoid saving if the sd is the same. This means when clients
431 copy files and end up copying the default sd that we don't
432 needlessly use xattrs */
433 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
434 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
437 return status;
442 answer a fileinfo query for the ACL
444 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
445 struct ntvfs_request *req,
446 struct pvfs_filename *name, int fd,
447 union smb_fileinfo *info)
449 NTSTATUS status = NT_STATUS_NOT_FOUND;
450 struct security_descriptor *sd;
452 if (pvfs->acl_ops) {
453 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
455 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
456 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
458 if (!NT_STATUS_IS_OK(status)) {
459 return status;
462 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
464 info->query_secdesc.out.sd = sd;
466 return NT_STATUS_OK;
471 check the read only bit against any of the write access bits
473 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
475 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
476 (access_mask & (SEC_FILE_WRITE_DATA |
477 SEC_FILE_APPEND_DATA |
478 SEC_FILE_WRITE_EA |
479 SEC_FILE_WRITE_ATTRIBUTE |
480 SEC_STD_DELETE |
481 SEC_STD_WRITE_DAC |
482 SEC_STD_WRITE_OWNER |
483 SEC_DIR_DELETE_CHILD))) {
484 return true;
486 return false;
490 see if we are a member of the appropriate unix group
492 static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
494 int i, ngroups;
495 gid_t *groups;
496 if (getegid() == gid) {
497 return true;
499 ngroups = getgroups(0, NULL);
500 if (ngroups <= 0) {
501 return false;
503 groups = talloc_array(pvfs, gid_t, ngroups);
504 if (groups == NULL) {
505 return false;
507 if (getgroups(ngroups, groups) != ngroups) {
508 talloc_free(groups);
509 return false;
511 for (i=0; i<ngroups; i++) {
512 if (groups[i] == gid) break;
514 talloc_free(groups);
515 return i < ngroups;
519 default access check function based on unix permissions
520 doing this saves on building a full security descriptor
521 for the common case of access check on files with no
522 specific NT ACL
524 If name is NULL then treat as a new file creation
526 static NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
527 struct ntvfs_request *req,
528 struct pvfs_filename *name,
529 uint32_t *access_mask)
531 uid_t uid = geteuid();
532 uint32_t max_bits = 0;
533 struct security_token *token = req->session_info->security_token;
535 if (pvfs_read_only(pvfs, *access_mask)) {
536 return NT_STATUS_ACCESS_DENIED;
539 if (name == NULL) {
540 max_bits |= SEC_RIGHTS_FILE_ALL | SEC_STD_ALL;
541 } else if (uid == name->st.st_uid || uwrap_enabled()) {
542 /* use the IxUSR bits */
543 if ((name->st.st_mode & S_IWUSR)) {
544 max_bits |= SEC_RIGHTS_FILE_ALL | SEC_STD_ALL;
545 } else if ((name->st.st_mode & (S_IRUSR | S_IXUSR))) {
546 max_bits |= SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_EXECUTE | SEC_STD_ALL;
548 } else if (pvfs_group_member(pvfs, name->st.st_gid)) {
549 /* use the IxGRP bits */
550 if ((name->st.st_mode & S_IWGRP)) {
551 max_bits |= SEC_RIGHTS_FILE_ALL | SEC_STD_ALL;
552 } else if ((name->st.st_mode & (S_IRGRP | S_IXGRP))) {
553 max_bits |= SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_EXECUTE | SEC_STD_ALL;
555 } else {
556 /* use the IxOTH bits */
557 if ((name->st.st_mode & S_IWOTH)) {
558 max_bits |= SEC_RIGHTS_FILE_ALL | SEC_STD_ALL;
559 } else if ((name->st.st_mode & (S_IROTH | S_IXOTH))) {
560 max_bits |= SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_EXECUTE | SEC_STD_ALL;
564 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
565 *access_mask |= max_bits;
566 *access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
569 if ((*access_mask & SEC_FLAG_SYSTEM_SECURITY) &&
570 security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
571 max_bits |= SEC_FLAG_SYSTEM_SECURITY;
574 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_RESTORE) &&
575 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
576 max_bits |= ~(SEC_RIGHTS_PRIV_RESTORE);
578 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_BACKUP) &&
579 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
580 max_bits |= ~(SEC_RIGHTS_PRIV_BACKUP);
583 if (*access_mask & ~max_bits) {
584 DEBUG(5,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
585 name?name->full_name:"(new file)", *access_mask, max_bits, *access_mask & ~max_bits));
586 return NT_STATUS_ACCESS_DENIED;
589 if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) {
590 /* on SMB, this bit is always granted, even if not
591 asked for */
592 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
595 return NT_STATUS_OK;
600 check the security descriptor on a file, if any
602 *access_mask is modified with the access actually granted
604 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
605 struct ntvfs_request *req,
606 struct pvfs_filename *name,
607 uint32_t *access_mask)
609 struct security_token *token = req->session_info->security_token;
610 struct xattr_NTACL *acl;
611 NTSTATUS status;
612 struct security_descriptor *sd;
613 bool allow_delete = false;
615 /* on SMB2 a blank access mask is always denied */
616 if (pvfs->ntvfs->ctx->protocol >= PROTOCOL_SMB2_02 &&
617 *access_mask == 0) {
618 return NT_STATUS_ACCESS_DENIED;
621 if (pvfs_read_only(pvfs, *access_mask)) {
622 return NT_STATUS_ACCESS_DENIED;
625 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED ||
626 *access_mask & SEC_STD_DELETE) {
627 status = pvfs_access_check_parent(pvfs, req,
628 name, SEC_DIR_DELETE_CHILD);
629 if (NT_STATUS_IS_OK(status)) {
630 allow_delete = true;
631 *access_mask &= ~SEC_STD_DELETE;
635 acl = talloc(req, struct xattr_NTACL);
636 if (acl == NULL) {
637 return NT_STATUS_NO_MEMORY;
640 /* expand the generic access bits to file specific bits */
641 *access_mask = pvfs_translate_mask(*access_mask);
642 if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) {
643 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
646 status = pvfs_acl_load(pvfs, name, -1, acl);
647 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
648 talloc_free(acl);
649 status = pvfs_access_check_unix(pvfs, req, name, access_mask);
650 goto done;
652 if (!NT_STATUS_IS_OK(status)) {
653 return status;
656 switch (acl->version) {
657 case 1:
658 sd = acl->info.sd;
659 break;
660 default:
661 return NT_STATUS_INVALID_ACL;
664 /* check the acl against the required access mask */
665 status = se_access_check(sd, token, *access_mask, access_mask);
666 talloc_free(acl);
668 /* if we used a NT acl, then allow access override if the
669 share allows for posix permission override
671 if (NT_STATUS_IS_OK(status)) {
672 name->allow_override = (pvfs->flags & PVFS_FLAG_PERM_OVERRIDE) != 0;
675 done:
676 if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) {
677 /* on SMB, this bit is always granted, even if not
678 asked for */
679 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
682 if (allow_delete) {
683 *access_mask |= SEC_STD_DELETE;
686 return status;
691 a simplified interface to access check, designed for calls that
692 do not take or return an access check mask
694 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
695 struct ntvfs_request *req,
696 struct pvfs_filename *name,
697 uint32_t access_needed)
699 if (access_needed == 0) {
700 return NT_STATUS_OK;
702 return pvfs_access_check(pvfs, req, name, &access_needed);
706 access check for creating a new file/directory
708 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
709 struct ntvfs_request *req,
710 struct pvfs_filename *name,
711 uint32_t *access_mask,
712 bool container,
713 struct security_descriptor **sd)
715 struct pvfs_filename *parent;
716 NTSTATUS status;
717 uint32_t parent_mask;
718 bool allow_delete = false;
720 if (pvfs_read_only(pvfs, *access_mask)) {
721 return NT_STATUS_ACCESS_DENIED;
724 status = pvfs_resolve_parent(pvfs, req, name, &parent);
725 NT_STATUS_NOT_OK_RETURN(status);
727 if (container) {
728 parent_mask = SEC_DIR_ADD_SUBDIR;
729 } else {
730 parent_mask = SEC_DIR_ADD_FILE;
732 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED ||
733 *access_mask & SEC_STD_DELETE) {
734 parent_mask |= SEC_DIR_DELETE_CHILD;
737 status = pvfs_access_check(pvfs, req, parent, &parent_mask);
738 if (NT_STATUS_IS_OK(status)) {
739 if (parent_mask & SEC_DIR_DELETE_CHILD) {
740 allow_delete = true;
742 } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
744 * on ACCESS_DENIED we get the rejected bits
745 * remove the non critical SEC_DIR_DELETE_CHILD
746 * and check if something else was rejected.
748 parent_mask &= ~SEC_DIR_DELETE_CHILD;
749 if (parent_mask != 0) {
750 return NT_STATUS_ACCESS_DENIED;
752 status = NT_STATUS_OK;
753 } else {
754 return status;
757 if (*sd == NULL) {
758 status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, sd);
761 talloc_free(parent);
762 if (!NT_STATUS_IS_OK(status)) {
763 return status;
766 /* expand the generic access bits to file specific bits */
767 *access_mask = pvfs_translate_mask(*access_mask);
769 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
770 *access_mask |= SEC_RIGHTS_FILE_ALL;
771 *access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
774 if (pvfs->ntvfs->ctx->protocol < PROTOCOL_SMB2_02) {
775 /* on SMB, this bit is always granted, even if not
776 asked for */
777 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
780 if (allow_delete) {
781 *access_mask |= SEC_STD_DELETE;
784 return NT_STATUS_OK;
788 access check for creating a new file/directory - no access mask supplied
790 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
791 struct ntvfs_request *req,
792 struct pvfs_filename *name,
793 uint32_t access_mask)
795 struct pvfs_filename *parent;
796 NTSTATUS status;
798 status = pvfs_resolve_parent(pvfs, req, name, &parent);
799 if (!NT_STATUS_IS_OK(status)) {
800 return status;
803 status = pvfs_access_check_simple(pvfs, req, parent, access_mask);
804 if (NT_STATUS_IS_OK(status) && parent->allow_override) {
805 name->allow_override = true;
807 return status;
812 determine if an ACE is inheritable
814 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
815 const struct security_ace *ace,
816 bool container)
818 if (!container) {
819 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
822 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
823 return true;
826 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
827 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
828 return true;
831 return false;
835 this is the core of ACL inheritance. It copies any inheritable
836 aces from the parent SD to the child SD. Note that the algorithm
837 depends on whether the child is a container or not
839 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
840 struct security_descriptor *parent_sd,
841 struct security_descriptor *sd,
842 bool container)
844 int i;
846 for (i=0;i<parent_sd->dacl->num_aces;i++) {
847 struct security_ace ace = parent_sd->dacl->aces[i];
848 NTSTATUS status;
849 const struct dom_sid *creator = NULL, *new_id = NULL;
850 uint32_t orig_flags;
852 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
853 continue;
856 orig_flags = ace.flags;
858 /* see the RAW-ACLS inheritance test for details on these rules */
859 if (!container) {
860 ace.flags = 0;
861 } else {
862 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
864 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
865 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
867 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
868 ace.flags = 0;
872 /* the CREATOR sids are special when inherited */
873 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
874 creator = pvfs->sid_cache.creator_owner;
875 new_id = sd->owner_sid;
876 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
877 creator = pvfs->sid_cache.creator_group;
878 new_id = sd->group_sid;
879 } else {
880 new_id = &ace.trustee;
883 if (creator && container &&
884 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
885 uint32_t flags = ace.flags;
887 ace.trustee = *new_id;
888 ace.flags = 0;
889 status = security_descriptor_dacl_add(sd, &ace);
890 if (!NT_STATUS_IS_OK(status)) {
891 return status;
894 ace.trustee = *creator;
895 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
896 status = security_descriptor_dacl_add(sd, &ace);
897 } else if (container &&
898 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
899 status = security_descriptor_dacl_add(sd, &ace);
900 } else {
901 ace.trustee = *new_id;
902 status = security_descriptor_dacl_add(sd, &ace);
905 if (!NT_STATUS_IS_OK(status)) {
906 return status;
910 return NT_STATUS_OK;
916 calculate the ACL on a new file/directory based on the inherited ACL
917 from the parent. If there is no inherited ACL then return a NULL
918 ACL, which means the default ACL should be used
920 NTSTATUS pvfs_acl_inherited_sd(struct pvfs_state *pvfs,
921 TALLOC_CTX *mem_ctx,
922 struct ntvfs_request *req,
923 struct pvfs_filename *parent,
924 bool container,
925 struct security_descriptor **ret_sd)
927 struct xattr_NTACL *acl;
928 NTSTATUS status;
929 struct security_descriptor *parent_sd, *sd;
930 struct id_map *ids;
931 struct composite_context *ctx;
932 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
934 *ret_sd = NULL;
936 acl = talloc(req, struct xattr_NTACL);
937 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(acl, tmp_ctx);
939 status = pvfs_acl_load(pvfs, parent, -1, acl);
940 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
941 talloc_free(tmp_ctx);
942 return NT_STATUS_OK;
944 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
946 switch (acl->version) {
947 case 1:
948 parent_sd = acl->info.sd;
949 break;
950 default:
951 talloc_free(tmp_ctx);
952 return NT_STATUS_INVALID_ACL;
955 if (parent_sd == NULL ||
956 parent_sd->dacl == NULL ||
957 parent_sd->dacl->num_aces == 0) {
958 /* go with the default ACL */
959 talloc_free(tmp_ctx);
960 return NT_STATUS_OK;
963 /* create the new sd */
964 sd = security_descriptor_initialise(req);
965 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sd, tmp_ctx);
967 ids = talloc_array(sd, struct id_map, 2);
968 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ids, tmp_ctx);
970 ids[0].xid.id = geteuid();
971 ids[0].xid.type = ID_TYPE_UID;
972 ids[0].sid = NULL;
973 ids[0].status = ID_UNKNOWN;
975 ids[1].xid.id = getegid();
976 ids[1].xid.type = ID_TYPE_GID;
977 ids[1].sid = NULL;
978 ids[1].status = ID_UNKNOWN;
980 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
981 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ctx, tmp_ctx);
983 status = wbc_xids_to_sids_recv(ctx, &ids);
984 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
986 sd->owner_sid = talloc_steal(sd, ids[0].sid);
987 sd->group_sid = talloc_steal(sd, ids[1].sid);
989 sd->type |= SEC_DESC_DACL_PRESENT;
991 /* fill in the aces from the parent */
992 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
993 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
995 /* if there is nothing to inherit then we fallback to the
996 default acl */
997 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
998 talloc_free(tmp_ctx);
999 return NT_STATUS_OK;
1002 *ret_sd = talloc_steal(mem_ctx, sd);
1004 talloc_free(tmp_ctx);
1005 return NT_STATUS_OK;
1010 setup an ACL on a new file/directory based on the inherited ACL from
1011 the parent. If there is no inherited ACL then we don't set anything,
1012 as the default ACL applies anyway
1014 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
1015 struct ntvfs_request *req,
1016 struct pvfs_filename *name,
1017 int fd)
1019 struct xattr_NTACL acl;
1020 NTSTATUS status;
1021 struct security_descriptor *sd;
1022 struct pvfs_filename *parent;
1023 bool container;
1025 /* form the parents path */
1026 status = pvfs_resolve_parent(pvfs, req, name, &parent);
1027 NT_STATUS_NOT_OK_RETURN(status);
1029 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
1031 status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, &sd);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 talloc_free(parent);
1034 return status;
1037 if (sd == NULL) {
1038 return NT_STATUS_OK;
1041 acl.version = 1;
1042 acl.info.sd = sd;
1044 status = pvfs_acl_save(pvfs, name, fd, &acl);
1045 talloc_free(sd);
1046 talloc_free(parent);
1048 return status;
1052 return the maximum allowed access mask
1054 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
1055 struct ntvfs_request *req,
1056 struct pvfs_filename *name,
1057 uint32_t *maximal_access)
1059 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
1060 return pvfs_access_check(pvfs, req, name, maximal_access);