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/ndr_xattr.h"
30 map a single access_mask from generic to specific bits for files/dirs
32 static uint32_t pvfs_translate_mask(uint32_t access_mask)
34 if (access_mask & SEC_MASK_GENERIC) {
35 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
36 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
37 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
38 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
39 access_mask &= ~SEC_MASK_GENERIC;
46 map any generic access bits in the given acl
47 this relies on the fact that the mappings for files and directories
50 static void pvfs_translate_generic_bits(struct security_acl *acl)
54 for (i=0;i<acl->num_aces;i++) {
55 struct security_ace *ace = &acl->aces[i];
56 ace->access_mask = pvfs_translate_mask(ace->access_mask);
62 setup a default ACL for a file
64 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
65 struct smbsrv_request *req,
66 struct pvfs_filename *name, int fd,
67 struct xattr_NTACL *acl)
69 struct security_descriptor *sd;
71 struct security_ace ace;
74 sd = security_descriptor_initialise(req);
76 return NT_STATUS_NO_MEMORY;
79 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
80 if (!NT_STATUS_IS_OK(status)) {
83 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
84 if (!NT_STATUS_IS_OK(status)) {
88 sd->type |= SEC_DESC_DACL_PRESENT;
90 mode = name->st.st_mode;
93 we provide up to 4 ACEs
101 /* setup owner ACE */
102 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
104 ace.trustee = *sd->owner_sid;
107 if (mode & S_IRUSR) {
108 if (mode & S_IWUSR) {
109 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
111 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
114 if (mode & S_IWUSR) {
115 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
117 if (ace.access_mask) {
118 security_descriptor_dacl_add(sd, &ace);
122 /* setup group ACE */
123 ace.trustee = *sd->group_sid;
125 if (mode & S_IRGRP) {
126 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
128 if (mode & S_IWGRP) {
129 /* note that delete is not granted - this matches posix behaviour */
130 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
132 if (ace.access_mask) {
133 security_descriptor_dacl_add(sd, &ace);
136 /* setup other ACE */
137 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
139 if (mode & S_IROTH) {
140 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
142 if (mode & S_IWOTH) {
143 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
145 if (ace.access_mask) {
146 security_descriptor_dacl_add(sd, &ace);
149 /* setup system ACE */
150 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
151 ace.access_mask = SEC_RIGHTS_FILE_ALL;
152 security_descriptor_dacl_add(sd, &ace);
162 omit any security_descriptor elements not specified in the given
165 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
167 if (!(secinfo_flags & SECINFO_OWNER)) {
168 sd->owner_sid = NULL;
170 if (!(secinfo_flags & SECINFO_GROUP)) {
171 sd->group_sid = NULL;
173 if (!(secinfo_flags & SECINFO_DACL)) {
176 if (!(secinfo_flags & SECINFO_SACL)) {
182 answer a setfileinfo for an ACL
184 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
185 struct smbsrv_request *req,
186 struct pvfs_filename *name, int fd,
187 uint32_t access_mask,
188 union smb_setfileinfo *info)
190 struct xattr_NTACL *acl;
191 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
192 struct security_descriptor *new_sd, *sd, orig_sd;
197 acl = talloc(req, struct xattr_NTACL);
199 return NT_STATUS_NO_MEMORY;
202 status = pvfs_acl_load(pvfs, name, fd, acl);
203 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
204 status = pvfs_default_acl(pvfs, req, name, fd, acl);
206 if (!NT_STATUS_IS_OK(status)) {
210 switch (acl->version) {
215 return NT_STATUS_INVALID_ACL;
218 new_sd = info->set_secdesc.in.sd;
221 uid = name->st.st_uid;
222 gid = name->st.st_gid;
224 /* only set the elements that have been specified */
225 if ((secinfo_flags & SECINFO_OWNER) &&
226 !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
227 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
228 return NT_STATUS_ACCESS_DENIED;
230 sd->owner_sid = new_sd->owner_sid;
231 status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid);
232 if (!NT_STATUS_IS_OK(status)) {
236 if ((secinfo_flags & SECINFO_GROUP) &&
237 !dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
238 sd->group_sid = new_sd->group_sid;
239 status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid);
240 if (!NT_STATUS_IS_OK(status)) {
244 if (secinfo_flags & SECINFO_DACL) {
245 sd->dacl = new_sd->dacl;
246 pvfs_translate_generic_bits(sd->dacl);
248 if (secinfo_flags & SECINFO_SACL) {
249 sd->sacl = new_sd->sacl;
250 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
251 return NT_STATUS_ACCESS_DENIED;
253 pvfs_translate_generic_bits(sd->sacl);
256 if (uid != -1 || gid != -1) {
259 ret = chown(name->full_name, uid, gid);
261 ret = fchown(fd, uid, gid);
264 return pvfs_map_errno(pvfs, errno);
268 /* we avoid saving if the sd is the same. This means when clients
269 copy files and end up copying the default sd that we don't
270 needlessly use xattrs */
271 if (!security_descriptor_equal(sd, &orig_sd)) {
272 status = pvfs_acl_save(pvfs, name, fd, acl);
280 answer a fileinfo query for the ACL
282 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
283 struct smbsrv_request *req,
284 struct pvfs_filename *name, int fd,
285 union smb_fileinfo *info)
287 struct xattr_NTACL *acl;
289 struct security_descriptor *sd;
291 acl = talloc(req, struct xattr_NTACL);
293 return NT_STATUS_NO_MEMORY;
296 status = pvfs_acl_load(pvfs, name, fd, acl);
297 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
298 status = pvfs_default_acl(pvfs, req, name, fd, acl);
300 if (!NT_STATUS_IS_OK(status)) {
304 switch (acl->version) {
309 return NT_STATUS_INVALID_ACL;
312 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
314 info->query_secdesc.out.sd = sd;
321 default access check function based on unix permissions
322 doing this saves on building a full security descriptor
323 for the common case of access check on files with no
326 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
327 struct smbsrv_request *req,
328 struct pvfs_filename *name,
329 uint32_t *access_mask)
331 uid_t uid = geteuid();
332 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
334 /* owner and root get extra permissions */
335 if (uid == 0 || uid == name->st.st_uid) {
336 max_bits |= SEC_STD_ALL;
339 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
340 *access_mask = max_bits;
344 if (*access_mask & ~max_bits) {
345 return NT_STATUS_ACCESS_DENIED;
348 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
355 check the security descriptor on a file, if any
357 *access_mask is modified with the access actually granted
359 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
360 struct smbsrv_request *req,
361 struct pvfs_filename *name,
362 uint32_t *access_mask)
364 struct security_token *token = req->session->session_info->security_token;
365 struct xattr_NTACL *acl;
367 struct security_descriptor *sd;
369 acl = talloc(req, struct xattr_NTACL);
371 return NT_STATUS_NO_MEMORY;
374 /* expand the generic access bits to file specific bits */
375 *access_mask = pvfs_translate_mask(*access_mask);
376 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
378 status = pvfs_acl_load(pvfs, name, -1, acl);
379 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
381 return pvfs_access_check_unix(pvfs, req, name, access_mask);
383 if (!NT_STATUS_IS_OK(status)) {
387 switch (acl->version) {
392 return NT_STATUS_INVALID_ACL;
395 /* check the acl against the required access mask */
396 status = sec_access_check(sd, token, *access_mask, access_mask);
398 /* this bit is always granted, even if not asked for */
399 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
408 a simplified interface to access check, designed for calls that
409 do not take or return an access check mask
411 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
412 struct smbsrv_request *req,
413 struct pvfs_filename *name,
414 uint32_t access_needed)
416 if (access_needed == 0) {
419 return pvfs_access_check(pvfs, req, name, &access_needed);
423 access check for creating a new file/directory
425 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
426 struct smbsrv_request *req,
427 struct pvfs_filename *name,
428 uint32_t *access_mask)
430 struct pvfs_filename *parent;
433 status = pvfs_resolve_parent(pvfs, req, name, &parent);
434 if (!NT_STATUS_IS_OK(status)) {
438 status = pvfs_access_check(pvfs, req, parent, access_mask);
439 if (!NT_STATUS_IS_OK(status)) {
443 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
444 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
451 access check for creating a new file/directory - no access mask supplied
453 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
454 struct smbsrv_request *req,
455 struct pvfs_filename *name,
456 uint32_t access_mask)
458 struct pvfs_filename *parent;
461 status = pvfs_resolve_parent(pvfs, req, name, &parent);
462 if (!NT_STATUS_IS_OK(status)) {
466 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
471 determine if an ACE is inheritable
473 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
474 const struct security_ace *ace,
478 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
481 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
485 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
486 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
494 this is the core of ACL inheritance. It copies any inheritable
495 aces from the parent SD to the child SD. Note that the algorithm
496 depends on whether the child is a container or not
498 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
499 struct security_descriptor *parent_sd,
500 struct security_descriptor *sd,
505 for (i=0;i<parent_sd->dacl->num_aces;i++) {
506 struct security_ace ace = parent_sd->dacl->aces[i];
508 const struct dom_sid *creator = NULL, *new_id = NULL;
511 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
515 orig_flags = ace.flags;
517 /* see the RAW-ACLS inheritance test for details on these rules */
521 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
523 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
524 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
526 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
531 /* the CREATOR sids are special when inherited */
532 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
533 creator = pvfs->sid_cache.creator_owner;
534 new_id = sd->owner_sid;
535 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
536 creator = pvfs->sid_cache.creator_group;
537 new_id = sd->group_sid;
539 new_id = &ace.trustee;
542 if (creator && container &&
543 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
544 uint32_t flags = ace.flags;
546 ace.trustee = *new_id;
548 status = security_descriptor_dacl_add(sd, &ace);
549 if (!NT_STATUS_IS_OK(status)) {
553 ace.trustee = *creator;
554 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
555 status = security_descriptor_dacl_add(sd, &ace);
556 } else if (container &&
557 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
558 status = security_descriptor_dacl_add(sd, &ace);
560 ace.trustee = *new_id;
561 status = security_descriptor_dacl_add(sd, &ace);
564 if (!NT_STATUS_IS_OK(status)) {
575 setup an ACL on a new file/directory based on the inherited ACL from
576 the parent. If there is no inherited ACL then we don't set anything,
577 as the default ACL applies anyway
579 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
580 struct smbsrv_request *req,
581 struct pvfs_filename *name,
584 struct xattr_NTACL *acl;
586 struct pvfs_filename *parent;
587 struct security_descriptor *parent_sd, *sd;
590 /* form the parents path */
591 status = pvfs_resolve_parent(pvfs, req, name, &parent);
592 if (!NT_STATUS_IS_OK(status)) {
596 acl = talloc(req, struct xattr_NTACL);
598 return NT_STATUS_NO_MEMORY;
601 status = pvfs_acl_load(pvfs, parent, -1, acl);
602 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
605 if (!NT_STATUS_IS_OK(status)) {
609 switch (acl->version) {
611 parent_sd = acl->info.sd;
614 return NT_STATUS_INVALID_ACL;
617 if (parent_sd == NULL ||
618 parent_sd->dacl == NULL ||
619 parent_sd->dacl->num_aces == 0) {
620 /* go with the default ACL */
624 /* create the new sd */
625 sd = security_descriptor_initialise(req);
627 return NT_STATUS_NO_MEMORY;
630 status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
631 if (!NT_STATUS_IS_OK(status)) {
634 status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
635 if (!NT_STATUS_IS_OK(status)) {
639 sd->type |= SEC_DESC_DACL_PRESENT;
641 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
643 /* fill in the aces from the parent */
644 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
645 if (!NT_STATUS_IS_OK(status)) {
649 /* if there is nothing to inherit then we fallback to the
651 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
657 status = pvfs_acl_save(pvfs, name, fd, acl);