xref: /illumos-gate/usr/src/common/zfs/zfs_deleg.c (revision e7437265dc2a4920c197ed4337665539d358b22c)
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