dbus-marshal-validate.c revision dbecdeabb20e0ce11121819c63373f0afba57c58
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2/* dbus-marshal-validate.c Validation routines for marshaled data 3 * 4 * Copyright (C) 2005 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24#include <config.h> 25#include "dbus-internals.h" 26#include "dbus-marshal-validate.h" 27#include "dbus-marshal-recursive.h" 28#include "dbus-marshal-basic.h" 29#include "dbus-signature.h" 30#include "dbus-string.h" 31 32/** 33 * @addtogroup DBusMarshal 34 * 35 * @{ 36 */ 37 38/** 39 * Verifies that the range of type_str from type_pos to type_end is a 40 * valid signature. If this function returns #TRUE, it will be safe 41 * to iterate over the signature with a types-only #DBusTypeReader. 42 * The range passed in should NOT include the terminating 43 * nul/DBUS_TYPE_INVALID. 44 * 45 * @param type_str the string 46 * @param type_pos where the typecodes start 47 * @param len length of typecodes 48 * @returns #DBUS_VALID if valid, reason why invalid otherwise 49 */ 50DBusValidity 51_dbus_validate_signature_with_reason (const DBusString *type_str, 52 int type_pos, 53 int len) 54{ 55 const unsigned char *p; 56 const unsigned char *end; 57 int last; 58 int struct_depth; 59 int array_depth; 60 int dict_entry_depth; 61 DBusValidity result; 62 63 int element_count; 64 DBusList *element_count_stack; 65 66 result = DBUS_VALID; 67 element_count_stack = NULL; 68 69 if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) 70 { 71 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 72 goto out; 73 } 74 75 _dbus_assert (type_str != NULL); 76 _dbus_assert (type_pos < _DBUS_INT32_MAX - len); 77 _dbus_assert (len >= 0); 78 _dbus_assert (type_pos >= 0); 79 80 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 81 { 82 result = DBUS_INVALID_SIGNATURE_TOO_LONG; 83 goto out; 84 } 85 86 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 87 88 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 89 struct_depth = 0; 90 array_depth = 0; 91 dict_entry_depth = 0; 92 last = DBUS_TYPE_INVALID; 93 94 while (p != end) 95 { 96 switch (*p) 97 { 98 case DBUS_TYPE_BYTE: 99 case DBUS_TYPE_BOOLEAN: 100 case DBUS_TYPE_INT16: 101 case DBUS_TYPE_UINT16: 102 case DBUS_TYPE_INT32: 103 case DBUS_TYPE_UINT32: 104 case DBUS_TYPE_UNIX_FD: 105 case DBUS_TYPE_INT64: 106 case DBUS_TYPE_UINT64: 107 case DBUS_TYPE_DOUBLE: 108 case DBUS_TYPE_STRING: 109 case DBUS_TYPE_OBJECT_PATH: 110 case DBUS_TYPE_SIGNATURE: 111 case DBUS_TYPE_VARIANT: 112 break; 113 114 case DBUS_TYPE_ARRAY: 115 array_depth += 1; 116 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 117 { 118 result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 119 goto out; 120 } 121 break; 122 123 case DBUS_STRUCT_BEGIN_CHAR: 124 struct_depth += 1; 125 126 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 127 { 128 result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 129 goto out; 130 } 131 132 if (!_dbus_list_append (&element_count_stack, 133 _DBUS_INT_TO_POINTER (0))) 134 { 135 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 136 goto out; 137 } 138 139 break; 140 141 case DBUS_STRUCT_END_CHAR: 142 if (struct_depth == 0) 143 { 144 result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 145 goto out; 146 } 147 148 if (last == DBUS_STRUCT_BEGIN_CHAR) 149 { 150 result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 151 goto out; 152 } 153 154 _dbus_list_pop_last (&element_count_stack); 155 156 struct_depth -= 1; 157 break; 158 159 case DBUS_DICT_ENTRY_BEGIN_CHAR: 160 if (last != DBUS_TYPE_ARRAY) 161 { 162 result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; 163 goto out; 164 } 165 166 dict_entry_depth += 1; 167 168 if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 169 { 170 result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 171 goto out; 172 } 173 174 if (!_dbus_list_append (&element_count_stack, 175 _DBUS_INT_TO_POINTER (0))) 176 { 177 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 178 goto out; 179 } 180 181 break; 182 183 case DBUS_DICT_ENTRY_END_CHAR: 184 if (dict_entry_depth == 0) 185 { 186 result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 187 goto out; 188 } 189 190 dict_entry_depth -= 1; 191 192 element_count = 193 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 194 195 if (element_count != 2) 196 { 197 if (element_count == 0) 198 result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 199 else if (element_count == 1) 200 result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD; 201 else 202 result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS; 203 204 goto out; 205 } 206 break; 207 208 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 209 case DBUS_TYPE_DICT_ENTRY: /* ditto */ 210 default: 211 result = DBUS_INVALID_UNKNOWN_TYPECODE; 212 goto out; 213 } 214 215 if (*p != DBUS_TYPE_ARRAY && 216 *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 217 *p != DBUS_STRUCT_BEGIN_CHAR) 218 { 219 element_count = 220 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 221 222 ++element_count; 223 224 if (!_dbus_list_append (&element_count_stack, 225 _DBUS_INT_TO_POINTER (element_count))) 226 { 227 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 228 goto out; 229 } 230 } 231 232 if (array_depth > 0) 233 { 234 if (*p == DBUS_TYPE_ARRAY && p != end) 235 { 236 const char *p1; 237 p1 = p + 1; 238 if (*p1 == DBUS_STRUCT_END_CHAR || 239 *p1 == DBUS_DICT_ENTRY_END_CHAR) 240 { 241 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 242 goto out; 243 } 244 } 245 else 246 { 247 array_depth = 0; 248 } 249 } 250 251 if (last == DBUS_DICT_ENTRY_BEGIN_CHAR) 252 { 253 if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p))) 254 { 255 result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; 256 goto out; 257 } 258 } 259 260 last = *p; 261 ++p; 262 } 263 264 265 if (array_depth > 0) 266 { 267 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 268 goto out; 269 } 270 271 if (struct_depth > 0) 272 { 273 result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 274 goto out; 275 } 276 277 if (dict_entry_depth > 0) 278 { 279 result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 280 goto out; 281 } 282 283 _dbus_assert (last != DBUS_TYPE_ARRAY); 284 _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); 285 _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); 286 287 result = DBUS_VALID; 288 289out: 290 _dbus_list_clear (&element_count_stack); 291 return result; 292} 293 294static DBusValidity 295validate_body_helper (DBusTypeReader *reader, 296 int byte_order, 297 dbus_bool_t walk_reader_to_end, 298 const unsigned char *p, 299 const unsigned char *end, 300 const unsigned char **new_p) 301{ 302 int current_type; 303 304 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 305 { 306 const unsigned char *a; 307 int alignment; 308 309#if 0 310 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 311 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 312 (int) (end - p)); 313#endif 314 315 /* Guarantee that p has one byte to look at */ 316 if (p == end) 317 return DBUS_INVALID_NOT_ENOUGH_DATA; 318 319 switch (current_type) 320 { 321 case DBUS_TYPE_BYTE: 322 ++p; 323 break; 324 325 case DBUS_TYPE_BOOLEAN: 326 case DBUS_TYPE_INT16: 327 case DBUS_TYPE_UINT16: 328 case DBUS_TYPE_INT32: 329 case DBUS_TYPE_UINT32: 330 case DBUS_TYPE_UNIX_FD: 331 case DBUS_TYPE_INT64: 332 case DBUS_TYPE_UINT64: 333 case DBUS_TYPE_DOUBLE: 334 alignment = _dbus_type_get_alignment (current_type); 335 a = _DBUS_ALIGN_ADDRESS (p, alignment); 336 if (a >= end) 337 return DBUS_INVALID_NOT_ENOUGH_DATA; 338 while (p != a) 339 { 340 if (*p != '\0') 341 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 342 ++p; 343 } 344 345 if (current_type == DBUS_TYPE_BOOLEAN) 346 { 347 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 348 p); 349 if (!(v == 0 || v == 1)) 350 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 351 } 352 353 p += alignment; 354 break; 355 356 case DBUS_TYPE_ARRAY: 357 case DBUS_TYPE_STRING: 358 case DBUS_TYPE_OBJECT_PATH: 359 { 360 dbus_uint32_t claimed_len; 361 362 a = _DBUS_ALIGN_ADDRESS (p, 4); 363 if (a + 4 > end) 364 return DBUS_INVALID_NOT_ENOUGH_DATA; 365 while (p != a) 366 { 367 if (*p != '\0') 368 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 369 ++p; 370 } 371 372 claimed_len = _dbus_unpack_uint32 (byte_order, p); 373 p += 4; 374 375 /* p may now be == end */ 376 _dbus_assert (p <= end); 377 378 if (current_type == DBUS_TYPE_ARRAY) 379 { 380 int array_elem_type = _dbus_type_reader_get_element_type (reader); 381 382 if (!_dbus_type_is_valid (array_elem_type)) 383 { 384 return DBUS_INVALID_UNKNOWN_TYPECODE; 385 } 386 387 alignment = _dbus_type_get_alignment (array_elem_type); 388 389 a = _DBUS_ALIGN_ADDRESS (p, alignment); 390 391 /* a may now be == end */ 392 if (a > end) 393 return DBUS_INVALID_NOT_ENOUGH_DATA; 394 395 while (p != a) 396 { 397 if (*p != '\0') 398 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 399 ++p; 400 } 401 } 402 403 if (claimed_len > (unsigned long) (end - p)) 404 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 405 406 if (current_type == DBUS_TYPE_OBJECT_PATH) 407 { 408 DBusString str; 409 _dbus_string_init_const_len (&str, p, claimed_len); 410 if (!_dbus_validate_path (&str, 0, 411 _dbus_string_get_length (&str))) 412 return DBUS_INVALID_BAD_PATH; 413 414 p += claimed_len; 415 } 416 else if (current_type == DBUS_TYPE_STRING) 417 { 418 DBusString str; 419 _dbus_string_init_const_len (&str, p, claimed_len); 420 if (!_dbus_string_validate_utf8 (&str, 0, 421 _dbus_string_get_length (&str))) 422 return DBUS_INVALID_BAD_UTF8_IN_STRING; 423 424 p += claimed_len; 425 } 426 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 427 { 428 DBusTypeReader sub; 429 DBusValidity validity; 430 const unsigned char *array_end; 431 int array_elem_type; 432 433 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 434 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 435 436 /* Remember that the reader is types only, so we can't 437 * use it to iterate over elements. It stays the same 438 * for all elements. 439 */ 440 _dbus_type_reader_recurse (reader, &sub); 441 442 array_end = p + claimed_len; 443 444 array_elem_type = _dbus_type_reader_get_element_type (reader); 445 446 /* avoid recursive call to validate_body_helper if this is an array 447 * of fixed-size elements 448 */ 449 if (dbus_type_is_fixed (array_elem_type)) 450 { 451 /* bools need to be handled differently, because they can 452 * have an invalid value 453 */ 454 if (array_elem_type == DBUS_TYPE_BOOLEAN) 455 { 456 dbus_uint32_t v; 457 alignment = _dbus_type_get_alignment (array_elem_type); 458 459 while (p < array_end) 460 { 461 v = _dbus_unpack_uint32 (byte_order, p); 462 463 if (!(v == 0 || v == 1)) 464 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 465 466 p += alignment; 467 } 468 } 469 470 else 471 { 472 p = array_end; 473 } 474 } 475 476 else 477 { 478 while (p < array_end) 479 { 480 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 481 if (validity != DBUS_VALID) 482 return validity; 483 } 484 } 485 486 if (p != array_end) 487 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 488 } 489 490 /* check nul termination */ 491 if (current_type != DBUS_TYPE_ARRAY) 492 { 493 if (p == end) 494 return DBUS_INVALID_NOT_ENOUGH_DATA; 495 496 if (*p != '\0') 497 return DBUS_INVALID_STRING_MISSING_NUL; 498 ++p; 499 } 500 } 501 break; 502 503 case DBUS_TYPE_SIGNATURE: 504 { 505 dbus_uint32_t claimed_len; 506 DBusString str; 507 DBusValidity validity; 508 509 claimed_len = *p; 510 ++p; 511 512 /* 1 is for nul termination */ 513 if (claimed_len + 1 > (unsigned long) (end - p)) 514 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 515 516 _dbus_string_init_const_len (&str, p, claimed_len); 517 validity = 518 _dbus_validate_signature_with_reason (&str, 0, 519 _dbus_string_get_length (&str)); 520 521 if (validity != DBUS_VALID) 522 return validity; 523 524 p += claimed_len; 525 526 _dbus_assert (p < end); 527 if (*p != DBUS_TYPE_INVALID) 528 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 529 530 ++p; 531 532 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 533 } 534 break; 535 536 case DBUS_TYPE_VARIANT: 537 { 538 /* 1 byte sig len, sig typecodes, align to 539 * contained-type-boundary, values. 540 */ 541 542 /* In addition to normal signature validation, we need to be sure 543 * the signature contains only a single (possibly container) type. 544 */ 545 dbus_uint32_t claimed_len; 546 DBusString sig; 547 DBusTypeReader sub; 548 DBusValidity validity; 549 int contained_alignment; 550 int contained_type; 551 DBusValidity reason; 552 553 claimed_len = *p; 554 ++p; 555 556 /* + 1 for nul */ 557 if (claimed_len + 1 > (unsigned long) (end - p)) 558 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 559 560 _dbus_string_init_const_len (&sig, p, claimed_len); 561 reason = _dbus_validate_signature_with_reason (&sig, 0, 562 _dbus_string_get_length (&sig)); 563 if (!(reason == DBUS_VALID)) 564 { 565 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 566 return reason; 567 else 568 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 569 } 570 571 p += claimed_len; 572 573 if (*p != DBUS_TYPE_INVALID) 574 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 575 ++p; 576 577 contained_type = _dbus_first_type_in_signature (&sig, 0); 578 if (contained_type == DBUS_TYPE_INVALID) 579 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 580 581 contained_alignment = _dbus_type_get_alignment (contained_type); 582 583 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 584 if (a > end) 585 return DBUS_INVALID_NOT_ENOUGH_DATA; 586 while (p != a) 587 { 588 if (*p != '\0') 589 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 590 ++p; 591 } 592 593 _dbus_type_reader_init_types_only (&sub, &sig, 0); 594 595 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 596 597 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 598 if (validity != DBUS_VALID) 599 return validity; 600 601 if (_dbus_type_reader_next (&sub)) 602 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 603 604 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 605 } 606 break; 607 608 case DBUS_TYPE_DICT_ENTRY: 609 case DBUS_TYPE_STRUCT: 610 { 611 DBusTypeReader sub; 612 DBusValidity validity; 613 614 a = _DBUS_ALIGN_ADDRESS (p, 8); 615 if (a > end) 616 return DBUS_INVALID_NOT_ENOUGH_DATA; 617 while (p != a) 618 { 619 if (*p != '\0') 620 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 621 ++p; 622 } 623 624 _dbus_type_reader_recurse (reader, &sub); 625 626 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 627 if (validity != DBUS_VALID) 628 return validity; 629 } 630 break; 631 632 default: 633 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 634 break; 635 } 636 637#if 0 638 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 639 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 640 (int) (end - p)); 641#endif 642 643 if (p > end) 644 { 645 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 646 p, end, (int) (end - p)); 647 return DBUS_INVALID_NOT_ENOUGH_DATA; 648 } 649 650 if (walk_reader_to_end) 651 _dbus_type_reader_next (reader); 652 else 653 break; 654 } 655 656 if (new_p) 657 *new_p = p; 658 659 return DBUS_VALID; 660} 661 662/** 663 * Verifies that the range of value_str from value_pos to value_end is 664 * a legitimate value of type expected_signature. If this function 665 * returns #TRUE, it will be safe to iterate over the values with 666 * #DBusTypeReader. The signature is assumed to be already valid. 667 * 668 * If bytes_remaining is not #NULL, then leftover bytes will be stored 669 * there and #DBUS_VALID returned. If it is #NULL, then 670 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left 671 * over. 672 * 673 * @param expected_signature the expected types in the value_str 674 * @param expected_signature_start where in expected_signature is the signature 675 * @param byte_order the byte order 676 * @param bytes_remaining place to store leftover bytes 677 * @param value_str the string containing the body 678 * @param value_pos where the values start 679 * @param len length of values after value_pos 680 * @returns #DBUS_VALID if valid, reason why invalid otherwise 681 */ 682DBusValidity 683_dbus_validate_body_with_reason (const DBusString *expected_signature, 684 int expected_signature_start, 685 int byte_order, 686 int *bytes_remaining, 687 const DBusString *value_str, 688 int value_pos, 689 int len) 690{ 691 DBusTypeReader reader; 692 const unsigned char *p; 693 const unsigned char *end; 694 DBusValidity validity; 695 696 _dbus_assert (len >= 0); 697 _dbus_assert (value_pos >= 0); 698 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 699 700 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 701 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 702 expected_signature_start, 703 0)); 704 705 _dbus_type_reader_init_types_only (&reader, 706 expected_signature, expected_signature_start); 707 708 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 709 end = p + len; 710 711 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 712 if (validity != DBUS_VALID) 713 return validity; 714 715 if (bytes_remaining) 716 { 717 *bytes_remaining = end - p; 718 return DBUS_VALID; 719 } 720 else if (p < end) 721 return DBUS_INVALID_TOO_MUCH_DATA; 722 else 723 { 724 _dbus_assert (p == end); 725 return DBUS_VALID; 726 } 727} 728 729/** 730 * Determine wether the given character is valid as the first character 731 * in a name. 732 */ 733#define VALID_INITIAL_NAME_CHARACTER(c) \ 734 ( ((c) >= 'A' && (c) <= 'Z') || \ 735 ((c) >= 'a' && (c) <= 'z') || \ 736 ((c) == '_') ) 737 738/** 739 * Determine wether the given character is valid as a second or later 740 * character in a name 741 */ 742#define VALID_NAME_CHARACTER(c) \ 743 ( ((c) >= '0' && (c) <= '9') || \ 744 ((c) >= 'A' && (c) <= 'Z') || \ 745 ((c) >= 'a' && (c) <= 'z') || \ 746 ((c) == '_') ) 747 748/** 749 * Checks that the given range of the string is a valid object path 750 * name in the D-Bus protocol. Part of the validation ensures that 751 * the object path contains only ASCII. 752 * 753 * @todo this is inconsistent with most of DBusString in that 754 * it allows a start,len range that extends past the string end. 755 * 756 * @todo change spec to disallow more things, such as spaces in the 757 * path name 758 * 759 * @param str the string 760 * @param start first byte index to check 761 * @param len number of bytes to check 762 * @returns #TRUE if the byte range exists and is a valid name 763 */ 764dbus_bool_t 765_dbus_validate_path (const DBusString *str, 766 int start, 767 int len) 768{ 769 const unsigned char *s; 770 const unsigned char *end; 771 const unsigned char *last_slash; 772 773 _dbus_assert (start >= 0); 774 _dbus_assert (len >= 0); 775 _dbus_assert (start <= _dbus_string_get_length (str)); 776 777 if (len > _dbus_string_get_length (str) - start) 778 return FALSE; 779 780 if (len == 0) 781 return FALSE; 782 783 s = _dbus_string_get_const_data (str) + start; 784 end = s + len; 785 786 if (*s != '/') 787 return FALSE; 788 last_slash = s; 789 ++s; 790 791 while (s != end) 792 { 793 if (*s == '/') 794 { 795 if ((s - last_slash) < 2) 796 return FALSE; /* no empty path components allowed */ 797 798 last_slash = s; 799 } 800 else 801 { 802 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 803 return FALSE; 804 } 805 806 ++s; 807 } 808 809 if ((end - last_slash) < 2 && 810 len > 1) 811 return FALSE; /* trailing slash not allowed unless the string is "/" */ 812 813 return TRUE; 814} 815 816const char * 817_dbus_validity_to_error_message (DBusValidity validity) 818{ 819 switch (validity) 820 { 821 case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory"; 822 case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason"; 823 case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete"; 824 case DBUS_VALIDITY_UNKNOWN: return "Validity unknown"; 825 case DBUS_VALID: return "Valid"; 826 case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode"; 827 case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type"; 828 case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long"; 829 case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion"; 830 case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion"; 831 case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started"; 832 case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended"; 833 case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields"; 834 case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null"; 835 case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one"; 836 case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data"; 837 case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data"; 838 case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order"; 839 case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version"; 840 case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type"; 841 case DBUS_INVALID_BAD_SERIAL: return "Bad serial"; 842 case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length"; 843 case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length"; 844 case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long"; 845 case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code"; 846 case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type"; 847 case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface"; 848 case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path"; 849 case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice"; 850 case DBUS_INVALID_BAD_DESTINATION: return "Bad destination"; 851 case DBUS_INVALID_BAD_INTERFACE: return "Bad interface"; 852 case DBUS_INVALID_BAD_MEMBER: return "Bad member"; 853 case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name"; 854 case DBUS_INVALID_BAD_SENDER: return "Bad sender"; 855 case DBUS_INVALID_MISSING_PATH: return "Missing path"; 856 case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface"; 857 case DBUS_INVALID_MISSING_MEMBER: return "Missing member"; 858 case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name"; 859 case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial"; 860 case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds"; 861 case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum"; 862 case DBUS_INVALID_BAD_PATH: return "Bad path"; 863 case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds"; 864 case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string"; 865 case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect"; 866 case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds"; 867 case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad"; 868 case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty"; 869 case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values"; 870 case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul"; 871 case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul"; 872 case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul"; 873 case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion"; 874 case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started"; 875 case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended"; 876 case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields"; 877 case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field"; 878 case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields"; 879 case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array"; 880 case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type"; 881 882 default: 883 return "Invalid"; 884 } 885} 886 887/** 888 * Checks that the given range of the string is a valid interface name 889 * in the D-Bus protocol. This includes a length restriction and an 890 * ASCII subset, see the specification. 891 * 892 * @todo this is inconsistent with most of DBusString in that 893 * it allows a start,len range that extends past the string end. 894 * 895 * @param str the string 896 * @param start first byte index to check 897 * @param len number of bytes to check 898 * @returns #TRUE if the byte range exists and is a valid name 899 */ 900dbus_bool_t 901_dbus_validate_interface (const DBusString *str, 902 int start, 903 int len) 904{ 905 const unsigned char *s; 906 const unsigned char *end; 907 const unsigned char *iface; 908 const unsigned char *last_dot; 909 910 _dbus_assert (start >= 0); 911 _dbus_assert (len >= 0); 912 _dbus_assert (start <= _dbus_string_get_length (str)); 913 914 if (len > _dbus_string_get_length (str) - start) 915 return FALSE; 916 917 if (len > DBUS_MAXIMUM_NAME_LENGTH) 918 return FALSE; 919 920 if (len == 0) 921 return FALSE; 922 923 last_dot = NULL; 924 iface = _dbus_string_get_const_data (str) + start; 925 end = iface + len; 926 s = iface; 927 928 /* check special cases of first char so it doesn't have to be done 929 * in the loop. Note we know len > 0 930 */ 931 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 932 return FALSE; 933 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 934 return FALSE; 935 else 936 ++s; 937 938 while (s != end) 939 { 940 if (*s == '.') 941 { 942 if (_DBUS_UNLIKELY ((s + 1) == end)) 943 return FALSE; 944 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 945 return FALSE; 946 last_dot = s; 947 ++s; /* we just validated the next char, so skip two */ 948 } 949 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 950 { 951 return FALSE; 952 } 953 954 ++s; 955 } 956 957 if (_DBUS_UNLIKELY (last_dot == NULL)) 958 return FALSE; 959 960 return TRUE; 961} 962 963/** 964 * Checks that the given range of the string is a valid member name 965 * in the D-Bus protocol. This includes a length restriction, etc., 966 * see the specification. 967 * 968 * @todo this is inconsistent with most of DBusString in that 969 * it allows a start,len range that extends past the string end. 970 * 971 * @param str the string 972 * @param start first byte index to check 973 * @param len number of bytes to check 974 * @returns #TRUE if the byte range exists and is a valid name 975 */ 976dbus_bool_t 977_dbus_validate_member (const DBusString *str, 978 int start, 979 int len) 980{ 981 const unsigned char *s; 982 const unsigned char *end; 983 const unsigned char *member; 984 985 _dbus_assert (start >= 0); 986 _dbus_assert (len >= 0); 987 _dbus_assert (start <= _dbus_string_get_length (str)); 988 989 if (len > _dbus_string_get_length (str) - start) 990 return FALSE; 991 992 if (len > DBUS_MAXIMUM_NAME_LENGTH) 993 return FALSE; 994 995 if (len == 0) 996 return FALSE; 997 998 member = _dbus_string_get_const_data (str) + start; 999 end = member + len; 1000 s = member; 1001 1002 /* check special cases of first char so it doesn't have to be done 1003 * in the loop. Note we know len > 0 1004 */ 1005 1006 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 1007 return FALSE; 1008 else 1009 ++s; 1010 1011 while (s != end) 1012 { 1013 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 1014 { 1015 return FALSE; 1016 } 1017 1018 ++s; 1019 } 1020 1021 return TRUE; 1022} 1023 1024/** 1025 * Checks that the given range of the string is a valid error name 1026 * in the D-Bus protocol. This includes a length restriction, etc., 1027 * see the specification. 1028 * 1029 * @todo this is inconsistent with most of DBusString in that 1030 * it allows a start,len range that extends past the string end. 1031 * 1032 * @param str the string 1033 * @param start first byte index to check 1034 * @param len number of bytes to check 1035 * @returns #TRUE if the byte range exists and is a valid name 1036 */ 1037dbus_bool_t 1038_dbus_validate_error_name (const DBusString *str, 1039 int start, 1040 int len) 1041{ 1042 /* Same restrictions as interface name at the moment */ 1043 return _dbus_validate_interface (str, start, len); 1044} 1045 1046/** 1047 * Determine wether the given character is valid as the first character 1048 * in a bus name. 1049 */ 1050#define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 1051 ( ((c) >= 'A' && (c) <= 'Z') || \ 1052 ((c) >= 'a' && (c) <= 'z') || \ 1053 ((c) == '_') || ((c) == '-')) 1054 1055/** 1056 * Determine wether the given character is valid as a second or later 1057 * character in a bus name 1058 */ 1059#define VALID_BUS_NAME_CHARACTER(c) \ 1060 ( ((c) >= '0' && (c) <= '9') || \ 1061 ((c) >= 'A' && (c) <= 'Z') || \ 1062 ((c) >= 'a' && (c) <= 'z') || \ 1063 ((c) == '_') || ((c) == '-')) 1064 1065/** 1066 * Checks that the given range of the string is a valid bus name in 1067 * the D-Bus protocol. This includes a length restriction, etc., see 1068 * the specification. 1069 * 1070 * @todo this is inconsistent with most of DBusString in that 1071 * it allows a start,len range that extends past the string end. 1072 * 1073 * @param str the string 1074 * @param start first byte index to check 1075 * @param len number of bytes to check 1076 * @returns #TRUE if the byte range exists and is a valid name 1077 */ 1078dbus_bool_t 1079_dbus_validate_bus_name (const DBusString *str, 1080 int start, 1081 int len) 1082{ 1083 const unsigned char *s; 1084 const unsigned char *end; 1085 const unsigned char *iface; 1086 const unsigned char *last_dot; 1087 1088 _dbus_assert (start >= 0); 1089 _dbus_assert (len >= 0); 1090 _dbus_assert (start <= _dbus_string_get_length (str)); 1091 1092 if (len > _dbus_string_get_length (str) - start) 1093 return FALSE; 1094 1095 if (len > DBUS_MAXIMUM_NAME_LENGTH) 1096 return FALSE; 1097 1098 if (len == 0) 1099 return FALSE; 1100 1101 last_dot = NULL; 1102 iface = _dbus_string_get_const_data (str) + start; 1103 end = iface + len; 1104 s = iface; 1105 1106 /* check special cases of first char so it doesn't have to be done 1107 * in the loop. Note we know len > 0 1108 */ 1109 if (*s == ':') 1110 { 1111 /* unique name */ 1112 ++s; 1113 while (s != end) 1114 { 1115 if (*s == '.') 1116 { 1117 if (_DBUS_UNLIKELY ((s + 1) == end)) 1118 return FALSE; 1119 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 1120 return FALSE; 1121 ++s; /* we just validated the next char, so skip two */ 1122 } 1123 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 1124 { 1125 return FALSE; 1126 } 1127 1128 ++s; 1129 } 1130 1131 return TRUE; 1132 } 1133 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 1134 return FALSE; 1135 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 1136 return FALSE; 1137 else 1138 ++s; 1139 1140 while (s != end) 1141 { 1142 if (*s == '.') 1143 { 1144 if (_DBUS_UNLIKELY ((s + 1) == end)) 1145 return FALSE; 1146 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 1147 return FALSE; 1148 last_dot = s; 1149 ++s; /* we just validated the next char, so skip two */ 1150 } 1151 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 1152 { 1153 return FALSE; 1154 } 1155 1156 ++s; 1157 } 1158 1159 if (_DBUS_UNLIKELY (last_dot == NULL)) 1160 return FALSE; 1161 1162 return TRUE; 1163} 1164 1165/** 1166 * Checks that the given range of the string is a valid message type 1167 * signature in the D-Bus protocol. 1168 * 1169 * @todo this is inconsistent with most of DBusString in that 1170 * it allows a start,len range that extends past the string end. 1171 * 1172 * @param str the string 1173 * @param start first byte index to check 1174 * @param len number of bytes to check 1175 * @returns #TRUE if the byte range exists and is a valid signature 1176 */ 1177dbus_bool_t 1178_dbus_validate_signature (const DBusString *str, 1179 int start, 1180 int len) 1181{ 1182 _dbus_assert (start >= 0); 1183 _dbus_assert (start <= _dbus_string_get_length (str)); 1184 _dbus_assert (len >= 0); 1185 1186 if (len > _dbus_string_get_length (str) - start) 1187 return FALSE; 1188 1189 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 1190} 1191 1192/** define _dbus_check_is_valid_path() */ 1193DEFINE_DBUS_NAME_CHECK(path) 1194/** define _dbus_check_is_valid_interface() */ 1195DEFINE_DBUS_NAME_CHECK(interface) 1196/** define _dbus_check_is_valid_member() */ 1197DEFINE_DBUS_NAME_CHECK(member) 1198/** define _dbus_check_is_valid_error_name() */ 1199DEFINE_DBUS_NAME_CHECK(error_name) 1200/** define _dbus_check_is_valid_bus_name() */ 1201DEFINE_DBUS_NAME_CHECK(bus_name) 1202/** define _dbus_check_is_valid_signature() */ 1203DEFINE_DBUS_NAME_CHECK(signature) 1204 1205/** @} */ 1206 1207/* tests in dbus-marshal-validate-util.c */ 1208