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  * Copyright (c) 2013 by Delphix. All rights reserved.
27  */
28 
29 /*
30  * Common name validation routines for ZFS.  These routines are shared by the
31  * userland code as well as the ioctl() layer to ensure that we don't
32  * inadvertently expose a hole through direct ioctl()s that never gets tested.
33  * In userland, however, we want significantly more information about _why_ the
34  * name is invalid.  In the kernel, we only care whether it's valid or not.
35  * Each routine therefore takes a 'namecheck_err_t' which describes exactly why
36  * the name failed to validate.
37  *
38  * Each function returns 0 on success, -1 on error.
39  */
40 
41 #if defined(_KERNEL)
42 #include <sys/systm.h>
43 #else
44 #include <string.h>
45 #endif
46 
47 #include <sys/dsl_dir.h>
48 #include <sys/param.h>
49 #include <sys/nvpair.h>
50 #include "zfs_namecheck.h"
51 #include "zfs_deleg.h"
52 
53 static int
54 valid_char(char c)
55 {
56 	return ((c >= 'a' && c <= 'z') ||
57 	    (c >= 'A' && c <= 'Z') ||
58 	    (c >= '0' && c <= '9') ||
59 	    c == '-' || c == '_' || c == '.' || c == ':' || c == ' ');
60 }
61 
62 /*
63  * Snapshot names must be made up of alphanumeric characters plus the following
64  * characters:
65  *
66  * 	[-_.: ]
67  */
68 int
69 zfs_component_namecheck(const char *path, namecheck_err_t *why, char *what)
70 {
71 	const char *loc;
72 
73 	if (strlen(path) >= ZFS_MAX_DATASET_NAME_LEN) {
74 		if (why)
75 			*why = NAME_ERR_TOOLONG;
76 		return (-1);
77 	}
78 
79 	if (path[0] == '\0') {
80 		if (why)
81 			*why = NAME_ERR_EMPTY_COMPONENT;
82 		return (-1);
83 	}
84 
85 	for (loc = path; *loc; loc++) {
86 		if (!valid_char(*loc)) {
87 			if (why) {
88 				*why = NAME_ERR_INVALCHAR;
89 				*what = *loc;
90 			}
91 			return (-1);
92 		}
93 	}
94 	return (0);
95 }
96 
97 
98 /*
99  * Permissions set name must start with the letter '@' followed by the
100  * same character restrictions as snapshot names, except that the name
101  * cannot exceed 64 characters.
102  */
103 int
104 permset_namecheck(const char *path, namecheck_err_t *why, char *what)
105 {
106 	if (strlen(path) >= ZFS_PERMSET_MAXLEN) {
107 		if (why)
108 			*why = NAME_ERR_TOOLONG;
109 		return (-1);
110 	}
111 
112 	if (path[0] != '@') {
113 		if (why) {
114 			*why = NAME_ERR_NO_AT;
115 			*what = path[0];
116 		}
117 		return (-1);
118 	}
119 
120 	return (zfs_component_namecheck(&path[1], why, what));
121 }
122 
123 /*
124  * Entity names must be of the following form:
125  *
126  * 	[component/]*[component][(@|#)component]?
127  *
128  * Where each component is made up of alphanumeric characters plus the following
129  * characters:
130  *
131  * 	[-_.:%]
132  *
133  * We allow '%' here as we use that character internally to create unique
134  * names for temporary clones (for online recv).
135  */
136 int
137 entity_namecheck(const char *path, namecheck_err_t *why, char *what)
138 {
139 	const char *start, *end;
140 	int found_delim;
141 
142 	/*
143 	 * Make sure the name is not too long.
144 	 */
145 
146 	if (strlen(path) >= ZFS_MAX_DATASET_NAME_LEN) {
147 		if (why)
148 			*why = NAME_ERR_TOOLONG;
149 		return (-1);
150 	}
151 
152 	/* Explicitly check for a leading slash.  */
153 	if (path[0] == '/') {
154 		if (why)
155 			*why = NAME_ERR_LEADING_SLASH;
156 		return (-1);
157 	}
158 
159 	if (path[0] == '\0') {
160 		if (why)
161 			*why = NAME_ERR_EMPTY_COMPONENT;
162 		return (-1);
163 	}
164 
165 	start = path;
166 	found_delim = 0;
167 	for (;;) {
168 		/* Find the end of this component */
169 		end = start;
170 		while (*end != '/' && *end != '@' && *end != '#' &&
171 		    *end != '\0')
172 			end++;
173 
174 		if (*end == '\0' && end[-1] == '/') {
175 			/* trailing slashes are not allowed */
176 			if (why)
177 				*why = NAME_ERR_TRAILING_SLASH;
178 			return (-1);
179 		}
180 
181 		/* Validate the contents of this component */
182 		for (const char *loc = start; loc != end; loc++) {
183 			if (!valid_char(*loc) && *loc != '%') {
184 				if (why) {
185 					*why = NAME_ERR_INVALCHAR;
186 					*what = *loc;
187 				}
188 				return (-1);
189 			}
190 		}
191 
192 		/* Snapshot or bookmark delimiter found */
193 		if (*end == '@' || *end == '#') {
194 			/* Multiple delimiters are not allowed */
195 			if (found_delim != 0) {
196 				if (why)
197 					*why = NAME_ERR_MULTIPLE_DELIMITERS;
198 				return (-1);
199 			}
200 
201 			found_delim = 1;
202 		}
203 
204 		/* Zero-length components are not allowed */
205 		if (start == end) {
206 			if (why)
207 				*why = NAME_ERR_EMPTY_COMPONENT;
208 			return (-1);
209 		}
210 
211 		/* If we've reached the end of the string, we're OK */
212 		if (*end == '\0')
213 			return (0);
214 
215 		/*
216 		 * If there is a '/' in a snapshot or bookmark name
217 		 * then report an error
218 		 */
219 		if (*end == '/' && found_delim != 0) {
220 			if (why)
221 				*why = NAME_ERR_TRAILING_SLASH;
222 			return (-1);
223 		}
224 
225 		/* Update to the next component */
226 		start = end + 1;
227 	}
228 }
229 
230 /*
231  * Dataset is any entity, except bookmark
232  */
233 int
234 dataset_namecheck(const char *path, namecheck_err_t *why, char *what)
235 {
236 	int ret = entity_namecheck(path, why, what);
237 
238 	if (ret == 0 && strchr(path, '#') != NULL) {
239 		if (why != NULL) {
240 			*why = NAME_ERR_INVALCHAR;
241 			*what = '#';
242 		}
243 		return (-1);
244 	}
245 
246 	return (ret);
247 }
248 
249 /*
250  * mountpoint names must be of the following form:
251  *
252  *	/[component][/]*[component][/]
253  */
254 int
255 mountpoint_namecheck(const char *path, namecheck_err_t *why)
256 {
257 	const char *start, *end;
258 
259 	/*
260 	 * Make sure none of the mountpoint component names are too long.
261 	 * If a component name is too long then the mkdir of the mountpoint
262 	 * will fail but then the mountpoint property will be set to a value
263 	 * that can never be mounted.  Better to fail before setting the prop.
264 	 * Extra slashes are OK, they will be tossed by the mountpoint mkdir.
265 	 */
266 
267 	if (path == NULL || *path != '/') {
268 		if (why)
269 			*why = NAME_ERR_LEADING_SLASH;
270 		return (-1);
271 	}
272 
273 	/* Skip leading slash  */
274 	start = &path[1];
275 	do {
276 		end = start;
277 		while (*end != '/' && *end != '\0')
278 			end++;
279 
280 		if (end - start >= ZFS_MAX_DATASET_NAME_LEN) {
281 			if (why)
282 				*why = NAME_ERR_TOOLONG;
283 			return (-1);
284 		}
285 		start = end + 1;
286 
287 	} while (*end != '\0');
288 
289 	return (0);
290 }
291 
292 /*
293  * For pool names, we have the same set of valid characters as described in
294  * dataset names, with the additional restriction that the pool name must begin
295  * with a letter.  The pool names 'raidz' and 'mirror' are also reserved names
296  * that cannot be used.
297  */
298 int
299 pool_namecheck(const char *pool, namecheck_err_t *why, char *what)
300 {
301 	const char *c;
302 
303 	/*
304 	 * Make sure the name is not too long.
305 	 * If we're creating a pool with version >= SPA_VERSION_DSL_SCRUB (v11)
306 	 * we need to account for additional space needed by the origin ds which
307 	 * will also be snapshotted: "poolname"+"/"+"$ORIGIN"+"@"+"$ORIGIN".
308 	 * Play it safe and enforce this limit even if the pool version is < 11
309 	 * so it can be upgraded without issues.
310 	 */
311 	if (strlen(pool) >= (ZFS_MAX_DATASET_NAME_LEN - 2 -
312 	    strlen(ORIGIN_DIR_NAME) * 2)) {
313 		if (why)
314 			*why = NAME_ERR_TOOLONG;
315 		return (-1);
316 	}
317 
318 	c = pool;
319 	while (*c != '\0') {
320 		if (!valid_char(*c)) {
321 			if (why) {
322 				*why = NAME_ERR_INVALCHAR;
323 				*what = *c;
324 			}
325 			return (-1);
326 		}
327 		c++;
328 	}
329 
330 	if (!(*pool >= 'a' && *pool <= 'z') &&
331 	    !(*pool >= 'A' && *pool <= 'Z')) {
332 		if (why)
333 			*why = NAME_ERR_NOLETTER;
334 		return (-1);
335 	}
336 
337 	if (strcmp(pool, "mirror") == 0 || strcmp(pool, "raidz") == 0) {
338 		if (why)
339 			*why = NAME_ERR_RESERVED;
340 		return (-1);
341 	}
342 
343 	if (pool[0] == 'c' && (pool[1] >= '0' && pool[1] <= '9')) {
344 		if (why)
345 			*why = NAME_ERR_DISKLIKE;
346 		return (-1);
347 	}
348 
349 	return (0);
350 }
351