D-Bus 1.12.4
dbus-marshal-header.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-marshal-header.c Managing marshaling/demarshaling of message headers
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/dbus-shared.h"
26#include "dbus-marshal-header.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-byteswap.h"
29
37/* Not thread locked, but strictly const/read-only so should be OK
38 */
40_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
42_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_LOCAL);
44_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_LOCAL);
45
47#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
49#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
50
51
53#define BYTE_ORDER_OFFSET 0
55#define TYPE_OFFSET 1
57#define FLAGS_OFFSET 2
59#define VERSION_OFFSET 3
61#define BODY_LENGTH_OFFSET 4
63#define SERIAL_OFFSET 8
65#define FIELDS_ARRAY_LENGTH_OFFSET 12
67#define FIRST_FIELD_OFFSET 16
68
69typedef struct
70{
71 unsigned char code;
72 unsigned char type;
74
75static const HeaderFieldType
76_dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
87};
88
90#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
91
93#define MAX_POSSIBLE_HEADER_PADDING 7
94static dbus_bool_t
95reserve_header_padding (DBusHeader *header)
96{
98
99 if (!_dbus_string_lengthen (&header->data,
101 return FALSE;
103 return TRUE;
104}
105
106static void
107correct_header_padding (DBusHeader *header)
108{
109 int unpadded_len;
110
111 _dbus_assert (header->padding == 7);
112
113 _dbus_string_shorten (&header->data, header->padding);
114 unpadded_len = _dbus_string_get_length (&header->data);
115
116 if (!_dbus_string_align_length (&header->data, 8))
117 _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
118
119 header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
120}
121
123#define HEADER_END_BEFORE_PADDING(header) \
124 (_dbus_string_get_length (&(header)->data) - (header)->padding)
125
133static void
134_dbus_header_cache_invalidate_all (DBusHeader *header)
135{
136 int i;
137
138 i = 0;
139 while (i <= DBUS_HEADER_FIELD_LAST)
140 {
141 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
142 ++i;
143 }
144}
145
153static void
154_dbus_header_cache_one (DBusHeader *header,
155 int field_code,
156 DBusTypeReader *variant_reader)
157{
158 header->fields[field_code].value_pos =
159 _dbus_type_reader_get_value_pos (variant_reader);
160
161#if 0
162 _dbus_verbose ("cached value_pos %d for field %d\n",
163 header->fields[field_code].value_pos, field_code)
164#endif
165}
166
173char
175{
176 _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
177
178 return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
179}
180
186static void
187_dbus_header_cache_revalidate (DBusHeader *header)
188{
189 DBusTypeReader array;
190 DBusTypeReader reader;
191 int i;
192
193 i = 0;
194 while (i <= DBUS_HEADER_FIELD_LAST)
195 {
196 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
197 ++i;
198 }
199
200 _dbus_type_reader_init (&reader,
202 &_dbus_header_signature_str,
204 &header->data,
206
207 _dbus_type_reader_recurse (&reader, &array);
208
210 {
211 DBusTypeReader sub;
212 DBusTypeReader variant;
213 unsigned char field_code;
214
215 _dbus_type_reader_recurse (&array, &sub);
216
218 _dbus_type_reader_read_basic (&sub, &field_code);
219
220 /* Unknown fields should be ignored */
221 if (field_code > DBUS_HEADER_FIELD_LAST)
222 goto next_field;
223
225
227 _dbus_type_reader_recurse (&sub, &variant);
228
229 _dbus_header_cache_one (header, field_code, &variant);
230
231 next_field:
232 _dbus_type_reader_next (&array);
233 }
234}
235
243static dbus_bool_t
244_dbus_header_cache_check (DBusHeader *header,
245 int field)
246{
248
249 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
250 _dbus_header_cache_revalidate (header);
251
252 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
253 return FALSE;
254
255 return TRUE;
256}
257
266static dbus_bool_t
267_dbus_header_cache_known_nonexistent (DBusHeader *header,
268 int field)
269{
271
272 return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
273}
274
284static dbus_bool_t
285write_basic_field (DBusTypeWriter *writer,
286 int field,
287 int type,
288 const void *value)
289{
290 DBusTypeWriter sub;
291 DBusTypeWriter variant;
292 int start;
293 int padding;
294 unsigned char field_byte;
295 DBusString contained_type;
296 char buf[2];
297
298 start = writer->value_pos;
299 padding = _dbus_string_get_length (writer->value_str) - start;
300
302 NULL, 0, &sub))
303 goto append_failed;
304
305 field_byte = field;
307 &field_byte))
308 goto append_failed;
309
310 buf[0] = type;
311 buf[1] = '\0';
312 _dbus_string_init_const_len (&contained_type, buf, 1);
313
315 &contained_type, 0, &variant))
316 goto append_failed;
317
318 if (!_dbus_type_writer_write_basic (&variant, type, value))
319 goto append_failed;
320
321 if (!_dbus_type_writer_unrecurse (&sub, &variant))
322 goto append_failed;
323
324 if (!_dbus_type_writer_unrecurse (writer, &sub))
325 goto append_failed;
326
327 return TRUE;
328
329 append_failed:
331 start,
332 _dbus_string_get_length (writer->value_str) - start - padding);
333 return FALSE;
334}
335
346static dbus_bool_t
347set_basic_field (DBusTypeReader *reader,
348 int field,
349 int type,
350 const void *value,
351 const DBusTypeReader *realign_root)
352{
353 DBusTypeReader sub;
354 DBusTypeReader variant;
355
356 _dbus_type_reader_recurse (reader, &sub);
357
359#ifndef DBUS_DISABLE_ASSERT
360 {
361 unsigned char v_BYTE;
362 _dbus_type_reader_read_basic (&sub, &v_BYTE);
363 _dbus_assert (((int) v_BYTE) == field);
364 }
365#endif
366
367 if (!_dbus_type_reader_next (&sub))
368 _dbus_assert_not_reached ("no variant field?");
369
370 _dbus_type_reader_recurse (&sub, &variant);
372
373 if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
374 return FALSE;
375
376 return TRUE;
377}
378
385int
387{
388 int type;
389
390 type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
392
393 return type;
394}
395
403void
405 dbus_uint32_t serial)
406{
407 /* we use this function to set the serial on outgoing
408 * messages, and to reset the serial in dbus_message_copy;
409 * this assertion should catch a double-set on outgoing.
410 */
411 _dbus_assert (_dbus_header_get_serial (header) == 0 ||
412 serial == 0);
413
416 serial,
418}
419
428{
429 return _dbus_marshal_read_uint32 (&header->data,
432 NULL);
433}
434
442void
444{
445 _dbus_string_set_length (&header->data, 0);
446
447 header->padding = 0;
448
449 _dbus_header_cache_invalidate_all (header);
450}
451
461{
462 if (!_dbus_string_init_preallocated (&header->data, 32))
463 return FALSE;
464
465 _dbus_header_reinit (header);
466
467 return TRUE;
468}
469
475void
477{
478 _dbus_string_free (&header->data);
479}
480
491 DBusHeader *dest)
492{
493 *dest = *header;
494
496 _dbus_string_get_length (&header->data)))
497 return FALSE;
498
499 if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
500 {
501 _dbus_string_free (&dest->data);
502 return FALSE;
503 }
504
505 /* Reset the serial */
506 _dbus_header_set_serial (dest, 0);
507
508 return TRUE;
509}
510
529 int byte_order,
530 int message_type,
531 const char *destination,
532 const char *path,
533 const char *interface,
534 const char *member,
535 const char *error_name)
536{
537 unsigned char v_BYTE;
538 dbus_uint32_t v_UINT32;
539 DBusTypeWriter writer;
540 DBusTypeWriter array;
541
542 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
543 byte_order == DBUS_BIG_ENDIAN);
544 _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
545 (error_name) ||
546 !(interface || member || error_name));
547 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
548
549 if (!reserve_header_padding (header))
550 return FALSE;
551
552 _dbus_type_writer_init_values_only (&writer, byte_order,
553 &_dbus_header_signature_str, 0,
554 &header->data,
556
557 v_BYTE = byte_order;
559 &v_BYTE))
560 goto oom;
561
562 v_BYTE = message_type;
564 &v_BYTE))
565 goto oom;
566
567 v_BYTE = 0; /* flags */
569 &v_BYTE))
570 goto oom;
571
574 &v_BYTE))
575 goto oom;
576
577 v_UINT32 = 0; /* body length */
579 &v_UINT32))
580 goto oom;
581
582 v_UINT32 = 0; /* serial */
584 &v_UINT32))
585 goto oom;
586
588 &_dbus_header_signature_str,
590 &array))
591 goto oom;
592
593 /* Marshal all the fields (Marshall Fields?) */
594
595 if (path != NULL)
596 {
597 if (!write_basic_field (&array,
600 &path))
601 goto oom;
602 }
603
604 if (destination != NULL)
605 {
606 if (!write_basic_field (&array,
609 &destination))
610 goto oom;
611 }
612
613 if (interface != NULL)
614 {
615 if (!write_basic_field (&array,
618 &interface))
619 goto oom;
620 }
621
622 if (member != NULL)
623 {
624 if (!write_basic_field (&array,
627 &member))
628 goto oom;
629 }
630
631 if (error_name != NULL)
632 {
633 if (!write_basic_field (&array,
636 &error_name))
637 goto oom;
638 }
639
640 if (!_dbus_type_writer_unrecurse (&writer, &array))
641 goto oom;
642
643 correct_header_padding (header);
644
645 return TRUE;
646
647 oom:
648 _dbus_string_delete (&header->data, 0,
649 _dbus_string_get_length (&header->data) - header->padding);
650 correct_header_padding (header);
651
652 return FALSE;
653}
654
674 DBusValidity *validity,
675 int *byte_order,
676 int *fields_array_len,
677 int *header_len,
678 int *body_len,
679 const DBusString *str,
680 int start,
681 int len)
682
683{
684 dbus_uint32_t header_len_unsigned;
685 dbus_uint32_t fields_array_len_unsigned;
686 dbus_uint32_t body_len_unsigned;
687
688 _dbus_assert (start >= 0);
689 _dbus_assert (start < _DBUS_INT32_MAX / 2);
690 _dbus_assert (len >= 0);
691
692 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
693
694 *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
695
696 if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
697 {
698 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
699 return FALSE;
700 }
701
703 fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
704 *byte_order, NULL);
705
706 if (fields_array_len_unsigned > (unsigned) max_message_length)
707 {
708 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
709 return FALSE;
710 }
711
713 body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
714 *byte_order, NULL);
715
716 if (body_len_unsigned > (unsigned) max_message_length)
717 {
718 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
719 return FALSE;
720 }
721
722 header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
723 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
724
725 /* overflow should be impossible since the lengths aren't allowed to
726 * be huge.
727 */
728 _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
729 if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
730 {
731 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
732 return FALSE;
733 }
734
735 _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
736 _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
737 _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
738
739 *body_len = body_len_unsigned;
740 *fields_array_len = fields_array_len_unsigned;
741 *header_len = header_len_unsigned;
742
743 *validity = DBUS_VALID;
744
745 _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
746 len, body_len_unsigned, header_len_unsigned,
747 body_len_unsigned + header_len_unsigned);
748
749 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
750}
751
752static DBusValidity
753check_mandatory_fields (DBusHeader *header)
754{
755#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
756
757 switch (_dbus_header_get_message_type (header))
758 {
760 REQUIRE_FIELD (INTERFACE);
761 /* FALL THRU - signals also require the path and member */
763 REQUIRE_FIELD (PATH);
764 REQUIRE_FIELD (MEMBER);
765 break;
767 REQUIRE_FIELD (ERROR_NAME);
768 REQUIRE_FIELD (REPLY_SERIAL);
769 break;
771 REQUIRE_FIELD (REPLY_SERIAL);
772 break;
773 default:
774 /* other message types allowed but ignored */
775 break;
776 }
777
778 return DBUS_VALID;
779}
780
781static DBusValidity
782load_and_validate_field (DBusHeader *header,
783 int field,
784 DBusTypeReader *variant_reader)
785{
786 int type;
787 int expected_type;
788 const DBusString *value_str;
789 int value_pos;
790 int str_data_pos;
791 dbus_uint32_t v_UINT32;
792 int bad_string_code;
793 dbus_bool_t (* string_validation_func) (const DBusString *str,
794 int start, int len);
795
796 /* Supposed to have been checked already */
799
800 /* Before we can cache a field, we need to know it has the right type */
801 type = _dbus_type_reader_get_current_type (variant_reader);
802
803 _dbus_assert (_dbus_header_field_types[field].code == field);
804
805 expected_type = EXPECTED_TYPE_OF_FIELD (field);
806 if (type != expected_type)
807 {
808 _dbus_verbose ("Field %d should have type %d but has %d\n",
809 field, expected_type, type);
810 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
811 }
812
813 /* If the field was provided twice, we aren't happy */
814 if (header->fields[field].value_pos >= 0)
815 {
816 _dbus_verbose ("Header field %d seen a second time\n", field);
817 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
818 }
819
820 /* Now we can cache and look at the field content */
821 _dbus_verbose ("initially caching field %d\n", field);
822 _dbus_header_cache_one (header, field, variant_reader);
823
824 string_validation_func = NULL;
825
826 /* make compiler happy that all this is initialized */
827 v_UINT32 = 0;
828 value_str = NULL;
829 value_pos = -1;
830 str_data_pos = -1;
831 bad_string_code = DBUS_VALID;
832
833 if (expected_type == DBUS_TYPE_UINT32)
834 {
835 _dbus_header_get_field_basic (header, field, expected_type,
836 &v_UINT32);
837 }
838 else if (expected_type == DBUS_TYPE_STRING ||
839 expected_type == DBUS_TYPE_OBJECT_PATH ||
840 expected_type == DBUS_TYPE_SIGNATURE)
841 {
842 _dbus_header_get_field_raw (header, field,
843 &value_str, &value_pos);
844 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
845 }
846 else
847 {
848 _dbus_assert_not_reached ("none of the known fields should have this type");
849 }
850
851 switch (field)
852 {
854 string_validation_func = _dbus_validate_bus_name;
855 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
856 break;
858 string_validation_func = _dbus_validate_interface;
859 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
860
861 if (_dbus_string_equal_substring (&_dbus_local_interface_str,
862 0,
863 _dbus_string_get_length (&_dbus_local_interface_str),
864 value_str, str_data_pos))
865 {
866 _dbus_verbose ("Message is on the local interface\n");
867 return DBUS_INVALID_USES_LOCAL_INTERFACE;
868 }
869 break;
870
872 string_validation_func = _dbus_validate_member;
873 bad_string_code = DBUS_INVALID_BAD_MEMBER;
874 break;
875
877 string_validation_func = _dbus_validate_error_name;
878 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
879 break;
880
882 string_validation_func = _dbus_validate_bus_name;
883 bad_string_code = DBUS_INVALID_BAD_SENDER;
884 break;
885
887 /* OBJECT_PATH was validated generically due to its type */
888 string_validation_func = NULL;
889
890 if (_dbus_string_equal_substring (&_dbus_local_path_str,
891 0,
892 _dbus_string_get_length (&_dbus_local_path_str),
893 value_str, str_data_pos))
894 {
895 _dbus_verbose ("Message is from the local path\n");
896 return DBUS_INVALID_USES_LOCAL_PATH;
897 }
898 break;
899
901 /* Can't be 0 */
902 if (v_UINT32 == 0)
903 {
904 return DBUS_INVALID_BAD_SERIAL;
905 }
906 break;
907
909 /* Every value makes sense */
910 break;
911
913 /* SIGNATURE validated generically due to its type */
914 string_validation_func = NULL;
915 break;
916
917 default:
918 _dbus_assert_not_reached ("unknown field shouldn't be seen here");
919 break;
920 }
921
922 if (string_validation_func)
923 {
924 dbus_uint32_t len;
925
926 _dbus_assert (bad_string_code != DBUS_VALID);
927
928 len = _dbus_marshal_read_uint32 (value_str, value_pos,
930 NULL);
931
932#if 0
933 _dbus_verbose ("Validating string header field; code %d if fails\n",
934 bad_string_code);
935#endif
936 if (!(*string_validation_func) (value_str, str_data_pos, len))
937 return bad_string_code;
938 }
939
940 return DBUS_VALID;
941}
942
972 DBusValidity *validity,
973 int byte_order,
974 int fields_array_len,
975 int header_len,
976 int body_len,
977 const DBusString *str,
978 int start,
979 int len)
980{
981 int leftover;
982 DBusValidity v;
983 DBusTypeReader reader;
984 DBusTypeReader array_reader;
985 unsigned char v_byte;
986 dbus_uint32_t v_uint32;
987 dbus_uint32_t serial;
988 int padding_start;
989 int padding_len;
990 int i;
991
992 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
993 _dbus_assert (header_len <= len);
994 _dbus_assert (_dbus_string_get_length (&header->data) == 0);
995
996 if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
997 {
998 _dbus_verbose ("Failed to copy buffer into new header\n");
1000 return FALSE;
1001 }
1002
1003 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1004 {
1005 leftover = len - header_len - body_len - start;
1006 }
1007 else
1008 {
1009 v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
1010 byte_order,
1011 &leftover,
1012 str, start, len);
1013
1014 if (v != DBUS_VALID)
1015 {
1016 *validity = v;
1017 goto invalid;
1018 }
1019 }
1020
1021 _dbus_assert (leftover < len);
1022
1023 padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
1024 padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
1025 _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
1026 _dbus_assert (start + header_len == padding_start + padding_len);
1027
1028 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1029 {
1030 if (!_dbus_string_validate_nul (str, padding_start, padding_len))
1031 {
1032 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1033 goto invalid;
1034 }
1035 }
1036
1037 header->padding = padding_len;
1038
1039 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1040 {
1041 *validity = DBUS_VALID;
1042 return TRUE;
1043 }
1044
1045 /* We now know the data is well-formed, but we have to check that
1046 * it's valid.
1047 */
1048
1049 _dbus_type_reader_init (&reader,
1050 byte_order,
1051 &_dbus_header_signature_str, 0,
1052 str, start);
1053
1054 /* BYTE ORDER */
1057 _dbus_type_reader_read_basic (&reader, &v_byte);
1058 _dbus_type_reader_next (&reader);
1059
1060 _dbus_assert (v_byte == byte_order);
1061
1062 /* MESSAGE TYPE */
1065 _dbus_type_reader_read_basic (&reader, &v_byte);
1066 _dbus_type_reader_next (&reader);
1067
1068 /* unknown message types are supposed to be ignored, so only validation here is
1069 * that it isn't invalid
1070 */
1071 if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
1072 {
1073 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1074 goto invalid;
1075 }
1076
1077 /* FLAGS */
1080 _dbus_type_reader_read_basic (&reader, &v_byte);
1081 _dbus_type_reader_next (&reader);
1082
1083 /* unknown flags should be ignored */
1084
1085 /* PROTOCOL VERSION */
1088 _dbus_type_reader_read_basic (&reader, &v_byte);
1089 _dbus_type_reader_next (&reader);
1090
1091 if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
1092 {
1093 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1094 goto invalid;
1095 }
1096
1097 /* BODY LENGTH */
1100 _dbus_type_reader_read_basic (&reader, &v_uint32);
1101 _dbus_type_reader_next (&reader);
1102
1103 _dbus_assert (body_len == (signed) v_uint32);
1104
1105 /* SERIAL */
1108 _dbus_type_reader_read_basic (&reader, &serial);
1109 _dbus_type_reader_next (&reader);
1110
1111 if (serial == 0)
1112 {
1113 *validity = DBUS_INVALID_BAD_SERIAL;
1114 goto invalid;
1115 }
1116
1119
1120 _dbus_type_reader_recurse (&reader, &array_reader);
1121 while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
1122 {
1123 DBusTypeReader struct_reader;
1124 DBusTypeReader variant_reader;
1125 unsigned char field_code;
1126
1128
1129 _dbus_type_reader_recurse (&array_reader, &struct_reader);
1130
1132 _dbus_type_reader_read_basic (&struct_reader, &field_code);
1133 _dbus_type_reader_next (&struct_reader);
1134
1135 if (field_code == DBUS_HEADER_FIELD_INVALID)
1136 {
1137 _dbus_verbose ("invalid header field code\n");
1138 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1139 goto invalid;
1140 }
1141
1142 if (field_code > DBUS_HEADER_FIELD_LAST)
1143 {
1144 _dbus_verbose ("unknown header field code %d, skipping\n",
1145 field_code);
1146 goto next_field;
1147 }
1148
1150 _dbus_type_reader_recurse (&struct_reader, &variant_reader);
1151
1152 v = load_and_validate_field (header, field_code, &variant_reader);
1153 if (v != DBUS_VALID)
1154 {
1155 _dbus_verbose ("Field %d was invalid\n", field_code);
1156 *validity = v;
1157 goto invalid;
1158 }
1159
1160 next_field:
1161 _dbus_type_reader_next (&array_reader);
1162 }
1163
1164 /* Anything we didn't fill in is now known not to exist */
1165 i = 0;
1166 while (i <= DBUS_HEADER_FIELD_LAST)
1167 {
1168 if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
1169 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
1170 ++i;
1171 }
1172
1173 v = check_mandatory_fields (header);
1174 if (v != DBUS_VALID)
1175 {
1176 _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
1177 *validity = v;
1178 goto invalid;
1179 }
1180
1181 *validity = DBUS_VALID;
1182 return TRUE;
1183
1184 invalid:
1185 _dbus_string_set_length (&header->data, 0);
1186 return FALSE;
1187}
1188
1195void
1197 int body_len)
1198{
1201 body_len,
1203}
1204
1218static dbus_bool_t
1219find_field_for_modification (DBusHeader *header,
1220 int field,
1221 DBusTypeReader *reader,
1222 DBusTypeReader *realign_root)
1223{
1224 dbus_bool_t retval;
1225
1226 retval = FALSE;
1227
1228 _dbus_type_reader_init (realign_root,
1230 &_dbus_header_signature_str,
1232 &header->data,
1234
1235 _dbus_type_reader_recurse (realign_root, reader);
1236
1238 {
1239 DBusTypeReader sub;
1240 unsigned char field_code;
1241
1242 _dbus_type_reader_recurse (reader, &sub);
1243
1245 _dbus_type_reader_read_basic (&sub, &field_code);
1246
1247 if (field_code == (unsigned) field)
1248 {
1250 retval = TRUE;
1251 goto done;
1252 }
1253
1254 _dbus_type_reader_next (reader);
1255 }
1256
1257 done:
1258 return retval;
1259}
1260
1274 int field,
1275 int type,
1276 const void *value)
1277{
1279
1280 if (!reserve_header_padding (header))
1281 return FALSE;
1282
1283 /* If the field exists we set, otherwise we append */
1284 if (_dbus_header_cache_check (header, field))
1285 {
1286 DBusTypeReader reader;
1287 DBusTypeReader realign_root;
1288
1289 if (!find_field_for_modification (header, field,
1290 &reader, &realign_root))
1291 _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
1292
1293 if (!set_basic_field (&reader, field, type, value, &realign_root))
1294 return FALSE;
1295 }
1296 else
1297 {
1298 DBusTypeWriter writer;
1299 DBusTypeWriter array;
1300
1303 &_dbus_header_signature_str,
1305 &header->data,
1307
1308 /* recurse into array without creating a new length, and jump to
1309 * end of array.
1310 */
1311 if (!_dbus_type_writer_append_array (&writer,
1312 &_dbus_header_signature_str,
1314 &array))
1315 _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
1316
1318 _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
1320
1321 if (!write_basic_field (&array,
1322 field, type, value))
1323 return FALSE;
1324
1325 if (!_dbus_type_writer_unrecurse (&writer, &array))
1326 _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
1327 }
1328
1329 correct_header_padding (header);
1330
1331 /* We could be smarter about this (only invalidate fields after the
1332 * one we modified, or even only if the one we modified changed
1333 * length). But this hack is a start.
1334 */
1335 _dbus_header_cache_invalidate_all (header);
1336
1337 return TRUE;
1338}
1339
1352 int field,
1353 int type,
1354 void *value)
1355{
1358 _dbus_assert (_dbus_header_field_types[field].code == field);
1359 /* in light of this you might ask why the type is passed in;
1360 * the only rationale I can think of is so the caller has
1361 * to specify its expectation and breaks if we change it
1362 */
1363 _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
1364
1365 if (!_dbus_header_cache_check (header, field))
1366 return FALSE;
1367
1368 _dbus_assert (header->fields[field].value_pos >= 0);
1369
1371 header->fields[field].value_pos,
1372 type, value, _dbus_header_get_byte_order (header),
1373 NULL);
1374
1375 return TRUE;
1376}
1377
1393 int field,
1394 const DBusString **str,
1395 int *pos)
1396{
1397 if (!_dbus_header_cache_check (header, field))
1398 return FALSE;
1399
1400 if (str)
1401 *str = &header->data;
1402 if (pos)
1403 *pos = header->fields[field].value_pos;
1404
1405 return TRUE;
1406}
1407
1417 int field)
1418{
1419 DBusTypeReader reader;
1420 DBusTypeReader realign_root;
1421
1422 if (_dbus_header_cache_known_nonexistent (header, field))
1423 return TRUE; /* nothing to do */
1424
1425 /* Scan to the field we want, delete and realign, reappend
1426 * padding. Field may turn out not to exist.
1427 */
1428 if (!find_field_for_modification (header, field,
1429 &reader, &realign_root))
1430 return TRUE; /* nothing to do */
1431
1432 if (!reserve_header_padding (header))
1433 return FALSE;
1434
1435 if (!_dbus_type_reader_delete (&reader,
1436 &realign_root))
1437 return FALSE;
1438
1439 correct_header_padding (header);
1440
1441 _dbus_header_cache_invalidate_all (header);
1442
1443 _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
1444
1445 return TRUE;
1446}
1447
1456void
1458 dbus_uint32_t flag,
1459 dbus_bool_t value)
1460{
1461 unsigned char *flags_p;
1462
1463 flags_p = _dbus_string_get_udata_len (&header->data, FLAGS_OFFSET, 1);
1464
1465 if (value)
1466 *flags_p |= flag;
1467 else
1468 *flags_p &= ~flag;
1469}
1470
1480 dbus_uint32_t flag)
1481{
1482 const unsigned char *flags_p;
1483
1484 flags_p = _dbus_string_get_const_udata_len (&header->data, FLAGS_OFFSET, 1);
1485
1486 return (*flags_p & flag) != 0;
1487}
1488
1495void
1497 int new_order)
1498{
1499 char byte_order;
1500
1501 byte_order = _dbus_header_get_byte_order (header);
1502
1503 if (byte_order == new_order)
1504 return;
1505
1506 _dbus_marshal_byteswap (&_dbus_header_signature_str,
1507 0, byte_order,
1508 new_order,
1509 &header->data, 0);
1510
1511 _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
1512}
1513
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_INT32_MAX
Maximum value of type "int32".
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
dbus_bool_t _dbus_header_load(DBusHeader *header, DBusValidationMode mode, DBusValidity *validity, int byte_order, int fields_array_len, int header_len, int body_len, const DBusString *str, int start, int len)
Creates a message header from potentially-untrusted data.
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
#define EXPECTED_TYPE_OF_FIELD(field)
Macro to look up the correct type for a field.
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
dbus_bool_t _dbus_header_get_field_basic(DBusHeader *header, int field, int type, void *value)
Gets the value of a field with basic type.
#define SERIAL_OFFSET
Offset to client serial from start of header.
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
#define VERSION_OFFSET
Offset to version from start of header.
dbus_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
void _dbus_marshal_byteswap(const DBusString *signature, int signature_start, int old_byte_order, int new_byte_order, DBusString *value_str, int value_pos)
Byteswaps the marshaled data in the given value_str.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
dbus_bool_t _dbus_header_have_message_untrusted(int max_message_length, DBusValidity *validity, int *byte_order, int *fields_array_len, int *header_len, int *body_len, const DBusString *str, int start, int len)
Given data long enough to contain the length of the message body and the fields array,...
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
#define FLAGS_OFFSET
Offset to flags from start of header.
#define FIELDS_ARRAY_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of the fields array.
#define MAX_POSSIBLE_HEADER_PADDING
The most padding we could ever need for a header.
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
#define FIRST_FIELD_OFFSET
Offset to first field in header.
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
void _dbus_header_free(DBusHeader *header)
Frees a header.
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
dbus_bool_t _dbus_header_create(DBusHeader *header, int byte_order, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name)
Fills in the primary fields of the header, so the header is ready for use.
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of an element of the fields array.
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
dbus_bool_t _dbus_type_writer_append_array(DBusTypeWriter *writer, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Append to an existing array.
void _dbus_header_toggle_flag(DBusHeader *header, dbus_uint32_t flag, dbus_bool_t value)
Toggles a message flag bit, turning on the bit if value = TRUE and flipping it off if value = FALSE.
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
#define HEADER_END_BEFORE_PADDING(header)
Compute the end of the header, ignoring padding.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
#define TYPE_OFFSET
Offset to type from start of header.
DBusValidationMode
This is used rather than a bool for high visibility.
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
@ DBUS_VALID
the data is valid
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
#define DBUS_HEADER_FIELD_INVALID
Not equal to any valid header field code.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_HEADER_SIGNATURE
Header format is defined as a signature: byte byte order byte message type ID byte flags byte protoco...
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_HEADER_FIELD_LAST
Value of the highest-numbered header field code, can be used to determine the size of an array indexe...
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
#define DBUS_MAJOR_PROTOCOL_VERSION
Protocol version.
Definition: dbus-protocol.h:57
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition: dbus-shared.h:105
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
Definition: dbus-string.c:2653
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2104
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:132
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:210
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1193
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
dbus_bool_t _dbus_string_align_length(DBusString *str, int alignment)
Align the length of a string to a specific alignment (typically 4 or 8) by appending nul bytes to the...
Definition: dbus-string.c:883
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1375
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
int value_pos
Position of field value, or -1/-2.
Message header data and some cached details of it.
DBusString data
Header network data, stored separately from body so we can independently realloc it.
dbus_uint32_t padding
bytes of alignment in header
DBusHeaderField fields[DBUS_HEADER_FIELD_LAST+1]
Track the location of each field in header.
The type reader is an iterator for reading values from a block of values.
The type writer is an iterator for writing to a block of values.
int start_pos
position of first element in the array
int value_pos
next position to write
union DBusTypeWriter::@3 u
class-specific data
int len_pos
position of length of the array
DBusString * value_str
where to write values
unsigned char type
the value type
unsigned char code
the field code