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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "auth/auth.h"
25 #include "vfs_posix.h"
26 #include "librpc/gen_ndr/xattr.h"
27 #include "libcli/security/security.h"
31 map a single access_mask from generic to specific bits for files/dirs
33 static uint32_t pvfs_translate_mask(uint32_t access_mask)
35 if (access_mask & SEC_MASK_GENERIC) {
36 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
37 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
38 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
39 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
40 access_mask &= ~SEC_MASK_GENERIC;
47 map any generic access bits in the given acl
48 this relies on the fact that the mappings for files and directories
51 static void pvfs_translate_generic_bits(struct security_acl *acl)
57 for (i=0;i<acl->num_aces;i++) {
58 struct security_ace *ace = &acl->aces[i];
59 ace->access_mask = pvfs_translate_mask(ace->access_mask);
65 setup a default ACL for a file
67 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
68 struct ntvfs_request *req,
69 struct pvfs_filename *name, int fd,
70 struct xattr_NTACL *acl)
72 struct security_descriptor *sd;
74 struct security_ace ace;
77 sd = security_descriptor_initialise(req);
79 return NT_STATUS_NO_MEMORY;
82 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
83 if (!NT_STATUS_IS_OK(status)) {
86 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
87 if (!NT_STATUS_IS_OK(status)) {
91 sd->type |= SEC_DESC_DACL_PRESENT;
93 mode = name->st.st_mode;
96 we provide up to 4 ACEs
104 /* setup owner ACE */
105 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
107 ace.trustee = *sd->owner_sid;
110 if (mode & S_IRUSR) {
111 if (mode & S_IWUSR) {
112 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
114 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
117 if (mode & S_IWUSR) {
118 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
120 if (ace.access_mask) {
121 security_descriptor_dacl_add(sd, &ace);
125 /* setup group ACE */
126 ace.trustee = *sd->group_sid;
128 if (mode & S_IRGRP) {
129 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
131 if (mode & S_IWGRP) {
132 /* note that delete is not granted - this matches posix behaviour */
133 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
135 if (ace.access_mask) {
136 security_descriptor_dacl_add(sd, &ace);
139 /* setup other ACE */
140 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
142 if (mode & S_IROTH) {
143 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
145 if (mode & S_IWOTH) {
146 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
148 if (ace.access_mask) {
149 security_descriptor_dacl_add(sd, &ace);
152 /* setup system ACE */
153 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
154 ace.access_mask = SEC_RIGHTS_FILE_ALL;
155 security_descriptor_dacl_add(sd, &ace);
165 omit any security_descriptor elements not specified in the given
168 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
170 if (!(secinfo_flags & SECINFO_OWNER)) {
171 sd->owner_sid = NULL;
173 if (!(secinfo_flags & SECINFO_GROUP)) {
174 sd->group_sid = NULL;
176 if (!(secinfo_flags & SECINFO_DACL)) {
179 if (!(secinfo_flags & SECINFO_SACL)) {
185 answer a setfileinfo for an ACL
187 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
188 struct ntvfs_request *req,
189 struct pvfs_filename *name, int fd,
190 uint32_t access_mask,
191 union smb_setfileinfo *info)
193 struct xattr_NTACL *acl;
194 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
195 struct security_descriptor *new_sd, *sd, orig_sd;
202 acl = talloc(req, struct xattr_NTACL);
204 return NT_STATUS_NO_MEMORY;
207 status = pvfs_acl_load(pvfs, name, fd, acl);
208 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
209 status = pvfs_default_acl(pvfs, req, name, fd, acl);
211 if (!NT_STATUS_IS_OK(status)) {
215 switch (acl->version) {
220 return NT_STATUS_INVALID_ACL;
223 new_sd = info->set_secdesc.in.sd;
226 old_uid = name->st.st_uid;
227 old_gid = name->st.st_gid;
229 /* only set the elements that have been specified */
230 if (secinfo_flags & SECINFO_OWNER) {
231 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
232 return NT_STATUS_ACCESS_DENIED;
234 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
235 status = sidmap_sid_to_unixuid(pvfs->sidmap, new_sd->owner_sid, &new_uid);
236 NT_STATUS_NOT_OK_RETURN(status);
238 sd->owner_sid = new_sd->owner_sid;
240 if (secinfo_flags & SECINFO_GROUP) {
241 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
242 return NT_STATUS_ACCESS_DENIED;
244 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
245 status = sidmap_sid_to_unixgid(pvfs->sidmap, new_sd->group_sid, &new_gid);
246 NT_STATUS_NOT_OK_RETURN(status);
248 sd->group_sid = new_sd->group_sid;
250 if (secinfo_flags & SECINFO_DACL) {
251 if (!(access_mask & SEC_STD_WRITE_DAC)) {
252 return NT_STATUS_ACCESS_DENIED;
254 sd->dacl = new_sd->dacl;
255 pvfs_translate_generic_bits(sd->dacl);
257 if (secinfo_flags & SECINFO_SACL) {
258 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
259 return NT_STATUS_ACCESS_DENIED;
261 sd->sacl = new_sd->sacl;
262 pvfs_translate_generic_bits(sd->sacl);
265 if (new_uid == old_uid) {
269 if (new_gid == old_gid) {
273 /* if there's something to change try it */
274 if (new_uid != -1 || new_gid != -1) {
277 ret = chown(name->full_name, new_uid, new_gid);
279 ret = fchown(fd, new_uid, new_gid);
282 return pvfs_map_errno(pvfs, errno);
286 /* we avoid saving if the sd is the same. This means when clients
287 copy files and end up copying the default sd that we don't
288 needlessly use xattrs */
289 if (!security_descriptor_equal(sd, &orig_sd)) {
290 status = pvfs_acl_save(pvfs, name, fd, acl);
298 answer a fileinfo query for the ACL
300 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
301 struct ntvfs_request *req,
302 struct pvfs_filename *name, int fd,
303 union smb_fileinfo *info)
305 struct xattr_NTACL *acl;
307 struct security_descriptor *sd;
309 acl = talloc(req, struct xattr_NTACL);
311 return NT_STATUS_NO_MEMORY;
314 status = pvfs_acl_load(pvfs, name, fd, acl);
315 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
316 status = pvfs_default_acl(pvfs, req, name, fd, acl);
318 if (!NT_STATUS_IS_OK(status)) {
322 switch (acl->version) {
327 return NT_STATUS_INVALID_ACL;
330 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
332 info->query_secdesc.out.sd = sd;
339 check the read only bit against any of the write access bits
341 static BOOL pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
343 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
344 (access_mask & (SEC_FILE_WRITE_DATA |
345 SEC_FILE_APPEND_DATA |
347 SEC_FILE_WRITE_ATTRIBUTE |
350 SEC_STD_WRITE_OWNER |
351 SEC_DIR_DELETE_CHILD))) {
358 default access check function based on unix permissions
359 doing this saves on building a full security descriptor
360 for the common case of access check on files with no
363 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
364 struct ntvfs_request *req,
365 struct pvfs_filename *name,
366 uint32_t *access_mask)
368 uid_t uid = geteuid();
369 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
371 if (pvfs_read_only(pvfs, *access_mask)) {
372 return NT_STATUS_ACCESS_DENIED;
375 /* owner and root get extra permissions */
377 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
378 } else if (uid == name->st.st_uid) {
379 max_bits |= SEC_STD_ALL;
382 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
383 *access_mask = max_bits;
387 if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
388 return NT_STATUS_PRIVILEGE_NOT_HELD;
391 if (*access_mask & ~max_bits) {
392 return NT_STATUS_ACCESS_DENIED;
395 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
402 check the security descriptor on a file, if any
404 *access_mask is modified with the access actually granted
406 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
407 struct ntvfs_request *req,
408 struct pvfs_filename *name,
409 uint32_t *access_mask)
411 struct security_token *token = req->session_info->security_token;
412 struct xattr_NTACL *acl;
414 struct security_descriptor *sd;
416 if (pvfs_read_only(pvfs, *access_mask)) {
417 return NT_STATUS_ACCESS_DENIED;
420 acl = talloc(req, struct xattr_NTACL);
422 return NT_STATUS_NO_MEMORY;
425 /* expand the generic access bits to file specific bits */
426 *access_mask = pvfs_translate_mask(*access_mask);
427 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
429 status = pvfs_acl_load(pvfs, name, -1, acl);
430 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
432 return pvfs_access_check_unix(pvfs, req, name, access_mask);
434 if (!NT_STATUS_IS_OK(status)) {
438 switch (acl->version) {
443 return NT_STATUS_INVALID_ACL;
446 /* check the acl against the required access mask */
447 status = sec_access_check(sd, token, *access_mask, access_mask);
449 /* this bit is always granted, even if not asked for */
450 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
459 a simplified interface to access check, designed for calls that
460 do not take or return an access check mask
462 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
463 struct ntvfs_request *req,
464 struct pvfs_filename *name,
465 uint32_t access_needed)
467 if (access_needed == 0) {
470 return pvfs_access_check(pvfs, req, name, &access_needed);
474 access check for creating a new file/directory
476 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
477 struct ntvfs_request *req,
478 struct pvfs_filename *name,
479 uint32_t *access_mask)
481 struct pvfs_filename *parent;
484 status = pvfs_resolve_parent(pvfs, req, name, &parent);
485 if (!NT_STATUS_IS_OK(status)) {
489 status = pvfs_access_check(pvfs, req, parent, access_mask);
490 if (!NT_STATUS_IS_OK(status)) {
494 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
495 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
502 access check for creating a new file/directory - no access mask supplied
504 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
505 struct ntvfs_request *req,
506 struct pvfs_filename *name,
507 uint32_t access_mask)
509 struct pvfs_filename *parent;
512 status = pvfs_resolve_parent(pvfs, req, name, &parent);
513 if (!NT_STATUS_IS_OK(status)) {
517 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
522 determine if an ACE is inheritable
524 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
525 const struct security_ace *ace,
529 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
532 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
536 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
537 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
545 this is the core of ACL inheritance. It copies any inheritable
546 aces from the parent SD to the child SD. Note that the algorithm
547 depends on whether the child is a container or not
549 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
550 struct security_descriptor *parent_sd,
551 struct security_descriptor *sd,
556 for (i=0;i<parent_sd->dacl->num_aces;i++) {
557 struct security_ace ace = parent_sd->dacl->aces[i];
559 const struct dom_sid *creator = NULL, *new_id = NULL;
562 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
566 orig_flags = ace.flags;
568 /* see the RAW-ACLS inheritance test for details on these rules */
572 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
574 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
575 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
577 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
582 /* the CREATOR sids are special when inherited */
583 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
584 creator = pvfs->sid_cache.creator_owner;
585 new_id = sd->owner_sid;
586 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
587 creator = pvfs->sid_cache.creator_group;
588 new_id = sd->group_sid;
590 new_id = &ace.trustee;
593 if (creator && container &&
594 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
595 uint32_t flags = ace.flags;
597 ace.trustee = *new_id;
599 status = security_descriptor_dacl_add(sd, &ace);
600 if (!NT_STATUS_IS_OK(status)) {
604 ace.trustee = *creator;
605 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
606 status = security_descriptor_dacl_add(sd, &ace);
607 } else if (container &&
608 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
609 status = security_descriptor_dacl_add(sd, &ace);
611 ace.trustee = *new_id;
612 status = security_descriptor_dacl_add(sd, &ace);
615 if (!NT_STATUS_IS_OK(status)) {
626 setup an ACL on a new file/directory based on the inherited ACL from
627 the parent. If there is no inherited ACL then we don't set anything,
628 as the default ACL applies anyway
630 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
631 struct ntvfs_request *req,
632 struct pvfs_filename *name,
635 struct xattr_NTACL *acl;
637 struct pvfs_filename *parent;
638 struct security_descriptor *parent_sd, *sd;
641 /* form the parents path */
642 status = pvfs_resolve_parent(pvfs, req, name, &parent);
643 if (!NT_STATUS_IS_OK(status)) {
647 acl = talloc(req, struct xattr_NTACL);
649 return NT_STATUS_NO_MEMORY;
652 status = pvfs_acl_load(pvfs, parent, -1, acl);
653 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
656 if (!NT_STATUS_IS_OK(status)) {
660 switch (acl->version) {
662 parent_sd = acl->info.sd;
665 return NT_STATUS_INVALID_ACL;
668 if (parent_sd == NULL ||
669 parent_sd->dacl == NULL ||
670 parent_sd->dacl->num_aces == 0) {
671 /* go with the default ACL */
675 /* create the new sd */
676 sd = security_descriptor_initialise(req);
678 return NT_STATUS_NO_MEMORY;
681 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
682 if (!NT_STATUS_IS_OK(status)) {
685 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
686 if (!NT_STATUS_IS_OK(status)) {
690 sd->type |= SEC_DESC_DACL_PRESENT;
692 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
694 /* fill in the aces from the parent */
695 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
696 if (!NT_STATUS_IS_OK(status)) {
700 /* if there is nothing to inherit then we fallback to the
702 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
708 status = pvfs_acl_save(pvfs, name, fd, acl);