diff options
author | jedgar <jedgar@FreeBSD.org> | 2001-04-24 22:45:41 +0000 |
---|---|---|
committer | jedgar <jedgar@FreeBSD.org> | 2001-04-24 22:45:41 +0000 |
commit | 2da23531d99e45f34811fd6982a681112de0e182 (patch) | |
tree | 0b8830fcccafadf6607f3658e96733124ef8617d /bin | |
parent | ecbf3eacd9a17a3a9b238e2fa65b2d33d85e8d1f (diff) | |
download | FreeBSD-src-2da23531d99e45f34811fd6982a681112de0e182.zip FreeBSD-src-2da23531d99e45f34811fd6982a681112de0e182.tar.gz |
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
Diffstat (limited to 'bin')
-rw-r--r-- | bin/setfacl/mask.c | 24 | ||||
-rw-r--r-- | bin/setfacl/merge.c | 121 | ||||
-rw-r--r-- | bin/setfacl/remove.c | 81 | ||||
-rw-r--r-- | bin/setfacl/setfacl.c | 26 | ||||
-rw-r--r-- | bin/setfacl/setfacl.h | 14 |
5 files changed, 168 insertions, 98 deletions
diff --git a/bin/setfacl/mask.c b/bin/setfacl/mask.c index 5992e94..595ab44 100644 --- a/bin/setfacl/mask.c +++ b/bin/setfacl/mask.c @@ -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; diff --git a/bin/setfacl/merge.c b/bin/setfacl/merge.c index c739b26..acb01f4 100644 --- a/bin/setfacl/merge.c +++ b/bin/setfacl/merge.c @@ -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; - 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; + 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; - 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; } diff --git a/bin/setfacl/remove.c b/bin/setfacl/remove.c index 0fe02d1..e987df7 100644 --- a/bin/setfacl/remove.c +++ b/bin/setfacl/remove.c @@ -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; } diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c index c18c3f9..b2d8578 100644 --- a/bin/setfacl/setfacl.c +++ b/bin/setfacl/setfacl.c @@ -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, diff --git a/bin/setfacl/setfacl.h b/bin/setfacl/setfacl.h index b80fa44..d3c7923 100644 --- a/bin/setfacl/setfacl.h +++ b/bin/setfacl/setfacl.h @@ -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); |