1198160Srrs/*-
2198160Srrs * Copyright (c) 2008, 2009 Edward Tomasz Napiera��a <trasz@FreeBSD.org>
3198160Srrs *
4198160Srrs * Redistribution and use in source and binary forms, with or without
5198160Srrs * modification, are permitted provided that the following conditions
6198160Srrs * are met:
7198160Srrs * 1. Redistributions of source code must retain the above copyright
8198160Srrs *    notice, this list of conditions and the following disclaimer.
9198160Srrs * 2. Redistributions in binary form must reproduce the above copyright
10198160Srrs *    notice, this list of conditions and the following disclaimer in the
11198160Srrs *    documentation and/or other materials provided with the distribution.
12198160Srrs *
13198160Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14198160Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15198160Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16198160Srrs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17198160Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18198160Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19198160Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20198160Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21198160Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22198160Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23198160Srrs * SUCH DAMAGE.
24198160Srrs */
25198160Srrs
26198160Srrs#include <sys/param.h>
27198160Srrs#include <sys/systm.h>
28198160Srrs#include <sys/types.h>
29211994Sjchandra#include <sys/malloc.h>
30211994Sjchandra#include <sys/errno.h>
31211994Sjchandra#include <sys/zfs_acl.h>
32198160Srrs#include <sys/acl.h>
33198160Srrs
34198160Srrsstruct zfs2bsd {
35198160Srrs	uint32_t	zb_zfs;
36198956Srrs	int		zb_bsd;
37198160Srrs};
38198160Srrs
39198160Srrsstruct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA},
40198160Srrs			{ACE_WRITE_DATA, ACL_WRITE_DATA},
41198160Srrs			{ACE_EXECUTE, ACL_EXECUTE},
42198160Srrs			{ACE_APPEND_DATA, ACL_APPEND_DATA},
43198160Srrs			{ACE_DELETE_CHILD, ACL_DELETE_CHILD},
44198160Srrs			{ACE_DELETE, ACL_DELETE},
45198160Srrs			{ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
46198160Srrs			{ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
47198160Srrs			{ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
48198160Srrs			{ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
49198160Srrs			{ACE_READ_ACL, ACL_READ_ACL},
50198160Srrs			{ACE_WRITE_ACL, ACL_WRITE_ACL},
51198160Srrs			{ACE_WRITE_OWNER, ACL_WRITE_OWNER},
52198160Srrs			{ACE_SYNCHRONIZE, ACL_SYNCHRONIZE},
53198160Srrs			{0, 0}};
54198160Srrs
55198160Srrsstruct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE,
56198160Srrs			    ACL_ENTRY_FILE_INHERIT},
57198160Srrs			{ACE_DIRECTORY_INHERIT_ACE,
58198160Srrs			    ACL_ENTRY_DIRECTORY_INHERIT},
59198160Srrs			{ACE_NO_PROPAGATE_INHERIT_ACE,
60198160Srrs			    ACL_ENTRY_NO_PROPAGATE_INHERIT},
61198160Srrs			{ACE_INHERIT_ONLY_ACE,
62198160Srrs			    ACL_ENTRY_INHERIT_ONLY},
63198160Srrs			{ACE_INHERITED_ACE,
64198160Srrs			    ACL_ENTRY_INHERITED},
65198160Srrs			{ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
66198160Srrs			    ACL_ENTRY_SUCCESSFUL_ACCESS},
67198160Srrs			{ACE_FAILED_ACCESS_ACE_FLAG,
68198160Srrs			    ACL_ENTRY_FAILED_ACCESS},
69198160Srrs			{0, 0}};
70198956Srrs
71198160Srrsstatic int
72198956Srrs_bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table)
73198956Srrs{
74198160Srrs	const struct zfs2bsd *tmp;
75198160Srrs	int bsd = 0;
76198160Srrs
77198160Srrs	for (tmp = table; tmp->zb_zfs != 0; tmp++) {
78198160Srrs		if (zfs & tmp->zb_zfs)
79198160Srrs			bsd |= tmp->zb_bsd;
80198160Srrs	}
81198160Srrs
82198160Srrs	return (bsd);
83198160Srrs}
84198160Srrs
85198160Srrsstatic uint32_t
86198160Srrs_zfs_from_bsd(int bsd, const struct zfs2bsd *table)
87198160Srrs{
88198160Srrs	const struct zfs2bsd *tmp;
89198160Srrs	uint32_t zfs = 0;
90198160Srrs
91198160Srrs	for (tmp = table; tmp->zb_bsd != 0; tmp++) {
92198160Srrs		if (bsd & tmp->zb_bsd)
93198160Srrs			zfs |= tmp->zb_zfs;
94198160Srrs	}
95198160Srrs
96198160Srrs	return (zfs);
97198160Srrs}
98198160Srrs
99198160Srrsint
100198625Srrsacl_from_aces(struct acl *aclp, const ace_t *aces, int nentries)
101198160Srrs{
102198160Srrs	int i;
103198160Srrs	struct acl_entry *entry;
104198160Srrs	const ace_t *ace;
105198160Srrs
106198160Srrs	if (nentries < 1) {
107198160Srrs		printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n");
108198160Srrs		return (EINVAL);
109198160Srrs	}
110198160Srrs
111198160Srrs	if (nentries > ACL_MAX_ENTRIES) {
112198160Srrs		/*
113198160Srrs		 * I believe it may happen only when moving a pool
114198160Srrs		 * from SunOS to FreeBSD.
115198625Srrs		 */
116		printf("acl_from_aces: ZFS ACL too big to fit "
117		    "into 'struct acl'; returning EINVAL.\n");
118		return (EINVAL);
119	}
120
121	bzero(aclp, sizeof(*aclp));
122	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
123	aclp->acl_cnt = nentries;
124
125	for (i = 0; i < nentries; i++) {
126		entry = &(aclp->acl_entry[i]);
127		ace = &(aces[i]);
128
129		if (ace->a_flags & ACE_OWNER)
130			entry->ae_tag = ACL_USER_OBJ;
131		else if (ace->a_flags & ACE_GROUP)
132			entry->ae_tag = ACL_GROUP_OBJ;
133		else if (ace->a_flags & ACE_EVERYONE)
134			entry->ae_tag = ACL_EVERYONE;
135		else if (ace->a_flags & ACE_IDENTIFIER_GROUP)
136			entry->ae_tag = ACL_GROUP;
137		else
138			entry->ae_tag = ACL_USER;
139
140		if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP)
141			entry->ae_id = ace->a_who;
142		else
143			entry->ae_id = ACL_UNDEFINED_ID;
144
145		entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms);
146		entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags);
147
148		switch (ace->a_type) {
149		case ACE_ACCESS_ALLOWED_ACE_TYPE:
150			entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
151			break;
152		case ACE_ACCESS_DENIED_ACE_TYPE:
153			entry->ae_entry_type = ACL_ENTRY_TYPE_DENY;
154			break;
155		case ACE_SYSTEM_AUDIT_ACE_TYPE:
156			entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
157			break;
158		case ACE_SYSTEM_ALARM_ACE_TYPE:
159			entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
160			break;
161		default:
162			panic("acl_from_aces: a_type is 0x%x", ace->a_type);
163		}
164	}
165
166	return (0);
167}
168
169void
170aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp)
171{
172	int i;
173	const struct acl_entry *entry;
174	ace_t *ace;
175
176	bzero(aces, sizeof(*aces) * aclp->acl_cnt);
177
178	*nentries = aclp->acl_cnt;
179
180	for (i = 0; i < aclp->acl_cnt; i++) {
181		entry = &(aclp->acl_entry[i]);
182		ace = &(aces[i]);
183
184		ace->a_who = entry->ae_id;
185
186		if (entry->ae_tag == ACL_USER_OBJ)
187			ace->a_flags = ACE_OWNER;
188		else if (entry->ae_tag == ACL_GROUP_OBJ)
189			ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP);
190		else if (entry->ae_tag == ACL_GROUP)
191			ace->a_flags = ACE_IDENTIFIER_GROUP;
192		else if (entry->ae_tag == ACL_EVERYONE)
193			ace->a_flags = ACE_EVERYONE;
194		else /* ACL_USER */
195			ace->a_flags = 0;
196
197		ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms);
198		ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags);
199
200		switch (entry->ae_entry_type) {
201		case ACL_ENTRY_TYPE_ALLOW:
202			ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
203			break;
204		case ACL_ENTRY_TYPE_DENY:
205			ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
206			break;
207		case ACL_ENTRY_TYPE_ALARM:
208			ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
209			break;
210		case ACL_ENTRY_TYPE_AUDIT:
211			ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
212			break;
213		default:
214			panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type);
215		}
216	}
217}
218