X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Faclq.c;h=6ea2e1dd7ba0e3d7e9c2b22d02716fbe4ed6608b;hb=97a849f60570c2174bf0397311498f29d5b9155a;hp=495196d77a33bb3c0fa7a904ec3df64dbe7eda38;hpb=b3babd5135c8683e68ce97cc76e0ec0487d4ee46;p=apply-default-acl.git diff --git a/src/aclq.c b/src/aclq.c index 495196d..6ea2e1d 100644 --- a/src/aclq.c +++ b/src/aclq.c @@ -1,13 +1,77 @@ #include +#include /* dirname() */ #include /* PATH_MAX */ #include #include #include +#include +#include +#include /* ACLs */ #include #include + +mode_t get_mode(const char* path) { + if (path == NULL) { + errno = ENOENT; + return -1; + } + + struct stat s; + int result = stat(path, &s); + + if (result == 0) { + return s.st_mode; + } + else { + /* errno will be set already by stat() */ + return result; + } +} + +bool mode_has_perm(mode_t mode, int perm) { + if (mode & perm) { + return true; + } + else { + return false; + } +} + + +bool is_regular_file(const char* path) { + if (path == NULL) { + return false; + } + + struct stat s; + int result = stat(path, &s); + if (result == 0) { + return S_ISREG(s.st_mode); + } + else { + return false; + } +} + +bool is_directory(const char* path) { + if (path == NULL) { + return false; + } + + struct stat s; + int result = stat(path, &s); + if (result == 0) { + return S_ISDIR(s.st_mode); + } + else { + return false; + } +} + + bool has_default_acl(const char* path) { /* Return true if the given path has a default ACL, false otherwise. */ @@ -55,7 +119,7 @@ bool has_default_tag_acl(const char* path, acl_tag_t tag_type) { int tag_result = acl_get_tag_type(entry, &tag); if (tag_result == -1) { - perror("has_default_tag_acl"); + perror("has_default_tag_acl - acl_get_tag_type"); return false; } else { @@ -79,21 +143,21 @@ bool has_default_group_obj_acl(const char* path) { return has_default_tag_acl(path, ACL_GROUP_OBJ); } -bool has_default_other_obj_acl(const char* path) { +bool has_default_other_acl(const char* path) { return has_default_tag_acl(path, ACL_OTHER); } -int get_default_tag_permset(const char* path, +bool get_default_tag_permset(const char* path, acl_tag_t tag_type, acl_permset_t* output_perms) { - /* Return true if the given path has a default ACL for the supplied - tag, false otherwise. */ + /* Returns true if successful or false on error */ acl_t defacl = acl_get_file(path, ACL_TYPE_DEFAULT); if (defacl == (acl_t)NULL) { /* Follow the acl_foo convention of -1 == error. */ - return -1; + errno = EINVAL; + return false; } acl_entry_t entry; @@ -105,85 +169,221 @@ int get_default_tag_permset(const char* path, if (tag_result == -1) { perror("get_default_tag_permset"); - return -1; + return false; } else { if (tag == tag_type) { /* We found the right tag, now get the permset. */ - return acl_get_permset(entry, output_perms); + int ps_result = acl_get_permset(entry, output_perms); + if (ps_result == 0) { + return true; + } + else { + return false; + } } } result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry); } - + + errno = EINVAL; return false; } -int get_default_user_obj_permset(const char* path, +bool get_default_user_obj_permset(const char* path, acl_permset_t* output_perms) { return get_default_tag_permset(path, ACL_USER_OBJ, output_perms); } -int get_default_group_obj_permset(const char* path, +bool get_default_group_obj_permset(const char* path, acl_permset_t* output_perms) { return get_default_tag_permset(path, ACL_GROUP_OBJ, output_perms); } -int get_default_other_obj_permset(const char* path, +bool get_default_other_permset(const char* path, acl_permset_t* output_perms) { return get_default_tag_permset(path, ACL_OTHER, output_perms); } + +bool has_default_tag_perm(const char* path, + acl_tag_t tag, + acl_perm_t perm) { + /* Check path to see if tag has perm. */ + + if (!has_default_tag_acl(path, tag)) { + return false; + } + + acl_permset_t permset; + bool ps_result = get_default_tag_permset(path, tag, &permset); + + if (!ps_result) { + return false; + } + + int p_result = acl_get_perm(permset, perm); + if (p_result == 1) { + return true; + } + else { + return false; + } +} + +bool has_default_user_obj_read(const char* path) { + return has_default_tag_perm(path, ACL_USER_OBJ, ACL_READ); +} + +bool has_default_user_obj_write(const char* path) { + return has_default_tag_perm(path, ACL_USER_OBJ, ACL_WRITE); +} + +bool has_default_user_obj_execute(const char* path) { + return has_default_tag_perm(path, ACL_USER_OBJ, ACL_EXECUTE); +} + +bool has_default_group_obj_read(const char* path) { + return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_READ); +} + +bool has_default_group_obj_write(const char* path) { + return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_WRITE); +} + +bool has_default_group_obj_execute(const char* path) { + return has_default_tag_perm(path, ACL_GROUP_OBJ, ACL_EXECUTE); +} + +bool has_default_other_read(const char* path) { + return has_default_tag_perm(path, ACL_OTHER, ACL_READ); +} + +bool has_default_other_write(const char* path) { + return has_default_tag_perm(path, ACL_OTHER, ACL_WRITE); +} + +bool has_default_other_execute(const char* path) { + return has_default_tag_perm(path, ACL_OTHER, ACL_EXECUTE); +} + +bool has_default_mask_read(const char* path) { + return has_default_tag_perm(path, ACL_MASK, ACL_READ); +} + +bool has_default_mask_write(const char* path) { + return has_default_tag_perm(path, ACL_MASK, ACL_WRITE); +} + +bool has_default_mask_execute(const char* path) { + return has_default_tag_perm(path, ACL_MASK, ACL_EXECUTE); +} + + +bool reapply_default_acl(const char* path) { + /* If this is a normal file or directory (i.e. that has just been + created), we proceed to find its parent directory which will have + a default ACL. */ + if (path == NULL) { + return false; + } + + if (!is_regular_file(path) && !is_directory(path)) { + return false; + } + + /* dirname mangles its argument */ + char path_copy[PATH_MAX]; + strncpy(path_copy, path, PATH_MAX-1); + path_copy[PATH_MAX] = 0; + + char* parent = dirname(path_copy); + if (!is_directory(parent)) { + /* Make sure dirname() did what we think it did. */ + return false; + } + + /* This is the original mode of path. We will simply add permissions + to it, and then later reapply the result via chmod. */ + mode_t path_mode = get_mode(path); + + + /* If parent has a default user ACL, apply it to path via chmod. */ + if (has_default_user_obj_read(parent)) { + path_mode |= S_IRUSR; + } + + if (has_default_user_obj_write(parent)) { + path_mode |= S_IWUSR; + } + + /* However, we don't want to set the execute bit on via the ACL + unless it was on originally. Furthermore, if the ACL denies + execute, we want to honor that. */ + if (has_default_user_obj_acl(parent)) { + if (!has_default_user_obj_execute(parent)) { + /* It has a user ACL, but no user execute is granted. */ + path_mode &= ~S_IXUSR; + } + } + + + /* Do the same thing with the other perms/ACL. */ + if (has_default_other_read(parent)) { + path_mode |= S_IROTH; + } + + if (has_default_other_write(parent)) { + path_mode |= S_IWOTH; + } + + if (has_default_other_acl(parent)) { + if (!has_default_other_execute(parent)) { + /* It has an other ACL, but no other execute is granted. */ + path_mode &= ~S_IXOTH; + } + } + + /* For the group bits, we'll use the ACL's mask instead of the group + object bits. If the default ACL had a group entry, it should + already have propagated (but might be masked. */ + if (has_default_mask_read(parent)) { + path_mode |= S_IRGRP; + } + + if (has_default_mask_write(parent)) { + path_mode |= S_IWGRP; + } + + /* Honor the mask execute unconditionally. */ + if (has_default_mask_execute(parent)) { + if (mode_has_perm(path_mode, S_IXGRP)) { + path_mode |= S_IXGRP; + } + } + + int result = chmod(path, path_mode); + if (result == 0) { + return true; + } + else { + return false; + } +} + + int main(int argc, char* argv[]) { const char* target = argv[1]; - printf("Target: %s\n", target); - if (has_default_acl(target)) { - printf("Target has a default ACL.\n"); - } - else { - printf("Target does not have a default ACL.\n"); - } - - if (has_default_user_obj_acl(target)) { - printf("Target has a default owner ACL.\n"); - acl_permset_t owner_perms; - get_default_user_obj_permset(target, &owner_perms); - if (acl_get_perm(owner_perms, ACL_READ) == 1) { - printf("User: read\n"); - } - if (acl_get_perm(owner_perms, ACL_WRITE) == 1) { - printf("User: write\n"); - } - if (acl_get_perm(owner_perms, ACL_EXECUTE) == 1) { - printf("User: execute\n"); - } - } - else { - printf("Target does not have a default owner ACL.\n"); - } - - if (has_default_group_obj_acl(target)) { - printf("Target has a default group ACL.\n"); - } - else { - printf("Target does not have a default group ACL.\n"); - } + bool result = reapply_default_acl(target); - if (has_default_other_obj_acl(target)) { - printf("Target has a default other ACL.\n"); + if (result) { + printf("Success.\n"); + return EXIT_SUCCESS; } else { - printf("Target does not have a default other ACL.\n"); + return EXIT_FAILURE; } - /* - acl_permset_t group_perms; - get_default_group_obj_permset(); - - acl_permset_t other_perms; - get_default_other_obj_permset(); - */ - return EXIT_SUCCESS; }