X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-marshal-header.c;h=88887a82a59333263f34a15a49b8ae5f740ac1ae;hb=67f9cca382df0d03adfe6b619aa613d103fa77f6;hp=a371115522d7afb3b2f65adfded40f24f9b9d661;hpb=31988af4089f3793940417535f8eabaae1ac26c8;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c index a371115..88887a8 100644 --- a/dbus/dbus-marshal-header.c +++ b/dbus/dbus-marshal-header.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-marshal-header.c Managing marshaling/demarshaling of message headers * * Copyright (C) 2005 Red Hat, Inc. @@ -17,12 +17,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include +#include "dbus/dbus-shared.h" #include "dbus-marshal-header.h" #include "dbus-marshal-recursive.h" +#include "dbus-marshal-byteswap.h" /** * @addtogroup DBusMarshal @@ -36,9 +39,9 @@ /** Static #DBusString containing the signature of a message header */ _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE); /** Static #DBusString containing the local interface */ -_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL); +_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_LOCAL); /** Static #DBusString containing the local path */ -_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_ORG_FREEDESKTOP_LOCAL); +_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_LOCAL); /** Offset from start of _dbus_header_signature_str to the signature of the fields array */ #define FIELDS_ARRAY_SIGNATURE_OFFSET 6 @@ -65,8 +68,8 @@ _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_ORG_FREEDESKTOP typedef struct { - unsigned char code; - unsigned char type; + unsigned char code; /**< the field code */ + unsigned char type; /**< the value type */ } HeaderFieldType; static const HeaderFieldType @@ -79,7 +82,8 @@ _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = { { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 }, { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING }, { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING }, - { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE } + { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }, + { DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 } }; /** Macro to look up the correct type for a field */ @@ -151,10 +155,6 @@ _dbus_header_cache_one (DBusHeader *header, int field_code, DBusTypeReader *variant_reader) { - int variant_type; - - variant_type = _dbus_type_reader_get_current_type (variant_reader); - header->fields[field_code].value_pos = _dbus_type_reader_get_value_pos (variant_reader); @@ -165,6 +165,20 @@ _dbus_header_cache_one (DBusHeader *header, } /** + * Returns the header's byte order. + * + * @param header the header + * @returns the byte order + */ +char +_dbus_header_get_byte_order (const DBusHeader *header) +{ + _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET); + + return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET); +} + +/** * Revalidates the fields cache * * @param header the header @@ -184,7 +198,7 @@ _dbus_header_cache_revalidate (DBusHeader *header) } _dbus_type_reader_init (&reader, - header->byte_order, + _dbus_header_get_byte_order (header), &_dbus_header_signature_str, FIELDS_ARRAY_SIGNATURE_OFFSET, &header->data, @@ -398,7 +412,7 @@ _dbus_header_set_serial (DBusHeader *header, _dbus_marshal_set_uint32 (&header->data, SERIAL_OFFSET, serial, - header->byte_order); + _dbus_header_get_byte_order (header)); } /** @@ -412,7 +426,7 @@ _dbus_header_get_serial (DBusHeader *header) { return _dbus_marshal_read_uint32 (&header->data, SERIAL_OFFSET, - header->byte_order, + _dbus_header_get_byte_order (header), NULL); } @@ -422,15 +436,12 @@ _dbus_header_get_serial (DBusHeader *header) * _dbus_header_create(). * * @param header header to re-initialize - * @param byte_order byte order of the header */ void -_dbus_header_reinit (DBusHeader *header, - int byte_order) +_dbus_header_reinit (DBusHeader *header) { _dbus_string_set_length (&header->data, 0); - header->byte_order = byte_order; header->padding = 0; _dbus_header_cache_invalidate_all (header); @@ -445,13 +456,12 @@ _dbus_header_reinit (DBusHeader *header, * @returns #FALSE if not enough memory */ dbus_bool_t -_dbus_header_init (DBusHeader *header, - int byte_order) +_dbus_header_init (DBusHeader *header) { if (!_dbus_string_init_preallocated (&header->data, 32)) return FALSE; - _dbus_header_reinit (header, byte_order); + _dbus_header_reinit (header); return TRUE; } @@ -505,7 +515,7 @@ _dbus_header_copy (const DBusHeader *header, * * @param header the header * @param message_type the message type - * @param destination service field or #NULL + * @param destination destination field or #NULL * @param path path field or #NULL * @param interface interface field or #NULL * @param member member field or #NULL @@ -514,6 +524,7 @@ _dbus_header_copy (const DBusHeader *header, */ dbus_bool_t _dbus_header_create (DBusHeader *header, + int byte_order, int message_type, const char *destination, const char *path, @@ -526,7 +537,9 @@ _dbus_header_create (DBusHeader *header, DBusTypeWriter writer; DBusTypeWriter array; - _dbus_assert ((interface && member) || + _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || + byte_order == DBUS_BIG_ENDIAN); + _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) || (error_name) || !(interface || member || error_name)); _dbus_assert (_dbus_string_get_length (&header->data) == 0); @@ -534,12 +547,12 @@ _dbus_header_create (DBusHeader *header, if (!reserve_header_padding (header)) return FALSE; - _dbus_type_writer_init_values_only (&writer, header->byte_order, + _dbus_type_writer_init_values_only (&writer, byte_order, &_dbus_header_signature_str, 0, &header->data, HEADER_END_BEFORE_PADDING (header)); - v_BYTE = header->byte_order; + v_BYTE = byte_order; if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)) goto oom; @@ -671,7 +684,7 @@ _dbus_header_have_message_untrusted (int max_message_length, dbus_uint32_t body_len_unsigned; _dbus_assert (start >= 0); - _dbus_assert (start < _DBUS_INT_MAX / 2); + _dbus_assert (start < _DBUS_INT32_MAX / 2); _dbus_assert (len >= 0); _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8)); @@ -710,16 +723,16 @@ _dbus_header_have_message_untrusted (int max_message_length, /* overflow should be impossible since the lengths aren't allowed to * be huge. */ - _dbus_assert (max_message_length < _DBUS_INT_MAX / 2); + _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2); if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length) { *validity = DBUS_INVALID_MESSAGE_TOO_LONG; return FALSE; } - _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT_MAX); - _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT_MAX); - _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT_MAX); + _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX); + _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX); + _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX); *body_len = body_len_unsigned; *fields_array_len = fields_array_len_unsigned; @@ -772,6 +785,7 @@ load_and_validate_field (DBusHeader *header, int expected_type; const DBusString *value_str; int value_pos; + int str_data_pos; dbus_uint32_t v_UINT32; int bad_string_code; dbus_bool_t (* string_validation_func) (const DBusString *str, @@ -811,6 +825,7 @@ load_and_validate_field (DBusHeader *header, v_UINT32 = 0; value_str = NULL; value_pos = -1; + str_data_pos = -1; bad_string_code = DBUS_VALID; if (expected_type == DBUS_TYPE_UINT32) @@ -824,6 +839,7 @@ load_and_validate_field (DBusHeader *header, { _dbus_header_get_field_raw (header, field, &value_str, &value_pos); + str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4; } else { @@ -833,7 +849,7 @@ load_and_validate_field (DBusHeader *header, switch (field) { case DBUS_HEADER_FIELD_DESTINATION: - string_validation_func = _dbus_validate_service; + string_validation_func = _dbus_validate_bus_name; bad_string_code = DBUS_INVALID_BAD_DESTINATION; break; case DBUS_HEADER_FIELD_INTERFACE: @@ -843,7 +859,7 @@ load_and_validate_field (DBusHeader *header, if (_dbus_string_equal_substring (&_dbus_local_interface_str, 0, _dbus_string_get_length (&_dbus_local_interface_str), - value_str, value_pos)) + value_str, str_data_pos)) { _dbus_verbose ("Message is on the local interface\n"); return DBUS_INVALID_USES_LOCAL_INTERFACE; @@ -861,7 +877,7 @@ load_and_validate_field (DBusHeader *header, break; case DBUS_HEADER_FIELD_SENDER: - string_validation_func = _dbus_validate_service; + string_validation_func = _dbus_validate_bus_name; bad_string_code = DBUS_INVALID_BAD_SENDER; break; @@ -869,13 +885,10 @@ load_and_validate_field (DBusHeader *header, /* OBJECT_PATH was validated generically due to its type */ string_validation_func = NULL; - _dbus_verbose ("value_str %p value_pos %d value_str_len %d\n", - value_str, value_pos, - _dbus_string_get_length (value_str)); if (_dbus_string_equal_substring (&_dbus_local_path_str, 0, _dbus_string_get_length (&_dbus_local_path_str), - value_str, value_pos)) + value_str, str_data_pos)) { _dbus_verbose ("Message is from the local path\n"); return DBUS_INVALID_USES_LOCAL_PATH; @@ -890,6 +903,10 @@ load_and_validate_field (DBusHeader *header, } break; + case DBUS_HEADER_FIELD_UNIX_FDS: + /* Every value makes sense */ + break; + case DBUS_HEADER_FIELD_SIGNATURE: /* SIGNATURE validated generically due to its type */ string_validation_func = NULL; @@ -907,9 +924,14 @@ load_and_validate_field (DBusHeader *header, _dbus_assert (bad_string_code != DBUS_VALID); len = _dbus_marshal_read_uint32 (value_str, value_pos, - header->byte_order, NULL); + _dbus_header_get_byte_order (header), + NULL); - if (!(*string_validation_func) (value_str, value_pos + 4, len)) +#if 0 + _dbus_verbose ("Validating string header field; code %d if fails\n", + bad_string_code); +#endif + if (!(*string_validation_func) (value_str, str_data_pos, len)) return bad_string_code; } @@ -917,11 +939,12 @@ load_and_validate_field (DBusHeader *header, } /** - * Creates a message header from untrusted data. The return value - * is #TRUE if there was enough memory and the data was valid. If it - * returns #TRUE, the header will be created. If it returns #FALSE - * and *validity == #DBUS_VALID, then there wasn't enough memory. If - * it returns #FALSE and *validity != #DBUS_VALID then the data was + * Creates a message header from potentially-untrusted data. The + * return value is #TRUE if there was enough memory and the data was + * valid. If it returns #TRUE, the header will be created. If it + * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR, + * then there wasn't enough memory. If it returns #FALSE + * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was * invalid. * * The byte_order, fields_array_len, and body_len args should be from @@ -930,6 +953,7 @@ load_and_validate_field (DBusHeader *header, * already done. * * @param header the header (must be initialized) + * @param mode whether to do validation * @param validity return location for invalidity reason * @param byte_order byte order from header * @param fields_array_len claimed length of fields array @@ -941,15 +965,16 @@ load_and_validate_field (DBusHeader *header, * @returns #FALSE if no memory or data was invalid, #TRUE otherwise */ dbus_bool_t -_dbus_header_load_untrusted (DBusHeader *header, - DBusValidity *validity, - int byte_order, - int fields_array_len, - int header_len, - int body_len, - const DBusString *str, - int start, - int len) +_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) { int leftover; DBusValidity v; @@ -969,19 +994,26 @@ _dbus_header_load_untrusted (DBusHeader *header, if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0)) { _dbus_verbose ("Failed to copy buffer into new header\n"); - *validity = DBUS_VALID; + *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; return FALSE; } - v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0, - byte_order, - &leftover, - str, start, len); - - if (v != DBUS_VALID) + if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) { - *validity = v; - goto invalid; + leftover = len - header_len - body_len - start; + } + else + { + v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0, + byte_order, + &leftover, + str, start, len); + + if (v != DBUS_VALID) + { + *validity = v; + goto invalid; + } } _dbus_assert (leftover < len); @@ -991,14 +1023,23 @@ _dbus_header_load_untrusted (DBusHeader *header, _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8)); _dbus_assert (start + header_len == padding_start + padding_len); - if (!_dbus_string_validate_nul (str, padding_start, padding_len)) + if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) { - *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; - goto invalid; + if (!_dbus_string_validate_nul (str, padding_start, padding_len)) + { + *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; + goto invalid; + } } header->padding = padding_len; + if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) + { + *validity = DBUS_VALID; + return TRUE; + } + /* We now know the data is well-formed, but we have to check that * it's valid. */ @@ -1156,9 +1197,22 @@ _dbus_header_update_lengths (DBusHeader *header, _dbus_marshal_set_uint32 (&header->data, BODY_LENGTH_OFFSET, body_len, - header->byte_order); + _dbus_header_get_byte_order (header)); } +/** + * Try to find the given field. + * + * @param header the header + * @param field the field code + * @param reader a type reader; on success this is left pointing at the struct + * (uv) for the field, while on failure it is left pointing into empty space + * at the end of the header fields + * @param realign_root another type reader; on success or failure it is left + * pointing to the beginning of the array of fields (i.e. the thing that might + * need realigning) + * @returns #TRUE on success + */ static dbus_bool_t find_field_for_modification (DBusHeader *header, int field, @@ -1170,7 +1224,7 @@ find_field_for_modification (DBusHeader *header, retval = FALSE; _dbus_type_reader_init (realign_root, - header->byte_order, + _dbus_header_get_byte_order (header), &_dbus_header_signature_str, FIELDS_ARRAY_SIGNATURE_OFFSET, &header->data, @@ -1219,7 +1273,7 @@ _dbus_header_set_field_basic (DBusHeader *header, int type, const void *value) { - _dbus_return_val_if_fail (field <= DBUS_HEADER_FIELD_LAST, FALSE); + _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); if (!reserve_header_padding (header)) return FALSE; @@ -1243,7 +1297,7 @@ _dbus_header_set_field_basic (DBusHeader *header, DBusTypeWriter array; _dbus_type_writer_init_values_only (&writer, - header->byte_order, + _dbus_header_get_byte_order (header), &_dbus_header_signature_str, FIELDS_ARRAY_SIGNATURE_OFFSET, &header->data, @@ -1313,7 +1367,7 @@ _dbus_header_get_field_basic (DBusHeader *header, _dbus_marshal_read_basic (&header->data, header->fields[field].value_pos, - type, value, header->byte_order, + type, value, _dbus_header_get_byte_order (header), NULL); return TRUE; @@ -1430,17 +1484,29 @@ _dbus_header_get_flag (DBusHeader *header, return (*flags_p & flag) != 0; } -/** @} */ +/** + * Swaps the header into the given order if required. + * + * @param header the header + * @param new_order the new byte order + */ +void +_dbus_header_byteswap (DBusHeader *header, + int new_order) +{ + char byte_order; -#ifdef DBUS_BUILD_TESTS -#include "dbus-test.h" -#include + byte_order = _dbus_header_get_byte_order (header); -dbus_bool_t -_dbus_marshal_header_test (void) -{ + if (byte_order == new_order) + return; - return TRUE; + _dbus_marshal_byteswap (&_dbus_header_signature_str, + 0, byte_order, + new_order, + &header->data, 0); + + _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order); } -#endif /* DBUS_BUILD_TESTS */ +/** @} */