Path: blob/main/contrib/libarchive/tar/test/test_option_acls.c
39507 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2017 Martin Matuska4* All rights reserved.5*/6#include "test.h"78#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL9static const acl_perm_t acl_perms[] = {10#if ARCHIVE_ACL_DARWIN11ACL_READ_DATA,12ACL_LIST_DIRECTORY,13ACL_WRITE_DATA,14ACL_ADD_FILE,15ACL_EXECUTE,16ACL_SEARCH,17ACL_DELETE,18ACL_APPEND_DATA,19ACL_ADD_SUBDIRECTORY,20ACL_DELETE_CHILD,21ACL_READ_ATTRIBUTES,22ACL_WRITE_ATTRIBUTES,23ACL_READ_EXTATTRIBUTES,24ACL_WRITE_EXTATTRIBUTES,25ACL_READ_SECURITY,26ACL_WRITE_SECURITY,27ACL_CHANGE_OWNER,28ACL_SYNCHRONIZE29#else /* !ARCHIVE_ACL_DARWIN */30ACL_EXECUTE,31ACL_WRITE,32ACL_READ,33#if ARCHIVE_ACL_FREEBSD_NFS434ACL_READ_DATA,35ACL_LIST_DIRECTORY,36ACL_WRITE_DATA,37ACL_ADD_FILE,38ACL_APPEND_DATA,39ACL_ADD_SUBDIRECTORY,40ACL_READ_NAMED_ATTRS,41ACL_WRITE_NAMED_ATTRS,42ACL_DELETE_CHILD,43ACL_READ_ATTRIBUTES,44ACL_WRITE_ATTRIBUTES,45ACL_DELETE,46ACL_READ_ACL,47ACL_WRITE_ACL,48ACL_WRITE_OWNER,49ACL_SYNCHRONIZE50#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */51#endif /* !ARCHIVE_ACL_DARWIN */52};53#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS454static const acl_flag_t acl_flags[] = {55#if ARCHIVE_ACL_DARWIN56ACL_ENTRY_INHERITED,57ACL_ENTRY_FILE_INHERIT,58ACL_ENTRY_DIRECTORY_INHERIT,59ACL_ENTRY_LIMIT_INHERIT,60ACL_ENTRY_ONLY_INHERIT61#else /* ARCHIVE_ACL_FREEBSD_NFS4 */62ACL_ENTRY_FILE_INHERIT,63ACL_ENTRY_DIRECTORY_INHERIT,64ACL_ENTRY_NO_PROPAGATE_INHERIT,65ACL_ENTRY_INHERIT_ONLY,66ACL_ENTRY_SUCCESSFUL_ACCESS,67ACL_ENTRY_FAILED_ACCESS,68#ifdef ACL_ENTRY_INHERITED69ACL_ENTRY_INHERITED70#endif71#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */72};73#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 */7475/*76* Compare two ACL entries on FreeBSD or on Mac OS X77*/78static int79compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4)80{81acl_tag_t tag_a, tag_b;82acl_permset_t permset_a, permset_b;83int perm_a, perm_b, perm_start, perm_end;84void *qual_a, *qual_b;85#if ARCHIVE_ACL_FREEBSD_NFS486acl_entry_type_t type_a, type_b;87#endif88#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN89acl_flagset_t flagset_a, flagset_b;90int flag_a, flag_b;91#endif92int i, r;939495/* Compare ACL tag */96r = acl_get_tag_type(ae_a, &tag_a);97failure("acl_get_tag_type() error: %s", strerror(errno));98if (assertEqualInt(r, 0) == 0)99return (-1);100r = acl_get_tag_type(ae_b, &tag_b);101failure("acl_get_tag_type() error: %s", strerror(errno));102if (assertEqualInt(r, 0) == 0)103return (-1);104if (tag_a != tag_b)105return (0);106107/* Compare ACL qualifier */108#if ARCHIVE_ACL_DARWIN109if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY)110#else111if (tag_a == ACL_USER || tag_a == ACL_GROUP)112#endif113{114qual_a = acl_get_qualifier(ae_a);115failure("acl_get_qualifier() error: %s", strerror(errno));116if (assert(qual_a != NULL) == 0)117return (-1);118qual_b = acl_get_qualifier(ae_b);119failure("acl_get_qualifier() error: %s", strerror(errno));120if (assert(qual_b != NULL) == 0) {121acl_free(qual_a);122return (-1);123}124#if ARCHIVE_ACL_DARWIN125if (memcmp(((guid_t *)qual_a)->g_guid,126((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0)127#else128if ((tag_a == ACL_USER &&129(*(uid_t *)qual_a != *(uid_t *)qual_b)) ||130(tag_a == ACL_GROUP &&131(*(gid_t *)qual_a != *(gid_t *)qual_b)))132#endif133{134acl_free(qual_a);135acl_free(qual_b);136return (0);137}138acl_free(qual_a);139acl_free(qual_b);140}141142#if ARCHIVE_ACL_FREEBSD_NFS4143if (is_nfs4) {144/* Compare NFS4 ACL type */145r = acl_get_entry_type_np(ae_a, &type_a);146failure("acl_get_entry_type_np() error: %s", strerror(errno));147if (assertEqualInt(r, 0) == 0)148return (-1);149r = acl_get_entry_type_np(ae_b, &type_b);150failure("acl_get_entry_type_np() error: %s", strerror(errno));151if (assertEqualInt(r, 0) == 0)152return (-1);153if (type_a != type_b)154return (0);155}156#endif157158/* Compare ACL perms */159r = acl_get_permset(ae_a, &permset_a);160failure("acl_get_permset() error: %s", strerror(errno));161if (assertEqualInt(r, 0) == 0)162return (-1);163r = acl_get_permset(ae_b, &permset_b);164failure("acl_get_permset() error: %s", strerror(errno));165if (assertEqualInt(r, 0) == 0)166return (-1);167168perm_start = 0;169perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0]));170#if ARCHIVE_ACL_FREEBSD_NFS4171if (is_nfs4)172perm_start = 3;173else174perm_end = 3;175#endif176/* Cycle through all perms and compare their value */177for (i = perm_start; i < perm_end; i++) {178#if ARCHIVE_ACL_LIBACL179perm_a = acl_get_perm(permset_a, acl_perms[i]);180perm_b = acl_get_perm(permset_b, acl_perms[i]);181#else182perm_a = acl_get_perm_np(permset_a, acl_perms[i]);183perm_b = acl_get_perm_np(permset_b, acl_perms[i]);184#endif185if (perm_a == -1 || perm_b == -1)186return (-1);187if (perm_a != perm_b)188return (0);189}190191#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN192if (is_nfs4) {193r = acl_get_flagset_np(ae_a, &flagset_a);194failure("acl_get_flagset_np() error: %s", strerror(errno));195if (assertEqualInt(r, 0) == 0)196return (-1);197r = acl_get_flagset_np(ae_b, &flagset_b);198failure("acl_get_flagset_np() error: %s", strerror(errno));199if (assertEqualInt(r, 0) == 0)200return (-1);201/* Cycle through all flags and compare their status */202for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0]));203i++) {204flag_a = acl_get_flag_np(flagset_a, acl_flags[i]);205flag_b = acl_get_flag_np(flagset_b, acl_flags[i]);206if (flag_a == -1 || flag_b == -1)207return (-1);208if (flag_a != flag_b)209return (0);210}211}212#else /* ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN */213(void)is_nfs4; /* UNUSED */214#endif215return (1);216}217#endif /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL */218219#if ARCHIVE_ACL_SUPPORT220/*221* Clear default ACLs or inheritance flags222*/223static void224clear_inheritance_flags(const char *path, int type)225{226switch (type) {227case ARCHIVE_TEST_ACL_TYPE_POSIX1E:228#if ARCHIVE_ACL_POSIX1E229#if !ARCHIVE_ACL_SUNOS230acl_delete_def_file(path);231#else232/* Solaris */233setTestAcl(path);234#endif235#endif /* ARCHIVE_ACL_POSIX1E */236break;237case ARCHIVE_TEST_ACL_TYPE_NFS4:238#if ARCHIVE_ACL_NFS4239setTestAcl(path);240#endif241break;242default:243(void)path; /* UNUSED */244break;245}246}247248static int249compare_acls(const char *path_a, const char *path_b)250{251int ret = 1;252int is_nfs4 = 0;253#if ARCHIVE_ACL_SUNOS254void *acl_a, *acl_b;255int aclcnt_a, aclcnt_b;256aclent_t *aclent_a, *aclent_b;257ace_t *ace_a, *ace_b;258int e;259#elif ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL260acl_t acl_a, acl_b;261acl_entry_t aclent_a, aclent_b;262int a, b, r;263#endif264#if ARCHIVE_ACL_LIBRICHACL265struct richacl *richacl_a, *richacl_b;266267richacl_a = NULL;268richacl_b = NULL;269#endif270271#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL || \272ARCHIVE_ACL_SUNOS273acl_a = NULL;274acl_b = NULL;275#endif276#if ARCHIVE_ACL_SUNOS277acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a);278if (acl_a == NULL) {279#if ARCHIVE_ACL_SUNOS_NFS4280is_nfs4 = 1;281acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a);282#endif283failure("acl_get() error: %s", strerror(errno));284if (assert(acl_a != NULL) == 0)285return (-1);286#if ARCHIVE_ACL_SUNOS_NFS4287acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b);288#endif289} else290acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b);291if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) {292free(acl_a);293return (0);294}295failure("acl_get() error: %s", strerror(errno));296if (assert(acl_b != NULL) == 0) {297free(acl_a);298return (-1);299}300301if (aclcnt_a != aclcnt_b) {302ret = 0;303goto exit_free;304}305306for (e = 0; e < aclcnt_a; e++) {307if (!is_nfs4) {308aclent_a = &((aclent_t *)acl_a)[e];309aclent_b = &((aclent_t *)acl_b)[e];310if (aclent_a->a_type != aclent_b->a_type ||311aclent_a->a_id != aclent_b->a_id ||312aclent_a->a_perm != aclent_b->a_perm) {313ret = 0;314goto exit_free;315}316}317#if ARCHIVE_ACL_SUNOS_NFS4318else {319ace_a = &((ace_t *)acl_a)[e];320ace_b = &((ace_t *)acl_b)[e];321if (ace_a->a_who != ace_b->a_who ||322ace_a->a_access_mask != ace_b->a_access_mask ||323ace_a->a_flags != ace_b->a_flags ||324ace_a->a_type != ace_b->a_type) {325ret = 0;326goto exit_free;327}328}329#endif330}331#else /* !ARCHIVE_ACL_SUNOS */332#if ARCHIVE_ACL_LIBRICHACL333richacl_a = richacl_get_file(path_a);334#if !ARCHIVE_ACL_LIBACL335if (richacl_a == NULL &&336(errno == ENODATA || errno == ENOTSUP || errno == ENOSYS))337return (0);338failure("richacl_get_file() error: %s (%s)", path_a, strerror(errno));339if (assert(richacl_a != NULL) == 0)340return (-1);341#endif342if (richacl_a != NULL) {343richacl_b = richacl_get_file(path_b);344if (richacl_b == NULL &&345(errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) {346richacl_free(richacl_a);347return (0);348}349failure("richacl_get_file() error: %s (%s)", path_b,350strerror(errno));351if (assert(richacl_b != NULL) == 0) {352richacl_free(richacl_a);353return (-1);354}355if (richacl_compare(richacl_a, richacl_b) == 0)356ret = 0;357richacl_free(richacl_a);358richacl_free(richacl_b);359return (ret);360}361#endif /* ARCHIVE_ACL_LIBRICHACL */362#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL363#if ARCHIVE_ACL_DARWIN364is_nfs4 = 1;365acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED);366#elif ARCHIVE_ACL_FREEBSD_NFS4367acl_a = acl_get_file(path_a, ACL_TYPE_NFS4);368if (acl_a != NULL)369is_nfs4 = 1;370#endif371if (acl_a == NULL)372acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS);373failure("acl_get_file() error: %s (%s)", path_a, strerror(errno));374if (assert(acl_a != NULL) == 0)375return (-1);376#if ARCHIVE_ACL_DARWIN377acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED);378#elif ARCHIVE_ACL_FREEBSD_NFS4379acl_b = acl_get_file(path_b, ACL_TYPE_NFS4);380#endif381#if !ARCHIVE_ACL_DARWIN382if (acl_b == NULL) {383#if ARCHIVE_ACL_FREEBSD_NFS4384if (is_nfs4) {385acl_free(acl_a);386return (0);387}388#endif389acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS);390}391failure("acl_get_file() error: %s (%s)", path_b, strerror(errno));392if (assert(acl_b != NULL) == 0) {393acl_free(acl_a);394return (-1);395}396#endif397a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a);398if (a == -1) {399ret = 0;400goto exit_free;401}402b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b);403if (b == -1) {404ret = 0;405goto exit_free;406}407#if ARCHIVE_ACL_DARWIN408while (a == 0 && b == 0)409#else /* FreeBSD, Linux */410while (a == 1 && b == 1)411#endif412{413r = compare_acl_entry(aclent_a, aclent_b, is_nfs4);414if (r != 1) {415ret = r;416goto exit_free;417}418a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a);419b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b);420}421/* Entry count must match */422if (a != b)423ret = 0;424#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */425#endif /* !ARCHIVE_ACL_SUNOS */426exit_free:427#if ARCHIVE_ACL_SUNOS428free(acl_a);429free(acl_b);430#else431acl_free(acl_a);432acl_free(acl_b);433#endif434return (ret);435}436#endif /* ARCHIVE_ACL_SUPPORT */437438DEFINE_TEST(test_option_acls)439{440#if !ARCHIVE_ACL_SUPPORT441skipping("ACLs are not supported on this platform");442#else /* ARCHIVE_ACL_SUPPORT */443int acltype, r;444445assertMakeFile("f", 0644, "a");446acltype = setTestAcl("f");447if (acltype == 0) {448skipping("Can't write ACLs on the filesystem");449return;450}451452/* Archive it with acls */453r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog);454assertEqualInt(r, 0);455456/* Archive it without acls */457r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog);458assertEqualInt(r, 0);459460/* Extract acls with acls */461assertMakeDir("acls_acls", 0755);462clear_inheritance_flags("acls_acls", acltype);463r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog);464assertEqualInt(r, 0);465r = compare_acls("f", "acls_acls/f");466assertEqualInt(r, 1);467468/* Extract acls without acls */469assertMakeDir("acls_noacls", 0755);470clear_inheritance_flags("acls_noacls", acltype);471r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog);472assertEqualInt(r, 0);473r = compare_acls("f", "acls_noacls/f");474assertEqualInt(r, 0);475476/* Extract noacls with acls flag */477assertMakeDir("noacls_acls", 0755);478clear_inheritance_flags("noacls_acls", acltype);479r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog);480assertEqualInt(r, 0);481r = compare_acls("f", "noacls_acls/f");482assertEqualInt(r, 0);483484/* Extract noacls with noacls */485assertMakeDir("noacls_noacls", 0755);486clear_inheritance_flags("noacls_noacls", acltype);487r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog);488assertEqualInt(r, 0);489r = compare_acls("f", "noacls_noacls/f");490assertEqualInt(r, 0);491#endif /* ARCHIVE_ACL_SUPPORT */492}493494495