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}, 67*28ffe927SXin LI {ACE_INHERITED_ACE, 68*28ffe927SXin LI ACL_ENTRY_INHERITED}, 690970b4baSEdward Tomasz Napierala {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, 700970b4baSEdward Tomasz Napierala ACL_ENTRY_SUCCESSFUL_ACCESS}, 710970b4baSEdward Tomasz Napierala {ACE_FAILED_ACCESS_ACE_FLAG, 720970b4baSEdward Tomasz Napierala ACL_ENTRY_FAILED_ACCESS}, 730970b4baSEdward Tomasz Napierala {0, 0}}; 740970b4baSEdward Tomasz Napierala 750970b4baSEdward Tomasz Napierala static int 760970b4baSEdward Tomasz Napierala _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) 770970b4baSEdward Tomasz Napierala { 780970b4baSEdward Tomasz Napierala const struct zfs2bsd *tmp; 790970b4baSEdward Tomasz Napierala int bsd = 0; 800970b4baSEdward Tomasz Napierala 810970b4baSEdward Tomasz Napierala for (tmp = table; tmp->zb_zfs != 0; tmp++) { 820970b4baSEdward Tomasz Napierala if (zfs & tmp->zb_zfs) 830970b4baSEdward Tomasz Napierala bsd |= tmp->zb_bsd; 840970b4baSEdward Tomasz Napierala } 850970b4baSEdward Tomasz Napierala 860970b4baSEdward Tomasz Napierala return (bsd); 870970b4baSEdward Tomasz Napierala } 880970b4baSEdward Tomasz Napierala 890970b4baSEdward Tomasz Napierala static uint32_t 900970b4baSEdward Tomasz Napierala _zfs_from_bsd(int bsd, const struct zfs2bsd *table) 910970b4baSEdward Tomasz Napierala { 920970b4baSEdward Tomasz Napierala const struct zfs2bsd *tmp; 930970b4baSEdward Tomasz Napierala uint32_t zfs = 0; 940970b4baSEdward Tomasz Napierala 950970b4baSEdward Tomasz Napierala for (tmp = table; tmp->zb_bsd != 0; tmp++) { 960970b4baSEdward Tomasz Napierala if (bsd & tmp->zb_bsd) 970970b4baSEdward Tomasz Napierala zfs |= tmp->zb_zfs; 980970b4baSEdward Tomasz Napierala } 990970b4baSEdward Tomasz Napierala 1000970b4baSEdward Tomasz Napierala return (zfs); 1010970b4baSEdward Tomasz Napierala } 1020970b4baSEdward Tomasz Napierala 1030970b4baSEdward Tomasz Napierala int 1040970b4baSEdward Tomasz Napierala acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) 1050970b4baSEdward Tomasz Napierala { 1060970b4baSEdward Tomasz Napierala int i; 1070970b4baSEdward Tomasz Napierala struct acl_entry *entry; 1080970b4baSEdward Tomasz Napierala const ace_t *ace; 1090970b4baSEdward Tomasz Napierala 110de2a5732SEdward Tomasz Napierala if (nentries < 1) { 111de2a5732SEdward Tomasz Napierala printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n"); 112de2a5732SEdward Tomasz Napierala return (EINVAL); 113de2a5732SEdward Tomasz Napierala } 1140970b4baSEdward Tomasz Napierala 1150970b4baSEdward Tomasz Napierala if (nentries > ACL_MAX_ENTRIES) { 1160970b4baSEdward Tomasz Napierala /* 1170970b4baSEdward Tomasz Napierala * I believe it may happen only when moving a pool 1180970b4baSEdward Tomasz Napierala * from SunOS to FreeBSD. 1190970b4baSEdward Tomasz Napierala */ 1200970b4baSEdward Tomasz Napierala printf("acl_from_aces: ZFS ACL too big to fit " 1210970b4baSEdward Tomasz Napierala "into 'struct acl'; returning EINVAL.\n"); 1220970b4baSEdward Tomasz Napierala return (EINVAL); 1230970b4baSEdward Tomasz Napierala } 1240970b4baSEdward Tomasz Napierala 1250970b4baSEdward Tomasz Napierala bzero(aclp, sizeof(*aclp)); 1260970b4baSEdward Tomasz Napierala aclp->acl_maxcnt = ACL_MAX_ENTRIES; 1270970b4baSEdward Tomasz Napierala aclp->acl_cnt = nentries; 1280970b4baSEdward Tomasz Napierala 1290970b4baSEdward Tomasz Napierala for (i = 0; i < nentries; i++) { 1300970b4baSEdward Tomasz Napierala entry = &(aclp->acl_entry[i]); 1310970b4baSEdward Tomasz Napierala ace = &(aces[i]); 1320970b4baSEdward Tomasz Napierala 1330970b4baSEdward Tomasz Napierala if (ace->a_flags & ACE_OWNER) 1340970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_USER_OBJ; 1350970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_GROUP) 1360970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_GROUP_OBJ; 1370970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_EVERYONE) 1380970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_EVERYONE; 1390970b4baSEdward Tomasz Napierala else if (ace->a_flags & ACE_IDENTIFIER_GROUP) 1400970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_GROUP; 1410970b4baSEdward Tomasz Napierala else 1420970b4baSEdward Tomasz Napierala entry->ae_tag = ACL_USER; 1430970b4baSEdward Tomasz Napierala 1440970b4baSEdward Tomasz Napierala if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) 1450970b4baSEdward Tomasz Napierala entry->ae_id = ace->a_who; 1460970b4baSEdward Tomasz Napierala else 1470970b4baSEdward Tomasz Napierala entry->ae_id = ACL_UNDEFINED_ID; 1480970b4baSEdward Tomasz Napierala 1490970b4baSEdward Tomasz Napierala entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); 1500970b4baSEdward Tomasz Napierala entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); 1510970b4baSEdward Tomasz Napierala 1520970b4baSEdward Tomasz Napierala switch (ace->a_type) { 1530970b4baSEdward Tomasz Napierala case ACE_ACCESS_ALLOWED_ACE_TYPE: 1540970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 1550970b4baSEdward Tomasz Napierala break; 1560970b4baSEdward Tomasz Napierala case ACE_ACCESS_DENIED_ACE_TYPE: 1570970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; 1580970b4baSEdward Tomasz Napierala break; 1590970b4baSEdward Tomasz Napierala case ACE_SYSTEM_AUDIT_ACE_TYPE: 1600970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 1610970b4baSEdward Tomasz Napierala break; 1620970b4baSEdward Tomasz Napierala case ACE_SYSTEM_ALARM_ACE_TYPE: 1630970b4baSEdward Tomasz Napierala entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 1640970b4baSEdward Tomasz Napierala break; 1650970b4baSEdward Tomasz Napierala default: 1660970b4baSEdward Tomasz Napierala panic("acl_from_aces: a_type is 0x%x", ace->a_type); 1670970b4baSEdward Tomasz Napierala } 1680970b4baSEdward Tomasz Napierala } 1690970b4baSEdward Tomasz Napierala 1700970b4baSEdward Tomasz Napierala return (0); 1710970b4baSEdward Tomasz Napierala } 1720970b4baSEdward Tomasz Napierala 1730970b4baSEdward Tomasz Napierala void 1740970b4baSEdward Tomasz Napierala aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) 1750970b4baSEdward Tomasz Napierala { 1760970b4baSEdward Tomasz Napierala int i; 1770970b4baSEdward Tomasz Napierala const struct acl_entry *entry; 1780970b4baSEdward Tomasz Napierala ace_t *ace; 1790970b4baSEdward Tomasz Napierala 1800970b4baSEdward Tomasz Napierala bzero(aces, sizeof(*aces) * aclp->acl_cnt); 1810970b4baSEdward Tomasz Napierala 1820970b4baSEdward Tomasz Napierala *nentries = aclp->acl_cnt; 1830970b4baSEdward Tomasz Napierala 1840970b4baSEdward Tomasz Napierala for (i = 0; i < aclp->acl_cnt; i++) { 1850970b4baSEdward Tomasz Napierala entry = &(aclp->acl_entry[i]); 1860970b4baSEdward Tomasz Napierala ace = &(aces[i]); 1870970b4baSEdward Tomasz Napierala 1880970b4baSEdward Tomasz Napierala ace->a_who = entry->ae_id; 1890970b4baSEdward Tomasz Napierala 1900970b4baSEdward Tomasz Napierala if (entry->ae_tag == ACL_USER_OBJ) 1910970b4baSEdward Tomasz Napierala ace->a_flags = ACE_OWNER; 1920970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_GROUP_OBJ) 1930970b4baSEdward Tomasz Napierala ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); 1940970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_GROUP) 1950970b4baSEdward Tomasz Napierala ace->a_flags = ACE_IDENTIFIER_GROUP; 1960970b4baSEdward Tomasz Napierala else if (entry->ae_tag == ACL_EVERYONE) 1970970b4baSEdward Tomasz Napierala ace->a_flags = ACE_EVERYONE; 1980970b4baSEdward Tomasz Napierala else /* ACL_USER */ 1990970b4baSEdward Tomasz Napierala ace->a_flags = 0; 2000970b4baSEdward Tomasz Napierala 2010970b4baSEdward Tomasz Napierala ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); 2020970b4baSEdward Tomasz Napierala ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); 2030970b4baSEdward Tomasz Napierala 2040970b4baSEdward Tomasz Napierala switch (entry->ae_entry_type) { 2050970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_ALLOW: 2060970b4baSEdward Tomasz Napierala ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 2070970b4baSEdward Tomasz Napierala break; 2080970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_DENY: 2090970b4baSEdward Tomasz Napierala ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 2100970b4baSEdward Tomasz Napierala break; 2110970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_ALARM: 2120970b4baSEdward Tomasz Napierala ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; 2130970b4baSEdward Tomasz Napierala break; 2140970b4baSEdward Tomasz Napierala case ACL_ENTRY_TYPE_AUDIT: 2150970b4baSEdward Tomasz Napierala ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; 2160970b4baSEdward Tomasz Napierala break; 2170970b4baSEdward Tomasz Napierala default: 2180970b4baSEdward Tomasz Napierala panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type); 2190970b4baSEdward Tomasz Napierala } 2200970b4baSEdward Tomasz Napierala } 2210970b4baSEdward Tomasz Napierala } 222