1 /*-
2 * Copyright (c) 2003-2010 Tim Kientzle
3 * Copyright (c) 2017 Martin Matuska
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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.
25 */
26 #include "test.h"
27 __FBSDID("$FreeBSD$");
28
29 #if ARCHIVE_ACL_NFS4
30 #if HAVE_SYS_ACL_H
31 #define _ACL_PRIVATE
32 #include <sys/acl.h>
33 #endif
34 #if HAVE_SYS_RICHACL_H
35 #include <sys/richacl.h>
36 #endif
37 #if HAVE_MEMBERSHIP_H
38 #include <membership.h>
39 #endif
40
41 struct myacl_t {
42 int type;
43 int permset;
44 int tag;
45 int qual; /* GID or UID of user/group, depending on tag. */
46 const char *name; /* Name of user/group, depending on tag. */
47 };
48
49 static struct myacl_t acls_reg[] = {
50 #if !ARCHIVE_ACL_DARWIN
51 /* For this test, we need the file owner to be able to read and write the ACL. */
52 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
53 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,
54 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
55 #endif
56 /* An entry for each type. */
57 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
58 ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
59 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
60 ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
61
62 /* An entry for each permission. */
63 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
64 ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
65 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
66 ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
67 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
68 ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
69 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
70 ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
71 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
72 ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
73 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
74 ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
75 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
76 ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
77 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
78 ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
79 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
80 ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
81 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
82 ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
83 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
84 ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
85 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
86 ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
87 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
88 ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
89
90 /* One entry for each qualifier. */
91 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
92 ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
93 // { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
94 // ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
95 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
96 ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
97 #if !ARCHIVE_ACL_DARWIN
98 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
99 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
100 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
101 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
102 #else /* MacOS - mode 0654 */
103 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
104 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
105 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
106 ARCHIVE_ENTRY_ACL_READ_DATA |
107 ARCHIVE_ENTRY_ACL_WRITE_DATA |
108 ARCHIVE_ENTRY_ACL_APPEND_DATA |
109 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
110 ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
111 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
112 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
113 ARCHIVE_ENTRY_ACL_READ_ACL |
114 ARCHIVE_ENTRY_ACL_WRITE_ACL |
115 ARCHIVE_ENTRY_ACL_WRITE_OWNER |
116 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
117 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
118 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
119 ARCHIVE_ENTRY_ACL_READ_DATA |
120 ARCHIVE_ENTRY_ACL_EXECUTE |
121 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
122 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
123 ARCHIVE_ENTRY_ACL_READ_ACL |
124 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
125 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
126 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
127 ARCHIVE_ENTRY_ACL_READ_DATA |
128 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
129 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
130 ARCHIVE_ENTRY_ACL_READ_ACL |
131 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
132 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
133 #endif
134 };
135
136 static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
137
138 static struct myacl_t acls_dir[] = {
139 /* For this test, we need to be able to read and write the ACL. */
140 #if !ARCHIVE_ACL_DARWIN
141 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
142 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
143 #endif
144
145 /* An entry for each type. */
146 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
147 ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
148 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
149 ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
150
151 /* An entry for each permission. */
152 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
153 ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
154 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
155 ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
156 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
157 ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
158 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
159 ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
160 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
161 ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
162 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
163 ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
164 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
165 ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
166 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
167 ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
168 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
169 ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
170 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
171 ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
172 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
173 ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
174 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
175 ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
176 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
177 ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
178
179 /* One entry with each inheritance value. */
180 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
181 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
182 ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
183 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
184 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
185 ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
186 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
187 ARCHIVE_ENTRY_ACL_READ_DATA |
188 ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
189 ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
190 ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
191 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
192 ARCHIVE_ENTRY_ACL_READ_DATA |
193 ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
194 ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
195 ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
196 #if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE)
197 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
198 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
199 ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
200 #endif
201
202 #if 0
203 /* FreeBSD does not support audit entries. */
204 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
205 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
206 ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
207 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
208 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
209 ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
210 #endif
211
212 /* One entry for each qualifier. */
213 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
214 ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
215 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
216 ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
217 #if !ARCHIVE_ACL_DARWIN
218 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
219 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
220 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
221 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
222 #else /* MacOS - mode 0654 */
223 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
224 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
225 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
226 ARCHIVE_ENTRY_ACL_READ_DATA |
227 ARCHIVE_ENTRY_ACL_WRITE_DATA |
228 ARCHIVE_ENTRY_ACL_APPEND_DATA |
229 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
230 ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
231 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
232 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
233 ARCHIVE_ENTRY_ACL_READ_ACL |
234 ARCHIVE_ENTRY_ACL_WRITE_ACL |
235 ARCHIVE_ENTRY_ACL_WRITE_OWNER |
236 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
237 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
238 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
239 ARCHIVE_ENTRY_ACL_READ_DATA |
240 ARCHIVE_ENTRY_ACL_EXECUTE |
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_GROUP_OBJ, -1, "" },
246 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
247 ARCHIVE_ENTRY_ACL_READ_DATA |
248 ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
249 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
250 ARCHIVE_ENTRY_ACL_READ_ACL |
251 ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
252 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
253 #endif
254 };
255
256 static const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0]));
257
258 static void
set_acls(struct archive_entry * ae,struct myacl_t * acls,int start,int end)259 set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
260 {
261 int i;
262
263 archive_entry_acl_clear(ae);
264 #if !ARCHIVE_ACL_DARWIN
265 if (start > 0) {
266 assertEqualInt(ARCHIVE_OK,
267 archive_entry_acl_add_entry(ae,
268 acls[0].type, acls[0].permset, acls[0].tag,
269 acls[0].qual, acls[0].name));
270 }
271 #endif
272 for (i = start; i < end; i++) {
273 assertEqualInt(ARCHIVE_OK,
274 archive_entry_acl_add_entry(ae,
275 acls[i].type, acls[i].permset, acls[i].tag,
276 acls[i].qual, acls[i].name));
277 }
278 }
279
280 static int
281 #if ARCHIVE_ACL_SUNOS_NFS4
acl_permset_to_bitmap(uint32_t mask)282 acl_permset_to_bitmap(uint32_t mask)
283 #elif ARCHIVE_ACL_LIBRICHACL
284 acl_permset_to_bitmap(unsigned int mask)
285 #else
286 acl_permset_to_bitmap(acl_permset_t opaque_ps)
287 #endif
288 {
289 static struct { int portable; int machine; } perms[] = {
290 #ifdef ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL permissions */
291 {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
292 {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
293 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
294 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
295 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
296 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
297 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
298 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
299 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
300 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
301 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
302 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
303 {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
304 {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
305 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
306 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
307 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
308 #elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL permissions */
309 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
310 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
311 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
312 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
313 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
314 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
315 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
316 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
317 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
318 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
319 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
320 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
321 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
322 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
323 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
324 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
325 #if HAVE_DECL_ACL_SYNCHRONIZE
326 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
327 #endif
328 #elif ARCHIVE_ACL_LIBRICHACL
329 {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
330 {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
331 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
332 {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
333 {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
334 {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
335 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
336 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
337 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
338 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
339 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
340 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
341 {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
342 {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
343 {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
344 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
345 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
346 #else /* FreeBSD NFSv4 ACL permissions */
347 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
348 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
349 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
350 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
351 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
352 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
353 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
354 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
355 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
356 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
357 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
358 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
359 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
360 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
361 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
362 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
363 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
364 #endif
365 };
366 int i, permset = 0;
367
368 for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
369 #if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
370 if (mask & perms[i].machine)
371 #else
372 if (acl_get_perm_np(opaque_ps, perms[i].machine))
373 #endif
374 permset |= perms[i].portable;
375 return permset;
376 }
377
378 static int
379 #if ARCHIVE_ACL_SUNOS_NFS4
acl_flagset_to_bitmap(uint16_t flags)380 acl_flagset_to_bitmap(uint16_t flags)
381 #elif ARCHIVE_ACL_LIBRICHACL
382 acl_flagset_to_bitmap(int flags)
383 #else
384 acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
385 #endif
386 {
387 static struct { int portable; int machine; } perms[] = {
388 #if ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL inheritance flags */
389 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
390 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
391 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
392 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
393 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
394 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
395 #ifdef ACE_INHERITED_ACE
396 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
397 #endif
398 #elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL inheritance flags */
399 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
400 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
401 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
402 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
403 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
404 #elif ARCHIVE_ACL_LIBRICHACL
405 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
406 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
407 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
408 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
409 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
410 #else /* FreeBSD NFSv4 ACL inheritance flags */
411 #ifdef ACL_ENTRY_INHERITED
412 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
413 #endif
414 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
415 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
416 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
417 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
418 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
419 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
420 #endif
421 };
422 int i, flagset = 0;
423
424 for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
425 #if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
426 if (flags & perms[i].machine)
427 #else
428 if (acl_get_flag_np(opaque_fs, perms[i].machine))
429 #endif
430 flagset |= perms[i].portable;
431 return flagset;
432 }
433
434 #if ARCHIVE_ACL_SUNOS_NFS4
435 static int
acl_match(ace_t * ace,struct myacl_t * myacl)436 acl_match(ace_t *ace, struct myacl_t *myacl)
437 {
438 int perms;
439
440 perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
441
442 if (perms != myacl->permset)
443 return (0);
444
445 switch (ace->a_type) {
446 case ACE_ACCESS_ALLOWED_ACE_TYPE:
447 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
448 return (0);
449 break;
450 case ACE_ACCESS_DENIED_ACE_TYPE:
451 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
452 return (0);
453 break;
454 case ACE_SYSTEM_AUDIT_ACE_TYPE:
455 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
456 return (0);
457 break;
458 case ACE_SYSTEM_ALARM_ACE_TYPE:
459 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
460 return (0);
461 break;
462 default:
463 return (0);
464 }
465
466 if (ace->a_flags & ACE_OWNER) {
467 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
468 return (0);
469 } else if (ace->a_flags & ACE_GROUP) {
470 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
471 return (0);
472 } else if (ace->a_flags & ACE_EVERYONE) {
473 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
474 return (0);
475 } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
476 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
477 return (0);
478 if ((gid_t)myacl->qual != ace->a_who)
479 return (0);
480 } else {
481 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
482 return (0);
483 if ((uid_t)myacl->qual != ace->a_who)
484 return (0);
485 }
486 return (1);
487 }
488 #elif ARCHIVE_ACL_LIBRICHACL
489 static int
acl_match(struct richace * richace,struct myacl_t * myacl)490 acl_match(struct richace *richace, struct myacl_t *myacl)
491 {
492 int perms;
493
494 perms = acl_permset_to_bitmap(richace->e_mask) |
495 acl_flagset_to_bitmap(richace->e_flags);
496
497 if (perms != myacl->permset)
498 return (0);
499
500 switch (richace->e_type) {
501 case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
502 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
503 return (0);
504 break;
505 case RICHACE_ACCESS_DENIED_ACE_TYPE:
506 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
507 return (0);
508 break;
509 default:
510 return (0);
511 }
512
513 if (richace->e_flags & RICHACE_SPECIAL_WHO) {
514 switch (richace->e_id) {
515 case RICHACE_OWNER_SPECIAL_ID:
516 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
517 return (0);
518 break;
519 case RICHACE_GROUP_SPECIAL_ID:
520 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
521 return (0);
522 break;
523 case RICHACE_EVERYONE_SPECIAL_ID:
524 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
525 return (0);
526 break;
527 default:
528 /* Invalid e_id */
529 return (0);
530 }
531 } else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
532 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
533 return (0);
534 if ((gid_t)myacl->qual != richace->e_id)
535 return (0);
536 } else {
537 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
538 return (0);
539 if ((uid_t)myacl->qual != richace->e_id)
540 return (0);
541 }
542 return (1);
543 }
544 #elif ARCHIVE_ACL_DARWIN
545 static int
acl_match(acl_entry_t aclent,struct myacl_t * myacl)546 acl_match(acl_entry_t aclent, struct myacl_t *myacl)
547 {
548 void *q;
549 uid_t ugid;
550 int r, idtype;
551 acl_tag_t tag_type;
552 acl_permset_t opaque_ps;
553 acl_flagset_t opaque_fs;
554 int perms;
555
556 acl_get_tag_type(aclent, &tag_type);
557
558 /* translate the silly opaque permset to a bitmap */
559 acl_get_permset(aclent, &opaque_ps);
560 acl_get_flagset_np(aclent, &opaque_fs);
561 perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
562 if (perms != myacl->permset)
563 return (0);
564
565 r = 0;
566 switch (tag_type) {
567 case ACL_EXTENDED_ALLOW:
568 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
569 return (0);
570 break;
571 case ACL_EXTENDED_DENY:
572 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
573 return (0);
574 break;
575 default:
576 return (0);
577 }
578 q = acl_get_qualifier(aclent);
579 if (q == NULL)
580 return (0);
581 r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
582 acl_free(q);
583 if (r != 0)
584 return (0);
585 switch (idtype) {
586 case ID_TYPE_UID:
587 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
588 return (0);
589 if ((uid_t)myacl->qual != ugid)
590 return (0);
591 break;
592 case ID_TYPE_GID:
593 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
594 return (0);
595 if ((gid_t)myacl->qual != ugid)
596 return (0);
597 break;
598 default:
599 return (0);
600 }
601 return (1);
602 }
603 #else /* ARCHIVE_ACL_FREEBSD_NFS4 */
604 static int
acl_match(acl_entry_t aclent,struct myacl_t * myacl)605 acl_match(acl_entry_t aclent, struct myacl_t *myacl)
606 {
607 gid_t g, *gp;
608 uid_t u, *up;
609 acl_entry_type_t entry_type;
610 acl_tag_t tag_type;
611 acl_permset_t opaque_ps;
612 acl_flagset_t opaque_fs;
613 int perms;
614
615 acl_get_tag_type(aclent, &tag_type);
616 acl_get_entry_type_np(aclent, &entry_type);
617
618 /* translate the silly opaque permset to a bitmap */
619 acl_get_permset(aclent, &opaque_ps);
620 acl_get_flagset_np(aclent, &opaque_fs);
621 perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
622 if (perms != myacl->permset)
623 return (0);
624
625 switch (entry_type) {
626 case ACL_ENTRY_TYPE_ALLOW:
627 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
628 return (0);
629 break;
630 case ACL_ENTRY_TYPE_DENY:
631 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
632 return (0);
633 break;
634 case ACL_ENTRY_TYPE_AUDIT:
635 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
636 return (0);
637 break;
638 case ACL_ENTRY_TYPE_ALARM:
639 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
640 return (0);
641 break;
642 default:
643 return (0);
644 }
645
646 switch (tag_type) {
647 case ACL_USER_OBJ:
648 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
649 break;
650 case ACL_USER:
651 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
652 return (0);
653 up = acl_get_qualifier(aclent);
654 u = *up;
655 acl_free(up);
656 if ((uid_t)myacl->qual != u)
657 return (0);
658 break;
659 case ACL_GROUP_OBJ:
660 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
661 break;
662 case ACL_GROUP:
663 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
664 return (0);
665 gp = acl_get_qualifier(aclent);
666 g = *gp;
667 acl_free(gp);
668 if ((gid_t)myacl->qual != g)
669 return (0);
670 break;
671 case ACL_MASK:
672 if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
673 break;
674 case ACL_EVERYONE:
675 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
676 break;
677 }
678 return (1);
679 }
680 #endif /* various ARCHIVE_ACL_NFS4 implementations */
681
682 static void
compare_acls(void * aclp,int aclcnt,struct myacl_t * myacls,const char * filename,int start,int end)683 compare_acls(
684 #if ARCHIVE_ACL_SUNOS_NFS4
685 void *aclp,
686 int aclcnt,
687 #elif ARCHIVE_ACL_LIBRICHACL
688 struct richacl *richacl,
689 #else
690 acl_t acl,
691 #endif
692 struct myacl_t *myacls, const char *filename, int start, int end)
693 {
694 int *marker;
695 int matched;
696 int i, n;
697 #if ARCHIVE_ACL_SUNOS_NFS4
698 int e;
699 ace_t *acl_entry;
700 #elif ARCHIVE_ACL_LIBRICHACL
701 int e;
702 struct richace *acl_entry;
703 int aclcnt;
704 #else
705 int entry_id = ACL_FIRST_ENTRY;
706 acl_entry_t acl_entry;
707 #if ARCHIVE_ACL_DARWIN
708 const int acl_get_entry_ret = 0;
709 #else
710 const int acl_get_entry_ret = 1;
711 #endif
712 #endif
713
714 #if ARCHIVE_ACL_SUNOS_NFS4
715 if (aclp == NULL)
716 return;
717 #elif ARCHIVE_ACL_LIBRICHACL
718 if (richacl == NULL)
719 return;
720 aclcnt = richacl->a_count;
721 #else
722 if (acl == NULL)
723 return;
724 #endif
725
726 n = end - start;
727 marker = malloc(sizeof(marker[0]) * (n + 1));
728 for (i = 0; i < n; i++)
729 marker[i] = i + start;
730 #if !ARCHIVE_ACL_DARWIN
731 /* Always include the first ACE. */
732 if (start > 0) {
733 marker[n] = 0;
734 ++n;
735 }
736 #endif
737
738 /*
739 * Iterate over acls in system acl object, try to match each
740 * one with an item in the myacls array.
741 */
742 #if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
743 for (e = 0; e < aclcnt; e++)
744 #else
745 while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
746 #endif
747 {
748 #if ARCHIVE_ACL_SUNOS_NFS4
749 acl_entry = &((ace_t *)aclp)[e];
750 #elif ARCHIVE_ACL_LIBRICHACL
751 acl_entry = &(richacl->a_entries[e]);
752 #else
753 /* After the first time... */
754 entry_id = ACL_NEXT_ENTRY;
755 #endif
756 /* Search for a matching entry (tag and qualifier) */
757 for (i = 0, matched = 0; i < n && !matched; i++) {
758 if (acl_match(acl_entry, &myacls[marker[i]])) {
759 /* We found a match; remove it. */
760 marker[i] = marker[n - 1];
761 n--;
762 matched = 1;
763 }
764 }
765
766 failure("ACL entry on file %s that shouldn't be there",
767 filename);
768 assert(matched == 1);
769 }
770
771 /* Dump entries in the myacls array that weren't in the system acl. */
772 for (i = 0; i < n; ++i) {
773 failure(" ACL entry %d missing from %s: "
774 "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
775 marker[i], filename,
776 myacls[marker[i]].type, myacls[marker[i]].permset,
777 myacls[marker[i]].tag, myacls[marker[i]].qual,
778 myacls[marker[i]].name);
779 assert(0); /* Record this as a failure. */
780 }
781 free(marker);
782 }
783
784 static void
compare_entry_acls(struct archive_entry * ae,struct myacl_t * myacls,const char * filename,int start,int end)785 compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
786 {
787 int *marker;
788 int matched;
789 int i, n;
790 int type, permset, tag, qual;
791 const char *name;
792
793 /* Count ACL entries in myacls array and allocate an indirect array. */
794 n = end - start;
795 marker = malloc(sizeof(marker[0]) * (n + 1));
796 for (i = 0; i < n; i++)
797 marker[i] = i + start;
798 /* Always include the first ACE. */
799 if (start > 0) {
800 marker[n] = 0;
801 ++n;
802 }
803
804 /*
805 * Iterate over acls in entry, try to match each
806 * one with an item in the myacls array.
807 */
808 assertEqualInt(n, archive_entry_acl_reset(ae,
809 ARCHIVE_ENTRY_ACL_TYPE_NFS4));
810 while (ARCHIVE_OK == archive_entry_acl_next(ae,
811 ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
812
813 /* Search for a matching entry (tag and qualifier) */
814 for (i = 0, matched = 0; i < n && !matched; i++) {
815 if (tag == myacls[marker[i]].tag
816 && qual == myacls[marker[i]].qual
817 && permset == myacls[marker[i]].permset
818 && type == myacls[marker[i]].type) {
819 /* We found a match; remove it. */
820 marker[i] = marker[n - 1];
821 n--;
822 matched = 1;
823 }
824 }
825
826 failure("ACL entry on file that shouldn't be there: "
827 "type=%#010x,permset=%#010x,tag=%d,qual=%d",
828 type,permset,tag,qual);
829 assert(matched == 1);
830 }
831
832 /* Dump entries in the myacls array that weren't in the system acl. */
833 for (i = 0; i < n; ++i) {
834 failure(" ACL entry %d missing from %s: "
835 "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
836 marker[i], filename,
837 myacls[marker[i]].type, myacls[marker[i]].permset,
838 myacls[marker[i]].tag, myacls[marker[i]].qual,
839 myacls[marker[i]].name);
840 assert(0); /* Record this as a failure. */
841 }
842 free(marker);
843 }
844 #endif /* ARCHIVE_ACL_NFS4 */
845
846 /*
847 * Verify ACL restore-to-disk. This test is Platform-specific.
848 */
849
DEFINE_TEST(test_acl_platform_nfs4)850 DEFINE_TEST(test_acl_platform_nfs4)
851 {
852 #if !ARCHIVE_ACL_NFS4
853 skipping("NFS4 ACLs are not supported on this platform");
854 #else /* ARCHIVE_ACL_NFS4 */
855 char buff[64];
856 int i;
857 struct stat st;
858 struct archive *a;
859 struct archive_entry *ae;
860 #if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */
861 const int regcnt = acls_reg_cnt - 4;
862 const int dircnt = acls_dir_cnt - 4;
863 #else
864 const int regcnt = acls_reg_cnt;
865 const int dircnt = acls_dir_cnt;
866 #endif
867 #if ARCHIVE_ACL_SUNOS_NFS4
868 void *aclp;
869 int aclcnt;
870 #elif ARCHIVE_ACL_LIBRICHACL
871 struct richacl *richacl;
872 #else /* !ARCHIVE_ACL_SUNOS_NFS4 */
873 acl_t acl;
874 #endif
875
876 assertMakeFile("pretest", 0644, "a");
877
878 if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
879 skipping("NFS4 ACLs are not writable on this filesystem");
880 return;
881 }
882
883 /* Create a write-to-disk object. */
884 assert(NULL != (a = archive_write_disk_new()));
885 archive_write_disk_set_options(a,
886 ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
887
888 /* Populate an archive entry with some metadata, including ACL info */
889 ae = archive_entry_new();
890 assert(ae != NULL);
891 archive_entry_set_pathname(ae, "testall");
892 archive_entry_set_filetype(ae, AE_IFREG);
893 archive_entry_set_perm(ae, 0654);
894 archive_entry_set_mtime(ae, 123456, 7890);
895 archive_entry_set_size(ae, 0);
896 set_acls(ae, acls_reg, 0, acls_reg_cnt);
897
898 /* Write the entry to disk, including ACLs. */
899 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
900
901 /* Likewise for a dir. */
902 archive_entry_set_pathname(ae, "dirall");
903 archive_entry_set_filetype(ae, AE_IFDIR);
904 archive_entry_set_perm(ae, 0654);
905 archive_entry_set_mtime(ae, 123456, 7890);
906 set_acls(ae, acls_dir, 0, acls_dir_cnt);
907 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
908
909 for (i = 0; i < acls_dir_cnt; ++i) {
910 sprintf(buff, "dir%d", i);
911 archive_entry_set_pathname(ae, buff);
912 archive_entry_set_filetype(ae, AE_IFDIR);
913 archive_entry_set_perm(ae, 0654);
914 archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
915 set_acls(ae, acls_dir, i, i + 1);
916 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
917 }
918
919 archive_entry_free(ae);
920
921 /* Close the archive. */
922 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
923 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
924
925 /* Verify the data on disk. */
926 assertEqualInt(0, stat("testall", &st));
927 assertEqualInt(st.st_mtime, 123456);
928 #if ARCHIVE_ACL_SUNOS_NFS4
929 aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
930 failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
931 strerror(errno));
932 assert(aclp != NULL);
933 #elif ARCHIVE_ACL_LIBRICHACL
934 richacl = richacl_get_file("testall");
935 failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
936 strerror(errno));
937 assert(richacl != NULL);
938 #else
939 #if ARCHIVE_ACL_DARWIN
940 acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
941 #else
942 acl = acl_get_file("testall", ACL_TYPE_NFS4);
943 #endif
944 failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
945 strerror(errno));
946 assert(acl != (acl_t)NULL);
947 #endif
948 #if ARCHIVE_ACL_SUNOS_NFS4
949 compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
950 free(aclp);
951 aclp = NULL;
952 #elif ARCHIVE_ACL_LIBRICHACL
953 compare_acls(richacl, acls_reg, "testall", 0, regcnt);
954 richacl_free(richacl);
955 #else
956 compare_acls(acl, acls_reg, "testall", 0, regcnt);
957 acl_free(acl);
958 #endif
959
960
961 /* Verify single-permission dirs on disk. */
962 for (i = 0; i < dircnt; ++i) {
963 sprintf(buff, "dir%d", i);
964 assertEqualInt(0, stat(buff, &st));
965 assertEqualInt(st.st_mtime, 123456 + i);
966 #if ARCHIVE_ACL_SUNOS_NFS4
967 aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
968 failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
969 strerror(errno));
970 assert(aclp != NULL);
971 #elif ARCHIVE_ACL_LIBRICHACL
972 richacl = richacl_get_file(buff);
973 /* First and last two dir do not return a richacl */
974 if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
975 errno == ENODATA)
976 continue;
977 failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
978 errno, strerror(errno));
979 assert(richacl != NULL);
980 #else
981 #if ARCHIVE_ACL_DARWIN
982 acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
983 #else
984 acl = acl_get_file(buff, ACL_TYPE_NFS4);
985 #endif
986 failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
987 strerror(errno));
988 assert(acl != (acl_t)NULL);
989 #endif
990 #if ARCHIVE_ACL_SUNOS_NFS4
991 compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
992 free(aclp);
993 aclp = NULL;
994 #elif ARCHIVE_ACL_LIBRICHACL
995 compare_acls(richacl, acls_dir, buff, i, i + 1);
996 richacl_free(richacl);
997 #else
998 compare_acls(acl, acls_dir, buff, i, i + 1);
999 acl_free(acl);
1000 #endif
1001 }
1002
1003 /* Verify "dirall" on disk. */
1004 assertEqualInt(0, stat("dirall", &st));
1005 assertEqualInt(st.st_mtime, 123456);
1006 #if ARCHIVE_ACL_SUNOS_NFS4
1007 aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
1008 failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
1009 strerror(errno));
1010 assert(aclp != NULL);
1011 #elif ARCHIVE_ACL_LIBRICHACL
1012 richacl = richacl_get_file("dirall");
1013 failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
1014 errno, strerror(errno));
1015 assert(richacl != NULL);
1016 #else
1017 #if ARCHIVE_ACL_DARWIN
1018 acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
1019 #else
1020 acl = acl_get_file("dirall", ACL_TYPE_NFS4);
1021 #endif
1022 failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
1023 strerror(errno));
1024 assert(acl != (acl_t)NULL);
1025 #endif
1026 #if ARCHIVE_ACL_SUNOS_NFS4
1027 compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
1028 free(aclp);
1029 aclp = NULL;
1030 #elif ARCHIVE_ACL_LIBRICHACL
1031 compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
1032 richacl_free(richacl);
1033 #else
1034 compare_acls(acl, acls_dir, "dirall", 0, dircnt);
1035 acl_free(acl);
1036 #endif
1037
1038 /* Read and compare ACL via archive_read_disk */
1039 a = archive_read_disk_new();
1040 assert(a != NULL);
1041 ae = archive_entry_new();
1042 assert(ae != NULL);
1043 archive_entry_set_pathname(ae, "testall");
1044 assertEqualInt(ARCHIVE_OK,
1045 archive_read_disk_entry_from_file(a, ae, -1, NULL));
1046 compare_entry_acls(ae, acls_reg, "testall", 0, acls_reg_cnt);
1047 archive_entry_free(ae);
1048 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1049
1050 /* Read and compare ACL via archive_read_disk */
1051 a = archive_read_disk_new();
1052 assert(a != NULL);
1053 ae = archive_entry_new();
1054 assert(ae != NULL);
1055 archive_entry_set_pathname(ae, "dirall");
1056 assertEqualInt(ARCHIVE_OK,
1057 archive_read_disk_entry_from_file(a, ae, -1, NULL));
1058 compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
1059 archive_entry_free(ae);
1060 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1061 #endif /* ARCHIVE_ACL_NFS4 */
1062 }
1063