X-Git-Url: https://gitweb.michael.orlitzky.com/?p=apply-default-acl.git;a=blobdiff_plain;f=src%2Flibadacl.c;h=aa473c4d696db186e2271d3ed92a09ed9c48596b;hp=5bca89fe405dc1a030bdab0ef4ccd55b8d5eab71;hb=9c3d24f7347f6f9f7a8c5fdf0c7f649ce5fb927a;hpb=62844f5f2d280403511c4741226b39843955c08c diff --git a/src/libadacl.c b/src/libadacl.c index 5bca89f..aa473c4 100644 --- a/src/libadacl.c +++ b/src/libadacl.c @@ -259,6 +259,17 @@ int acl_update_entry(acl_t aclp, acl_entry_t entry) { return ACL_ERROR; } + /* This can allocate memory, so from here on out we have to jump to + the "cleanup" label to exit. */ + void* entry_qualifier = acl_get_qualifier(entry); + if (entry_qualifier == NULL && + (entry_tag == ACL_USER || entry_tag == ACL_GROUP)) { + /* acl_get_qualifier() can return NULL, but it shouldn't for + ACL_USER or ACL_GROUP entries. */ + perror("acl_update_entry (acl_get_qualifier)"); + return ACL_ERROR; + } + /* Our return value. Default to failure, and change to success if we actually update something. */ int result = ACL_FAILURE; @@ -277,15 +288,53 @@ int acl_update_entry(acl_t aclp, acl_entry_t entry) { } if (existing_tag == entry_tag) { - /* If we update something, we're done and return ACL_SUCCESS */ - if (acl_set_permset(existing_entry, entry_permset) == ACL_ERROR) { - perror("acl_update_entry (acl_set_permset)"); - result = ACL_ERROR; - goto cleanup; + /* Our tag types match, but if we have a named user or group + entry, then we need to check that the user/group (that is, + the qualifier) matches too. */ + bool qualifiers_match = false; + + /* There are three ways the qualifiers can match... */ + void* existing_qualifier = acl_get_qualifier(existing_entry); + if (existing_qualifier == NULL) { + if (existing_tag == ACL_USER || existing_tag == ACL_GROUP) { + perror("acl_update_entry (acl_get_qualifier)"); + result = ACL_ERROR; + goto cleanup; + } + else { + /* First, we could be dealing with an entry that isn't a + named user or group, in which case they "match + vacuously." */ + qualifiers_match = true; + } } - result = ACL_SUCCESS; - goto cleanup; + /* Otherwise, we have to have matching UIDs or GIDs. */ + if (entry_tag == ACL_USER) { + qualifiers_match = ( *((uid_t*)existing_qualifier) + == + *((uid_t*)entry_qualifier) ); + } + else if (entry_tag == ACL_GROUP) { + qualifiers_match = ( *((gid_t*)existing_qualifier) + == + *((gid_t*)entry_qualifier) ); + } + + /* Be sure to free this inside the loop, where memory is allocated. */ + acl_free(existing_qualifier); + + if (qualifiers_match) { + /* If we update something, we're done and return ACL_SUCCESS */ + if (acl_set_permset(existing_entry, entry_permset) == ACL_ERROR) { + perror("acl_update_entry (acl_set_permset)"); + result = ACL_ERROR; + goto cleanup; + } + + result = ACL_SUCCESS; + goto cleanup; + } } get_entry_result = acl_get_entry(aclp, ACL_NEXT_ENTRY, &existing_entry); @@ -299,6 +348,7 @@ int acl_update_entry(acl_t aclp, acl_entry_t entry) { } cleanup: + acl_free(entry_qualifier); return result; }