1185029Spjd/* 2185029Spjd * CDDL HEADER START 3185029Spjd * 4185029Spjd * The contents of this file are subject to the terms of the 5185029Spjd * Common Development and Distribution License (the "License"). 6185029Spjd * You may not use this file except in compliance with the License. 7185029Spjd * 8185029Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9185029Spjd * or http://www.opensolaris.org/os/licensing. 10185029Spjd * See the License for the specific language governing permissions 11185029Spjd * and limitations under the License. 12185029Spjd * 13185029Spjd * When distributing Covered Code, include this CDDL HEADER in each 14185029Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15185029Spjd * If applicable, add the following below this CDDL HEADER, with the 16185029Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17185029Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18185029Spjd * 19185029Spjd * CDDL HEADER END 20185029Spjd */ 21185029Spjd/* 22219089Spjd * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23219089Spjd * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 24263407Sdelphij * Copyright (c) 2013 by Delphix. All rights reserved. 25185029Spjd */ 26185029Spjd 27263407Sdelphij#include <sys/zfs_context.h> 28263407Sdelphij 29185029Spjd#if defined(_KERNEL) 30185029Spjd#include <sys/systm.h> 31185029Spjd#include <sys/sunddi.h> 32185029Spjd#include <sys/ctype.h> 33185029Spjd#else 34185029Spjd#include <stdio.h> 35185029Spjd#include <unistd.h> 36185029Spjd#include <strings.h> 37185029Spjd#include <libnvpair.h> 38185029Spjd#include <ctype.h> 39185029Spjd#endif 40185029Spjd#include <sys/dsl_deleg.h> 41185029Spjd#include "zfs_prop.h" 42185029Spjd#include "zfs_deleg.h" 43185029Spjd#include "zfs_namecheck.h" 44185029Spjd 45185029Spjdzfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = { 46263407Sdelphij {ZFS_DELEG_PERM_ALLOW}, 47263407Sdelphij {ZFS_DELEG_PERM_BOOKMARK}, 48263407Sdelphij {ZFS_DELEG_PERM_CLONE}, 49263407Sdelphij {ZFS_DELEG_PERM_CREATE}, 50263407Sdelphij {ZFS_DELEG_PERM_DESTROY}, 51263407Sdelphij {ZFS_DELEG_PERM_DIFF}, 52263407Sdelphij {ZFS_DELEG_PERM_MOUNT}, 53263407Sdelphij {ZFS_DELEG_PERM_PROMOTE}, 54263407Sdelphij {ZFS_DELEG_PERM_RECEIVE}, 55263407Sdelphij {ZFS_DELEG_PERM_RENAME}, 56263407Sdelphij {ZFS_DELEG_PERM_ROLLBACK}, 57263407Sdelphij {ZFS_DELEG_PERM_SNAPSHOT}, 58263407Sdelphij {ZFS_DELEG_PERM_SHARE}, 59263407Sdelphij {ZFS_DELEG_PERM_SEND}, 60263407Sdelphij {ZFS_DELEG_PERM_USERPROP}, 61263407Sdelphij {ZFS_DELEG_PERM_USERQUOTA}, 62263407Sdelphij {ZFS_DELEG_PERM_GROUPQUOTA}, 63263407Sdelphij {ZFS_DELEG_PERM_USERUSED}, 64263407Sdelphij {ZFS_DELEG_PERM_GROUPUSED}, 65263407Sdelphij {ZFS_DELEG_PERM_HOLD}, 66263407Sdelphij {ZFS_DELEG_PERM_RELEASE}, 67263407Sdelphij {NULL} 68185029Spjd}; 69185029Spjd 70185029Spjdstatic int 71185029Spjdzfs_valid_permission_name(const char *perm) 72185029Spjd{ 73185029Spjd if (zfs_deleg_canonicalize_perm(perm)) 74185029Spjd return (0); 75185029Spjd 76185029Spjd return (permset_namecheck(perm, NULL, NULL)); 77185029Spjd} 78185029Spjd 79185029Spjdconst char * 80185029Spjdzfs_deleg_canonicalize_perm(const char *perm) 81185029Spjd{ 82185029Spjd int i; 83185029Spjd zfs_prop_t prop; 84185029Spjd 85185029Spjd for (i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) { 86185029Spjd if (strcmp(perm, zfs_deleg_perm_tab[i].z_perm) == 0) 87185029Spjd return (perm); 88185029Spjd } 89185029Spjd 90185029Spjd prop = zfs_name_to_prop(perm); 91185029Spjd if (prop != ZPROP_INVAL && zfs_prop_delegatable(prop)) 92185029Spjd return (zfs_prop_to_name(prop)); 93185029Spjd return (NULL); 94185029Spjd 95185029Spjd} 96185029Spjd 97185029Spjdstatic int 98185029Spjdzfs_validate_who(char *who) 99185029Spjd{ 100185029Spjd char *p; 101185029Spjd 102185029Spjd if (who[2] != ZFS_DELEG_FIELD_SEP_CHR) 103185029Spjd return (-1); 104185029Spjd 105185029Spjd switch (who[0]) { 106185029Spjd case ZFS_DELEG_USER: 107185029Spjd case ZFS_DELEG_GROUP: 108185029Spjd case ZFS_DELEG_USER_SETS: 109185029Spjd case ZFS_DELEG_GROUP_SETS: 110185029Spjd if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT) 111185029Spjd return (-1); 112185029Spjd for (p = &who[3]; *p; p++) 113185029Spjd if (!isdigit(*p)) 114185029Spjd return (-1); 115185029Spjd break; 116185029Spjd 117185029Spjd case ZFS_DELEG_NAMED_SET: 118185029Spjd case ZFS_DELEG_NAMED_SET_SETS: 119185029Spjd if (who[1] != ZFS_DELEG_NA) 120185029Spjd return (-1); 121185029Spjd return (permset_namecheck(&who[3], NULL, NULL)); 122185029Spjd 123185029Spjd case ZFS_DELEG_CREATE: 124185029Spjd case ZFS_DELEG_CREATE_SETS: 125185029Spjd if (who[1] != ZFS_DELEG_NA) 126185029Spjd return (-1); 127185029Spjd if (who[3] != '\0') 128185029Spjd return (-1); 129185029Spjd break; 130185029Spjd 131185029Spjd case ZFS_DELEG_EVERYONE: 132185029Spjd case ZFS_DELEG_EVERYONE_SETS: 133185029Spjd if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT) 134185029Spjd return (-1); 135185029Spjd if (who[3] != '\0') 136185029Spjd return (-1); 137185029Spjd break; 138185029Spjd 139185029Spjd default: 140185029Spjd return (-1); 141185029Spjd } 142185029Spjd 143185029Spjd return (0); 144185029Spjd} 145185029Spjd 146185029Spjdint 147185029Spjdzfs_deleg_verify_nvlist(nvlist_t *nvp) 148185029Spjd{ 149185029Spjd nvpair_t *who, *perm_name; 150185029Spjd nvlist_t *perms; 151185029Spjd int error; 152185029Spjd 153185029Spjd if (nvp == NULL) 154185029Spjd return (-1); 155185029Spjd 156185029Spjd who = nvlist_next_nvpair(nvp, NULL); 157185029Spjd if (who == NULL) 158185029Spjd return (-1); 159185029Spjd 160185029Spjd do { 161185029Spjd if (zfs_validate_who(nvpair_name(who))) 162185029Spjd return (-1); 163185029Spjd 164185029Spjd error = nvlist_lookup_nvlist(nvp, nvpair_name(who), &perms); 165185029Spjd 166185029Spjd if (error && error != ENOENT) 167185029Spjd return (-1); 168185029Spjd if (error == ENOENT) 169185029Spjd continue; 170185029Spjd 171185029Spjd perm_name = nvlist_next_nvpair(perms, NULL); 172185029Spjd if (perm_name == NULL) { 173185029Spjd return (-1); 174185029Spjd } 175185029Spjd do { 176185029Spjd error = zfs_valid_permission_name( 177185029Spjd nvpair_name(perm_name)); 178185029Spjd if (error) 179185029Spjd return (-1); 180185029Spjd } while (perm_name = nvlist_next_nvpair(perms, perm_name)); 181185029Spjd } while (who = nvlist_next_nvpair(nvp, who)); 182185029Spjd return (0); 183185029Spjd} 184185029Spjd 185185029Spjd/* 186185029Spjd * Construct the base attribute name. The base attribute names 187185029Spjd * are the "key" to locate the jump objects which contain the actual 188185029Spjd * permissions. The base attribute names are encoded based on 189185029Spjd * type of entry and whether it is a local or descendent permission. 190185029Spjd * 191185029Spjd * Arguments: 192185029Spjd * attr - attribute name return string, attribute is assumed to be 193185029Spjd * ZFS_MAX_DELEG_NAME long. 194185029Spjd * type - type of entry to construct 195185029Spjd * inheritchr - inheritance type (local,descendent, or NA for create and 196185029Spjd * permission set definitions 197185029Spjd * data - is either a permission set name or a 64 bit uid/gid. 198185029Spjd */ 199185029Spjdvoid 200185029Spjdzfs_deleg_whokey(char *attr, zfs_deleg_who_type_t type, 201185029Spjd char inheritchr, void *data) 202185029Spjd{ 203185029Spjd int len = ZFS_MAX_DELEG_NAME; 204185029Spjd uint64_t *id = data; 205185029Spjd 206185029Spjd switch (type) { 207185029Spjd case ZFS_DELEG_USER: 208185029Spjd case ZFS_DELEG_GROUP: 209185029Spjd case ZFS_DELEG_USER_SETS: 210185029Spjd case ZFS_DELEG_GROUP_SETS: 211185029Spjd (void) snprintf(attr, len, "%c%c%c%lld", type, inheritchr, 212185029Spjd ZFS_DELEG_FIELD_SEP_CHR, (longlong_t)*id); 213185029Spjd break; 214185029Spjd case ZFS_DELEG_NAMED_SET_SETS: 215185029Spjd case ZFS_DELEG_NAMED_SET: 216185029Spjd (void) snprintf(attr, len, "%c-%c%s", type, 217185029Spjd ZFS_DELEG_FIELD_SEP_CHR, (char *)data); 218185029Spjd break; 219185029Spjd case ZFS_DELEG_CREATE: 220185029Spjd case ZFS_DELEG_CREATE_SETS: 221185029Spjd (void) snprintf(attr, len, "%c-%c", type, 222185029Spjd ZFS_DELEG_FIELD_SEP_CHR); 223185029Spjd break; 224185029Spjd case ZFS_DELEG_EVERYONE: 225185029Spjd case ZFS_DELEG_EVERYONE_SETS: 226185029Spjd (void) snprintf(attr, len, "%c%c%c", type, inheritchr, 227185029Spjd ZFS_DELEG_FIELD_SEP_CHR); 228185029Spjd break; 229185029Spjd default: 230185029Spjd ASSERT(!"bad zfs_deleg_who_type_t"); 231185029Spjd } 232185029Spjd} 233