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 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 146 valid_string(const char *str) 147 { 148 return (strlen(str) < REP_PROTOCOL_VALUE_LEN); 149 } 150 151 static int 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 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 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 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 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 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 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 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 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