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