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
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);
293 unsigned char field_byte;
314 &contained_type, 0, &variant))
357 #ifndef DBUS_DISABLE_ASSERT
359 unsigned char v_BYTE;
447 _dbus_header_cache_invalidate_all (header);
529 const char *destination,
531 const char *interface,
533 const char *error_name)
535 unsigned char v_BYTE;
544 !(interface || member || error_name));
547 if (!reserve_header_padding (header))
551 &_dbus_header_signature_str, 0,
560 v_BYTE = message_type;
586 &_dbus_header_signature_str,
595 if (!write_basic_field (&array,
602 if (destination !=
NULL)
604 if (!write_basic_field (&array,
611 if (interface !=
NULL)
613 if (!write_basic_field (&array,
622 if (!write_basic_field (&array,
629 if (error_name !=
NULL)
631 if (!write_basic_field (&array,
641 correct_header_padding (header);
648 correct_header_padding (header);
674 int *fields_array_len,
690 _dbus_assert (start == (
int) _DBUS_ALIGN_VALUE (start, 8));
696 *validity = DBUS_INVALID_BAD_BYTE_ORDER;
704 if (fields_array_len_unsigned > (
unsigned) max_message_length)
706 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
714 if (body_len_unsigned > (
unsigned) max_message_length)
716 *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
721 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
727 if (body_len_unsigned + header_len_unsigned > (
unsigned) max_message_length)
729 *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
734 _dbus_assert (fields_array_len_unsigned < (
unsigned) _DBUS_INT32_MAX);
735 _dbus_assert (header_len_unsigned < (
unsigned) _DBUS_INT32_MAX);
737 *body_len = body_len_unsigned;
738 *fields_array_len = fields_array_len_unsigned;
739 *header_len = header_len_unsigned;
743 _dbus_verbose (
"have %d bytes, need body %u + header %u = %u\n",
744 len, body_len_unsigned, header_len_unsigned,
745 body_len_unsigned + header_len_unsigned);
747 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
753 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
758 REQUIRE_FIELD (INTERFACE);
761 REQUIRE_FIELD (PATH);
762 REQUIRE_FIELD (MEMBER);
765 REQUIRE_FIELD (ERROR_NAME);
766 REQUIRE_FIELD (REPLY_SERIAL);
769 REQUIRE_FIELD (REPLY_SERIAL);
801 _dbus_assert (_dbus_header_field_types[field].code == field);
804 if (type != expected_type)
806 _dbus_verbose (
"Field %d should have type %d but has %d\n",
807 field, expected_type, type);
808 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
814 _dbus_verbose (
"Header field %d seen a second time\n", field);
815 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
819 _dbus_verbose (
"initially caching field %d\n", field);
820 _dbus_header_cache_one (header, field, variant_reader);
822 string_validation_func =
NULL;
841 &value_str, &value_pos);
842 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
853 bad_string_code = DBUS_INVALID_BAD_DESTINATION;
857 bad_string_code = DBUS_INVALID_BAD_INTERFACE;
862 value_str, str_data_pos))
864 _dbus_verbose (
"Message is on the local interface\n");
865 return DBUS_INVALID_USES_LOCAL_INTERFACE;
871 bad_string_code = DBUS_INVALID_BAD_MEMBER;
876 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
881 bad_string_code = DBUS_INVALID_BAD_SENDER;
886 string_validation_func =
NULL;
891 value_str, str_data_pos))
893 _dbus_verbose (
"Message is from the local path\n");
894 return DBUS_INVALID_USES_LOCAL_PATH;
902 return DBUS_INVALID_BAD_SERIAL;
912 string_validation_func =
NULL;
920 if (string_validation_func)
931 _dbus_verbose (
"Validating string header field; code %d if fails\n",
934 if (!(*string_validation_func) (value_str, str_data_pos, len))
935 return bad_string_code;
972 int fields_array_len,
983 unsigned char v_byte;
990 _dbus_assert (start == (
int) _DBUS_ALIGN_VALUE (start, 8));
996 _dbus_verbose (
"Failed to copy buffer into new header\n");
1001 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1003 leftover = len - header_len - body_len - start;
1023 _dbus_assert (start + header_len == (
int) _DBUS_ALIGN_VALUE (padding_start, 8));
1024 _dbus_assert (start + header_len == padding_start + padding_len);
1026 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1030 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
1035 header->
padding = padding_len;
1037 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
1049 &_dbus_header_signature_str, 0,
1071 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
1091 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
1111 *validity = DBUS_INVALID_BAD_SERIAL;
1123 unsigned char field_code;
1135 _dbus_verbose (
"invalid header field code\n");
1136 *validity = DBUS_INVALID_HEADER_FIELD_CODE;
1142 _dbus_verbose (
"unknown header field code %d, skipping\n",
1150 v = load_and_validate_field (header, field_code, &variant_reader);
1153 _dbus_verbose (
"Field %d was invalid\n", field_code);
1171 v = check_mandatory_fields (header);
1174 _dbus_verbose (
"Mandatory fields were missing, code %d\n", v);
1217 find_field_for_modification (
DBusHeader *header,
1228 &_dbus_header_signature_str,
1238 unsigned char field_code;
1245 if (field_code == (
unsigned) field)
1278 if (!reserve_header_padding (header))
1282 if (_dbus_header_cache_check (header, field))
1287 if (!find_field_for_modification (header, field,
1288 &reader, &realign_root))
1291 if (!set_basic_field (&reader, field, type, value, &realign_root))
1301 &_dbus_header_signature_str,
1310 &_dbus_header_signature_str,
1319 if (!write_basic_field (&array,
1320 field, type, value))
1327 correct_header_padding (header);
1333 _dbus_header_cache_invalidate_all (header);
1356 _dbus_assert (_dbus_header_field_types[field].code == field);
1363 if (!_dbus_header_cache_check (header, field))
1395 if (!_dbus_header_cache_check (header, field))
1399 *str = &header->
data;
1420 if (_dbus_header_cache_known_nonexistent (header, field))
1426 if (!find_field_for_modification (header, field,
1427 &reader, &realign_root))
1430 if (!reserve_header_padding (header))
1437 correct_header_padding (header);
1439 _dbus_header_cache_invalidate_all (header);
1441 _dbus_assert (!_dbus_header_cache_check (header, field));
1459 unsigned char *flags_p;
1480 const unsigned char *flags_p;
1484 return (*flags_p & flag) != 0;
1501 if (byte_order == new_order)
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
#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.
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.
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...
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
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_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.
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.
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
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_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.
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
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_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.
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_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.
void _dbus_string_set_byte(DBusString *str, int i, unsigned char byte)
Sets the value of the byte at the given position.
#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.
const char * _dbus_string_get_const_data_len(const DBusString *str, int start, int len)
const version of _dbus_string_get_data_len().
#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.