1192800Strasz/*- 2192800Strasz * Copyright (c) 2008, 2009 Edward Tomasz Napiera��a <trasz@FreeBSD.org> 3192800Strasz * All rights reserved. 4192800Strasz * 5192800Strasz * Redistribution and use in source and binary forms, with or without 6192800Strasz * modification, are permitted provided that the following conditions 7192800Strasz * are met: 8192800Strasz * 1. Redistributions of source code must retain the above copyright 9192800Strasz * notice, this list of conditions and the following disclaimer. 10192800Strasz * 2. Redistributions in binary form must reproduce the above copyright 11192800Strasz * notice, this list of conditions and the following disclaimer in the 12192800Strasz * documentation and/or other materials provided with the distribution. 13192800Strasz * 14192804Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15192804Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16192804Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17192804Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18192804Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19192804Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20192804Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21192804Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22192804Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23192804Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24192804Strasz * SUCH DAMAGE. 25192800Strasz */ 26192800Strasz 27192800Strasz#include <sys/cdefs.h> 28192800Strasz__FBSDID("$FreeBSD$"); 29192800Strasz 30192800Strasz#include <sys/param.h> 31192800Strasz#include <sys/systm.h> 32192800Strasz#include <sys/types.h> 33192800Strasz#include <sys/malloc.h> 34192800Strasz#include <sys/errno.h> 35192800Strasz#include <sys/zfs_acl.h> 36192800Strasz#include <sys/acl.h> 37192800Strasz 38192800Straszstruct zfs2bsd { 39192800Strasz uint32_t zb_zfs; 40192800Strasz int zb_bsd; 41192800Strasz}; 42192800Strasz 43192800Straszstruct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA}, 44192800Strasz {ACE_WRITE_DATA, ACL_WRITE_DATA}, 45192800Strasz {ACE_EXECUTE, ACL_EXECUTE}, 46192800Strasz {ACE_APPEND_DATA, ACL_APPEND_DATA}, 47192800Strasz {ACE_DELETE_CHILD, ACL_DELETE_CHILD}, 48192800Strasz {ACE_DELETE, ACL_DELETE}, 49192800Strasz {ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 50192800Strasz {ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 51192800Strasz {ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 52192800Strasz {ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 53192800Strasz {ACE_READ_ACL, ACL_READ_ACL}, 54192800Strasz {ACE_WRITE_ACL, ACL_WRITE_ACL}, 55192800Strasz {ACE_WRITE_OWNER, ACL_WRITE_OWNER}, 56192800Strasz {ACE_SYNCHRONIZE, ACL_SYNCHRONIZE}, 57192800Strasz {0, 0}}; 58192800Strasz 59192800Straszstruct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE, 60192800Strasz ACL_ENTRY_FILE_INHERIT}, 61192800Strasz {ACE_DIRECTORY_INHERIT_ACE, 62192800Strasz ACL_ENTRY_DIRECTORY_INHERIT}, 63192800Strasz {ACE_NO_PROPAGATE_INHERIT_ACE, 64192800Strasz ACL_ENTRY_NO_PROPAGATE_INHERIT}, 65192800Strasz {ACE_INHERIT_ONLY_ACE, 66192800Strasz ACL_ENTRY_INHERIT_ONLY}, 67290893Sngie {ACE_INHERITED_ACE, 68290893Sngie ACL_ENTRY_INHERITED}, 69192800Strasz {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, 70192800Strasz ACL_ENTRY_SUCCESSFUL_ACCESS}, 71192800Strasz {ACE_FAILED_ACCESS_ACE_FLAG, 72192800Strasz ACL_ENTRY_FAILED_ACCESS}, 73192800Strasz {0, 0}}; 74192800Strasz 75192800Straszstatic int 76192800Strasz_bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) 77192800Strasz{ 78192800Strasz const struct zfs2bsd *tmp; 79192800Strasz int bsd = 0; 80192800Strasz 81192800Strasz for (tmp = table; tmp->zb_zfs != 0; tmp++) { 82192800Strasz if (zfs & tmp->zb_zfs) 83192800Strasz bsd |= tmp->zb_bsd; 84192800Strasz } 85192800Strasz 86192800Strasz return (bsd); 87192800Strasz} 88192800Strasz 89192800Straszstatic uint32_t 90192800Strasz_zfs_from_bsd(int bsd, const struct zfs2bsd *table) 91192800Strasz{ 92192800Strasz const struct zfs2bsd *tmp; 93192800Strasz uint32_t zfs = 0; 94192800Strasz 95192800Strasz for (tmp = table; tmp->zb_bsd != 0; tmp++) { 96192800Strasz if (bsd & tmp->zb_bsd) 97192800Strasz zfs |= tmp->zb_zfs; 98192800Strasz } 99192800Strasz 100192800Strasz return (zfs); 101192800Strasz} 102192800Strasz 103192800Straszint 104192800Straszacl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) 105192800Strasz{ 106192800Strasz int i; 107192800Strasz struct acl_entry *entry; 108192800Strasz const ace_t *ace; 109192800Strasz 110216084Strasz if (nentries < 1) { 111216084Strasz printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n"); 112216084Strasz return (EINVAL); 113216084Strasz } 114192800Strasz 115192800Strasz if (nentries > ACL_MAX_ENTRIES) { 116192800Strasz /* 117192800Strasz * I believe it may happen only when moving a pool 118192800Strasz * from SunOS to FreeBSD. 119192800Strasz */ 120192800Strasz printf("acl_from_aces: ZFS ACL too big to fit " 121192800Strasz "into 'struct acl'; returning EINVAL.\n"); 122192800Strasz return (EINVAL); 123192800Strasz } 124192800Strasz 125192800Strasz bzero(aclp, sizeof(*aclp)); 126192800Strasz aclp->acl_maxcnt = ACL_MAX_ENTRIES; 127192800Strasz aclp->acl_cnt = nentries; 128192800Strasz 129192800Strasz for (i = 0; i < nentries; i++) { 130192800Strasz entry = &(aclp->acl_entry[i]); 131192800Strasz ace = &(aces[i]); 132192800Strasz 133192800Strasz if (ace->a_flags & ACE_OWNER) 134192800Strasz entry->ae_tag = ACL_USER_OBJ; 135192800Strasz else if (ace->a_flags & ACE_GROUP) 136192800Strasz entry->ae_tag = ACL_GROUP_OBJ; 137192800Strasz else if (ace->a_flags & ACE_EVERYONE) 138192800Strasz entry->ae_tag = ACL_EVERYONE; 139192800Strasz else if (ace->a_flags & ACE_IDENTIFIER_GROUP) 140192800Strasz entry->ae_tag = ACL_GROUP; 141192800Strasz else 142192800Strasz entry->ae_tag = ACL_USER; 143192800Strasz 144192800Strasz if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) 145192800Strasz entry->ae_id = ace->a_who; 146192800Strasz else 147192800Strasz entry->ae_id = ACL_UNDEFINED_ID; 148192800Strasz 149192800Strasz entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); 150192800Strasz entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); 151192800Strasz 152192800Strasz switch (ace->a_type) { 153192800Strasz case ACE_ACCESS_ALLOWED_ACE_TYPE: 154192800Strasz entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 155192800Strasz break; 156192800Strasz case ACE_ACCESS_DENIED_ACE_TYPE: 157192800Strasz entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; 158192800Strasz break; 159192800Strasz case ACE_SYSTEM_AUDIT_ACE_TYPE: 160192800Strasz entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 161192800Strasz break; 162192800Strasz case ACE_SYSTEM_ALARM_ACE_TYPE: 163192800Strasz entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 164192800Strasz break; 165192800Strasz default: 166192800Strasz panic("acl_from_aces: a_type is 0x%x", ace->a_type); 167192800Strasz } 168192800Strasz } 169192800Strasz 170192800Strasz return (0); 171192800Strasz} 172192800Strasz 173192800Straszvoid 174192800Straszaces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) 175192800Strasz{ 176192800Strasz int i; 177192800Strasz const struct acl_entry *entry; 178192800Strasz ace_t *ace; 179192800Strasz 180192800Strasz bzero(aces, sizeof(*aces) * aclp->acl_cnt); 181192800Strasz 182192800Strasz *nentries = aclp->acl_cnt; 183192800Strasz 184192800Strasz for (i = 0; i < aclp->acl_cnt; i++) { 185192800Strasz entry = &(aclp->acl_entry[i]); 186192800Strasz ace = &(aces[i]); 187192800Strasz 188192800Strasz ace->a_who = entry->ae_id; 189192800Strasz 190192800Strasz if (entry->ae_tag == ACL_USER_OBJ) 191192800Strasz ace->a_flags = ACE_OWNER; 192192800Strasz else if (entry->ae_tag == ACL_GROUP_OBJ) 193192800Strasz ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); 194192800Strasz else if (entry->ae_tag == ACL_GROUP) 195192800Strasz ace->a_flags = ACE_IDENTIFIER_GROUP; 196192800Strasz else if (entry->ae_tag == ACL_EVERYONE) 197192800Strasz ace->a_flags = ACE_EVERYONE; 198192800Strasz else /* ACL_USER */ 199192800Strasz ace->a_flags = 0; 200192800Strasz 201192800Strasz ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); 202192800Strasz ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); 203192800Strasz 204192800Strasz switch (entry->ae_entry_type) { 205192800Strasz case ACL_ENTRY_TYPE_ALLOW: 206192800Strasz ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 207192800Strasz break; 208192800Strasz case ACL_ENTRY_TYPE_DENY: 209192800Strasz ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 210192800Strasz break; 211192800Strasz case ACL_ENTRY_TYPE_ALARM: 212192800Strasz ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; 213192800Strasz break; 214192800Strasz case ACL_ENTRY_TYPE_AUDIT: 215192800Strasz ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; 216192800Strasz break; 217192800Strasz default: 218192800Strasz panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type); 219192800Strasz } 220192800Strasz } 221192800Strasz} 222