10970b4baSEdward Tomasz Napierala /*- 20970b4baSEdward Tomasz Napierala * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 30970b4baSEdward Tomasz Napierala * All rights reserved. 40970b4baSEdward Tomasz Napierala * 50970b4baSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 60970b4baSEdward Tomasz Napierala * modification, are permitted provided that the following conditions 70970b4baSEdward Tomasz Napierala * are met: 80970b4baSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 90970b4baSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 100970b4baSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 110970b4baSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 120970b4baSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 130970b4baSEdward Tomasz Napierala * 14b7014134SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15b7014134SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16b7014134SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17b7014134SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18b7014134SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19b7014134SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20b7014134SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21b7014134SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22b7014134SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23b7014134SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24b7014134SEdward Tomasz Napierala * SUCH DAMAGE. 250970b4baSEdward Tomasz Napierala */ 260970b4baSEdward Tomasz Napierala 270970b4baSEdward Tomasz Napierala #include <sys/cdefs.h> 280970b4baSEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 290970b4baSEdward Tomasz Napierala 300970b4baSEdward Tomasz Napierala #include <sys/param.h> 310970b4baSEdward Tomasz Napierala #include <sys/systm.h> 320970b4baSEdward Tomasz Napierala #include <sys/types.h> 330970b4baSEdward Tomasz Napierala #include <sys/malloc.h> 340970b4baSEdward Tomasz Napierala #include <sys/errno.h> 350970b4baSEdward Tomasz Napierala #include <sys/zfs_acl.h> 360970b4baSEdward Tomasz Napierala #include <sys/acl.h> 370970b4baSEdward Tomasz Napierala 380970b4baSEdward Tomasz Napierala struct zfs2bsd { 390970b4baSEdward Tomasz Napierala uint32_t zb_zfs; 400970b4baSEdward Tomasz Napierala int zb_bsd; 410970b4baSEdward Tomasz Napierala }; 420970b4baSEdward Tomasz Napierala 430970b4baSEdward Tomasz Napierala struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA}, 440970b4baSEdward Tomasz Napierala {ACE_WRITE_DATA, ACL_WRITE_DATA}, 450970b4baSEdward Tomasz Napierala {ACE_EXECUTE, ACL_EXECUTE}, 460970b4baSEdward Tomasz Napierala {ACE_APPEND_DATA, ACL_APPEND_DATA}, 470970b4baSEdward Tomasz Napierala {ACE_DELETE_CHILD, ACL_DELETE_CHILD}, 480970b4baSEdward Tomasz Napierala {ACE_DELETE, ACL_DELETE}, 490970b4baSEdward Tomasz Napierala {ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 500970b4baSEdward Tomasz Napierala {ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 510970b4baSEdward Tomasz Napierala {ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 520970b4baSEdward Tomasz Napierala {ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 530970b4baSEdward Tomasz Napierala {ACE_READ_ACL, ACL_READ_ACL}, 540970b4baSEdward Tomasz Napierala {ACE_WRITE_ACL, ACL_WRITE_ACL}, 550970b4baSEdward Tomasz Napierala {ACE_WRITE_OWNER, ACL_WRITE_OWNER}, 560970b4baSEdward Tomasz Napierala {ACE_SYNCHRONIZE, ACL_SYNCHRONIZE}, 570970b4baSEdward Tomasz Napierala {0, 0}}; 580970b4baSEdward Tomasz Napierala 590970b4baSEdward Tomasz Napierala struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE, 600970b4baSEdward Tomasz Napierala ACL_ENTRY_FILE_INHERIT}, 610970b4baSEdward Tomasz Napierala {ACE_DIRECTORY_INHERIT_ACE, 620970b4baSEdward Tomasz Napierala ACL_ENTRY_DIRECTORY_INHERIT}, 630970b4baSEdward Tomasz Napierala {ACE_NO_PROPAGATE_INHERIT_ACE, 640970b4baSEdward Tomasz Napierala ACL_ENTRY_NO_PROPAGATE_INHERIT}, 650970b4baSEdward Tomasz Napierala {ACE_INHERIT_ONLY_ACE, 660970b4baSEdward Tomasz Napierala ACL_ENTRY_INHERIT_ONLY}, 670970b4baSEdward Tomasz Napierala {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, 680970b4baSEdward Tomasz Napierala ACL_ENTRY_SUCCESSFUL_ACCESS}, 690970b4baSEdward Tomasz Napierala {ACE_FAILED_ACCESS_ACE_FLAG, 700970b4baSEdward Tomasz Napierala ACL_ENTRY_FAILED_ACCESS}, 710970b4baSEdward Tomasz Napierala {0, 0}}; 720970b4baSEdward Tomasz Napierala 730970b4baSEdward Tomasz Napierala static int 740970b4baSEdward Tomasz Napierala _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) 750970b4baSEdward Tomasz Napierala { 760970b4baSEdward Tomasz Napierala const struct zfs2bsd *tmp; 770970b4baSEdward Tomasz Napierala int bsd = 0; 780970b4baSEdward Tomasz Napierala 790970b4baSEdward Tomasz Napierala for (tmp = table; tmp->zb_zfs != 0; tmp++) { 800970b4baSEdward Tomasz Napierala if (zfs & tmp->zb_zfs) 810970b4baSEdward Tomasz Napierala bsd |= tmp->zb_bsd; 820970b4baSEdward Tomasz Napierala } 830970b4baSEdward Tomasz Napierala 840970b4baSEdward Tomasz Napierala return (bsd); 850970b4baSEdward Tomasz Napierala } 860970b4baSEdward Tomasz Napierala 870970b4baSEdward Tomasz Napierala static uint32_t 880970b4baSEdward Tomasz Napierala _zfs_from_bsd(int bsd, const struct zfs2bsd *table) 890970b4baSEdward Tomasz Napierala { 900970b4baSEdward Tomasz Napierala const struct zfs2bsd *tmp; 910970b4baSEdward Tomasz Napierala uint32_t zfs = 0; 920970b4baSEdward Tomasz Napierala 930970b4baSEdward Tomasz Napierala for (tmp = table; tmp->zb_bsd != 0; tmp++) { 940970b4baSEdward Tomasz Napierala if (bsd & tmp->zb_bsd) 950970b4baSEdward Tomasz Napierala zfs |= tmp->zb_zfs; 960970b4baSEdward Tomasz Napierala } 970970b4baSEdward Tomasz Napierala 980970b4baSEdward Tomasz Napierala return (zfs); 990970b4baSEdward Tomasz Napierala } 1000970b4baSEdward Tomasz Napierala 1010970b4baSEdward Tomasz Napierala int 1020970b4baSEdward Tomasz Napierala acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) 1030970b4baSEdward Tomasz Napierala { 1040970b4baSEdward Tomasz Napierala int i; 1050970b4baSEdward Tomasz Napierala struct acl_entry *entry; 1060970b4baSEdward Tomasz Napierala const ace_t *ace; 1070970b4baSEdward Tomasz Napierala 1080970b4baSEdward Tomasz Napierala KASSERT(nentries >= 1, ("empty ZFS ACL")); 1090970b4baSEdward Tomasz Napierala 1100970b4baSEdward Tomasz Napierala if (nentries > ACL_MAX_ENTRIES) { 1110970b4baSEdward Tomasz Napierala /* 1120970b4baSEdward Tomasz Napierala * I believe it may happen only when moving a pool 1130970b4baSEdward Tomasz Napierala * from SunOS to FreeBSD. 1140970b4baSEdward Tomasz Napierala */ 1150970b4baSEdward Tomasz Napierala printf("acl_from_aces: ZFS ACL too big to fit " 1160970b4baSEdward Tomasz Napierala "into 'struct acl'; returning EINVAL.\n"); 1170970b4baSEdward Tomasz Napierala return (EINVAL); 1180970b4baSEdward Tomasz Napierala } 1190970b4baSEdward Tomasz Napierala 1200970b4baSEdward Tomasz Napierala bzero(aclp, sizeof(*aclp)); 1210970b4baSEdward Tomasz Napierala aclp->acl_maxcnt = ACL_MAX_ENTRIES; 1220970b4baSEdward Tomasz Napierala aclp->acl_cnt = nentries; 1230970b4baSEdward Tomasz Napierala 1240970b4baSEdward Tomasz Napierala for (i = 0; i < nentries; i++) { 1250970b4baSEdward Tomasz Napierala entry = &(aclp->acl_entry[i]); 1260970b4baSEdward Tomasz Napierala ace = &(aces[i]); 1270970b4baSEdward Tomasz Napierala 1280970b4baSEdward Tomasz Napierala if (ace->a_flags & ACE_OWNER) 1290970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_USER_OBJ; 1300970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_GROUP) 1310970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_GROUP_OBJ; 1320970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_EVERYONE) 1330970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_EVERYONE; 1340970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_IDENTIFIER_GROUP) 1350970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_GROUP; 1360970b4baSEdward Tomasz Napierala else 1370970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_USER; 1380970b4baSEdward Tomasz Napierala 1390970b4baSEdward Tomasz Napierala if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) 1400970b4baSEdward Tomasz Napierala entry->ae_id = ace->a_who; 1410970b4baSEdward Tomasz Napierala else 1420970b4baSEdward Tomasz Napierala entry->ae_id = ACL_UNDEFINED_ID; 1430970b4baSEdward Tomasz Napierala 1440970b4baSEdward Tomasz Napierala entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); 1450970b4baSEdward Tomasz Napierala entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); 1460970b4baSEdward Tomasz Napierala 1470970b4baSEdward Tomasz Napierala switch (ace->a_type) { 1480970b4baSEdward Tomasz Napierala case ACE_ACCESS_ALLOWED_ACE_TYPE: 1490970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 1500970b4baSEdward Tomasz Napierala break; 1510970b4baSEdward Tomasz Napierala case ACE_ACCESS_DENIED_ACE_TYPE: 1520970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; 1530970b4baSEdward Tomasz Napierala break; 1540970b4baSEdward Tomasz Napierala case ACE_SYSTEM_AUDIT_ACE_TYPE: 1550970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 1560970b4baSEdward Tomasz Napierala break; 1570970b4baSEdward Tomasz Napierala case ACE_SYSTEM_ALARM_ACE_TYPE: 1580970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 1590970b4baSEdward Tomasz Napierala break; 1600970b4baSEdward Tomasz Napierala default: 1610970b4baSEdward Tomasz Napierala panic("acl_from_aces: a_type is 0x%x", ace->a_type); 1620970b4baSEdward Tomasz Napierala } 1630970b4baSEdward Tomasz Napierala } 1640970b4baSEdward Tomasz Napierala 1650970b4baSEdward Tomasz Napierala return (0); 1660970b4baSEdward Tomasz Napierala } 1670970b4baSEdward Tomasz Napierala 1680970b4baSEdward Tomasz Napierala void 1690970b4baSEdward Tomasz Napierala aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) 1700970b4baSEdward Tomasz Napierala { 1710970b4baSEdward Tomasz Napierala int i; 1720970b4baSEdward Tomasz Napierala const struct acl_entry *entry; 1730970b4baSEdward Tomasz Napierala ace_t *ace; 1740970b4baSEdward Tomasz Napierala 1750970b4baSEdward Tomasz Napierala bzero(aces, sizeof(*aces) * aclp->acl_cnt); 1760970b4baSEdward Tomasz Napierala 1770970b4baSEdward Tomasz Napierala *nentries = aclp->acl_cnt; 1780970b4baSEdward Tomasz Napierala 1790970b4baSEdward Tomasz Napierala for (i = 0; i < aclp->acl_cnt; i++) { 1800970b4baSEdward Tomasz Napierala entry = &(aclp->acl_entry[i]); 1810970b4baSEdward Tomasz Napierala ace = &(aces[i]); 1820970b4baSEdward Tomasz Napierala 1830970b4baSEdward Tomasz Napierala ace->a_who = entry->ae_id; 1840970b4baSEdward Tomasz Napierala 1850970b4baSEdward Tomasz Napierala if (entry->ae_tag == ACL_USER_OBJ) 1860970b4baSEdward Tomasz Napierala ace->a_flags = ACE_OWNER; 1870970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_GROUP_OBJ) 1880970b4baSEdward Tomasz Napierala ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); 1890970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_GROUP) 1900970b4baSEdward Tomasz Napierala ace->a_flags = ACE_IDENTIFIER_GROUP; 1910970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_EVERYONE) 1920970b4baSEdward Tomasz Napierala ace->a_flags = ACE_EVERYONE; 1930970b4baSEdward Tomasz Napierala else /* ACL_USER */ 1940970b4baSEdward Tomasz Napierala ace->a_flags = 0; 1950970b4baSEdward Tomasz Napierala 1960970b4baSEdward Tomasz Napierala ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); 1970970b4baSEdward Tomasz Napierala ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); 1980970b4baSEdward Tomasz Napierala 1990970b4baSEdward Tomasz Napierala switch (entry->ae_entry_type) { 2000970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_ALLOW: 2010970b4baSEdward Tomasz Napierala ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 2020970b4baSEdward Tomasz Napierala break; 2030970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_DENY: 2040970b4baSEdward Tomasz Napierala ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 2050970b4baSEdward Tomasz Napierala break; 2060970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_ALARM: 2070970b4baSEdward Tomasz Napierala ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; 2080970b4baSEdward Tomasz Napierala break; 2090970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_AUDIT: 2100970b4baSEdward Tomasz Napierala ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; 2110970b4baSEdward Tomasz Napierala break; 2120970b4baSEdward Tomasz Napierala default: 2130970b4baSEdward Tomasz Napierala panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type); 2140970b4baSEdward Tomasz Napierala } 2150970b4baSEdward Tomasz Napierala } 2160970b4baSEdward Tomasz Napierala } 217