2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - ACL support
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "auth/auth.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "libcli/security/security.h"
29 /* the list of currently registered ACL backends */
30 static struct pvfs_acl_backend {
31 const struct pvfs_acl_ops *ops;
33 static int num_backends;
36 register a pvfs acl backend.
38 The 'name' can be later used by other backends to find the operations
39 structure for this backend.
41 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
43 struct pvfs_acl_ops *new_ops;
45 if (pvfs_acl_backend_byname(ops->name) != NULL) {
46 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
47 return NT_STATUS_OBJECT_NAME_COLLISION;
50 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
51 NT_STATUS_HAVE_NO_MEMORY(backends);
53 new_ops = talloc_memdup(backends, ops, sizeof(*ops));
54 new_ops->name = talloc_strdup(new_ops, ops->name);
56 backends[num_backends].ops = new_ops;
60 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
67 return the operations structure for a named backend
69 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
73 for (i=0;i<num_backends;i++) {
74 if (strcmp(backends[i].ops->name, name) == 0) {
75 return backends[i].ops;
84 map a single access_mask from generic to specific bits for files/dirs
86 static uint32_t pvfs_translate_mask(uint32_t access_mask)
88 if (access_mask & SEC_MASK_GENERIC) {
89 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
90 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
91 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
92 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
93 access_mask &= ~SEC_MASK_GENERIC;
100 map any generic access bits in the given acl
101 this relies on the fact that the mappings for files and directories
104 static void pvfs_translate_generic_bits(struct security_acl *acl)
110 for (i=0;i<acl->num_aces;i++) {
111 struct security_ace *ace = &acl->aces[i];
112 ace->access_mask = pvfs_translate_mask(ace->access_mask);
118 setup a default ACL for a file
120 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
121 struct ntvfs_request *req,
122 struct pvfs_filename *name, int fd,
123 struct security_descriptor **psd)
125 struct security_descriptor *sd;
127 struct security_ace ace;
130 *psd = security_descriptor_initialise(req);
132 return NT_STATUS_NO_MEMORY;
136 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
137 if (!NT_STATUS_IS_OK(status)) {
140 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
141 if (!NT_STATUS_IS_OK(status)) {
145 sd->type |= SEC_DESC_DACL_PRESENT;
147 mode = name->st.st_mode;
150 we provide up to 4 ACEs
158 /* setup owner ACE */
159 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
161 ace.trustee = *sd->owner_sid;
164 if (mode & S_IRUSR) {
165 if (mode & S_IWUSR) {
166 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
168 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
171 if (mode & S_IWUSR) {
172 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
174 if (ace.access_mask) {
175 security_descriptor_dacl_add(sd, &ace);
179 /* setup group ACE */
180 ace.trustee = *sd->group_sid;
182 if (mode & S_IRGRP) {
183 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
185 if (mode & S_IWGRP) {
186 /* note that delete is not granted - this matches posix behaviour */
187 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
189 if (ace.access_mask) {
190 security_descriptor_dacl_add(sd, &ace);
193 /* setup other ACE */
194 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
196 if (mode & S_IROTH) {
197 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
199 if (mode & S_IWOTH) {
200 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
202 if (ace.access_mask) {
203 security_descriptor_dacl_add(sd, &ace);
206 /* setup system ACE */
207 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
208 ace.access_mask = SEC_RIGHTS_FILE_ALL;
209 security_descriptor_dacl_add(sd, &ace);
216 omit any security_descriptor elements not specified in the given
219 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
221 if (!(secinfo_flags & SECINFO_OWNER)) {
222 sd->owner_sid = NULL;
224 if (!(secinfo_flags & SECINFO_GROUP)) {
225 sd->group_sid = NULL;
227 if (!(secinfo_flags & SECINFO_DACL)) {
230 if (!(secinfo_flags & SECINFO_SACL)) {
236 answer a setfileinfo for an ACL
238 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
239 struct ntvfs_request *req,
240 struct pvfs_filename *name, int fd,
241 uint32_t access_mask,
242 union smb_setfileinfo *info)
244 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
245 struct security_descriptor *new_sd, *sd, orig_sd;
246 NTSTATUS status = NT_STATUS_NOT_FOUND;
252 if (pvfs->acl_ops != NULL) {
253 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
255 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
256 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
258 if (!NT_STATUS_IS_OK(status)) {
262 new_sd = info->set_secdesc.in.sd;
265 old_uid = name->st.st_uid;
266 old_gid = name->st.st_gid;
268 /* only set the elements that have been specified */
269 if (secinfo_flags & SECINFO_OWNER) {
270 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
271 return NT_STATUS_ACCESS_DENIED;
273 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
274 status = sidmap_sid_to_unixuid(pvfs->sidmap, new_sd->owner_sid, &new_uid);
275 NT_STATUS_NOT_OK_RETURN(status);
277 sd->owner_sid = new_sd->owner_sid;
279 if (secinfo_flags & SECINFO_GROUP) {
280 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
281 return NT_STATUS_ACCESS_DENIED;
283 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
284 status = sidmap_sid_to_unixgid(pvfs->sidmap, new_sd->group_sid, &new_gid);
285 NT_STATUS_NOT_OK_RETURN(status);
287 sd->group_sid = new_sd->group_sid;
289 if (secinfo_flags & SECINFO_DACL) {
290 if (!(access_mask & SEC_STD_WRITE_DAC)) {
291 return NT_STATUS_ACCESS_DENIED;
293 sd->dacl = new_sd->dacl;
294 pvfs_translate_generic_bits(sd->dacl);
296 if (secinfo_flags & SECINFO_SACL) {
297 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
298 return NT_STATUS_ACCESS_DENIED;
300 sd->sacl = new_sd->sacl;
301 pvfs_translate_generic_bits(sd->sacl);
304 if (new_uid == old_uid) {
308 if (new_gid == old_gid) {
312 /* if there's something to change try it */
313 if (new_uid != -1 || new_gid != -1) {
316 ret = chown(name->full_name, new_uid, new_gid);
318 ret = fchown(fd, new_uid, new_gid);
321 return pvfs_map_errno(pvfs, errno);
325 /* we avoid saving if the sd is the same. This means when clients
326 copy files and end up copying the default sd that we don't
327 needlessly use xattrs */
328 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
329 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
337 answer a fileinfo query for the ACL
339 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
340 struct ntvfs_request *req,
341 struct pvfs_filename *name, int fd,
342 union smb_fileinfo *info)
344 NTSTATUS status = NT_STATUS_NOT_FOUND;
345 struct security_descriptor *sd;
348 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
350 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
351 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
353 if (!NT_STATUS_IS_OK(status)) {
357 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
359 info->query_secdesc.out.sd = sd;
366 check the read only bit against any of the write access bits
368 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
370 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
371 (access_mask & (SEC_FILE_WRITE_DATA |
372 SEC_FILE_APPEND_DATA |
374 SEC_FILE_WRITE_ATTRIBUTE |
377 SEC_STD_WRITE_OWNER |
378 SEC_DIR_DELETE_CHILD))) {
385 default access check function based on unix permissions
386 doing this saves on building a full security descriptor
387 for the common case of access check on files with no
390 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
391 struct ntvfs_request *req,
392 struct pvfs_filename *name,
393 uint32_t *access_mask)
395 uid_t uid = geteuid();
396 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
398 if (pvfs_read_only(pvfs, *access_mask)) {
399 return NT_STATUS_ACCESS_DENIED;
402 /* owner and root get extra permissions */
404 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
405 } else if (uid == name->st.st_uid) {
406 max_bits |= SEC_STD_ALL;
409 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
410 *access_mask = max_bits;
414 if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
415 return NT_STATUS_PRIVILEGE_NOT_HELD;
418 if (*access_mask & ~max_bits) {
419 return NT_STATUS_ACCESS_DENIED;
422 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
429 check the security descriptor on a file, if any
431 *access_mask is modified with the access actually granted
433 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
434 struct ntvfs_request *req,
435 struct pvfs_filename *name,
436 uint32_t *access_mask)
438 struct security_token *token = req->session_info->security_token;
439 struct xattr_NTACL *acl;
441 struct security_descriptor *sd;
443 if (pvfs_read_only(pvfs, *access_mask)) {
444 return NT_STATUS_ACCESS_DENIED;
447 acl = talloc(req, struct xattr_NTACL);
449 return NT_STATUS_NO_MEMORY;
452 /* expand the generic access bits to file specific bits */
453 *access_mask = pvfs_translate_mask(*access_mask);
454 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
456 status = pvfs_acl_load(pvfs, name, -1, acl);
457 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
459 return pvfs_access_check_unix(pvfs, req, name, access_mask);
461 if (!NT_STATUS_IS_OK(status)) {
465 switch (acl->version) {
470 return NT_STATUS_INVALID_ACL;
473 /* check the acl against the required access mask */
474 status = sec_access_check(sd, token, *access_mask, access_mask);
476 /* this bit is always granted, even if not asked for */
477 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
486 a simplified interface to access check, designed for calls that
487 do not take or return an access check mask
489 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
490 struct ntvfs_request *req,
491 struct pvfs_filename *name,
492 uint32_t access_needed)
494 if (access_needed == 0) {
497 return pvfs_access_check(pvfs, req, name, &access_needed);
501 access check for creating a new file/directory
503 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
504 struct ntvfs_request *req,
505 struct pvfs_filename *name,
506 uint32_t *access_mask)
508 struct pvfs_filename *parent;
511 status = pvfs_resolve_parent(pvfs, req, name, &parent);
512 if (!NT_STATUS_IS_OK(status)) {
516 status = pvfs_access_check(pvfs, req, parent, access_mask);
517 if (!NT_STATUS_IS_OK(status)) {
521 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
522 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
529 access check for creating a new file/directory - no access mask supplied
531 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
532 struct ntvfs_request *req,
533 struct pvfs_filename *name,
534 uint32_t access_mask)
536 struct pvfs_filename *parent;
539 status = pvfs_resolve_parent(pvfs, req, name, &parent);
540 if (!NT_STATUS_IS_OK(status)) {
544 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
549 determine if an ACE is inheritable
551 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
552 const struct security_ace *ace,
556 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
559 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
563 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
564 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
572 this is the core of ACL inheritance. It copies any inheritable
573 aces from the parent SD to the child SD. Note that the algorithm
574 depends on whether the child is a container or not
576 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
577 struct security_descriptor *parent_sd,
578 struct security_descriptor *sd,
583 for (i=0;i<parent_sd->dacl->num_aces;i++) {
584 struct security_ace ace = parent_sd->dacl->aces[i];
586 const struct dom_sid *creator = NULL, *new_id = NULL;
589 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
593 orig_flags = ace.flags;
595 /* see the RAW-ACLS inheritance test for details on these rules */
599 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
601 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
602 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
604 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
609 /* the CREATOR sids are special when inherited */
610 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
611 creator = pvfs->sid_cache.creator_owner;
612 new_id = sd->owner_sid;
613 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
614 creator = pvfs->sid_cache.creator_group;
615 new_id = sd->group_sid;
617 new_id = &ace.trustee;
620 if (creator && container &&
621 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
622 uint32_t flags = ace.flags;
624 ace.trustee = *new_id;
626 status = security_descriptor_dacl_add(sd, &ace);
627 if (!NT_STATUS_IS_OK(status)) {
631 ace.trustee = *creator;
632 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
633 status = security_descriptor_dacl_add(sd, &ace);
634 } else if (container &&
635 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
636 status = security_descriptor_dacl_add(sd, &ace);
638 ace.trustee = *new_id;
639 status = security_descriptor_dacl_add(sd, &ace);
642 if (!NT_STATUS_IS_OK(status)) {
653 setup an ACL on a new file/directory based on the inherited ACL from
654 the parent. If there is no inherited ACL then we don't set anything,
655 as the default ACL applies anyway
657 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
658 struct ntvfs_request *req,
659 struct pvfs_filename *name,
662 struct xattr_NTACL *acl;
664 struct pvfs_filename *parent;
665 struct security_descriptor *parent_sd, *sd;
668 /* form the parents path */
669 status = pvfs_resolve_parent(pvfs, req, name, &parent);
670 if (!NT_STATUS_IS_OK(status)) {
674 acl = talloc(req, struct xattr_NTACL);
676 return NT_STATUS_NO_MEMORY;
679 status = pvfs_acl_load(pvfs, parent, -1, acl);
680 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
683 if (!NT_STATUS_IS_OK(status)) {
687 switch (acl->version) {
689 parent_sd = acl->info.sd;
692 return NT_STATUS_INVALID_ACL;
695 if (parent_sd == NULL ||
696 parent_sd->dacl == NULL ||
697 parent_sd->dacl->num_aces == 0) {
698 /* go with the default ACL */
702 /* create the new sd */
703 sd = security_descriptor_initialise(req);
705 return NT_STATUS_NO_MEMORY;
708 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
709 if (!NT_STATUS_IS_OK(status)) {
712 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
713 if (!NT_STATUS_IS_OK(status)) {
717 sd->type |= SEC_DESC_DACL_PRESENT;
719 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
721 /* fill in the aces from the parent */
722 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
723 if (!NT_STATUS_IS_OK(status)) {
727 /* if there is nothing to inherit then we fallback to the
729 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
735 status = pvfs_acl_save(pvfs, name, fd, acl);