2012-06-29 15:23:21 +00:00
|
|
|
/* packet-dbus.c
|
|
|
|
* Routines for D-Bus dissection
|
|
|
|
* Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
|
2020-11-28 23:22:24 +00:00
|
|
|
* Copyright 2020, Simon Holesch <simon@holesch.de>
|
2012-06-29 15:23:21 +00:00
|
|
|
*
|
|
|
|
* Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-12 11:23:27 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2012-06-29 15:23:21 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <epan/packet.h>
|
2013-11-29 20:53:00 +00:00
|
|
|
#include <wiretap/wtap.h>
|
2012-06-29 15:23:21 +00:00
|
|
|
#include <epan/expert.h>
|
2020-11-28 23:22:24 +00:00
|
|
|
#include <epan/ptvcursor.h>
|
2021-06-16 09:01:23 +00:00
|
|
|
#include <wsutil/ws_roundup.h>
|
2014-12-20 21:23:59 +00:00
|
|
|
#include "packet-tcp.h"
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
#define DBUS_MAX_ARRAY_LEN (64 * 1024 * 1024)
|
|
|
|
#define DBUS_MAX_NAME_LENGTH 255
|
|
|
|
#define DBUS_MAX_SIGNATURE_LENGTH 255
|
|
|
|
#define DBUS_MAX_TYPE_NESTING_LEVEL 32
|
|
|
|
#define DBUS_MAX_TOTAL_NESTING_LEVEL (2 * DBUS_MAX_TYPE_NESTING_LEVEL)
|
|
|
|
|
|
|
|
#define SIG_CODE_BYTE ('y')
|
|
|
|
#define SIG_CODE_BOOLEAN ('b')
|
|
|
|
#define SIG_CODE_INT16 ('n')
|
|
|
|
#define SIG_CODE_UINT16 ('q')
|
|
|
|
#define SIG_CODE_INT32 ('i')
|
|
|
|
#define SIG_CODE_UINT32 ('u')
|
|
|
|
#define SIG_CODE_INT64 ('x')
|
|
|
|
#define SIG_CODE_UINT64 ('t')
|
|
|
|
#define SIG_CODE_DOUBLE ('d')
|
|
|
|
#define SIG_CODE_STRING ('s')
|
|
|
|
#define SIG_CODE_OBJECT_PATH ('o')
|
|
|
|
#define SIG_CODE_SIGNATURE ('g')
|
|
|
|
#define SIG_CODE_ARRAY ('a')
|
|
|
|
#define SIG_CODE_STRUCT_OPEN ('(')
|
|
|
|
#define SIG_CODE_STRUCT_CLOSE (')')
|
|
|
|
#define SIG_CODE_VARIANT ('v')
|
|
|
|
#define SIG_CODE_DICT_ENTRY_OPEN ('{')
|
|
|
|
#define SIG_CODE_DICT_ENTRY_CLOSE ('}')
|
|
|
|
#define SIG_CODE_UNIX_FD ('h')
|
|
|
|
|
2013-03-16 08:52:09 +00:00
|
|
|
void proto_register_dbus(void);
|
|
|
|
void proto_reg_handoff_dbus(void);
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static int proto_dbus = -1;
|
2012-06-29 15:23:21 +00:00
|
|
|
static gboolean dbus_desegment = TRUE;
|
|
|
|
|
2013-08-17 07:16:12 +00:00
|
|
|
static dissector_handle_t dbus_handle;
|
|
|
|
static dissector_handle_t dbus_handle_tcp;
|
2012-06-29 15:23:21 +00:00
|
|
|
|
|
|
|
#define DBUS_MESSAGE_TYPE_INVALID 0
|
|
|
|
#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
|
|
|
|
#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
|
|
|
|
#define DBUS_MESSAGE_TYPE_ERROR 3
|
|
|
|
#define DBUS_MESSAGE_TYPE_SIGNAL 4
|
|
|
|
|
|
|
|
static const value_string message_type_vals[] = {
|
|
|
|
{ DBUS_MESSAGE_TYPE_INVALID, "Invalid" },
|
|
|
|
{ DBUS_MESSAGE_TYPE_METHOD_CALL, "Method call" },
|
|
|
|
{ DBUS_MESSAGE_TYPE_METHOD_RETURN, "Method reply" },
|
|
|
|
{ DBUS_MESSAGE_TYPE_ERROR, "Error reply" },
|
|
|
|
{ DBUS_MESSAGE_TYPE_SIGNAL, "Signal emission" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DBUS_HEADER_FIELD_INVALID 0
|
|
|
|
#define DBUS_HEADER_FIELD_PATH 1
|
|
|
|
#define DBUS_HEADER_FIELD_INTERFACE 2
|
|
|
|
#define DBUS_HEADER_FIELD_MEMBER 3
|
|
|
|
#define DBUS_HEADER_FIELD_ERROR_NAME 4
|
|
|
|
#define DBUS_HEADER_FIELD_REPLY_SERIAL 5
|
|
|
|
#define DBUS_HEADER_FIELD_DESTINATION 6
|
|
|
|
#define DBUS_HEADER_FIELD_SENDER 7
|
|
|
|
#define DBUS_HEADER_FIELD_SIGNATURE 8
|
|
|
|
#define DBUS_HEADER_FIELD_UNIX_FDS 9
|
|
|
|
|
|
|
|
static const value_string field_code_vals[] = {
|
2020-11-28 23:22:24 +00:00
|
|
|
{ DBUS_HEADER_FIELD_INVALID, "Invalid" },
|
|
|
|
{ DBUS_HEADER_FIELD_PATH, "Path" },
|
|
|
|
{ DBUS_HEADER_FIELD_INTERFACE, "Interface" },
|
|
|
|
{ DBUS_HEADER_FIELD_MEMBER, "Member" },
|
|
|
|
{ DBUS_HEADER_FIELD_ERROR_NAME, "Error name" },
|
|
|
|
{ DBUS_HEADER_FIELD_REPLY_SERIAL, "Reply serial" },
|
|
|
|
{ DBUS_HEADER_FIELD_DESTINATION, "Destination" },
|
|
|
|
{ DBUS_HEADER_FIELD_SENDER, "Sender" },
|
|
|
|
{ DBUS_HEADER_FIELD_SIGNATURE, "Signature" },
|
|
|
|
{ DBUS_HEADER_FIELD_UNIX_FDS, "Unix FDs" },
|
2012-06-29 15:23:21 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static const value_string endianness_vals[] = {
|
|
|
|
{ 'l', "little-endian" },
|
|
|
|
{ 'B', "big-endian" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2021-02-14 15:36:32 +00:00
|
|
|
static const true_false_string allow_vals = { "Allow", "Don't allow" };
|
|
|
|
static const true_false_string no_start_vals = { "Don't start", "Start" };
|
|
|
|
static const true_false_string not_expected_vals = { "Not expected", "Expected" };
|
2020-11-28 23:22:24 +00:00
|
|
|
|
|
|
|
static int hf_dbus_endianness = -1;
|
|
|
|
static int hf_dbus_message_type = -1;
|
|
|
|
static int hf_dbus_flags = -1;
|
|
|
|
static int hf_dbus_flags_no_reply_expected = -1;
|
|
|
|
static int hf_dbus_flags_no_auto_start = -1;
|
|
|
|
static int hf_dbus_flags_allow_interactive_authorization = -1;
|
|
|
|
static int hf_dbus_version = -1;
|
|
|
|
static int hf_dbus_body_length = -1;
|
|
|
|
static int hf_dbus_serial = -1;
|
|
|
|
static int hf_dbus_field_code = -1;
|
|
|
|
static int hf_dbus_padding = -1;
|
|
|
|
static int hf_dbus_path = -1;
|
|
|
|
static int hf_dbus_interface = -1;
|
|
|
|
static int hf_dbus_member = -1;
|
|
|
|
static int hf_dbus_error_name = -1;
|
|
|
|
static int hf_dbus_reply_serial = -1;
|
|
|
|
static int hf_dbus_destination = -1;
|
|
|
|
static int hf_dbus_sender = -1;
|
|
|
|
static int hf_dbus_signature = -1;
|
|
|
|
static int hf_dbus_unix_fds = -1;
|
|
|
|
static int hf_dbus_body = -1;
|
|
|
|
static int hf_dbus_type_byte = -1;
|
|
|
|
static int hf_dbus_type_boolean = -1;
|
|
|
|
static int hf_dbus_type_int16 = -1;
|
|
|
|
static int hf_dbus_type_uint16 = -1;
|
|
|
|
static int hf_dbus_type_int32 = -1;
|
|
|
|
static int hf_dbus_type_uint32 = -1;
|
|
|
|
static int hf_dbus_type_int64 = -1;
|
|
|
|
static int hf_dbus_type_uint64 = -1;
|
|
|
|
static int hf_dbus_type_double = -1;
|
|
|
|
static int hf_dbus_type_string = -1;
|
|
|
|
static int hf_dbus_type_object_path = -1;
|
|
|
|
static int hf_dbus_type_signature = -1;
|
|
|
|
static int hf_dbus_type_array = -1;
|
|
|
|
static int hf_dbus_type_array_length = -1;
|
|
|
|
static int hf_dbus_type_struct = -1;
|
|
|
|
static int hf_dbus_type_variant = -1;
|
|
|
|
static int hf_dbus_type_variant_signature = -1;
|
|
|
|
static int hf_dbus_type_dict_entry = -1;
|
|
|
|
static int hf_dbus_type_dict_entry_key = -1;
|
|
|
|
static int hf_dbus_type_unix_fd = -1;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static int ett_dbus = -1;
|
|
|
|
static int ett_dbus_flags = -1;
|
|
|
|
static int ett_dbus_header_field_array = -1;
|
|
|
|
static int ett_dbus_header_field = -1;
|
|
|
|
static int ett_dbus_body = -1;
|
|
|
|
static int ett_dbus_type_array = -1;
|
|
|
|
static int ett_dbus_type_struct = -1;
|
|
|
|
static int ett_dbus_type_variant = -1;
|
|
|
|
static int ett_dbus_type_dict_entry = -1;
|
|
|
|
|
|
|
|
static expert_field ei_dbus_endianness_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_message_type_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_message_type_unknown = EI_INIT;
|
|
|
|
static expert_field ei_dbus_version_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_serial_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_field_code_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_required_header_field_missing = EI_INIT;
|
|
|
|
static expert_field ei_dbus_padding_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_field_signature_wrong = EI_INIT;
|
|
|
|
static expert_field ei_dbus_interface_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_member_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_error_name_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_bus_name_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_boolean_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_string_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_signature_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_array_too_long = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_array_content_out_of_bounds = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_object_path_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_type_variant_signature_invalid = EI_INIT;
|
|
|
|
static expert_field ei_dbus_nested_too_deeply = EI_INIT;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
typedef struct {
|
|
|
|
ptvcursor_t *cursor;
|
|
|
|
packet_info *pinfo;
|
|
|
|
guint enc;
|
|
|
|
guint32 message_type;
|
|
|
|
guint32 body_len;
|
|
|
|
guint32 serial;
|
|
|
|
|
|
|
|
proto_item *current_pi;
|
|
|
|
const char *path;
|
|
|
|
const char *interface;
|
|
|
|
const char *member;
|
|
|
|
const char *error_name;
|
|
|
|
guint32 reply_serial;
|
|
|
|
const char *destination;
|
|
|
|
const char *sender;
|
|
|
|
const char *signature;
|
|
|
|
guint32 unix_fds;
|
|
|
|
} dbus_packet_t;
|
|
|
|
|
|
|
|
typedef struct _dbus_type_reader_t {
|
|
|
|
dbus_packet_t *packet;
|
|
|
|
const char *signature;
|
|
|
|
guint32 level;
|
|
|
|
guint32 array_level;
|
|
|
|
guint32 struct_level;
|
|
|
|
guint32 dict_entry_level;
|
|
|
|
const char *array_type_start;
|
|
|
|
int array_end_offset;
|
|
|
|
gboolean is_in_variant;
|
|
|
|
gboolean is_basic_variant;
|
|
|
|
gboolean is_in_dict_entry;
|
|
|
|
gboolean is_basic_dict_entry;
|
|
|
|
proto_item *container;
|
|
|
|
struct _dbus_type_reader_t *parent;
|
|
|
|
} dbus_type_reader_t;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
typedef union {
|
|
|
|
gboolean bool_;
|
|
|
|
guint32 uint;
|
|
|
|
gint32 int_;
|
|
|
|
guint64 uint64;
|
|
|
|
gint64 int64;
|
|
|
|
double double_;
|
|
|
|
const char *string;
|
|
|
|
} dbus_val_t;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_ascii_digit(char c) {
|
|
|
|
return (guint)c - '0' < 10;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_ascii_alpha(char c) {
|
|
|
|
return ((guint)c | 0x20) - 'a' <= 'z' - 'a';
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_dbus_object_path_valid(const char *path) {
|
|
|
|
// - The path may be of any length.
|
|
|
|
// - The path must begin with an ASCII '/' (integer 47) character, and must consist of elements separated by
|
|
|
|
// slash characters.
|
|
|
|
// - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
|
|
|
|
// - No element may be the empty string.
|
|
|
|
// - Multiple '/' characters cannot occur in sequence.
|
|
|
|
// - A trailing '/' character is not allowed unless the path is the root path (a single '/' character).
|
|
|
|
if (*path == '/' && *(path + 1) == '\0') {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
while (*path == '/') {
|
|
|
|
path++;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (*path == '/') {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
while (is_ascii_alpha(*path) || is_ascii_digit(*path) || *path == '_') {
|
|
|
|
path++;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (*path == '\0') {
|
|
|
|
return *(path - 1) != '/';
|
|
|
|
}
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_dbus_interface_valid(const char *interface) {
|
|
|
|
// - Interface names are composed of 2 or more elements separated by a period ('.') character. All elements
|
|
|
|
// must contain at least one character.
|
|
|
|
// - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_" and must not begin with a digit.
|
|
|
|
// - Interface names must not exceed the maximum name length.
|
|
|
|
gint elements = 0;
|
|
|
|
const char *p = interface;
|
|
|
|
do {
|
|
|
|
if (!(is_ascii_alpha(*p) || *p == '_')) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
elements++;
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_') {
|
|
|
|
p++;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (*p == '\0') {
|
|
|
|
size_t length = p - interface;
|
|
|
|
return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
|
|
|
|
}
|
|
|
|
} while (*p++ == '.');
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_dbus_member_name_valid(const char *member_name) {
|
|
|
|
// - Must only contain the ASCII characters "[A-Z][a-z][0-9]_" and may not begin with a digit.
|
|
|
|
// - Must not contain the '.' (period) character.
|
|
|
|
// - Must not exceed the maximum name length.
|
|
|
|
// - Must be at least 1 byte in length.
|
|
|
|
const char *p = member_name;
|
|
|
|
|
|
|
|
if (!(is_ascii_alpha(*p) || *p == '_')) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
do {
|
|
|
|
p++;
|
|
|
|
} while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_');
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (*p == '\0') {
|
|
|
|
size_t length = p - member_name;
|
|
|
|
return length <= DBUS_MAX_NAME_LENGTH;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2013-08-16 21:52:35 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_dbus_bus_name_valid(const char *bus_name) {
|
|
|
|
// - Bus names that start with a colon (':') character are unique connection names. Other bus names are called
|
|
|
|
// well-known bus names.
|
|
|
|
// - Bus names are composed of 1 or more elements separated by a period ('.') character. All elements must
|
|
|
|
// contain at least one character.
|
|
|
|
// - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-", with "-" discouraged in new bus
|
|
|
|
// names. Only elements that are part of a unique connection name may begin with a digit, elements in other
|
|
|
|
// bus names must not begin with a digit.
|
|
|
|
// - Bus names must contain at least one '.' (period) character (and thus at least two elements).
|
|
|
|
// - Bus names must not begin with a '.' (period) character.
|
|
|
|
// - Bus names must not exceed the maximum name length.
|
|
|
|
gint elements = 0;
|
|
|
|
const char *p = bus_name;
|
|
|
|
gboolean is_unique_name = FALSE;
|
|
|
|
|
|
|
|
if (*p == ':') {
|
|
|
|
is_unique_name = TRUE;
|
|
|
|
p++;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
do {
|
|
|
|
if (!(is_ascii_alpha(*p) || *p == '_' || *p == '-' || (is_unique_name && is_ascii_digit(*p)))) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
elements++;
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_' || *p == '-') {
|
|
|
|
p++;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (*p == '\0') {
|
|
|
|
size_t length = p - bus_name;
|
|
|
|
return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
|
|
|
|
}
|
|
|
|
} while (*p++ == '.');
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
|
|
|
static gboolean
|
2020-11-28 23:22:24 +00:00
|
|
|
is_basic_type(char sig_code) {
|
|
|
|
switch (sig_code) {
|
|
|
|
case SIG_CODE_BYTE:
|
|
|
|
case SIG_CODE_BOOLEAN:
|
|
|
|
case SIG_CODE_INT16:
|
|
|
|
case SIG_CODE_UINT16:
|
|
|
|
case SIG_CODE_INT32:
|
|
|
|
case SIG_CODE_UINT32:
|
|
|
|
case SIG_CODE_INT64:
|
|
|
|
case SIG_CODE_UINT64:
|
|
|
|
case SIG_CODE_DOUBLE:
|
|
|
|
case SIG_CODE_STRING:
|
|
|
|
case SIG_CODE_OBJECT_PATH:
|
|
|
|
case SIG_CODE_SIGNATURE:
|
|
|
|
case SIG_CODE_UNIX_FD:
|
|
|
|
return TRUE;
|
|
|
|
default:
|
2012-06-29 15:23:21 +00:00
|
|
|
return FALSE;
|
2020-11-28 23:22:24 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2021-01-28 00:17:54 +00:00
|
|
|
static const char *
|
|
|
|
skip_enclosed_container(const char *signature, char open_bracket, char closed_bracket) {
|
|
|
|
int nested = 0;
|
|
|
|
for (char sig_code = *signature++; sig_code != '\0'; sig_code = *signature++) {
|
|
|
|
if (sig_code == closed_bracket) {
|
|
|
|
if (nested == 0) {
|
|
|
|
return signature;
|
|
|
|
}
|
|
|
|
nested--;
|
|
|
|
} else if (sig_code == open_bracket) {
|
|
|
|
nested++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
skip_single_complete_type(const char *signature) {
|
|
|
|
char sig_code;
|
|
|
|
while (1) {
|
|
|
|
sig_code = *signature++;
|
|
|
|
switch (sig_code) {
|
|
|
|
case SIG_CODE_BYTE:
|
|
|
|
case SIG_CODE_BOOLEAN:
|
|
|
|
case SIG_CODE_INT16:
|
|
|
|
case SIG_CODE_UINT16:
|
|
|
|
case SIG_CODE_INT32:
|
|
|
|
case SIG_CODE_UINT32:
|
|
|
|
case SIG_CODE_INT64:
|
|
|
|
case SIG_CODE_UINT64:
|
|
|
|
case SIG_CODE_DOUBLE:
|
|
|
|
case SIG_CODE_STRING:
|
|
|
|
case SIG_CODE_OBJECT_PATH:
|
|
|
|
case SIG_CODE_SIGNATURE:
|
|
|
|
case SIG_CODE_VARIANT:
|
|
|
|
case SIG_CODE_UNIX_FD:
|
|
|
|
return signature;
|
|
|
|
case SIG_CODE_ARRAY:
|
|
|
|
continue;
|
|
|
|
case SIG_CODE_STRUCT_OPEN:
|
|
|
|
return skip_enclosed_container(signature, SIG_CODE_STRUCT_OPEN, SIG_CODE_STRUCT_CLOSE);
|
|
|
|
case SIG_CODE_DICT_ENTRY_OPEN:
|
|
|
|
return skip_enclosed_container(signature, SIG_CODE_DICT_ENTRY_OPEN, SIG_CODE_DICT_ENTRY_CLOSE);
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static gboolean
|
|
|
|
is_dbus_signature_valid(const char *signature) {
|
|
|
|
char sig_code;
|
|
|
|
size_t length = 0;
|
2021-01-28 00:17:54 +00:00
|
|
|
char prev_sig_code = '\0';
|
2020-11-28 23:22:24 +00:00
|
|
|
wmem_stack_t *expected_chars = wmem_stack_new(wmem_packet_scope());
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
while ((sig_code = *signature++) != '\0') {
|
|
|
|
if (++length >= DBUS_MAX_SIGNATURE_LENGTH) {
|
2012-06-29 15:23:21 +00:00
|
|
|
return FALSE;
|
2020-11-28 23:22:24 +00:00
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
switch (sig_code) {
|
|
|
|
case SIG_CODE_BYTE:
|
|
|
|
case SIG_CODE_SIGNATURE:
|
|
|
|
case SIG_CODE_VARIANT:
|
|
|
|
case SIG_CODE_INT16:
|
|
|
|
case SIG_CODE_UINT16:
|
|
|
|
case SIG_CODE_INT32:
|
|
|
|
case SIG_CODE_UINT32:
|
|
|
|
case SIG_CODE_BOOLEAN:
|
|
|
|
case SIG_CODE_OBJECT_PATH:
|
|
|
|
case SIG_CODE_STRING:
|
|
|
|
case SIG_CODE_UNIX_FD:
|
|
|
|
case SIG_CODE_INT64:
|
|
|
|
case SIG_CODE_UINT64:
|
|
|
|
case SIG_CODE_DOUBLE:
|
|
|
|
break;
|
|
|
|
case SIG_CODE_ARRAY:
|
2021-01-28 00:17:54 +00:00
|
|
|
switch (*signature) {
|
|
|
|
case '\0':
|
|
|
|
case SIG_CODE_STRUCT_CLOSE:
|
|
|
|
case SIG_CODE_DICT_ENTRY_CLOSE:
|
2020-11-28 23:22:24 +00:00
|
|
|
// arrays must be followed by a single complete type
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-01-28 00:17:54 +00:00
|
|
|
// invalid signature codes are detected in the next iteration
|
2020-11-28 23:22:24 +00:00
|
|
|
break;
|
|
|
|
case SIG_CODE_STRUCT_OPEN:
|
2021-01-28 00:17:54 +00:00
|
|
|
if (*signature == SIG_CODE_STRUCT_CLOSE) {
|
|
|
|
// empty structures are not allowed
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
wmem_stack_push(expected_chars, (void *)SIG_CODE_STRUCT_CLOSE);
|
|
|
|
break;
|
2021-01-28 00:17:54 +00:00
|
|
|
case SIG_CODE_DICT_ENTRY_OPEN: {
|
|
|
|
// dict entries must be an array element type
|
|
|
|
// the first single complete type (the "key") must be a basic type
|
|
|
|
if (prev_sig_code != SIG_CODE_ARRAY || !is_basic_type(*signature)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dict entries must contain exactly two single complete types
|
|
|
|
// + 1 can be used here, since the key is a basic type
|
|
|
|
const char *sig_code_close = skip_single_complete_type(signature + 1);
|
|
|
|
if (!sig_code_close || *sig_code_close != SIG_CODE_DICT_ENTRY_CLOSE) {
|
2020-11-28 23:22:24 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
wmem_stack_push(expected_chars, (void *)SIG_CODE_DICT_ENTRY_CLOSE);
|
|
|
|
break;
|
2021-01-28 00:17:54 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
case SIG_CODE_STRUCT_CLOSE:
|
|
|
|
case SIG_CODE_DICT_ENTRY_CLOSE:
|
|
|
|
if (wmem_stack_count(expected_chars) == 0 ||
|
|
|
|
(char)(guintptr)wmem_stack_pop(expected_chars) != sig_code) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-01-28 00:17:54 +00:00
|
|
|
|
|
|
|
prev_sig_code = sig_code;
|
2020-11-28 23:22:24 +00:00
|
|
|
}
|
|
|
|
return wmem_stack_count(expected_chars) == 0;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static void
|
|
|
|
add_expert(dbus_packet_t *packet, expert_field *ei) {
|
|
|
|
expert_add_info(packet->pinfo, packet->current_pi, ei);
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static guint32
|
|
|
|
add_uint(dbus_packet_t *packet, gint hf) {
|
|
|
|
header_field_info *info = proto_registrar_get_nth(hf);
|
|
|
|
gint length;
|
|
|
|
guint32 value;
|
|
|
|
switch (info->type) {
|
|
|
|
case FT_UINT8:
|
|
|
|
length = 1;
|
|
|
|
break;
|
|
|
|
case FT_UINT32:
|
|
|
|
length = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
}
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf, length, packet->enc, &value);
|
|
|
|
return value;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static const guint8 *
|
|
|
|
add_dbus_string(dbus_packet_t *packet, int hf, gint uint_length) {
|
|
|
|
const guint8 *string;
|
|
|
|
gint start_offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
proto_item *pi = ptvcursor_add_ret_string(packet->cursor, hf, uint_length,
|
|
|
|
packet->enc | ENC_UTF_8, wmem_packet_scope(), &string);
|
|
|
|
gint item_length = ptvcursor_current_offset(packet->cursor) - start_offset;
|
|
|
|
guint8 term_byte = tvb_get_guint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
|
|
|
|
proto_item_set_len(pi, item_length + 1);
|
|
|
|
ptvcursor_advance(packet->cursor, 1);
|
|
|
|
packet->current_pi = pi;
|
|
|
|
|
|
|
|
if ((strlen(string) != (size_t)(item_length - uint_length)) || (term_byte != '\0')) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return string;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 13:45:24 +00:00
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
calculate_padding_len(gint offset, char sig) {
|
|
|
|
int alignment;
|
2015-11-20 13:45:24 +00:00
|
|
|
switch (sig) {
|
2020-11-28 23:22:24 +00:00
|
|
|
case SIG_CODE_BYTE:
|
|
|
|
case SIG_CODE_SIGNATURE:
|
|
|
|
case SIG_CODE_VARIANT:
|
|
|
|
default:
|
|
|
|
alignment = 1;
|
|
|
|
break;
|
|
|
|
case SIG_CODE_INT16:
|
|
|
|
case SIG_CODE_UINT16:
|
|
|
|
alignment = 2;
|
|
|
|
break;
|
|
|
|
case SIG_CODE_INT32:
|
|
|
|
case SIG_CODE_UINT32:
|
|
|
|
case SIG_CODE_BOOLEAN:
|
|
|
|
case SIG_CODE_OBJECT_PATH:
|
|
|
|
case SIG_CODE_ARRAY:
|
|
|
|
case SIG_CODE_STRING:
|
|
|
|
case SIG_CODE_UNIX_FD:
|
|
|
|
alignment = 4;
|
|
|
|
break;
|
|
|
|
case SIG_CODE_INT64:
|
|
|
|
case SIG_CODE_UINT64:
|
|
|
|
case SIG_CODE_DOUBLE:
|
|
|
|
case SIG_CODE_STRUCT_OPEN:
|
|
|
|
case SIG_CODE_DICT_ENTRY_OPEN:
|
|
|
|
alignment = 8;
|
|
|
|
break;
|
2015-11-20 13:45:24 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
return (alignment - (offset % alignment)) % alignment;
|
2015-11-20 13:45:24 +00:00
|
|
|
}
|
|
|
|
|
2012-06-29 15:23:21 +00:00
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
add_padding(dbus_packet_t *packet, char sig) {
|
|
|
|
guint8 value;
|
|
|
|
tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
gint padding_len = calculate_padding_len(offset, sig);
|
|
|
|
|
|
|
|
if (padding_len != 0) {
|
|
|
|
packet->current_pi = ptvcursor_add(packet->cursor, hf_dbus_padding, padding_len, packet->enc);
|
|
|
|
for (gint i = offset; i < (offset + padding_len); i++) {
|
|
|
|
value = tvb_get_guint8(tvb, i);
|
|
|
|
if (value != 0) {
|
|
|
|
add_expert(packet, &ei_dbus_padding_invalid);
|
|
|
|
return 1;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
proto_item_set_hidden(packet->current_pi);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2021-01-27 22:32:55 +00:00
|
|
|
static void
|
|
|
|
reader_cleanup(dbus_type_reader_t *reader) {
|
|
|
|
for (dbus_type_reader_t *r = reader; r->parent; r = r->parent) {
|
|
|
|
ptvcursor_pop_subtree(r->packet->cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static dbus_type_reader_t *
|
|
|
|
reader_next(dbus_type_reader_t *reader, int hf, int ett, dbus_val_t *value) {
|
|
|
|
int err = 0;
|
|
|
|
char sig_code = *reader->signature++;
|
|
|
|
dbus_packet_t *packet = reader->packet;
|
|
|
|
gboolean is_single_complete_type = TRUE;
|
|
|
|
add_padding(packet, sig_code);
|
|
|
|
|
|
|
|
switch (sig_code) {
|
|
|
|
case SIG_CODE_BYTE:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_byte, 1, packet->enc, &value->uint);
|
|
|
|
break;
|
|
|
|
case SIG_CODE_BOOLEAN: {
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
|
|
|
|
guint8 val = tvb_get_guint8(tvb, offset);
|
|
|
|
packet->current_pi = ptvcursor_add_ret_boolean(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_boolean, 4, packet->enc, &value->bool_);
|
|
|
|
if (val >= 2) {
|
|
|
|
add_expert(packet, &ei_dbus_type_boolean_invalid);
|
|
|
|
err = 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_INT16:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_int16, 2, packet->enc, &value->int_);
|
|
|
|
break;
|
|
|
|
case SIG_CODE_UINT16:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_uint16, 2, packet->enc, &value->uint);
|
|
|
|
break;
|
|
|
|
case SIG_CODE_INT32:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_int32, 4, packet->enc, &value->int_);
|
|
|
|
break;
|
|
|
|
case SIG_CODE_UINT32:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_uint32, 4, packet->enc, &value->uint);
|
|
|
|
break;
|
|
|
|
case SIG_CODE_INT64: {
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
|
|
|
|
value->int64 = tvb_get_gint64(tvb, offset, packet->enc);
|
|
|
|
packet->current_pi = ptvcursor_add(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_int64, 8, packet->enc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_UINT64: {
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
|
|
|
|
value->uint64 = tvb_get_guint64(tvb, offset, packet->enc);
|
|
|
|
packet->current_pi = ptvcursor_add(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_uint64, 8, packet->enc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_DOUBLE: {
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
|
|
|
|
value->double_ = tvb_get_ieee_double(tvb, offset, packet->enc);
|
|
|
|
packet->current_pi = ptvcursor_add(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_double, 8, packet->enc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_STRING: {
|
|
|
|
const char *val = add_dbus_string(packet,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_string, 4);
|
|
|
|
if (!val || !g_utf8_validate(val, -1, NULL)) {
|
|
|
|
add_expert(packet, &ei_dbus_string_invalid);
|
|
|
|
err = 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
value->string = val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_OBJECT_PATH: {
|
|
|
|
const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_object_path, 4);
|
|
|
|
if (!val || !is_dbus_object_path_valid(val)) {
|
|
|
|
add_expert(packet, &ei_dbus_type_object_path_invalid);
|
|
|
|
err = 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
value->string = val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_SIGNATURE: {
|
|
|
|
const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_signature, 1);
|
|
|
|
if (!val || !is_dbus_signature_valid(val)) {
|
|
|
|
add_expert(packet, &ei_dbus_type_signature_invalid);
|
|
|
|
err = 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
value->string = val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_ARRAY: {
|
|
|
|
is_single_complete_type = FALSE;
|
|
|
|
proto_item *array = ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_array,
|
|
|
|
SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_array);
|
|
|
|
if (*reader->signature == SIG_CODE_DICT_ENTRY_OPEN) {
|
|
|
|
proto_item_append_text(array, " (Dict)");
|
|
|
|
}
|
|
|
|
guint32 array_len = add_uint(packet, hf_dbus_type_array_length);
|
|
|
|
value->uint = array_len;
|
|
|
|
add_padding(packet, *reader->signature);
|
|
|
|
if (array_len == 0) {
|
|
|
|
reader->signature = skip_single_complete_type(reader->signature);
|
2021-01-28 00:17:54 +00:00
|
|
|
// all signatures are validated
|
|
|
|
DISSECTOR_ASSERT(reader->signature);
|
2020-11-28 23:22:24 +00:00
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
is_single_complete_type = TRUE;
|
|
|
|
} else if (array_len <= DBUS_MAX_ARRAY_LEN) {
|
|
|
|
int end_offset = ptvcursor_current_offset(packet->cursor) + array_len;
|
2020-12-21 02:30:28 +00:00
|
|
|
dbus_type_reader_t *child = wmem_new(wmem_packet_scope(), dbus_type_reader_t);
|
2020-11-28 23:22:24 +00:00
|
|
|
*child = (dbus_type_reader_t){
|
|
|
|
.packet = reader->packet,
|
|
|
|
.signature = reader->signature,
|
|
|
|
.level = reader->level + 1,
|
|
|
|
.array_level = reader->array_level + 1,
|
|
|
|
.array_type_start = reader->signature,
|
|
|
|
.array_end_offset = end_offset,
|
|
|
|
.container = array,
|
|
|
|
.parent = reader,
|
|
|
|
};
|
|
|
|
reader = child;
|
|
|
|
} else {
|
|
|
|
add_expert(packet, &ei_dbus_type_array_too_long);
|
|
|
|
err = 1;
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_STRUCT_OPEN: {
|
|
|
|
is_single_complete_type = FALSE;
|
|
|
|
ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_struct,
|
|
|
|
SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_struct);
|
2020-12-21 02:30:28 +00:00
|
|
|
dbus_type_reader_t *child = wmem_new(wmem_packet_scope(), dbus_type_reader_t);
|
2020-11-28 23:22:24 +00:00
|
|
|
*child = (dbus_type_reader_t){
|
|
|
|
.packet = reader->packet,
|
|
|
|
.signature = reader->signature,
|
|
|
|
.level = reader->level + 1,
|
|
|
|
.struct_level = reader->struct_level + 1,
|
|
|
|
.parent = reader,
|
|
|
|
};
|
|
|
|
reader = child;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_VARIANT: {
|
|
|
|
is_single_complete_type = FALSE;
|
|
|
|
proto_item *variant = ptvcursor_add_with_subtree(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_variant,
|
|
|
|
SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_variant);
|
|
|
|
const char *variant_signature = add_dbus_string(packet, hf_dbus_type_variant_signature, 1);
|
|
|
|
value->string = variant_signature;
|
|
|
|
if (variant_signature && is_dbus_signature_valid(variant_signature)) {
|
2021-01-27 22:51:50 +00:00
|
|
|
if (variant_signature[0] != '\0') {
|
|
|
|
dbus_type_reader_t *child = wmem_new(wmem_packet_scope(), dbus_type_reader_t);
|
|
|
|
*child = (dbus_type_reader_t){
|
|
|
|
.packet = reader->packet,
|
|
|
|
.signature = variant_signature,
|
|
|
|
.level = reader->level + 1,
|
|
|
|
.is_in_variant = TRUE,
|
|
|
|
.is_basic_variant = is_basic_type(*variant_signature)
|
|
|
|
&& *(variant_signature + 1) == '\0',
|
|
|
|
.container = variant,
|
|
|
|
.parent = reader,
|
|
|
|
};
|
|
|
|
if (reader->is_in_dict_entry && child->is_basic_variant) {
|
|
|
|
reader->is_basic_dict_entry = TRUE;
|
|
|
|
}
|
|
|
|
reader = child;
|
|
|
|
} else {
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
2020-11-28 23:22:24 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
add_expert(packet, &ei_dbus_type_variant_signature_invalid);
|
|
|
|
err = 1;
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_DICT_ENTRY_OPEN: {
|
|
|
|
is_single_complete_type = FALSE;
|
|
|
|
proto_item *dict_entry = ptvcursor_add_with_subtree(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_dict_entry,
|
|
|
|
SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_dict_entry);
|
2020-12-21 02:30:28 +00:00
|
|
|
dbus_type_reader_t *child = wmem_new(wmem_packet_scope(), dbus_type_reader_t);
|
2020-11-28 23:22:24 +00:00
|
|
|
*child = (dbus_type_reader_t){
|
|
|
|
.packet = reader->packet,
|
|
|
|
.signature = reader->signature,
|
|
|
|
.level = reader->level + 1,
|
|
|
|
.dict_entry_level = reader->dict_entry_level + 1,
|
|
|
|
.is_in_dict_entry = TRUE,
|
|
|
|
.is_basic_dict_entry = is_basic_type(*(reader->signature + 1)),
|
|
|
|
.container = dict_entry,
|
|
|
|
.parent = reader,
|
|
|
|
};
|
|
|
|
reader = child;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SIG_CODE_STRUCT_CLOSE:
|
|
|
|
case SIG_CODE_DICT_ENTRY_CLOSE:
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
reader->parent->signature = reader->signature;
|
|
|
|
reader = reader->parent;
|
|
|
|
break;
|
|
|
|
case SIG_CODE_UNIX_FD:
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
|
|
|
|
hf != -1 ? hf : hf_dbus_type_unix_fd, 4, packet->enc, &value->uint);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// all signatures are validated
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (reader->level > DBUS_MAX_TOTAL_NESTING_LEVEL ||
|
|
|
|
reader->array_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
|
|
|
|
reader->struct_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
|
|
|
|
reader->dict_entry_level > DBUS_MAX_TYPE_NESTING_LEVEL) {
|
|
|
|
add_expert(packet, &ei_dbus_nested_too_deeply);
|
|
|
|
err= 1;
|
|
|
|
} else if (is_single_complete_type) {
|
|
|
|
// Arrays and variants don't have a closing signature code, but they end after a single complete type.
|
|
|
|
// Close them here recursively, e.g. "aav"
|
|
|
|
while (1) {
|
|
|
|
if (reader->array_type_start) { // inside array
|
|
|
|
gint offset = ptvcursor_current_offset(packet->cursor);
|
|
|
|
|
|
|
|
if (offset < reader->array_end_offset) {
|
|
|
|
// parse next array element -> reset signature
|
|
|
|
reader->signature = reader->array_type_start;
|
|
|
|
break;
|
|
|
|
} else if (offset == reader->array_end_offset) {
|
|
|
|
// all array elements parsed
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
reader->parent->signature = reader->signature;
|
|
|
|
reader = reader->parent;
|
|
|
|
} else {
|
|
|
|
// array elements don't fit into array
|
|
|
|
expert_add_info(packet->pinfo, reader->container,
|
|
|
|
&ei_dbus_type_array_content_out_of_bounds);
|
|
|
|
err = 1;
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
} else if (reader->is_in_variant) {
|
|
|
|
if (reader->is_basic_variant) {
|
|
|
|
proto_item_append_text(reader->container, ": %s",
|
|
|
|
proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
reader = reader->parent;
|
|
|
|
} else {
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
if (reader->is_in_dict_entry) {
|
|
|
|
// add "key: value" to dict entry item to make it readable without expanding the tree
|
|
|
|
if (*(reader->signature - 2) == SIG_CODE_DICT_ENTRY_OPEN) { // == key
|
|
|
|
// key is always a basic type
|
|
|
|
proto_item_append_text(reader->container, ", %s",
|
|
|
|
proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
|
|
|
|
} else if (reader->is_basic_dict_entry) { // == value
|
|
|
|
proto_item_append_text(reader->container, ": %s",
|
|
|
|
proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (err) {
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
|
|
|
return NULL;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2021-01-27 22:32:55 +00:00
|
|
|
return reader;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2021-01-27 22:32:55 +00:00
|
|
|
static gboolean
|
|
|
|
reader_is_finished(dbus_type_reader_t *reader) {
|
2020-11-28 23:22:24 +00:00
|
|
|
return *reader->signature == '\0' && reader->parent == NULL;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static int
|
|
|
|
dissect_dbus_signature(dbus_packet_t *packet, const char *signature) {
|
|
|
|
dbus_type_reader_t root_reader = {
|
|
|
|
.packet = packet,
|
|
|
|
.signature = signature,
|
|
|
|
};
|
|
|
|
dbus_type_reader_t *reader = &root_reader;
|
|
|
|
dbus_val_t value;
|
|
|
|
while (!reader_is_finished(reader)) {
|
|
|
|
reader = reader_next(reader, -1, -1, &value);
|
|
|
|
if (!reader) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static int
|
|
|
|
dissect_dbus_body(dbus_packet_t *packet) {
|
|
|
|
int err = 0;
|
|
|
|
if (packet->signature[0]) {
|
|
|
|
ptvcursor_add_with_subtree(packet->cursor, hf_dbus_body,
|
|
|
|
SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett_dbus_body);
|
|
|
|
err = dissect_dbus_signature(packet, packet->signature);
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
static int
|
|
|
|
dissect_dbus_header_fields(dbus_packet_t *packet) {
|
|
|
|
dbus_type_reader_t root_reader = {
|
|
|
|
.packet = packet,
|
|
|
|
.signature = "a{yv}",
|
|
|
|
};
|
|
|
|
dbus_type_reader_t *reader = &root_reader;
|
|
|
|
dbus_val_t value;
|
|
|
|
#define NEXT_OR_RETURN(hf, ett) if (!(reader = reader_next(reader, hf, ett, &value))) return 1;
|
|
|
|
|
|
|
|
// Header Field Array
|
|
|
|
NEXT_OR_RETURN(-1, ett_dbus_header_field_array);
|
|
|
|
proto_item *header_field_array_pi = reader->container;
|
|
|
|
proto_item_set_text(header_field_array_pi, "Header Field Array");
|
|
|
|
while (reader->level > 0) {
|
|
|
|
// Header Field (Dict)
|
|
|
|
NEXT_OR_RETURN(-1, ett_dbus_header_field);
|
|
|
|
// Field Code
|
|
|
|
NEXT_OR_RETURN(hf_dbus_field_code, -1);
|
|
|
|
guint32 field_code = value.uint;
|
|
|
|
const gchar *field_code_str = val_to_str_const(field_code, field_code_vals, "Unknown field code");
|
|
|
|
proto_item_append_text(reader->container, ", %s", field_code_str);
|
|
|
|
if (field_code == DBUS_HEADER_FIELD_INVALID) {
|
|
|
|
add_expert(packet, &ei_dbus_field_code_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Header Field Value (Variant)
|
|
|
|
NEXT_OR_RETURN(-1, -1);
|
|
|
|
const char *header_field_signature = value.string;
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
const char *expected_signature;
|
|
|
|
switch (field_code) {
|
|
|
|
case DBUS_HEADER_FIELD_PATH:
|
|
|
|
expected_signature = "o";
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_INTERFACE:
|
|
|
|
case DBUS_HEADER_FIELD_MEMBER:
|
|
|
|
case DBUS_HEADER_FIELD_ERROR_NAME:
|
|
|
|
case DBUS_HEADER_FIELD_DESTINATION:
|
|
|
|
case DBUS_HEADER_FIELD_SENDER:
|
|
|
|
expected_signature = "s";
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
case DBUS_HEADER_FIELD_REPLY_SERIAL:
|
2020-11-28 23:22:24 +00:00
|
|
|
expected_signature = "u";
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_UNIX_FDS:
|
|
|
|
expected_signature = "u";
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_SIGNATURE:
|
|
|
|
expected_signature = "g";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
expected_signature = NULL;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
if (expected_signature && strcmp(header_field_signature, expected_signature) != 0) {
|
|
|
|
add_expert(packet, &ei_dbus_field_signature_wrong);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Variant Value
|
|
|
|
switch (field_code) {
|
|
|
|
case DBUS_HEADER_FIELD_PATH:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_path, -1);
|
|
|
|
packet->path = value.string;
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_INTERFACE:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_interface, -1);
|
|
|
|
packet->interface = value.string;
|
|
|
|
if (!is_dbus_interface_valid(packet->interface)) {
|
|
|
|
add_expert(packet, &ei_dbus_interface_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_MEMBER:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_member, -1);
|
|
|
|
packet->member = value.string;
|
|
|
|
if (!is_dbus_member_name_valid(packet->member)) {
|
|
|
|
add_expert(packet, &ei_dbus_member_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_ERROR_NAME:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_error_name, -1);
|
|
|
|
packet->error_name = value.string;
|
|
|
|
if (!is_dbus_interface_valid(packet->error_name)) {
|
|
|
|
add_expert(packet, &ei_dbus_error_name_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_DESTINATION:
|
2020-11-28 23:22:24 +00:00
|
|
|
NEXT_OR_RETURN(hf_dbus_destination, -1);
|
|
|
|
packet->destination = value.string;
|
|
|
|
if (!is_dbus_bus_name_valid(packet->destination)) {
|
|
|
|
add_expert(packet, &ei_dbus_bus_name_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(packet->destination)+1,
|
|
|
|
wmem_strdup(packet->pinfo->pool, packet->destination));
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
case DBUS_HEADER_FIELD_SENDER:
|
2020-11-28 23:22:24 +00:00
|
|
|
NEXT_OR_RETURN(hf_dbus_sender, -1);
|
|
|
|
packet->sender = value.string;
|
|
|
|
if (!is_dbus_bus_name_valid(packet->sender)) {
|
|
|
|
add_expert(packet, &ei_dbus_bus_name_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(packet->sender)+1,
|
|
|
|
wmem_strdup(packet->pinfo->pool, packet->sender));
|
2012-06-29 15:23:21 +00:00
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_SIGNATURE:
|
2020-11-28 23:22:24 +00:00
|
|
|
NEXT_OR_RETURN(hf_dbus_signature, -1);
|
|
|
|
packet->signature = value.string;
|
|
|
|
break;
|
|
|
|
case DBUS_HEADER_FIELD_REPLY_SERIAL:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_reply_serial, -1);
|
|
|
|
packet->reply_serial = value.uint;
|
|
|
|
if (packet->reply_serial == 0) {
|
|
|
|
add_expert(packet, &ei_dbus_serial_invalid);
|
2021-01-27 22:32:55 +00:00
|
|
|
reader_cleanup(reader);
|
2020-11-28 23:22:24 +00:00
|
|
|
return 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
break;
|
2020-11-28 23:22:24 +00:00
|
|
|
case DBUS_HEADER_FIELD_UNIX_FDS:
|
|
|
|
NEXT_OR_RETURN(hf_dbus_unix_fds, -1);
|
|
|
|
packet->unix_fds = value.uint;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Unknown Field code must be skipped without error
|
|
|
|
do {
|
|
|
|
NEXT_OR_RETURN(-1, -1);
|
|
|
|
// Skip while inside Header Field Array -> Header Field Dict -> Variant
|
|
|
|
} while (reader->level >= 3);
|
|
|
|
}
|
|
|
|
// end of dict
|
|
|
|
NEXT_OR_RETURN(-1, -1);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
gboolean is_field_missing = FALSE;
|
|
|
|
switch (packet->message_type) {
|
|
|
|
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
|
|
|
is_field_missing = !packet->path || !packet->member;
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
|
|
|
is_field_missing = !packet->reply_serial;
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_ERROR:
|
|
|
|
is_field_missing = !packet->error_name || !packet->reply_serial;
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_SIGNAL:
|
|
|
|
is_field_missing = !packet->path || !packet->interface || !packet->member;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
if (is_field_missing) {
|
|
|
|
expert_add_info(packet->pinfo, header_field_array_pi, &ei_dbus_required_header_field_missing);
|
|
|
|
return 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
switch(packet->message_type) {
|
|
|
|
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
|
|
|
col_add_fstr(packet->pinfo->cinfo, COL_INFO, "%s() @ %s", packet->member, packet->path);
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_SIGNAL:
|
|
|
|
col_add_fstr(packet->pinfo->cinfo, COL_INFO, "* %s() @ %s", packet->member, packet->path);
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_ERROR:
|
|
|
|
col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s", packet->error_name);
|
|
|
|
break;
|
|
|
|
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
|
|
|
col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> '%s'", packet->signature);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
break;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Header length must be a multiple of 8 bytes
|
|
|
|
return add_padding(packet, SIG_CODE_STRUCT_OPEN);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
dissect_dbus_header(dbus_packet_t *packet) {
|
|
|
|
guint32 val;
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Endianness
|
|
|
|
packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf_dbus_endianness, 1, ENC_NA, &val);
|
|
|
|
switch (val) {
|
|
|
|
case 'l':
|
|
|
|
packet->enc = ENC_LITTLE_ENDIAN;
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
packet->enc = ENC_BIG_ENDIAN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
add_expert(packet, &ei_dbus_endianness_invalid);
|
|
|
|
return 1;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Message Type
|
|
|
|
packet->message_type = add_uint(packet, hf_dbus_message_type);
|
|
|
|
const gchar *info = try_val_to_str(packet->message_type, message_type_vals);
|
|
|
|
if (packet->message_type == DBUS_MESSAGE_TYPE_INVALID) {
|
|
|
|
col_set_str(packet->pinfo->cinfo, COL_INFO, info);
|
|
|
|
add_expert(packet, &ei_dbus_message_type_invalid);
|
|
|
|
return 1;
|
|
|
|
} else if (!info) {
|
|
|
|
col_set_str(packet->pinfo->cinfo, COL_INFO, "Unknown message type");
|
|
|
|
add_expert(packet, &ei_dbus_message_type_unknown);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
col_set_str(packet->pinfo->cinfo, COL_INFO, info);
|
|
|
|
|
|
|
|
// Flags
|
|
|
|
ptvcursor_add_with_subtree(packet->cursor, hf_dbus_flags, 1, packet->enc, ett_dbus_flags);
|
|
|
|
ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_reply_expected, 1, packet->enc);
|
|
|
|
ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_auto_start, 1, packet->enc);
|
|
|
|
ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_allow_interactive_authorization, 1, packet->enc);
|
|
|
|
ptvcursor_advance(packet->cursor, 1);
|
|
|
|
ptvcursor_pop_subtree(packet->cursor);
|
|
|
|
|
|
|
|
// Version
|
|
|
|
if (add_uint(packet, hf_dbus_version) != 1) {
|
|
|
|
add_expert(packet, &ei_dbus_version_invalid);
|
|
|
|
return 1;
|
|
|
|
}
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Body Length
|
|
|
|
packet->body_len = add_uint(packet, hf_dbus_body_length);
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
// Serial
|
|
|
|
packet->serial = add_uint(packet, hf_dbus_serial);
|
|
|
|
if (packet->serial == 0) {
|
|
|
|
add_expert(packet, &ei_dbus_serial_invalid);
|
|
|
|
return 1;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
2020-11-28 23:22:24 +00:00
|
|
|
|
|
|
|
return 0;
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
|
|
|
|
dbus_packet_t packet = { .pinfo = pinfo, .signature = "" };
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-Bus");
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "D-Bus");
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
proto_item *pi = proto_tree_add_protocol_format(tree, proto_dbus, tvb, 0, -1, "D-Bus");
|
|
|
|
proto_tree *dbus_tree = proto_item_add_subtree(pi, ett_dbus);
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
gint offset = 0;
|
|
|
|
packet.cursor = ptvcursor_new(dbus_tree, tvb, offset);
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
(void)(dissect_dbus_header(&packet) ||
|
|
|
|
dissect_dbus_header_fields(&packet) ||
|
|
|
|
dissect_dbus_body(&packet));
|
2012-06-29 15:23:21 +00:00
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
offset = ptvcursor_current_offset(packet.cursor);
|
|
|
|
proto_item_set_end(pi, tvb, offset);
|
|
|
|
ptvcursor_free(packet.cursor);
|
2012-06-29 15:23:21 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DBUS_HEADER_LEN 16
|
|
|
|
|
2012-07-13 22:06:40 +00:00
|
|
|
static guint
|
2015-01-25 19:30:13 +00:00
|
|
|
get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
|
2020-11-28 23:22:24 +00:00
|
|
|
int offset, void *data _U_) {
|
2012-06-29 15:23:21 +00:00
|
|
|
guint32 (*get_guint32)(tvbuff_t *, const gint);
|
|
|
|
|
|
|
|
guint32 len_body, len_hdr;
|
|
|
|
|
|
|
|
switch (tvb_get_guint8(tvb, offset)) {
|
|
|
|
case 'l':
|
|
|
|
get_guint32 = tvb_get_letohl;
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
default:
|
|
|
|
get_guint32 = tvb_get_ntohl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
len_hdr = DBUS_HEADER_LEN + get_guint32(tvb, offset + 12);
|
2021-06-16 09:01:23 +00:00
|
|
|
len_hdr = WS_ROUNDUP_8(len_hdr);
|
2012-06-29 15:23:21 +00:00
|
|
|
len_body = get_guint32(tvb, offset + 4);
|
|
|
|
|
|
|
|
return len_hdr + len_body;
|
|
|
|
}
|
|
|
|
|
2013-11-09 17:46:28 +00:00
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
2013-11-09 17:46:28 +00:00
|
|
|
return dissect_dbus(tvb, pinfo, tree, data);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2020-11-28 23:22:24 +00:00
|
|
|
dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
|
|
|
|
tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN,
|
|
|
|
get_dbus_message_len, dissect_dbus_pdu, data);
|
2015-04-16 13:58:53 +00:00
|
|
|
return tvb_reported_length(tvb);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-13 22:06:40 +00:00
|
|
|
void
|
2020-11-28 23:22:24 +00:00
|
|
|
proto_register_dbus(void) {
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_dbus_endianness, { "Endianness", "dbus.endianness",
|
|
|
|
FT_UINT8, BASE_NONE, VALS(endianness_vals), 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_message_type, { "Message Type", "dbus.message_type",
|
|
|
|
FT_UINT8, BASE_NONE, VALS(message_type_vals), 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_flags, { "Message Flags", "dbus.flags",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_flags_no_reply_expected, { "No Reply Expected", "dbus.flags.no_reply_expected",
|
|
|
|
FT_BOOLEAN, 8, TFS(¬_expected_vals), 0x01, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_flags_no_auto_start, { "No Auto Start", "dbus.flags.no_auto_start",
|
|
|
|
FT_BOOLEAN, 8, TFS(&no_start_vals), 0x02, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_flags_allow_interactive_authorization, { "Allow Interactive Authorization", "dbus.flags.allow_interactive_authorization",
|
|
|
|
FT_BOOLEAN, 8, TFS(&allow_vals), 0x04, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_version, { "Protocol Version", "dbus.version",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_body_length, { "Message Body Length", "dbus.body_length",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_serial, { "Message Serial", "dbus.serial",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_field_code, { "Field Code", "dbus.field_code",
|
|
|
|
FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_padding, { "Padding", "dbus.padding",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_path, { "Path", "dbus.path",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_interface, { "Interface", "dbus.interface",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_member, { "Member", "dbus.member",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_error_name, { "Error name", "dbus.error_name",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_reply_serial, { "Reply serial", "dbus.reply_serial",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_destination, { "Destination", "dbus.destination",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_sender, { "Sender", "dbus.sender",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_signature, { "Signature", "dbus.signature",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_unix_fds, { "Unix FDs", "dbus.unix_fds",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_body, { "Body", "dbus.body",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_byte, { "Byte", "dbus.type.byte",
|
|
|
|
FT_UINT8, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_boolean, { "Boolean", "dbus.type.boolean",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_int16, { "Int16", "dbus.type.int16",
|
|
|
|
FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_uint16, { "Uint16", "dbus.type.uint16",
|
|
|
|
FT_UINT16, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_int32, { "Int32", "dbus.type.int32",
|
|
|
|
FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_uint32, { "Uint32", "dbus.type.uint32",
|
|
|
|
FT_UINT32, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_int64, { "Int64", "dbus.type.int64",
|
|
|
|
FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_uint64, { "Uint64", "dbus.type.uint64",
|
|
|
|
FT_UINT64, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_double, { "Double", "dbus.type.double",
|
|
|
|
FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_string, { "String", "dbus.type.string",
|
|
|
|
FT_UINT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_object_path, { "Object Path", "dbus.type.object_path",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_signature, { "Signature", "dbus.type.signature",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_array, { "Array", "dbus.type.array",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_array_length, { "Array Length", "dbus.type.array.length",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_struct, { "Struct", "dbus.type.struct",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_variant, { "Variant", "dbus.type.variant",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_variant_signature, { "Variant Signature", "dbus.type.variant.signature",
|
|
|
|
FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_dict_entry, { "Dict Entry", "dbus.type.dict_entry",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_dict_entry_key, { "Key", "dbus.type.dict_entry.key",
|
|
|
|
FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
|
|
|
|
{ &hf_dbus_type_unix_fd, { "Unix FD", "dbus.type.unix_fd",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
2012-06-29 15:23:21 +00:00
|
|
|
};
|
|
|
|
|
2012-07-13 22:06:40 +00:00
|
|
|
static gint *ett[] = {
|
2012-06-29 15:23:21 +00:00
|
|
|
&ett_dbus,
|
2020-11-28 23:22:24 +00:00
|
|
|
&ett_dbus_flags,
|
|
|
|
&ett_dbus_header_field_array,
|
|
|
|
&ett_dbus_header_field,
|
2012-06-29 15:23:21 +00:00
|
|
|
&ett_dbus_body,
|
2020-11-28 23:22:24 +00:00
|
|
|
&ett_dbus_type_array,
|
|
|
|
&ett_dbus_type_struct,
|
|
|
|
&ett_dbus_type_variant,
|
|
|
|
&ett_dbus_type_dict_entry,
|
2012-06-29 15:23:21 +00:00
|
|
|
};
|
|
|
|
|
2013-06-09 03:28:05 +00:00
|
|
|
static ei_register_info ei[] = {
|
2020-11-28 23:22:24 +00:00
|
|
|
{ &ei_dbus_endianness_invalid, { "dbus.endianness.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid endianness flag", EXPFILL }},
|
|
|
|
{ &ei_dbus_message_type_invalid, { "dbus.message_type.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid message type", EXPFILL }},
|
|
|
|
{ &ei_dbus_message_type_unknown, { "dbus.message_type.unknown",
|
|
|
|
PI_PROTOCOL, PI_WARN, "Unknown message type", EXPFILL }},
|
|
|
|
{ &ei_dbus_version_invalid, { "dbus.version.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid version", EXPFILL }},
|
|
|
|
{ &ei_dbus_serial_invalid, { "dbus.serial.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid serial", EXPFILL }},
|
|
|
|
{ &ei_dbus_field_code_invalid, { "dbus.field_code.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid field code", EXPFILL }},
|
|
|
|
{ &ei_dbus_required_header_field_missing, { "dbus.required_header_field_missing",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Required header field is missing", EXPFILL }},
|
|
|
|
{ &ei_dbus_padding_invalid, { "dbus.padding.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Padding bytes must be zero", EXPFILL }},
|
|
|
|
{ &ei_dbus_field_signature_wrong, { "dbus.field_signature_wrong",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Wrong header field variant signature", EXPFILL }},
|
|
|
|
{ &ei_dbus_interface_invalid, { "dbus.interface.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid interface name", EXPFILL }},
|
|
|
|
{ &ei_dbus_member_invalid, { "dbus.member.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid member name", EXPFILL }},
|
|
|
|
{ &ei_dbus_error_name_invalid, { "dbus.error_name.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid error name", EXPFILL }},
|
|
|
|
{ &ei_dbus_bus_name_invalid, { "dbus.bus_name.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid bus name", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_boolean_invalid, { "dbus.type.boolean.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid boolean value", EXPFILL }},
|
|
|
|
{ &ei_dbus_string_invalid, { "dbus.type.string.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid string value", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_signature_invalid, { "dbus.type.signature.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid signature", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_array_too_long, { "dbus.type.array.too_long",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Array too long", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_array_content_out_of_bounds, { "dbus.type.array.content_out_of_bounds",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Array content is out of bounds", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_object_path_invalid, { "dbus.type.object_path.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid object path", EXPFILL }},
|
|
|
|
{ &ei_dbus_type_variant_signature_invalid, { "dbus.type.variant.signature.invalid",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Invalid variant signature", EXPFILL }},
|
|
|
|
{ &ei_dbus_nested_too_deeply, { "dbus.nested_too_deeply",
|
|
|
|
PI_PROTOCOL, PI_ERROR, "Containers nested too deeply", EXPFILL }},
|
2013-06-09 03:28:05 +00:00
|
|
|
};
|
|
|
|
|
2013-08-17 07:16:12 +00:00
|
|
|
expert_module_t *expert_dbus;
|
|
|
|
|
2020-11-28 23:22:24 +00:00
|
|
|
proto_dbus = proto_register_protocol("D-Bus", "D-Bus", "dbus");
|
|
|
|
proto_register_field_array(proto_dbus, hf, array_length(hf));
|
2012-06-29 15:23:21 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_dbus = expert_register_protocol(proto_dbus);
|
|
|
|
expert_register_field_array(expert_dbus, ei, array_length(ei));
|
2013-08-17 07:16:12 +00:00
|
|
|
|
2015-12-09 03:49:44 +00:00
|
|
|
dbus_handle = create_dissector_handle(dissect_dbus, proto_dbus);
|
|
|
|
dbus_handle_tcp = create_dissector_handle(dissect_dbus_tcp, proto_dbus);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-13 22:06:40 +00:00
|
|
|
void
|
2020-11-28 23:22:24 +00:00
|
|
|
proto_reg_handoff_dbus(void) {
|
2012-06-29 15:23:21 +00:00
|
|
|
dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS, dbus_handle);
|
2016-10-07 20:25:01 +00:00
|
|
|
dissector_add_for_decode_as_with_preference("tcp.port", dbus_handle_tcp);
|
2012-06-29 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 20:59:17 +00:00
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2014-09-30 20:59:17 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|