Exemple #1
0
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);
}
Exemple #4
0
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);
}
Exemple #6
0
/* 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;
        }
}
Exemple #8
0
/**
* 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;

}
Exemple #9
0
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);
}
Exemple #10
0
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;
}
Exemple #12
0
/* 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);
}
Exemple #13
0
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;
}
Exemple #14
0
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);
}
Exemple #16
0
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);
}
Exemple #17
0
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;
}
Exemple #18
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;
}
Exemple #19
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;
}
Exemple #20
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);
}
Exemple #21
0
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;
}
Exemple #22
0
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;
}
Exemple #23
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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);
}
Exemple #28
0
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;
}
Exemple #29
0
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;
}