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