25 #include "dbus/dbus-shared.h"
26 #include "dbus-marshal-header.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-byteswap.h"
47 #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
49 #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
53 #define BYTE_ORDER_OFFSET 0
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
90 #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
93 #define MAX_POSSIBLE_HEADER_PADDING 7
114 unpadded_len = _dbus_string_get_length (&header->
data);
119 header->
padding = _dbus_string_get_length (&header->
data) - unpadded_len;
123 #define HEADER_END_BEFORE_PADDING(header) \
124 (_dbus_string_get_length (&(header)->data) - (header)->padding)
134 _dbus_header_cache_invalidate_all (
DBusHeader *header)
162 _dbus_verbose (
"cached value_pos %d for field %d\n",
187 _dbus_header_cache_revalidate (
DBusHeader *header)
202 &_dbus_header_signature_str,
213 unsigned char field_code;
229 _dbus_header_cache_one (header, field_code, &variant);
249 if (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
250 _dbus_header_cache_revalidate (header);
252 if (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
267 _dbus_header_cache_known_nonexistent (
DBusHeader *header,
272 return (header->
fields[field].
value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
294 unsigned char field_byte;
299 padding = _dbus_string_get_length (writer->
value_str) - start;
315 &contained_type, 0, &variant))
332 _dbus_string_get_length (writer->
value_str) - start - padding);
359 #ifndef DBUS_DISABLE_ASSERT
361 unsigned char v_BYTE;
405 dbus_uint32_t serial)
449 _dbus_header_cache_invalidate_all (header);
496 _dbus_string_get_length (&header->
data)))
531 const char *destination,
533 const char *interface,
535 const char *error_name)
537 unsigned char v_BYTE;
538 dbus_uint32_t v_UINT32;
546 !(interface || member || error_name));
549 if (!reserve_header_padding (header))
553 &_dbus_header_signature_str, 0,
562 v_BYTE = message_type;
588 &_dbus_header_signature_str,
597 if (!write_basic_field (&array,
604 if (destination !=
NULL)
606 if (!write_basic_field (&array,
613 if (interface !=
NULL)
615 if (!write_basic_field (&array,
624 if (!write_basic_field (&array,
631 if (error_name !=
NULL)
633 if (!write_basic_field (&array,
643 correct_header_padding (header);
649 _dbus_string_get_length (&header->
data) - header->
padding);
650 correct_header_padding (header);
676 int *fields_array_len,
684 dbus_uint32_t header_len_unsigned;
685 dbus_uint32_t fields_array_len_unsigned;
686 dbus_uint32_t body_len_unsigned;
692 _dbus_assert (start == (
int) _DBUS_ALIGN_VALUE (start, 8));
698 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
706 if (fields_array_len_unsigned > (
unsigned) max_message_length)
708 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
716 if (body_len_unsigned > (
unsigned) max_message_length)
718 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
723 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
729 if (body_len_unsigned + header_len_unsigned > (
unsigned) max_message_length)
731 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
736 _dbus_assert (fields_array_len_unsigned < (
unsigned) _DBUS_INT32_MAX);
737 _dbus_assert (header_len_unsigned < (
unsigned) _DBUS_INT32_MAX);
739 *body_len = body_len_unsigned;
740 *fields_array_len = fields_array_len_unsigned;
741 *header_len = header_len_unsigned;
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);
749 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
755 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
760 REQUIRE_FIELD (INTERFACE);
763 REQUIRE_FIELD (PATH);
764 REQUIRE_FIELD (MEMBER);
767 REQUIRE_FIELD (ERROR_NAME);
768 REQUIRE_FIELD (REPLY_SERIAL);
771 REQUIRE_FIELD (REPLY_SERIAL);
791 dbus_uint32_t v_UINT32;
803 _dbus_assert (_dbus_header_field_types[field].code == field);
806 if (type != expected_type)
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;
816 _dbus_verbose (
"Header field %d seen a second time\n", field);
817 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
821 _dbus_verbose (
"initially caching field %d\n", field);
822 _dbus_header_cache_one (header, field, variant_reader);
824 string_validation_func =
NULL;
843 &value_str, &value_pos);
844 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
855 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
859 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
863 _dbus_string_get_length (&_dbus_local_interface_str),
864 value_str, str_data_pos))
866 _dbus_verbose (
"Message is on the local interface\n");
867 return DBUS_INVALID_USES_LOCAL_INTERFACE;
873 bad_string_code = DBUS_INVALID_BAD_MEMBER;
878 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
883 bad_string_code = DBUS_INVALID_BAD_SENDER;
888 string_validation_func =
NULL;
892 _dbus_string_get_length (&_dbus_local_path_str),
893 value_str, str_data_pos))
895 _dbus_verbose (
"Message is from the local path\n");
896 return DBUS_INVALID_USES_LOCAL_PATH;
904 return DBUS_INVALID_BAD_SERIAL;
914 string_validation_func =
NULL;
922 if (string_validation_func)
933 _dbus_verbose (
"Validating string header field; code %d if fails\n",
936 if (!(*string_validation_func) (value_str, str_data_pos, len))
937 return bad_string_code;
974 int fields_array_len,
985 unsigned char v_byte;
986 dbus_uint32_t v_uint32;
987 dbus_uint32_t serial;
992 _dbus_assert (start == (
int) _DBUS_ALIGN_VALUE (start, 8));
998 _dbus_verbose (
"Failed to copy buffer into new header\n");
1003 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1005 leftover = len - header_len - body_len - start;
1025 _dbus_assert (start + header_len == (
int) _DBUS_ALIGN_VALUE (padding_start, 8));
1026 _dbus_assert (start + header_len == padding_start + padding_len);
1028 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1032 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1037 header->
padding = padding_len;
1039 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1051 &_dbus_header_signature_str, 0,
1073 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1093 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1113 *validity = DBUS_INVALID_BAD_SERIAL;
1125 unsigned char field_code;
1137 _dbus_verbose (
"invalid header field code\n");
1138 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1144 _dbus_verbose (
"unknown header field code %d, skipping\n",
1152 v = load_and_validate_field (header, field_code, &variant_reader);
1155 _dbus_verbose (
"Field %d was invalid\n", field_code);
1173 v = check_mandatory_fields (header);
1176 _dbus_verbose (
"Mandatory fields were missing, code %d\n", v);
1219 find_field_for_modification (
DBusHeader *header,
1230 &_dbus_header_signature_str,
1240 unsigned char field_code;
1247 if (field_code == (
unsigned) field)
1280 if (!reserve_header_padding (header))
1284 if (_dbus_header_cache_check (header, field))
1289 if (!find_field_for_modification (header, field,
1290 &reader, &realign_root))
1293 if (!set_basic_field (&reader, field, type, value, &realign_root))
1303 &_dbus_header_signature_str,
1312 &_dbus_header_signature_str,
1321 if (!write_basic_field (&array,
1322 field, type, value))
1329 correct_header_padding (header);
1335 _dbus_header_cache_invalidate_all (header);
1358 _dbus_assert (_dbus_header_field_types[field].code == field);
1365 if (!_dbus_header_cache_check (header, field))
1397 if (!_dbus_header_cache_check (header, field))
1401 *str = &header->
data;
1422 if (_dbus_header_cache_known_nonexistent (header, field))
1428 if (!find_field_for_modification (header, field,
1429 &reader, &realign_root))
1432 if (!reserve_header_padding (header))
1439 correct_header_padding (header);
1441 _dbus_header_cache_invalidate_all (header);
1443 _dbus_assert (!_dbus_header_cache_check (header, field));
1461 unsigned char *flags_p;
1482 const unsigned char *flags_p;
1484 flags_p = _dbus_string_get_const_data_len (&header->
data,
FLAGS_OFFSET, 1);
1486 return (*flags_p & flag) != 0;
1503 if (byte_order == new_order)
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...
#define DBUS_HEADER_FIELD_INVALID
Not equal to any valid header field code.
#define NULL
A null pointer, defined appropriately for C or C++.
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.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given 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_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
The type writer is an iterator for writing to a block of values.
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...
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string...
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
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.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
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...
#define DBUS_HEADER_SIGNATURE
Header format is defined as a signature: byte byte order byte message type ID byte flags byte protoco...
#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_BYTE
Type code marking an 8-bit unsigned integer.
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
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_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define EXPECTED_TYPE_OF_FIELD(field)
Macro to look up the correct type for a field.
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
DBusValidationMode
This is used rather than a bool for high visibility.
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...
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
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.
DBusString * value_str
where to write values
#define VERSION_OFFSET
Offset to version from start of header.
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of an element of the fields array...
#define DBUS_MAJOR_PROTOCOL_VERSION
Protocol version.
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.
#define BYTE_ORDER_OFFSET
Offset to byte order from start of 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...
#define TYPE_OFFSET
Offset to type 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...
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...
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
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_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
#define SERIAL_OFFSET
Offset to client serial from start of header.
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.
can't determine validity due to OOM
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
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...
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_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
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, check whether the data is long enough to contain the entire message (assuming the claimed lengths are accurate).
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
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_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...
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
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.
#define FIRST_FIELD_OFFSET
Offset to first field in header.
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define HEADER_END_BEFORE_PADDING(header)
Compute the end of the header, ignoring padding.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
#define MAX_POSSIBLE_HEADER_PADDING
The most padding we could ever need for a header.
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
The type reader is an iterator for reading values from a block of values.
#define TRUE
Expands to "1".
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.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus...
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
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 DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
int value_pos
next position to write
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.
void _dbus_header_free(DBusHeader *header)
Frees a header.
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE)
Static DBusString containing the signature of a message header.
union DBusTypeWriter::@3 u
class-specific data
#define _DBUS_INT32_MAX
Maximum value of type "int32".
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.
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.
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...
#define FALSE
Expands to "0".
#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...
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
#define FLAGS_OFFSET
Offset to flags from start of header.
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.
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
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 FIELDS_ARRAY_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of the fields 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_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
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.
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
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.