Example #1
0
/*
 * Create a file system FUID, based on information in the users cred
 */
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
    dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
{
	uint64_t	idx;
	ksid_t		*ksid;
	uint32_t	rid;
	char 		*kdomain;
	const char	*domain;
	uid_t		id;

	VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);

	if (type == ZFS_OWNER)
		id = crgetuid(cr);
	else
		id = crgetgid(cr);

	if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id))
		return ((uint64_t)id);

	ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);

	VERIFY(ksid != NULL);
	rid = ksid_getrid(ksid);
	domain = ksid_getdomain(ksid);

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);

	zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);

	return (FUID_ENCODE(idx, rid));
}
Example #2
0
/*
 * Check to see if id is a groupmember.  If cred
 * has ksid info then sidlist is checked first
 * and if still not found then POSIX groups are checked
 *
 * Will use a straight FUID compare when possible.
 */
boolean_t
zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
{
	ksid_t		*ksid = crgetsid(cr, KSID_GROUP);
	uid_t		gid;

	if (ksid) {
		int 		i;
		ksid_t		*ksid_groups;
		ksidlist_t	*ksidlist = crgetsidlist(cr);
		uint32_t	idx = FUID_INDEX(id);
		uint32_t	rid = FUID_RID(id);

		ASSERT(ksidlist);
		ksid_groups = ksidlist->ksl_sids;

		for (i = 0; i != ksidlist->ksl_nsid; i++) {
			if (idx == 0) {
				if (id != IDMAP_WK_CREATOR_GROUP_GID &&
				    id == ksid_groups[i].ks_id) {
					return (B_TRUE);
				}
			} else {
				char *domain;

				domain = zfs_fuid_find_by_idx(zfsvfs, idx);
				ASSERT(domain != NULL);

				if (strcmp(domain,
				    IDMAP_WK_CREATOR_SID_AUTHORITY) == 0)
					return (B_FALSE);

				if ((strcmp(domain,
				    ksid_groups[i].ks_domain->kd_name) == 0) &&
				    rid == ksid_groups[i].ks_rid)
					return (B_TRUE);
			}
		}
	}

	/*
	 * Not found in ksidlist, check posix groups
	 */
	gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP);
#ifdef __APPLE__
	return (groupmember(gid, (kauth_cred_t)cr));
#else
	return (groupmember(gid, cr));
#endif
}
Example #3
0
/*
 * Create a file system FUID, based on information in the users cred
 *
 * If cred contains KSID_OWNER then it should be used to determine
 * the uid otherwise cred's uid will be used. By default cred's gid
 * is used unless it's an ephemeral ID in which case KSID_GROUP will
 * be used if it exists.
 */
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
    cred_t *cr, zfs_fuid_info_t **fuidp)
{
	uint64_t	idx;
	ksid_t		*ksid;
	uint32_t	rid;
	char 		*kdomain;
	const char	*domain;
	uid_t		id;

	VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);

	ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);

	if (!zfsvfs->z_use_fuids || (ksid == NULL)) {
		id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);

		if (IS_EPHEMERAL(id))
			return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY);

		return ((uint64_t)id);
	}

	/*
	 * ksid is present and FUID is supported
	 */
	id = (type == ZFS_OWNER) ? ksid_getid(ksid) : crgetgid(cr);

	if (!IS_EPHEMERAL(id))
		return ((uint64_t)id);

	if (type == ZFS_GROUP)
		id = ksid_getid(ksid);

	rid = ksid_getrid(ksid);
	domain = ksid_getdomain(ksid);

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);

	zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);

	return (FUID_ENCODE(idx, rid));
}
Example #4
0
/*
 * smb_fsacl_inherit
 *
 * Manufacture the inherited ACL from the given ACL considering
 * the new object type (file/dir) specified by 'is_dir'. The
 * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
 * This function implements Windows inheritance rules explained above.
 *
 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs
 */
acl_t *
smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr)
{
	boolean_t use_default = B_FALSE;
	int num_inheritable = 0;
	int numaces;
	ace_t *dir_zace;
	acl_t *new_zacl;
	ace_t *new_zace;
	ksid_t *owner_sid;
	ksid_t *group_sid;
	uid_t uid;
	gid_t gid;

	owner_sid = crgetsid(cr, KSID_OWNER);
	group_sid = crgetsid(cr, KSID_GROUP);
	ASSERT(owner_sid);
	ASSERT(group_sid);
	uid = owner_sid->ks_id;
	gid = group_sid->ks_id;

	num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir);

	if (num_inheritable == 0) {
		if (which_acl == SMB_DACL_SECINFO) {
			/* No inheritable access ACEs -> default DACL */
			num_inheritable = DEFAULT_DACL_ACENUM;
			use_default = B_TRUE;
		} else {
			return (NULL);
		}
	}

	new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT);
	new_zace = new_zacl->acl_aclp;

	if (use_default) {
		bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
		new_zace->a_who = uid;
		return (new_zacl);
	}

	for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
	    numaces < dir_zacl->acl_cnt;
	    dir_zace++, numaces++) {
		switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
		case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
			/*
			 * Files inherit an effective ACE.
			 *
			 * Dirs inherit an effective ACE.
			 * The inherited ACE is inheritable unless the
			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
			 */
			smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
			new_zace++;

			if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
			    (ZACE_IS_PROPAGATE(dir_zace))) {
				*new_zace = *dir_zace;
				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
				    ACE_INHERITED_ACE);
				new_zace++;
			}
			break;

		case ACE_FILE_INHERIT_ACE:
			/*
			 * Files inherit as an effective ACE.
			 *
			 * Dirs inherit an inherit-only ACE
			 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
			 * flag is also set.
			 */
			if (is_dir == 0) {
				smb_ace_inherit(dir_zace, new_zace, is_dir,
				    uid, gid);
				new_zace++;
			} else if (ZACE_IS_PROPAGATE(dir_zace)) {
				*new_zace = *dir_zace;
				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
				    ACE_INHERITED_ACE);
				new_zace++;
			}
			break;

		case ACE_DIRECTORY_INHERIT_ACE:
			/*
			 * No effect on files
			 *
			 * Dirs inherit an effective ACE.
			 * The inherited ACE is inheritable unless the
			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
			 */
			if (is_dir == 0)
				break;

			smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
			new_zace++;

			if (ZACE_IS_CREATOR(dir_zace) &&
			    (ZACE_IS_PROPAGATE(dir_zace))) {
				*new_zace = *dir_zace;
				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
				    ACE_INHERITED_ACE);
				new_zace++;
			}

			break;

		default:
			break;
		}
	}

	return (new_zacl);
}