test_acl_platform_nfs4.c revision 316337
1203955Srdivacky/*-
2198092Srdivacky * Copyright (c) 2003-2010 Tim Kientzle
3198092Srdivacky * Copyright (c) 2017 Martin Matuska
4198092Srdivacky * All rights reserved.
5198092Srdivacky *
6198092Srdivacky * Redistribution and use in source and binary forms, with or without
7198092Srdivacky * modification, are permitted provided that the following conditions
8198092Srdivacky * are met:
9239462Sdim * 1. Redistributions of source code must retain the above copyright
10239462Sdim *    notice, this list of conditions and the following disclaimer.
11239462Sdim * 2. Redistributions in binary form must reproduce the above copyright
12239462Sdim *    notice, this list of conditions and the following disclaimer in the
13239462Sdim *    documentation and/or other materials provided with the distribution.
14198092Srdivacky *
15198092Srdivacky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16198092Srdivacky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17198092Srdivacky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18198092Srdivacky * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19198092Srdivacky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20198092Srdivacky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21198092Srdivacky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22249423Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23218893Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24206084Srdivacky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25198092Srdivacky */
26198092Srdivacky#include "test.h"
27198092Srdivacky__FBSDID("$FreeBSD$");
28198092Srdivacky
29206084Srdivacky#if ARCHIVE_ACL_NFS4
30234353Sdim#if HAVE_SYS_ACL_H
31234353Sdim#define _ACL_PRIVATE
32234353Sdim#include <sys/acl.h>
33234353Sdim#endif
34234353Sdim#if HAVE_SYS_RICHACL_H
35234353Sdim#include <sys/richacl.h>
36234353Sdim#endif
37234353Sdim#if HAVE_MEMBERSHIP_H
38198092Srdivacky#include <membership.h>
39234353Sdim#endif
40198092Srdivacky
41198092Srdivackystruct myacl_t {
42239462Sdim	int type;
43198092Srdivacky	int permset;
44239462Sdim	int tag;
45198092Srdivacky	int qual; /* GID or UID of user/group, depending on tag. */
46198092Srdivacky	const char *name; /* Name of user/group, depending on tag. */
47234353Sdim};
48198092Srdivacky
49234353Sdimstatic struct myacl_t acls_reg[] = {
50239462Sdim#if !ARCHIVE_ACL_DARWIN
51198092Srdivacky	/* For this test, we need the file owner to be able to read and write the ACL. */
52234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
53239462Sdim	  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,
54198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
55198092Srdivacky#endif
56239462Sdim	/* An entry for each type. */
57239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
58198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
59234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
60239462Sdim	  ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
61239462Sdim
62234353Sdim	/* An entry for each permission. */
63221345Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
64198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
65200583Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
66234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
67218893Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
68218893Sdim	  ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
69218893Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
70234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
71239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
72239462Sdim	  ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
73239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
74210299Sed	  ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
75234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
76239462Sdim	  ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
77239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
78234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
79198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
80198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
81234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
82206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
83206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
84219077Sdim	  ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
85206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
86206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
87206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
88234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
89206084Srdivacky
90206084Srdivacky	/* One entry for each qualifier. */
91206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
92234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
93206084Srdivacky//	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
94206084Srdivacky//	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
95206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
96206084Srdivacky	  ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
97234353Sdim#if !ARCHIVE_ACL_DARWIN
98206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
99206084Srdivacky	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
100206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
101234353Sdim	  ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
102206084Srdivacky#else	/* MacOS - mode 0654 */
103206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
104234353Sdim	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
105206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
106206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_DATA |
107206084Srdivacky	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
108206084Srdivacky	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
109206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
110206084Srdivacky	    ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
111234353Sdim	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
112206084Srdivacky	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
113206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ACL |
114206084Srdivacky	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
115234353Sdim	    ARCHIVE_ENTRY_ACL_WRITE_OWNER |
116206084Srdivacky	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
117205219Srdivacky	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
118205219Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
119205219Srdivacky	    ARCHIVE_ENTRY_ACL_READ_DATA |
120205219Srdivacky	    ARCHIVE_ENTRY_ACL_EXECUTE |
121239462Sdim	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
122198092Srdivacky	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
123234353Sdim	    ARCHIVE_ENTRY_ACL_READ_ACL |
124239462Sdim	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
125198092Srdivacky	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
126198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
127206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_DATA |
128206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
129234353Sdim	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
130206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ACL |
131206084Srdivacky	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
132206084Srdivacky	  ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
133206084Srdivacky#endif
134234353Sdim};
135206084Srdivacky
136206084Srdivackystatic const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
137206084Srdivacky
138206084Srdivackystatic struct myacl_t acls_dir[] = {
139206084Srdivacky	/* For this test, we need to be able to read and write the ACL. */
140206084Srdivacky#if !ARCHIVE_ACL_DARWIN
141206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
142206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
143234353Sdim#endif
144234353Sdim
145198092Srdivacky	/* An entry for each type. */
146206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
147234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
148234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
149234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
150234353Sdim
151234353Sdim	/* An entry for each permission. */
152234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
153234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
154234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
155234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
156234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
157234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
158206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
159206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
160206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
161206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
162206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
163198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
164234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
165210299Sed	  ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
166198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
167206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
168198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
169234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
170198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
171198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
172200583Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
173234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
174198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
175206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
176202379Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
177202379Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
178234353Sdim
179202379Srdivacky	/* One entry with each inheritance value. */
180206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
181202379Srdivacky	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
182234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
183202379Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
184234353Sdim	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
185198092Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
186239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
187239462Sdim	  ARCHIVE_ENTRY_ACL_READ_DATA |
188239462Sdim	  ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
189239462Sdim	  ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
190239462Sdim	  ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
191239462Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
192206084Srdivacky	  ARCHIVE_ENTRY_ACL_READ_DATA |
193206084Srdivacky	  ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
194234353Sdim	  ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
195234353Sdim	  ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
196206084Srdivacky#if !defined(ARCHIVE_ACL_SUNOS_NFS4) || defined(ACE_INHERITED_ACE)
197200583Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
198206084Srdivacky	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
199206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
200206084Srdivacky#endif
201206084Srdivacky
202206084Srdivacky#if 0
203206084Srdivacky	/* FreeBSD does not support audit entries. */
204249423Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
205249423Sdim	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
206249423Sdim	  ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
207249423Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
208249423Sdim	  ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
209249423Sdim	  ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
210249423Sdim#endif
211249423Sdim
212234353Sdim	/* One entry for each qualifier. */
213234353Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
214206084Srdivacky	  ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
215206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
216200583Srdivacky	  ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
217206084Srdivacky#if !ARCHIVE_ACL_DARWIN
218198092Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
219234353Sdim	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
220226633Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
221218893Sdim	  ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
222218893Sdim#else	/* MacOS - mode 0654 */
223218893Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
224218893Sdim	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
225226633Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
226218893Sdim	    ARCHIVE_ENTRY_ACL_READ_DATA |
227218893Sdim	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
228218893Sdim	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
229218893Sdim	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
230234353Sdim	    ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
231218893Sdim	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
232218893Sdim	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
233218893Sdim	    ARCHIVE_ENTRY_ACL_READ_ACL |
234234353Sdim	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
235218893Sdim	    ARCHIVE_ENTRY_ACL_WRITE_OWNER |
236218893Sdim	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
237218893Sdim	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
238218893Sdim	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
239234353Sdim	    ARCHIVE_ENTRY_ACL_READ_DATA |
240200583Srdivacky	    ARCHIVE_ENTRY_ACL_EXECUTE |
241200583Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
242200583Srdivacky	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
243206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ACL |
244206084Srdivacky	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
245234353Sdim	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
246206084Srdivacky	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
247200583Srdivacky	    ARCHIVE_ENTRY_ACL_READ_DATA |
248206084Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
249200583Srdivacky	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
250200583Srdivacky	    ARCHIVE_ENTRY_ACL_READ_ACL |
251200583Srdivacky	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
252200583Srdivacky	  ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
253200583Srdivacky#endif
254249423Sdim};
255249423Sdim
256249423Sdimstatic const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0]));
257249423Sdim
258249423Sdimstatic void
259249423Sdimset_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
260249423Sdim{
261249423Sdim	int i;
262249423Sdim
263249423Sdim	archive_entry_acl_clear(ae);
264249423Sdim#if !ARCHIVE_ACL_DARWIN
265249423Sdim	if (start > 0) {
266249423Sdim		assertEqualInt(ARCHIVE_OK,
267198092Srdivacky			archive_entry_acl_add_entry(ae,
268206084Srdivacky			    acls[0].type, acls[0].permset, acls[0].tag,
269198092Srdivacky			    acls[0].qual, acls[0].name));
270198092Srdivacky	}
271239462Sdim#endif
272239462Sdim	for (i = start; i < end; i++) {
273239462Sdim		assertEqualInt(ARCHIVE_OK,
274239462Sdim		    archive_entry_acl_add_entry(ae,
275239462Sdim			acls[i].type, acls[i].permset, acls[i].tag,
276239462Sdim			acls[i].qual, acls[i].name));
277198092Srdivacky	}
278198092Srdivacky}
279226633Sdim
280206084Srdivackystatic int
281206084Srdivacky#if ARCHIVE_ACL_SUNOS_NFS4
282206084Srdivackyacl_permset_to_bitmap(uint32_t mask)
283206084Srdivacky#elif ARCHIVE_ACL_LIBRICHACL
284206084Srdivackyacl_permset_to_bitmap(unsigned int mask)
285206084Srdivacky#else
286206084Srdivackyacl_permset_to_bitmap(acl_permset_t opaque_ps)
287206084Srdivacky#endif
288206084Srdivacky{
289226633Sdim	static struct { int portable; int machine; } perms[] = {
290218893Sdim#ifdef ARCHIVE_ACL_SUNOS_NFS4	/* Solaris NFSv4 ACL permissions */
291218893Sdim		{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
292234353Sdim		{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
293218893Sdim		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
294218893Sdim		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
295218893Sdim		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
296226633Sdim		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
297218893Sdim		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
298218893Sdim		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
299218893Sdim		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
300198092Srdivacky		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
301198092Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
302198092Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
303234353Sdim		{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
304198092Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
305198092Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
306226633Sdim		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
307226633Sdim		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
308218893Sdim#elif ARCHIVE_ACL_DARWIN	/* MacOS NFSv4 ACL permissions */
309218893Sdim		{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
310218893Sdim		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
311226633Sdim		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
312198092Srdivacky		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
313234353Sdim		{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
314198092Srdivacky		{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
315198092Srdivacky		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
316200583Srdivacky		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
317234353Sdim		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
318218893Sdim		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
319234353Sdim		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
320206084Srdivacky		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
321198092Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
322234353Sdim		{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
323239462Sdim		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
324249423Sdim		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
325239462Sdim#if HAVE_DECL_ACL_SYNCHRONIZE
326239462Sdim		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
327239462Sdim#endif
328239462Sdim#elif ARCHIVE_ACL_LIBRICHACL
329239462Sdim		{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
330239462Sdim		{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
331239462Sdim		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
332239462Sdim		{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
333239462Sdim		{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
334239462Sdim		{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
335206084Srdivacky		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
336206084Srdivacky		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
337206084Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
338206084Srdivacky		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
339206084Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
340198092Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
341234353Sdim		{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
342206084Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
343234353Sdim		{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
344198092Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
345198092Srdivacky		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
346226633Sdim#else	/* FreeBSD NFSv4 ACL permissions */
347198092Srdivacky		{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
348198092Srdivacky		{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
349198893Srdivacky		{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
350198893Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
351198893Srdivacky		{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
352226633Sdim		{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
353198893Srdivacky		{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
354198893Srdivacky		{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
355198893Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
356198092Srdivacky		{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
357198893Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
358226633Sdim		{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
359226633Sdim		{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
360198893Srdivacky		{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
361198893Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
362198893Srdivacky		{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
363198893Srdivacky		{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
364226633Sdim#endif
365234353Sdim	};
366218893Sdim	int i, permset = 0;
367218893Sdim
368218893Sdim	for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
369234353Sdim#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
370218893Sdim		if (mask & perms[i].machine)
371198092Srdivacky#else
372210299Sed		if (acl_get_perm_np(opaque_ps, perms[i].machine))
373210299Sed#endif
374210299Sed			permset |= perms[i].portable;
375210299Sed	return permset;
376210299Sed}
377210299Sed
378198092Srdivackystatic int
379198092Srdivacky#if ARCHIVE_ACL_SUNOS_NFS4
380198092Srdivackyacl_flagset_to_bitmap(uint16_t flags)
381234353Sdim#elif ARCHIVE_ACL_LIBRICHACL
382198092Srdivackyacl_flagset_to_bitmap(int flags)
383206084Srdivacky#else
384206084Srdivackyacl_flagset_to_bitmap(acl_flagset_t opaque_fs)
385202379Srdivacky#endif
386202379Srdivacky{
387234353Sdim	static struct { int portable; int machine; } perms[] = {
388198092Srdivacky#if ARCHIVE_ACL_SUNOS_NFS4	/* Solaris NFSv4 ACL inheritance flags */
389198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
390198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
391198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
392198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
393198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
394198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
395234353Sdim#ifdef ACE_INHERITED_ACE
396218893Sdim		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
397218893Sdim#endif
398218893Sdim#elif ARCHIVE_ACL_DARWIN	/* MacOS NFSv4 ACL inheritance flags */
399198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
400198092Srdivacky		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
401206084Srdivacky		{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		{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
412		{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
413		{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
414		{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
415		{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
416		{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
417		{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
418#endif
419	};
420	int i, flagset = 0;
421
422	for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
423#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
424		if (flags & perms[i].machine)
425#else
426		if (acl_get_flag_np(opaque_fs, perms[i].machine))
427#endif
428			flagset |= perms[i].portable;
429	return flagset;
430}
431
432#if ARCHIVE_ACL_SUNOS_NFS4
433static int
434acl_match(ace_t *ace, struct myacl_t *myacl)
435{
436	int perms;
437
438	perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
439
440	if (perms != myacl->permset)
441		return (0);
442
443	switch (ace->a_type) {
444	case ACE_ACCESS_ALLOWED_ACE_TYPE:
445		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
446			return (0);
447		break;
448	case ACE_ACCESS_DENIED_ACE_TYPE:
449		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
450			return (0);
451		break;
452	case ACE_SYSTEM_AUDIT_ACE_TYPE:
453		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
454			return (0);
455		break;
456	case ACE_SYSTEM_ALARM_ACE_TYPE:
457		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
458			return (0);
459		break;
460	default:
461		return (0);
462	}
463
464	if (ace->a_flags & ACE_OWNER) {
465		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
466			return (0);
467	} else if (ace->a_flags & ACE_GROUP) {
468		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
469			return (0);
470	} else if (ace->a_flags & ACE_EVERYONE) {
471		if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
472			return (0);
473	} else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
474		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
475			return (0);
476		if ((gid_t)myacl->qual != ace->a_who)
477			return (0);
478	} else {
479		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
480			return (0);
481		if ((uid_t)myacl->qual != ace->a_who)
482			return (0);
483	}
484	return (1);
485}
486#elif ARCHIVE_ACL_LIBRICHACL
487static int
488acl_match(struct richace *richace, struct myacl_t *myacl)
489{
490	int perms;
491
492	perms = acl_permset_to_bitmap(richace->e_mask) |
493	    acl_flagset_to_bitmap(richace->e_flags);
494
495	if (perms != myacl->permset)
496		return (0);
497
498	switch (richace->e_type) {
499	case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
500		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
501			return (0);
502		break;
503	case RICHACE_ACCESS_DENIED_ACE_TYPE:
504		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
505			return (0);
506		break;
507	default:
508		return (0);
509	}
510
511	if (richace->e_flags & RICHACE_SPECIAL_WHO) {
512		switch (richace->e_id) {
513		case RICHACE_OWNER_SPECIAL_ID:
514			if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
515				return (0);
516			break;
517		case RICHACE_GROUP_SPECIAL_ID:
518			if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
519				return (0);
520			break;
521		case RICHACE_EVERYONE_SPECIAL_ID:
522			if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
523				return (0);
524			break;
525		default:
526			/* Invalid e_id */
527			return (0);
528		}
529	} else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
530		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
531			return (0);
532		if ((gid_t)myacl->qual != richace->e_id)
533			return (0);
534	} else {
535		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
536			return (0);
537		if ((uid_t)myacl->qual != richace->e_id)
538			return (0);
539	}
540	return (1);
541}
542#elif ARCHIVE_ACL_DARWIN
543static int
544acl_match(acl_entry_t aclent, struct myacl_t *myacl)
545{
546	void *q;
547	uid_t ugid;
548	int r, idtype;
549	acl_tag_t tag_type;
550	acl_permset_t opaque_ps;
551	acl_flagset_t opaque_fs;
552	int perms;
553
554	acl_get_tag_type(aclent, &tag_type);
555
556	/* translate the silly opaque permset to a bitmap */
557	acl_get_permset(aclent, &opaque_ps);
558	acl_get_flagset_np(aclent, &opaque_fs);
559	perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
560	if (perms != myacl->permset)
561		return (0);
562
563	r = 0;
564	switch (tag_type) {
565	case ACL_EXTENDED_ALLOW:
566		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
567			return (0);
568		break;
569	case ACL_EXTENDED_DENY:
570		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
571			return (0);
572		break;
573	default:
574		return (0);
575	}
576	q = acl_get_qualifier(aclent);
577	if (q == NULL)
578		return (0);
579	r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
580	acl_free(q);
581	if (r != 0)
582		return (0);
583	switch (idtype) {
584		case ID_TYPE_UID:
585			if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
586				return (0);
587			if ((uid_t)myacl->qual != ugid)
588				return (0);
589			break;
590		case ID_TYPE_GID:
591			if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
592				return (0);
593			if ((gid_t)myacl->qual != ugid)
594				return (0);
595			break;
596		default:
597			return (0);
598	}
599	return (1);
600}
601#else /* ARCHIVE_ACL_FREEBSD_NFS4 */
602static int
603acl_match(acl_entry_t aclent, struct myacl_t *myacl)
604{
605	gid_t g, *gp;
606	uid_t u, *up;
607	acl_entry_type_t entry_type;
608	acl_tag_t tag_type;
609	acl_permset_t opaque_ps;
610	acl_flagset_t opaque_fs;
611	int perms;
612
613	acl_get_tag_type(aclent, &tag_type);
614	acl_get_entry_type_np(aclent, &entry_type);
615
616	/* translate the silly opaque permset to a bitmap */
617	acl_get_permset(aclent, &opaque_ps);
618	acl_get_flagset_np(aclent, &opaque_fs);
619	perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
620	if (perms != myacl->permset)
621		return (0);
622
623	switch (entry_type) {
624	case ACL_ENTRY_TYPE_ALLOW:
625		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
626			return (0);
627		break;
628	case ACL_ENTRY_TYPE_DENY:
629		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
630			return (0);
631		break;
632	case ACL_ENTRY_TYPE_AUDIT:
633		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
634			return (0);
635	case ACL_ENTRY_TYPE_ALARM:
636		if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
637			return (0);
638	default:
639		return (0);
640	}
641
642	switch (tag_type) {
643	case ACL_USER_OBJ:
644		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
645		break;
646	case ACL_USER:
647		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
648			return (0);
649		up = acl_get_qualifier(aclent);
650		u = *up;
651		acl_free(up);
652		if ((uid_t)myacl->qual != u)
653			return (0);
654		break;
655	case ACL_GROUP_OBJ:
656		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
657		break;
658	case ACL_GROUP:
659		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
660			return (0);
661		gp = acl_get_qualifier(aclent);
662		g = *gp;
663		acl_free(gp);
664		if ((gid_t)myacl->qual != g)
665			return (0);
666		break;
667	case ACL_MASK:
668		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
669		break;
670	case ACL_EVERYONE:
671		if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
672		break;
673	}
674	return (1);
675}
676#endif	/* various ARCHIVE_ACL_NFS4 implementations */
677
678static void
679compare_acls(
680#if ARCHIVE_ACL_SUNOS_NFS4
681    void *aclp,
682    int aclcnt,
683#elif ARCHIVE_ACL_LIBRICHACL
684    struct richacl *richacl,
685#else
686    acl_t acl,
687#endif
688    struct myacl_t *myacls, const char *filename, int start, int end)
689{
690	int *marker;
691	int matched;
692	int i, n;
693#if ARCHIVE_ACL_SUNOS_NFS4
694	int e;
695	ace_t *acl_entry;
696#elif ARCHIVE_ACL_LIBRICHACL
697	int e;
698	struct richace *acl_entry;
699	int aclcnt;
700#else
701	int entry_id = ACL_FIRST_ENTRY;
702	acl_entry_t acl_entry;
703#if ARCHIVE_ACL_DARWIN
704	const int acl_get_entry_ret = 0;
705#else
706	const int acl_get_entry_ret = 1;
707#endif
708#endif
709
710#if ARCHIVE_ACL_SUNOS_NFS4
711	if (aclp == NULL)
712		return;
713#elif ARCHIVE_ACL_LIBRICHACL
714	if (richacl == NULL)
715		return;
716	aclcnt = richacl->a_count;
717#else
718	if (acl == NULL)
719		return;
720#endif
721
722	n = end - start;
723	marker = malloc(sizeof(marker[0]) * (n + 1));
724	for (i = 0; i < n; i++)
725		marker[i] = i + start;
726#if !ARCHIVE_ACL_DARWIN
727	/* Always include the first ACE. */
728	if (start > 0) {
729	  marker[n] = 0;
730	  ++n;
731	}
732#endif
733
734	/*
735	 * Iterate over acls in system acl object, try to match each
736	 * one with an item in the myacls array.
737	 */
738#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
739	for (e = 0; e < aclcnt; e++)
740#else
741	while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
742#endif
743	{
744#if ARCHIVE_ACL_SUNOS_NFS4
745		acl_entry = &((ace_t *)aclp)[e];
746#elif ARCHIVE_ACL_LIBRICHACL
747		acl_entry = &(richacl->a_entries[e]);
748#else
749		/* After the first time... */
750		entry_id = ACL_NEXT_ENTRY;
751#endif
752		/* Search for a matching entry (tag and qualifier) */
753		for (i = 0, matched = 0; i < n && !matched; i++) {
754			if (acl_match(acl_entry, &myacls[marker[i]])) {
755				/* We found a match; remove it. */
756				marker[i] = marker[n - 1];
757				n--;
758				matched = 1;
759			}
760		}
761
762		failure("ACL entry on file %s that shouldn't be there",
763		    filename);
764		assert(matched == 1);
765	}
766
767	/* Dump entries in the myacls array that weren't in the system acl. */
768	for (i = 0; i < n; ++i) {
769		failure(" ACL entry %d missing from %s: "
770		    "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
771		    marker[i], filename,
772		    myacls[marker[i]].type, myacls[marker[i]].permset,
773		    myacls[marker[i]].tag, myacls[marker[i]].qual,
774		    myacls[marker[i]].name);
775		assert(0); /* Record this as a failure. */
776	}
777	free(marker);
778}
779
780static void
781compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
782{
783	int *marker;
784	int matched;
785	int i, n;
786	int type, permset, tag, qual;
787	const char *name;
788
789	/* Count ACL entries in myacls array and allocate an indirect array. */
790	n = end - start;
791	marker = malloc(sizeof(marker[0]) * (n + 1));
792	for (i = 0; i < n; i++)
793		marker[i] = i + start;
794	/* Always include the first ACE. */
795	if (start > 0) {
796	  marker[n] = 0;
797	  ++n;
798	}
799
800	/*
801	 * Iterate over acls in entry, try to match each
802	 * one with an item in the myacls array.
803	 */
804	assertEqualInt(n, archive_entry_acl_reset(ae,
805	    ARCHIVE_ENTRY_ACL_TYPE_NFS4));
806	while (ARCHIVE_OK == archive_entry_acl_next(ae,
807	    ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
808
809		/* Search for a matching entry (tag and qualifier) */
810		for (i = 0, matched = 0; i < n && !matched; i++) {
811			if (tag == myacls[marker[i]].tag
812			    && qual == myacls[marker[i]].qual
813			    && permset == myacls[marker[i]].permset
814			    && type == myacls[marker[i]].type) {
815				/* We found a match; remove it. */
816				marker[i] = marker[n - 1];
817				n--;
818				matched = 1;
819			}
820		}
821
822		failure("ACL entry on file that shouldn't be there: "
823			"type=%#010x,permset=%#010x,tag=%d,qual=%d",
824			type,permset,tag,qual);
825		assert(matched == 1);
826	}
827
828	/* Dump entries in the myacls array that weren't in the system acl. */
829	for (i = 0; i < n; ++i) {
830		failure(" ACL entry %d missing from %s: "
831		    "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
832		    marker[i], filename,
833		    myacls[marker[i]].type, myacls[marker[i]].permset,
834		    myacls[marker[i]].tag, myacls[marker[i]].qual,
835		    myacls[marker[i]].name);
836		assert(0); /* Record this as a failure. */
837	}
838	free(marker);
839}
840#endif	/* ARCHIVE_ACL_NFS4 */
841
842/*
843 * Verify ACL restore-to-disk.  This test is Platform-specific.
844 */
845
846DEFINE_TEST(test_acl_platform_nfs4)
847{
848#if !ARCHIVE_ACL_NFS4
849	skipping("NFS4 ACLs are not supported on this platform");
850#else /* ARCHIVE_ACL_NFS4 */
851	char buff[64];
852	int i;
853	struct stat st;
854	struct archive *a;
855	struct archive_entry *ae;
856#if ARCHIVE_ACL_DARWIN /* On MacOS we skip trivial ACLs in some tests */
857	const int regcnt = acls_reg_cnt - 4;
858	const int dircnt = acls_dir_cnt - 4;
859#else
860	const int regcnt = acls_reg_cnt;
861	const int dircnt = acls_dir_cnt;
862#endif
863#if ARCHIVE_ACL_SUNOS_NFS4
864	void *aclp;
865	int aclcnt;
866#elif ARCHIVE_ACL_LIBRICHACL
867	struct richacl *richacl;
868#else	/* !ARCHIVE_ACL_SUNOS_NFS4 */
869	acl_t acl;
870#endif
871
872	assertMakeFile("pretest", 0644, "a");
873
874	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
875		skipping("NFS4 ACLs are not writable on this filesystem");
876		return;
877	}
878
879	/* Create a write-to-disk object. */
880	assert(NULL != (a = archive_write_disk_new()));
881	archive_write_disk_set_options(a,
882	    ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
883
884	/* Populate an archive entry with some metadata, including ACL info */
885	ae = archive_entry_new();
886	assert(ae != NULL);
887	archive_entry_set_pathname(ae, "testall");
888	archive_entry_set_filetype(ae, AE_IFREG);
889	archive_entry_set_perm(ae, 0654);
890	archive_entry_set_mtime(ae, 123456, 7890);
891	archive_entry_set_size(ae, 0);
892	set_acls(ae, acls_reg, 0, acls_reg_cnt);
893
894	/* Write the entry to disk, including ACLs. */
895	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
896
897	/* Likewise for a dir. */
898	archive_entry_set_pathname(ae, "dirall");
899	archive_entry_set_filetype(ae, AE_IFDIR);
900	archive_entry_set_perm(ae, 0654);
901	archive_entry_set_mtime(ae, 123456, 7890);
902	set_acls(ae, acls_dir, 0, acls_dir_cnt);
903	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
904
905	for (i = 0; i < acls_dir_cnt; ++i) {
906	  sprintf(buff, "dir%d", i);
907	  archive_entry_set_pathname(ae, buff);
908	  archive_entry_set_filetype(ae, AE_IFDIR);
909	  archive_entry_set_perm(ae, 0654);
910	  archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
911	  set_acls(ae, acls_dir, i, i + 1);
912	  assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
913	}
914
915	archive_entry_free(ae);
916
917	/* Close the archive. */
918	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
919	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
920
921	/* Verify the data on disk. */
922	assertEqualInt(0, stat("testall", &st));
923	assertEqualInt(st.st_mtime, 123456);
924#if ARCHIVE_ACL_SUNOS_NFS4
925	aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
926	failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
927	    strerror(errno));
928	assert(aclp != NULL);
929#elif ARCHIVE_ACL_LIBRICHACL
930	richacl = richacl_get_file("testall");
931	failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
932	    strerror(errno));
933	assert(richacl != NULL);
934#else
935#if ARCHIVE_ACL_DARWIN
936	acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
937#else
938	acl = acl_get_file("testall", ACL_TYPE_NFS4);
939#endif
940	failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
941	    strerror(errno));
942	assert(acl != (acl_t)NULL);
943#endif
944#if ARCHIVE_ACL_SUNOS_NFS4
945	compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
946	free(aclp);
947	aclp = NULL;
948#elif ARCHIVE_ACL_LIBRICHACL
949	compare_acls(richacl, acls_reg, "testall", 0, regcnt);
950	richacl_free(richacl);
951#else
952	compare_acls(acl, acls_reg, "testall", 0, regcnt);
953	acl_free(acl);
954#endif
955
956
957	/* Verify single-permission dirs on disk. */
958	for (i = 0; i < dircnt; ++i) {
959		sprintf(buff, "dir%d", i);
960		assertEqualInt(0, stat(buff, &st));
961		assertEqualInt(st.st_mtime, 123456 + i);
962#if ARCHIVE_ACL_SUNOS_NFS4
963		aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
964		failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
965		    strerror(errno));
966		assert(aclp != NULL);
967#elif ARCHIVE_ACL_LIBRICHACL
968		richacl = richacl_get_file(buff);
969		/* First and last two dir do not return a richacl */
970		if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
971		    errno == ENODATA)
972			continue;
973		failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
974		    errno, strerror(errno));
975		assert(richacl != NULL);
976#else
977#if ARCHIVE_ACL_DARWIN
978		acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
979#else
980		acl = acl_get_file(buff, ACL_TYPE_NFS4);
981#endif
982		failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
983		    strerror(errno));
984		assert(acl != (acl_t)NULL);
985#endif
986#if ARCHIVE_ACL_SUNOS_NFS4
987		compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
988		free(aclp);
989		aclp = NULL;
990#elif ARCHIVE_ACL_LIBRICHACL
991		compare_acls(richacl, acls_dir, buff, i, i + 1);
992		richacl_free(richacl);
993#else
994		compare_acls(acl, acls_dir, buff, i, i + 1);
995		acl_free(acl);
996#endif
997	}
998
999	/* Verify "dirall" on disk. */
1000	assertEqualInt(0, stat("dirall", &st));
1001	assertEqualInt(st.st_mtime, 123456);
1002#if ARCHIVE_ACL_SUNOS_NFS4
1003	aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
1004	failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
1005	    strerror(errno));
1006	assert(aclp != NULL);
1007#elif ARCHIVE_ACL_LIBRICHACL
1008	richacl = richacl_get_file("dirall");
1009	failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
1010	    errno, strerror(errno));
1011	assert(richacl != NULL);
1012#else
1013#if ARCHIVE_ACL_DARWIN
1014	acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
1015#else
1016	acl = acl_get_file("dirall", ACL_TYPE_NFS4);
1017#endif
1018	failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
1019	    strerror(errno));
1020	assert(acl != (acl_t)NULL);
1021#endif
1022#if ARCHIVE_ACL_SUNOS_NFS4
1023	compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
1024	free(aclp);
1025	aclp = NULL;
1026#elif ARCHIVE_ACL_LIBRICHACL
1027	compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
1028	richacl_free(richacl);
1029#else
1030	compare_acls(acl, acls_dir, "dirall", 0, dircnt);
1031	acl_free(acl);
1032#endif
1033
1034	/* Read and compare ACL via archive_read_disk */
1035	a = archive_read_disk_new();
1036	assert(a != NULL);
1037	ae = archive_entry_new();
1038	assert(ae != NULL);
1039	archive_entry_set_pathname(ae, "testall");
1040	assertEqualInt(ARCHIVE_OK,
1041		       archive_read_disk_entry_from_file(a, ae, -1, NULL));
1042	compare_entry_acls(ae, acls_reg, "testall", 0, acls_reg_cnt);
1043	archive_entry_free(ae);
1044	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1045
1046	/* Read and compare ACL via archive_read_disk */
1047	a = archive_read_disk_new();
1048	assert(a != NULL);
1049	ae = archive_entry_new();
1050	assert(ae != NULL);
1051	archive_entry_set_pathname(ae, "dirall");
1052	assertEqualInt(ARCHIVE_OK,
1053	archive_read_disk_entry_from_file(a, ae, -1, NULL));
1054	compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
1055	archive_entry_free(ae);
1056	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1057#endif /* ARCHIVE_ACL_NFS4 */
1058}
1059