acl_strip.c revision 212906
1266072Sdes/*- 2266072Sdes * Copyright (c) 2001 Chris D. Faulhaber 3285206Sdes * All rights reserved. 4266072Sdes * 5266072Sdes * Redistribution and use in source and binary forms, with or without 6266072Sdes * modification, are permitted provided that the following conditions 7266072Sdes * are met: 8266072Sdes * 1. Redistributions of source code must retain the above copyright 9266072Sdes * notice, this list of conditions and the following disclaimer. 10266072Sdes * 2. Redistributions in binary form must reproduce the above copyright 11285206Sdes * notice, this list of conditions and the following disclaimer in the 12285206Sdes * documentation and/or other materials provided with the distribution. 13285206Sdes * 14285206Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15285206Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16285206Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17285206Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18285206Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19266072Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20285206Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21285206Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22285206Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23285206Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24266072Sdes * SUCH DAMAGE. 25285206Sdes */ 26285206Sdes 27266072Sdes#include <sys/cdefs.h> 28266072Sdes__FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_strip.c 212906 2010-09-20 17:10:06Z trasz $"); 29266072Sdes 30266072Sdes#include <errno.h> 31285206Sdes#include <stdio.h> 32266072Sdes#include <assert.h> 33266072Sdes#include <sys/acl.h> 34285206Sdes#include <sys/stat.h> 35266072Sdes 36266072Sdes#include "acl_support.h" 37266072Sdes 38266072Sdes/* 39266072Sdes * These three routines from sys/kern/subr_acl_nfs4.c are used by both kernel 40266072Sdes * and libc. 41266072Sdes */ 42266072Sdesvoid acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode); 43266072Sdesvoid acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode, 44266072Sdes int file_owner_id); 45266072Sdesvoid acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp); 46266072Sdes 47266072Sdesstatic acl_t 48266072Sdes_nfs4_acl_strip_np(const acl_t aclp, int canonical_six) 49266072Sdes{ 50266072Sdes acl_t newacl; 51266072Sdes mode_t mode = 0; 52266072Sdes 53266072Sdes newacl = acl_init(ACL_MAX_ENTRIES); 54266072Sdes if (newacl == NULL) { 55266072Sdes errno = ENOMEM; 56266072Sdes return (NULL); 57266072Sdes } 58266072Sdes 59266072Sdes _acl_brand_as(newacl, ACL_BRAND_NFS4); 60266072Sdes 61266072Sdes acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl)); 62285206Sdes if (canonical_six) 63266072Sdes acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1); 64266072Sdes else 65266072Sdes acl_nfs4_trivial_from_mode(&(newacl->ats_acl), mode); 66266072Sdes 67266072Sdes return (newacl); 68266072Sdes} 69266072Sdes 70266072Sdesstatic acl_t 71266072Sdes_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask) 72266072Sdes{ 73266072Sdes acl_t acl_new, acl_old; 74266072Sdes acl_entry_t entry, entry_new; 75266072Sdes acl_permset_t perm; 76266072Sdes acl_tag_t tag; 77266072Sdes int entry_id, have_mask_entry; 78266072Sdes 79266072Sdes assert(_acl_brand(aclp) == ACL_BRAND_POSIX); 80266072Sdes 81266072Sdes acl_old = acl_dup(aclp); 82266072Sdes if (acl_old == NULL) 83266072Sdes return (NULL); 84266072Sdes 85266072Sdes assert(_acl_brand(acl_old) == ACL_BRAND_POSIX); 86285206Sdes 87266072Sdes have_mask_entry = 0; 88266072Sdes acl_new = acl_init(ACL_MAX_ENTRIES); 89266072Sdes if (acl_new == NULL) 90266072Sdes return (NULL); 91266072Sdes tag = ACL_UNDEFINED_TAG; 92266072Sdes 93266072Sdes /* only save the default user/group/other entries */ 94266072Sdes entry_id = ACL_FIRST_ENTRY; 95266072Sdes while (acl_get_entry(acl_old, entry_id, &entry) == 1) { 96266072Sdes entry_id = ACL_NEXT_ENTRY; 97266072Sdes 98266072Sdes assert(_entry_brand(entry) == ACL_BRAND_POSIX); 99266072Sdes 100266072Sdes if (acl_get_tag_type(entry, &tag) == -1) 101266072Sdes return (NULL); 102266072Sdes 103266072Sdes switch(tag) { 104266072Sdes case ACL_USER_OBJ: 105266072Sdes case ACL_GROUP_OBJ: 106285206Sdes case ACL_OTHER: 107285206Sdes if (acl_get_tag_type(entry, &tag) == -1) 108285206Sdes return (NULL); 109285206Sdes if (acl_get_permset(entry, &perm) == -1) 110285206Sdes return (NULL); 111285206Sdes if (acl_create_entry(&acl_new, &entry_new) == -1) 112285206Sdes return (NULL); 113285206Sdes if (acl_set_tag_type(entry_new, tag) == -1) 114285206Sdes return (NULL); 115285206Sdes if (acl_set_permset(entry_new, perm) == -1) 116285206Sdes return (NULL); 117285206Sdes if (acl_copy_entry(entry_new, entry) == -1) 118285206Sdes return (NULL); 119285206Sdes assert(_entry_brand(entry_new) == ACL_BRAND_POSIX); 120285206Sdes break; 121285206Sdes case ACL_MASK: 122285206Sdes have_mask_entry = 1; 123285206Sdes break; 124285206Sdes default: 125266072Sdes break; 126266072Sdes } 127285206Sdes } 128285206Sdes 129285206Sdes assert(_acl_brand(acl_new) == ACL_BRAND_POSIX); 130266072Sdes 131285206Sdes if (have_mask_entry && recalculate_mask) { 132285206Sdes if (acl_calc_mask(&acl_new) == -1) 133285206Sdes return (NULL); 134285206Sdes } 135285206Sdes 136266072Sdes return (acl_new); 137266072Sdes} 138266072Sdes 139266072Sdesacl_t 140266072Sdesacl_strip_np(const acl_t aclp, int recalculate_mask) 141266072Sdes{ 142285206Sdes switch (_acl_brand(aclp)) { 143266072Sdes case ACL_BRAND_NFS4: 144266072Sdes return (_nfs4_acl_strip_np(aclp, 1)); 145266072Sdes 146266072Sdes case ACL_BRAND_POSIX: 147266072Sdes return (_posix1e_acl_strip_np(aclp, recalculate_mask)); 148266072Sdes 149266072Sdes default: 150266072Sdes errno = EINVAL; 151266072Sdes return (NULL); 152266072Sdes } 153266072Sdes} 154266072Sdes 155266072Sdes/* 156266072Sdes * Return 1, if ACL is trivial, 0 otherwise. 157266072Sdes * 158266072Sdes * ACL is trivial, iff its meaning could be fully expressed using just file 159266072Sdes * mode. In other words, ACL is trivial iff it doesn't have "+" to the right 160266072Sdes * of the mode bits in "ls -l" output ;-) 161266072Sdes */ 162266072Sdesint 163266072Sdesacl_is_trivial_np(const acl_t aclp, int *trivialp) 164266072Sdes{ 165266072Sdes acl_t tmpacl; 166266072Sdes int differs; 167266072Sdes 168266072Sdes if (aclp == NULL || trivialp == NULL) { 169266072Sdes errno = EINVAL; 170266072Sdes return (-1); 171266072Sdes } 172266072Sdes 173266072Sdes switch (_acl_brand(aclp)) { 174266072Sdes case ACL_BRAND_POSIX: 175266072Sdes if (aclp->ats_acl.acl_cnt == 3) 176266072Sdes *trivialp = 1; 177266072Sdes else 178266072Sdes *trivialp = 0; 179266072Sdes 180266072Sdes return (0); 181266072Sdes 182266072Sdes case ACL_BRAND_NFS4: 183266072Sdes /* 184266072Sdes * If the ACL has more than canonical six entries, 185266072Sdes * it's non trivial by definition. 186266072Sdes */ 187266072Sdes if (aclp->ats_acl.acl_cnt > 6) { 188266072Sdes *trivialp = 0; 189285206Sdes return (0); 190266072Sdes } 191266072Sdes 192285206Sdes /* 193266072Sdes * Calculate trivial ACL - using acl_strip_np(3) - and compare 194285206Sdes * with the original. 195266072Sdes */ 196266072Sdes tmpacl = _nfs4_acl_strip_np(aclp, 0); 197266072Sdes if (tmpacl == NULL) 198285206Sdes return (-1); 199266072Sdes 200266072Sdes differs = _acl_differs(aclp, tmpacl); 201266072Sdes acl_free(tmpacl); 202266072Sdes 203266072Sdes if (differs == 0) { 204266072Sdes *trivialp = 1; 205266072Sdes return (0); 206266072Sdes } 207266072Sdes 208266072Sdes /* 209266072Sdes * Try again with an old-style, "canonical six" trivial ACL. 210266072Sdes */ 211285206Sdes tmpacl = _nfs4_acl_strip_np(aclp, 1); 212266072Sdes if (tmpacl == NULL) 213266072Sdes return (-1); 214266072Sdes 215266072Sdes differs = _acl_differs(aclp, tmpacl); 216266072Sdes acl_free(tmpacl); 217266072Sdes 218266072Sdes if (differs) 219266072Sdes *trivialp = 0; 220266072Sdes else 221266072Sdes *trivialp = 1; 222285206Sdes 223266072Sdes return (0); 224266072Sdes 225266072Sdes default: 226285206Sdes errno = EINVAL; 227266072Sdes return (-1); 228285206Sdes } 229285206Sdes} 230266072Sdes