o Separate acl_t into internal and external representations as

required by POSIX.1e.  This maintains the current 'struct acl'
  in the kernel while providing the generic external acl_t
  interface required to complete the ACL editing library.
o Add the acl_get_entry() function.
o Convert the existing ACL utilities, getfacl and setfacl, to
  fully make use of the ACL editing library.

Obtained from:	TrustedBSD Project
This commit is contained in:
Chris D. Faulhaber 2001-04-24 22:45:41 +00:00
parent 15fca934f6
commit 0f6263079e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75928
22 changed files with 551 additions and 233 deletions

View File

@ -40,10 +40,14 @@
/* set the appropriate mask the given ACL's */
int
set_acl_mask(acl_t prev_acl)
set_acl_mask(acl_t *prev_acl)
{
acl_entry_t entry;
acl_t acl;
int i;
acl_tag_t tag;
int entry_id;
entry = NULL;
/*
* ... if a mask entry is specified, then the permissions of the mask
@ -53,7 +57,7 @@ set_acl_mask(acl_t prev_acl)
if (have_mask)
return 0;
acl = acl_dup(prev_acl);
acl = acl_dup(*prev_acl);
if (!acl)
err(EX_OSERR, "acl_dup() failed");
@ -76,11 +80,19 @@ set_acl_mask(acl_t prev_acl)
* specified, then the permissions of the resulting ACL
* mask entry shall remain unchanged ...
*/
for (i = 0; i < acl->acl_cnt; i++)
if (acl->acl_entry[i].ae_tag == ACL_MASK) {
entry_id = ACL_FIRST_ENTRY;
while (acl_get_entry(acl, entry_id, &entry) == 1) {
entry_id = ACL_NEXT_ENTRY;
if (acl_get_tag_type(entry, &tag) == -1)
err(1, "acl_get_tag_type() failed");
if (tag == ACL_MASK) {
acl_free(acl);
return 0;
}
}
/*
* If no mask entry is specified, the -n option is specified,
@ -93,7 +105,7 @@ set_acl_mask(acl_t prev_acl)
return 0;
}
*prev_acl = *acl;
prev_acl = &acl;
acl_free(acl);
return 0;

View File

@ -40,11 +40,12 @@
int
merge_acl(acl_t acl, acl_t *prev_acl)
{
acl_entry_t entry, entry_new;
acl_permset_t permset;
acl_t acl_new;
int blank_acl_user, blank_acl_group, have_entry, i, j;
struct stat sb;
blank_acl_user = blank_acl_group = 0;
acl_tag_t tag, tag_new;
int entry_id, entry_id_new, have_entry;
uid_t *id, *id_new;
if (acl_type == ACL_TYPE_ACCESS)
acl_new = acl_dup(prev_acl[0]);
@ -53,61 +54,99 @@ merge_acl(acl_t acl, acl_t *prev_acl)
if (!acl_new)
err(EX_OSERR, "acl_dup() failed");
/* step through new ACL entries */
for (i = 0; i < acl->acl_cnt; i++) {
entry_id = ACL_FIRST_ENTRY;
while (acl_get_entry(acl, entry_id, &entry) == 1) {
entry_id = ACL_NEXT_ENTRY;
have_entry = 0;
/* oh look, we have an ACL_MASK entry */
if (acl->acl_entry[i].ae_tag == ACL_MASK)
/* keep track of existing ACL_MASK entries */
if (acl_get_tag_type(entry, &tag) == -1)
err(EX_OSERR,
"acl_get_tag_type() failed - invalid ACL entry");
if (tag == ACL_MASK)
have_mask = 1;
/* check against the existing ACL entries */
for (j = 0; j < acl_new->acl_cnt && !have_entry; j++) {
if (acl_new->acl_entry[j].ae_tag ==
acl->acl_entry[i].ae_tag) {
switch(acl->acl_entry[i].ae_tag) {
case ACL_USER_OBJ:
acl_new->acl_entry[j].ae_perm =
acl->acl_entry[i].ae_perm;
acl_new->acl_entry[j].ae_id = sb.st_uid;
entry_id_new = ACL_FIRST_ENTRY;
while (!have_entry &&
acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) {
entry_id_new = ACL_NEXT_ENTRY;
if (acl_get_tag_type(entry, &tag) == -1)
err(EX_OSERR, "acl_get_tag_type() failed");
if (acl_get_tag_type(entry_new, &tag_new) == -1)
err(EX_OSERR, "acl_get_tag_type() failed");
if (tag != tag_new)
continue;
switch(tag) {
case ACL_USER:
case ACL_GROUP:
id = acl_get_qualifier(entry);
if (id == NULL)
err(EX_OSERR,
"acl_get_qualifier() failed");
id_new = acl_get_qualifier(entry_new);
if (id_new == NULL)
err(EX_OSERR,
"acl_get_qualifier() failed");
if (*id == *id_new) {
/* any other matches */
if (acl_get_permset(entry, &permset)
== -1)
err(EX_OSERR,
"acl_get_permset() failed");
if (acl_set_permset(entry_new, permset)
== -1)
err(EX_OSERR,
"acl_set_permset() failed");
have_entry = 1;
break;
case ACL_GROUP_OBJ:
acl_new->acl_entry[j].ae_perm =
acl->acl_entry[i].ae_perm;
acl_new->acl_entry[j].ae_id = sb.st_gid;
have_entry = 1;
break;
default:
if (acl_new->acl_entry[j].ae_id ==
acl->acl_entry[i].ae_id) {
/* any other matches */
acl_new->acl_entry[j].ae_perm =
acl->acl_entry[i].ae_perm;
have_entry = 1;
}
break;
}
acl_free(id);
acl_free(id_new);
if (!have_entry)
break;
/* FALLTHROUGH */
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_OTHER:
case ACL_MASK:
if (acl_get_permset(entry, &permset) == -1)
err(EX_OSERR,
"acl_get_permset() failed");
if (acl_set_permset(entry_new, permset) == -1)
err(EX_OSERR,
"acl_set_permset() failed");
have_entry = 1;
break;
default:
/* should never be here */
errx(EX_OSERR, "Invalid tag type: %i", tag);
break;
}
}
/* if this entry has not been found, it must be new */
if (!have_entry) {
if (acl_new->acl_cnt == ACL_MAX_ENTRIES) {
warn("too many ACL entries");
if (acl_create_entry(&acl_new, &entry_new) == -1) {
acl_free(acl_new);
return -1;
}
acl_new->acl_entry[acl_new->acl_cnt++] =
acl->acl_entry[i];
if (acl_copy_entry(entry_new, entry) == -1)
err(EX_OSERR, "acl_copy_entry() failed");
}
}
if (acl_type == ACL_TYPE_ACCESS)
*prev_acl[0] = *acl_new;
else
*prev_acl[1] = *acl_new;
acl_free(acl_new);
if (acl_type == ACL_TYPE_ACCESS) {
acl_free(prev_acl[0]);
prev_acl[0] = acl_new;
} else {
acl_free(prev_acl[1]);
prev_acl[1] = acl_new;
}
return 0;
}

View File

@ -41,8 +41,10 @@
int
remove_acl(acl_t acl, acl_t *prev_acl)
{
acl_t acl_new;
int carried_error, i;
acl_entry_t entry;
acl_t acl_new;
acl_tag_t tag;
int carried_error, entry_id;
carried_error = 0;
@ -53,11 +55,17 @@ remove_acl(acl_t acl, acl_t *prev_acl)
if (!acl_new)
err(EX_OSERR, "acl_dup() failed");
tag = ACL_UNDEFINED_TAG;
/* find and delete the entry */
for (i = 0; i < acl->acl_cnt; i++) {
if (acl->acl_entry[i].ae_tag == ACL_MASK)
entry_id = ACL_FIRST_ENTRY;
while (acl_get_entry(acl, entry_id, &entry) == 1) {
entry_id = ACL_NEXT_ENTRY;
if (acl_get_tag_type(entry, &tag) == -1)
err(1, "acl_get_tag_type() failed");
if (tag == ACL_MASK)
have_mask++;
if (acl_delete_entry(acl_new, &acl->acl_entry[i]) == -1) {
if (acl_delete_entry(acl_new, entry) == -1) {
carried_error++;
warnx("cannot remove non-existent acl entry");
}
@ -83,8 +91,10 @@ remove_default(acl_t *prev_acl)
{
if (prev_acl[1]) {
bzero(prev_acl[1], sizeof(struct acl));
prev_acl[1]->acl_cnt = 0;
acl_free(prev_acl[1]);
prev_acl[1] = acl_init(ACL_MAX_ENTRIES);
if (!prev_acl[1])
err(1, "acl_init() failed");
} else {
warn("cannot remove default ACL");
return -1;
@ -97,8 +107,10 @@ void
remove_ext(acl_t *prev_acl)
{
acl_t acl_new, acl_old;
acl_perm_t group_perm, mask_perm;
int have_mask_entry, i;
acl_entry_t entry, entry_new;
acl_permset_t perm;
acl_tag_t tag;
int entry_id, have_mask_entry;
if (acl_type == ACL_TYPE_ACCESS)
acl_old = acl_dup(prev_acl[0]);
@ -107,41 +119,50 @@ remove_ext(acl_t *prev_acl)
if (!acl_old)
err(EX_OSERR, "acl_dup() failed");
group_perm = mask_perm = 0;
have_mask_entry = 0;
acl_new = acl_init(ACL_MAX_ENTRIES);
if (!acl_new)
err(EX_OSERR, "%s", "acl_init() failed");
tag = ACL_UNDEFINED_TAG;
/* only save the default user/group/other entries */
for (i = 0; i < acl_old->acl_cnt; i++)
switch(acl_old->acl_entry[i].ae_tag) {
entry_id = ACL_FIRST_ENTRY;
while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
entry_id = ACL_NEXT_ENTRY;
if (acl_get_tag_type(entry, &tag) == -1)
err(1, "acl_get_tag_type() failed");
switch(tag) {
case ACL_USER_OBJ:
acl_new->acl_entry[0] = acl_old->acl_entry[i];
break;
case ACL_GROUP_OBJ:
acl_new->acl_entry[1] = acl_old->acl_entry[i];
group_perm = acl_old->acl_entry[i].ae_perm;
break;
case ACL_OTHER_OBJ:
acl_new->acl_entry[2] = acl_old->acl_entry[i];
case ACL_OTHER:
if (acl_get_tag_type(entry, &tag) == -1)
err(1, "acl_get_tag_type() failed");
if (acl_get_permset(entry, &perm) == -1)
err(1, "acl_get_permset() failed");
if (acl_create_entry(&acl_new, &entry_new) == -1)
err(1, "acl_create_entry() failed");
if (acl_set_tag_type(entry_new, tag) == -1)
err(1, "acl_set_tag_type() failed");
if (acl_set_permset(entry_new, perm) == -1)
err(1, "acl_get_permset() failed");
if (acl_copy_entry(entry_new, entry) == -1)
err(1, "acl_copy_entry() failed");
break;
case ACL_MASK:
mask_perm = acl_old->acl_entry[i].ae_perm;
have_mask_entry = 1;
break;
default:
break;
}
/*
* If the ACL contains a mask entry, then the permissions associated
* with the owning group entry in the resulting ACL shall be set to
* only those permissions associated with both the owning group entry
* and the mask entry of the current ACL.
*/
if (have_mask_entry)
acl_new->acl_entry[1].ae_perm = group_perm & mask_perm;
acl_new->acl_cnt = 3;
}
if (have_mask_entry && !n_flag) {
if (acl_calc_mask(&acl_new) == -1)
err(1, "acl_calc_mask() failed");
} else {
have_mask = 1;
}
if (acl_type == ACL_TYPE_ACCESS) {
acl_free(prev_acl[0]);
@ -150,6 +171,4 @@ remove_ext(acl_t *prev_acl)
acl_free(prev_acl[1]);
prev_acl[1] = acl_new;
}
have_mask = 0;
}

View File

@ -56,7 +56,7 @@ add_filename(const char *filename)
}
file = zmalloc(sizeof(struct sf_file));
file->filename = filename;
STAILQ_INSERT_TAIL(&filelist, file, next);
TAILQ_INSERT_TAIL(&filelist, file, next);
}
static acl_t *
@ -106,8 +106,8 @@ main(int argc, char *argv[])
carried_error = local_error = 0;
have_mask = have_stdin = n_flag = need_mask = 0;
STAILQ_INIT(&entrylist);
STAILQ_INIT(&filelist);
TAILQ_INIT(&entrylist);
TAILQ_INIT(&filelist);
while ((ch = getopt(argc, argv, "M:X:bdkm:nx:")) != -1)
switch(ch) {
@ -117,18 +117,18 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_OSERR, "get_acl_from_file() failed");
entry->op = OP_MERGE_ACL;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'X':
entry = zmalloc(sizeof(struct sf_entry));
entry->acl = get_acl_from_file(optarg);
entry->op = OP_REMOVE_ACL;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'b':
entry = zmalloc(sizeof(struct sf_entry));
entry->op = OP_REMOVE_EXT;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'd':
acl_type = ACL_TYPE_DEFAULT;
@ -136,7 +136,7 @@ main(int argc, char *argv[])
case 'k':
entry = zmalloc(sizeof(struct sf_entry));
entry->op = OP_REMOVE_DEF;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'm':
entry = zmalloc(sizeof(struct sf_entry));
@ -144,7 +144,7 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_USAGE, "acl_from_text() failed");
entry->op = OP_MERGE_ACL;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
case 'n':
n_flag++;
@ -155,7 +155,7 @@ main(int argc, char *argv[])
if (!entry->acl)
err(EX_USAGE, "acl_from_text() failed");
entry->op = OP_REMOVE_ACL;
STAILQ_INSERT_TAIL(&entrylist, entry, next);
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
default:
usage();
@ -164,7 +164,7 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
if (STAILQ_EMPTY(&entrylist))
if (!n_flag && TAILQ_EMPTY(&entrylist))
usage();
/* take list of files from stdin */
@ -183,7 +183,7 @@ main(int argc, char *argv[])
add_filename(argv[i]);
/* cycle through each file */
STAILQ_FOREACH(file, &filelist, next) {
TAILQ_FOREACH(file, &filelist, next) {
/* get our initial access and default ACL's */
acl = get_file_acls(file->filename);
if (!acl)
@ -196,7 +196,7 @@ main(int argc, char *argv[])
local_error = 0;
/* cycle through each option */
STAILQ_FOREACH(entry, &entrylist, next) {
TAILQ_FOREACH(entry, &entrylist, next) {
if (local_error)
continue;
@ -236,7 +236,7 @@ main(int argc, char *argv[])
else
final_acl = acl[1];
if (need_mask && (set_acl_mask(final_acl) == -1)) {
if (need_mask && (set_acl_mask(&final_acl) == -1)) {
warnx("failed to set ACL mask on %s", file->filename);
carried_error++;
} else if (acl_set_file(file->filename, acl_type,

View File

@ -39,20 +39,20 @@
#define OP_REMOVE_EXT 0x02 /* remove extended acl's (-b) */
#define OP_REMOVE_ACL 0x03 /* remove acl's (-xX) */
/* STAILQ entry for acl operations */
/* TAILQ entry for acl operations */
struct sf_entry {
uint op;
acl_t acl;
STAILQ_ENTRY(sf_entry) next;
TAILQ_ENTRY(sf_entry) next;
};
STAILQ_HEAD(, sf_entry) entrylist;
TAILQ_HEAD(, sf_entry) entrylist;
/* STAILQ entry for files */
/* TAILQ entry for files */
struct sf_file {
const char *filename;
STAILQ_ENTRY(sf_file) next;
TAILQ_ENTRY(sf_file) next;
};
STAILQ_HEAD(, sf_file) filelist;
TAILQ_HEAD(, sf_file) filelist;
/* files.c */
acl_t get_acl_from_file(const char *filename);
@ -63,7 +63,7 @@ int remove_acl(acl_t acl, acl_t *prev_acl);
int remove_default(acl_t *prev_acl);
void remove_ext(acl_t *prev_acl);
/* mask.c */
int set_acl_mask(acl_t prev_acl);
int set_acl_mask(acl_t *prev_acl);
/* util.c */
void *zmalloc(size_t size);

View File

@ -47,6 +47,7 @@ MAN+= acl.3 \
acl_free.3 \
acl_from_text.3 \
acl_get.3 \
acl_get_entry.3 \
acl_get_permset.3 \
acl_get_perm_np.3 \
acl_get_qualifier.3 \

View File

@ -32,22 +32,34 @@
#include "un-namespace.h"
#include <errno.h>
#include <stdio.h>
/*
* acl_calc_mask() calculates and set the permissions associated
* with the ACL_MASK ACL entry. If the ACL already contains an
* ACL_MASK entry, its permissions shall be overwritten; if not,
* one shall be added.
* acl_calc_mask() (23.4.2): calculate and set the permissions
* associated with the ACL_MASK ACL entry. If the ACL already
* contains an ACL_MASK entry, its permissions shall be
* overwritten; if not, one shall be added.
*/
int
acl_calc_mask(acl_t *acl_p)
{
acl_t acl_new;
int group_obj, i, mask_mode, mask_num, other_obj, user_obj;
struct acl *acl_int, *acl_int_new;
acl_t acl_new;
int i, mask_mode, mask_num;
/* check args */
if (!acl_p || !*acl_p || ((*acl_p)->acl_cnt < 3) ||
((*acl_p)->acl_cnt > ACL_MAX_ENTRIES)) {
/*
* (23.4.2.4) requires acl_p to point to a pointer to a valid ACL.
* Since one of the primary reasons to use this function would be
* to calculate the appropriate mask to obtain a valid ACL, we only
* perform sanity checks here and validate the ACL prior to
* returning.
*/
if (!acl_p || !*acl_p) {
errno = EINVAL;
return -1;
}
acl_int = &(*acl_p)->ats_acl;
if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
errno = EINVAL;
return -1;
}
@ -55,57 +67,42 @@ acl_calc_mask(acl_t *acl_p)
acl_new = acl_dup(*acl_p);
if (!acl_new)
return -1;
acl_int_new = &acl_new->ats_acl;
user_obj = group_obj = other_obj = mask_mode = 0;
mask_mode = 0;
mask_num = -1;
/* gather permissions and find a mask entry */
for (i = 0; i < acl_new->acl_cnt; i++) {
switch(acl_new->acl_entry[i].ae_tag) {
case ACL_USER_OBJ:
user_obj++;
break;
case ACL_OTHER:
other_obj++;
break;
case ACL_GROUP_OBJ:
group_obj++;
/* FALLTHROUGH */
case ACL_GROUP:
for (i = 0; i < acl_int_new->acl_cnt; i++) {
switch(acl_int_new->acl_entry[i].ae_tag) {
case ACL_USER:
case ACL_GROUP:
case ACL_GROUP_OBJ:
mask_mode |=
acl_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
break;
case ACL_MASK:
mask_num = i;
break;
default:
errno = EINVAL;
acl_free(acl_new);
return -1;
/* NOTREACHED */
}
}
if ((user_obj != 1) || (group_obj != 1) || (other_obj != 1)) {
errno = EINVAL;
acl_free(acl_new);
return -1;
}
/* if a mask entry already exists, overwrite the perms */
if (mask_num != -1) {
acl_new->acl_entry[mask_num].ae_perm = mask_mode;
} else {
if (mask_num != -1)
acl_int_new->acl_entry[mask_num].ae_perm = mask_mode;
else {
/* if no mask exists, check acl_cnt... */
if (acl_new->acl_cnt == ACL_MAX_ENTRIES) {
errno = EINVAL;
acl_free(acl_new);
if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) {
errno = ENOMEM;
return -1;
}
/* ...and add the mask entry */
acl_new->acl_entry[acl_new->acl_cnt].ae_tag = ACL_MASK;
acl_new->acl_entry[acl_new->acl_cnt].ae_id = 0;
acl_new->acl_entry[acl_new->acl_cnt].ae_perm = mask_mode;
acl_new->acl_cnt++;
acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK;
acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id =
ACL_UNDEFINED_ID;
acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm =
mask_mode;
acl_int_new->acl_cnt++;
}
if (acl_valid(acl_new) == -1) {

View File

@ -35,7 +35,7 @@
#include <string.h>
/*
* acl_copy_entry() - copy the contents of ACL entry src_d to
* acl_copy_entry() (23.4.4): copy the contents of ACL entry src_d to
* ACL entry dest_d
*/
int

View File

@ -26,8 +26,6 @@
* $FreeBSD$
*/
/* acl_delete_entry() - delete an ACL entry from an ACL */
#include <sys/types.h>
#include "namespace.h"
#include <sys/acl.h>
@ -35,26 +33,41 @@
#include <errno.h>
#include <string.h>
/*
* acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
* from acl.
*/
int
acl_delete_entry(acl_t acl, acl_entry_t entry_d)
{
struct acl *acl_int;
int i;
if (!acl || !entry_d || (acl->acl_cnt < 1) ||
(acl->acl_cnt > ACL_MAX_ENTRIES)) {
if (!acl || !entry_d) {
errno = EINVAL;
return -1;
}
for (i = 0; i < acl->acl_cnt; i++) {
acl_int = &acl->ats_acl;
if ((acl->ats_acl.acl_cnt < 1) ||
(acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
errno = EINVAL;
return -1;
}
for (i = 0; i < acl->ats_acl.acl_cnt; i++) {
/* if this is our entry... */
if ((acl->acl_entry[i].ae_tag == entry_d->ae_tag) &&
(acl->acl_entry[i].ae_id == entry_d->ae_id)) {
if ((acl->ats_acl.acl_entry[i].ae_tag == entry_d->ae_tag) &&
(acl->ats_acl.acl_entry[i].ae_id == entry_d->ae_id)) {
/* ...shift the remaining entries... */
while (i < acl->acl_cnt - 1)
acl->acl_entry[i] = acl->acl_entry[++i];
while (i < acl->ats_acl.acl_cnt - 1)
acl->ats_acl.acl_entry[i] =
acl->ats_acl.acl_entry[++i];
/* ...drop the count and zero the unused entry... */
acl->acl_cnt--;
bzero(&acl->acl_entry[i], sizeof(struct acl_entry));
acl->ats_acl.acl_cnt--;
bzero(&acl->ats_acl.acl_entry[i],
sizeof(struct acl_entry));
acl->ats_cur_entry = 0;
return 0;
}
}

View File

@ -34,32 +34,64 @@
#include <errno.h>
#include <stdlib.h>
/*
* acl_create_entry() (23.4.7): create a new ACL entry in the ACL pointed
* to by acl_p.
*/
int
acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
{
acl_t acl;
struct acl *acl_int;
if (!acl_p || !*acl_p || ((*acl_p)->acl_cnt >= ACL_MAX_ENTRIES) ||
((*acl_p)->acl_cnt < 0)) {
if (!acl_p) {
errno = EINVAL;
return -1;
}
acl = *acl_p;
acl_int = &(*acl_p)->ats_acl;
*entry_p = &acl->acl_entry[acl->acl_cnt++];
if ((acl_int->acl_cnt >= ACL_MAX_ENTRIES) || (acl_int->acl_cnt < 0)) {
errno = EINVAL;
return -1;
}
*entry_p = &acl_int->acl_entry[acl_int->acl_cnt++];
(**entry_p).ae_tag = ACL_UNDEFINED_TAG;
(**entry_p).ae_id = ACL_UNDEFINED_ID;
(**entry_p).ae_perm = ACL_PERM_NONE;
(*acl_p)->ats_cur_entry = 0;
return 0;
}
/*
* acl_get_entry() (23.4.14): returns an ACL entry from an ACL
* indicated by entry_id.
*/
int
acl_get_entry(acl_t acl, int entry_id, acl_entry_t *entry_p)
{
struct acl *acl_int;
errno = ENOSYS;
if (!acl) {
errno = EINVAL;
return -1;
}
acl_int = &acl->ats_acl;
switch(entry_id) {
case ACL_FIRST_ENTRY:
acl->ats_cur_entry = 0;
/* PASSTHROUGH */
case ACL_NEXT_ENTRY:
if (acl->ats_cur_entry >= acl->ats_acl.acl_cnt)
return 0;
*entry_p = &acl_int->acl_entry[acl->ats_cur_entry++];
return 1;
}
errno = EINVAL;
return -1;
}

View File

@ -36,10 +36,18 @@
#include <sys/errno.h>
#include <stdlib.h>
/*
* acl_free() (23.4.12): free any releasable memory allocated to the
* ACL data object identified by obj_p.
*/
int
acl_free(void *obj_p)
{
free(obj_p);
if (obj_p) {
free(obj_p);
obj_p = NULL;
}
return (0);
}

View File

@ -109,13 +109,13 @@ acl_string_to_tag(char *tag, char *qualifier)
acl_t
acl_from_text(const char *buf_p)
{
acl_tag_t t;
acl_perm_t p;
acl_t acl;
uid_t id;
char *mybuf_p, *line, *cur, *notcomment, *comment, *entry;
char *tag, *qualifier, *permission;
int error;
acl_tag_t t;
acl_perm_t p;
acl_t acl;
char *mybuf_p, *line, *cur, *notcomment, *comment, *entry;
char *tag, *qualifier, *permission;
int error;
uid_t id;
/* Local copy we can mess up. */
mybuf_p = strdup(buf_p);

View File

@ -48,7 +48,7 @@
acl_t
acl_get_file(const char *path_p, acl_type_t type)
{
struct acl *aclp;
acl_t aclp;
int error;
aclp = acl_init(ACL_MAX_ENTRIES);
@ -56,7 +56,7 @@ acl_get_file(const char *path_p, acl_type_t type)
return (NULL);
}
error = __acl_get_file(path_p, type, aclp);
error = __acl_get_file(path_p, type, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
@ -68,7 +68,7 @@ acl_get_file(const char *path_p, acl_type_t type)
acl_t
acl_get_fd(int fd)
{
struct acl *aclp;
acl_t aclp;
int error;
aclp = acl_init(ACL_MAX_ENTRIES);
@ -76,7 +76,7 @@ acl_get_fd(int fd)
return (NULL);
}
error = ___acl_get_fd(fd, ACL_TYPE_ACCESS, aclp);
error = ___acl_get_fd(fd, ACL_TYPE_ACCESS, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
@ -88,7 +88,7 @@ acl_get_fd(int fd)
acl_t
acl_get_fd_np(int fd, acl_type_t type)
{
struct acl *aclp;
acl_t aclp;
int error;
aclp = acl_init(ACL_MAX_ENTRIES);
@ -96,7 +96,7 @@ acl_get_fd_np(int fd, acl_type_t type)
return (NULL);
}
error = ___acl_get_fd(fd, type, aclp);
error = ___acl_get_fd(fd, type, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
@ -109,6 +109,11 @@ int
acl_get_perm_np(acl_permset_t permset_d, acl_perm_t perm)
{
if (!permset_d) {
errno = EINVAL;
return -1;
}
switch(perm) {
case ACL_READ:
case ACL_WRITE:
@ -124,6 +129,10 @@ acl_get_perm_np(acl_permset_t permset_d, acl_perm_t perm)
return 0;
}
/*
* acl_get_permset() (23.4.17): return via permset_p a descriptor to
* the permission set in the ACL entry entry_d.
*/
int
acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p)
{
@ -138,6 +147,10 @@ acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p)
return 0;
}
/*
* acl_get_qualifier() (23.4.18): retrieve the qualifier of the tag
* for the ACL entry entry_d.
*/
void *
acl_get_qualifier(acl_entry_t entry_d)
{
@ -152,16 +165,20 @@ acl_get_qualifier(acl_entry_t entry_d)
case ACL_USER:
case ACL_GROUP:
retval = malloc(sizeof(uid_t));
if (retval) {
*retval = entry_d->ae_id;
return retval;
}
if (!retval)
return NULL;
*retval = entry_d->ae_id;
return retval;
}
errno = EINVAL;
return NULL;
}
/*
* acl_get_tag_type() (23.4.19): return the tag type for the ACL
* entry entry_p.
*/
int
acl_get_tag_type(acl_entry_t entry_d, acl_tag_t *tag_type_p)
{

View File

@ -0,0 +1,139 @@
.\"-
.\" Copyright (c) 2001 Chris D. Faulhaber
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE
.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd April 13, 2001
.Dt ACL_GET_ENTRY 3
.Os
.Sh NAME
.Nm acl_get_entry
.Nd retrieve an ACL entry from an ACL
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.Fd #include <sys/types.h>
.Fd #include <sys/acl.h>
.Ft void *
.Fn acl_get_entry "acl_t acl" "int entry_id" "acl_entry_t entry_p"
.Sh DESCRIPTION
.Fn acl_get_entry
is a POSIX.1e call that retrieves a descriptor for an ACL entry
specified by the argument
.Fa entry_d
within the ACL indicated by the argument
.Fa acl .
.Pp
If the value of
.Fa entry_id
is
.Dv ACL_FIRST_ENTRY ,
then the function will return in
.Fa entry_p
a descriptor for the first ACL entry within
.Fa acl .
If a call is made to
.Fn acl_get_entry
with
.Fa entry_id
set to
.Dv ACL_NEXT_ENTRY
when there has not been either an initial successful call to
.Fn acl_get_entry ,
or a previous successfull call to
.Fn acl_create_entry ,
.Fn acl_delete_entry ,
.Fn acl_dup ,
.Fn acl_from_text ,
.Fn acl_get_fd ,
.Fn acl_get_file ,
.Fn acl_set_fd ,
.Fn acl_set_file,
or
.Fn acl_valid ,
then the result is unspecified.
.Pp
.Sh RETURN VALUES
If the
.Fn acl_get_entry
function successfully obtains an ACL entry, a value of 1 is returned.
If the ACL has no ACL entries, the
.Fn function
returns a value of 0. If the value of
.Fa entry_id
is
.Dv ACL_NEXT_ENTRY
and the last ACL entry in the ACL has already been returned by a
previous call to
.Fn acl_get_entry ,
a value of 0 will be returned until a successful call with
.Fa entry_id
of
.Dv ACL_FIRST_ENTRY
is made. Otherwise, a value of -1 will be returned and
.Va errno
will be set to indicate the error.
.Sh ERRORS
The
.Fn acl_get_entry
fails if:
.Bl -tag -width Er
.It Bq Er EINVAL
Argument
.Fa acl
does not point to a valid ACL. Argument
.Fa entry_id
is neither
.Dv ACL_FIRST_ENTRY
nor
.Dv ACL_NEXT_ENTRY .
.Sh SEE ALSO
.Xr acl 3 ,
.Xr acl_calc_mask 3 ,
.Xr acl_create_entry 3 ,
.Xr acl_delete_entry 3 ,
.Xr acl_dup 3 ,
.Xr acl_from_text 3 ,
.Xr acl_get_fd 3 ,
.Xr acl_get_file 3 ,
.Xr acl_init 3 ,
.Xr acl_set_fd 3 ,
.Xr acl_set_file 3 ,
.Xr acl_valid 3 ,
.Xr posix1e 3
.Sh STANDARDS
POSIX.1e is described in IEEE POSIX.1e draft 17.
.Sh HISTORY
POSIX.1e support was introduced in
.Fx 4.0 .
The
.Fn acl_get_entry
function was added in
.Fx 5.0 .
.Sh AUTHORS
The
.Fn acl_get_entry
function was written by
.An Chris D. Faulhaber Aq jedgar@fxp.org .

View File

@ -41,16 +41,20 @@
acl_t
acl_init(int count)
{
struct acl *acl;
acl_t acl;
if (count > ACL_MAX_ENTRIES) {
errno = ENOMEM;
return (NULL);
}
if (count < 0) {
errno = EINVAL;
return (NULL);
}
acl = (struct acl *) malloc(sizeof(struct acl));
acl = malloc(sizeof(struct acl_t_struct));
if (acl != NULL)
bzero(acl, sizeof(struct acl));
bzero(acl, sizeof(struct acl_t_struct));
return (acl);
}
@ -58,13 +62,14 @@ acl_init(int count)
acl_t
acl_dup(acl_t acl)
{
struct acl *acl_new;
acl_t acl_new;
acl_new = acl_init(ACL_MAX_ENTRIES);
if (!acl_new)
return(NULL);
return NULL;
*acl_new = *acl;
acl->ats_cur_entry = 0;
acl_new->ats_cur_entry = 0;
return(acl_new);
}

View File

@ -35,25 +35,29 @@
#include <string.h>
/*
* acl_add_perm() adds the permission contained in perm to the
* acl_add_perm() (23.4.1): add the permission contained in perm to the
* permission set permset_d
*/
int
acl_add_perm(acl_permset_t permset_d, acl_perm_t perm)
{
if (!permset_d || (perm & !(ACL_PERM_BITS))) {
errno = EINVAL;
return -1;
if (permset_d) {
switch(perm) {
case ACL_READ:
case ACL_WRITE:
case ACL_EXECUTE:
*permset_d |= perm;
return 0;
}
}
*permset_d |= perm;
return 0;
errno = EINVAL;
return -1;
}
/*
* acl_clear_perms() clears all permisions from the permission
* acl_clear_perms() (23.4.3): clear all permisions from the permission
* set permset_d
*/
int
@ -65,25 +69,29 @@ acl_clear_perms(acl_permset_t permset_d)
return -1;
}
*permset_d = 0;
*permset_d = ACL_PERM_NONE;
return 0;
}
/*
* acl_delete_perm() removes the permission in perm from the
* acl_delete_perm() (23.4.10): remove the permission in perm from the
* permission set permset_d
*/
int
acl_delete_perm(acl_permset_t permset_d, acl_perm_t perm)
{
if (!permset_d) {
errno = EINVAL;
return -1;
if (permset_d) {
switch(perm) {
case ACL_READ:
case ACL_WRITE:
case ACL_EXECUTE:
*permset_d &= ~(perm & ACL_PERM_BITS);
return 0;
}
}
*permset_d &= ~(perm & ACL_PERM_BITS);
return 0;
errno = EINVAL;
return -1;
}

View File

@ -59,7 +59,9 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
}
}
return (__acl_set_file(path_p, type, acl));
acl->ats_cur_entry = 0;
return (__acl_set_file(path_p, type, &acl->ats_acl));
}
int
@ -73,7 +75,9 @@ acl_set_fd(int fd, acl_t acl)
return(-1);
}
return (___acl_set_fd(fd, ACL_TYPE_ACCESS, acl));
acl->ats_cur_entry = 0;
return (___acl_set_fd(fd, ACL_TYPE_ACCESS, &acl->ats_acl));
}
int
@ -89,11 +93,13 @@ acl_set_fd_np(int fd, acl_t acl, acl_type_t type)
}
}
return (___acl_set_fd(fd, type, acl));
acl->ats_cur_entry = 0;
return (___acl_set_fd(fd, type, &acl->ats_acl));
}
/*
* acl_set_permset() sets the permissions of ACL entry entry_d
* acl_set_permset() (23.4.23): sets the permissions of ACL entry entry_d
* with the permissions in permset_d
*/
int

View File

@ -96,9 +96,12 @@ _posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
int
_posix1e_acl_sort(acl_t acl)
{
struct acl *acl_int;
qsort(&acl->acl_entry[0], acl->acl_cnt, sizeof(struct acl_entry),
(compare) _posix1e_acl_entry_compare);
acl_int = &acl->ats_acl;
qsort(&acl_int->acl_entry[0], acl_int->acl_cnt,
sizeof(struct acl_entry), (compare) _posix1e_acl_entry_compare);
return (0);
}
@ -130,8 +133,9 @@ _posix1e_acl(acl_t acl, acl_type_t type)
* this. Returns 0 on success, EINVAL on failure.
*/
int
_posix1e_acl_check(struct acl *acl)
_posix1e_acl_check(acl_t acl)
{
struct acl *acl_int;
struct acl_entry *entry; /* current entry */
uid_t obj_uid=-1, obj_gid=-1, highest_uid=0, highest_gid=0;
int stage = ACL_USER_OBJ;
@ -139,10 +143,12 @@ _posix1e_acl_check(struct acl *acl)
int count_user_obj=0, count_user=0, count_group_obj=0,
count_group=0, count_mask=0, count_other=0;
acl_int = &acl->ats_acl;
/* printf("_posix1e_acl_check: checking acl with %d entries\n",
acl->acl_cnt); */
while (i < acl->acl_cnt) {
entry = &acl->acl_entry[i];
while (i < acl_int->acl_cnt) {
entry = &acl_int->acl_entry[i];
if ((entry->ae_perm | ACL_PERM_BITS) != ACL_PERM_BITS)
return (EINVAL);
@ -408,18 +414,21 @@ _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm)
int
_posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
{
struct acl *acl_int;
struct acl_entry *e;
if (acl->acl_cnt >= ACL_MAX_ENTRIES) {
acl_int = &acl->ats_acl;
if (acl_int->acl_cnt >= ACL_MAX_ENTRIES) {
errno = ENOMEM;
return (-1);
}
e = &(acl->acl_entry[acl->acl_cnt]);
e = &(acl_int->acl_entry[acl_int->acl_cnt]);
e->ae_perm = perm;
e->ae_tag = tag;
e->ae_id = id;
acl->acl_cnt++;
acl_int->acl_cnt++;
return (0);
}

View File

@ -34,7 +34,7 @@
#define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */
int _posix1e_acl_check(struct acl *acl);
int _posix1e_acl_check(acl_t acl);
int _posix1e_acl_sort(acl_t acl);
int _posix1e_acl(acl_t acl, acl_type_t type);
int _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len,

View File

@ -52,28 +52,31 @@
char *
acl_to_text(acl_t acl, ssize_t *len_p)
{
char *buf, *tmpbuf;
char name_buf[UT_NAMESIZE+1];
char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
int i, error, len;
uid_t ae_id;
acl_tag_t ae_tag;
acl_perm_t ae_perm, effective_perm, mask_perm;
struct acl *acl_int;
char *buf, *tmpbuf;
char name_buf[UT_NAMESIZE+1];
char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
int i, error, len;
uid_t ae_id;
acl_tag_t ae_tag;
acl_perm_t ae_perm, effective_perm, mask_perm;
buf = strdup("");
if (!buf)
return(NULL);
mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */
for (i = 0; i < acl->acl_cnt; i++)
if (acl->acl_entry[i].ae_tag == ACL_MASK)
mask_perm = acl->acl_entry[i].ae_perm;
acl_int = &acl->ats_acl;
for (i = 0; i < acl->acl_cnt; i++) {
ae_tag = acl->acl_entry[i].ae_tag;
ae_id = acl->acl_entry[i].ae_id;
ae_perm = acl->acl_entry[i].ae_perm;
mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */
for (i = 0; i < acl_int->acl_cnt; i++)
if (acl_int->acl_entry[i].ae_tag == ACL_MASK)
mask_perm = acl_int->acl_entry[i].ae_perm;
for (i = 0; i < acl_int->acl_cnt; i++) {
ae_tag = acl_int->acl_entry[i].ae_tag;
ae_id = acl_int->acl_entry[i].ae_id;
ae_perm = acl_int->acl_entry[i].ae_perm;
switch(ae_tag) {
case ACL_USER_OBJ:

View File

@ -78,7 +78,7 @@ acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
}
}
return (__acl_aclcheck_file(pathp, type, acl));
return (__acl_aclcheck_file(pathp, type, &acl->ats_acl));
}
@ -95,5 +95,8 @@ acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
}
}
return (___acl_aclcheck_fd(fd, type, acl));
acl->ats_cur_entry = 0;
return (___acl_aclcheck_fd(fd, type, &acl->ats_acl));
}

View File

@ -56,11 +56,18 @@ struct acl_entry {
};
typedef struct acl_entry *acl_entry_t;
/* internal ACL structure */
struct acl {
int acl_cnt;
struct acl_entry acl_entry[ACL_MAX_ENTRIES];
};
typedef struct acl *acl_t;
/* external ACL structure */
struct acl_t_struct {
struct acl ats_acl;
int ats_cur_entry;
};
typedef struct acl_t_struct *acl_t;
/*
* Possible valid values for ae_tag field.
@ -148,14 +155,14 @@ __END_DECLS
*/
__BEGIN_DECLS
int acl_add_perm(acl_permset_t _permset_d, acl_perm_t _perm);
int acl_calc_mask(acl_t *acl_p);
int acl_calc_mask(acl_t *_acl_p);
int acl_clear_perms(acl_permset_t _permset_d);
int acl_copy_entry(acl_entry_t _dest_d, acl_entry_t _src_d);
ssize_t acl_copy_ext(void *_buf_p, acl_t _acl, ssize_t _size);
acl_t acl_copy_int(const void *_buf_p);
int acl_create_entry(acl_t *_acl_p, acl_entry_t *_entry_p);
int acl_delete_fd_np(int _filedes, acl_type_t _type);
int acl_delete_entry(acl_t acl, acl_entry_t entry_d);
int acl_delete_entry(acl_t _acl, acl_entry_t _entry_d);
int acl_delete_file_np(const char *_path_p, acl_type_t _type);
int acl_delete_def_file(const char *_path_p);
int acl_delete_perm(acl_permset_t _permset_d, acl_perm_t _perm);