Beispiel #1
0
/*
 * Return 0, if both ACLs are identical.
 */
int
_acl_differs(const acl_t a, const acl_t b)
{
    int i;
    struct acl_entry *entrya, *entryb;

    assert(_acl_brand(a) == _acl_brand(b));
    assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
    assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);

    if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
        return (1);

    for (i = 0; i < b->ats_acl.acl_cnt; i++) {
        entrya = &(a->ats_acl.acl_entry[i]);
        entryb = &(b->ats_acl.acl_entry[i]);

        if (entrya->ae_tag != entryb->ae_tag ||
                entrya->ae_id != entryb->ae_id ||
                entrya->ae_perm != entryb->ae_perm ||
                entrya->ae_entry_type != entryb->ae_entry_type ||
                entrya->ae_flags != entryb->ae_flags)
            return (1);
    }

    return (0);
}
Beispiel #2
0
/*
 * Return 1, iff branding ACL as "brand" is ok.
 */
int
_acl_brand_may_be(const acl_t acl, int brand)
{

	if (_acl_brand(acl) == ACL_BRAND_UNKNOWN)
		return (1);

	if (_acl_brand(acl) == brand)
		return (1);

	return (0);
}
Beispiel #3
0
/*
 * acl_posix1e -- in what situations should we acl_sort before submission?
 * We apply posix1e ACL semantics for any ACL of type ACL_TYPE_ACCESS or
 * ACL_TYPE_DEFAULT
 */
int
_posix1e_acl(acl_t acl, acl_type_t type)
{

    if (_acl_brand(acl) != ACL_BRAND_POSIX)
        return (0);

    return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
}
Beispiel #4
0
int
acl_get_brand_np(acl_t acl, int *brand_p)
{

	if (acl == NULL || brand_p == NULL) {
		errno = EINVAL;
		return (-1);
	}
	*brand_p = _acl_brand(acl);

	return (0);
}
Beispiel #5
0
/*
 * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
 * from acl.
 */
int
acl_delete_entry(acl_t acl, acl_entry_t entry_d)
{
	struct acl *acl_int;
	struct acl_entry entry_int;
	int i, j, found = 0;

	if (acl == NULL || entry_d == NULL) {
		errno = EINVAL;
		return (-1);
	}

	acl_int = &acl->ats_acl;

	if (_entry_brand(entry_d) != _acl_brand(acl)) {
		errno = EINVAL;
		return (-1);
	}

	if ((acl->ats_acl.acl_cnt < 1) ||
	    (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
		errno = EINVAL;
		return (-1);
	}

	/* Use a local copy to prevent deletion of more than this entry */
	entry_int = *entry_d;

	for (i = 0; i < acl->ats_acl.acl_cnt;) {
		if (_entry_matches(&(acl->ats_acl.acl_entry[i]), &entry_int)) {
			/* ...shift the remaining entries... */
			for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
				acl->ats_acl.acl_entry[j] =
				    acl->ats_acl.acl_entry[j+1];
			/* ...drop the count and zero the unused entry... */
			acl->ats_acl.acl_cnt--;
			bzero(&acl->ats_acl.acl_entry[j],
			    sizeof(struct acl_entry));
			acl->ats_cur_entry = 0;
			
			/* Continue with the loop to remove all maching entries. */
			found = 1;
		} else
			i++;
	}

	if (found)
		return (0);

	errno = EINVAL;
	return (-1);
}
Beispiel #6
0
acl_t
acl_strip_np(const acl_t aclp, int recalculate_mask)
{
	switch (_acl_brand(aclp)) {
	case ACL_BRAND_NFS4:
		return (_nfs4_acl_strip_np(aclp, 0));

	case ACL_BRAND_POSIX:
		return (_posix1e_acl_strip_np(aclp, recalculate_mask));

	default:
		errno = EINVAL;
		return (NULL);
	}
}
Beispiel #7
0
char *
acl_to_text_np(acl_t acl, ssize_t *len_p, int flags)
{

    if (acl == NULL) {
        errno = EINVAL;
        return(NULL);
    }

    switch (_acl_brand(acl)) {
    case ACL_BRAND_POSIX:
        return (_posix1e_acl_to_text(acl, len_p, flags));
    case ACL_BRAND_NFS4:
        return (_nfs4_acl_to_text_np(acl, len_p, flags));
    default:
        errno = EINVAL;
        return (NULL);
    }
}
Beispiel #8
0
int
_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type)
{

	switch (_acl_brand(acl)) {
	case ACL_BRAND_NFS4:
		if (type == ACL_TYPE_NFS4)
			return (0);
		break;

	case ACL_BRAND_POSIX:
		if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT)
			return (0);
		break;

	case ACL_BRAND_UNKNOWN:
		return (0);
	}

	return (-1);
}
Beispiel #9
0
static int
_posix1e_acl_entry_from_text(acl_t aclp, char *entry)
{
	acl_tag_t	 t;
	acl_perm_t	 p;
	char		*tag, *qualifier, *permission;
	uid_t		 id;
	int		 error;

	assert(_acl_brand(aclp) == ACL_BRAND_POSIX);

	/* Split into three ':' delimited fields. */
	tag = strsep(&entry, ":");
	if (tag == NULL) {
		errno = EINVAL;
		return (-1);
	}
	tag = string_skip_whitespace(tag);
	if ((*tag == '\0') && (!entry)) {
		/*
		 * Is an entirely comment line, skip to next
		 * comma.
		 */
		return (0);
	}
	string_trim_trailing_whitespace(tag);

	qualifier = strsep(&entry, ":");
	if (qualifier == NULL) {
		errno = EINVAL;
		return (-1);
	}
	qualifier = string_skip_whitespace(qualifier);
	string_trim_trailing_whitespace(qualifier);

	permission = strsep(&entry, ":");
	if (permission == NULL || entry) {
		errno = EINVAL;
		return (-1);
	}
	permission = string_skip_whitespace(permission);
	string_trim_trailing_whitespace(permission);

	t = acl_string_to_tag(tag, qualifier);
	if (t == -1) {
		errno = EINVAL;
		return (-1);
	}

	error = _posix1e_acl_string_to_perm(permission, &p);
	if (error == -1) {
		errno = EINVAL;
		return (-1);
	}		

	switch(t) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_MASK:
		case ACL_OTHER:
			if (*qualifier != '\0') {
				errno = EINVAL;
				return (-1);
			}
			id = 0;
			break;

		case ACL_USER:
		case ACL_GROUP:
			error = _acl_name_to_id(t, qualifier, &id);
			if (error == -1)
				return (-1);
			break;

		default:
			errno = EINVAL;
			return (-1);
	}

	error = _posix1e_acl_add_entry(aclp, t, id, p);
	if (error == -1)
		return (-1);

	return (0);
}
Beispiel #10
0
/*
 * acl_from_text -- Convert a string into an ACL.
 * Postpone most validity checking until the end and call acl_valid() to do
 * that.
 */
acl_t
acl_from_text(const char *buf_p)
{
	acl_t		 acl;
	char		*mybuf_p, *line, *cur, *notcomment, *comment, *entry;
	int		 error;

	/* Local copy we can mess up. */
	mybuf_p = strdup(buf_p);
	if (mybuf_p == NULL)
		return(NULL);

	acl = acl_init(3); /* XXX: WTF, 3? */
	if (acl == NULL) {
		free(mybuf_p);
		return(NULL);
	}

	/* Outer loop: delimit at \n boundaries. */
	cur = mybuf_p;
	while ((line = strsep(&cur, "\n"))) {
		/* Now split the line on the first # to strip out comments. */
		comment = line;
		notcomment = strsep(&comment, "#");

		/* Inner loop: delimit at ',' boundaries. */
		while ((entry = strsep(&notcomment, ","))) {

			/* Skip empty lines. */
			if (strlen(string_skip_whitespace(entry)) == 0)
				continue;

			if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
				if (_text_is_nfs4_entry(entry))
					_acl_brand_as(acl, ACL_BRAND_NFS4);
				else
					_acl_brand_as(acl, ACL_BRAND_POSIX);
			}

			switch (_acl_brand(acl)) {
			case ACL_BRAND_NFS4:
				error = _nfs4_acl_entry_from_text(acl, entry);
				break;

			case ACL_BRAND_POSIX:
				error = _posix1e_acl_entry_from_text(acl, entry);
				break;

			default:
				error = EINVAL;
				break;
			}

			if (error)
				goto error_label;
		}
	}

#if 0
	/* XXX Should we only return ACLs valid according to acl_valid? */
	/* Verify validity of the ACL we read in. */
	if (acl_valid(acl) == -1) {
		errno = EINVAL;
		goto error_label;
	}
#endif

	free(mybuf_p);
	return(acl);

error_label:
	acl_free(acl);
	free(mybuf_p);
	return(NULL);
}
Beispiel #11
0
static acl_t
_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
{
	acl_t acl_new, acl_old;
	acl_entry_t entry, entry_new;
	acl_permset_t perm;
	acl_tag_t tag;
	int entry_id, have_mask_entry;

	assert(_acl_brand(aclp) == ACL_BRAND_POSIX);

	acl_old = acl_dup(aclp);
	if (acl_old == NULL)
		return (NULL);

	assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);

	have_mask_entry = 0;
	acl_new = acl_init(ACL_MAX_ENTRIES);
	if (acl_new == NULL)
		return (NULL);
	tag = ACL_UNDEFINED_TAG;

	/* only save the default user/group/other entries */
	entry_id = ACL_FIRST_ENTRY;
	while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
		entry_id = ACL_NEXT_ENTRY;

		assert(_entry_brand(entry) == ACL_BRAND_POSIX);

		if (acl_get_tag_type(entry, &tag) == -1)
			return (NULL);

		switch(tag) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_OTHER:
			if (acl_get_tag_type(entry, &tag) == -1)
				return (NULL);
			if (acl_get_permset(entry, &perm) == -1)
				return (NULL);
			if (acl_create_entry(&acl_new, &entry_new) == -1)
				return (NULL);
			if (acl_set_tag_type(entry_new, tag) == -1)
				return (NULL);
			if (acl_set_permset(entry_new, perm) == -1)
				return (NULL);
			if (acl_copy_entry(entry_new, entry) == -1)
				return (NULL);
			assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
			break;
		case ACL_MASK:
			have_mask_entry = 1;
			break;
		default:
			break;
		}
	}

	assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);

	if (have_mask_entry && recalculate_mask) {
		if (acl_calc_mask(&acl_new) == -1)
			return (NULL);
	}

	return (acl_new);
}
Beispiel #12
0
/*
 * Return 1, if ACL is trivial, 0 otherwise.
 *
 * ACL is trivial, iff its meaning could be fully expressed using just file
 * mode.  In other words, ACL is trivial iff it doesn't have "+" to the right
 * of the mode bits in "ls -l" output ;-)
 */
int
acl_is_trivial_np(const acl_t aclp, int *trivialp)
{
	acl_t tmpacl;
	int differs;

	if (aclp == NULL || trivialp == NULL) {
		errno = EINVAL;
		return (-1);
	}

	switch (_acl_brand(aclp)) {
	case ACL_BRAND_POSIX:
		if (aclp->ats_acl.acl_cnt == 3)
			*trivialp = 1;
		else
			*trivialp = 0;

		return (0);

	case ACL_BRAND_NFS4:
		/*
		 * If the ACL has more than canonical six entries,
		 * it's non trivial by definition.
		 */
		if (aclp->ats_acl.acl_cnt > 6) {
			*trivialp = 0;
			return (0);
		}
			
		/*
		 * Calculate trivial ACL - using acl_strip_np(3) - and compare
		 * with the original.
		 */
		tmpacl = _nfs4_acl_strip_np(aclp, 0);
		if (tmpacl == NULL)
			return (-1);

		differs = _acl_differs(aclp, tmpacl);
		acl_free(tmpacl);

		if (differs == 0) {
			*trivialp = 1;
			return (0);
		}

		/*
		 * Try again with an old-style, "canonical six" trivial ACL.
		 */
		tmpacl = _nfs4_acl_strip_np(aclp, 1);
		if (tmpacl == NULL)
			return (-1);

		differs = _acl_differs(aclp, tmpacl);
		acl_free(tmpacl);

		if (differs)
			*trivialp = 0;
		else
			*trivialp = 1;

		return (0);

	default:
		errno = EINVAL;
		return (-1);
	}
}
Beispiel #13
0
int
_entry_brand(const acl_entry_t entry)
{

	return (_acl_brand(entry2acl(entry)));
}