1*ecd6cf80Smarks /* 2*ecd6cf80Smarks * CDDL HEADER START 3*ecd6cf80Smarks * 4*ecd6cf80Smarks * The contents of this file are subject to the terms of the 5*ecd6cf80Smarks * Common Development and Distribution License (the "License"). 6*ecd6cf80Smarks * You may not use this file except in compliance with the License. 7*ecd6cf80Smarks * 8*ecd6cf80Smarks * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*ecd6cf80Smarks * or http://www.opensolaris.org/os/licensing. 10*ecd6cf80Smarks * See the License for the specific language governing permissions 11*ecd6cf80Smarks * and limitations under the License. 12*ecd6cf80Smarks * 13*ecd6cf80Smarks * When distributing Covered Code, include this CDDL HEADER in each 14*ecd6cf80Smarks * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*ecd6cf80Smarks * If applicable, add the following below this CDDL HEADER, with the 16*ecd6cf80Smarks * fields enclosed by brackets "[]" replaced with your own identifying 17*ecd6cf80Smarks * information: Portions Copyright [yyyy] [name of copyright owner] 18*ecd6cf80Smarks * 19*ecd6cf80Smarks * CDDL HEADER END 20*ecd6cf80Smarks */ 21*ecd6cf80Smarks /* 22*ecd6cf80Smarks * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*ecd6cf80Smarks * Use is subject to license terms. 24*ecd6cf80Smarks */ 25*ecd6cf80Smarks 26*ecd6cf80Smarks 27*ecd6cf80Smarks #pragma ident "%Z%%M% %I% %E% SMI" 28*ecd6cf80Smarks 29*ecd6cf80Smarks #if defined(_KERNEL) 30*ecd6cf80Smarks #include <sys/systm.h> 31*ecd6cf80Smarks #include <sys/sunddi.h> 32*ecd6cf80Smarks #include <sys/ctype.h> 33*ecd6cf80Smarks #else 34*ecd6cf80Smarks #include <stdio.h> 35*ecd6cf80Smarks #include <unistd.h> 36*ecd6cf80Smarks #include <strings.h> 37*ecd6cf80Smarks #include <libnvpair.h> 38*ecd6cf80Smarks #include <ctype.h> 39*ecd6cf80Smarks #endif 40*ecd6cf80Smarks #include <sys/dsl_deleg.h> 41*ecd6cf80Smarks #include "zfs_deleg.h" 42*ecd6cf80Smarks #include "zfs_namecheck.h" 43*ecd6cf80Smarks 44*ecd6cf80Smarks /* 45*ecd6cf80Smarks * permission table 46*ecd6cf80Smarks */ 47*ecd6cf80Smarks 48*ecd6cf80Smarks char *zfs_deleg_perm_tab[] = { 49*ecd6cf80Smarks ZFS_DELEG_PERM_CREATE, 50*ecd6cf80Smarks ZFS_DELEG_PERM_DESTROY, 51*ecd6cf80Smarks ZFS_DELEG_PERM_SNAPSHOT, 52*ecd6cf80Smarks ZFS_DELEG_PERM_ROLLBACK, 53*ecd6cf80Smarks ZFS_DELEG_PERM_CLONE, 54*ecd6cf80Smarks ZFS_DELEG_PERM_PROMOTE, 55*ecd6cf80Smarks ZFS_DELEG_PERM_RENAME, 56*ecd6cf80Smarks ZFS_DELEG_PERM_MOUNT, 57*ecd6cf80Smarks ZFS_DELEG_PERM_SHARE, 58*ecd6cf80Smarks ZFS_DELEG_PERM_SEND, 59*ecd6cf80Smarks ZFS_DELEG_PERM_RECEIVE, 60*ecd6cf80Smarks ZFS_DELEG_PERM_QUOTA, 61*ecd6cf80Smarks ZFS_DELEG_PERM_RESERVATION, 62*ecd6cf80Smarks ZFS_DELEG_PERM_VOLSIZE, 63*ecd6cf80Smarks ZFS_DELEG_PERM_RECORDSIZE, 64*ecd6cf80Smarks ZFS_DELEG_PERM_MOUNTPOINT, 65*ecd6cf80Smarks ZFS_DELEG_PERM_SHARENFS, 66*ecd6cf80Smarks ZFS_DELEG_PERM_CHECKSUM, 67*ecd6cf80Smarks ZFS_DELEG_PERM_COMPRESSION, 68*ecd6cf80Smarks ZFS_DELEG_PERM_ATIME, 69*ecd6cf80Smarks ZFS_DELEG_PERM_DEVICES, 70*ecd6cf80Smarks ZFS_DELEG_PERM_EXEC, 71*ecd6cf80Smarks ZFS_DELEG_PERM_SETUID, 72*ecd6cf80Smarks ZFS_DELEG_PERM_READONLY, 73*ecd6cf80Smarks ZFS_DELEG_PERM_ZONED, 74*ecd6cf80Smarks ZFS_DELEG_PERM_SNAPDIR, 75*ecd6cf80Smarks ZFS_DELEG_PERM_ACLMODE, 76*ecd6cf80Smarks ZFS_DELEG_PERM_ACLINHERIT, 77*ecd6cf80Smarks ZFS_DELEG_PERM_ALLOW, 78*ecd6cf80Smarks ZFS_DELEG_PERM_CANMOUNT, 79*ecd6cf80Smarks ZFS_DELEG_PERM_USERPROP, 80*ecd6cf80Smarks ZFS_DELEG_PERM_SHAREISCSI, 81*ecd6cf80Smarks ZFS_DELEG_PERM_XATTR, 82*ecd6cf80Smarks ZFS_DELEG_PERM_COPIES, 83*ecd6cf80Smarks NULL 84*ecd6cf80Smarks }; 85*ecd6cf80Smarks 86*ecd6cf80Smarks int 87*ecd6cf80Smarks zfs_deleg_type(char *name) 88*ecd6cf80Smarks { 89*ecd6cf80Smarks return (name[0]); 90*ecd6cf80Smarks } 91*ecd6cf80Smarks 92*ecd6cf80Smarks static int 93*ecd6cf80Smarks zfs_valid_permission_name(char *perm) 94*ecd6cf80Smarks { 95*ecd6cf80Smarks int i; 96*ecd6cf80Smarks for (i = 0; zfs_deleg_perm_tab[i] != NULL; i++) { 97*ecd6cf80Smarks if (strcmp(perm, zfs_deleg_perm_tab[i]) == 0) 98*ecd6cf80Smarks return (0); 99*ecd6cf80Smarks } 100*ecd6cf80Smarks 101*ecd6cf80Smarks return (permset_namecheck(perm, NULL, NULL)); 102*ecd6cf80Smarks } 103*ecd6cf80Smarks 104*ecd6cf80Smarks static int 105*ecd6cf80Smarks zfs_validate_who(char *who) 106*ecd6cf80Smarks { 107*ecd6cf80Smarks int error = 0; 108*ecd6cf80Smarks char *p; 109*ecd6cf80Smarks 110*ecd6cf80Smarks switch (zfs_deleg_type(who)) { 111*ecd6cf80Smarks case ZFS_DELEG_USER: 112*ecd6cf80Smarks case ZFS_DELEG_GROUP: 113*ecd6cf80Smarks case ZFS_DELEG_USER_SETS: 114*ecd6cf80Smarks case ZFS_DELEG_GROUP_SETS: 115*ecd6cf80Smarks if ((who[1] != 'l' || who[1] != 'd') && 116*ecd6cf80Smarks (who[2] != ZFS_DELEG_FIELD_SEP_CHR)) { 117*ecd6cf80Smarks error = -1; 118*ecd6cf80Smarks break; 119*ecd6cf80Smarks } 120*ecd6cf80Smarks 121*ecd6cf80Smarks for (p = &who[3]; p && *p; p++) 122*ecd6cf80Smarks if (!isdigit(*p)) { 123*ecd6cf80Smarks error = -1; 124*ecd6cf80Smarks } 125*ecd6cf80Smarks break; 126*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET: 127*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET_SETS: 128*ecd6cf80Smarks error = permset_namecheck(&who[3], NULL, NULL); 129*ecd6cf80Smarks break; 130*ecd6cf80Smarks 131*ecd6cf80Smarks case ZFS_DELEG_CREATE: 132*ecd6cf80Smarks case ZFS_DELEG_CREATE_SETS: 133*ecd6cf80Smarks case ZFS_DELEG_EVERYONE: 134*ecd6cf80Smarks case ZFS_DELEG_EVERYONE_SETS: 135*ecd6cf80Smarks if (who[3] != '\0') 136*ecd6cf80Smarks error = -1; 137*ecd6cf80Smarks break; 138*ecd6cf80Smarks default: 139*ecd6cf80Smarks error = -1; 140*ecd6cf80Smarks } 141*ecd6cf80Smarks 142*ecd6cf80Smarks return (error); 143*ecd6cf80Smarks } 144*ecd6cf80Smarks 145*ecd6cf80Smarks static int 146*ecd6cf80Smarks zfs_validate_iflags(char *who) 147*ecd6cf80Smarks { 148*ecd6cf80Smarks switch (zfs_deleg_type(who)) { 149*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET: 150*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET_SETS: 151*ecd6cf80Smarks case ZFS_DELEG_CREATE: 152*ecd6cf80Smarks case ZFS_DELEG_CREATE_SETS: 153*ecd6cf80Smarks if (who[1] != '-') 154*ecd6cf80Smarks return (-1); 155*ecd6cf80Smarks break; 156*ecd6cf80Smarks default: 157*ecd6cf80Smarks if (who[1] != 'l' && who[1] != 'd') 158*ecd6cf80Smarks return (-1); 159*ecd6cf80Smarks break; 160*ecd6cf80Smarks } 161*ecd6cf80Smarks return (0); 162*ecd6cf80Smarks } 163*ecd6cf80Smarks 164*ecd6cf80Smarks int 165*ecd6cf80Smarks zfs_deleg_verify_nvlist(nvlist_t *nvp) 166*ecd6cf80Smarks { 167*ecd6cf80Smarks nvpair_t *who, *perm_name; 168*ecd6cf80Smarks nvlist_t *perms; 169*ecd6cf80Smarks int error; 170*ecd6cf80Smarks 171*ecd6cf80Smarks if (nvp == NULL) 172*ecd6cf80Smarks return (-1); 173*ecd6cf80Smarks 174*ecd6cf80Smarks who = nvlist_next_nvpair(nvp, NULL); 175*ecd6cf80Smarks if (who == NULL) 176*ecd6cf80Smarks return (-1); 177*ecd6cf80Smarks 178*ecd6cf80Smarks do { 179*ecd6cf80Smarks if (zfs_validate_who(nvpair_name(who))) 180*ecd6cf80Smarks return (-1); 181*ecd6cf80Smarks 182*ecd6cf80Smarks if (zfs_validate_iflags(nvpair_name(who))) 183*ecd6cf80Smarks return (-1); 184*ecd6cf80Smarks 185*ecd6cf80Smarks error = nvlist_lookup_nvlist(nvp, nvpair_name(who), &perms); 186*ecd6cf80Smarks 187*ecd6cf80Smarks if (error && error != ENOENT) 188*ecd6cf80Smarks return (-1); 189*ecd6cf80Smarks if (error == ENOENT) 190*ecd6cf80Smarks continue; 191*ecd6cf80Smarks 192*ecd6cf80Smarks perm_name = nvlist_next_nvpair(perms, NULL); 193*ecd6cf80Smarks if (perm_name == NULL) { 194*ecd6cf80Smarks return (-1); 195*ecd6cf80Smarks } 196*ecd6cf80Smarks do { 197*ecd6cf80Smarks error = zfs_valid_permission_name( 198*ecd6cf80Smarks nvpair_name(perm_name)); 199*ecd6cf80Smarks if (error) { 200*ecd6cf80Smarks return (-1); 201*ecd6cf80Smarks } 202*ecd6cf80Smarks } while (perm_name = nvlist_next_nvpair(perms, perm_name)); 203*ecd6cf80Smarks } while (who = nvlist_next_nvpair(nvp, who)); 204*ecd6cf80Smarks return (0); 205*ecd6cf80Smarks } 206*ecd6cf80Smarks 207*ecd6cf80Smarks /* 208*ecd6cf80Smarks * Construct the base attribute name. The base attribute names 209*ecd6cf80Smarks * are the "key" to locate the jump objects which contain the actual 210*ecd6cf80Smarks * permissions. The base attribute names are encoded based on 211*ecd6cf80Smarks * type of entry and whether it is a local or descendent permission. 212*ecd6cf80Smarks * 213*ecd6cf80Smarks * Arguments: 214*ecd6cf80Smarks * attr - attribute name return string, attribute is assumed to be 215*ecd6cf80Smarks * ZFS_MAX_DELEG_NAME long. 216*ecd6cf80Smarks * type - type of entry to construct 217*ecd6cf80Smarks * inheritchr - inheritance type (local,descendent, or NA for create and 218*ecd6cf80Smarks * permission set definitions 219*ecd6cf80Smarks * data - is either a permission set name or a 64 bit uid/gid. 220*ecd6cf80Smarks */ 221*ecd6cf80Smarks void 222*ecd6cf80Smarks zfs_deleg_whokey(char *attr, char type, char inheritchr, void *data) 223*ecd6cf80Smarks { 224*ecd6cf80Smarks int len = ZFS_MAX_DELEG_NAME; 225*ecd6cf80Smarks uint64_t *id = data; 226*ecd6cf80Smarks 227*ecd6cf80Smarks switch (type) { 228*ecd6cf80Smarks case ZFS_DELEG_USER: 229*ecd6cf80Smarks case ZFS_DELEG_GROUP: 230*ecd6cf80Smarks case ZFS_DELEG_USER_SETS: 231*ecd6cf80Smarks case ZFS_DELEG_GROUP_SETS: 232*ecd6cf80Smarks (void) snprintf(attr, len, "%c%c%c%lld", type, inheritchr, 233*ecd6cf80Smarks ZFS_DELEG_FIELD_SEP_CHR, (longlong_t)*id); 234*ecd6cf80Smarks break; 235*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET_SETS: 236*ecd6cf80Smarks case ZFS_DELEG_NAMED_SET: 237*ecd6cf80Smarks (void) snprintf(attr, len, "%c-%c%s", type, 238*ecd6cf80Smarks ZFS_DELEG_FIELD_SEP_CHR, (char *)data); 239*ecd6cf80Smarks break; 240*ecd6cf80Smarks case ZFS_DELEG_CREATE: 241*ecd6cf80Smarks case ZFS_DELEG_CREATE_SETS: 242*ecd6cf80Smarks (void) snprintf(attr, len, "%c-%c", type, 243*ecd6cf80Smarks ZFS_DELEG_FIELD_SEP_CHR); 244*ecd6cf80Smarks break; 245*ecd6cf80Smarks default: 246*ecd6cf80Smarks (void) snprintf(attr, len, "%c%c%c", type, inheritchr, 247*ecd6cf80Smarks ZFS_DELEG_FIELD_SEP_CHR); 248*ecd6cf80Smarks } 249*ecd6cf80Smarks } 250