struct name_list *get_list(const struct stat *st, acl_t acl) { struct name_list *first = NULL, *last = NULL; acl_entry_t ent; int ret = 0; if (acl != NULL) ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &ent); if (ret != 1) return NULL; while (ret > 0) { acl_tag_t e_type; const id_t *id_p; const char *name = ""; int len; acl_get_tag_type(ent, &e_type); switch(e_type) { case ACL_USER_OBJ: name = user_name(st->st_uid, opt_numeric); break; case ACL_USER: id_p = acl_get_qualifier(ent); if (id_p != NULL) name = user_name(*id_p, opt_numeric); break; case ACL_GROUP_OBJ: name = group_name(st->st_gid, opt_numeric); break; case ACL_GROUP: id_p = acl_get_qualifier(ent); if (id_p != NULL) name = group_name(*id_p, opt_numeric); break; } name = xquote(name, "\t\n\r"); len = strlen(name); if (last == NULL) { first = last = (struct name_list *) malloc(sizeof(struct name_list) + len + 1); } else { last->next = (struct name_list *) malloc(sizeof(struct name_list) + len + 1); last = last->next; } if (last == NULL) { free_list(first); return NULL; } last->next = NULL; strcpy(last->name, name); ret = acl_get_entry(acl, ACL_NEXT_ENTRY, &ent); } return first; }
/* * Translate POSIX.1e ACL into libarchive internal structure. */ static void setup_acl_posix1e(struct archive_read_disk *a, struct archive_entry *entry, acl_t acl, int archive_entry_acl_type) { acl_tag_t acl_tag; acl_entry_t acl_entry; acl_permset_t acl_permset; int s, ae_id, ae_tag, ae_perm; const char *ae_name; s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); while (s == 1) { ae_id = -1; ae_name = NULL; acl_get_tag_type(acl_entry, &acl_tag); if (acl_tag == ACL_USER) { ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_uname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_USER; } else if (acl_tag == ACL_GROUP) { ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_gname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_GROUP; } else if (acl_tag == ACL_MASK) { ae_tag = ARCHIVE_ENTRY_ACL_MASK; } else if (acl_tag == ACL_USER_OBJ) { ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; } else if (acl_tag == ACL_GROUP_OBJ) { ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; } else if (acl_tag == ACL_OTHER) { ae_tag = ARCHIVE_ENTRY_ACL_OTHER; } else { /* Skip types that libarchive can't support. */ continue; } acl_get_permset(acl_entry, &acl_permset); ae_perm = 0; /* * acl_get_perm() is spelled differently on different * platforms; see above. */ if (ACL_GET_PERM(acl_permset, ACL_EXECUTE)) ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; if (ACL_GET_PERM(acl_permset, ACL_READ)) ae_perm |= ARCHIVE_ENTRY_ACL_READ; if (ACL_GET_PERM(acl_permset, ACL_WRITE)) ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; archive_entry_acl_add_entry(entry, archive_entry_acl_type, ae_perm, ae_tag, ae_id, ae_name); s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); } }
static int acl_match(acl_entry_t aclent, struct myacl_t *myacl) { gid_t g, *gp; uid_t u, *up; acl_tag_t tag_type; acl_permset_t opaque_ps; int permset = 0; acl_get_tag_type(aclent, &tag_type); /* translate the silly opaque permset to a bitmap */ acl_get_permset(aclent, &opaque_ps); if (acl_get_perm_np(opaque_ps, ACL_EXECUTE)) permset |= ARCHIVE_ENTRY_ACL_EXECUTE; if (acl_get_perm_np(opaque_ps, ACL_WRITE)) permset |= ARCHIVE_ENTRY_ACL_WRITE; if (acl_get_perm_np(opaque_ps, ACL_READ)) permset |= ARCHIVE_ENTRY_ACL_READ; if (permset != myacl->permset) return (0); switch (tag_type) { case ACL_USER_OBJ: if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); break; case ACL_USER: if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) return (0); up = acl_get_qualifier(aclent); u = *up; acl_free(up); if ((uid_t)myacl->qual != u) return (0); break; case ACL_GROUP_OBJ: if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); break; case ACL_GROUP: if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) return (0); gp = acl_get_qualifier(aclent); g = *gp; acl_free(gp); if ((gid_t)myacl->qual != g) return (0); break; case ACL_MASK: if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); break; case ACL_OTHER: if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0); break; } return (1); }
static acl_entry_t findEntry(acl_t acl, acl_tag_t tag, id_t qaul) { acl_entry_t entry; acl_tag_t entryTag; uid_t *uidp; gid_t *gidp; int ent, s; for (ent = ACL_FIRST_ENTRY; ; ent = ACL_NEXT_ENTRY) { s = acl_get_entry(acl, ent, &entry); if (s == -1) errExit("acl_get_entry"); if (s == 0) return NULL; if (acl_get_tag_type(entry, &entryTag) == -1) errExit("acl_get_tag_type"); if (tag == entryTag) { if (tag == ACL_USER) { uidp = acl_get_qualifier(entry); if (uidp == NULL) errExit("acl_get_qualifier"); if (qaul == *uidp) { if (acl_free(uidp) == -1) errExit("acl_free"); return entry; } else { if (acl_free(uidp) == -1) errExit("acl_free"); } } else if (tag == ACL_GROUP) { gidp = acl_get_qualifier(entry); if (gidp == NULL) errExit("acl_get_qualifier"); if (qaul == *gidp) { if (acl_free(gidp) == -1) errExit("acl_free"); return entry; } else { if (acl_free(gidp) == -1) errExit("acl_free"); } } else { return entry; } } } }
static int acl_match(acl_entry_t aclent, struct myacl_t *myacl) { gid_t g, *gp; uid_t u, *up; acl_tag_t tag_type; acl_permset_t opaque_ps; acl_flagset_t opaque_fs; int perms; acl_get_tag_type(aclent, &tag_type); /* translate the silly opaque permset to a bitmap */ acl_get_permset(aclent, &opaque_ps); acl_get_flagset_np(aclent, &opaque_fs); perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs); if (perms != myacl->permset) return (0); switch (tag_type) { case ACL_USER_OBJ: if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); break; case ACL_USER: if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) return (0); up = acl_get_qualifier(aclent); u = *up; acl_free(up); if ((uid_t)myacl->qual != u) return (0); break; case ACL_GROUP_OBJ: if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); break; case ACL_GROUP: if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) return (0); gp = acl_get_qualifier(aclent); g = *gp; acl_free(gp); if ((gid_t)myacl->qual != g) return (0); break; case ACL_MASK: if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); break; case ACL_EVERYONE: if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0); break; } return (1); }
/* Compares two ACL entries for equality */ int compare_acl_entries(acl_entry_t a, acl_entry_t b) { acl_tag_t atag, btag; acl_permset_t aperms, bperms; acl_flagset_t aflags, bflags; int pcmp = 0, fcmp = 0; void *aqual, *bqual; aqual = acl_get_qualifier(a); bqual = acl_get_qualifier(b); int compare = compare_acl_qualifiers(aqual, bqual); acl_free(aqual); acl_free(bqual); if (compare != 0) return MATCH_NONE; if (0 != acl_get_tag_type(a, &atag)) { // err(1, "No tag type present in entry"); fprintf(stderr, "chmod: No tag type present in entry: %s\n", strerror(errno)); pthread_exit(NULL); } if (0!= acl_get_tag_type(b, &btag)) { // err(1, "No tag type present in entry"); fprintf(stderr, "chmod: No tag type present in entry: %s\n", strerror(errno)); pthread_exit(NULL); } if (atag != btag) return MATCH_NONE; if ((acl_get_permset(a, &aperms) != 0) || (acl_get_flagset_np(a, &aflags) != 0) || (acl_get_permset(b, &bperms) != 0) || (acl_get_flagset_np(b, &bflags) != 0)) { // err(1, "error fetching permissions"); fprintf(stderr, "chmod: error fetching permissions: %s\n", strerror(errno)); pthread_exit(NULL); } pcmp = compare_acl_permsets(aperms, bperms); fcmp = compare_acl_flagsets(aflags, bflags); if ((pcmp == MATCH_NONE) || (fcmp == MATCH_NONE)) return(MATCH_PARTIAL); else return(MATCH_EXACT); }
static acl_entry_t find_entry (acl_t acl, acl_tag_t type, id_t id) { acl_entry_t ent; acl_tag_t e_type; id_t *e_id_p; if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1) return NULL; for(;;) { acl_get_tag_type(ent, &e_type); if (type == e_type) { if (id == ACL_UNDEFINED_ID) return ent; e_id_p = acl_get_qualifier(ent); if (e_id_p == NULL) return NULL; if (*e_id_p == id) { acl_free(e_id_p); return ent; } acl_free(e_id_p); } if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1) return NULL; } }
/** * modifies `entry` to contain characteristics of `entry_in` *entry: ptr to entry to modify(only used if !add is true) *entry_in: ptr to entry who characterisitcs to use to modify entry *add: should this be a new entry * acl: acl to add new entry to *returns: status * if add is FALSE, acl is not checked **/ _BOOL acl_modify(acl_entry_t *entry,acl_entry_in *entry_in,_BOOL add,acl_t *acl){ if(entry_in == NULL){errno = EINVAL; return FALSE;} if(!add&&entry==NULL){errno = EINVAL;return FALSE;} if(add&&acl==NULL){errno = EINVAL; return FALSE;} if(!add){ //just do some checks to verify input acl_tag_t tag; if(acl_get_tag_type(*entry,&tag)!=ACL_OK) return FALSE; if(tag!=entry_in->tag){errno = EINVAL; return FALSE;} long *qual; if((qual=acl_get_qualifier(*entry))!=NULL){ if(*qual!=entry_in->qualifier.zero) return FALSE; } else if(!ISVALIDQUAL(entry_in->qualifier.zero)) return FALSE; //end checks if(!acl_update_permset(entry,entry_in)) return FALSE; } else if(add){ if(!acl_create(acl,entry_in)) return FALSE; } return TRUE; }
static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new, int acl_brand) { acl_permset_t permset; acl_entry_type_t entry_type; acl_flagset_t flagset; int have_entry; uid_t *id, *id_new; have_entry = 0; id = acl_get_qualifier(*entry); if (id == NULL) err(1, "acl_get_qualifier() failed"); id_new = acl_get_qualifier(*entry_new); if (id_new == NULL) err(1, "acl_get_qualifier() failed"); if (*id == *id_new) { /* any other matches */ if (acl_get_permset(*entry, &permset) == -1) err(1, "acl_get_permset() failed"); if (acl_set_permset(*entry_new, permset) == -1) err(1, "acl_set_permset() failed"); if (acl_brand == ACL_BRAND_NFS4) { if (acl_get_entry_type_np(*entry, &entry_type)) err(1, "acl_get_entry_type_np() failed"); if (acl_set_entry_type_np(*entry_new, entry_type)) err(1, "acl_set_entry_type_np() failed"); if (acl_get_flagset_np(*entry, &flagset)) err(1, "acl_get_flagset_np() failed"); if (acl_set_flagset_np(*entry_new, flagset)) err(1, "acl_set_flagset_np() failed"); } have_entry = 1; } acl_free(id); acl_free(id_new); return (have_entry); }
int search_acl_groups(char*** dst, const char* path, bool* belong) { acl_t acl; assert(path); assert(belong); acl = acl_get_file(path, ACL_TYPE_DEFAULT); if (acl) { acl_entry_t entry; int r; r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); while (r > 0) { acl_tag_t tag; gid_t *gid; char *name; r = acl_get_tag_type(entry, &tag); if (r < 0) break; if (tag != ACL_GROUP) goto next; gid = acl_get_qualifier(entry); if (!gid) break; if (in_gid(*gid) > 0) { *belong = true; break; } name = gid_to_name(*gid); if (!name) { acl_free(acl); return log_oom(); } r = strv_consume(dst, name); if (r < 0) { acl_free(acl); return log_oom(); } next: r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } acl_free(acl); } return 0; }
static int acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_tag) { int entry_id = ACL_FIRST_ENTRY; acl_entry_t acl_entry; acl_tag_t acl_tag_type; while (1 == acl_get_entry(acl, entry_id, &acl_entry)) { /* After the first time... */ entry_id = ACL_NEXT_ENTRY; /* If this matches, return perm mask */ acl_get_tag_type(acl_entry, &acl_tag_type); if (acl_tag_type == requested_tag_type) { switch (acl_tag_type) { case ACL_USER_OBJ: if ((uid_t)requested_tag == *(uid_t *)(acl_get_qualifier(acl_entry))) { return acl_entry_get_perm(acl_entry); } break; case ACL_GROUP_OBJ: if ((gid_t)requested_tag == *(gid_t *)(acl_get_qualifier(acl_entry))) { return acl_entry_get_perm(acl_entry); } break; case ACL_USER: case ACL_GROUP: case ACL_OTHER: return acl_entry_get_perm(acl_entry); default: failure("Unexpected ACL tag type"); assert(0); } } } return -1; }
/* merge two acl entries together if the qualifier is the same */ static int merge_user_group(acl_entry_t *entry1, acl_entry_t *entry2) { acl_permset_t permset; acl_entry_type_t entry_type; acl_flagset_t flagset; uid_t *id1, *id2; int rval = 0; if ((id1 = acl_get_qualifier(*entry1)) == NULL) err(EX_OSERR, "acl_get_qualifier() failed"); if ((id2 = acl_get_qualifier(*entry2)) == NULL) err(EX_OSERR, "acl_get_qualifier() failed"); if (*id1 == *id2) { merge_acl_entries(entry1, entry2); rval = 1; } acl_free(id1); acl_free(id2); return (rval); }
aclent_t getentry(acl_entry_t acl_entry, struct stat st, int acl_default) { aclent_t aclent; acl_tag_t e_type; acl_get_tag_type(acl_entry, &e_type); acl_permset_t permset; acl_get_permset(acl_entry, &permset); void *qualifier = acl_get_qualifier(acl_entry); aclent.a_perm = getmode(permset); switch(e_type) { case ACL_USER_OBJ: aclent.a_id = st.st_uid; break; case ACL_USER: aclent.a_id = *(uid_t*)qualifier; break; case ACL_GROUP_OBJ: aclent.a_id = st.st_gid; break; case ACL_GROUP: aclent.a_id = *(gid_t*)qualifier; break; case ACL_MASK: aclent.a_id = -1; break; case ACL_OTHER: aclent.a_id = -1; break; } aclent.a_type = e_type | acl_default; if(qualifier != NULL) { acl_free(qualifier); } return aclent; }
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { acl_entry_t i; int r; assert(acl); assert(entry); for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); r > 0; r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { acl_tag_t tag; uid_t *u; bool b; if (acl_get_tag_type(i, &tag) < 0) return -errno; if (tag != ACL_USER) continue; u = acl_get_qualifier(i); if (!u) return -errno; b = *u == uid; acl_free(u); if (b) { *entry = i; return 1; } } if (r < 0) return -errno; return 0; }
acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl) #endif { #if HAVE_POSIX_ACL gid_t g, *gp; uid_t u, *up; acl_tag_t tag_type; #endif if (myacl->permset != acl_entry_get_perm(aclent)) return (0); #if HAVE_SUN_ACL switch (aclent->a_type) #else acl_get_tag_type(aclent, &tag_type); switch (tag_type) #endif { #if HAVE_SUN_ACL case DEF_USER_OBJ: case USER_OBJ: #else case ACL_USER_OBJ: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0); break; #if HAVE_SUN_ACL case DEF_USER: case USER: #else case ACL_USER: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_USER) return (0); #if HAVE_SUN_ACL if ((uid_t)myacl->qual != aclent->a_id) return (0); #else up = acl_get_qualifier(aclent); u = *up; acl_free(up); if ((uid_t)myacl->qual != u) return (0); #endif break; #if HAVE_SUN_ACL case DEF_GROUP_OBJ: case GROUP_OBJ: #else case ACL_GROUP_OBJ: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0); break; #if HAVE_SUN_ACL case DEF_GROUP: case GROUP: #else case ACL_GROUP: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP) return (0); #if HAVE_SUN_ACL if ((gid_t)myacl->qual != aclent->a_id) return (0); #else gp = acl_get_qualifier(aclent); g = *gp; acl_free(gp); if ((gid_t)myacl->qual != g) return (0); #endif break; #if HAVE_SUN_ACL case DEF_CLASS_OBJ: case CLASS_OBJ: #else case ACL_MASK: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0); break; #if HAVE_SUN_ACL case DEF_OTHER_OBJ: case OTHER_OBJ: #else case ACL_OTHER: #endif if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0); break; } return (1); }
int sl_checkacls(acl_t a, struct srt_stat *sstb, const struct pscfs_creds *pcrp, int accmode) { int wh, rv = EACCES, i, rc, prec = 6; acl_entry_t e, authz = NULL, mask = NULL; acl_tag_t tag; gid_t *gp, g; uid_t *up; wh = ACL_FIRST_ENTRY; while ((rc = acl_get_entry(a, wh, &e)) == 1) { wh = ACL_NEXT_ENTRY; rc = acl_get_tag_type(e, &tag); switch (tag) { case ACL_USER_OBJ: if (sstb->sst_uid == pcrp->pcr_uid) ACL_SET_PRECEDENCE(1, prec, e, authz); break; case ACL_USER: up = acl_get_qualifier(e); if (*up == pcrp->pcr_uid) ACL_SET_PRECEDENCE(2, prec, e, authz); break; case ACL_GROUP_OBJ: FOREACH_GROUP(g, i, pcrp) if (g == sstb->sst_gid) { ACL_SET_PRECEDENCE(3, prec, e, authz); break; } break; case ACL_GROUP: gp = acl_get_qualifier(e); FOREACH_GROUP(g, i, pcrp) if (g == *gp) { ACL_SET_PRECEDENCE(4, prec, e, authz); break; } break; case ACL_OTHER: ACL_SET_PRECEDENCE(5, prec, e, authz); break; case ACL_MASK: mask = e; break; default: psclog_error("acl_get_tag_type"); break; } } if (rc == -1) psclog_error("acl_get_entry"); else if (authz) { rv = ACL_AUTH(authz, accmode); if (prec != 1 && prec != 5 && rv == 0 && mask) rv = ACL_AUTH(mask, accmode); } #ifdef SLOPT_POSIX_ACLS_REVERT else rv = checkcreds(sstb, pcrp, accmode); #endif return (rv); }
int do_show(FILE *stream, const char *path_p, const struct stat *st, acl_t acl, acl_t dacl) { struct name_list *acl_names = get_list(st, acl), *first_acl_name = acl_names; struct name_list *dacl_names = get_list(st, dacl), *first_dacl_name = dacl_names; int acl_names_width = max_name_length(acl_names); int dacl_names_width = max_name_length(dacl_names); acl_entry_t acl_ent; acl_entry_t dacl_ent; char acl_mask[ACL_PERMS+1], dacl_mask[ACL_PERMS+1]; int ret; names_width = 8; if (acl_names_width > names_width) names_width = acl_names_width; if (dacl_names_width > names_width) names_width = dacl_names_width; acl_mask[0] = '\0'; if (acl) { acl_mask_perm_str(acl, acl_mask); ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_ent); if (ret == 0) acl = NULL; if (ret < 0) return ret; } dacl_mask[0] = '\0'; if (dacl) { acl_mask_perm_str(dacl, dacl_mask); ret = acl_get_entry(dacl, ACL_FIRST_ENTRY, &dacl_ent); if (ret == 0) dacl = NULL; if (ret < 0) return ret; } fprintf(stream, "# file: %s\n", xquote(path_p, "\n\r")); while (acl_names != NULL || dacl_names != NULL) { acl_tag_t acl_tag, dacl_tag; if (acl) acl_get_tag_type(acl_ent, &acl_tag); if (dacl) acl_get_tag_type(dacl_ent, &dacl_tag); if (acl && (!dacl || acl_tag < dacl_tag)) { show_line(stream, &acl_names, acl, &acl_ent, acl_mask, NULL, NULL, NULL, NULL); continue; } else if (dacl && (!acl || dacl_tag < acl_tag)) { show_line(stream, NULL, NULL, NULL, NULL, &dacl_names, dacl, &dacl_ent, dacl_mask); continue; } else { if (acl_tag == ACL_USER || acl_tag == ACL_GROUP) { id_t *acl_id_p = NULL, *dacl_id_p = NULL; if (acl_ent) acl_id_p = acl_get_qualifier(acl_ent); if (dacl_ent) dacl_id_p = acl_get_qualifier(dacl_ent); if (acl && (!dacl || *acl_id_p < *dacl_id_p)) { show_line(stream, &acl_names, acl, &acl_ent, acl_mask, NULL, NULL, NULL, NULL); continue; } else if (dacl && (!acl || *dacl_id_p < *acl_id_p)) { show_line(stream, NULL, NULL, NULL, NULL, &dacl_names, dacl, &dacl_ent, dacl_mask); continue; } } show_line(stream, &acl_names, acl, &acl_ent, acl_mask, &dacl_names, dacl, &dacl_ent, dacl_mask); } } free_list(first_acl_name); free_list(first_dacl_name); return 0; }
int main (int argc, char *argv[]) { DIR *cwd_p; struct dirent *thisDir_p; acl_t acl; acl_entry_t entry; acl_tag_t tag; int entryId; uid_t *uid_p, cmdlineUid; gid_t *gid_p, cmdlineGid; UorG_t entryType; // cmdline args if (argc != 3) { usage (argv[0]); return 1; } switch (argv[1][0]) { case 'u': entryType = USER_e; if (!user_id_from_name (argv[2], &cmdlineUid)) { fprintf (stderr, "user_id_from_name() failure\n"); return 1; } break; case 'g': entryType = GROUP_e; if (!group_id_from_name (argv[2], &cmdlineGid)) { fprintf (stderr, "group_id_from_name() failure\n"); return 1; } break; default: usage (argv[0]); return 1; } cwd_p = opendir ("."); if (cwd_p == NULL) { perror ("opendir(.)"); return 1; } while ((thisDir_p = readdir (cwd_p)) != NULL) { if (thisDir_p->d_type != DT_REG) continue; acl = acl_get_file (thisDir_p->d_name, ACL_TYPE_ACCESS); if (acl == NULL) continue; for (entryId=ACL_FIRST_ENTRY; ; entryId=ACL_NEXT_ENTRY) { if (acl_get_entry (acl, entryId, &entry) == -1) break; if (acl_get_tag_type (entry, &tag) == -1) break; if (entryType == USER_e) { if (tag == ACL_USER) { uid_p = acl_get_qualifier (entry); if (uid_p == NULL) break; if (*uid_p == cmdlineUid) printf ("acl user matches: %s\n", thisDir_p->d_name); acl_free (uid_p); } } else { if (tag == ACL_GROUP) { gid_p = acl_get_qualifier (entry); if (gid_p == NULL) break; if (*gid_p == cmdlineGid) printf ("acl grp matches: %s\n", thisDir_p->d_name); acl_free (gid_p); } } } acl_free (acl); } closedir (cwd_p); return 0; }
int walk_acl(const acl_t acl, walk_acl_callback callback, void *data) { DEBUG("%s\n", "walking ACL"); int i = ACL_FIRST_ENTRY; do { acl_entry_t acl_entry = NULL; errno = 0; if (acl_get_entry(acl, i, &acl_entry) != 1) { if (errno != 0) { return -errno; } break; } acl_tag_t tag = ACL_UNDEFINED_TAG; void *id = NULL; int perms = 0; errno = 0; if (acl_get_tag_type(acl_entry, &tag) != 0) { return -errno; } if (tag == ACL_USER || tag == ACL_GROUP) { errno = 0; id = acl_get_qualifier(acl_entry); if (id == NULL) { return -errno; } } acl_permset_t permset = NULL; errno = 0; if (acl_get_permset(acl_entry, &permset) != 0) { acl_free(id); return -errno; } if (acl_get_perm(permset, ACL_READ) == 1) perms |= ACL_READ; if (acl_get_perm(permset, ACL_WRITE) == 1) perms |= ACL_WRITE; if (acl_get_perm(permset, ACL_EXECUTE) == 1) perms |= ACL_EXECUTE; int callback_ret = callback(tag, perms, id, data); if (callback_ret != 0) { acl_free(id); DEBUG("acl_to_text callback returned %s\n", strerror(-callback_ret)); return callback_ret; } acl_free(id); i = ACL_NEXT_ENTRY; } while (1); return 0; }
int main(int argc,char *argv[]) { acl_t acl; acl_type_t type; acl_entry_t entry; acl_tag_t tag; uid_t *uidp; gid_t *gidp; acl_permset_t permset; char *name; int entryId,permVal,opt; type = ACL_TYPE_ACCESS; while((opt = getopt(argc,argv,"d") != -1)) { switch(opt) { case 'd': type = ACL_TYPE_DEFAULT;break; case '?': usageError(argv[0]); } } if (optind + 1 != argc) { usageError(argv[0]); } acl = acl_get_file(argv[optind],type); if (acl == NULL) { errExit("acl_get_file"); } /* Walk through each entry in this ACL */ for (entryId = ACL_FIRST_ENTRY; ; entryId = ACL_NEXT_ENTRY) { if (acl_get_entry(acl,entryId,&entry) != 1) { break; /* Exit on error or no more entries */ } /* Retrieve and display tag type */ if (acl_get_tag_type(entry,&tag) == -1) { errExit("acl_get_tag_type"); } printf("%-12s", (tag == ACL_USER_OBJ) ? "user_obj" : (tag == ACL_USER) ? "user" : (tag == ACL_GROUP_OBJ) ? "group_obj": (tag == ACL_GROUP) ? "group": (tag == ACL_MASK) ? "mask": (tag == ACL_OTHER) ? "other":"???"); /* Retrieve and display otpional tag qualifier */ if (tag == ACL_USER) { uidp = acl_get_qualifier(entry); if (uidp == NULL) { errExit("acl_get_qualifier"); } name = userNameFromId(*uidp); if (name == NULL) { printf("%-8d",*uidp); } else { printf("%-8s",name); } if (acl_free(uidp) == -1) { errExit("acl_free"); } }else if (tag == ACL_GROUP) { gidp = acl_get_qualifier(entry); if (gidp == NULL) { errExit("acl_get_qualifier"); } name = groupNameFromId(*gidp); if (name == NULL) { printf("%-12d",*gidp); } else { printf("%-12s",name); } if (acl_free(gidp) == -1) { errExit("acl_free"); } }else { printf(" "); } /* Retrieve and display permissions */ if (acl_get_permset(entry,&permset) == -1) { errExit("acl_get_permset"); } permVal = acl_get_perm(permset,ACL_READ); if (permVal == -1) { errExit("acl_get_perm - ACL_READ"); } printf("%c", (permVal == 1) ? 'r' : '-'); permVal = acl_get_perm(permset,ACL_WRITE); if (permVal == -1) { errExit("acl_get_perm -ACL_WRITE"); } printf("%c", (permVal == 1) ? 'w': '-'); permVal = acl_get_perm(permset,ACL_EXECUTE); if (permVal == -1) { errExit("acl_get_perm - ACL_EXECUTE"); } printf("%c", (permVal == 1) ? 'x' : '-'); printf("\n"); } if (acl_free(acl) == -1) { errExit("acl_free"); } exit(EXIT_SUCCESS); }
static acl_entry_t FindACE(acl_t acl, acl_entry_t ace_find) { acl_entry_t ace_curr; acl_tag_t tag_curr; acl_tag_t tag_find; id_t *id_curr; id_t *id_find; int more_aces; int retv_tag; id_find = NULL; more_aces = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace_curr); if (more_aces == -1) { Log(LOG_LEVEL_ERR, "Error reading acl. (acl_get_entry: %s)", GetErrorStr()); return NULL; } else if (more_aces == 0) { return NULL; } /* find the tag type and id we are looking for */ if (acl_get_tag_type(ace_find, &tag_find) != 0) { Log(LOG_LEVEL_ERR, "Error reading tag type. (acl_get_tag_type: %s)", GetErrorStr()); return NULL; } if (tag_find == ACL_USER || tag_find == ACL_GROUP) { id_find = acl_get_qualifier(ace_find); if (id_find == NULL) { Log(LOG_LEVEL_ERR, "Error reading tag type. (acl_get_qualifier: %s)", GetErrorStr()); return NULL; } } /* check if any of the aces match */ while (more_aces) { if ((retv_tag = acl_get_tag_type(ace_curr, &tag_curr)) != 0) { Log(LOG_LEVEL_ERR, "Unable to get tag type. (acl_get_tag_type: %s)", GetErrorStr()); acl_free(id_find); return NULL; } if (tag_curr == tag_find) { if (id_find == NULL) { return ace_curr; } id_curr = acl_get_qualifier(ace_curr); if (id_curr == NULL) { Log(LOG_LEVEL_ERR, "Couldn't extract qualifier. (acl_get_qualifier: %s)", GetErrorStr()); return NULL; } if (*id_curr == *id_find) { acl_free(id_find); acl_free(id_curr); return ace_curr; } acl_free(id_curr); } more_aces = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace_curr); } if (id_find != NULL) { acl_free(id_find); } return NULL; }
int main (int argc, char *argv[]) { acl_t acl; acl_type_t type; acl_entry_t entry; acl_tag_t tag; uid_t *uid_p; gid_t *gid_p; acl_permset_t permset; char *name_p; int entryId, permVal, opt; type = ACL_TYPE_ACCESS; while ((opt = getopt (argc, argv, "d")) != -1) { switch (opt) { case 'd': type = ACL_TYPE_DEFAULT; break; case '?': usage (argv[0]); return 1; } } if (optind + 1 != argc) { usage (argv[0]); return 1; } acl = acl_get_file (argv[optind], type); if (acl == NULL) { perror ("acl_get_file()"); return 1; } for (entryId=ACL_FIRST_ENTRY; ; entryId=ACL_NEXT_ENTRY) { if (acl_get_entry (acl, entryId, &entry) != 1) break; if (acl_get_tag_type (entry, &tag) == -1) { perror ("acl_get_tag_type()"); return 1; } printf ("%-12s", (tag == ACL_USER_OBJ)? "user_obj" : (tag == ACL_USER)? "user" : (tag == ACL_GROUP_OBJ)? "group_obj" : (tag == ACL_GROUP)? "group" : (tag == ACL_MASK)? "mask" : (tag == ACL_OTHER)? "other" : "???"); // optional user/group ACLs if (tag == ACL_USER) { uid_p = acl_get_qualifier (entry); if (uid_p == NULL) { perror ("acl_get_qualifier()"); return 1; } name_p = user_name_from_id (*uid_p); if (name_p == NULL) printf ("\t\t%d", *uid_p); else printf ("\t\t%s", name_p); if (acl_free (uid_p) == -1) perror ("acl_free (uid_p)"); } else if (tag == ACL_GROUP) { gid_p = acl_get_qualifier (entry); if (gid_p == NULL) { perror ("acl_get_qualifier()"); return 1; } name_p = group_name_from_id (*gid_p); if (name_p == NULL) printf ("\t\t%d", *gid_p); else printf ("\t\t%s", name_p); if (acl_free (gid_p) == -1) perror ("acl_free (gid_p)"); } else printf ("\t\t"); // permissions if (acl_get_permset (entry, &permset) == -1) { perror ("acl_get_permset()"); return 1; } if ((permVal = acl_get_perm (permset, ACL_READ)) == -1) { perror ("acl_get_perm (ACL_READ)"); return 1; } printf ("\t\t%c", (permVal == 1)? 'r' : '-'); if ((permVal = acl_get_perm (permset, ACL_WRITE)) == -1) { perror ("acl_get_perm (ACL_WRITE)"); return 1; } printf ("%c", (permVal == 1)? 'w' : '-'); if ((permVal = acl_get_perm (permset, ACL_EXECUTE)) == -1) { perror ("acl_get_perm (ACL_EXECUTE)"); return 1; } printf ("%c", (permVal == 1)? 'x' : '-'); printf ("\n"); } if (acl_free (acl) == -1) { perror ("acl_free (acl)"); return 1; } return 0; }
static int set_facl(const char* filename, uid_t uid, int add) { int get; acl_t acl; acl_entry_t entry = NULL; acl_entry_t e; acl_permset_t permset; int ret; /* don't touch ACLs for root */ if (uid == 0) return 0; /* read current record */ acl = acl_get_file(filename, ACL_TYPE_ACCESS); if (!acl) return -1; /* locate ACL_USER entry for uid */ get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e); while (get == 1) { acl_tag_t t; acl_get_tag_type(e, &t); if (t == ACL_USER) { uid_t *u; u = (uid_t*)acl_get_qualifier(e); if (u == NULL) { ret = -1; goto out; } if (*u == uid) { entry = e; acl_free(u); break; } acl_free(u); } get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e); } /* remove ACL_USER entry for uid */ if (!add) { if (entry == NULL) { ret = 0; goto out; } acl_delete_entry(acl, entry); goto update; } /* create ACL_USER entry for uid */ if (entry == NULL) { ret = acl_create_entry(&acl, &entry); if (ret != 0) goto out; acl_set_tag_type(entry, ACL_USER); acl_set_qualifier(entry, &uid); } /* add permissions for uid */ acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ|ACL_WRITE); update: /* update record */ if (debug) printf("%c%u %s\n", add ? '+' : '-', uid, filename); acl_calc_mask(&acl); ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl); if (ret != 0) goto out; out: acl_free(acl); return ret; }
static bool smb_ace_to_internal(acl_entry_t posix_ace, struct smb_acl_entry *ace) { acl_tag_t tag; acl_permset_t permset; if (acl_get_tag_type(posix_ace, &tag) != 0) { DEBUG(0, ("smb_acl_get_tag_type failed\n")); return False; } switch(tag) { case ACL_USER: ace->a_type = SMB_ACL_USER; break; case ACL_USER_OBJ: ace->a_type = SMB_ACL_USER_OBJ; break; case ACL_GROUP: ace->a_type = SMB_ACL_GROUP; break; case ACL_GROUP_OBJ: ace->a_type = SMB_ACL_GROUP_OBJ; break; case ACL_OTHER: ace->a_type = SMB_ACL_OTHER; break; case ACL_MASK: ace->a_type = SMB_ACL_MASK; break; default: DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag)); return False; } switch(ace->a_type) { case SMB_ACL_USER: { uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace); if (puid == NULL) { DEBUG(0, ("smb_acl_get_qualifier failed\n")); return False; } ace->uid = *puid; acl_free(puid); break; } case SMB_ACL_GROUP: { gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace); if (pgid == NULL) { DEBUG(0, ("smb_acl_get_qualifier failed\n")); return False; } ace->gid = *pgid; acl_free(pgid); break; } default: break; } if (acl_get_permset(posix_ace, &permset) != 0) { DEBUG(0, ("smb_acl_get_mode failed\n")); return False; } ace->a_perm = 0; #ifdef HAVE_ACL_GET_PERM_NP ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0); ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0); ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); #else ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0); ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0); ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); #endif return True; }
int main (int argc, char *argv[]) { if (argc != 4) { usage(argv[0]); } char mode; if (strcmp(argv[1], "u") == 0) { mode = 'u'; } else if (strcmp(argv[1], "g") == 0) { mode = 'g'; } else { usage(argv[0]); } uid_t uid; gid_t gid; if (mode == 'u') { uid = userIdFromName(argv[2]); if (uid == -1) { errExit("couldn't find user %s\n", argv[2]); } } else { // mode == 'g' gid = groupIdFromName(argv[2]); if (gid == -1) { errExit("couldn't find group %s\n", argv[2]); } } char *filepath = argv[3]; struct stat stats; if (stat(filepath, &stats) == -1) { errExit("stat\n"); } acl_t acl = acl_get_file(filepath, ACL_TYPE_ACCESS); if (acl == NULL) { errExit("acl_get_file\n"); } acl_entry_t entry; acl_tag_t tag; int entryId; int mask_found = 0; acl_entry_t mask; for (entryId = ACL_FIRST_ENTRY; ; entryId = ACL_NEXT_ENTRY) { if (acl_get_entry(acl, entryId, &entry) == 1) { break; } if ((tag = acl_get_tag_type(entry, &tag)) == -1) { errExit("acl_get_tag_type\n"); } if (tag == ACL_MASK) { mask_found = 1; mask = entry; break; } } acl_entry_t needle; uid_t *uid_p; gid_t *gid_p; for (entryId = ACL_FIRST_ENTRY; ; entryId = ACL_NEXT_ENTRY) { if (acl_get_entry(acl, entryId, &entry) != 1) { errExit( "couldn't find an entry for the specified %s\n", mode == 'u' ? "user" : "group" ); } if (acl_get_tag_type(entry, &tag) == -1) { errExit("acl_get_tag_type\n"); } if (mode == 'u') { if (uid == stats.st_uid && tag == ACL_USER_OBJ) { needle = entry; break; } if (tag != ACL_USER) { continue; } uid_p = acl_get_qualifier(entry); if (uid_p == NULL) { errExit("acl_get_qualifier\n"); } if (*uid_p == uid) { needle = entry; break; } } if (mode == 'g') { if (gid == stats.st_gid && tag == ACL_GROUP_OBJ) { needle = entry; break; } if (tag != ACL_GROUP) { continue; } gid_p = acl_get_qualifier(entry); if (gid_p == NULL) { errExit("acl_get_qualifier\n"); } if (*gid_p == gid) { needle = entry; break; } } } acl_permset_t needle_perms; if (acl_get_permset(needle, &needle_perms) == -1) { errExit("acl_get_permset\n"); } printPerms(needle_perms); printf("\n"); if (mask_found && !(mode == 'u' && uid == stats.st_uid && tag == ACL_USER_OBJ)) { acl_permset_t mask_perms; if (acl_get_permset(mask, &mask_perms) == -1) { errExit("acl_get_permset\n"); } printf("Effective permissions: "); if (maskPermset(needle_perms, mask_perms) == -1) { errExit("maskPermset\n"); } printPerms(needle_perms); printf("\n"); } exit(EXIT_SUCCESS); }
char * acl_to_text(acl_t acl, ssize_t *len_p) { acl_tag_t tag; acl_entry_t entry = NULL; acl_flagset_t flags; acl_permset_t perms; uid_t id; int i, first; int isgid; size_t bufsize = 1024; char *buf = NULL; if (!_ACL_VALID_ACL(acl)) { errno = EINVAL; return NULL; } if (len_p == NULL) if ((len_p = alloca(sizeof(ssize_t))) == NULL) goto err_nomem; *len_p = 0; if ((buf = malloc(bufsize)) == NULL) goto err_nomem; if (!raosnprintf(&buf, &bufsize, len_p, "!#acl %d", 1)) goto err_nomem; if (acl_get_flagset_np(acl, &flags) == 0) { for (i = 0, first = 0; acl_flags[i].name != NULL; ++i) { if (acl_flags[i].type & ACL_TYPE_ACL && acl_get_flag_np(flags, acl_flags[i].flag) != 0) { if(!raosnprintf(&buf, &bufsize, len_p, "%s%s", first++ ? "," : " ", acl_flags[i].name)) goto err_nomem; } } } for (;acl_get_entry(acl, entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &entry) == 0;) { int valid; uuid_t *uu; char *str, uu_str[37]; if (((uu = (uuid_t *) acl_get_qualifier(entry)) == NULL) || (acl_get_tag_type(entry, &tag) != 0) || (acl_get_flagset_np(entry, &flags) != 0) || (acl_get_permset(entry, &perms) != 0)) { if (uu != NULL) acl_free(uu); continue; } uuid_unparse_upper(*uu, uu_str); if ((str = uuid_to_name(uu, &id, &isgid)) != NULL) { valid = raosnprintf(&buf, &bufsize, len_p, "\n%s:%s:%s:%d:%s", isgid ? "group" : "user", uu_str, str, id, (tag == ACL_EXTENDED_ALLOW) ? "allow" : "deny"); } else { valid = raosnprintf(&buf, &bufsize, len_p, "\nuser:%s:::%s", uu_str, (tag == ACL_EXTENDED_ALLOW) ? "allow" : "deny"); } free(str); acl_free(uu); if (!valid) goto err_nomem; for (i = 0; acl_flags[i].name != NULL; ++i) { if (acl_flags[i].type & (ACL_TYPE_DIR | ACL_TYPE_FILE)) { if(acl_get_flag_np(flags, acl_flags[i].flag) != 0) { if(!raosnprintf(&buf, &bufsize, len_p, ",%s", acl_flags[i].name)) goto err_nomem; } } } for (i = 0, first = 0; acl_perms[i].name != NULL; ++i) { if (acl_perms[i].type & (ACL_TYPE_DIR | ACL_TYPE_FILE)) { if(acl_get_perm_np(perms, acl_perms[i].perm) != 0) { if(!raosnprintf(&buf, &bufsize, len_p, "%s%s", first++ ? "," : ":", acl_perms[i].name)) goto err_nomem; } } } } buf[(*len_p)++] = '\n'; buf[(*len_p)] = 0; return buf; err_nomem: if (buf != NULL) free(buf); errno = ENOMEM; return NULL; }
static int translate_acl(struct archive_read_disk *a, struct archive_entry *entry, acl_t acl, int default_entry_acl_type) { acl_tag_t acl_tag; acl_entry_type_t acl_type; acl_flagset_t acl_flagset; acl_entry_t acl_entry; acl_permset_t acl_permset; int brand, i, r, entry_acl_type; int s, ae_id, ae_tag, ae_perm; const char *ae_name; // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 // Make sure the "brand" on this ACL is consistent // with the default_entry_acl_type bits provided. acl_get_brand_np(acl, &brand); switch (brand) { case ACL_BRAND_POSIX: switch (default_entry_acl_type) { case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: break; default: // XXX set warning message? return ARCHIVE_FAILED; } break; case ACL_BRAND_NFS4: if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { // XXX set warning message? return ARCHIVE_FAILED; } break; default: // XXX set warning message? return ARCHIVE_FAILED; break; } s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); while (s == 1) { ae_id = -1; ae_name = NULL; ae_perm = 0; acl_get_tag_type(acl_entry, &acl_tag); switch (acl_tag) { case ACL_USER: ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_uname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_USER; break; case ACL_GROUP: ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_gname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_GROUP; break; case ACL_MASK: ae_tag = ARCHIVE_ENTRY_ACL_MASK; break; case ACL_USER_OBJ: ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; break; case ACL_GROUP_OBJ: ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; break; case ACL_OTHER: ae_tag = ARCHIVE_ENTRY_ACL_OTHER; break; case ACL_EVERYONE: ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; break; default: /* Skip types that libarchive can't support. */ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); continue; } // XXX acl type maps to allow/deny/audit/YYYY bits // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for // non-NFSv4 ACLs entry_acl_type = default_entry_acl_type; r = acl_get_entry_type_np(acl_entry, &acl_type); if (r == 0) { switch (acl_type) { case ACL_ENTRY_TYPE_ALLOW: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; break; case ACL_ENTRY_TYPE_DENY: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; break; case ACL_ENTRY_TYPE_AUDIT: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; break; case ACL_ENTRY_TYPE_ALARM: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; break; } } /* * Libarchive stores "flag" (NFSv4 inheritance bits) * in the ae_perm bitmap. */ acl_get_flagset_np(acl_entry, &acl_flagset); for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { if (acl_get_flag_np(acl_flagset, acl_inherit_map[i].platform_inherit)) ae_perm |= acl_inherit_map[i].archive_inherit; } acl_get_permset(acl_entry, &acl_permset); for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { /* * acl_get_perm() is spelled differently on different * platforms; see above. */ if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm)) ae_perm |= acl_perm_map[i].archive_perm; } archive_entry_acl_add_entry(entry, entry_acl_type, ae_perm, ae_tag, ae_id, ae_name); s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); } return (ARCHIVE_OK); }
int acl_search_groups(const char *path, char ***ret_groups) { _cleanup_strv_free_ char **g = NULL; _cleanup_(acl_freep) acl_t acl = NULL; bool ret = false; acl_entry_t entry; int r; assert(path); acl = acl_get_file(path, ACL_TYPE_DEFAULT); if (!acl) return -errno; r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); for (;;) { _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL; acl_tag_t tag; if (r < 0) return -errno; if (r == 0) break; if (acl_get_tag_type(entry, &tag) < 0) return -errno; if (tag != ACL_GROUP) goto next; gid = acl_get_qualifier(entry); if (!gid) return -errno; if (in_gid(*gid) > 0) { if (!ret_groups) return true; ret = true; } if (ret_groups) { char *name; name = gid_to_name(*gid); if (!name) return -ENOMEM; r = strv_consume(&g, name); if (r < 0) return r; } next: r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } if (ret_groups) *ret_groups = TAKE_PTR(g); return ret; }
static int check_facl(pool *p, const char *path, int mode, void *acl, int nents, struct stat *st, uid_t uid, gid_t gid, array_header *suppl_gids) { # if defined(HAVE_BSD_POSIX_ACL) || defined(HAVE_LINUX_POSIX_ACL) register unsigned int i; int have_access_entry = FALSE, res = -1; pool *acl_pool; acl_t facl = acl; acl_entry_t ae; acl_tag_t ae_type; acl_entry_t acl_user_entry = NULL; acl_entry_t acl_group_entry = NULL; acl_entry_t acl_other_entry = NULL; acl_entry_t acl_mask_entry = NULL; array_header *acl_groups; array_header *acl_users; /* Iterate through all of the ACL entries, sorting them for later * checking. */ res = acl_get_entry(facl, ACL_FIRST_ENTRY, &ae); if (res < 0) { pr_log_debug(DEBUG10, "FS: unable to retrieve first ACL entry for '%s': %s", path, strerror(errno)); errno = EACCES; return -1; } if (res == 0) { pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s' has no entries!", path); errno = EACCES; return -1; } acl_pool = make_sub_pool(p); acl_groups = make_array(acl_pool, 1, sizeof(acl_entry_t)); acl_users = make_array(acl_pool, 1, sizeof(acl_entry_t)); while (res > 0) { if (acl_get_tag_type(ae, &ae_type) < 0) { pr_log_debug(DEBUG5, "FS: error retrieving type of ACL entry for '%s': %s", path, strerror(errno)); res = acl_get_entry(facl, ACL_NEXT_ENTRY, &ae); continue; } if (ae_type & ACL_USER_OBJ) { acl_copy_entry(acl_user_entry, ae); } else if (ae_type & ACL_USER) { acl_entry_t *ae_dup = push_array(acl_users); acl_copy_entry(*ae_dup, ae); } else if (ae_type & ACL_GROUP_OBJ) { acl_copy_entry(acl_group_entry, ae); } else if (ae_type & ACL_GROUP) { acl_entry_t *ae_dup = push_array(acl_groups); acl_copy_entry(*ae_dup, ae); } else if (ae_type & ACL_OTHER) { acl_copy_entry(acl_other_entry, ae); } else if (ae_type & ACL_MASK) { acl_copy_entry(acl_mask_entry, ae); } res = acl_get_entry(facl, ACL_NEXT_ENTRY, &ae); } /* Select the ACL entry that determines access. */ res = -1; /* 1. If the given user ID matches the file owner, use that entry for * access. */ if (uid == st->st_uid) { /* Check the acl_user_entry for access. */ acl_copy_entry(ae, acl_user_entry); ae_type = ACL_USER_OBJ; have_access_entry = TRUE; } /* 2. If not matched above, and f the given user ID matches one of the * named user entries, use that entry for access. */ for (i = 0; !have_access_entry && i < acl_users->nelts; i++) { acl_entry_t e = ((acl_entry_t *) acl_users->elts)[i]; if (uid == *((uid_t *) acl_get_qualifier(e))) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ acl_copy_entry(ae, e); ae_type = ACL_USER; have_access_entry = TRUE; break; } } /* 3. If not matched above, and if one of the group IDs matches the * group owner entry, and the group owner entry contains the * requested permissions, use that entry for access. */ if (!have_access_entry && gid == st->st_gid) { /* Check the acl_group_entry for access. First though, we need to * see if the acl_group_entry contains the requested permissions. */ acl_permset_t perms; acl_get_permset(acl_group_entry, &perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(perms, mode) == 1) { # endif acl_copy_entry(ae, acl_group_entry); ae_type = ACL_GROUP_OBJ; have_access_entry = TRUE; } } if (suppl_gids) { for (i = 0; !have_access_entry && i < suppl_gids->nelts; i++) { gid_t suppl_gid = ((gid_t *) suppl_gids->elts)[i]; if (suppl_gid == st->st_gid) { /* Check the acl_group_entry for access. First though, we need to * see if the acl_group_entry contains the requested permissions. */ acl_permset_t perms; acl_get_permset(acl_group_entry, &perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(perms, mode) == 1) { # endif acl_copy_entry(ae, acl_group_entry); ae_type = ACL_GROUP_OBJ; have_access_entry = TRUE; break; } } } } /* 5. If not matched above, and if one of the group IDs matches one * of the named group entries, and that entry contains the requested * permissions, use that entry for access. */ for (i = 0; !have_access_entry && i < acl_groups->nelts; i++) { acl_entry_t e = ((acl_entry_t *) acl_groups->elts)[i]; if (gid == *((gid_t *) acl_get_qualifier(e))) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ acl_permset_t perms; acl_get_permset(e, &perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(perms, mode) == 1) { # endif acl_copy_entry(ae, e); ae_type = ACL_GROUP; have_access_entry = TRUE; break; } } if (suppl_gids) { register unsigned int j; for (j = 0; !have_access_entry && j < suppl_gids->nelts; j++) { gid_t suppl_gid = ((gid_t *) suppl_gids->elts)[j]; if (suppl_gid == *((gid_t *) acl_get_qualifier(e))) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ acl_permset_t perms; acl_get_permset(e, &perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(perms, mode) == 1) { # endif acl_copy_entry(ae, e); ae_type = ACL_GROUP; have_access_entry = TRUE; break; } } } } } /* 6. If not matched above, and if one of the group IDs matches * the group owner or any of the named group entries, but neither * the group owner entry nor any of the named group entries contains * the requested permissions, access is denied. */ /* 7. If not matched above, the other entry determines access. */ if (!have_access_entry) { acl_copy_entry(ae, acl_other_entry); ae_type = ACL_OTHER; have_access_entry = TRUE; } /* Access determination: * * If either the user owner entry or other entry were used, and the * entry contains the requested permissions, access is permitted. * * Otherwise, if the selected entry and the mask entry both contain * the requested permissions, access is permitted. * * Otherwise, access is denied. */ switch (ae_type) { case ACL_USER_OBJ: case ACL_OTHER: { acl_permset_t perms; acl_get_permset(ae, &perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(perms, mode) == 1) { # endif res = 0; } break; } default: { acl_permset_t ent_perms, mask_perms; acl_get_permset(ae, &ent_perms); acl_get_permset(acl_mask_entry, &mask_perms); # if defined(HAVE_BSD_POSIX_ACL) if (acl_get_perm_np(ent_perms, mode) == 1 && acl_get_perm_np(mask_perms, mode) == 1) { # elif defined(HAVE_LINUX_POSIX_ACL) if (acl_get_perm(ent_perms, mode) == 1 && acl_get_perm(mask_perms, mode) == 1) { # endif res = 0; } break; } } destroy_pool(acl_pool); if (res < 0) errno = EACCES; return res; # elif defined(HAVE_SOLARIS_POSIX_ACL) register unsigned int i; int have_access_entry = FALSE, idx, res = -1; pool *acl_pool; aclent_t *acls = acl; aclent_t ae; int ae_type = 0; aclent_t acl_user_entry; aclent_t acl_group_entry; aclent_t acl_other_entry; aclent_t acl_mask_entry; array_header *acl_groups; array_header *acl_users; /* In the absence of any clear documentation, I'll assume that * Solaris ACLs follow the same selection and checking algorithm * as do BSD and Linux. */ res = aclcheck(acls, nents, &idx); switch (res) { case 0: break; case GRP_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "too many GROUP entries"); errno = EACCES; return -1; case USER_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "too many USER entries"); errno = EACCES; return -1; case OTHER_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "too many OTHER entries"); errno = EACCES; return -1; case CLASS_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "too many CLASS entries"); errno = EACCES; return -1; case DUPLICATE_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "duplicate entries"); errno = EACCES; return -1; case MISS_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "missing required entry"); errno = EACCES; return -1; case MEM_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "Out of memory!"); errno = EACCES; return -1; case ENTRY_ERROR: pr_log_debug(DEBUG3, "FS: ill-formed ACL for '%s': %s", path, "invalid entry type"); errno = EACCES; return -1; } /* Iterate through all of the ACL entries, sorting them for later * checking. */ acl_pool = make_sub_pool(p); acl_groups = make_array(acl_pool, 1, sizeof(aclent_t)); acl_users = make_array(acl_pool, 1, sizeof(aclent_t)); for (i = 0; i < nents; i++) { if (acls[i].a_type & USER_OBJ) { memcpy(&acl_user_entry, &(acls[i]), sizeof(aclent_t)); } else if (acls[i].a_type & USER) { aclent_t *ae_dup = push_array(acl_users); memcpy(ae_dup, &(acls[i]), sizeof(aclent_t)); } else if (acls[i].a_type & GROUP_OBJ) { memcpy(&acl_group_entry, &(acls[i]), sizeof(aclent_t)); } else if (acls[i].a_type & GROUP) { aclent_t *ae_dup = push_array(acl_groups); memcpy(ae_dup, &(acls[i]), sizeof(aclent_t)); } else if (acls[i].a_type & OTHER_OBJ) { memcpy(&acl_other_entry, &(acls[i]), sizeof(aclent_t)); } else if (acls[i].a_type & CLASS_OBJ) { memcpy(&acl_mask_entry, &(acls[i]), sizeof(aclent_t)); } } /* Select the ACL entry that determines access. */ res = -1; /* 1. If the given user ID matches the file owner, use that entry for * access. */ if (uid == st->st_uid) { /* Check the acl_user_entry for access. */ memcpy(&ae, &acl_user_entry, sizeof(aclent_t)); ae_type = USER_OBJ; have_access_entry = TRUE; } /* 2. If not matched above, and f the given user ID matches one of the * named user entries, use that entry for access. */ for (i = 0; !have_access_entry && i < acl_users->nelts; i++) { aclent_t e; memcpy(&e, &(((aclent_t *) acl_users->elts)[i]), sizeof(aclent_t)); if (uid == e.a_id) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ memcpy(&ae, &e, sizeof(aclent_t)); ae_type = USER; have_access_entry = TRUE; break; } } /* 3. If not matched above, and if one of the group IDs matches the * group owner entry, and the group owner entry contains the * requested permissions, use that entry for access. */ if (!have_access_entry && gid == st->st_gid) { /* Check the acl_group_entry for access. First though, we need to * see if the acl_group_entry contains the requested permissions. */ if (acl_group_entry.a_perm & mode) { memcpy(&ae, &acl_group_entry, sizeof(aclent_t)); ae_type = GROUP_OBJ; have_access_entry = TRUE; } } if (suppl_gids) { for (i = 0; !have_access_entry && i < suppl_gids->nelts; i++) { gid_t suppl_gid = ((gid_t *) suppl_gids->elts)[i]; if (suppl_gid == st->st_gid) { /* Check the acl_group_entry for access. First though, we need to * see if the acl_group_entry contains the requested permissions. */ if (acl_group_entry.a_perm & mode) { memcpy(&ae, &acl_group_entry, sizeof(aclent_t)); ae_type = GROUP_OBJ; have_access_entry = TRUE; break; } } } } /* 5. If not matched above, and if one of the group IDs matches one * of the named group entries, and that entry contains the requested * permissions, use that entry for access. */ for (i = 0; !have_access_entry && i < acl_groups->nelts; i++) { aclent_t e; memcpy(&e, &(((aclent_t *) acl_groups->elts)[i]), sizeof(aclent_t)); if (gid == e.a_id) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ if (e.a_perm & mode) { memcpy(&ae, &e, sizeof(aclent_t)); ae_type = GROUP; have_access_entry = TRUE; break; } } if (suppl_gids) { register unsigned int j; for (j = 0; !have_access_entry && j < suppl_gids->nelts; j++) { gid_t suppl_gid = ((gid_t *) suppl_gids->elts)[j]; if (suppl_gid == e.a_id) { /* Check this entry for access. Note that it'll need to * be modified by the mask, if any, later. */ if (e.a_perm & mode) { memcpy(&ae, &e, sizeof(aclent_t)); ae_type = GROUP; have_access_entry = TRUE; break; } } } } } /* 6. If not matched above, and if one of the group IDs matches * the group owner or any of the named group entries, but neither * the group owner entry nor any of the named group entries contains * the requested permissions, access is denied. */ /* 7. If not matched above, the other entry determines access. */ if (!have_access_entry) { memcpy(&ae, &acl_other_entry, sizeof(aclent_t)); ae_type = OTHER_OBJ; have_access_entry = TRUE; } /* Access determination: * * If either the user owner entry or other entry were used, and the * entry contains the requested permissions, access is permitted. * * Otherwise, if the selected entry and the mask entry both contain * the requested permissions, access is permitted. * * Otherwise, access is denied. */ switch (ae_type) { case USER_OBJ: case OTHER_OBJ: if (ae.a_perm & mode) res = 0; break; default: if ((ae.a_perm & mode) && (acl_mask_entry.a_perm & mode)) res = 0; break; } destroy_pool(acl_pool); if (res < 0) errno = EACCES; return res; # endif /* HAVE_SOLARIS_POSIX_ACL */ } /* FSIO handlers */ static int facl_fsio_access(pr_fs_t *fs, const char *path, int mode, uid_t uid, gid_t gid, array_header *suppl_gids) { int nents = 0; struct stat st; void *acls; pr_fs_clear_cache(); if (pr_fsio_stat(path, &st) < 0) return -1; /* Look up the acl for this path. */ # if defined(HAVE_BSD_POSIX_ACL) || defined(HAVE_LINUX_POSIX_ACL) acls = acl_get_file(path, ACL_TYPE_ACCESS); if (!acls) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL for '%s': %s", path, strerror(errno)); return -1; } # elif defined(HAVE_SOLARIS_POSIX_ACL) nents = acl(path, GETACLCNT, 0, NULL); if (nents < 0) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL count for '%s': %s", path, strerror(errno)); return -1; } acls = pcalloc(fs->fs_pool, nents * sizeof(aclent_t)); nents = acl(path, GETACL, nents, acls); if (nents < 0) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL for '%s': %s", path, strerror(errno)); return -1; } # endif return check_facl(fs->fs_pool, path, mode, acls, nents, &st, uid, gid, suppl_gids); } static int facl_fsio_faccess(pr_fh_t *fh, int mode, uid_t uid, gid_t gid, array_header *suppl_gids) { int nents = 0; struct stat st; void *acls; pr_fs_clear_cache(); if (pr_fsio_fstat(fh, &st) < 0) return -1; /* Look up the acl for this fd. */ # if defined(HAVE_BSD_POSIX_ACL) || defined(HAVE_LINUX_POSIX_ACL) acls = acl_get_fd(PR_FH_FD(fh)); if (!acls) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL for '%s': %s", fh->fh_path, strerror(errno)); return -1; } # elif defined(HAVE_SOLARIS_POSIX_ACL) nents = facl(PR_FH_FD(fh), GETACLCNT, 0, NULL); if (nents < 0) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL count for '%s': %s", fh->fh_path, strerror(errno)); return -1; } acls = pcalloc(fh->fh_fs->fs_pool, nents * sizeof(aclent_t)); nents = facl(PR_FH_FD(fh), GETACL, nents, acls); if (nents < 0) { pr_log_debug(DEBUG10, "FS: unable to retrieve ACL for '%s': %s", fh->fh_path, strerror(errno)); return -1; } # endif return check_facl(fh->fh_fs->fs_pool, fh->fh_path, mode, acls, nents, &st, uid, gid, suppl_gids); } #endif /* HAVE_POSIX_ACL */ /* Initialization routines */ static int facl_init(void) { #if defined(PR_USE_FACL) && defined(HAVE_POSIX_ACL) pr_fs_t *fs = pr_register_fs(permanent_pool, "facl", "/"); if (!fs) { pr_log_pri(PR_LOG_ERR, MOD_FACL_VERSION ": error registering fs: %s", strerror(errno)); return -1; } /* Ensure that our ACL-checking handlers are used. */ fs->access = facl_fsio_access; fs->faccess = facl_fsio_faccess; #endif /* PR_USE_FACL and HAVE_POSIX_ACL */ return 0; } /* Module Tables */ module facl_module = { /* Always NULL */ NULL, NULL, /* Module API version */ 0x20, /* Module name */ "facl", /* Module configuration directive handlers */ NULL, /* Module command handlers */ NULL, /* Module authentication handlers */ NULL, /* Module initialization */ facl_init, /* Session initialization */ NULL, /* Module version */ MOD_FACL_VERSION };
static int posix_acl_read (MateVFSACL *acl, acl_t p_acl, gboolean def) { acl_entry_t entry; int res; int e_id; int n; if (p_acl == NULL) { return 0; } n = 0; e_id = ACL_FIRST_ENTRY; while ((res = acl_get_entry (p_acl, e_id, &entry)) == 1) { MateVFSACLPerm pset[POSIX_N_TAGS + 1]; MateVFSACLKind kind; MateVFSACE *ace; acl_permset_t e_ps; acl_tag_t e_type; void *e_qf; char *id; e_id = ACL_NEXT_ENTRY; e_type = ACL_UNDEFINED_ID; e_qf = NULL; /* prop = (def) ? MATE_VFS_ACL_DEFAULT : MATE_VFS_ACL_TYPE_NULL; */ /* Read "default" */ res = acl_get_tag_type (entry, &e_type); if (res == -1 || e_type == ACL_UNDEFINED_ID || e_type == ACL_MASK) { continue; } if (def == FALSE && (e_type != ACL_USER && e_type != ACL_GROUP)) { /* skip the standard unix permissions */ continue; } res = acl_get_permset (entry, &e_ps); if (res == -1) { continue; } e_qf = acl_get_qualifier (entry); id = NULL; kind = MATE_VFS_ACL_KIND_NULL; switch (e_type) { case ACL_USER: id = uid_to_string (*(uid_t *) e_qf); /* FALLTHROUGH */ case ACL_USER_OBJ: kind = MATE_VFS_ACL_USER; break; case ACL_GROUP: id = gid_to_string (*(gid_t *) e_qf); /* FALLTHROUGH */ case ACL_GROUP_OBJ: kind = MATE_VFS_ACL_GROUP; break; case ACL_MASK: case ACL_OTHER: kind = MATE_VFS_ACL_OTHER; break; } permset_to_perms (e_ps, pset); ace = mate_vfs_ace_new (kind, id, pset); g_free (id); if (def) { g_object_set (G_OBJECT(ace), "inherit", def, NULL); } mate_vfs_acl_set (acl, ace); g_object_unref (ace); if (e_qf) { acl_free (e_qf); } n++; } return n; }