s3:nmbd: add _NMBD_NMBD_H_ guard to nmbd.h
[Samba/gebeck_regimport.git] / source4 / ntvfs / posix / pvfs_acl.c
blob67b544d4dee550d2961de2ca97009d32c81fe1f6
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"
28 #include "../lib/util/unix_privs.h"
30 #if defined(UID_WRAPPER)
31 #if !defined(UID_WRAPPER_REPLACE) && !defined(UID_WRAPPER_NOT_REPLACE)
32 #define UID_WRAPPER_REPLACE
33 #include "../uid_wrapper/uid_wrapper.h"
34 #endif
35 #else
36 #define uwrap_enabled() 0
37 #endif
39 /* the list of currently registered ACL backends */
40 static struct pvfs_acl_backend {
41 const struct pvfs_acl_ops *ops;
42 } *backends = NULL;
43 static int num_backends;
46 register a pvfs acl backend.
48 The 'name' can be later used by other backends to find the operations
49 structure for this backend.
51 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
53 struct pvfs_acl_ops *new_ops;
55 if (pvfs_acl_backend_byname(ops->name) != NULL) {
56 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
57 return NT_STATUS_OBJECT_NAME_COLLISION;
60 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
61 NT_STATUS_HAVE_NO_MEMORY(backends);
63 new_ops = (struct pvfs_acl_ops *)talloc_memdup(backends, ops, sizeof(*ops));
64 new_ops->name = talloc_strdup(new_ops, ops->name);
66 backends[num_backends].ops = new_ops;
68 num_backends++;
70 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
72 return NT_STATUS_OK;
77 return the operations structure for a named backend
79 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
81 int i;
83 for (i=0;i<num_backends;i++) {
84 if (strcmp(backends[i].ops->name, name) == 0) {
85 return backends[i].ops;
89 return NULL;
92 NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
94 static bool initialized = false;
95 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
96 STATIC_pvfs_acl_MODULES_PROTO;
97 init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
98 init_module_fn *shared_init;
100 if (initialized) return NT_STATUS_OK;
101 initialized = true;
103 shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
105 run_init_functions(static_init);
106 run_init_functions(shared_init);
108 talloc_free(shared_init);
110 return NT_STATUS_OK;
115 map a single access_mask from generic to specific bits for files/dirs
117 static uint32_t pvfs_translate_mask(uint32_t access_mask)
119 if (access_mask & SEC_MASK_GENERIC) {
120 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
121 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
122 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
123 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
124 access_mask &= ~SEC_MASK_GENERIC;
126 return access_mask;
131 map any generic access bits in the given acl
132 this relies on the fact that the mappings for files and directories
133 are the same
135 static void pvfs_translate_generic_bits(struct security_acl *acl)
137 unsigned i;
139 if (!acl) return;
141 for (i=0;i<acl->num_aces;i++) {
142 struct security_ace *ace = &acl->aces[i];
143 ace->access_mask = pvfs_translate_mask(ace->access_mask);
149 setup a default ACL for a file
151 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
152 struct ntvfs_request *req,
153 struct pvfs_filename *name, int fd,
154 struct security_descriptor **psd)
156 struct security_descriptor *sd;
157 NTSTATUS status;
158 struct security_ace ace;
159 mode_t mode;
160 struct id_map *ids;
161 struct composite_context *ctx;
163 *psd = security_descriptor_initialise(req);
164 if (*psd == NULL) {
165 return NT_STATUS_NO_MEMORY;
167 sd = *psd;
169 ids = talloc_zero_array(sd, struct id_map, 2);
170 NT_STATUS_HAVE_NO_MEMORY(ids);
172 ids[0].xid.id = name->st.st_uid;
173 ids[0].xid.type = ID_TYPE_UID;
174 ids[0].sid = NULL;
176 ids[1].xid.id = name->st.st_gid;
177 ids[1].xid.type = ID_TYPE_GID;
178 ids[1].sid = NULL;
180 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
181 NT_STATUS_HAVE_NO_MEMORY(ctx);
183 status = wbc_xids_to_sids_recv(ctx, &ids);
184 NT_STATUS_NOT_OK_RETURN(status);
186 sd->owner_sid = talloc_steal(sd, ids[0].sid);
187 sd->group_sid = talloc_steal(sd, ids[1].sid);
189 talloc_free(ids);
190 sd->type |= SEC_DESC_DACL_PRESENT;
192 mode = name->st.st_mode;
195 we provide up to 4 ACEs
196 - Owner
197 - Group
198 - Everyone
199 - Administrator
203 /* setup owner ACE */
204 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
205 ace.flags = 0;
206 ace.trustee = *sd->owner_sid;
207 ace.access_mask = 0;
209 if (mode & S_IRUSR) {
210 if (mode & S_IWUSR) {
211 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
212 } else {
213 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
216 if (mode & S_IWUSR) {
217 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
219 if (ace.access_mask) {
220 security_descriptor_dacl_add(sd, &ace);
224 /* setup group ACE */
225 ace.trustee = *sd->group_sid;
226 ace.access_mask = 0;
227 if (mode & S_IRGRP) {
228 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
230 if (mode & S_IWGRP) {
231 /* note that delete is not granted - this matches posix behaviour */
232 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
234 if (ace.access_mask) {
235 security_descriptor_dacl_add(sd, &ace);
238 /* setup other ACE */
239 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
240 ace.access_mask = 0;
241 if (mode & S_IROTH) {
242 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
244 if (mode & S_IWOTH) {
245 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
247 if (ace.access_mask) {
248 security_descriptor_dacl_add(sd, &ace);
251 /* setup system ACE */
252 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
253 ace.access_mask = SEC_RIGHTS_FILE_ALL;
254 security_descriptor_dacl_add(sd, &ace);
256 return NT_STATUS_OK;
261 omit any security_descriptor elements not specified in the given
262 secinfo flags
264 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
266 if (!(secinfo_flags & SECINFO_OWNER)) {
267 sd->owner_sid = NULL;
269 if (!(secinfo_flags & SECINFO_GROUP)) {
270 sd->group_sid = NULL;
272 if (!(secinfo_flags & SECINFO_DACL)) {
273 sd->dacl = NULL;
275 if (!(secinfo_flags & SECINFO_SACL)) {
276 sd->sacl = NULL;
281 answer a setfileinfo for an ACL
283 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
284 struct ntvfs_request *req,
285 struct pvfs_filename *name, int fd,
286 uint32_t access_mask,
287 union smb_setfileinfo *info)
289 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
290 struct security_descriptor *new_sd, *sd, orig_sd;
291 NTSTATUS status = NT_STATUS_NOT_FOUND;
292 uid_t old_uid = -1;
293 gid_t old_gid = -1;
294 uid_t new_uid = -1;
295 gid_t new_gid = -1;
296 struct id_map *ids;
297 struct composite_context *ctx;
299 if (pvfs->acl_ops != NULL) {
300 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
302 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
303 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
305 if (!NT_STATUS_IS_OK(status)) {
306 return status;
309 ids = talloc(req, struct id_map);
310 NT_STATUS_HAVE_NO_MEMORY(ids);
311 ZERO_STRUCT(ids->xid);
312 ids->sid = NULL;
313 ids->status = ID_UNKNOWN;
315 new_sd = info->set_secdesc.in.sd;
316 orig_sd = *sd;
318 old_uid = name->st.st_uid;
319 old_gid = name->st.st_gid;
321 /* only set the elements that have been specified */
322 if (secinfo_flags & SECINFO_OWNER) {
323 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
324 return NT_STATUS_ACCESS_DENIED;
326 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
327 ids->sid = new_sd->owner_sid;
328 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
329 NT_STATUS_HAVE_NO_MEMORY(ctx);
330 status = wbc_sids_to_xids_recv(ctx, &ids);
331 NT_STATUS_NOT_OK_RETURN(status);
333 if (ids->xid.type == ID_TYPE_BOTH ||
334 ids->xid.type == ID_TYPE_UID) {
335 new_uid = ids->xid.id;
338 sd->owner_sid = new_sd->owner_sid;
340 if (secinfo_flags & SECINFO_GROUP) {
341 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
342 return NT_STATUS_ACCESS_DENIED;
344 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
345 ids->sid = new_sd->group_sid;
346 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
347 NT_STATUS_HAVE_NO_MEMORY(ctx);
348 status = wbc_sids_to_xids_recv(ctx, &ids);
349 NT_STATUS_NOT_OK_RETURN(status);
351 if (ids->xid.type == ID_TYPE_BOTH ||
352 ids->xid.type == ID_TYPE_GID) {
353 new_gid = ids->xid.id;
357 sd->group_sid = new_sd->group_sid;
359 if (secinfo_flags & SECINFO_DACL) {
360 if (!(access_mask & SEC_STD_WRITE_DAC)) {
361 return NT_STATUS_ACCESS_DENIED;
363 sd->dacl = new_sd->dacl;
364 pvfs_translate_generic_bits(sd->dacl);
366 if (secinfo_flags & SECINFO_SACL) {
367 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
368 return NT_STATUS_ACCESS_DENIED;
370 sd->sacl = new_sd->sacl;
371 pvfs_translate_generic_bits(sd->sacl);
374 if (new_uid == old_uid) {
375 new_uid = -1;
378 if (new_gid == old_gid) {
379 new_gid = -1;
382 /* if there's something to change try it */
383 if (new_uid != -1 || new_gid != -1) {
384 int ret;
385 if (fd == -1) {
386 ret = chown(name->full_name, new_uid, new_gid);
387 } else {
388 ret = fchown(fd, new_uid, new_gid);
390 if (errno == EPERM) {
391 if (uwrap_enabled()) {
392 ret = 0;
393 } else {
394 /* try again as root if we have SEC_PRIV_RESTORE or
395 SEC_PRIV_TAKE_OWNERSHIP */
396 if (security_token_has_privilege(req->session_info->security_token,
397 SEC_PRIV_RESTORE) ||
398 security_token_has_privilege(req->session_info->security_token,
399 SEC_PRIV_TAKE_OWNERSHIP)) {
400 void *privs;
401 privs = root_privileges();
402 if (fd == -1) {
403 ret = chown(name->full_name, new_uid, new_gid);
404 } else {
405 ret = fchown(fd, new_uid, new_gid);
407 talloc_free(privs);
411 if (ret == -1) {
412 return pvfs_map_errno(pvfs, errno);
416 /* we avoid saving if the sd is the same. This means when clients
417 copy files and end up copying the default sd that we don't
418 needlessly use xattrs */
419 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
420 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
423 return status;
428 answer a fileinfo query for the ACL
430 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
431 struct ntvfs_request *req,
432 struct pvfs_filename *name, int fd,
433 union smb_fileinfo *info)
435 NTSTATUS status = NT_STATUS_NOT_FOUND;
436 struct security_descriptor *sd;
438 if (pvfs->acl_ops) {
439 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
441 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
442 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
444 if (!NT_STATUS_IS_OK(status)) {
445 return status;
448 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
450 info->query_secdesc.out.sd = sd;
452 return NT_STATUS_OK;
457 check the read only bit against any of the write access bits
459 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
461 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
462 (access_mask & (SEC_FILE_WRITE_DATA |
463 SEC_FILE_APPEND_DATA |
464 SEC_FILE_WRITE_EA |
465 SEC_FILE_WRITE_ATTRIBUTE |
466 SEC_STD_DELETE |
467 SEC_STD_WRITE_DAC |
468 SEC_STD_WRITE_OWNER |
469 SEC_DIR_DELETE_CHILD))) {
470 return true;
472 return false;
476 see if we are a member of the appropriate unix group
478 static bool pvfs_group_member(struct pvfs_state *pvfs, gid_t gid)
480 int i, ngroups;
481 gid_t *groups;
482 if (getegid() == gid) {
483 return true;
485 ngroups = getgroups(0, NULL);
486 if (ngroups == 0) {
487 return false;
489 groups = talloc_array(pvfs, gid_t, ngroups);
490 if (groups == NULL) {
491 return false;
493 if (getgroups(ngroups, groups) != ngroups) {
494 talloc_free(groups);
495 return false;
497 for (i=0; i<ngroups; i++) {
498 if (groups[i] == gid) break;
500 talloc_free(groups);
501 return i < ngroups;
505 default access check function based on unix permissions
506 doing this saves on building a full security descriptor
507 for the common case of access check on files with no
508 specific NT ACL
510 If name is NULL then treat as a new file creation
512 static NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
513 struct ntvfs_request *req,
514 struct pvfs_filename *name,
515 uint32_t *access_mask)
517 uid_t uid = geteuid();
518 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
519 struct security_token *token = req->session_info->security_token;
521 if (pvfs_read_only(pvfs, *access_mask)) {
522 return NT_STATUS_ACCESS_DENIED;
525 if (name == NULL || uid == name->st.st_uid) {
526 max_bits |= SEC_STD_ALL;
527 } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
528 max_bits |= SEC_STD_DELETE;
531 if (name == NULL ||
532 (name->st.st_mode & S_IWOTH) ||
533 ((name->st.st_mode & S_IWGRP) &&
534 pvfs_group_member(pvfs, name->st.st_gid))) {
535 max_bits |= SEC_STD_ALL;
538 if (uwrap_enabled()) {
539 /* when running with the uid wrapper, files will be created
540 owned by the ruid, but we may have a different simulated
541 euid. We need to force the permission bits as though the
542 files owner matches the euid */
543 max_bits |= SEC_STD_ALL;
546 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
547 *access_mask |= max_bits;
548 *access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
551 if ((*access_mask & SEC_FLAG_SYSTEM_SECURITY) &&
552 security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
553 max_bits |= SEC_FLAG_SYSTEM_SECURITY;
556 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_RESTORE) &&
557 security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
558 max_bits |= ~(SEC_RIGHTS_PRIV_RESTORE);
560 if (((*access_mask & ~max_bits) & SEC_RIGHTS_PRIV_BACKUP) &&
561 security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
562 max_bits |= ~(SEC_RIGHTS_PRIV_BACKUP);
565 if (*access_mask & ~max_bits) {
566 DEBUG(0,(__location__ " denied access to '%s' - wanted 0x%08x but got 0x%08x (missing 0x%08x)\n",
567 name?name->full_name:"(new file)", *access_mask, max_bits, *access_mask & ~max_bits));
568 return NT_STATUS_ACCESS_DENIED;
571 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
572 /* on SMB, this bit is always granted, even if not
573 asked for */
574 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
577 return NT_STATUS_OK;
582 check the security descriptor on a file, if any
584 *access_mask is modified with the access actually granted
586 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
587 struct ntvfs_request *req,
588 struct pvfs_filename *name,
589 uint32_t *access_mask)
591 struct security_token *token = req->session_info->security_token;
592 struct xattr_NTACL *acl;
593 NTSTATUS status;
594 struct security_descriptor *sd;
595 bool allow_delete = false;
597 /* on SMB2 a blank access mask is always denied */
598 if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
599 *access_mask == 0) {
600 return NT_STATUS_ACCESS_DENIED;
603 if (pvfs_read_only(pvfs, *access_mask)) {
604 return NT_STATUS_ACCESS_DENIED;
607 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED ||
608 *access_mask & SEC_STD_DELETE) {
609 status = pvfs_access_check_parent(pvfs, req,
610 name, SEC_DIR_DELETE_CHILD);
611 if (NT_STATUS_IS_OK(status)) {
612 allow_delete = true;
613 *access_mask &= ~SEC_STD_DELETE;
617 acl = talloc(req, struct xattr_NTACL);
618 if (acl == NULL) {
619 return NT_STATUS_NO_MEMORY;
622 /* expand the generic access bits to file specific bits */
623 *access_mask = pvfs_translate_mask(*access_mask);
624 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
625 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
628 status = pvfs_acl_load(pvfs, name, -1, acl);
629 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
630 talloc_free(acl);
631 status = pvfs_access_check_unix(pvfs, req, name, access_mask);
632 goto done;
634 if (!NT_STATUS_IS_OK(status)) {
635 return status;
638 switch (acl->version) {
639 case 1:
640 sd = acl->info.sd;
641 break;
642 default:
643 return NT_STATUS_INVALID_ACL;
646 /* check the acl against the required access mask */
647 status = se_access_check(sd, token, *access_mask, access_mask);
648 talloc_free(acl);
649 done:
650 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
651 /* on SMB, this bit is always granted, even if not
652 asked for */
653 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
656 if (allow_delete) {
657 *access_mask |= SEC_STD_DELETE;
660 return status;
665 a simplified interface to access check, designed for calls that
666 do not take or return an access check mask
668 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
669 struct ntvfs_request *req,
670 struct pvfs_filename *name,
671 uint32_t access_needed)
673 if (access_needed == 0) {
674 return NT_STATUS_OK;
676 return pvfs_access_check(pvfs, req, name, &access_needed);
680 access check for creating a new file/directory
682 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
683 struct ntvfs_request *req,
684 struct pvfs_filename *name,
685 uint32_t *access_mask,
686 bool container,
687 struct security_descriptor **sd)
689 struct pvfs_filename *parent;
690 NTSTATUS status;
691 uint32_t parent_mask;
692 bool allow_delete = false;
694 if (pvfs_read_only(pvfs, *access_mask)) {
695 return NT_STATUS_ACCESS_DENIED;
698 status = pvfs_resolve_parent(pvfs, req, name, &parent);
699 NT_STATUS_NOT_OK_RETURN(status);
701 if (container) {
702 parent_mask = SEC_DIR_ADD_SUBDIR;
703 } else {
704 parent_mask = SEC_DIR_ADD_FILE;
706 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED ||
707 *access_mask & SEC_STD_DELETE) {
708 parent_mask |= SEC_DIR_DELETE_CHILD;
711 status = pvfs_access_check(pvfs, req, parent, &parent_mask);
712 if (NT_STATUS_IS_OK(status)) {
713 if (parent_mask & SEC_DIR_DELETE_CHILD) {
714 allow_delete = true;
716 } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
718 * on ACCESS_DENIED we get the rejected bits
719 * remove the non critical SEC_DIR_DELETE_CHILD
720 * and check if something else was rejected.
722 parent_mask &= ~SEC_DIR_DELETE_CHILD;
723 if (parent_mask != 0) {
724 return NT_STATUS_ACCESS_DENIED;
726 status = NT_STATUS_OK;
727 } else {
728 return status;
731 if (*sd == NULL) {
732 status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, sd);
735 talloc_free(parent);
736 if (!NT_STATUS_IS_OK(status)) {
737 return status;
740 /* expand the generic access bits to file specific bits */
741 *access_mask = pvfs_translate_mask(*access_mask);
743 if (*access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
744 *access_mask |= SEC_RIGHTS_FILE_ALL;
745 *access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
748 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
749 /* on SMB, this bit is always granted, even if not
750 asked for */
751 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
754 if (allow_delete) {
755 *access_mask |= SEC_STD_DELETE;
758 return NT_STATUS_OK;
762 access check for creating a new file/directory - no access mask supplied
764 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
765 struct ntvfs_request *req,
766 struct pvfs_filename *name,
767 uint32_t access_mask)
769 struct pvfs_filename *parent;
770 NTSTATUS status;
772 status = pvfs_resolve_parent(pvfs, req, name, &parent);
773 if (!NT_STATUS_IS_OK(status)) {
774 return status;
777 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
782 determine if an ACE is inheritable
784 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
785 const struct security_ace *ace,
786 bool container)
788 if (!container) {
789 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
792 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
793 return true;
796 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
797 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
798 return true;
801 return false;
805 this is the core of ACL inheritance. It copies any inheritable
806 aces from the parent SD to the child SD. Note that the algorithm
807 depends on whether the child is a container or not
809 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
810 struct security_descriptor *parent_sd,
811 struct security_descriptor *sd,
812 bool container)
814 int i;
816 for (i=0;i<parent_sd->dacl->num_aces;i++) {
817 struct security_ace ace = parent_sd->dacl->aces[i];
818 NTSTATUS status;
819 const struct dom_sid *creator = NULL, *new_id = NULL;
820 uint32_t orig_flags;
822 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
823 continue;
826 orig_flags = ace.flags;
828 /* see the RAW-ACLS inheritance test for details on these rules */
829 if (!container) {
830 ace.flags = 0;
831 } else {
832 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
834 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
835 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
837 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
838 ace.flags = 0;
842 /* the CREATOR sids are special when inherited */
843 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
844 creator = pvfs->sid_cache.creator_owner;
845 new_id = sd->owner_sid;
846 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
847 creator = pvfs->sid_cache.creator_group;
848 new_id = sd->group_sid;
849 } else {
850 new_id = &ace.trustee;
853 if (creator && container &&
854 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
855 uint32_t flags = ace.flags;
857 ace.trustee = *new_id;
858 ace.flags = 0;
859 status = security_descriptor_dacl_add(sd, &ace);
860 if (!NT_STATUS_IS_OK(status)) {
861 return status;
864 ace.trustee = *creator;
865 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
866 status = security_descriptor_dacl_add(sd, &ace);
867 } else if (container &&
868 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
869 status = security_descriptor_dacl_add(sd, &ace);
870 } else {
871 ace.trustee = *new_id;
872 status = security_descriptor_dacl_add(sd, &ace);
875 if (!NT_STATUS_IS_OK(status)) {
876 return status;
880 return NT_STATUS_OK;
886 calculate the ACL on a new file/directory based on the inherited ACL
887 from the parent. If there is no inherited ACL then return a NULL
888 ACL, which means the default ACL should be used
890 NTSTATUS pvfs_acl_inherited_sd(struct pvfs_state *pvfs,
891 TALLOC_CTX *mem_ctx,
892 struct ntvfs_request *req,
893 struct pvfs_filename *parent,
894 bool container,
895 struct security_descriptor **ret_sd)
897 struct xattr_NTACL *acl;
898 NTSTATUS status;
899 struct security_descriptor *parent_sd, *sd;
900 struct id_map *ids;
901 struct composite_context *ctx;
902 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
904 *ret_sd = NULL;
906 acl = talloc(req, struct xattr_NTACL);
907 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(acl, tmp_ctx);
909 status = pvfs_acl_load(pvfs, parent, -1, acl);
910 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
911 talloc_free(tmp_ctx);
912 return NT_STATUS_OK;
914 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
916 switch (acl->version) {
917 case 1:
918 parent_sd = acl->info.sd;
919 break;
920 default:
921 talloc_free(tmp_ctx);
922 return NT_STATUS_INVALID_ACL;
925 if (parent_sd == NULL ||
926 parent_sd->dacl == NULL ||
927 parent_sd->dacl->num_aces == 0) {
928 /* go with the default ACL */
929 talloc_free(tmp_ctx);
930 return NT_STATUS_OK;
933 /* create the new sd */
934 sd = security_descriptor_initialise(req);
935 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sd, tmp_ctx);
937 ids = talloc_array(sd, struct id_map, 2);
938 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ids, tmp_ctx);
940 ids[0].xid.id = geteuid();
941 ids[0].xid.type = ID_TYPE_UID;
942 ids[0].sid = NULL;
943 ids[0].status = ID_UNKNOWN;
945 ids[1].xid.id = getegid();
946 ids[1].xid.type = ID_TYPE_GID;
947 ids[1].sid = NULL;
948 ids[1].status = ID_UNKNOWN;
950 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
951 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(ctx, tmp_ctx);
953 status = wbc_xids_to_sids_recv(ctx, &ids);
954 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
956 sd->owner_sid = talloc_steal(sd, ids[0].sid);
957 sd->group_sid = talloc_steal(sd, ids[1].sid);
959 sd->type |= SEC_DESC_DACL_PRESENT;
961 /* fill in the aces from the parent */
962 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
963 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
965 /* if there is nothing to inherit then we fallback to the
966 default acl */
967 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
968 talloc_free(tmp_ctx);
969 return NT_STATUS_OK;
972 *ret_sd = talloc_steal(mem_ctx, sd);
974 talloc_free(tmp_ctx);
975 return NT_STATUS_OK;
980 setup an ACL on a new file/directory based on the inherited ACL from
981 the parent. If there is no inherited ACL then we don't set anything,
982 as the default ACL applies anyway
984 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
985 struct ntvfs_request *req,
986 struct pvfs_filename *name,
987 int fd)
989 struct xattr_NTACL acl;
990 NTSTATUS status;
991 struct security_descriptor *sd;
992 struct pvfs_filename *parent;
993 bool container;
995 /* form the parents path */
996 status = pvfs_resolve_parent(pvfs, req, name, &parent);
997 NT_STATUS_NOT_OK_RETURN(status);
999 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
1001 status = pvfs_acl_inherited_sd(pvfs, req, req, parent, container, &sd);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 talloc_free(parent);
1004 return status;
1007 if (sd == NULL) {
1008 return NT_STATUS_OK;
1011 acl.version = 1;
1012 acl.info.sd = sd;
1014 status = pvfs_acl_save(pvfs, name, fd, &acl);
1015 talloc_free(sd);
1016 talloc_free(parent);
1018 return status;
1022 return the maximum allowed access mask
1024 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
1025 struct ntvfs_request *req,
1026 struct pvfs_filename *name,
1027 uint32_t *maximal_access)
1029 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
1030 return pvfs_access_check(pvfs, req, name, maximal_access);