示例#1
3
文件: uacl.c 项目: nshrine/jfacl
int setacl(const char *pathp, int size, aclent_t *aclpbuf)
{
	acl_t acl = NULL, default_acl = NULL, *current;
	acl_entry_t entry;
	acl_permset_t permset;
	int i, result, default_count = 0;
	
	struct stat st;
	
	if (stat(pathp, &st) != 0) {
		return -1;
	}
	
	for (i = 0; i < size; i++) {
		if (aclpbuf[i].a_type & ACL_DEFAULT) {
			default_count++;
		}
	}	
	acl = acl_init(size - default_count);
	if (default_count > 0) {
		default_acl = acl_init(default_count);
	}
	
	for (i = 0; i < size; i++) {		
		if (aclpbuf[i].a_type & ACL_DEFAULT) {						
			current = &default_acl;			
		} else {
			current = &acl;			
		}		
		acl_create_entry(current, &entry);		
		acl_get_permset(entry, &permset);		
		setmode(&permset, aclpbuf[i].a_perm);		
		acl_set_tag_type(entry, aclpbuf[i].a_type & ~ACL_DEFAULT);
		acl_set_qualifier(entry, &aclpbuf[i].a_id);
		acl_free(entry);
	}
	
	result = acl_set_file(pathp, ACL_TYPE_ACCESS, acl);
	if (result != 0 && (errno == ENOSYS || errno == ENOTSUP)) {
		if (default_acl != NULL) {
			return result;
		}
		
        mode_t mode;                                                                                                                                                             
        if (acl_equiv_mode(acl, &mode) == 0) {			
			result = chmod(pathp, mode);			
		}
	} else if ((result == 0) && S_ISDIR(st.st_mode)) {
		if (default_acl == NULL) {
			result = acl_delete_def_file(pathp);
		} else {
			result = acl_set_file(pathp, ACL_TYPE_DEFAULT, default_acl);
			acl_free(default_acl);
		}
	}
	acl_free(acl);
	
	return result;
}
示例#2
0
/* Add the perms specified in modifier to rentry */
static int
merge_entry_perms(acl_entry_t rentry, acl_entry_t  modifier)
{
	acl_permset_t rperms, mperms;
	acl_flagset_t rflags, mflags;
	int i;

	if ((acl_get_permset(rentry, &rperms) != 0) ||
	    (acl_get_flagset_np(rentry, &rflags) != 0) ||
	    (acl_get_permset(modifier, &mperms) != 0) ||
        (acl_get_flagset_np(modifier, &mflags) != 0)) {
		// err(1, "error computing ACL modification");
        fprintf(stderr, "chmod: error computing ACL modification: %s\n", strerror(errno));
        pthread_exit(NULL);
    }

	for (i = 0; acl_perms[i].name != NULL; i++) {
		if (acl_get_perm_np(mperms, acl_perms[i].perm))
			acl_add_perm(rperms, acl_perms[i].perm);
	}
	for (i = 0; acl_flags[i].name != NULL; i++) {
		if (acl_get_flag_np(mflags, acl_flags[i].flag))
			acl_add_flag_np(rflags, acl_flags[i].flag);
	}
	acl_set_permset(rentry, rperms);
	acl_set_flagset_np(rentry, rflags);
	return 0;
}
示例#3
0
/* Remove all perms specified in modifier from rentry*/
int
subtract_from_entry(acl_entry_t rentry, acl_entry_t  modifier, int* valid_perms)
{
	acl_permset_t rperms, mperms;
	acl_flagset_t rflags, mflags;
	if (valid_perms)
		*valid_perms = 0;
	int i;

	if ((acl_get_permset(rentry, &rperms) != 0) ||
	    (acl_get_flagset_np(rentry, &rflags) != 0) ||
	    (acl_get_permset(modifier, &mperms) != 0) ||
        (acl_get_flagset_np(modifier, &mflags) != 0)) {
		// err(1, "error computing ACL modification");
        fprintf(stderr, "chmod: error computing ACL modification: %s\n", strerror(errno));
        pthread_exit(NULL);
    }

	for (i = 0; acl_perms[i].name != NULL; i++) {
		if (acl_get_perm_np(mperms, acl_perms[i].perm))
			acl_delete_perm(rperms, acl_perms[i].perm);
		else if (valid_perms && acl_get_perm_np(rperms, acl_perms[i].perm)) 
			(*valid_perms)++;
	}
	for (i = 0; acl_flags[i].name != NULL; i++) {
		if (acl_get_flag_np(mflags, acl_flags[i].flag))
			acl_delete_flag_np(rflags, acl_flags[i].flag);
	}
	acl_set_permset(rentry, rperms);
	acl_set_flagset_np(rentry, rflags);
	return 0;
}
示例#4
0
/* Add the perms specified in modifier to rentry */
static int
merge_entry_perms(acl_entry_t rentry, acl_entry_t  modifier)
{
	acl_permset_t rperms, mperms;
	acl_flagset_t rflags, mflags;
	int i;

	if ((acl_get_permset(rentry, &rperms) != 0) ||
	    (acl_get_flagset_np(rentry, &rflags) != 0) ||
	    (acl_get_permset(modifier, &mperms) != 0) ||
	    (acl_get_flagset_np(modifier, &mflags) != 0))
		err(1, "error computing ACL modification");

	for (i = 0; acl_perms[i].name != NULL; i++) {
		if (acl_get_perm_np(mperms, acl_perms[i].perm))
			acl_add_perm(rperms, acl_perms[i].perm);
	}
	for (i = 0; acl_flags[i].name != NULL; i++) {
		if (acl_get_flag_np(mflags, acl_flags[i].flag))
			acl_add_flag_np(rflags, acl_flags[i].flag);
	}
	acl_set_permset(rentry, rperms);
	acl_set_flagset_np(rentry, rflags);
	return 0;
}
示例#5
0
static int
remove_extended_entries(
	acl_t acl)
{
	acl_entry_t ent, group_obj;
	acl_permset_t mask_permset, group_obj_permset;
	acl_tag_t tag;
	int error;
	
	/*
	 * Removing the ACL_MASK entry from the ACL results in
	 * increased permissions for the owning group if the
	 * ACL_GROUP_OBJ entry contains permissions not contained
	 * in the ACL_MASK entry. We remove these permissions from
	 * the ACL_GROUP_OBJ entry to avoid that.
	 *
	 * After removing the ACL, the file owner and the owning group
	 * therefore have the same permissions as before.
	 */

	ent = find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID);
	group_obj = find_entry(acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID);
	if (ent && group_obj) {
		if (!acl_get_permset(ent, &mask_permset) &&
		    !acl_get_permset(group_obj, &group_obj_permset)) {
			if (!acl_get_perm(mask_permset, ACL_READ))
				acl_delete_perm(group_obj_permset, ACL_READ);
			if (!acl_get_perm(mask_permset, ACL_WRITE))
				acl_delete_perm(group_obj_permset, ACL_WRITE);
			if (!acl_get_perm(mask_permset, ACL_EXECUTE))
				acl_delete_perm(group_obj_permset, ACL_EXECUTE);
		}
	}

	error = acl_get_entry(acl, ACL_FIRST_ENTRY, &ent);
	while (error == 1) {
		acl_get_tag_type(ent, &tag);
		switch(tag) {
			case ACL_USER:
			case ACL_GROUP:
			case ACL_MASK:
				acl_delete_entry(acl, ent);
				break;
			default:
				break;
		}
	
		error = acl_get_entry(acl, ACL_NEXT_ENTRY, &ent);
	}
	if (error < 0)
		return -1;
	return 0;
}
示例#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);
}
acl_entry_get_perm(acl_entry_t aclent)
#endif
{
	int permset = 0;
#if HAVE_POSIX_ACL
	acl_permset_t opaque_ps;
#endif

#if HAVE_SUN_ACL
	if (aclent->a_perm & 1)
		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
	if (aclent->a_perm & 2)
		permset |= ARCHIVE_ENTRY_ACL_WRITE;
	if (aclent->a_perm & 4)
		permset |= ARCHIVE_ENTRY_ACL_READ;
#else
	/* translate the silly opaque permset to a bitmap */
	acl_get_permset(aclent, &opaque_ps);
	if (ACL_GET_PERM(opaque_ps, ACL_EXECUTE))
		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
	if (ACL_GET_PERM(opaque_ps, ACL_WRITE))
		permset |= ARCHIVE_ENTRY_ACL_WRITE;
	if (ACL_GET_PERM(opaque_ps, ACL_READ))
		permset |= ARCHIVE_ENTRY_ACL_READ;
#endif
	return permset;
}
示例#8
0
static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
{
        int ret;
        acl_permset_t permset;

	if ((ret = acl_get_permset(entry, &permset)) != 0) {
		return ret;
	}
        if ((ret = acl_clear_perms(permset)) != 0) {
                return ret;
	}
        if ((perm & SMB_ACL_READ) &&
	    ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
		return ret;
	}
        if ((perm & SMB_ACL_WRITE) &&
	    ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
		return ret;
	}
        if ((perm & SMB_ACL_EXECUTE) &&
	    ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
		return ret;
	}
        return acl_set_permset(entry, permset);
}
示例#9
0
/**
* removes entry in ptr from acl
* acl: ptr to acl to modify
* entry: ptr to entry to remove
* returns: status
**/
_BOOL acl_remove(acl_t * acl, acl_entry_t *entry,acl_entry_in *entry_in){
  if(acl==NULL || entry==NULL){errno = EINVAL; return FALSE;}

  #ifdef POSIXLY_CORRECT
  if(entry_in->no_perm){
    errno = EINVAL;
    return FALSE;
  }
  acl_permset_t permset;
  if(acl_get_permset(*entry,&permset)!=ACL_OK)
    return FALSE;
  int verify_bits = 0;
  verify_bits += ((entry_in->permset.nibble)&READ&&acl_get_perm(permset,ACL_READ)|| !(entry_in->permset.nibble&READ)) ? 1 : 0;
  verify_bits += ((entry_in->permset.nibble&WRITE)&&acl_get_perm(permset,ACL_WRITE)|| !(entry_in->permset.nibble&WRITE)) ? 1 : 0;
  verify_bits += ((entry_in->permset.nibble&EXEC)&&acl_get_perm(permset,ACL_EXECUTE)|| !(entry_in->permset.nibble&EXEC)) ? 1 : 0;
  if(verify_bits!=VERIFIED_BITS){errno = EINVAL; return FALSE;}
  #else
  if(!entry_in->no_perm){
    errno = EINVAL;
    return FALSE;
  }
  #endif

  if(acl_delete_entry(*acl,*entry)!=ACL_OK)
    return FALSE;

  return TRUE;

}
/*
 * 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);
}
示例#12
0
void acl_perm_str(acl_entry_t entry, char *str)
{
	acl_permset_t permset;
	int n;

	acl_get_permset(entry, &permset);
	for (n = 0; n < (int) ACL_PERMS; n++) {
		str[n] = (acl_get_perm(permset, acl_perm_defs[n].tag) ?
		          acl_perm_defs[n].c : '-');
	}
	str[n] = '\0';
}
示例#13
0
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);
}
示例#14
0
文件: uacl.c 项目: nshrine/jfacl
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;
}
示例#15
0
int
score_acl_entry(acl_entry_t entry) {

	acl_tag_t	tag;
	acl_flagset_t	flags;
	acl_permset_t	perms;
	
	int score = 0;

	if (entry == NULL)
		return (MINIMUM_TIER);

	if (acl_get_tag_type(entry, &tag) != 0) {
		// err(1, "Malformed ACL entry, no tag present");
        fprintf(stderr, "chmod: Malformed ACL entry, no tag present: %s\n", strerror(errno));
        pthread_exit(NULL);
	}
	if (acl_get_flagset_np(entry, &flags) != 0){
		// err(1, "Unable to obtain flagset");
        fprintf(stderr, "chmod: Unable to obtain flagset: %s\n", strerror(errno));
        pthread_exit(NULL);
	}
    if (acl_get_permset(entry, &perms) != 0) {
		// err(1, "Malformed ACL entry, no permt present");
        fprintf(stderr, "chmod: Malformed ACL entry, no permt present: %s\n", strerror(errno));
        pthread_exit(NULL);
    }
	
	switch(tag) {
	case ACL_EXTENDED_ALLOW:
		break;
	case ACL_EXTENDED_DENY:
		score++;
		break;
	default:
		// errx(1, "Unknown tag type %d present in ACL entry", tag);
        fprintf(stderr, "chmod: Unknown tag type %d present in ACL entry\n", tag);
        pthread_exit(NULL);
	        /* NOTREACHED */
	}

	if (acl_get_flag_np(flags, ACL_ENTRY_INHERITED))
		score += get_inheritance_level(entry) * INHERITANCE_TIER;

	return score;
}
示例#16
0
static int fix_acl(int fd, uid_t uid) {

#ifdef HAVE_ACL
        _cleanup_(acl_freep) acl_t acl = NULL;
        acl_entry_t entry;
        acl_permset_t permset;

        assert(fd >= 0);

        if (uid <= SYSTEM_UID_MAX)
                return 0;

        /* Make sure normal users can read (but not write or delete)
         * their own coredumps */

        acl = acl_get_fd(fd);
        if (!acl) {
                log_error("Failed to get ACL: %m");
                return -errno;
        }

        if (acl_create_entry(&acl, &entry) < 0 ||
            acl_set_tag_type(entry, ACL_USER) < 0 ||
            acl_set_qualifier(entry, &uid) < 0) {
                log_error("Failed to patch ACL: %m");
                return -errno;
        }

        if (acl_get_permset(entry, &permset) < 0 ||
            acl_add_perm(permset, ACL_READ) < 0 ||
            calc_acl_mask_if_needed(&acl) < 0) {
                log_warning("Failed to patch ACL: %m");
                return -errno;
        }

        if (acl_set_fd(fd, acl) < 0) {
                log_error("Failed to apply ACL: %m");
                return -errno;
        }
#endif

        return 0;
}
示例#17
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);
}
示例#18
0
/**
* update a perm_set_t in entry to the one in aclentry
* entry: acl entry to change from in-memory
* acl_entry: where to retrieve new perms from
* returns status
**/
static _BOOL acl_update_perm(acl_entry_t *entry,acl_entry_in *entry_in){

  if(entry_in == NULL) return;

  acl_permset_t perm_set;
  if(acl_get_permset(*entry,&perm_set)!=ACL_OK)
    return FALSE;


  if(((entry_in->permset.nibble&READ) ? acl_add_perm(perm_set,ACL_READ)   : acl_delete_perm(perm_set,ACL_READ))!=ACL_OK)
    return FALSE;
  if(((entry_in->permset.nibble&WRITE)? acl_add_perm(perm_set,ACL_WRITE)  : acl_delete_perm(perm_set,ACL_WRITE))!=ACL_OK)
    return FALSE;
  if(((entry_in->permset.nibble&EXEC) ? acl_add_perm(perm_set,ACL_EXECUTE): acl_delete_perm(perm_set,ACL_EXECUTE))!=ACL_OK)
    return FALSE;

  if(acl_set_permset(*entry,perm_set)!=ACL_OK)
    return FALSE;
  return TRUE;
}
示例#19
0
int
has_execute_perms(
	acl_t acl)
{
	acl_entry_t ent;

	if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
		return 0;

	for(;;) {
		acl_permset_t permset;

		acl_get_permset(ent, &permset);
		if (acl_get_perm(permset, ACL_EXECUTE) != 0)
			return 1;

		if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
			return 0;
	}
}
示例#20
0
static int fix_acl(int fd, uid_t uid) {

#if HAVE_ACL
        _cleanup_(acl_freep) acl_t acl = NULL;
        acl_entry_t entry;
        acl_permset_t permset;
        int r;

        assert(fd >= 0);

        if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
                return 0;

        /* Make sure normal users can read (but not write or delete)
         * their own coredumps */

        acl = acl_get_fd(fd);
        if (!acl)
                return log_error_errno(errno, "Failed to get ACL: %m");

        if (acl_create_entry(&acl, &entry) < 0 ||
            acl_set_tag_type(entry, ACL_USER) < 0 ||
            acl_set_qualifier(entry, &uid) < 0)
                return log_error_errno(errno, "Failed to patch ACL: %m");

        if (acl_get_permset(entry, &permset) < 0 ||
            acl_add_perm(permset, ACL_READ) < 0)
                return log_warning_errno(errno, "Failed to patch ACL: %m");

        r = calc_acl_mask_if_needed(&acl);
        if (r < 0)
                return log_warning_errno(r, "Failed to patch ACL: %m");

        if (acl_set_fd(fd, acl) < 0)
                return log_error_errno(errno, "Failed to apply ACL: %m");
#endif

        return 0;
}
示例#21
0
文件: winacl.c 项目: Arcko/freenas
/* merge two acl entries together */
static int
merge_acl_entries(acl_entry_t *entry1, acl_entry_t *entry2)
{
	acl_permset_t permset;
	acl_entry_type_t entry_type;
	acl_flagset_t flagset;

	if (acl_get_permset(*entry1, &permset) < 0)
		err(EX_OSERR, "acl_get_permset() failed");
	if (acl_set_permset(*entry2, permset) < 0)
		err(EX_OSERR, "acl_set_permset() failed");
	if (acl_get_entry_type_np(*entry1, &entry_type) < 0)
		err(EX_OSERR, "acl_get_entry_type_np() failed");
	if (acl_set_entry_type_np(*entry2, entry_type) < 0)
		err(EX_OSERR, "acl_set_entry_type_np() failed");
	if (acl_get_flagset_np(*entry1, &flagset) < 0)
		err(EX_OSERR, "acl_get_flagset_np() failed");
	if (acl_set_flagset_np(*entry2, flagset) < 0)
		err(EX_OSERR, "acl_set_flagset_np() failed");

	return (0);
}
示例#22
0
static void
set_perm(
	acl_entry_t ent,
	mode_t add,
	mode_t remove)
{
	acl_permset_t set;

	acl_get_permset(ent, &set);
	if (remove & CMD_PERM_READ)
		acl_delete_perm(set, ACL_READ);
	if (remove & CMD_PERM_WRITE)
		acl_delete_perm(set, ACL_WRITE);
	if (remove & CMD_PERM_EXECUTE)
		acl_delete_perm(set, ACL_EXECUTE);
	if (add & CMD_PERM_READ)
		acl_add_perm(set, ACL_READ);
	if (add & CMD_PERM_WRITE)
		acl_add_perm(set, ACL_WRITE);
	if (add & CMD_PERM_EXECUTE)
		acl_add_perm(set, ACL_EXECUTE);
}
示例#23
0
static void
setPerms(acl_entry_t entry, int perms)
{
    acl_permset_t permset;

    if (acl_get_permset(entry, &permset) == -1)
        errExit("acl_get_permset");

    if (acl_clear_perms(permset) == -1)
        errExit("acl_clear_perms");

    if (perms & ACL_READ)
        if (acl_add_perm(permset, ACL_READ) == -1)
            errExit("acl_add_perm");
    if (perms & ACL_WRITE)
        if (acl_add_perm(permset, ACL_WRITE) == -1)
            errExit("acl_add_perm");
    if (perms & ACL_EXECUTE)
        if (acl_add_perm(permset, ACL_EXECUTE) == -1)
            errExit("acl_add_perm");

    if (acl_set_permset(entry, permset) == -1)
        errExit("acl_set_permset");
}
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);
}
示例#25
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);
}
示例#26
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);
}
示例#27
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;
}
示例#28
0
acl_t
pfl_acl_from_xattr(const void *buf, size_t size)
{
	int i, entries;
	const struct acl_ea_header *h = buf;
	const struct acl_ea_entry *xe = PSC_AGP(h + 1, 0);
	unsigned int xperms;
	acl_permset_t permset;
	acl_entry_t e;
	acl_tag_t tag;
	acl_t a;

	if (size < sizeof(*h)) {
		errno = EINVAL;
		return (NULL);
	}
	if (le32toh(h->version) != ACL_EA_VERSION) {
		errno = EINVAL;
		return (NULL);
	}
	size -= sizeof(*h);
	if (size % sizeof(*xe)) {
		errno = EINVAL;
		return (NULL);
	}
	entries = size / sizeof(*xe);

	a = acl_init(entries);
	if (a == NULL)
		return (NULL);
	for (i = 0; i < entries; i++, xe++) {
		acl_create_entry(&a, &e);
		if (acl_get_permset(e, &permset) == -1)
			psclog_error("get_permset");
		acl_clear_perms(permset);

		xperms = le16toh(xe->perm);

		if (xperms & ACL_READ)
			acl_add_perm(permset, ACL_READ);
		if (xperms & ACL_WRITE)
			acl_add_perm(permset, ACL_WRITE);
		if (xperms & ACL_EXECUTE)
			acl_add_perm(permset, ACL_EXECUTE);
		if (acl_set_permset(e, permset) == -1)
			psclog_error("set_permset");

		acl_set_tag_type(e, tag = le16toh(xe->tag));

		switch (tag) {
		case ACL_USER: {
			uid_t uid = le32toh(xe->id);

			acl_set_qualifier(e, &uid);
			break;
		    }
		case ACL_GROUP: {
			gid_t gid = le32toh(xe->id);

			acl_set_qualifier(e, &gid);
			break;
		    }
		}
	}
	return (a);
}
示例#29
0
文件: mod_facl.c 项目: OPSF/uClinux
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
};
示例#30
0
文件: remove.c 项目: genua/anoubis_os
/*
 * remove extended entries
 */
void
remove_ext(acl_t *prev_acl)
{
	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;

	if (acl_type == ACL_TYPE_ACCESS)
		acl_old = acl_dup(prev_acl[ACCESS_ACL]);
	else
		acl_old = acl_dup(prev_acl[DEFAULT_ACL]);

	if (acl_old == NULL)
		err(1, "acl_dup() failed");

	have_mask_entry = 0;
	acl_new = acl_init(ACL_MAX_ENTRIES);
	if (acl_new == NULL)
		err(1, "acl_init() failed");

	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;

		if (acl_get_tag_type(entry, &tag) == -1)
			err(1, "acl_get_tag_type() failed");

		switch(tag) {
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_OTHER:
			if (acl_get_tag_type(entry, &tag) == -1)
				err(1, "acl_get_tag_type() failed");
			if (acl_get_permset(entry, &perm) == -1)
				err(1, "acl_get_permset() failed");
			if (acl_create_entry(&acl_new, &entry_new) == -1)
				err(1, "acl_create_entry() failed");
			if (acl_set_tag_type(entry_new, tag) == -1)
				err(1, "acl_set_tag_type() failed");
			if (acl_set_permset(entry_new, perm) == -1)
				err(1, "acl_get_permset() failed");
			if (acl_copy_entry(entry_new, entry) == -1)
				err(1, "acl_copy_entry() failed");
			break;
		case ACL_MASK:
			have_mask_entry = 1;
			break;
		default:
			break;
		}
	}
	if (have_mask_entry && n_flag == 0) {
		if (acl_calc_mask(&acl_new) == -1)
			err(1, "acl_calc_mask() failed");
	} else {
		have_mask = 1;
	}

	if (acl_type == ACL_TYPE_ACCESS) {
		acl_free(prev_acl[ACCESS_ACL]);
		prev_acl[ACCESS_ACL] = acl_new;
	} else {
		acl_free(prev_acl[DEFAULT_ACL]);
		prev_acl[DEFAULT_ACL] = acl_new;
	}
}