Path: blob/main/sys/contrib/openzfs/module/zcommon/zfs_deleg.c
48383 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.23* Copyright 2010 Nexenta Systems, Inc. All rights reserved.24* Copyright (c) 2013, 2015 by Delphix. All rights reserved.25* Copyright 2016 Igor Kozhukhov <[email protected]>26*/2728#include <sys/zfs_context.h>2930#if defined(_KERNEL)31#include <sys/sunddi.h>32#include <sys/ctype.h>33#else34#include <stdio.h>35#include <unistd.h>36#include <libnvpair.h>37#include <ctype.h>38#endif39#include <sys/string.h>40#include <sys/dsl_deleg.h>41#include "zfs_prop.h"42#include "zfs_deleg.h"43#include "zfs_namecheck.h"4445const zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = {46{ZFS_DELEG_PERM_ALLOW},47{ZFS_DELEG_PERM_BOOKMARK},48{ZFS_DELEG_PERM_CLONE},49{ZFS_DELEG_PERM_CREATE},50{ZFS_DELEG_PERM_DESTROY},51{ZFS_DELEG_PERM_DIFF},52{ZFS_DELEG_PERM_MOUNT},53{ZFS_DELEG_PERM_PROMOTE},54{ZFS_DELEG_PERM_RECEIVE},55{ZFS_DELEG_PERM_RECEIVE_APPEND},56{ZFS_DELEG_PERM_RENAME},57{ZFS_DELEG_PERM_ROLLBACK},58{ZFS_DELEG_PERM_SNAPSHOT},59{ZFS_DELEG_PERM_SHARE},60{ZFS_DELEG_PERM_SEND},61{ZFS_DELEG_PERM_SEND_RAW},62{ZFS_DELEG_PERM_USERPROP},63{ZFS_DELEG_PERM_USERQUOTA},64{ZFS_DELEG_PERM_GROUPQUOTA},65{ZFS_DELEG_PERM_USERUSED},66{ZFS_DELEG_PERM_GROUPUSED},67{ZFS_DELEG_PERM_USEROBJQUOTA},68{ZFS_DELEG_PERM_GROUPOBJQUOTA},69{ZFS_DELEG_PERM_USEROBJUSED},70{ZFS_DELEG_PERM_GROUPOBJUSED},71{ZFS_DELEG_PERM_HOLD},72{ZFS_DELEG_PERM_RELEASE},73{ZFS_DELEG_PERM_LOAD_KEY},74{ZFS_DELEG_PERM_CHANGE_KEY},75{ZFS_DELEG_PERM_PROJECTUSED},76{ZFS_DELEG_PERM_PROJECTQUOTA},77{ZFS_DELEG_PERM_PROJECTOBJUSED},78{ZFS_DELEG_PERM_PROJECTOBJQUOTA},79{NULL}80};8182static int83zfs_valid_permission_name(const char *perm)84{85if (zfs_deleg_canonicalize_perm(perm))86return (0);8788return (permset_namecheck(perm, NULL, NULL));89}9091const char *92zfs_deleg_canonicalize_perm(const char *perm)93{94for (int i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) {95if (strcmp(perm, zfs_deleg_perm_tab[i].z_perm) == 0)96return (perm);97}9899zfs_prop_t prop = zfs_name_to_prop(perm);100if (prop != ZPROP_INVAL && zfs_prop_delegatable(prop))101return (zfs_prop_to_name(prop));102return (NULL);103104}105106static int107zfs_validate_who(const char *who)108{109const char *p;110111if (who[2] != ZFS_DELEG_FIELD_SEP_CHR)112return (-1);113114switch (who[0]) {115case ZFS_DELEG_USER:116case ZFS_DELEG_GROUP:117case ZFS_DELEG_USER_SETS:118case ZFS_DELEG_GROUP_SETS:119if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT)120return (-1);121for (p = &who[3]; *p; p++)122if (!isdigit(*p))123return (-1);124break;125126case ZFS_DELEG_NAMED_SET:127case ZFS_DELEG_NAMED_SET_SETS:128if (who[1] != ZFS_DELEG_NA)129return (-1);130return (permset_namecheck(&who[3], NULL, NULL));131132case ZFS_DELEG_CREATE:133case ZFS_DELEG_CREATE_SETS:134if (who[1] != ZFS_DELEG_NA)135return (-1);136if (who[3] != '\0')137return (-1);138break;139140case ZFS_DELEG_EVERYONE:141case ZFS_DELEG_EVERYONE_SETS:142if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT)143return (-1);144if (who[3] != '\0')145return (-1);146break;147148default:149return (-1);150}151152return (0);153}154155int156zfs_deleg_verify_nvlist(nvlist_t *nvp)157{158nvpair_t *who, *perm_name;159nvlist_t *perms;160int error;161162if (nvp == NULL)163return (-1);164165who = nvlist_next_nvpair(nvp, NULL);166if (who == NULL)167return (-1);168169do {170if (zfs_validate_who(nvpair_name(who)))171return (-1);172173error = nvlist_lookup_nvlist(nvp, nvpair_name(who), &perms);174175if (error && error != ENOENT)176return (-1);177if (error == ENOENT)178continue;179180perm_name = nvlist_next_nvpair(perms, NULL);181if (perm_name == NULL) {182return (-1);183}184do {185error = zfs_valid_permission_name(186nvpair_name(perm_name));187if (error)188return (-1);189} while ((perm_name = nvlist_next_nvpair(perms, perm_name))190!= NULL);191} while ((who = nvlist_next_nvpair(nvp, who)) != NULL);192return (0);193}194195/*196* Construct the base attribute name. The base attribute names197* are the "key" to locate the jump objects which contain the actual198* permissions. The base attribute names are encoded based on199* type of entry and whether it is a local or descendent permission.200*201* Arguments:202* attr - attribute name return string, attribute is assumed to be203* ZFS_MAX_DELEG_NAME long.204* type - type of entry to construct205* inheritchr - inheritance type (local,descendent, or NA for create and206* permission set definitions207* data - is either a permission set name or a 64 bit uid/gid.208*/209void210zfs_deleg_whokey(char *attr, zfs_deleg_who_type_t type,211char inheritchr, void *data)212{213int len = ZFS_MAX_DELEG_NAME;214uint64_t *id = data;215216switch (type) {217case ZFS_DELEG_USER:218case ZFS_DELEG_GROUP:219case ZFS_DELEG_USER_SETS:220case ZFS_DELEG_GROUP_SETS:221(void) snprintf(attr, len, "%c%c%c%lld", type, inheritchr,222ZFS_DELEG_FIELD_SEP_CHR, (longlong_t)*id);223break;224case ZFS_DELEG_NAMED_SET_SETS:225case ZFS_DELEG_NAMED_SET:226(void) snprintf(attr, len, "%c-%c%s", type,227ZFS_DELEG_FIELD_SEP_CHR, (char *)data);228break;229case ZFS_DELEG_CREATE:230case ZFS_DELEG_CREATE_SETS:231(void) snprintf(attr, len, "%c-%c", type,232ZFS_DELEG_FIELD_SEP_CHR);233break;234case ZFS_DELEG_EVERYONE:235case ZFS_DELEG_EVERYONE_SETS:236(void) snprintf(attr, len, "%c%c%c", type, inheritchr,237ZFS_DELEG_FIELD_SEP_CHR);238break;239default:240ASSERT(!"bad zfs_deleg_who_type_t");241}242}243244#if defined(_KERNEL)245EXPORT_SYMBOL(zfs_deleg_verify_nvlist);246EXPORT_SYMBOL(zfs_deleg_whokey);247EXPORT_SYMBOL(zfs_deleg_canonicalize_perm);248#endif249250251