acl_strip.c revision 204819
1194955Strasz/*- 2194955Strasz * Copyright (c) 2001 Chris D. Faulhaber 3194955Strasz * All rights reserved. 4194955Strasz * 5194955Strasz * Redistribution and use in source and binary forms, with or without 6194955Strasz * modification, are permitted provided that the following conditions 7194955Strasz * are met: 8194955Strasz * 1. Redistributions of source code must retain the above copyright 9194955Strasz * notice, this list of conditions and the following disclaimer. 10194955Strasz * 2. Redistributions in binary form must reproduce the above copyright 11194955Strasz * notice, this list of conditions and the following disclaimer in the 12194955Strasz * documentation and/or other materials provided with the distribution. 13194955Strasz * 14194955Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15194955Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16194955Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17204819Sjoel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18204819Sjoel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19204819Sjoel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20204819Sjoel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21204819Sjoel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22204819Sjoel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23204819Sjoel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24204819Sjoel * SUCH DAMAGE. 25194955Strasz */ 26194955Strasz 27194955Strasz#include <sys/cdefs.h> 28194955Strasz__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_strip.c 204819 2010-03-07 07:59:05Z joel $"); 29194955Strasz 30194955Strasz#include <errno.h> 31194955Strasz#include <stdio.h> 32194955Strasz#include <assert.h> 33194955Strasz#include <sys/acl.h> 34194955Strasz 35194955Strasz#include "acl_support.h" 36194955Strasz 37194955Strasz/* 38194955Strasz * These two routines from sys/kern/subr_acl_nfs4.c are used by both kernel 39194955Strasz * and libc. 40194955Strasz */ 41194955Straszvoid acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode, 42194955Strasz int file_owner_id); 43194955Straszvoid acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp); 44194955Strasz 45194955Straszstatic acl_t 46194955Strasz_nfs4_acl_strip_np(const acl_t aclp, int recalculate_mask) 47194955Strasz{ 48194955Strasz acl_t newacl; 49194955Strasz mode_t mode; 50194955Strasz 51194955Strasz newacl = acl_init(ACL_MAX_ENTRIES); 52194955Strasz if (newacl == NULL) { 53194955Strasz errno = ENOMEM; 54194955Strasz return (NULL); 55194955Strasz } 56194955Strasz 57194955Strasz _acl_brand_as(newacl, ACL_BRAND_NFS4); 58194955Strasz 59194955Strasz acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl)); 60194955Strasz acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1); 61194955Strasz 62194955Strasz return (newacl); 63194955Strasz} 64194955Strasz 65194955Straszstatic acl_t 66194955Strasz_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask) 67194955Strasz{ 68194955Strasz acl_t acl_new, acl_old; 69194955Strasz acl_entry_t entry, entry_new; 70194955Strasz acl_permset_t perm; 71194955Strasz acl_tag_t tag; 72194955Strasz int entry_id, have_mask_entry; 73194955Strasz 74194955Strasz assert(_acl_brand(aclp) == ACL_BRAND_POSIX); 75194955Strasz 76194955Strasz acl_old = acl_dup(aclp); 77194955Strasz if (acl_old == NULL) 78194955Strasz return (NULL); 79194955Strasz 80194955Strasz assert(_acl_brand(acl_old) == ACL_BRAND_POSIX); 81194955Strasz 82194955Strasz have_mask_entry = 0; 83194955Strasz acl_new = acl_init(ACL_MAX_ENTRIES); 84194955Strasz if (acl_new == NULL) 85194955Strasz return (NULL); 86194955Strasz tag = ACL_UNDEFINED_TAG; 87194955Strasz 88194955Strasz /* only save the default user/group/other entries */ 89194955Strasz entry_id = ACL_FIRST_ENTRY; 90194955Strasz while (acl_get_entry(acl_old, entry_id, &entry) == 1) { 91194955Strasz entry_id = ACL_NEXT_ENTRY; 92194955Strasz 93194955Strasz assert(_entry_brand(entry) == ACL_BRAND_POSIX); 94194955Strasz 95194955Strasz if (acl_get_tag_type(entry, &tag) == -1) 96194955Strasz return (NULL); 97194955Strasz 98194955Strasz switch(tag) { 99194955Strasz case ACL_USER_OBJ: 100194955Strasz case ACL_GROUP_OBJ: 101194955Strasz case ACL_OTHER: 102194955Strasz if (acl_get_tag_type(entry, &tag) == -1) 103194955Strasz return (NULL); 104194955Strasz if (acl_get_permset(entry, &perm) == -1) 105194955Strasz return (NULL); 106194955Strasz if (acl_create_entry(&acl_new, &entry_new) == -1) 107194955Strasz return (NULL); 108194955Strasz if (acl_set_tag_type(entry_new, tag) == -1) 109194955Strasz return (NULL); 110194955Strasz if (acl_set_permset(entry_new, perm) == -1) 111194955Strasz return (NULL); 112194955Strasz if (acl_copy_entry(entry_new, entry) == -1) 113194955Strasz return (NULL); 114194955Strasz assert(_entry_brand(entry_new) == ACL_BRAND_POSIX); 115194955Strasz break; 116194955Strasz case ACL_MASK: 117194955Strasz have_mask_entry = 1; 118194955Strasz break; 119194955Strasz default: 120194955Strasz break; 121194955Strasz } 122194955Strasz } 123194955Strasz 124194955Strasz assert(_acl_brand(acl_new) == ACL_BRAND_POSIX); 125194955Strasz 126194955Strasz if (have_mask_entry && recalculate_mask) { 127194955Strasz if (acl_calc_mask(&acl_new) == -1) 128194955Strasz return (NULL); 129194955Strasz } 130194955Strasz 131194955Strasz return (acl_new); 132194955Strasz} 133194955Strasz 134194955Straszacl_t 135194955Straszacl_strip_np(const acl_t aclp, int recalculate_mask) 136194955Strasz{ 137194955Strasz switch (_acl_brand(aclp)) { 138194955Strasz case ACL_BRAND_NFS4: 139194955Strasz return (_nfs4_acl_strip_np(aclp, recalculate_mask)); 140194955Strasz 141194955Strasz case ACL_BRAND_POSIX: 142194955Strasz return (_posix1e_acl_strip_np(aclp, recalculate_mask)); 143194955Strasz 144194955Strasz default: 145194955Strasz errno = EINVAL; 146194955Strasz return (NULL); 147194955Strasz } 148194955Strasz} 149194955Strasz 150194955Strasz/* 151194955Strasz * Return 1, if ACL is trivial, 0 otherwise. 152194955Strasz * 153194955Strasz * ACL is trivial, iff its meaning could be fully expressed using just file 154194955Strasz * mode. In other words, ACL is trivial iff it doesn't have "+" to the right 155194955Strasz * of the mode bits in "ls -l" output ;-) 156194955Strasz */ 157194955Straszint 158194955Straszacl_is_trivial_np(const acl_t aclp, int *trivialp) 159194955Strasz{ 160194955Strasz acl_t tmpacl; 161194955Strasz int differs; 162194955Strasz 163194955Strasz if (aclp == NULL || trivialp == NULL) { 164194955Strasz errno = EINVAL; 165194955Strasz return (-1); 166194955Strasz } 167194955Strasz 168194955Strasz switch (_acl_brand(aclp)) { 169194955Strasz case ACL_BRAND_POSIX: 170194955Strasz if (aclp->ats_acl.acl_cnt == 3) 171194955Strasz *trivialp = 1; 172194955Strasz else 173194955Strasz *trivialp = 0; 174194955Strasz 175194955Strasz return (0); 176194955Strasz 177194955Strasz case ACL_BRAND_NFS4: 178194955Strasz /* 179194955Strasz * Calculate trivial ACL - using acl_strip_np - and compare 180194955Strasz * with the original. 181194955Strasz */ 182194955Strasz tmpacl = acl_strip_np(aclp, 0); 183194955Strasz if (tmpacl == NULL) 184194955Strasz return (-1); 185194955Strasz 186194955Strasz differs = _acl_differs(aclp, tmpacl); 187194955Strasz acl_free(tmpacl); 188194955Strasz 189194955Strasz if (differs) 190194955Strasz *trivialp = 0; 191194955Strasz else 192194955Strasz *trivialp = 1; 193194955Strasz 194194955Strasz return (0); 195194955Strasz 196194955Strasz default: 197194955Strasz errno = EINVAL; 198194955Strasz return (-1); 199194955Strasz } 200194955Strasz} 201