1315633Smm/*- 2315633Smm * Copyright (c) 2003-2009 Tim Kientzle 3315633Smm * Copyright (c) 2010-2012 Michihiro NAKAJIMA 4316083Smm * Copyright (c) 2017 Martin Matuska 5315633Smm * All rights reserved. 6315633Smm * 7315633Smm * Redistribution and use in source and binary forms, with or without 8315633Smm * modification, are permitted provided that the following conditions 9315633Smm * are met: 10315633Smm * 1. Redistributions of source code must retain the above copyright 11315633Smm * notice, this list of conditions and the following disclaimer. 12315633Smm * 2. Redistributions in binary form must reproduce the above copyright 13315633Smm * notice, this list of conditions and the following disclaimer in the 14315633Smm * documentation and/or other materials provided with the distribution. 15315633Smm * 16315633Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17315633Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18315633Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19315633Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20315633Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21315633Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22315633Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23315633Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24315633Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25315633Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26315633Smm */ 27315633Smm 28315633Smm#include "archive_platform.h" 29315633Smm 30316095Smm#if ARCHIVE_ACL_FREEBSD 31316095Smm 32315633Smm#ifdef HAVE_ERRNO_H 33315633Smm#include <errno.h> 34315633Smm#endif 35315633Smm#ifdef HAVE_FCNTL_H 36315633Smm#include <fcntl.h> 37315633Smm#endif 38315633Smm#ifdef HAVE_SYS_TYPES_H 39315633Smm#include <sys/types.h> 40315633Smm#endif 41315633Smm#ifdef HAVE_SYS_ACL_H 42315633Smm#define _ACL_PRIVATE /* For debugging */ 43315633Smm#include <sys/acl.h> 44315633Smm#endif 45315633Smm 46315633Smm#include "archive_entry.h" 47315633Smm#include "archive_private.h" 48315633Smm#include "archive_read_disk_private.h" 49316083Smm#include "archive_write_disk_private.h" 50315633Smm 51316083Smmtypedef struct { 52316083Smm const int a_perm; /* Libarchive permission or flag */ 53316083Smm const int p_perm; /* Platform permission or flag */ 54316083Smm} acl_perm_map_t; 55316083Smm 56316083Smmstatic const acl_perm_map_t acl_posix_perm_map[] = { 57316083Smm {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 58316083Smm {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, 59316083Smm {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, 60316083Smm}; 61316083Smm 62316083Smmstatic const int acl_posix_perm_map_size = 63316083Smm (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); 64316083Smm 65316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 66316083Smmstatic const acl_perm_map_t acl_nfs4_perm_map[] = { 67316083Smm {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 68316083Smm {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, 69316083Smm {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, 70316083Smm {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, 71316083Smm {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, 72316083Smm {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, 73316083Smm {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, 74316083Smm {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 75316083Smm {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 76316083Smm {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, 77316083Smm {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 78316083Smm {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 79316083Smm {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, 80316083Smm {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, 81316083Smm {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, 82316083Smm {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, 83316083Smm {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} 84316083Smm}; 85316083Smm 86316083Smmstatic const int acl_nfs4_perm_map_size = 87316083Smm (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); 88316083Smm 89316083Smmstatic const acl_perm_map_t acl_nfs4_flag_map[] = { 90316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, 91316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, 92316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, 93316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, 94316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, 95316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, 96328828Smm#ifdef ACL_ENTRY_INHERITED 97316083Smm {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} 98328828Smm#endif 99316083Smm}; 100316083Smm 101316083Smmstatic const int acl_nfs4_flag_map_size = 102316083Smm (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); 103316083Smm#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ 104316083Smm 105315633Smmstatic int 106315633Smmtranslate_acl(struct archive_read_disk *a, 107315633Smm struct archive_entry *entry, acl_t acl, int default_entry_acl_type) 108315633Smm{ 109315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 110315633Smm int brand; 111315633Smm acl_flagset_t acl_flagset; 112316083Smm acl_entry_type_t acl_type; 113315633Smm#endif 114315633Smm acl_tag_t acl_tag; 115315633Smm acl_entry_t acl_entry; 116315633Smm acl_permset_t acl_permset; 117315633Smm int i, entry_acl_type, perm_map_size; 118315633Smm const acl_perm_map_t *perm_map; 119315633Smm int r, s, ae_id, ae_tag, ae_perm; 120315633Smm void *q; 121315633Smm const char *ae_name; 122315633Smm 123315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 124315633Smm // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 125315633Smm // Make sure the "brand" on this ACL is consistent 126315633Smm // with the default_entry_acl_type bits provided. 127315633Smm if (acl_get_brand_np(acl, &brand) != 0) { 128315633Smm archive_set_error(&a->archive, errno, 129315633Smm "Failed to read ACL brand"); 130315633Smm return (ARCHIVE_WARN); 131315633Smm } 132315633Smm switch (brand) { 133315633Smm case ACL_BRAND_POSIX: 134315633Smm switch (default_entry_acl_type) { 135315633Smm case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 136315633Smm case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 137315633Smm break; 138315633Smm default: 139315633Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 140315633Smm "Invalid ACL entry type for POSIX.1e ACL"); 141315633Smm return (ARCHIVE_WARN); 142315633Smm } 143315633Smm break; 144315633Smm case ACL_BRAND_NFS4: 145315633Smm if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 146315633Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 147315633Smm "Invalid ACL entry type for NFSv4 ACL"); 148315633Smm return (ARCHIVE_WARN); 149315633Smm } 150315633Smm break; 151315633Smm default: 152315633Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 153315633Smm "Unknown ACL brand"); 154315633Smm return (ARCHIVE_WARN); 155315633Smm } 156315633Smm#endif 157315633Smm 158315633Smm s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); 159315633Smm if (s == -1) { 160315633Smm archive_set_error(&a->archive, errno, 161315633Smm "Failed to get first ACL entry"); 162315633Smm return (ARCHIVE_WARN); 163315633Smm } 164315633Smm 165315633Smm while (s == 1) { 166315633Smm ae_id = -1; 167315633Smm ae_name = NULL; 168315633Smm ae_perm = 0; 169315633Smm 170315633Smm if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { 171315633Smm archive_set_error(&a->archive, errno, 172315633Smm "Failed to get ACL tag type"); 173315633Smm return (ARCHIVE_WARN); 174315633Smm } 175315633Smm switch (acl_tag) { 176315633Smm case ACL_USER: 177315633Smm q = acl_get_qualifier(acl_entry); 178315633Smm if (q != NULL) { 179315633Smm ae_id = (int)*(uid_t *)q; 180315633Smm acl_free(q); 181315633Smm ae_name = archive_read_disk_uname(&a->archive, 182315633Smm ae_id); 183315633Smm } 184315633Smm ae_tag = ARCHIVE_ENTRY_ACL_USER; 185315633Smm break; 186315633Smm case ACL_GROUP: 187315633Smm q = acl_get_qualifier(acl_entry); 188315633Smm if (q != NULL) { 189315633Smm ae_id = (int)*(gid_t *)q; 190315633Smm acl_free(q); 191315633Smm ae_name = archive_read_disk_gname(&a->archive, 192315633Smm ae_id); 193315633Smm } 194315633Smm ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 195315633Smm break; 196315633Smm case ACL_MASK: 197315633Smm ae_tag = ARCHIVE_ENTRY_ACL_MASK; 198315633Smm break; 199315633Smm case ACL_USER_OBJ: 200315633Smm ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; 201315633Smm break; 202315633Smm case ACL_GROUP_OBJ: 203315633Smm ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; 204315633Smm break; 205315633Smm case ACL_OTHER: 206315633Smm ae_tag = ARCHIVE_ENTRY_ACL_OTHER; 207315633Smm break; 208315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 209315633Smm case ACL_EVERYONE: 210315633Smm ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; 211315633Smm break; 212315633Smm#endif 213315633Smm default: 214315633Smm /* Skip types that libarchive can't support. */ 215315633Smm s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 216315633Smm continue; 217315633Smm } 218315633Smm 219315633Smm // XXX acl_type maps to allow/deny/audit/YYYY bits 220315633Smm entry_acl_type = default_entry_acl_type; 221315633Smm 222315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 223315633Smm if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 224315633Smm /* 225315633Smm * acl_get_entry_type_np() fails with non-NFSv4 ACLs 226315633Smm */ 227315633Smm if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { 228315633Smm archive_set_error(&a->archive, errno, "Failed " 229315633Smm "to get ACL type from a NFSv4 ACL entry"); 230315633Smm return (ARCHIVE_WARN); 231315633Smm } 232315633Smm switch (acl_type) { 233315633Smm case ACL_ENTRY_TYPE_ALLOW: 234315633Smm entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; 235315633Smm break; 236315633Smm case ACL_ENTRY_TYPE_DENY: 237315633Smm entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; 238315633Smm break; 239315633Smm case ACL_ENTRY_TYPE_AUDIT: 240315633Smm entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; 241315633Smm break; 242315633Smm case ACL_ENTRY_TYPE_ALARM: 243315633Smm entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; 244315633Smm break; 245315633Smm default: 246315633Smm archive_set_error(&a->archive, errno, 247315633Smm "Invalid NFSv4 ACL entry type"); 248315633Smm return (ARCHIVE_WARN); 249315633Smm } 250315633Smm 251315633Smm /* 252315633Smm * Libarchive stores "flag" (NFSv4 inheritance bits) 253315633Smm * in the ae_perm bitmap. 254315633Smm * 255315633Smm * acl_get_flagset_np() fails with non-NFSv4 ACLs 256315633Smm */ 257315633Smm if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 258315633Smm archive_set_error(&a->archive, errno, 259315633Smm "Failed to get flagset from a NFSv4 " 260315633Smm "ACL entry"); 261315633Smm return (ARCHIVE_WARN); 262315633Smm } 263315633Smm for (i = 0; i < acl_nfs4_flag_map_size; ++i) { 264315633Smm r = acl_get_flag_np(acl_flagset, 265315633Smm acl_nfs4_flag_map[i].p_perm); 266315633Smm if (r == -1) { 267315633Smm archive_set_error(&a->archive, errno, 268315633Smm "Failed to check flag in a NFSv4 " 269315633Smm "ACL flagset"); 270315633Smm return (ARCHIVE_WARN); 271315633Smm } else if (r) 272315633Smm ae_perm |= acl_nfs4_flag_map[i].a_perm; 273315633Smm } 274315633Smm } 275315633Smm#endif 276315633Smm 277315633Smm if (acl_get_permset(acl_entry, &acl_permset) != 0) { 278315633Smm archive_set_error(&a->archive, errno, 279315633Smm "Failed to get ACL permission set"); 280315633Smm return (ARCHIVE_WARN); 281315633Smm } 282315633Smm 283315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 284315633Smm if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 285315633Smm perm_map_size = acl_nfs4_perm_map_size; 286315633Smm perm_map = acl_nfs4_perm_map; 287315633Smm } else { 288315633Smm#endif 289315633Smm perm_map_size = acl_posix_perm_map_size; 290315633Smm perm_map = acl_posix_perm_map; 291315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 292315633Smm } 293315633Smm#endif 294315633Smm 295315633Smm for (i = 0; i < perm_map_size; ++i) { 296315633Smm r = acl_get_perm_np(acl_permset, perm_map[i].p_perm); 297315633Smm if (r == -1) { 298315633Smm archive_set_error(&a->archive, errno, 299315633Smm "Failed to check permission in an ACL " 300315633Smm "permission set"); 301315633Smm return (ARCHIVE_WARN); 302315633Smm } else if (r) 303315633Smm ae_perm |= perm_map[i].a_perm; 304315633Smm } 305315633Smm 306315633Smm archive_entry_acl_add_entry(entry, entry_acl_type, 307315633Smm ae_perm, ae_tag, 308315633Smm ae_id, ae_name); 309315633Smm 310315633Smm s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 311315633Smm if (s == -1) { 312315633Smm archive_set_error(&a->archive, errno, 313315633Smm "Failed to get next ACL entry"); 314315633Smm return (ARCHIVE_WARN); 315315633Smm } 316315633Smm } 317315633Smm return (ARCHIVE_OK); 318315633Smm} 319315633Smm 320316083Smmstatic int 321316083Smmset_acl(struct archive *a, int fd, const char *name, 322316083Smm struct archive_acl *abstract_acl, 323316083Smm int ae_requested_type, const char *tname) 324316083Smm{ 325316083Smm int acl_type = 0; 326316083Smm acl_t acl; 327316083Smm acl_entry_t acl_entry; 328316083Smm acl_permset_t acl_permset; 329316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 330316083Smm acl_flagset_t acl_flagset; 331316083Smm int r; 332316083Smm#endif 333316083Smm int ret; 334316083Smm int ae_type, ae_permset, ae_tag, ae_id; 335316083Smm int perm_map_size; 336316083Smm const acl_perm_map_t *perm_map; 337316083Smm uid_t ae_uid; 338316083Smm gid_t ae_gid; 339316083Smm const char *ae_name; 340316083Smm int entries; 341316083Smm int i; 342316083Smm 343316083Smm ret = ARCHIVE_OK; 344316083Smm entries = archive_acl_reset(abstract_acl, ae_requested_type); 345316083Smm if (entries == 0) 346316083Smm return (ARCHIVE_OK); 347316083Smm 348316083Smm 349316083Smm switch (ae_requested_type) { 350316083Smm case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 351316083Smm acl_type = ACL_TYPE_ACCESS; 352316083Smm break; 353316083Smm case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 354316083Smm acl_type = ACL_TYPE_DEFAULT; 355316083Smm break; 356316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 357316083Smm case ARCHIVE_ENTRY_ACL_TYPE_NFS4: 358316083Smm acl_type = ACL_TYPE_NFS4; 359316083Smm break; 360316083Smm#endif 361316083Smm default: 362316083Smm errno = ENOENT; 363316083Smm archive_set_error(a, errno, "Unsupported ACL type"); 364316083Smm return (ARCHIVE_FAILED); 365316083Smm } 366316083Smm 367316083Smm acl = acl_init(entries); 368316083Smm if (acl == (acl_t)NULL) { 369316083Smm archive_set_error(a, errno, 370316083Smm "Failed to initialize ACL working storage"); 371316083Smm return (ARCHIVE_FAILED); 372316083Smm } 373316083Smm 374316083Smm while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, 375316083Smm &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { 376316083Smm if (acl_create_entry(&acl, &acl_entry) != 0) { 377316083Smm archive_set_error(a, errno, 378316083Smm "Failed to create a new ACL entry"); 379316083Smm ret = ARCHIVE_FAILED; 380316083Smm goto exit_free; 381316083Smm } 382316083Smm switch (ae_tag) { 383316083Smm case ARCHIVE_ENTRY_ACL_USER: 384316083Smm ae_uid = archive_write_disk_uid(a, ae_name, ae_id); 385316083Smm acl_set_tag_type(acl_entry, ACL_USER); 386316083Smm acl_set_qualifier(acl_entry, &ae_uid); 387316083Smm break; 388316083Smm case ARCHIVE_ENTRY_ACL_GROUP: 389316083Smm ae_gid = archive_write_disk_gid(a, ae_name, ae_id); 390316083Smm acl_set_tag_type(acl_entry, ACL_GROUP); 391316083Smm acl_set_qualifier(acl_entry, &ae_gid); 392316083Smm break; 393316083Smm case ARCHIVE_ENTRY_ACL_USER_OBJ: 394316083Smm acl_set_tag_type(acl_entry, ACL_USER_OBJ); 395316083Smm break; 396316083Smm case ARCHIVE_ENTRY_ACL_GROUP_OBJ: 397316083Smm acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); 398316083Smm break; 399316083Smm case ARCHIVE_ENTRY_ACL_MASK: 400316083Smm acl_set_tag_type(acl_entry, ACL_MASK); 401316083Smm break; 402316083Smm case ARCHIVE_ENTRY_ACL_OTHER: 403316083Smm acl_set_tag_type(acl_entry, ACL_OTHER); 404316083Smm break; 405316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 406316083Smm case ARCHIVE_ENTRY_ACL_EVERYONE: 407316083Smm acl_set_tag_type(acl_entry, ACL_EVERYONE); 408316083Smm break; 409316083Smm#endif 410316083Smm default: 411316083Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 412316083Smm "Unsupported ACL tag"); 413316083Smm ret = ARCHIVE_FAILED; 414316083Smm goto exit_free; 415316083Smm } 416316083Smm 417316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 418316083Smm r = 0; 419316083Smm switch (ae_type) { 420316083Smm case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: 421316083Smm r = acl_set_entry_type_np(acl_entry, 422316083Smm ACL_ENTRY_TYPE_ALLOW); 423316083Smm break; 424316083Smm case ARCHIVE_ENTRY_ACL_TYPE_DENY: 425316083Smm r = acl_set_entry_type_np(acl_entry, 426316083Smm ACL_ENTRY_TYPE_DENY); 427316083Smm break; 428316083Smm case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: 429316083Smm r = acl_set_entry_type_np(acl_entry, 430316083Smm ACL_ENTRY_TYPE_AUDIT); 431316083Smm break; 432316083Smm case ARCHIVE_ENTRY_ACL_TYPE_ALARM: 433316083Smm r = acl_set_entry_type_np(acl_entry, 434316083Smm ACL_ENTRY_TYPE_ALARM); 435316083Smm break; 436316083Smm case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 437316083Smm case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 438316083Smm // These don't translate directly into the system ACL. 439316083Smm break; 440316083Smm default: 441316083Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 442316083Smm "Unsupported ACL entry type"); 443316083Smm ret = ARCHIVE_FAILED; 444316083Smm goto exit_free; 445316083Smm } 446316083Smm 447316083Smm if (r != 0) { 448316083Smm archive_set_error(a, errno, 449316083Smm "Failed to set ACL entry type"); 450316083Smm ret = ARCHIVE_FAILED; 451316083Smm goto exit_free; 452316083Smm } 453316083Smm#endif 454316083Smm 455316083Smm if (acl_get_permset(acl_entry, &acl_permset) != 0) { 456316083Smm archive_set_error(a, errno, 457316083Smm "Failed to get ACL permission set"); 458316083Smm ret = ARCHIVE_FAILED; 459316083Smm goto exit_free; 460316083Smm } 461316083Smm if (acl_clear_perms(acl_permset) != 0) { 462316083Smm archive_set_error(a, errno, 463316083Smm "Failed to clear ACL permissions"); 464316083Smm ret = ARCHIVE_FAILED; 465316083Smm goto exit_free; 466316083Smm } 467316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 468316083Smm if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 469316083Smm perm_map_size = acl_nfs4_perm_map_size; 470316083Smm perm_map = acl_nfs4_perm_map; 471316083Smm } else { 472316083Smm#endif 473316083Smm perm_map_size = acl_posix_perm_map_size; 474316083Smm perm_map = acl_posix_perm_map; 475316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 476316083Smm } 477316083Smm#endif 478316083Smm 479316083Smm for (i = 0; i < perm_map_size; ++i) { 480316083Smm if (ae_permset & perm_map[i].a_perm) { 481316083Smm if (acl_add_perm(acl_permset, 482316083Smm perm_map[i].p_perm) != 0) { 483316083Smm archive_set_error(a, errno, 484316083Smm "Failed to add ACL permission"); 485316083Smm ret = ARCHIVE_FAILED; 486316083Smm goto exit_free; 487316083Smm } 488316083Smm } 489316083Smm } 490316083Smm 491316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 492316083Smm if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 493316083Smm /* 494316083Smm * acl_get_flagset_np() fails with non-NFSv4 ACLs 495316083Smm */ 496316083Smm if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 497316083Smm archive_set_error(a, errno, 498316083Smm "Failed to get flagset from an NFSv4 " 499316083Smm "ACL entry"); 500316083Smm ret = ARCHIVE_FAILED; 501316083Smm goto exit_free; 502316083Smm } 503316083Smm if (acl_clear_flags_np(acl_flagset) != 0) { 504316083Smm archive_set_error(a, errno, 505316083Smm "Failed to clear flags from an NFSv4 " 506316083Smm "ACL flagset"); 507316083Smm ret = ARCHIVE_FAILED; 508316083Smm goto exit_free; 509316083Smm } 510316083Smm for (i = 0; i < acl_nfs4_flag_map_size; ++i) { 511316083Smm if (ae_permset & acl_nfs4_flag_map[i].a_perm) { 512316083Smm if (acl_add_flag_np(acl_flagset, 513316083Smm acl_nfs4_flag_map[i].p_perm) != 0) { 514316083Smm archive_set_error(a, errno, 515316083Smm "Failed to add flag to " 516316083Smm "NFSv4 ACL flagset"); 517316083Smm ret = ARCHIVE_FAILED; 518316083Smm goto exit_free; 519316083Smm } 520316083Smm } 521316083Smm } 522316083Smm } 523316083Smm#endif 524316083Smm } 525316083Smm 526316083Smm /* Try restoring the ACL through 'fd' if we can. */ 527316083Smm if (fd >= 0) { 528316083Smm if (acl_set_fd_np(fd, acl, acl_type) == 0) 529316083Smm ret = ARCHIVE_OK; 530316083Smm else { 531316083Smm if (errno == EOPNOTSUPP) { 532316083Smm /* Filesystem doesn't support ACLs */ 533316083Smm ret = ARCHIVE_OK; 534316083Smm } else { 535316083Smm archive_set_error(a, errno, 536316083Smm "Failed to set acl on fd: %s", tname); 537316083Smm ret = ARCHIVE_WARN; 538316083Smm } 539316083Smm } 540316083Smm } 541316083Smm#if HAVE_ACL_SET_LINK_NP 542316083Smm else if (acl_set_link_np(name, acl_type, acl) != 0) 543316083Smm#else 544316083Smm /* FreeBSD older than 8.0 */ 545316083Smm else if (acl_set_file(name, acl_type, acl) != 0) 546316083Smm#endif 547316083Smm { 548316083Smm if (errno == EOPNOTSUPP) { 549316083Smm /* Filesystem doesn't support ACLs */ 550316083Smm ret = ARCHIVE_OK; 551316083Smm } else { 552316083Smm archive_set_error(a, errno, "Failed to set acl: %s", 553316083Smm tname); 554316083Smm ret = ARCHIVE_WARN; 555316083Smm } 556316083Smm } 557316083Smmexit_free: 558316083Smm acl_free(acl); 559316083Smm return (ret); 560316083Smm} 561316083Smm 562315633Smmint 563315633Smmarchive_read_disk_entry_setup_acls(struct archive_read_disk *a, 564315633Smm struct archive_entry *entry, int *fd) 565315633Smm{ 566315633Smm const char *accpath; 567315633Smm acl_t acl; 568315633Smm int r; 569315633Smm 570315633Smm accpath = NULL; 571315633Smm 572315633Smm if (*fd < 0) { 573315633Smm accpath = archive_read_disk_entry_setup_path(a, entry, fd); 574315633Smm if (accpath == NULL) 575315633Smm return (ARCHIVE_WARN); 576315633Smm } 577315633Smm 578315633Smm archive_entry_acl_clear(entry); 579315633Smm 580315633Smm acl = NULL; 581315633Smm 582315633Smm#if ARCHIVE_ACL_FREEBSD_NFS4 583315633Smm /* Try NFSv4 ACL first. */ 584315633Smm if (*fd >= 0) 585315633Smm acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4); 586315633Smm else if (!a->follow_symlinks) 587315633Smm acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); 588315633Smm else 589315633Smm acl = acl_get_file(accpath, ACL_TYPE_NFS4); 590315633Smm 591315633Smm /* Ignore "trivial" ACLs that just mirror the file mode. */ 592315633Smm if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 593315633Smm acl_free(acl); 594315633Smm acl = NULL; 595315633Smm return (ARCHIVE_OK); 596315633Smm } 597315633Smm 598315633Smm if (acl != NULL) { 599315633Smm r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); 600315633Smm acl_free(acl); 601315633Smm acl = NULL; 602315633Smm 603315633Smm if (r != ARCHIVE_OK) { 604315633Smm archive_set_error(&a->archive, errno, 605315633Smm "Couldn't translate NFSv4 ACLs"); 606315633Smm } 607315633Smm 608315633Smm return (r); 609315633Smm } 610315633Smm#endif 611315633Smm 612315633Smm /* Retrieve access ACL from file. */ 613315633Smm if (*fd >= 0) 614315633Smm acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS); 615315633Smm#if HAVE_ACL_GET_LINK_NP 616315633Smm else if (!a->follow_symlinks) 617315633Smm acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); 618315633Smm#else 619315633Smm else if ((!a->follow_symlinks) 620315633Smm && (archive_entry_filetype(entry) == AE_IFLNK)) 621315633Smm /* We can't get the ACL of a symlink, so we assume it can't 622315633Smm have one. */ 623315633Smm acl = NULL; 624315633Smm#endif 625315633Smm else 626315633Smm acl = acl_get_file(accpath, ACL_TYPE_ACCESS); 627315633Smm 628315633Smm#if HAVE_ACL_IS_TRIVIAL_NP 629315633Smm /* Ignore "trivial" ACLs that just mirror the file mode. */ 630315633Smm if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { 631315633Smm acl_free(acl); 632315633Smm acl = NULL; 633315633Smm } 634315633Smm#endif 635315633Smm 636315633Smm if (acl != NULL) { 637315633Smm r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); 638315633Smm acl_free(acl); 639315633Smm acl = NULL; 640315633Smm 641315633Smm if (r != ARCHIVE_OK) { 642315633Smm archive_set_error(&a->archive, errno, 643315633Smm "Couldn't translate access ACLs"); 644315633Smm return (r); 645315633Smm } 646315633Smm } 647315633Smm 648315633Smm /* Only directories can have default ACLs. */ 649315633Smm if (S_ISDIR(archive_entry_mode(entry))) { 650315633Smm if (*fd >= 0) 651315633Smm acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); 652315633Smm else 653315633Smm acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); 654315633Smm if (acl != NULL) { 655315633Smm r = translate_acl(a, entry, acl, 656315633Smm ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); 657315633Smm acl_free(acl); 658315633Smm if (r != ARCHIVE_OK) { 659315633Smm archive_set_error(&a->archive, errno, 660315633Smm "Couldn't translate default ACLs"); 661315633Smm return (r); 662315633Smm } 663315633Smm } 664315633Smm } 665315633Smm return (ARCHIVE_OK); 666315633Smm} 667316083Smm 668316083Smmint 669316083Smmarchive_write_disk_set_acls(struct archive *a, int fd, const char *name, 670316083Smm struct archive_acl *abstract_acl, __LA_MODE_T mode) 671316083Smm{ 672316083Smm int ret = ARCHIVE_OK; 673316083Smm 674316083Smm (void)mode; /* UNUSED */ 675316083Smm 676316083Smm if ((archive_acl_types(abstract_acl) 677316083Smm & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { 678316083Smm if ((archive_acl_types(abstract_acl) 679316083Smm & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { 680316083Smm ret = set_acl(a, fd, name, abstract_acl, 681316083Smm ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); 682316083Smm if (ret != ARCHIVE_OK) 683316083Smm return (ret); 684316083Smm } 685316083Smm if ((archive_acl_types(abstract_acl) 686316083Smm & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) 687316083Smm ret = set_acl(a, fd, name, abstract_acl, 688316083Smm ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); 689316083Smm 690316083Smm /* Simultaneous POSIX.1e and NFSv4 is not supported */ 691316083Smm return (ret); 692316083Smm } 693316083Smm#if ARCHIVE_ACL_FREEBSD_NFS4 694316083Smm else if ((archive_acl_types(abstract_acl) & 695316083Smm ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { 696316083Smm ret = set_acl(a, fd, name, abstract_acl, 697316083Smm ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); 698316083Smm } 699316083Smm#endif 700316083Smm return (ret); 701316083Smm} 702316095Smm#endif /* ARCHIVE_ACL_FREEBSD */ 703