/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
 * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
 */

#include <sys/zfs_context.h>

#if defined(_KERNEL)
#include <sys/sunddi.h>
#include <sys/ctype.h>
#else
#include <stdio.h>
#include <unistd.h>
#include <libnvpair.h>
#include <ctype.h>
#endif
#include <sys/strings.h>
#include <sys/dsl_deleg.h>
#include "zfs_prop.h"
#include "zfs_deleg.h"
#include "zfs_namecheck.h"

zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = {
	{ZFS_DELEG_PERM_ALLOW},
	{ZFS_DELEG_PERM_BOOKMARK},
	{ZFS_DELEG_PERM_CLONE},
	{ZFS_DELEG_PERM_CREATE},
	{ZFS_DELEG_PERM_DESTROY},
	{ZFS_DELEG_PERM_DIFF},
	{ZFS_DELEG_PERM_MOUNT},
	{ZFS_DELEG_PERM_PROMOTE},
	{ZFS_DELEG_PERM_RECEIVE},
	{ZFS_DELEG_PERM_REMAP},
	{ZFS_DELEG_PERM_RENAME},
	{ZFS_DELEG_PERM_ROLLBACK},
	{ZFS_DELEG_PERM_SNAPSHOT},
	{ZFS_DELEG_PERM_SHARE},
	{ZFS_DELEG_PERM_SEND},
	{ZFS_DELEG_PERM_USERPROP},
	{ZFS_DELEG_PERM_USERQUOTA},
	{ZFS_DELEG_PERM_GROUPQUOTA},
	{ZFS_DELEG_PERM_USERUSED},
	{ZFS_DELEG_PERM_GROUPUSED},
	{ZFS_DELEG_PERM_USEROBJQUOTA},
	{ZFS_DELEG_PERM_GROUPOBJQUOTA},
	{ZFS_DELEG_PERM_USEROBJUSED},
	{ZFS_DELEG_PERM_GROUPOBJUSED},
	{ZFS_DELEG_PERM_HOLD},
	{ZFS_DELEG_PERM_RELEASE},
	{ZFS_DELEG_PERM_LOAD_KEY},
	{ZFS_DELEG_PERM_CHANGE_KEY},
	{ZFS_DELEG_PERM_PROJECTUSED},
	{ZFS_DELEG_PERM_PROJECTQUOTA},
	{ZFS_DELEG_PERM_PROJECTOBJUSED},
	{ZFS_DELEG_PERM_PROJECTOBJQUOTA},
	{NULL}
};

static int
zfs_valid_permission_name(const char *perm)
{
	if (zfs_deleg_canonicalize_perm(perm))
		return (0);

	return (permset_namecheck(perm, NULL, NULL));
}

const char *
zfs_deleg_canonicalize_perm(const char *perm)
{
	int i;
	zfs_prop_t prop;

	for (i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) {
		if (strcmp(perm, zfs_deleg_perm_tab[i].z_perm) == 0)
			return (perm);
	}

	prop = zfs_name_to_prop(perm);
	if (prop != ZPROP_INVAL && zfs_prop_delegatable(prop))
		return (zfs_prop_to_name(prop));
	return (NULL);

}

static int
zfs_validate_who(char *who)
{
	char *p;

	if (who[2] != ZFS_DELEG_FIELD_SEP_CHR)
		return (-1);

	switch (who[0]) {
	case ZFS_DELEG_USER:
	case ZFS_DELEG_GROUP:
	case ZFS_DELEG_USER_SETS:
	case ZFS_DELEG_GROUP_SETS:
		if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT)
			return (-1);
		for (p = &who[3]; *p; p++)
			if (!isdigit(*p))
				return (-1);
		break;

	case ZFS_DELEG_NAMED_SET:
	case ZFS_DELEG_NAMED_SET_SETS:
		if (who[1] != ZFS_DELEG_NA)
			return (-1);
		return (permset_namecheck(&who[3], NULL, NULL));

	case ZFS_DELEG_CREATE:
	case ZFS_DELEG_CREATE_SETS:
		if (who[1] != ZFS_DELEG_NA)
			return (-1);
		if (who[3] != '\0')
			return (-1);
		break;

	case ZFS_DELEG_EVERYONE:
	case ZFS_DELEG_EVERYONE_SETS:
		if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT)
			return (-1);
		if (who[3] != '\0')
			return (-1);
		break;

	default:
		return (-1);
	}

	return (0);
}

int
zfs_deleg_verify_nvlist(nvlist_t *nvp)
{
	nvpair_t *who, *perm_name;
	nvlist_t *perms;
	int error;

	if (nvp == NULL)
		return (-1);

	who = nvlist_next_nvpair(nvp, NULL);
	if (who == NULL)
		return (-1);

	do {
		if (zfs_validate_who(nvpair_name(who)))
			return (-1);

		error = nvlist_lookup_nvlist(nvp, nvpair_name(who), &perms);

		if (error && error != ENOENT)
			return (-1);
		if (error == ENOENT)
			continue;

		perm_name = nvlist_next_nvpair(perms, NULL);
		if (perm_name == NULL) {
			return (-1);
		}
		do {
			error = zfs_valid_permission_name(
			    nvpair_name(perm_name));
			if (error)
				return (-1);
		} while ((perm_name = nvlist_next_nvpair(perms, perm_name))
		    != NULL);
	} while ((who = nvlist_next_nvpair(nvp, who)) != NULL);
	return (0);
}

/*
 * Construct the base attribute name.  The base attribute names
 * are the "key" to locate the jump objects which contain the actual
 * permissions.  The base attribute names are encoded based on
 * type of entry and whether it is a local or descendent permission.
 *
 * Arguments:
 * attr - attribute name return string, attribute is assumed to be
 *        ZFS_MAX_DELEG_NAME long.
 * type - type of entry to construct
 * inheritchr - inheritance type (local,descendent, or NA for create and
 *                               permission set definitions
 * data - is either a permission set name or a 64 bit uid/gid.
 */
void
zfs_deleg_whokey(char *attr, zfs_deleg_who_type_t type,
    char inheritchr, void *data)
{
	int len = ZFS_MAX_DELEG_NAME;
	uint64_t *id = data;

	switch (type) {
	case ZFS_DELEG_USER:
	case ZFS_DELEG_GROUP:
	case ZFS_DELEG_USER_SETS:
	case ZFS_DELEG_GROUP_SETS:
		(void) snprintf(attr, len, "%c%c%c%lld", type, inheritchr,
		    ZFS_DELEG_FIELD_SEP_CHR, (longlong_t)*id);
		break;
	case ZFS_DELEG_NAMED_SET_SETS:
	case ZFS_DELEG_NAMED_SET:
		(void) snprintf(attr, len, "%c-%c%s", type,
		    ZFS_DELEG_FIELD_SEP_CHR, (char *)data);
		break;
	case ZFS_DELEG_CREATE:
	case ZFS_DELEG_CREATE_SETS:
		(void) snprintf(attr, len, "%c-%c", type,
		    ZFS_DELEG_FIELD_SEP_CHR);
		break;
	case ZFS_DELEG_EVERYONE:
	case ZFS_DELEG_EVERYONE_SETS:
		(void) snprintf(attr, len, "%c%c%c", type, inheritchr,
		    ZFS_DELEG_FIELD_SEP_CHR);
		break;
	default:
		ASSERT(!"bad zfs_deleg_who_type_t");
	}
}

#if defined(_KERNEL)
EXPORT_SYMBOL(zfs_deleg_verify_nvlist);
EXPORT_SYMBOL(zfs_deleg_whokey);
EXPORT_SYMBOL(zfs_deleg_canonicalize_perm);
#endif
