174432Sjedgar/* 290781Sjedgar * Copyright (c) 2001-2002 Chris D. Faulhaber 374432Sjedgar * All rights reserved. 474432Sjedgar * 574432Sjedgar * Redistribution and use in source and binary forms, with or without 674432Sjedgar * modification, are permitted provided that the following conditions 774432Sjedgar * are met: 874432Sjedgar * 1. Redistributions of source code must retain the above copyright 974432Sjedgar * notice, this list of conditions and the following disclaimer. 1074432Sjedgar * 2. Redistributions in binary form must reproduce the above copyright 1174432Sjedgar * notice, this list of conditions and the following disclaimer in the 1274432Sjedgar * documentation and/or other materials provided with the distribution. 1374432Sjedgar * 1474432Sjedgar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1574432Sjedgar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1674432Sjedgar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184607Simp * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18184607Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184607Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184607Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184607Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184607Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184607Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184607Simp * SUCH DAMAGE. 2574432Sjedgar */ 2674432Sjedgar 2792986Sobrien#include <sys/cdefs.h> 2892986Sobrien__FBSDID("$FreeBSD$"); 2992986Sobrien 3074432Sjedgar#include <sys/types.h> 3175185Stmm#include "namespace.h" 3274432Sjedgar#include <sys/acl.h> 3375185Stmm#include "un-namespace.h" 3474432Sjedgar 3574432Sjedgar#include <errno.h> 3675928Sjedgar#include <stdio.h> 3774432Sjedgar 38194955Strasz#include "acl_support.h" 39194955Strasz 4074432Sjedgar/* 4175928Sjedgar * acl_calc_mask() (23.4.2): calculate and set the permissions 4275928Sjedgar * associated with the ACL_MASK ACL entry. If the ACL already 4375928Sjedgar * contains an ACL_MASK entry, its permissions shall be 4475928Sjedgar * overwritten; if not, one shall be added. 4574432Sjedgar */ 4674432Sjedgarint 4774432Sjedgaracl_calc_mask(acl_t *acl_p) 4874432Sjedgar{ 4975928Sjedgar struct acl *acl_int, *acl_int_new; 5075928Sjedgar acl_t acl_new; 5175928Sjedgar int i, mask_mode, mask_num; 5274432Sjedgar 5375928Sjedgar /* 5475928Sjedgar * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL. 5575928Sjedgar * Since one of the primary reasons to use this function would be 5675928Sjedgar * to calculate the appropriate mask to obtain a valid ACL, we only 5775928Sjedgar * perform sanity checks here and validate the ACL prior to 5875928Sjedgar * returning. 5975928Sjedgar */ 6090781Sjedgar if (acl_p == NULL || *acl_p == NULL) { 6174432Sjedgar errno = EINVAL; 6290781Sjedgar return (-1); 6374432Sjedgar } 64196740Strasz 65196740Strasz if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) { 66196740Strasz errno = EINVAL; 67196740Strasz return (-1); 68196740Strasz } 69196740Strasz _acl_brand_as(*acl_p, ACL_BRAND_POSIX); 70196740Strasz 7175928Sjedgar acl_int = &(*acl_p)->ats_acl; 7275928Sjedgar if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) { 7375928Sjedgar errno = EINVAL; 7490781Sjedgar return (-1); 7575928Sjedgar } 7674432Sjedgar 7774432Sjedgar acl_new = acl_dup(*acl_p); 7890781Sjedgar if (acl_new == NULL) 7990781Sjedgar return (-1); 8075928Sjedgar acl_int_new = &acl_new->ats_acl; 8174432Sjedgar 8275928Sjedgar mask_mode = 0; 8374432Sjedgar mask_num = -1; 8474432Sjedgar 8574432Sjedgar /* gather permissions and find a mask entry */ 8675928Sjedgar for (i = 0; i < acl_int_new->acl_cnt; i++) { 8775928Sjedgar switch(acl_int_new->acl_entry[i].ae_tag) { 8875928Sjedgar case ACL_USER: 8975928Sjedgar case ACL_GROUP: 9074432Sjedgar case ACL_GROUP_OBJ: 9174432Sjedgar mask_mode |= 9275928Sjedgar acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS; 9374432Sjedgar break; 9474432Sjedgar case ACL_MASK: 9574432Sjedgar mask_num = i; 9674432Sjedgar break; 9774432Sjedgar } 9874432Sjedgar } 9975928Sjedgar 10074432Sjedgar /* if a mask entry already exists, overwrite the perms */ 10175928Sjedgar if (mask_num != -1) 10275928Sjedgar acl_int_new->acl_entry[mask_num].ae_perm = mask_mode; 10375928Sjedgar else { 10474432Sjedgar /* if no mask exists, check acl_cnt... */ 10575928Sjedgar if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) { 10675928Sjedgar errno = ENOMEM; 10790781Sjedgar return (-1); 10874432Sjedgar } 10974432Sjedgar /* ...and add the mask entry */ 11075928Sjedgar acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK; 11175928Sjedgar acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id = 11275928Sjedgar ACL_UNDEFINED_ID; 11375928Sjedgar acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm = 11475928Sjedgar mask_mode; 11575928Sjedgar acl_int_new->acl_cnt++; 11674432Sjedgar } 11774432Sjedgar 11874432Sjedgar if (acl_valid(acl_new) == -1) { 11974432Sjedgar errno = EINVAL; 12074432Sjedgar acl_free(acl_new); 12190781Sjedgar return (-1); 12274432Sjedgar } 12374432Sjedgar 12474432Sjedgar **acl_p = *acl_new; 12574432Sjedgar acl_free(acl_new); 12674432Sjedgar 12790781Sjedgar return (0); 12874432Sjedgar} 129