1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21168404Spjd/*
22209962Smm * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23168404Spjd * Use is subject to license terms.
24168404Spjd */
25168404Spjd
26168404Spjd/*
27168404Spjd * Common name validation routines for ZFS.  These routines are shared by the
28168404Spjd * userland code as well as the ioctl() layer to ensure that we don't
29168404Spjd * inadvertently expose a hole through direct ioctl()s that never gets tested.
30168404Spjd * In userland, however, we want significantly more information about _why_ the
31168404Spjd * name is invalid.  In the kernel, we only care whether it's valid or not.
32168404Spjd * Each routine therefore takes a 'namecheck_err_t' which describes exactly why
33168404Spjd * the name failed to validate.
34168404Spjd *
35168404Spjd * Each function returns 0 on success, -1 on error.
36168404Spjd */
37168404Spjd
38168404Spjd#if defined(_KERNEL)
39168404Spjd#include <sys/systm.h>
40168404Spjd#else
41168404Spjd#include <string.h>
42168404Spjd#endif
43168404Spjd
44168404Spjd#include <sys/param.h>
45185029Spjd#include <sys/nvpair.h>
46168404Spjd#include "zfs_namecheck.h"
47185029Spjd#include "zfs_deleg.h"
48168404Spjd
49168404Spjdstatic int
50168404Spjdvalid_char(char c)
51168404Spjd{
52168404Spjd	return ((c >= 'a' && c <= 'z') ||
53168404Spjd	    (c >= 'A' && c <= 'Z') ||
54168404Spjd	    (c >= '0' && c <= '9') ||
55185029Spjd	    c == '-' || c == '_' || c == '.' || c == ':' || c == ' ');
56168404Spjd}
57168404Spjd
58168404Spjd/*
59168404Spjd * Snapshot names must be made up of alphanumeric characters plus the following
60168404Spjd * characters:
61168404Spjd *
62219089Spjd * 	[-_.: ]
63168404Spjd */
64168404Spjdint
65168404Spjdsnapshot_namecheck(const char *path, namecheck_err_t *why, char *what)
66168404Spjd{
67168404Spjd	const char *loc;
68168404Spjd
69168404Spjd	if (strlen(path) >= MAXNAMELEN) {
70168404Spjd		if (why)
71168404Spjd			*why = NAME_ERR_TOOLONG;
72168404Spjd		return (-1);
73168404Spjd	}
74168404Spjd
75168404Spjd	if (path[0] == '\0') {
76168404Spjd		if (why)
77168404Spjd			*why = NAME_ERR_EMPTY_COMPONENT;
78168404Spjd		return (-1);
79168404Spjd	}
80168404Spjd
81168404Spjd	for (loc = path; *loc; loc++) {
82168404Spjd		if (!valid_char(*loc)) {
83168404Spjd			if (why) {
84168404Spjd				*why = NAME_ERR_INVALCHAR;
85168404Spjd				*what = *loc;
86168404Spjd			}
87168404Spjd			return (-1);
88168404Spjd		}
89168404Spjd	}
90168404Spjd	return (0);
91168404Spjd}
92168404Spjd
93185029Spjd
94168404Spjd/*
95185029Spjd * Permissions set name must start with the letter '@' followed by the
96185029Spjd * same character restrictions as snapshot names, except that the name
97185029Spjd * cannot exceed 64 characters.
98185029Spjd */
99185029Spjdint
100185029Spjdpermset_namecheck(const char *path, namecheck_err_t *why, char *what)
101185029Spjd{
102185029Spjd	if (strlen(path) >= ZFS_PERMSET_MAXLEN) {
103185029Spjd		if (why)
104185029Spjd			*why = NAME_ERR_TOOLONG;
105185029Spjd		return (-1);
106185029Spjd	}
107185029Spjd
108185029Spjd	if (path[0] != '@') {
109185029Spjd		if (why) {
110185029Spjd			*why = NAME_ERR_NO_AT;
111185029Spjd			*what = path[0];
112185029Spjd		}
113185029Spjd		return (-1);
114185029Spjd	}
115185029Spjd
116185029Spjd	return (snapshot_namecheck(&path[1], why, what));
117185029Spjd}
118185029Spjd
119185029Spjd/*
120168404Spjd * Dataset names must be of the following form:
121168404Spjd *
122168404Spjd * 	[component][/]*[component][@component]
123168404Spjd *
124168404Spjd * Where each component is made up of alphanumeric characters plus the following
125168404Spjd * characters:
126168404Spjd *
127185029Spjd * 	[-_.:%]
128185029Spjd *
129185029Spjd * We allow '%' here as we use that character internally to create unique
130185029Spjd * names for temporary clones (for online recv).
131168404Spjd */
132168404Spjdint
133168404Spjddataset_namecheck(const char *path, namecheck_err_t *why, char *what)
134168404Spjd{
135168404Spjd	const char *loc, *end;
136168404Spjd	int found_snapshot;
137168404Spjd
138168404Spjd	/*
139168404Spjd	 * Make sure the name is not too long.
140168404Spjd	 *
141168404Spjd	 * ZFS_MAXNAMELEN is the maximum dataset length used in the userland
142168404Spjd	 * which is the same as MAXNAMELEN used in the kernel.
143168404Spjd	 * If ZFS_MAXNAMELEN value is changed, make sure to cleanup all
144168404Spjd	 * places using MAXNAMELEN.
145168404Spjd	 */
146185029Spjd
147168404Spjd	if (strlen(path) >= MAXNAMELEN) {
148168404Spjd		if (why)
149168404Spjd			*why = NAME_ERR_TOOLONG;
150168404Spjd		return (-1);
151168404Spjd	}
152168404Spjd
153168404Spjd	/* Explicitly check for a leading slash.  */
154168404Spjd	if (path[0] == '/') {
155168404Spjd		if (why)
156168404Spjd			*why = NAME_ERR_LEADING_SLASH;
157168404Spjd		return (-1);
158168404Spjd	}
159168404Spjd
160168404Spjd	if (path[0] == '\0') {
161168404Spjd		if (why)
162168404Spjd			*why = NAME_ERR_EMPTY_COMPONENT;
163168404Spjd		return (-1);
164168404Spjd	}
165168404Spjd
166168404Spjd	loc = path;
167168404Spjd	found_snapshot = 0;
168168404Spjd	for (;;) {
169168404Spjd		/* Find the end of this component */
170168404Spjd		end = loc;
171168404Spjd		while (*end != '/' && *end != '@' && *end != '\0')
172168404Spjd			end++;
173168404Spjd
174168404Spjd		if (*end == '\0' && end[-1] == '/') {
175168404Spjd			/* trailing slashes are not allowed */
176168404Spjd			if (why)
177168404Spjd				*why = NAME_ERR_TRAILING_SLASH;
178168404Spjd			return (-1);
179168404Spjd		}
180168404Spjd
181168404Spjd		/* Zero-length components are not allowed */
182168404Spjd		if (loc == end) {
183168404Spjd			if (why) {
184168404Spjd				/*
185168404Spjd				 * Make sure this is really a zero-length
186168404Spjd				 * component and not a '@@'.
187168404Spjd				 */
188168404Spjd				if (*end == '@' && found_snapshot) {
189168404Spjd					*why = NAME_ERR_MULTIPLE_AT;
190168404Spjd				} else {
191168404Spjd					*why = NAME_ERR_EMPTY_COMPONENT;
192168404Spjd				}
193168404Spjd			}
194168404Spjd
195168404Spjd			return (-1);
196168404Spjd		}
197168404Spjd
198168404Spjd		/* Validate the contents of this component */
199168404Spjd		while (loc != end) {
200185029Spjd			if (!valid_char(*loc) && *loc != '%') {
201168404Spjd				if (why) {
202168404Spjd					*why = NAME_ERR_INVALCHAR;
203168404Spjd					*what = *loc;
204168404Spjd				}
205168404Spjd				return (-1);
206168404Spjd			}
207168404Spjd			loc++;
208168404Spjd		}
209168404Spjd
210168404Spjd		/* If we've reached the end of the string, we're OK */
211168404Spjd		if (*end == '\0')
212168404Spjd			return (0);
213168404Spjd
214168404Spjd		if (*end == '@') {
215168404Spjd			/*
216168404Spjd			 * If we've found an @ symbol, indicate that we're in
217168404Spjd			 * the snapshot component, and report a second '@'
218168404Spjd			 * character as an error.
219168404Spjd			 */
220168404Spjd			if (found_snapshot) {
221168404Spjd				if (why)
222168404Spjd					*why = NAME_ERR_MULTIPLE_AT;
223168404Spjd				return (-1);
224168404Spjd			}
225168404Spjd
226168404Spjd			found_snapshot = 1;
227168404Spjd		}
228168404Spjd
229168404Spjd		/*
230168404Spjd		 * If there is a '/' in a snapshot name
231168404Spjd		 * then report an error
232168404Spjd		 */
233168404Spjd		if (*end == '/' && found_snapshot) {
234168404Spjd			if (why)
235168404Spjd				*why = NAME_ERR_TRAILING_SLASH;
236168404Spjd			return (-1);
237168404Spjd		}
238168404Spjd
239168404Spjd		/* Update to the next component */
240168404Spjd		loc = end + 1;
241168404Spjd	}
242168404Spjd}
243168404Spjd
244185029Spjd
245168404Spjd/*
246185029Spjd * mountpoint names must be of the following form:
247185029Spjd *
248185029Spjd *	/[component][/]*[component][/]
249185029Spjd */
250185029Spjdint
251185029Spjdmountpoint_namecheck(const char *path, namecheck_err_t *why)
252185029Spjd{
253185029Spjd	const char *start, *end;
254185029Spjd
255185029Spjd	/*
256185029Spjd	 * Make sure none of the mountpoint component names are too long.
257185029Spjd	 * If a component name is too long then the mkdir of the mountpoint
258185029Spjd	 * will fail but then the mountpoint property will be set to a value
259185029Spjd	 * that can never be mounted.  Better to fail before setting the prop.
260185029Spjd	 * Extra slashes are OK, they will be tossed by the mountpoint mkdir.
261185029Spjd	 */
262185029Spjd
263185029Spjd	if (path == NULL || *path != '/') {
264185029Spjd		if (why)
265185029Spjd			*why = NAME_ERR_LEADING_SLASH;
266185029Spjd		return (-1);
267185029Spjd	}
268185029Spjd
269185029Spjd	/* Skip leading slash  */
270185029Spjd	start = &path[1];
271185029Spjd	do {
272185029Spjd		end = start;
273185029Spjd		while (*end != '/' && *end != '\0')
274185029Spjd			end++;
275185029Spjd
276185029Spjd		if (end - start >= MAXNAMELEN) {
277185029Spjd			if (why)
278185029Spjd				*why = NAME_ERR_TOOLONG;
279185029Spjd			return (-1);
280185029Spjd		}
281185029Spjd		start = end + 1;
282185029Spjd
283185029Spjd	} while (*end != '\0');
284185029Spjd
285185029Spjd	return (0);
286185029Spjd}
287185029Spjd
288185029Spjd/*
289168404Spjd * For pool names, we have the same set of valid characters as described in
290168404Spjd * dataset names, with the additional restriction that the pool name must begin
291168404Spjd * with a letter.  The pool names 'raidz' and 'mirror' are also reserved names
292168404Spjd * that cannot be used.
293168404Spjd */
294168404Spjdint
295168404Spjdpool_namecheck(const char *pool, namecheck_err_t *why, char *what)
296168404Spjd{
297168404Spjd	const char *c;
298168404Spjd
299168404Spjd	/*
300168404Spjd	 * Make sure the name is not too long.
301168404Spjd	 *
302168404Spjd	 * ZPOOL_MAXNAMELEN is the maximum pool length used in the userland
303168404Spjd	 * which is the same as MAXNAMELEN used in the kernel.
304168404Spjd	 * If ZPOOL_MAXNAMELEN value is changed, make sure to cleanup all
305168404Spjd	 * places using MAXNAMELEN.
306168404Spjd	 */
307168404Spjd	if (strlen(pool) >= MAXNAMELEN) {
308168404Spjd		if (why)
309168404Spjd			*why = NAME_ERR_TOOLONG;
310168404Spjd		return (-1);
311168404Spjd	}
312168404Spjd
313168404Spjd	c = pool;
314168404Spjd	while (*c != '\0') {
315168404Spjd		if (!valid_char(*c)) {
316168404Spjd			if (why) {
317168404Spjd				*why = NAME_ERR_INVALCHAR;
318168404Spjd				*what = *c;
319168404Spjd			}
320168404Spjd			return (-1);
321168404Spjd		}
322168404Spjd		c++;
323168404Spjd	}
324168404Spjd
325168404Spjd	if (!(*pool >= 'a' && *pool <= 'z') &&
326168404Spjd	    !(*pool >= 'A' && *pool <= 'Z')) {
327168404Spjd		if (why)
328168404Spjd			*why = NAME_ERR_NOLETTER;
329168404Spjd		return (-1);
330168404Spjd	}
331168404Spjd
332168404Spjd	if (strcmp(pool, "mirror") == 0 || strcmp(pool, "raidz") == 0) {
333168404Spjd		if (why)
334168404Spjd			*why = NAME_ERR_RESERVED;
335168404Spjd		return (-1);
336168404Spjd	}
337168404Spjd
338168404Spjd	if (pool[0] == 'c' && (pool[1] >= '0' && pool[1] <= '9')) {
339168404Spjd		if (why)
340168404Spjd			*why = NAME_ERR_DISKLIKE;
341168404Spjd		return (-1);
342168404Spjd	}
343168404Spjd
344168404Spjd	return (0);
345168404Spjd}
346