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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident       "%Z%%M%   %I%       %E% SMI"
28 
29 #include "libuutil_common.h"
30 
31 #include <string.h>
32 
33 /*
34  * We require names of the form:
35  *        [provider,]identifier[/[provider,]identifier]...
36  *
37  * Where provider is either a stock symbol (SUNW) or a java-style reversed
38  * domain name (com.sun).
39  *
40  * Both providers and identifiers must start with a letter, and may
41  * only contain alphanumerics, dashes, and underlines.  Providers
42  * may also contain periods.
43  *
44  * Note that we do _not_ use the macros in <ctype.h>, since they are affected
45  * by the current locale settings.
46  */
47 
48 #define   IS_ALPHA(c) \
49           (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
50 
51 #define   IS_DIGIT(c) \
52           ((c) >= '0' && (c) <= '9')
53 
54 static int
is_valid_ident(const char * s,const char * e,int allowdot)55 is_valid_ident(const char *s, const char *e, int allowdot)
56 {
57           char c;
58 
59           if (s >= e)
60                     return (0);                   /* name is empty */
61 
62           c = *s++;
63           if (!IS_ALPHA(c))
64                     return (0);                   /* does not start with letter */
65 
66           while (s < e && (c = *s++) != 0) {
67                     if (IS_ALPHA(c) || IS_DIGIT(c) || c == '-' || c == '_' ||
68                         (allowdot && c == '.'))
69                               continue;
70                     return (0);                   /* invalid character */
71           }
72           return (1);
73 }
74 
75 static int
is_valid_component(const char * b,const char * e,uint_t flags)76 is_valid_component(const char *b, const char *e, uint_t flags)
77 {
78           char *sp;
79 
80           if (flags & UU_NAME_DOMAIN) {
81                     sp = strchr(b, ',');
82                     if (sp != NULL && sp < e) {
83                               if (!is_valid_ident(b, sp, 1))
84                                         return (0);
85                               b = sp + 1;
86                     }
87           }
88 
89           return (is_valid_ident(b, e, 0));
90 }
91 
92 int
uu_check_name(const char * name,uint_t flags)93 uu_check_name(const char *name, uint_t flags)
94 {
95           const char *end = name + strlen(name);
96           const char *p;
97 
98           if (flags & ~(UU_NAME_DOMAIN | UU_NAME_PATH)) {
99                     uu_set_error(UU_ERROR_UNKNOWN_FLAG);
100                     return (-1);
101           }
102 
103           if (!(flags & UU_NAME_PATH)) {
104                     if (!is_valid_component(name, end, flags))
105                               goto bad;
106                     return (0);
107           }
108 
109           while ((p = strchr(name, '/')) != NULL) {
110                     if (!is_valid_component(name, p - 1, flags))
111                               goto bad;
112                     name = p + 1;
113           }
114           if (!is_valid_component(name, end, flags))
115                     goto bad;
116 
117           return (0);
118 
119 bad:
120           uu_set_error(UU_ERROR_INVALID_ARGUMENT);
121           return (-1);
122 }
123