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