]>
Commit | Line | Data |
---|---|---|
9f0a21e6 MM |
1 | /* |
2 | * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> | |
9f0a21e6 MM |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
16 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
17 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
18 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
19 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
20 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
21 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
22 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
23 | * SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #include <sys/cdefs.h> | |
27 | __FBSDID("$FreeBSD$"); | |
28 | ||
e64cc495 | 29 | #include <sys/types.h> |
9f0a21e6 MM |
30 | #include <sys/param.h> |
31 | #include <sys/systm.h> | |
32 | #include <sys/types.h> | |
33 | #include <sys/malloc.h> | |
34 | #include <sys/errno.h> | |
35 | #include <sys/zfs_acl.h> | |
36 | #include <sys/acl.h> | |
37 | ||
38 | struct zfs2bsd { | |
39 | uint32_t zb_zfs; | |
40 | int zb_bsd; | |
41 | }; | |
42 | ||
861166b0 | 43 | static const struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA}, |
9f0a21e6 MM |
44 | {ACE_WRITE_DATA, ACL_WRITE_DATA}, |
45 | {ACE_EXECUTE, ACL_EXECUTE}, | |
46 | {ACE_APPEND_DATA, ACL_APPEND_DATA}, | |
47 | {ACE_DELETE_CHILD, ACL_DELETE_CHILD}, | |
48 | {ACE_DELETE, ACL_DELETE}, | |
49 | {ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, | |
50 | {ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, | |
51 | {ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, | |
52 | {ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, | |
53 | {ACE_READ_ACL, ACL_READ_ACL}, | |
54 | {ACE_WRITE_ACL, ACL_WRITE_ACL}, | |
55 | {ACE_WRITE_OWNER, ACL_WRITE_OWNER}, | |
56 | {ACE_SYNCHRONIZE, ACL_SYNCHRONIZE}, | |
57 | {0, 0}}; | |
58 | ||
861166b0 | 59 | static const struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE, |
9f0a21e6 MM |
60 | ACL_ENTRY_FILE_INHERIT}, |
61 | {ACE_DIRECTORY_INHERIT_ACE, | |
62 | ACL_ENTRY_DIRECTORY_INHERIT}, | |
63 | {ACE_NO_PROPAGATE_INHERIT_ACE, | |
64 | ACL_ENTRY_NO_PROPAGATE_INHERIT}, | |
65 | {ACE_INHERIT_ONLY_ACE, | |
66 | ACL_ENTRY_INHERIT_ONLY}, | |
67 | {ACE_INHERITED_ACE, | |
68 | ACL_ENTRY_INHERITED}, | |
69 | {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, | |
70 | ACL_ENTRY_SUCCESSFUL_ACCESS}, | |
71 | {ACE_FAILED_ACCESS_ACE_FLAG, | |
72 | ACL_ENTRY_FAILED_ACCESS}, | |
73 | {0, 0}}; | |
74 | ||
75 | static int | |
76 | _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) | |
77 | { | |
78 | const struct zfs2bsd *tmp; | |
79 | int bsd = 0; | |
80 | ||
81 | for (tmp = table; tmp->zb_zfs != 0; tmp++) { | |
82 | if (zfs & tmp->zb_zfs) | |
83 | bsd |= tmp->zb_bsd; | |
84 | } | |
85 | ||
86 | return (bsd); | |
87 | } | |
88 | ||
89 | static uint32_t | |
90 | _zfs_from_bsd(int bsd, const struct zfs2bsd *table) | |
91 | { | |
92 | const struct zfs2bsd *tmp; | |
93 | uint32_t zfs = 0; | |
94 | ||
95 | for (tmp = table; tmp->zb_bsd != 0; tmp++) { | |
96 | if (bsd & tmp->zb_bsd) | |
97 | zfs |= tmp->zb_zfs; | |
98 | } | |
99 | ||
100 | return (zfs); | |
101 | } | |
102 | ||
103 | int | |
104 | acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) | |
105 | { | |
106 | int i; | |
107 | struct acl_entry *entry; | |
108 | const ace_t *ace; | |
109 | ||
110 | if (nentries < 1) { | |
111 | printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n"); | |
112 | return (EINVAL); | |
113 | } | |
114 | ||
115 | if (nentries > ACL_MAX_ENTRIES) { | |
116 | /* | |
117 | * I believe it may happen only when moving a pool | |
118 | * from SunOS to FreeBSD. | |
119 | */ | |
120 | printf("acl_from_aces: ZFS ACL too big to fit " | |
121 | "into 'struct acl'; returning EINVAL.\n"); | |
122 | return (EINVAL); | |
123 | } | |
124 | ||
861166b0 | 125 | memset(aclp, 0, sizeof (*aclp)); |
9f0a21e6 MM |
126 | aclp->acl_maxcnt = ACL_MAX_ENTRIES; |
127 | aclp->acl_cnt = nentries; | |
128 | ||
129 | for (i = 0; i < nentries; i++) { | |
130 | entry = &(aclp->acl_entry[i]); | |
131 | ace = &(aces[i]); | |
132 | ||
133 | if (ace->a_flags & ACE_OWNER) | |
134 | entry->ae_tag = ACL_USER_OBJ; | |
135 | else if (ace->a_flags & ACE_GROUP) | |
136 | entry->ae_tag = ACL_GROUP_OBJ; | |
137 | else if (ace->a_flags & ACE_EVERYONE) | |
138 | entry->ae_tag = ACL_EVERYONE; | |
139 | else if (ace->a_flags & ACE_IDENTIFIER_GROUP) | |
140 | entry->ae_tag = ACL_GROUP; | |
141 | else | |
142 | entry->ae_tag = ACL_USER; | |
143 | ||
144 | if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) | |
145 | entry->ae_id = ace->a_who; | |
146 | else | |
147 | entry->ae_id = ACL_UNDEFINED_ID; | |
148 | ||
149 | entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); | |
150 | entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); | |
151 | ||
152 | switch (ace->a_type) { | |
153 | case ACE_ACCESS_ALLOWED_ACE_TYPE: | |
154 | entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; | |
155 | break; | |
156 | case ACE_ACCESS_DENIED_ACE_TYPE: | |
157 | entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; | |
158 | break; | |
159 | case ACE_SYSTEM_AUDIT_ACE_TYPE: | |
160 | entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; | |
161 | break; | |
162 | case ACE_SYSTEM_ALARM_ACE_TYPE: | |
163 | entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; | |
164 | break; | |
165 | default: | |
166 | panic("acl_from_aces: a_type is 0x%x", ace->a_type); | |
167 | } | |
168 | } | |
169 | ||
170 | return (0); | |
171 | } | |
172 | ||
173 | void | |
174 | aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) | |
175 | { | |
176 | int i; | |
177 | const struct acl_entry *entry; | |
178 | ace_t *ace; | |
179 | ||
861166b0 | 180 | memset(aces, 0, sizeof (*aces) * aclp->acl_cnt); |
9f0a21e6 MM |
181 | |
182 | *nentries = aclp->acl_cnt; | |
183 | ||
184 | for (i = 0; i < aclp->acl_cnt; i++) { | |
185 | entry = &(aclp->acl_entry[i]); | |
186 | ace = &(aces[i]); | |
187 | ||
188 | ace->a_who = entry->ae_id; | |
189 | ||
190 | if (entry->ae_tag == ACL_USER_OBJ) | |
191 | ace->a_flags = ACE_OWNER; | |
192 | else if (entry->ae_tag == ACL_GROUP_OBJ) | |
193 | ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); | |
194 | else if (entry->ae_tag == ACL_GROUP) | |
195 | ace->a_flags = ACE_IDENTIFIER_GROUP; | |
196 | else if (entry->ae_tag == ACL_EVERYONE) | |
197 | ace->a_flags = ACE_EVERYONE; | |
198 | else /* ACL_USER */ | |
199 | ace->a_flags = 0; | |
200 | ||
201 | ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); | |
202 | ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); | |
203 | ||
204 | switch (entry->ae_entry_type) { | |
205 | case ACL_ENTRY_TYPE_ALLOW: | |
206 | ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; | |
207 | break; | |
208 | case ACL_ENTRY_TYPE_DENY: | |
209 | ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; | |
210 | break; | |
211 | case ACL_ENTRY_TYPE_ALARM: | |
212 | ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; | |
213 | break; | |
214 | case ACL_ENTRY_TYPE_AUDIT: | |
215 | ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; | |
216 | break; | |
217 | default: | |
218 | panic("aces_from_acl: ae_entry_type is 0x%x", | |
219 | entry->ae_entry_type); | |
220 | } | |
221 | } | |
222 | } |