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 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <assert.h>
27 #include <repcache_protocol.h>
28 #include "scf_type.h"
29 #include <errno.h>
30 #include <libgen.h>
31 #include <libscf_priv.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38
39 #define UTF8_TOP_N(n) \
40 (0xff ^ (0xff >> (n))) /* top N bits set */
41
42 #define UTF8_BOTTOM_N(n) \
43 ((1 << (n)) - 1) /* bottom N bits set */
44
45 /*
46 * The first byte of an n-byte UTF8 encoded character looks like:
47 *
48 * n bits
49 *
50 * 1 0xxxxxxx
51 * 2 110xxxxx
52 * 3 1110xxxx
53 * 4 11110xxx
54 * 5 111110xx
55 * 6 1111110x
56 *
57 * Continuation bytes are 01xxxxxx.
58 */
59
60 #define UTF8_MAX_BYTES 6
61
62 /*
63 * number of bits in an n-byte UTF-8 encoding. for multi-byte encodings,
64 * You get (7 - n) bits in the first byte, and 6 bits for each additional byte.
65 */
66 #define UTF8_BITS(n) /* 1 <= n <= 6 */ \
67 ((n) == 1)? 7 : \
68 (7 - (n) + 6 * ((n) - 1))
69
70 #define UTF8_SINGLE_BYTE(c) \
71 (((c) & UTF8_TOP_N(1)) == 0) /* 0xxxxxxx */
72
73 #define UTF8_HEAD_CHECK(c, n) /* 2 <= n <= 6 */ \
74 (((c) & UTF8_TOP_N((n) + 1)) == UTF8_TOP_N(n))
75
76 #define UTF8_HEAD_VALUE(c, n) /* 2 <= n <= 6 */ \
77 ((c) & UTF8_BOTTOM_N(7 - (n))) /* 'x' mask */
78
79 #define UTF8_CONT_CHECK(c) \
80 (((c) & UTF8_TOP_N(2)) == UTF8_TOP_N(1)) /* 10xxxxxx */
81
82 /*
83 * adds in the 6 new bits from a continuation byte
84 */
85 #define UTF8_VALUE_UPDATE(v, c) \
86 (((v) << 6) | ((c) & UTF8_BOTTOM_N(6)))
87
88 /*
89 * URI components
90 */
91
92 #define URI_COMPONENT_COUNT 5
93
94 enum {
95 URI_SCHEME = 0x0, /* URI scheme */
96 URI_AUTHORITY, /* URI authority */
97 URI_PATH, /* URI path */
98 URI_QUERY, /* URI query */
99 URI_FRAGMENT /* URI fragment */
100 };
101
102 static int
valid_utf8(const char * str_arg)103 valid_utf8(const char *str_arg)
104 {
105 const char *str = str_arg;
106 uint_t c;
107 uint32_t v;
108 int i, n;
109
110 while ((c = *str++) != 0) {
111 if (UTF8_SINGLE_BYTE(c))
112 continue; /* ascii */
113
114 for (n = 2; n <= UTF8_MAX_BYTES; n++)
115 if (UTF8_HEAD_CHECK(c, n))
116 break;
117
118 if (n > UTF8_MAX_BYTES)
119 return (0); /* invalid head byte */
120
121 v = UTF8_HEAD_VALUE(c, n);
122
123 for (i = 1; i < n; i++) {
124 c = *str++;
125 if (!UTF8_CONT_CHECK(c))
126 return (0); /* invalid byte */
127
128 v = UTF8_VALUE_UPDATE(v, c);
129 }
130
131 /*
132 * if v could have been encoded in the next smallest
133 * encoding, the string is not well-formed UTF-8.
134 */
135 if ((v >> (UTF8_BITS(n - 1))) == 0)
136 return (0);
137 }
138
139 /*
140 * we've reached the end of the string -- make sure it is short enough
141 */
142 return ((str - str_arg) < REP_PROTOCOL_VALUE_LEN);
143 }
144
145 static int
valid_string(const char * str)146 valid_string(const char *str)
147 {
148 return (strlen(str) < REP_PROTOCOL_VALUE_LEN);
149 }
150
151 static int
valid_opaque(const char * str_arg)152 valid_opaque(const char *str_arg)
153 {
154 const char *str = str_arg;
155 uint_t c;
156 ptrdiff_t len;
157
158 while ((c = *str++) != 0)
159 if ((c < '0' || c > '9') && (c < 'a' || c > 'f') &&
160 (c < 'A' || c > 'F'))
161 return (0); /* not hex digit */
162
163 len = (str - str_arg) - 1; /* not counting NIL byte */
164 return ((len % 2) == 0 && len / 2 < REP_PROTOCOL_VALUE_LEN);
165 }
166
167 /*
168 * Return 1 if the supplied parameter is a conformant URI (as defined
169 * by RFC 2396), 0 otherwise.
170 */
171 static int
valid_uri(const char * str)172 valid_uri(const char *str)
173 {
174 /*
175 * URI Regular Expression. Compiled with regcmp(1).
176 *
177 * ^(([^:/?#]+:){0,1})$0(//([^/?#]*)$1){0,1}([^?#]*)$2
178 * (?([^#]*)$3){0,1}(#(.*)$4){0,1}
179 */
180 char exp[] = {
181 040, 074, 00, 060, 012, 0126, 05, 072, 057, 077, 043, 024,
182 072, 057, 00, 00, 01, 014, 00, 00, 060, 020, 024, 057,
183 024, 057, 074, 01, 0125, 04, 057, 077, 043, 014, 01, 01,
184 057, 01, 00, 01, 074, 02, 0125, 03, 077, 043, 014, 02,
185 02, 060, 014, 024, 077, 074, 03, 0125, 02, 043, 014, 03,
186 03, 057, 02, 00, 01, 060, 012, 024, 043, 074, 04, 021,
187 014, 04, 04, 057, 03, 00, 01, 064, 00,
188 0};
189 char uri[URI_COMPONENT_COUNT][REP_PROTOCOL_VALUE_LEN];
190
191 /*
192 * If the string is too long, then the URI cannot be valid. Also,
193 * this protects against buffer overflow attacks on the uri array.
194 */
195 if (strlen(str) >= REP_PROTOCOL_VALUE_LEN)
196 return (0);
197
198 if (regex(exp, str, uri[URI_SCHEME], uri[URI_AUTHORITY], uri[URI_PATH],
199 uri[URI_QUERY], uri[URI_FRAGMENT]) == NULL) {
200 return (0);
201 }
202 /*
203 * To be a valid URI, the length of the URI_PATH must not be zero
204 */
205 if (strlen(uri[URI_PATH]) == 0) {
206 return (0);
207 }
208 return (1);
209 }
210
211 /*
212 * Return 1 if the supplied parameter is a conformant fmri, 0
213 * otherwise.
214 */
215 static int
valid_fmri(const char * str)216 valid_fmri(const char *str)
217 {
218 int ret;
219 char fmri[REP_PROTOCOL_VALUE_LEN] = { 0 };
220
221 /*
222 * Try to parse the fmri, if we can parse it then it
223 * must be syntactically correct. Work on a copy of
224 * the fmri since the parsing process can modify the
225 * supplied string.
226 */
227 if (strlcpy(fmri, str, sizeof (fmri)) >= sizeof (fmri))
228 return (0);
229
230 ret = ! scf_parse_fmri(fmri, NULL, NULL, NULL, NULL, NULL, NULL);
231
232 return (ret);
233 }
234
235 /*
236 * check_prefix()
237 * Return 1 if the prefix is a valid IPv4 or IPv6 network prefix, 0 otherwise
238 */
239 static int
check_net_prefix(const char * p,int max_len)240 check_net_prefix(const char *p, int max_len)
241 {
242 char *end;
243 int len;
244
245 len = strtol(p, &end, 10);
246 if (p == end || len < 0 || len > max_len)
247 return (0);
248
249 return (1);
250 }
251
252 /*
253 * Return 1 if the supplied IP address is valid, 0 otherwise.
254 */
255 static int
valid_ip(int af,const char * str)256 valid_ip(int af, const char *str)
257 {
258 void *unused[4];
259 const char *addr = str;
260 char buf[INET6_ADDRSTRLEN]; /* enough for both IPv4 and IPv6 */
261 char *net_prefix;
262 int buf_sz;
263 int plen;
264
265 switch (af) {
266 case AF_INET:
267 buf_sz = INET_ADDRSTRLEN;
268 plen = 32; /* bit size of an IPv4 */
269 break;
270
271 case AF_INET6:
272 buf_sz = INET6_ADDRSTRLEN;
273 plen = 128; /* bit size of an IPv6 */
274 break;
275
276 default:
277 assert(0);
278 abort();
279 }
280
281 /* check network prefix for the IP address */
282 if ((net_prefix = strchr(str, '/')) != NULL) {
283 if (check_net_prefix(++net_prefix, plen) == 0)
284 return (0);
285
286 (void) strlcpy(buf, str, buf_sz);
287 if ((net_prefix = strchr(buf, '/')) != NULL)
288 *net_prefix = '\0';
289
290 addr = buf;
291 }
292
293 return (inet_pton(af, addr, unused));
294 }
295
296 rep_protocol_value_type_t
scf_proto_underlying_type(rep_protocol_value_type_t t)297 scf_proto_underlying_type(rep_protocol_value_type_t t)
298 {
299 switch (t) {
300 case REP_PROTOCOL_TYPE_BOOLEAN:
301 case REP_PROTOCOL_TYPE_COUNT:
302 case REP_PROTOCOL_TYPE_INTEGER:
303 case REP_PROTOCOL_TYPE_TIME:
304 case REP_PROTOCOL_TYPE_STRING:
305 case REP_PROTOCOL_TYPE_OPAQUE:
306 return (t);
307
308 case REP_PROTOCOL_SUBTYPE_USTRING:
309 return (REP_PROTOCOL_TYPE_STRING);
310
311 case REP_PROTOCOL_SUBTYPE_URI:
312 return (REP_PROTOCOL_SUBTYPE_USTRING);
313 case REP_PROTOCOL_SUBTYPE_FMRI:
314 return (REP_PROTOCOL_SUBTYPE_URI);
315
316 case REP_PROTOCOL_SUBTYPE_HOST:
317 return (REP_PROTOCOL_SUBTYPE_USTRING);
318 case REP_PROTOCOL_SUBTYPE_HOSTNAME:
319 return (REP_PROTOCOL_SUBTYPE_HOST);
320 case REP_PROTOCOL_SUBTYPE_NETADDR:
321 return (REP_PROTOCOL_SUBTYPE_HOST);
322 case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
323 return (REP_PROTOCOL_SUBTYPE_NETADDR);
324 case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
325 return (REP_PROTOCOL_SUBTYPE_NETADDR);
326
327 case REP_PROTOCOL_TYPE_INVALID:
328 default:
329 return (REP_PROTOCOL_TYPE_INVALID);
330 }
331 }
332
333 int
scf_is_compatible_protocol_type(rep_protocol_value_type_t base,rep_protocol_value_type_t new)334 scf_is_compatible_protocol_type(rep_protocol_value_type_t base,
335 rep_protocol_value_type_t new)
336 {
337 rep_protocol_value_type_t t, cur;
338
339 if (base == REP_PROTOCOL_TYPE_INVALID)
340 return (0);
341
342 if (base == new)
343 return (1);
344
345 for (t = new; t != (cur = scf_proto_underlying_type(t)); t = cur) {
346 if (cur == REP_PROTOCOL_TYPE_INVALID)
347 return (0);
348 if (cur == base)
349 return (1); /* base is parent of new */
350 }
351 return (0);
352 }
353
354 static int
valid_encoded_value(rep_protocol_value_type_t t,const char * v)355 valid_encoded_value(rep_protocol_value_type_t t, const char *v)
356 {
357 char *p;
358 ulong_t ns;
359
360 switch (t) {
361 case REP_PROTOCOL_TYPE_BOOLEAN:
362 return ((*v == '0' || *v == '1') && v[1] == 0);
363
364 case REP_PROTOCOL_TYPE_COUNT:
365 errno = 0;
366 if (strtoull(v, &p, 10) != 0 && *v == '0')
367 return (0);
368 return (errno == 0 && p != v && *p == 0);
369
370 case REP_PROTOCOL_TYPE_INTEGER:
371 errno = 0;
372 if (strtoll(v, &p, 10) != 0 && *v == '0')
373 return (0);
374 return (errno == 0 && p != v && *p == 0);
375
376 case REP_PROTOCOL_TYPE_TIME:
377 errno = 0;
378 (void) strtoll(v, &p, 10);
379 if (errno != 0 || p == v || (*p != 0 && *p != '.'))
380 return (0);
381 if (*p == '.') {
382 v = p + 1;
383 errno = 0;
384 ns = strtoul(v, &p, 10);
385
386 /* must be exactly 9 digits */
387 if ((p - v) != 9 || errno != 0 || *p != 0)
388 return (0);
389 if (ns >= NANOSEC)
390 return (0);
391 }
392 return (1);
393
394 case REP_PROTOCOL_TYPE_STRING:
395 return (valid_string(v));
396
397 case REP_PROTOCOL_TYPE_OPAQUE:
398 return (valid_opaque(v));
399
400 /*
401 * The remaining types are subtypes -- because of the way
402 * scf_validate_encoded_value() works, we can rely on the fact
403 * that v is a valid example of our base type. We only have to
404 * check our own additional restrictions.
405 */
406 case REP_PROTOCOL_SUBTYPE_USTRING:
407 return (valid_utf8(v));
408
409 case REP_PROTOCOL_SUBTYPE_URI:
410 return (valid_uri(v));
411
412 case REP_PROTOCOL_SUBTYPE_FMRI:
413 return (valid_fmri(v));
414
415 case REP_PROTOCOL_SUBTYPE_HOST:
416 return (valid_encoded_value(REP_PROTOCOL_SUBTYPE_HOSTNAME, v) ||
417 valid_encoded_value(REP_PROTOCOL_SUBTYPE_NETADDR, v));
418
419 case REP_PROTOCOL_SUBTYPE_HOSTNAME:
420 /* XXX check for valid hostname */
421 return (valid_utf8(v));
422
423 case REP_PROTOCOL_SUBTYPE_NETADDR:
424 return (valid_ip(AF_INET, v) || valid_ip(AF_INET6, v));
425
426 case REP_PROTOCOL_SUBTYPE_NETADDR_V4:
427 return (valid_ip(AF_INET, v));
428
429 case REP_PROTOCOL_SUBTYPE_NETADDR_V6:
430 return (valid_ip(AF_INET6, v));
431
432 case REP_PROTOCOL_TYPE_INVALID:
433 default:
434 return (0);
435 }
436 }
437
438 int
scf_validate_encoded_value(rep_protocol_value_type_t t,const char * v)439 scf_validate_encoded_value(rep_protocol_value_type_t t, const char *v)
440 {
441 rep_protocol_value_type_t base, cur;
442
443 base = scf_proto_underlying_type(t);
444 while ((cur = scf_proto_underlying_type(base)) != base)
445 base = cur;
446
447 if (base != t && !valid_encoded_value(base, v))
448 return (0);
449
450 return (valid_encoded_value(t, v));
451 }
452