1d05f0226Sjoerg /*-
2d05f0226Sjoerg * Copyright (c) 2003-2009 Tim Kientzle
3d05f0226Sjoerg * Copyright (c) 2010-2012 Michihiro NAKAJIMA
4d05f0226Sjoerg * Copyright (c) 2017 Martin Matuska
5d05f0226Sjoerg * All rights reserved.
6d05f0226Sjoerg *
7d05f0226Sjoerg * Redistribution and use in source and binary forms, with or without
8d05f0226Sjoerg * modification, are permitted provided that the following conditions
9d05f0226Sjoerg * are met:
10d05f0226Sjoerg * 1. Redistributions of source code must retain the above copyright
11d05f0226Sjoerg * notice, this list of conditions and the following disclaimer.
12d05f0226Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
13d05f0226Sjoerg * notice, this list of conditions and the following disclaimer in the
14d05f0226Sjoerg * documentation and/or other materials provided with the distribution.
15d05f0226Sjoerg *
16d05f0226Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17d05f0226Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18d05f0226Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19d05f0226Sjoerg * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20d05f0226Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21d05f0226Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22d05f0226Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23d05f0226Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24d05f0226Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25d05f0226Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26d05f0226Sjoerg */
27d05f0226Sjoerg
28d05f0226Sjoerg #include "archive_platform.h"
29d05f0226Sjoerg
30d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD
31d05f0226Sjoerg
32d05f0226Sjoerg #ifdef HAVE_ERRNO_H
33d05f0226Sjoerg #include <errno.h>
34d05f0226Sjoerg #endif
35d05f0226Sjoerg #ifdef HAVE_FCNTL_H
36d05f0226Sjoerg #include <fcntl.h>
37d05f0226Sjoerg #endif
38d05f0226Sjoerg #ifdef HAVE_SYS_TYPES_H
39d05f0226Sjoerg #include <sys/types.h>
40d05f0226Sjoerg #endif
41d05f0226Sjoerg #ifdef HAVE_SYS_ACL_H
42d05f0226Sjoerg #define _ACL_PRIVATE /* For debugging */
43d05f0226Sjoerg #include <sys/acl.h>
44d05f0226Sjoerg #endif
45d05f0226Sjoerg
46d05f0226Sjoerg #include "archive_entry.h"
47d05f0226Sjoerg #include "archive_private.h"
48d05f0226Sjoerg #include "archive_read_disk_private.h"
49d05f0226Sjoerg #include "archive_write_disk_private.h"
50d05f0226Sjoerg
51d05f0226Sjoerg typedef struct {
52d05f0226Sjoerg const int a_perm; /* Libarchive permission or flag */
53d05f0226Sjoerg const int p_perm; /* Platform permission or flag */
54d05f0226Sjoerg } acl_perm_map_t;
55d05f0226Sjoerg
56d05f0226Sjoerg static const acl_perm_map_t acl_posix_perm_map[] = {
57d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
58d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
59d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
60d05f0226Sjoerg };
61d05f0226Sjoerg
62d05f0226Sjoerg static const int acl_posix_perm_map_size =
63d05f0226Sjoerg (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
64d05f0226Sjoerg
65d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
66d05f0226Sjoerg static const acl_perm_map_t acl_nfs4_perm_map[] = {
67d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
68d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
69d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
70d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
71d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
72d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
73d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
74d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
75d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
76d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
77d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
78d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
79d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
80d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
81d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
82d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
83d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
84d05f0226Sjoerg };
85d05f0226Sjoerg
86d05f0226Sjoerg static const int acl_nfs4_perm_map_size =
87d05f0226Sjoerg (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
88d05f0226Sjoerg
89d05f0226Sjoerg static const acl_perm_map_t acl_nfs4_flag_map[] = {
90d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
91d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
92d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
93d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
94d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
95d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
96*efdd4e46Sjoerg #ifdef ACL_ENTRY_INHERITED
97d05f0226Sjoerg {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
98*efdd4e46Sjoerg #endif
99d05f0226Sjoerg };
100d05f0226Sjoerg
101d05f0226Sjoerg static const int acl_nfs4_flag_map_size =
102d05f0226Sjoerg (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
103d05f0226Sjoerg #endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
104d05f0226Sjoerg
105d05f0226Sjoerg static int
translate_acl(struct archive_read_disk * a,struct archive_entry * entry,acl_t acl,int default_entry_acl_type)106d05f0226Sjoerg translate_acl(struct archive_read_disk *a,
107d05f0226Sjoerg struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
108d05f0226Sjoerg {
109d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
110d05f0226Sjoerg int brand;
111d05f0226Sjoerg acl_flagset_t acl_flagset;
112d05f0226Sjoerg acl_entry_type_t acl_type;
113d05f0226Sjoerg #endif
114d05f0226Sjoerg acl_tag_t acl_tag;
115d05f0226Sjoerg acl_entry_t acl_entry;
116d05f0226Sjoerg acl_permset_t acl_permset;
117d05f0226Sjoerg int i, entry_acl_type, perm_map_size;
118d05f0226Sjoerg const acl_perm_map_t *perm_map;
119d05f0226Sjoerg int r, s, ae_id, ae_tag, ae_perm;
120d05f0226Sjoerg void *q;
121d05f0226Sjoerg const char *ae_name;
122d05f0226Sjoerg
123d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
124d05f0226Sjoerg // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
125d05f0226Sjoerg // Make sure the "brand" on this ACL is consistent
126d05f0226Sjoerg // with the default_entry_acl_type bits provided.
127d05f0226Sjoerg if (acl_get_brand_np(acl, &brand) != 0) {
128d05f0226Sjoerg archive_set_error(&a->archive, errno,
129d05f0226Sjoerg "Failed to read ACL brand");
130d05f0226Sjoerg return (ARCHIVE_WARN);
131d05f0226Sjoerg }
132d05f0226Sjoerg switch (brand) {
133d05f0226Sjoerg case ACL_BRAND_POSIX:
134d05f0226Sjoerg switch (default_entry_acl_type) {
135d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
136d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
137d05f0226Sjoerg break;
138d05f0226Sjoerg default:
139d05f0226Sjoerg archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
140d05f0226Sjoerg "Invalid ACL entry type for POSIX.1e ACL");
141d05f0226Sjoerg return (ARCHIVE_WARN);
142d05f0226Sjoerg }
143d05f0226Sjoerg break;
144d05f0226Sjoerg case ACL_BRAND_NFS4:
145d05f0226Sjoerg if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
146d05f0226Sjoerg archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
147d05f0226Sjoerg "Invalid ACL entry type for NFSv4 ACL");
148d05f0226Sjoerg return (ARCHIVE_WARN);
149d05f0226Sjoerg }
150d05f0226Sjoerg break;
151d05f0226Sjoerg default:
152d05f0226Sjoerg archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
153d05f0226Sjoerg "Unknown ACL brand");
154d05f0226Sjoerg return (ARCHIVE_WARN);
155d05f0226Sjoerg }
156d05f0226Sjoerg #endif
157d05f0226Sjoerg
158d05f0226Sjoerg s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
159d05f0226Sjoerg if (s == -1) {
160d05f0226Sjoerg archive_set_error(&a->archive, errno,
161d05f0226Sjoerg "Failed to get first ACL entry");
162d05f0226Sjoerg return (ARCHIVE_WARN);
163d05f0226Sjoerg }
164d05f0226Sjoerg
165d05f0226Sjoerg while (s == 1) {
166d05f0226Sjoerg ae_id = -1;
167d05f0226Sjoerg ae_name = NULL;
168d05f0226Sjoerg ae_perm = 0;
169d05f0226Sjoerg
170d05f0226Sjoerg if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
171d05f0226Sjoerg archive_set_error(&a->archive, errno,
172d05f0226Sjoerg "Failed to get ACL tag type");
173d05f0226Sjoerg return (ARCHIVE_WARN);
174d05f0226Sjoerg }
175d05f0226Sjoerg switch (acl_tag) {
176d05f0226Sjoerg case ACL_USER:
177d05f0226Sjoerg q = acl_get_qualifier(acl_entry);
178d05f0226Sjoerg if (q != NULL) {
179d05f0226Sjoerg ae_id = (int)*(uid_t *)q;
180d05f0226Sjoerg acl_free(q);
181d05f0226Sjoerg ae_name = archive_read_disk_uname(&a->archive,
182d05f0226Sjoerg ae_id);
183d05f0226Sjoerg }
184d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_USER;
185d05f0226Sjoerg break;
186d05f0226Sjoerg case ACL_GROUP:
187d05f0226Sjoerg q = acl_get_qualifier(acl_entry);
188d05f0226Sjoerg if (q != NULL) {
189d05f0226Sjoerg ae_id = (int)*(gid_t *)q;
190d05f0226Sjoerg acl_free(q);
191d05f0226Sjoerg ae_name = archive_read_disk_gname(&a->archive,
192d05f0226Sjoerg ae_id);
193d05f0226Sjoerg }
194d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
195d05f0226Sjoerg break;
196d05f0226Sjoerg case ACL_MASK:
197d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_MASK;
198d05f0226Sjoerg break;
199d05f0226Sjoerg case ACL_USER_OBJ:
200d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
201d05f0226Sjoerg break;
202d05f0226Sjoerg case ACL_GROUP_OBJ:
203d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
204d05f0226Sjoerg break;
205d05f0226Sjoerg case ACL_OTHER:
206d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
207d05f0226Sjoerg break;
208d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
209d05f0226Sjoerg case ACL_EVERYONE:
210d05f0226Sjoerg ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
211d05f0226Sjoerg break;
212d05f0226Sjoerg #endif
213d05f0226Sjoerg default:
214d05f0226Sjoerg /* Skip types that libarchive can't support. */
215d05f0226Sjoerg s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
216d05f0226Sjoerg continue;
217d05f0226Sjoerg }
218d05f0226Sjoerg
219d05f0226Sjoerg // XXX acl_type maps to allow/deny/audit/YYYY bits
220d05f0226Sjoerg entry_acl_type = default_entry_acl_type;
221d05f0226Sjoerg
222d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
223d05f0226Sjoerg if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
224d05f0226Sjoerg /*
225d05f0226Sjoerg * acl_get_entry_type_np() fails with non-NFSv4 ACLs
226d05f0226Sjoerg */
227d05f0226Sjoerg if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
228d05f0226Sjoerg archive_set_error(&a->archive, errno, "Failed "
229d05f0226Sjoerg "to get ACL type from a NFSv4 ACL entry");
230d05f0226Sjoerg return (ARCHIVE_WARN);
231d05f0226Sjoerg }
232d05f0226Sjoerg switch (acl_type) {
233d05f0226Sjoerg case ACL_ENTRY_TYPE_ALLOW:
234d05f0226Sjoerg entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
235d05f0226Sjoerg break;
236d05f0226Sjoerg case ACL_ENTRY_TYPE_DENY:
237d05f0226Sjoerg entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
238d05f0226Sjoerg break;
239d05f0226Sjoerg case ACL_ENTRY_TYPE_AUDIT:
240d05f0226Sjoerg entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
241d05f0226Sjoerg break;
242d05f0226Sjoerg case ACL_ENTRY_TYPE_ALARM:
243d05f0226Sjoerg entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
244d05f0226Sjoerg break;
245d05f0226Sjoerg default:
246d05f0226Sjoerg archive_set_error(&a->archive, errno,
247d05f0226Sjoerg "Invalid NFSv4 ACL entry type");
248d05f0226Sjoerg return (ARCHIVE_WARN);
249d05f0226Sjoerg }
250d05f0226Sjoerg
251d05f0226Sjoerg /*
252d05f0226Sjoerg * Libarchive stores "flag" (NFSv4 inheritance bits)
253d05f0226Sjoerg * in the ae_perm bitmap.
254d05f0226Sjoerg *
255d05f0226Sjoerg * acl_get_flagset_np() fails with non-NFSv4 ACLs
256d05f0226Sjoerg */
257d05f0226Sjoerg if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
258d05f0226Sjoerg archive_set_error(&a->archive, errno,
259d05f0226Sjoerg "Failed to get flagset from a NFSv4 "
260d05f0226Sjoerg "ACL entry");
261d05f0226Sjoerg return (ARCHIVE_WARN);
262d05f0226Sjoerg }
263d05f0226Sjoerg for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
264d05f0226Sjoerg r = acl_get_flag_np(acl_flagset,
265d05f0226Sjoerg acl_nfs4_flag_map[i].p_perm);
266d05f0226Sjoerg if (r == -1) {
267d05f0226Sjoerg archive_set_error(&a->archive, errno,
268d05f0226Sjoerg "Failed to check flag in a NFSv4 "
269d05f0226Sjoerg "ACL flagset");
270d05f0226Sjoerg return (ARCHIVE_WARN);
271d05f0226Sjoerg } else if (r)
272d05f0226Sjoerg ae_perm |= acl_nfs4_flag_map[i].a_perm;
273d05f0226Sjoerg }
274d05f0226Sjoerg }
275d05f0226Sjoerg #endif
276d05f0226Sjoerg
277d05f0226Sjoerg if (acl_get_permset(acl_entry, &acl_permset) != 0) {
278d05f0226Sjoerg archive_set_error(&a->archive, errno,
279d05f0226Sjoerg "Failed to get ACL permission set");
280d05f0226Sjoerg return (ARCHIVE_WARN);
281d05f0226Sjoerg }
282d05f0226Sjoerg
283d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
284d05f0226Sjoerg if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
285d05f0226Sjoerg perm_map_size = acl_nfs4_perm_map_size;
286d05f0226Sjoerg perm_map = acl_nfs4_perm_map;
287d05f0226Sjoerg } else {
288d05f0226Sjoerg #endif
289d05f0226Sjoerg perm_map_size = acl_posix_perm_map_size;
290d05f0226Sjoerg perm_map = acl_posix_perm_map;
291d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
292d05f0226Sjoerg }
293d05f0226Sjoerg #endif
294d05f0226Sjoerg
295d05f0226Sjoerg for (i = 0; i < perm_map_size; ++i) {
296d05f0226Sjoerg r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
297d05f0226Sjoerg if (r == -1) {
298d05f0226Sjoerg archive_set_error(&a->archive, errno,
299d05f0226Sjoerg "Failed to check permission in an ACL "
300d05f0226Sjoerg "permission set");
301d05f0226Sjoerg return (ARCHIVE_WARN);
302d05f0226Sjoerg } else if (r)
303d05f0226Sjoerg ae_perm |= perm_map[i].a_perm;
304d05f0226Sjoerg }
305d05f0226Sjoerg
306d05f0226Sjoerg archive_entry_acl_add_entry(entry, entry_acl_type,
307d05f0226Sjoerg ae_perm, ae_tag,
308d05f0226Sjoerg ae_id, ae_name);
309d05f0226Sjoerg
310d05f0226Sjoerg s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
311d05f0226Sjoerg if (s == -1) {
312d05f0226Sjoerg archive_set_error(&a->archive, errno,
313d05f0226Sjoerg "Failed to get next ACL entry");
314d05f0226Sjoerg return (ARCHIVE_WARN);
315d05f0226Sjoerg }
316d05f0226Sjoerg }
317d05f0226Sjoerg return (ARCHIVE_OK);
318d05f0226Sjoerg }
319d05f0226Sjoerg
320d05f0226Sjoerg static int
set_acl(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl,int ae_requested_type,const char * tname)321d05f0226Sjoerg set_acl(struct archive *a, int fd, const char *name,
322d05f0226Sjoerg struct archive_acl *abstract_acl,
323d05f0226Sjoerg int ae_requested_type, const char *tname)
324d05f0226Sjoerg {
325d05f0226Sjoerg int acl_type = 0;
326d05f0226Sjoerg acl_t acl;
327d05f0226Sjoerg acl_entry_t acl_entry;
328d05f0226Sjoerg acl_permset_t acl_permset;
329d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
330d05f0226Sjoerg acl_flagset_t acl_flagset;
331d05f0226Sjoerg int r;
332d05f0226Sjoerg #endif
333d05f0226Sjoerg int ret;
334d05f0226Sjoerg int ae_type, ae_permset, ae_tag, ae_id;
335d05f0226Sjoerg int perm_map_size;
336d05f0226Sjoerg const acl_perm_map_t *perm_map;
337d05f0226Sjoerg uid_t ae_uid;
338d05f0226Sjoerg gid_t ae_gid;
339d05f0226Sjoerg const char *ae_name;
340d05f0226Sjoerg int entries;
341d05f0226Sjoerg int i;
342d05f0226Sjoerg
343d05f0226Sjoerg ret = ARCHIVE_OK;
344d05f0226Sjoerg entries = archive_acl_reset(abstract_acl, ae_requested_type);
345d05f0226Sjoerg if (entries == 0)
346d05f0226Sjoerg return (ARCHIVE_OK);
347d05f0226Sjoerg
348d05f0226Sjoerg
349d05f0226Sjoerg switch (ae_requested_type) {
350d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
351d05f0226Sjoerg acl_type = ACL_TYPE_ACCESS;
352d05f0226Sjoerg break;
353d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
354d05f0226Sjoerg acl_type = ACL_TYPE_DEFAULT;
355d05f0226Sjoerg break;
356d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
357d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
358d05f0226Sjoerg acl_type = ACL_TYPE_NFS4;
359d05f0226Sjoerg break;
360d05f0226Sjoerg #endif
361d05f0226Sjoerg default:
362d05f0226Sjoerg errno = ENOENT;
363d05f0226Sjoerg archive_set_error(a, errno, "Unsupported ACL type");
364d05f0226Sjoerg return (ARCHIVE_FAILED);
365d05f0226Sjoerg }
366d05f0226Sjoerg
367d05f0226Sjoerg acl = acl_init(entries);
368d05f0226Sjoerg if (acl == (acl_t)NULL) {
369d05f0226Sjoerg archive_set_error(a, errno,
370d05f0226Sjoerg "Failed to initialize ACL working storage");
371d05f0226Sjoerg return (ARCHIVE_FAILED);
372d05f0226Sjoerg }
373d05f0226Sjoerg
374d05f0226Sjoerg while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
375d05f0226Sjoerg &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
376d05f0226Sjoerg if (acl_create_entry(&acl, &acl_entry) != 0) {
377d05f0226Sjoerg archive_set_error(a, errno,
378d05f0226Sjoerg "Failed to create a new ACL entry");
379d05f0226Sjoerg ret = ARCHIVE_FAILED;
380d05f0226Sjoerg goto exit_free;
381d05f0226Sjoerg }
382d05f0226Sjoerg switch (ae_tag) {
383d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_USER:
384d05f0226Sjoerg ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
385d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_USER);
386d05f0226Sjoerg acl_set_qualifier(acl_entry, &ae_uid);
387d05f0226Sjoerg break;
388d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_GROUP:
389d05f0226Sjoerg ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
390d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_GROUP);
391d05f0226Sjoerg acl_set_qualifier(acl_entry, &ae_gid);
392d05f0226Sjoerg break;
393d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_USER_OBJ:
394d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_USER_OBJ);
395d05f0226Sjoerg break;
396d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
397d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
398d05f0226Sjoerg break;
399d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_MASK:
400d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_MASK);
401d05f0226Sjoerg break;
402d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_OTHER:
403d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_OTHER);
404d05f0226Sjoerg break;
405d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
406d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_EVERYONE:
407d05f0226Sjoerg acl_set_tag_type(acl_entry, ACL_EVERYONE);
408d05f0226Sjoerg break;
409d05f0226Sjoerg #endif
410d05f0226Sjoerg default:
411d05f0226Sjoerg archive_set_error(a, ARCHIVE_ERRNO_MISC,
412d05f0226Sjoerg "Unsupported ACL tag");
413d05f0226Sjoerg ret = ARCHIVE_FAILED;
414d05f0226Sjoerg goto exit_free;
415d05f0226Sjoerg }
416d05f0226Sjoerg
417d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
418d05f0226Sjoerg r = 0;
419d05f0226Sjoerg switch (ae_type) {
420d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
421d05f0226Sjoerg r = acl_set_entry_type_np(acl_entry,
422d05f0226Sjoerg ACL_ENTRY_TYPE_ALLOW);
423d05f0226Sjoerg break;
424d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_DENY:
425d05f0226Sjoerg r = acl_set_entry_type_np(acl_entry,
426d05f0226Sjoerg ACL_ENTRY_TYPE_DENY);
427d05f0226Sjoerg break;
428d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
429d05f0226Sjoerg r = acl_set_entry_type_np(acl_entry,
430d05f0226Sjoerg ACL_ENTRY_TYPE_AUDIT);
431d05f0226Sjoerg break;
432d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
433d05f0226Sjoerg r = acl_set_entry_type_np(acl_entry,
434d05f0226Sjoerg ACL_ENTRY_TYPE_ALARM);
435d05f0226Sjoerg break;
436d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
437d05f0226Sjoerg case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
438d05f0226Sjoerg // These don't translate directly into the system ACL.
439d05f0226Sjoerg break;
440d05f0226Sjoerg default:
441d05f0226Sjoerg archive_set_error(a, ARCHIVE_ERRNO_MISC,
442d05f0226Sjoerg "Unsupported ACL entry type");
443d05f0226Sjoerg ret = ARCHIVE_FAILED;
444d05f0226Sjoerg goto exit_free;
445d05f0226Sjoerg }
446d05f0226Sjoerg
447d05f0226Sjoerg if (r != 0) {
448d05f0226Sjoerg archive_set_error(a, errno,
449d05f0226Sjoerg "Failed to set ACL entry type");
450d05f0226Sjoerg ret = ARCHIVE_FAILED;
451d05f0226Sjoerg goto exit_free;
452d05f0226Sjoerg }
453d05f0226Sjoerg #endif
454d05f0226Sjoerg
455d05f0226Sjoerg if (acl_get_permset(acl_entry, &acl_permset) != 0) {
456d05f0226Sjoerg archive_set_error(a, errno,
457d05f0226Sjoerg "Failed to get ACL permission set");
458d05f0226Sjoerg ret = ARCHIVE_FAILED;
459d05f0226Sjoerg goto exit_free;
460d05f0226Sjoerg }
461d05f0226Sjoerg if (acl_clear_perms(acl_permset) != 0) {
462d05f0226Sjoerg archive_set_error(a, errno,
463d05f0226Sjoerg "Failed to clear ACL permissions");
464d05f0226Sjoerg ret = ARCHIVE_FAILED;
465d05f0226Sjoerg goto exit_free;
466d05f0226Sjoerg }
467d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
468d05f0226Sjoerg if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
469d05f0226Sjoerg perm_map_size = acl_nfs4_perm_map_size;
470d05f0226Sjoerg perm_map = acl_nfs4_perm_map;
471d05f0226Sjoerg } else {
472d05f0226Sjoerg #endif
473d05f0226Sjoerg perm_map_size = acl_posix_perm_map_size;
474d05f0226Sjoerg perm_map = acl_posix_perm_map;
475d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
476d05f0226Sjoerg }
477d05f0226Sjoerg #endif
478d05f0226Sjoerg
479d05f0226Sjoerg for (i = 0; i < perm_map_size; ++i) {
480d05f0226Sjoerg if (ae_permset & perm_map[i].a_perm) {
481d05f0226Sjoerg if (acl_add_perm(acl_permset,
482d05f0226Sjoerg perm_map[i].p_perm) != 0) {
483d05f0226Sjoerg archive_set_error(a, errno,
484d05f0226Sjoerg "Failed to add ACL permission");
485d05f0226Sjoerg ret = ARCHIVE_FAILED;
486d05f0226Sjoerg goto exit_free;
487d05f0226Sjoerg }
488d05f0226Sjoerg }
489d05f0226Sjoerg }
490d05f0226Sjoerg
491d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
492d05f0226Sjoerg if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
493d05f0226Sjoerg /*
494d05f0226Sjoerg * acl_get_flagset_np() fails with non-NFSv4 ACLs
495d05f0226Sjoerg */
496d05f0226Sjoerg if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
497d05f0226Sjoerg archive_set_error(a, errno,
498d05f0226Sjoerg "Failed to get flagset from an NFSv4 "
499d05f0226Sjoerg "ACL entry");
500d05f0226Sjoerg ret = ARCHIVE_FAILED;
501d05f0226Sjoerg goto exit_free;
502d05f0226Sjoerg }
503d05f0226Sjoerg if (acl_clear_flags_np(acl_flagset) != 0) {
504d05f0226Sjoerg archive_set_error(a, errno,
505d05f0226Sjoerg "Failed to clear flags from an NFSv4 "
506d05f0226Sjoerg "ACL flagset");
507d05f0226Sjoerg ret = ARCHIVE_FAILED;
508d05f0226Sjoerg goto exit_free;
509d05f0226Sjoerg }
510d05f0226Sjoerg for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
511d05f0226Sjoerg if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
512d05f0226Sjoerg if (acl_add_flag_np(acl_flagset,
513d05f0226Sjoerg acl_nfs4_flag_map[i].p_perm) != 0) {
514d05f0226Sjoerg archive_set_error(a, errno,
515d05f0226Sjoerg "Failed to add flag to "
516d05f0226Sjoerg "NFSv4 ACL flagset");
517d05f0226Sjoerg ret = ARCHIVE_FAILED;
518d05f0226Sjoerg goto exit_free;
519d05f0226Sjoerg }
520d05f0226Sjoerg }
521d05f0226Sjoerg }
522d05f0226Sjoerg }
523d05f0226Sjoerg #endif
524d05f0226Sjoerg }
525d05f0226Sjoerg
526d05f0226Sjoerg /* Try restoring the ACL through 'fd' if we can. */
527d05f0226Sjoerg if (fd >= 0) {
528d05f0226Sjoerg if (acl_set_fd_np(fd, acl, acl_type) == 0)
529d05f0226Sjoerg ret = ARCHIVE_OK;
530d05f0226Sjoerg else {
531d05f0226Sjoerg if (errno == EOPNOTSUPP) {
532d05f0226Sjoerg /* Filesystem doesn't support ACLs */
533d05f0226Sjoerg ret = ARCHIVE_OK;
534d05f0226Sjoerg } else {
535d05f0226Sjoerg archive_set_error(a, errno,
536d05f0226Sjoerg "Failed to set acl on fd: %s", tname);
537d05f0226Sjoerg ret = ARCHIVE_WARN;
538d05f0226Sjoerg }
539d05f0226Sjoerg }
540d05f0226Sjoerg }
541d05f0226Sjoerg #if HAVE_ACL_SET_LINK_NP
542d05f0226Sjoerg else if (acl_set_link_np(name, acl_type, acl) != 0)
543d05f0226Sjoerg #else
544d05f0226Sjoerg /* FreeBSD older than 8.0 */
545d05f0226Sjoerg else if (acl_set_file(name, acl_type, acl) != 0)
546d05f0226Sjoerg #endif
547d05f0226Sjoerg {
548d05f0226Sjoerg if (errno == EOPNOTSUPP) {
549d05f0226Sjoerg /* Filesystem doesn't support ACLs */
550d05f0226Sjoerg ret = ARCHIVE_OK;
551d05f0226Sjoerg } else {
552d05f0226Sjoerg archive_set_error(a, errno, "Failed to set acl: %s",
553d05f0226Sjoerg tname);
554d05f0226Sjoerg ret = ARCHIVE_WARN;
555d05f0226Sjoerg }
556d05f0226Sjoerg }
557d05f0226Sjoerg exit_free:
558d05f0226Sjoerg acl_free(acl);
559d05f0226Sjoerg return (ret);
560d05f0226Sjoerg }
561d05f0226Sjoerg
562d05f0226Sjoerg int
archive_read_disk_entry_setup_acls(struct archive_read_disk * a,struct archive_entry * entry,int * fd)563d05f0226Sjoerg archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
564d05f0226Sjoerg struct archive_entry *entry, int *fd)
565d05f0226Sjoerg {
566d05f0226Sjoerg const char *accpath;
567d05f0226Sjoerg acl_t acl;
568d05f0226Sjoerg int r;
569d05f0226Sjoerg
570d05f0226Sjoerg accpath = NULL;
571d05f0226Sjoerg
572d05f0226Sjoerg if (*fd < 0) {
573d05f0226Sjoerg accpath = archive_read_disk_entry_setup_path(a, entry, fd);
574d05f0226Sjoerg if (accpath == NULL)
575d05f0226Sjoerg return (ARCHIVE_WARN);
576d05f0226Sjoerg }
577d05f0226Sjoerg
578d05f0226Sjoerg archive_entry_acl_clear(entry);
579d05f0226Sjoerg
580d05f0226Sjoerg acl = NULL;
581d05f0226Sjoerg
582d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
583d05f0226Sjoerg /* Try NFSv4 ACL first. */
584d05f0226Sjoerg if (*fd >= 0)
585d05f0226Sjoerg acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
586d05f0226Sjoerg else if (!a->follow_symlinks)
587d05f0226Sjoerg acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
588d05f0226Sjoerg else
589d05f0226Sjoerg acl = acl_get_file(accpath, ACL_TYPE_NFS4);
590d05f0226Sjoerg
591d05f0226Sjoerg /* Ignore "trivial" ACLs that just mirror the file mode. */
592d05f0226Sjoerg if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
593d05f0226Sjoerg acl_free(acl);
594d05f0226Sjoerg acl = NULL;
595d05f0226Sjoerg return (ARCHIVE_OK);
596d05f0226Sjoerg }
597d05f0226Sjoerg
598d05f0226Sjoerg if (acl != NULL) {
599d05f0226Sjoerg r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
600d05f0226Sjoerg acl_free(acl);
601d05f0226Sjoerg acl = NULL;
602d05f0226Sjoerg
603d05f0226Sjoerg if (r != ARCHIVE_OK) {
604d05f0226Sjoerg archive_set_error(&a->archive, errno,
605d05f0226Sjoerg "Couldn't translate NFSv4 ACLs");
606d05f0226Sjoerg }
607d05f0226Sjoerg
608d05f0226Sjoerg return (r);
609d05f0226Sjoerg }
610d05f0226Sjoerg #endif
611d05f0226Sjoerg
612d05f0226Sjoerg /* Retrieve access ACL from file. */
613d05f0226Sjoerg if (*fd >= 0)
614d05f0226Sjoerg acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
615d05f0226Sjoerg #if HAVE_ACL_GET_LINK_NP
616d05f0226Sjoerg else if (!a->follow_symlinks)
617d05f0226Sjoerg acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
618d05f0226Sjoerg #else
619d05f0226Sjoerg else if ((!a->follow_symlinks)
620d05f0226Sjoerg && (archive_entry_filetype(entry) == AE_IFLNK))
621d05f0226Sjoerg /* We can't get the ACL of a symlink, so we assume it can't
622d05f0226Sjoerg have one. */
623d05f0226Sjoerg acl = NULL;
624d05f0226Sjoerg #endif
625d05f0226Sjoerg else
626d05f0226Sjoerg acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
627d05f0226Sjoerg
628d05f0226Sjoerg #if HAVE_ACL_IS_TRIVIAL_NP
629d05f0226Sjoerg /* Ignore "trivial" ACLs that just mirror the file mode. */
630d05f0226Sjoerg if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
631d05f0226Sjoerg acl_free(acl);
632d05f0226Sjoerg acl = NULL;
633d05f0226Sjoerg }
634d05f0226Sjoerg #endif
635d05f0226Sjoerg
636d05f0226Sjoerg if (acl != NULL) {
637d05f0226Sjoerg r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
638d05f0226Sjoerg acl_free(acl);
639d05f0226Sjoerg acl = NULL;
640d05f0226Sjoerg
641d05f0226Sjoerg if (r != ARCHIVE_OK) {
642d05f0226Sjoerg archive_set_error(&a->archive, errno,
643d05f0226Sjoerg "Couldn't translate access ACLs");
644d05f0226Sjoerg return (r);
645d05f0226Sjoerg }
646d05f0226Sjoerg }
647d05f0226Sjoerg
648d05f0226Sjoerg /* Only directories can have default ACLs. */
649d05f0226Sjoerg if (S_ISDIR(archive_entry_mode(entry))) {
650d05f0226Sjoerg if (*fd >= 0)
651d05f0226Sjoerg acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
652d05f0226Sjoerg else
653d05f0226Sjoerg acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
654d05f0226Sjoerg if (acl != NULL) {
655d05f0226Sjoerg r = translate_acl(a, entry, acl,
656d05f0226Sjoerg ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
657d05f0226Sjoerg acl_free(acl);
658d05f0226Sjoerg if (r != ARCHIVE_OK) {
659d05f0226Sjoerg archive_set_error(&a->archive, errno,
660d05f0226Sjoerg "Couldn't translate default ACLs");
661d05f0226Sjoerg return (r);
662d05f0226Sjoerg }
663d05f0226Sjoerg }
664d05f0226Sjoerg }
665d05f0226Sjoerg return (ARCHIVE_OK);
666d05f0226Sjoerg }
667d05f0226Sjoerg
668d05f0226Sjoerg int
archive_write_disk_set_acls(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl,__LA_MODE_T mode)669d05f0226Sjoerg archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
670d05f0226Sjoerg struct archive_acl *abstract_acl, __LA_MODE_T mode)
671d05f0226Sjoerg {
672d05f0226Sjoerg int ret = ARCHIVE_OK;
673d05f0226Sjoerg
674d05f0226Sjoerg (void)mode; /* UNUSED */
675d05f0226Sjoerg
676d05f0226Sjoerg if ((archive_acl_types(abstract_acl)
677d05f0226Sjoerg & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
678d05f0226Sjoerg if ((archive_acl_types(abstract_acl)
679d05f0226Sjoerg & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
680d05f0226Sjoerg ret = set_acl(a, fd, name, abstract_acl,
681d05f0226Sjoerg ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
682d05f0226Sjoerg if (ret != ARCHIVE_OK)
683d05f0226Sjoerg return (ret);
684d05f0226Sjoerg }
685d05f0226Sjoerg if ((archive_acl_types(abstract_acl)
686d05f0226Sjoerg & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
687d05f0226Sjoerg ret = set_acl(a, fd, name, abstract_acl,
688d05f0226Sjoerg ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
689d05f0226Sjoerg
690d05f0226Sjoerg /* Simultaneous POSIX.1e and NFSv4 is not supported */
691d05f0226Sjoerg return (ret);
692d05f0226Sjoerg }
693d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
694d05f0226Sjoerg else if ((archive_acl_types(abstract_acl) &
695d05f0226Sjoerg ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
696d05f0226Sjoerg ret = set_acl(a, fd, name, abstract_acl,
697d05f0226Sjoerg ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
698d05f0226Sjoerg }
699d05f0226Sjoerg #endif
700d05f0226Sjoerg return (ret);
701d05f0226Sjoerg }
702d05f0226Sjoerg #endif /* ARCHIVE_ACL_FREEBSD */
703