2 * Copyright (c) 2003-2010 Tim Kientzle
3 * Copyright (c) 2017 Martin Matuska
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 __FBSDID("$FreeBSD$");
29 #if HAVE_POSIX_ACL || HAVE_NFS4_ACL
33 #include <membership.h>
42 int qual; /* GID or UID of user/group, depending on tag. */
43 const char *name; /* Name of user/group, depending on tag. */
46 static struct myacl_t acls_reg[] = {
48 /* For this test, we need the file owner to be able to read and write the ACL. */
49 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
50 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
51 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
53 /* An entry for each type. */
54 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
55 ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
56 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
57 ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
59 /* An entry for each permission. */
60 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
61 ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
62 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
63 ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
64 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
65 ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
66 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
67 ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
68 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
69 ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
70 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
71 ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
72 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
73 ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
74 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
75 ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
76 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
77 ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
78 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
79 ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
80 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
81 ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
82 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
83 ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
84 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
85 ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
87 /* One entry for each qualifier. */
88 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
89 ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
90 // { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
91 // ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
92 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
93 ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
95 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
96 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
97 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
98 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
99 #else /* MacOS - mode 0654 */
100 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
101 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
102 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
103 ARCHIVE_ENTRY_ACL_READ_DATA |
104 ARCHIVE_ENTRY_ACL_WRITE_DATA |
105 ARCHIVE_ENTRY_ACL_APPEND_DATA |
106 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
107 ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
108 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
109 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
110 ARCHIVE_ENTRY_ACL_READ_ACL |
111 ARCHIVE_ENTRY_ACL_WRITE_ACL |
112 ARCHIVE_ENTRY_ACL_WRITE_OWNER |
113 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
114 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
115 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
116 ARCHIVE_ENTRY_ACL_READ_DATA |
117 ARCHIVE_ENTRY_ACL_EXECUTE |
118 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
119 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
120 ARCHIVE_ENTRY_ACL_READ_ACL |
121 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
122 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
123 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
124 ARCHIVE_ENTRY_ACL_READ_DATA |
125 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
126 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
127 ARCHIVE_ENTRY_ACL_READ_ACL |
128 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
129 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
133 static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
135 static struct myacl_t acls_dir[] = {
136 /* For this test, we need to be able to read and write the ACL. */
138 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
139 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
142 /* An entry for each type. */
143 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
144 ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
145 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
146 ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
148 /* An entry for each permission. */
149 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
150 ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
151 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
152 ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
153 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
154 ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
155 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
156 ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
157 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
158 ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
159 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
160 ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
161 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
162 ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
163 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
164 ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
165 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
166 ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
167 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
168 ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
169 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
170 ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
171 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
172 ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
173 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
174 ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
176 /* One entry with each inheritance value. */
177 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
178 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
179 ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
180 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
181 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
182 ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
184 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
185 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
186 ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
187 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
188 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
189 ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
190 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
191 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
192 ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
196 /* FreeBSD does not support audit entries. */
197 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
198 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
199 ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
200 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
201 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
202 ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
205 /* One entry for each qualifier. */
206 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
207 ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
208 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
209 ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
211 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
212 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
213 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
214 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
215 #else /* MacOS - mode 0654 */
216 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
217 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
218 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
219 ARCHIVE_ENTRY_ACL_READ_DATA |
220 ARCHIVE_ENTRY_ACL_WRITE_DATA |
221 ARCHIVE_ENTRY_ACL_APPEND_DATA |
222 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
223 ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
224 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
225 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
226 ARCHIVE_ENTRY_ACL_READ_ACL |
227 ARCHIVE_ENTRY_ACL_WRITE_ACL |
228 ARCHIVE_ENTRY_ACL_WRITE_OWNER |
229 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
230 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
231 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
232 ARCHIVE_ENTRY_ACL_READ_DATA |
233 ARCHIVE_ENTRY_ACL_EXECUTE |
234 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
235 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
236 ARCHIVE_ENTRY_ACL_READ_ACL |
237 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
238 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
239 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
240 ARCHIVE_ENTRY_ACL_READ_DATA |
241 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
242 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
243 ARCHIVE_ENTRY_ACL_READ_ACL |
244 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
245 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
249 static const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0]));
252 set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
256 archive_entry_acl_clear(ae);
258 assertEqualInt(ARCHIVE_OK,
259 archive_entry_acl_add_entry(ae,
260 acls[0].type, acls[0].permset, acls[0].tag,
261 acls[0].qual, acls[0].name));
263 for (i = start; i < end; i++) {
264 assertEqualInt(ARCHIVE_OK,
265 archive_entry_acl_add_entry(ae,
266 acls[i].type, acls[i].permset, acls[i].tag,
267 acls[i].qual, acls[i].name));
273 acl_permset_to_bitmap(uint32_t a_access_mask)
275 acl_permset_to_bitmap(acl_permset_t opaque_ps)
278 static struct { int machine; int portable; } perms[] = {
279 #ifdef HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
280 {ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
281 {ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
282 {ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
283 {ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
284 {ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
285 {ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
286 {ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
287 {ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
288 {ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
289 {ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
290 {ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
291 {ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
292 {ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
293 {ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
294 {ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
295 {ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
296 {ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
297 #elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL permissions */
298 {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
299 {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
300 {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
301 {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
302 {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
303 {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
304 {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
305 {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
306 {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
307 {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
308 {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
309 {ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
310 {ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
311 {ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
312 {ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
313 {ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
314 {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
315 #else /* FreeBSD NFSv4 ACL permissions */
316 {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
317 {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
318 {ACL_READ, ARCHIVE_ENTRY_ACL_READ},
319 {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
320 {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
321 {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
322 {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
323 {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
324 {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
325 {ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
326 {ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
327 {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
328 {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
329 {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
330 {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
331 {ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
332 {ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
333 {ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
334 {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
339 for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
341 if (a_access_mask & perms[i].machine)
343 if (acl_get_perm_np(opaque_ps, perms[i].machine))
345 permset |= perms[i].portable;
351 acl_flagset_to_bitmap(uint16_t a_flags)
353 acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
356 static struct { int machine; int portable; } flags[] = {
357 #if HAVE_SUN_ACL /* Solaris NFSv4 ACL inheritance flags */
358 {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
359 {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
360 {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
361 {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
362 {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
363 {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
364 {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
365 #elif HAVE_DARWIN_ACL /* MacOS NFSv4 ACL inheritance flags */
366 {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
367 {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
368 {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
369 {ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
370 {ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
371 #else /* FreeBSD NFSv4 ACL inheritance flags */
372 {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
373 {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
374 {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
375 {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
376 {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
377 {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
382 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
384 if (a_flags & flags[i].machine)
386 if (acl_get_flag_np(opaque_fs, flags[i].machine))
388 flagset |= flags[i].portable;
394 acl_match(ace_t *ace, struct myacl_t *myacl)
396 acl_match(acl_entry_t aclent, struct myacl_t *myacl)
407 acl_entry_type_t entry_type;
408 #endif /* !HAVE_DARWIN_ACL */
410 acl_permset_t opaque_ps;
411 acl_flagset_t opaque_fs;
412 #endif /* !HAVE_SUN_ACL */
416 perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
418 acl_get_tag_type(aclent, &tag_type);
420 acl_get_entry_type_np(aclent, &entry_type);
423 /* translate the silly opaque permset to a bitmap */
424 acl_get_permset(aclent, &opaque_ps);
425 acl_get_flagset_np(aclent, &opaque_fs);
426 perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
428 if (perms != myacl->permset)
432 switch (ace->a_type) {
433 case ACE_ACCESS_ALLOWED_ACE_TYPE:
434 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
437 case ACE_ACCESS_DENIED_ACE_TYPE:
438 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
441 case ACE_SYSTEM_AUDIT_ACE_TYPE:
442 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
445 case ACE_SYSTEM_ALARM_ACE_TYPE:
446 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
453 if (ace->a_flags & ACE_OWNER) {
454 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
456 } else if (ace->a_flags & ACE_GROUP) {
457 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
459 } else if (ace->a_flags & ACE_EVERYONE) {
460 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
462 } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
463 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
465 if ((gid_t)myacl->qual != ace->a_who)
468 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
470 if ((uid_t)myacl->qual != ace->a_who)
473 #elif HAVE_DARWIN_ACL
476 case ACL_EXTENDED_ALLOW:
477 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
480 case ACL_EXTENDED_DENY:
481 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
487 q = acl_get_qualifier(aclent);
490 r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
496 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
498 if ((uid_t)myacl->qual != ugid)
502 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
504 if ((gid_t)myacl->qual != ugid)
510 #else /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
511 switch (entry_type) {
512 case ACL_ENTRY_TYPE_ALLOW:
513 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
516 case ACL_ENTRY_TYPE_DENY:
517 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
520 case ACL_ENTRY_TYPE_AUDIT:
521 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
523 case ACL_ENTRY_TYPE_ALARM:
524 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
532 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
535 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
537 up = acl_get_qualifier(aclent);
540 if ((uid_t)myacl->qual != u)
544 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
547 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
549 gp = acl_get_qualifier(aclent);
552 if ((gid_t)myacl->qual != g)
556 if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
559 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
562 #endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
573 struct myacl_t *myacls, const char *filename, int start, int end)
582 int entry_id = ACL_FIRST_ENTRY;
583 acl_entry_t acl_entry;
587 marker = malloc(sizeof(marker[0]) * (n + 1));
588 for (i = 0; i < n; i++)
589 marker[i] = i + start;
590 /* Always include the first ACE. */
597 * Iterate over acls in system acl object, try to match each
598 * one with an item in the myacls array.
601 for (e = 0; e < acl->acl_cnt; e++)
602 #elif HAVE_DARWIN_ACL
603 while (0 == acl_get_entry(acl, entry_id, &acl_entry))
605 while (1 == acl_get_entry(acl, entry_id, &acl_entry))
609 acl_entry = &((ace_t *)acl->acl_aclp)[e];
611 /* After the first time... */
612 entry_id = ACL_NEXT_ENTRY;
614 /* Search for a matching entry (tag and qualifier) */
615 for (i = 0, matched = 0; i < n && !matched; i++) {
616 if (acl_match(acl_entry, &myacls[marker[i]])) {
617 /* We found a match; remove it. */
618 marker[i] = marker[n - 1];
624 failure("ACL entry on file %s that shouldn't be there",
626 assert(matched == 1);
629 /* Dump entries in the myacls array that weren't in the system acl. */
630 for (i = 0; i < n; ++i) {
631 failure(" ACL entry %d missing from %s: "
632 "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
634 myacls[marker[i]].type, myacls[marker[i]].permset,
635 myacls[marker[i]].tag, myacls[marker[i]].qual,
636 myacls[marker[i]].name);
637 assert(0); /* Record this as a failure. */
643 compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
648 int type, permset, tag, qual;
651 /* Count ACL entries in myacls array and allocate an indirect array. */
653 marker = malloc(sizeof(marker[0]) * (n + 1));
654 for (i = 0; i < n; i++)
655 marker[i] = i + start;
656 /* Always include the first ACE. */
663 * Iterate over acls in entry, try to match each
664 * one with an item in the myacls array.
666 assertEqualInt(n, archive_entry_acl_reset(ae,
667 ARCHIVE_ENTRY_ACL_TYPE_NFS4));
668 while (ARCHIVE_OK == archive_entry_acl_next(ae,
669 ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
671 /* Search for a matching entry (tag and qualifier) */
672 for (i = 0, matched = 0; i < n && !matched; i++) {
673 if (tag == myacls[marker[i]].tag
674 && qual == myacls[marker[i]].qual
675 && permset == myacls[marker[i]].permset
676 && type == myacls[marker[i]].type) {
677 /* We found a match; remove it. */
678 marker[i] = marker[n - 1];
684 failure("ACL entry on file that shouldn't be there: "
685 "type=%#010x,permset=%#010x,tag=%d,qual=%d",
686 type,permset,tag,qual);
687 assert(matched == 1);
690 /* Dump entries in the myacls array that weren't in the system acl. */
691 for (i = 0; i < n; ++i) {
692 failure(" ACL entry %d missing from %s: "
693 "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
695 myacls[marker[i]].type, myacls[marker[i]].permset,
696 myacls[marker[i]].tag, myacls[marker[i]].qual,
697 myacls[marker[i]].name);
698 assert(0); /* Record this as a failure. */
702 #endif /* HAVE_NFS4_ACL */
705 * Verify ACL restore-to-disk. This test is Platform-specific.
708 DEFINE_TEST(test_acl_platform_nfs4)
711 skipping("NFS4 ACLs are not supported on this platform");
716 struct archive_entry *ae;
719 #if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
720 const int regcnt = acls_reg_cnt - 4;
721 const int dircnt = acls_dir_cnt - 4;
723 const int regcnt = acls_reg_cnt;
724 const int dircnt = acls_dir_cnt;
728 #else /* !HAVE_SUN_ACL */
731 acl_permset_t permset;
732 const uid_t uid = 1000;
734 #endif /* HAVE_DARWIN_ACL */
736 #endif /* !HAVE_SUN_ACL */
739 * First, do a quick manual set/read of ACL data to
740 * verify that the local filesystem does support ACLs.
741 * If it doesn't, we'll simply skip the remaining tests.
743 #if HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4
744 acl = acl_from_text("owner@:rwxp::allow,group@:rwp:f:allow");
745 failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
746 assert((void *)acl != NULL);
747 #elif HAVE_DARWIN_ACL
749 assert((void *)acl != NULL);
750 assertEqualInt(0, acl_create_entry(&acl, &aclent));
751 assertEqualInt(0, acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW));
752 assertEqualInt(0, acl_get_permset(aclent, &permset));
753 assertEqualInt(0, acl_add_perm(permset, ACL_READ_DATA));
754 assertEqualInt(0, acl_add_perm(permset, ACL_WRITE_DATA));
755 assertEqualInt(0, acl_add_perm(permset, ACL_APPEND_DATA));
756 assertEqualInt(0, acl_add_perm(permset, ACL_EXECUTE));
757 assertEqualInt(0, acl_set_permset(aclent, permset));
758 assertEqualInt(0, mbr_identifier_to_uuid(ID_TYPE_UID, &uid,
759 sizeof(uid_t), uuid));
760 assertEqualInt(0, acl_set_qualifier(aclent, uuid));
763 /* Create a test dir and try to set an ACL on it. */
764 if (!assertMakeDir("pretest", 0755)) {
773 n = acl_get("pretest", 0, &acl);
775 func = "acl_set_file()";
777 n = acl_set_file("pretest", ACL_TYPE_EXTENDED, acl);
779 n = acl_set_file("pretest", ACL_TYPE_NFS4, acl);
787 if (errno == EOPNOTSUPP || errno == EINVAL)
790 skipping("NFS4 ACL is not supported on this filesystem");
794 failure("%s: errno = %d (%s)", func, errno, strerror(errno));
795 assertEqualInt(0, n);
798 if (acl->acl_type != ACE_T) {
800 skipping("NFS4 ACL is not supported on this filesystem");
806 /* Create a write-to-disk object. */
807 assert(NULL != (a = archive_write_disk_new()));
808 archive_write_disk_set_options(a,
809 ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
811 /* Populate an archive entry with some metadata, including ACL info */
812 ae = archive_entry_new();
814 archive_entry_set_pathname(ae, "testall");
815 archive_entry_set_filetype(ae, AE_IFREG);
816 archive_entry_set_perm(ae, 0654);
817 archive_entry_set_mtime(ae, 123456, 7890);
818 archive_entry_set_size(ae, 0);
819 set_acls(ae, acls_reg, 0, acls_reg_cnt);
821 /* Write the entry to disk, including ACLs. */
822 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
824 /* Likewise for a dir. */
825 archive_entry_set_pathname(ae, "dirall");
826 archive_entry_set_filetype(ae, AE_IFDIR);
827 archive_entry_set_perm(ae, 0654);
828 archive_entry_set_mtime(ae, 123456, 7890);
829 set_acls(ae, acls_dir, 0, acls_dir_cnt);
830 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
832 for (i = 0; i < acls_dir_cnt; ++i) {
833 sprintf(buff, "dir%d", i);
834 archive_entry_set_pathname(ae, buff);
835 archive_entry_set_filetype(ae, AE_IFDIR);
836 archive_entry_set_perm(ae, 0654);
837 archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
838 set_acls(ae, acls_dir, i, i + 1);
839 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
842 archive_entry_free(ae);
844 /* Close the archive. */
845 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
846 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
848 /* Verify the data on disk. */
849 assertEqualInt(0, stat("testall", &st));
850 assertEqualInt(st.st_mtime, 123456);
852 n = acl_get("testall", 0, &acl);
853 failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
854 assertEqualInt(0, n);
857 acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
859 acl = acl_get_file("testall", ACL_TYPE_NFS4);
861 failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
862 assert(acl != (acl_t)NULL);
864 compare_acls(acl, acls_reg, "testall", 0, regcnt);
867 /* Verify single-permission dirs on disk. */
868 for (i = 0; i < dircnt; ++i) {
869 sprintf(buff, "dir%d", i);
870 assertEqualInt(0, stat(buff, &st));
871 assertEqualInt(st.st_mtime, 123456 + i);
873 n = acl_get(buff, 0, &acl);
874 failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
875 assertEqualInt(0, n);
878 acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
880 acl = acl_get_file(buff, ACL_TYPE_NFS4);
882 failure("acl_get_file(): errno = %d (%s)", errno,
884 assert(acl != (acl_t)NULL);
886 compare_acls(acl, acls_dir, buff, i, i + 1);
890 /* Verify "dirall" on disk. */
891 assertEqualInt(0, stat("dirall", &st));
892 assertEqualInt(st.st_mtime, 123456);
894 n = acl_get("dirall", 0, &acl);
895 failure("acl_get(): errno = %d (%s)", errno, strerror(errno));
896 assertEqualInt(0, n);
899 acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
901 acl = acl_get_file("dirall", ACL_TYPE_NFS4);
903 failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
904 assert(acl != (acl_t)NULL);
906 compare_acls(acl, acls_dir, "dirall", 0, dircnt);
909 /* Read and compare ACL via archive_read_disk */
910 a = archive_read_disk_new();
912 ae = archive_entry_new();
914 archive_entry_set_pathname(ae, "testall");
915 assertEqualInt(ARCHIVE_OK,
916 archive_read_disk_entry_from_file(a, ae, -1, NULL));
917 compare_entry_acls(ae, acls_reg, "testall", 0, acls_reg_cnt);
918 archive_entry_free(ae);
919 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
921 /* Read and compare ACL via archive_read_disk */
922 a = archive_read_disk_new();
924 ae = archive_entry_new();
926 archive_entry_set_pathname(ae, "dirall");
927 assertEqualInt(ARCHIVE_OK,
928 archive_read_disk_entry_from_file(a, ae, -1, NULL));
929 compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
930 archive_entry_free(ae);
931 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
932 #endif /* HAVE_NFS4_ACL */