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$"); 29194955Strasz 30194955Strasz#include <errno.h> 31194955Strasz#include <stdio.h> 32194955Strasz#include <assert.h> 33194955Strasz#include <sys/acl.h> 34212906Strasz#include <sys/stat.h> 35194955Strasz 36194955Strasz#include "acl_support.h" 37194955Strasz 38194955Strasz/* 39219878Strasz * These routines from sys/kern/subr_acl_nfs4.c are used by both kernel 40194955Strasz * and libc. 41194955Strasz */ 42194955Straszvoid acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp); 43219878Straszvoid acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int file_owner_id, 44219878Strasz int canonical_six); 45194955Strasz 46194955Straszstatic acl_t 47212906Strasz_nfs4_acl_strip_np(const acl_t aclp, int canonical_six) 48194955Strasz{ 49194955Strasz acl_t newacl; 50208784Strasz mode_t mode = 0; 51194955Strasz 52194955Strasz newacl = acl_init(ACL_MAX_ENTRIES); 53194955Strasz if (newacl == NULL) { 54194955Strasz errno = ENOMEM; 55194955Strasz return (NULL); 56194955Strasz } 57194955Strasz 58194955Strasz _acl_brand_as(newacl, ACL_BRAND_NFS4); 59194955Strasz 60194955Strasz acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl)); 61219878Strasz acl_nfs4_trivial_from_mode_libc(&(newacl->ats_acl), mode, canonical_six); 62194955Strasz 63194955Strasz return (newacl); 64194955Strasz} 65194955Strasz 66194955Straszstatic acl_t 67194955Strasz_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask) 68194955Strasz{ 69194955Strasz acl_t acl_new, acl_old; 70194955Strasz acl_entry_t entry, entry_new; 71194955Strasz acl_permset_t perm; 72194955Strasz acl_tag_t tag; 73194955Strasz int entry_id, have_mask_entry; 74194955Strasz 75194955Strasz assert(_acl_brand(aclp) == ACL_BRAND_POSIX); 76194955Strasz 77194955Strasz acl_old = acl_dup(aclp); 78194955Strasz if (acl_old == NULL) 79194955Strasz return (NULL); 80194955Strasz 81194955Strasz assert(_acl_brand(acl_old) == ACL_BRAND_POSIX); 82194955Strasz 83194955Strasz have_mask_entry = 0; 84194955Strasz acl_new = acl_init(ACL_MAX_ENTRIES); 85194955Strasz if (acl_new == NULL) 86194955Strasz return (NULL); 87194955Strasz tag = ACL_UNDEFINED_TAG; 88194955Strasz 89194955Strasz /* only save the default user/group/other entries */ 90194955Strasz entry_id = ACL_FIRST_ENTRY; 91194955Strasz while (acl_get_entry(acl_old, entry_id, &entry) == 1) { 92194955Strasz entry_id = ACL_NEXT_ENTRY; 93194955Strasz 94194955Strasz assert(_entry_brand(entry) == ACL_BRAND_POSIX); 95194955Strasz 96194955Strasz if (acl_get_tag_type(entry, &tag) == -1) 97194955Strasz return (NULL); 98194955Strasz 99194955Strasz switch(tag) { 100194955Strasz case ACL_USER_OBJ: 101194955Strasz case ACL_GROUP_OBJ: 102194955Strasz case ACL_OTHER: 103194955Strasz if (acl_get_tag_type(entry, &tag) == -1) 104194955Strasz return (NULL); 105194955Strasz if (acl_get_permset(entry, &perm) == -1) 106194955Strasz return (NULL); 107194955Strasz if (acl_create_entry(&acl_new, &entry_new) == -1) 108194955Strasz return (NULL); 109194955Strasz if (acl_set_tag_type(entry_new, tag) == -1) 110194955Strasz return (NULL); 111194955Strasz if (acl_set_permset(entry_new, perm) == -1) 112194955Strasz return (NULL); 113194955Strasz if (acl_copy_entry(entry_new, entry) == -1) 114194955Strasz return (NULL); 115194955Strasz assert(_entry_brand(entry_new) == ACL_BRAND_POSIX); 116194955Strasz break; 117194955Strasz case ACL_MASK: 118194955Strasz have_mask_entry = 1; 119194955Strasz break; 120194955Strasz default: 121194955Strasz break; 122194955Strasz } 123194955Strasz } 124194955Strasz 125194955Strasz assert(_acl_brand(acl_new) == ACL_BRAND_POSIX); 126194955Strasz 127194955Strasz if (have_mask_entry && recalculate_mask) { 128194955Strasz if (acl_calc_mask(&acl_new) == -1) 129194955Strasz return (NULL); 130194955Strasz } 131194955Strasz 132194955Strasz return (acl_new); 133194955Strasz} 134194955Strasz 135194955Straszacl_t 136194955Straszacl_strip_np(const acl_t aclp, int recalculate_mask) 137194955Strasz{ 138194955Strasz switch (_acl_brand(aclp)) { 139194955Strasz case ACL_BRAND_NFS4: 140219268Strasz return (_nfs4_acl_strip_np(aclp, 0)); 141194955Strasz 142194955Strasz case ACL_BRAND_POSIX: 143194955Strasz return (_posix1e_acl_strip_np(aclp, recalculate_mask)); 144194955Strasz 145194955Strasz default: 146194955Strasz errno = EINVAL; 147194955Strasz return (NULL); 148194955Strasz } 149194955Strasz} 150194955Strasz 151194955Strasz/* 152194955Strasz * Return 1, if ACL is trivial, 0 otherwise. 153194955Strasz * 154194955Strasz * ACL is trivial, iff its meaning could be fully expressed using just file 155194955Strasz * mode. In other words, ACL is trivial iff it doesn't have "+" to the right 156194955Strasz * of the mode bits in "ls -l" output ;-) 157194955Strasz */ 158194955Straszint 159194955Straszacl_is_trivial_np(const acl_t aclp, int *trivialp) 160194955Strasz{ 161194955Strasz acl_t tmpacl; 162194955Strasz int differs; 163194955Strasz 164194955Strasz if (aclp == NULL || trivialp == NULL) { 165194955Strasz errno = EINVAL; 166194955Strasz return (-1); 167194955Strasz } 168194955Strasz 169194955Strasz switch (_acl_brand(aclp)) { 170194955Strasz case ACL_BRAND_POSIX: 171194955Strasz if (aclp->ats_acl.acl_cnt == 3) 172194955Strasz *trivialp = 1; 173194955Strasz else 174194955Strasz *trivialp = 0; 175194955Strasz 176194955Strasz return (0); 177194955Strasz 178194955Strasz case ACL_BRAND_NFS4: 179194955Strasz /* 180212376Strasz * If the ACL has more than canonical six entries, 181212376Strasz * it's non trivial by definition. 182212376Strasz */ 183212376Strasz if (aclp->ats_acl.acl_cnt > 6) { 184212379Strasz *trivialp = 0; 185212376Strasz return (0); 186212376Strasz } 187212376Strasz 188212376Strasz /* 189212906Strasz * Calculate trivial ACL - using acl_strip_np(3) - and compare 190194955Strasz * with the original. 191194955Strasz */ 192212906Strasz tmpacl = _nfs4_acl_strip_np(aclp, 0); 193194955Strasz if (tmpacl == NULL) 194194955Strasz return (-1); 195194955Strasz 196194955Strasz differs = _acl_differs(aclp, tmpacl); 197194955Strasz acl_free(tmpacl); 198194955Strasz 199212906Strasz if (differs == 0) { 200212906Strasz *trivialp = 1; 201212906Strasz return (0); 202212906Strasz } 203212906Strasz 204212906Strasz /* 205212906Strasz * Try again with an old-style, "canonical six" trivial ACL. 206212906Strasz */ 207212906Strasz tmpacl = _nfs4_acl_strip_np(aclp, 1); 208212906Strasz if (tmpacl == NULL) 209212906Strasz return (-1); 210212906Strasz 211212906Strasz differs = _acl_differs(aclp, tmpacl); 212212906Strasz acl_free(tmpacl); 213212906Strasz 214194955Strasz if (differs) 215194955Strasz *trivialp = 0; 216194955Strasz else 217194955Strasz *trivialp = 1; 218194955Strasz 219194955Strasz return (0); 220194955Strasz 221194955Strasz default: 222194955Strasz errno = EINVAL; 223194955Strasz return (-1); 224194955Strasz } 225194955Strasz} 226