From b7e682520c10f18efdd50901896291b7a74a72fc Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 15 Aug 2012 02:51:08 -0400 Subject: [PATCH] Add another test. Settle on the new reapplication algorithm. Remove a ton of dead code. --- run-tests.sh | 60 ++++- src/aclq.c | 723 ++++++++++----------------------------------------- 2 files changed, 193 insertions(+), 590 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 4bfd364..a01d47c 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -139,8 +139,8 @@ compare -# Make sure execute permission is removed for group/other after the -# reapplication. +# Since the default ACL will grant r-x to group/other, they will wind +# up with it. TESTNUM=6 touch "${TARGET}" chmod 744 "${TARGET}" @@ -151,9 +151,9 @@ setfacl -d -m user:mail:rwx "${TESTDIR}" EXPECTED=$(cat < 3) { + return entry_count; +} + + +int acl_is_minimal(acl_t* acl) { + /* An ACL is minimal if it has fewer than four entries. Return 0 for + false, 1 for true, and -1 on error. */ + + int ec = acl_entry_count(acl); + if (ec == -1) { + perror("acl_is_minimal (acl_entry_count)"); + return -1; + } + + if (ec < 4) { return 1; } else { @@ -751,7 +209,10 @@ int acl_is_minimal(acl_t* acl) { } } + int any_can_execute(const char* path) { + /* Returns 1 if any ACL entry has execute access, 0 if none do, and + -1 on error. */ acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); if (acl_is_minimal(&acl)) { @@ -802,7 +263,86 @@ int any_can_execute(const char* path) { } -int reapply_default_acl_ng(const char* path) { +int inherit_default_acl(const char* path, const char* parent) { + /* Inherit the default ACL from parent to path. This overwrites any + existing default ACL. Returns 1 for success, 0 for failure, and + -1 on error. */ + + if (path == NULL) { + errno = ENOENT; + return -1; + } + + if (!is_directory(path) || !is_directory(parent)) { + return 0; + } + + acl_t parent_acl = acl_get_file(parent, ACL_TYPE_DEFAULT); + acl_t path_acl = acl_dup(parent_acl); + + if (path_acl == (acl_t)NULL) { + perror("inherit_default_acl (acl_dup)"); + return -1; + } + + int sf_result = acl_set_file(path, ACL_TYPE_DEFAULT, path_acl); + if (sf_result == -1) { + perror("inherit_default_acl (acl_set_file)"); + return -1; + } + + acl_free(path_acl); + return 1; +} + + +int wipe_acls(const char* path) { + /* Remove ACL_USER, ACL_GROUP, and ACL_MASK entries from + path. Returns 1 for success, 0 for failure, and -1 on error. */ + + if (path == NULL) { + errno = ENOENT; + return -1; + } + + /* Finally, remove individual named/mask entries. */ + acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == (acl_t)NULL) { + perror("wipe_acls (acl_get_file)"); + return -1; + } + + acl_entry_t entry; + int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + + while (result == 1) { + int d_result = acl_delete_entry(acl, entry); + if (d_result == -1) { + perror("wipe_acls (acl_delete_entry)"); + return -1; + } + + result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + } + + /* Catches the first acl_get_entry as well as the ones at the end of + the loop. */ + if (result == -1) { + perror("reapply_default_acl_ng (acl_get_entry)"); + return -1; + } + + int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl); + if (sf_result == -1) { + perror("wipe_acls (acl_set_file)"); + return -1; + } + + return 1; +} + + +int reapply_default_acl(const char* path) { /* Really reapply the default ACL by looping through it. Returns one for success, zero for failure (i.e. no ACL), and -1 on unexpected errors. */ @@ -834,10 +374,31 @@ int reapply_default_acl_ng(const char* path) { bool allow_exec = (bool)ace_result; acl_t defacl = acl_get_file(parent, ACL_TYPE_DEFAULT); + + if (defacl == (acl_t)NULL) { + perror("reapply_default_acl_ng (acl_get_file)"); + return -1; + } + + int wipe_result = wipe_acls(path); + if (wipe_result == -1) { + perror("reapply_default_acl_ng (wipe_acls)"); + return -1; + } + + /* Do this after wipe_acls(), otherwise we'll overwrite the wiped + ACL with this one. */ acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == (acl_t)NULL) { + perror("reapply_default_acl_ng (acl_get_file)"); + return -1; + } - if (defacl == (acl_t)NULL || acl == (acl_t)NULL) { - return 0; + /* If it's a directory, inherit the parent's default. */ + int inherit_result = inherit_default_acl(path, parent); + if (inherit_result == -1) { + perror("reapply_default_acl_ng (inherit_acls)"); + return -1; } acl_entry_t entry; @@ -885,9 +446,9 @@ int reapply_default_acl_ng(const char* path) { } /* Finally, add the permset to the access ACL. */ - int set_result = set_acl_entry(&acl, entry); + int set_result = acl_set_entry(&acl, entry); if (set_result == -1) { - perror("reapply_default_acl_ng (set_acl_entry)"); + perror("reapply_default_acl_ng (acl_set_entry)"); return -1; } @@ -915,7 +476,7 @@ int reapply_default_acl_ng(const char* path) { int main(int argc, char* argv[]) { const char* target = argv[1]; - bool result = reapply_default_acl_ng(target); + bool result = reapply_default_acl(target); if (result) { return EXIT_SUCCESS; -- 2.43.2