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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #if defined(_KERNEL) 27 #include <sys/systm.h> 28 #include <sys/sunddi.h> 29 #include <sys/ctype.h> 30 #else 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <strings.h> 34 #include <libnvpair.h> 35 #include <ctype.h> 36 #endif 37 /* XXX includes zfs_context.h, so why bother with the above? */ 38 #include <sys/dsl_deleg.h> 39 #include "zfs_prop.h" 40 #include "zfs_deleg.h" 41 #include "zfs_namecheck.h" 42 43 /* 44 * permission table 45 * 46 * Keep this table in sorted order 47 * 48 * This table is used for displaying all permissions for 49 * zfs allow 50 */ 51 52 zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = { 53 {ZFS_DELEG_PERM_ALLOW, ZFS_DELEG_NOTE_ALLOW}, 54 {ZFS_DELEG_PERM_CLONE, ZFS_DELEG_NOTE_CLONE }, 55 {ZFS_DELEG_PERM_CREATE, ZFS_DELEG_NOTE_CREATE }, 56 {ZFS_DELEG_PERM_DESTROY, ZFS_DELEG_NOTE_DESTROY }, 57 {ZFS_DELEG_PERM_MOUNT, ZFS_DELEG_NOTE_MOUNT }, 58 {ZFS_DELEG_PERM_PROMOTE, ZFS_DELEG_NOTE_PROMOTE }, 59 {ZFS_DELEG_PERM_RECEIVE, ZFS_DELEG_NOTE_RECEIVE }, 60 {ZFS_DELEG_PERM_RENAME, ZFS_DELEG_NOTE_RENAME }, 61 {ZFS_DELEG_PERM_ROLLBACK, ZFS_DELEG_NOTE_ROLLBACK }, 62 {ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT }, 63 {ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE }, 64 {ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_NONE }, 65 {ZFS_DELEG_PERM_USERPROP, ZFS_DELEG_NOTE_USERPROP }, 66 {ZFS_DELEG_PERM_USERQUOTA, ZFS_DELEG_NOTE_USERQUOTA }, 67 {ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA }, 68 {ZFS_DELEG_PERM_USERUSED, ZFS_DELEG_NOTE_USERUSED }, 69 {ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED }, 70 {NULL, ZFS_DELEG_NOTE_NONE } 71 }; 72 73 static int 74 zfs_valid_permission_name(const char *perm) 75 { 76 if (zfs_deleg_canonicalize_perm(perm)) 77 return (0); 78 79 return (permset_namecheck(perm, NULL, NULL)); 80 } 81 82 const char * 83 zfs_deleg_canonicalize_perm(const char *perm) 84 { 85 int i; 86 zfs_prop_t prop; 87 88 for (i = 0; zfs_deleg_perm_tab[i].z_perm != NULL; i++) { 89 if (strcmp(perm, zfs_deleg_perm_tab[i].z_perm) == 0) 90 return (perm); 91 } 92 93 prop = zfs_name_to_prop(perm); 94 if (prop != ZPROP_INVAL && zfs_prop_delegatable(prop)) 95 return (zfs_prop_to_name(prop)); 96 return (NULL); 97 98 } 99 100 static int 101 zfs_validate_who(char *who) 102 { 103 char *p; 104 105 if (who[2] != ZFS_DELEG_FIELD_SEP_CHR) 106 return (-1); 107 108 switch (who[0]) { 109 case ZFS_DELEG_USER: 110 case ZFS_DELEG_GROUP: 111 case ZFS_DELEG_USER_SETS: 112 case ZFS_DELEG_GROUP_SETS: 113 if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT) 114 return (-1); 115 for (p = &who[3]; *p; p++) 116 if (!isdigit(*p)) 117 return (-1); 118 break; 119 120 case ZFS_DELEG_NAMED_SET: 121 case ZFS_DELEG_NAMED_SET_SETS: 122 if (who[1] != ZFS_DELEG_NA) 123 return (-1); 124 return (permset_namecheck(&who[3], NULL, NULL)); 125 126 case ZFS_DELEG_CREATE: 127 case ZFS_DELEG_CREATE_SETS: 128 if (who[1] != ZFS_DELEG_NA) 129 return (-1); 130 if (who[3] != '\0') 131 return (-1); 132 break; 133 134 case ZFS_DELEG_EVERYONE: 135 case ZFS_DELEG_EVERYONE_SETS: 136 if (who[1] != ZFS_DELEG_LOCAL && who[1] != ZFS_DELEG_DESCENDENT) 137 return (-1); 138 if (who[3] != '\0') 139 return (-1); 140 break; 141 142 default: 143 return (-1); 144 } 145 146 return (0); 147 } 148 149 int 150 zfs_deleg_verify_nvlist(nvlist_t *nvp) 151 { 152 nvpair_t *who, *perm_name; 153 nvlist_t *perms; 154 int error; 155 156 if (nvp == NULL) 157 return (-1); 158 159 who = nvlist_next_nvpair(nvp, NULL); 160 if (who == NULL) 161 return (-1); 162 163 do { 164 if (zfs_validate_who(nvpair_name(who))) 165 return (-1); 166 167 error = nvlist_lookup_nvlist(nvp, nvpair_name(who), &perms); 168 169 if (error && error != ENOENT) 170 return (-1); 171 if (error == ENOENT) 172 continue; 173 174 perm_name = nvlist_next_nvpair(perms, NULL); 175 if (perm_name == NULL) { 176 return (-1); 177 } 178 do { 179 error = zfs_valid_permission_name( 180 nvpair_name(perm_name)); 181 if (error) 182 return (-1); 183 } while (perm_name = nvlist_next_nvpair(perms, perm_name)); 184 } while (who = nvlist_next_nvpair(nvp, who)); 185 return (0); 186 } 187 188 /* 189 * Construct the base attribute name. The base attribute names 190 * are the "key" to locate the jump objects which contain the actual 191 * permissions. The base attribute names are encoded based on 192 * type of entry and whether it is a local or descendent permission. 193 * 194 * Arguments: 195 * attr - attribute name return string, attribute is assumed to be 196 * ZFS_MAX_DELEG_NAME long. 197 * type - type of entry to construct 198 * inheritchr - inheritance type (local,descendent, or NA for create and 199 * permission set definitions 200 * data - is either a permission set name or a 64 bit uid/gid. 201 */ 202 void 203 zfs_deleg_whokey(char *attr, zfs_deleg_who_type_t type, 204 char inheritchr, void *data) 205 { 206 int len = ZFS_MAX_DELEG_NAME; 207 uint64_t *id = data; 208 209 switch (type) { 210 case ZFS_DELEG_USER: 211 case ZFS_DELEG_GROUP: 212 case ZFS_DELEG_USER_SETS: 213 case ZFS_DELEG_GROUP_SETS: 214 (void) snprintf(attr, len, "%c%c%c%lld", type, inheritchr, 215 ZFS_DELEG_FIELD_SEP_CHR, (longlong_t)*id); 216 break; 217 case ZFS_DELEG_NAMED_SET_SETS: 218 case ZFS_DELEG_NAMED_SET: 219 (void) snprintf(attr, len, "%c-%c%s", type, 220 ZFS_DELEG_FIELD_SEP_CHR, (char *)data); 221 break; 222 case ZFS_DELEG_CREATE: 223 case ZFS_DELEG_CREATE_SETS: 224 (void) snprintf(attr, len, "%c-%c", type, 225 ZFS_DELEG_FIELD_SEP_CHR); 226 break; 227 case ZFS_DELEG_EVERYONE: 228 case ZFS_DELEG_EVERYONE_SETS: 229 (void) snprintf(attr, len, "%c%c%c", type, inheritchr, 230 ZFS_DELEG_FIELD_SEP_CHR); 231 break; 232 default: 233 ASSERT(!"bad zfs_deleg_who_type_t"); 234 } 235 } 236