Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-dbus.c
bloba78e300fa5217bdde92df1bffbac5558485eb012
1 /* packet-dbus.c
2 * Routines for D-Bus dissection
3 * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
4 * Copyright 2020, Simon Holesch <simon@holesch.de>
6 * Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <wiretap/wtap.h>
19 #include <epan/expert.h>
20 #include <epan/ptvcursor.h>
21 #include <epan/tfs.h>
22 #include <wsutil/ws_roundup.h>
23 #include <epan/conversation.h>
24 #include "packet-tcp.h"
26 #define DBUS_MAX_ARRAY_LEN (64 * 1024 * 1024)
27 #define DBUS_MAX_NAME_LENGTH 255
28 #define DBUS_MAX_SIGNATURE_LENGTH 255
29 #define DBUS_MAX_TYPE_NESTING_LEVEL 32
30 #define DBUS_MAX_TOTAL_NESTING_LEVEL (2 * DBUS_MAX_TYPE_NESTING_LEVEL)
32 #define SIG_CODE_BYTE ('y')
33 #define SIG_CODE_BOOLEAN ('b')
34 #define SIG_CODE_INT16 ('n')
35 #define SIG_CODE_UINT16 ('q')
36 #define SIG_CODE_INT32 ('i')
37 #define SIG_CODE_UINT32 ('u')
38 #define SIG_CODE_INT64 ('x')
39 #define SIG_CODE_UINT64 ('t')
40 #define SIG_CODE_DOUBLE ('d')
41 #define SIG_CODE_STRING ('s')
42 #define SIG_CODE_OBJECT_PATH ('o')
43 #define SIG_CODE_SIGNATURE ('g')
44 #define SIG_CODE_ARRAY ('a')
45 #define SIG_CODE_STRUCT_OPEN ('(')
46 #define SIG_CODE_STRUCT_CLOSE (')')
47 #define SIG_CODE_VARIANT ('v')
48 #define SIG_CODE_DICT_ENTRY_OPEN ('{')
49 #define SIG_CODE_DICT_ENTRY_CLOSE ('}')
50 #define SIG_CODE_UNIX_FD ('h')
52 void proto_register_dbus(void);
53 void proto_reg_handoff_dbus(void);
55 static int proto_dbus;
56 static bool dbus_desegment = true;
57 static bool dbus_resolve_names = true;
59 static dissector_handle_t dbus_handle;
60 static dissector_handle_t dbus_handle_tcp;
62 #define DBUS_MESSAGE_TYPE_INVALID 0
63 #define DBUS_MESSAGE_TYPE_METHOD_CALL 1
64 #define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
65 #define DBUS_MESSAGE_TYPE_ERROR 3
66 #define DBUS_MESSAGE_TYPE_SIGNAL 4
68 static const value_string message_type_vals[] = {
69 { DBUS_MESSAGE_TYPE_INVALID, "Invalid" },
70 { DBUS_MESSAGE_TYPE_METHOD_CALL, "Method call" },
71 { DBUS_MESSAGE_TYPE_METHOD_RETURN, "Method reply" },
72 { DBUS_MESSAGE_TYPE_ERROR, "Error reply" },
73 { DBUS_MESSAGE_TYPE_SIGNAL, "Signal emission" },
74 { 0, NULL }
77 #define DBUS_HEADER_FIELD_INVALID 0
78 #define DBUS_HEADER_FIELD_PATH 1
79 #define DBUS_HEADER_FIELD_INTERFACE 2
80 #define DBUS_HEADER_FIELD_MEMBER 3
81 #define DBUS_HEADER_FIELD_ERROR_NAME 4
82 #define DBUS_HEADER_FIELD_REPLY_SERIAL 5
83 #define DBUS_HEADER_FIELD_DESTINATION 6
84 #define DBUS_HEADER_FIELD_SENDER 7
85 #define DBUS_HEADER_FIELD_SIGNATURE 8
86 #define DBUS_HEADER_FIELD_UNIX_FDS 9
88 static const value_string field_code_vals[] = {
89 { DBUS_HEADER_FIELD_INVALID, "Invalid" },
90 { DBUS_HEADER_FIELD_PATH, "Path" },
91 { DBUS_HEADER_FIELD_INTERFACE, "Interface" },
92 { DBUS_HEADER_FIELD_MEMBER, "Member" },
93 { DBUS_HEADER_FIELD_ERROR_NAME, "Error name" },
94 { DBUS_HEADER_FIELD_REPLY_SERIAL, "Reply serial" },
95 { DBUS_HEADER_FIELD_DESTINATION, "Destination" },
96 { DBUS_HEADER_FIELD_SENDER, "sender" },
97 { DBUS_HEADER_FIELD_SIGNATURE, "Signature" },
98 { DBUS_HEADER_FIELD_UNIX_FDS, "Unix FDs" },
99 { 0, NULL }
102 static const value_string endianness_vals[] = {
103 { 'l', "little-endian" },
104 { 'B', "big-endian" },
105 { 0, NULL }
108 #define DBUS_FLAGS_NO_REPLY_EXPECTED_MASK 0x01
109 #define DBUS_FLAGS_NO_AUTO_START_MASK 0x02
110 #define DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK 0x04
112 static const true_false_string allow_vals = { "Allow", "Don't allow" };
113 static const true_false_string no_start_vals = { "Don't start", "Start" };
114 static const true_false_string not_expected_vals = { "Not expected", "Expected" };
116 static int hf_dbus_endianness;
117 static int hf_dbus_message_type;
118 static int hf_dbus_flags;
119 static int hf_dbus_flags_no_reply_expected;
120 static int hf_dbus_flags_no_auto_start;
121 static int hf_dbus_flags_allow_interactive_authorization;
122 static int hf_dbus_version;
123 static int hf_dbus_body_length;
124 static int hf_dbus_serial;
125 static int hf_dbus_field_code;
126 static int hf_dbus_padding;
127 static int hf_dbus_path;
128 static int hf_dbus_interface;
129 static int hf_dbus_member;
130 static int hf_dbus_error_name;
131 static int hf_dbus_reply_serial;
132 static int hf_dbus_destination;
133 static int hf_dbus_sender;
134 static int hf_dbus_signature;
135 static int hf_dbus_unix_fds;
136 static int hf_dbus_body;
137 static int hf_dbus_type_byte;
138 static int hf_dbus_type_boolean;
139 static int hf_dbus_type_int16;
140 static int hf_dbus_type_uint16;
141 static int hf_dbus_type_int32;
142 static int hf_dbus_type_uint32;
143 static int hf_dbus_type_int64;
144 static int hf_dbus_type_uint64;
145 static int hf_dbus_type_double;
146 static int hf_dbus_type_string;
147 static int hf_dbus_type_object_path;
148 static int hf_dbus_type_signature;
149 static int hf_dbus_type_array;
150 static int hf_dbus_type_array_length;
151 static int hf_dbus_type_struct;
152 static int hf_dbus_type_variant;
153 static int hf_dbus_type_variant_signature;
154 static int hf_dbus_type_dict_entry;
155 static int hf_dbus_type_dict_entry_key;
156 static int hf_dbus_type_unix_fd;
157 static int hf_dbus_response_in;
158 static int hf_dbus_response_to;
159 static int hf_dbus_response_time;
161 static int ett_dbus;
162 static int ett_dbus_flags;
163 static int ett_dbus_header_field_array;
164 static int ett_dbus_header_field;
165 static int ett_dbus_body;
166 static int ett_dbus_type_array;
167 static int ett_dbus_type_struct;
168 static int ett_dbus_type_variant;
169 static int ett_dbus_type_dict_entry;
171 static expert_field ei_dbus_endianness_invalid;
172 static expert_field ei_dbus_message_type_invalid;
173 static expert_field ei_dbus_message_type_unknown;
174 static expert_field ei_dbus_version_invalid;
175 static expert_field ei_dbus_serial_invalid;
176 static expert_field ei_dbus_field_code_invalid;
177 static expert_field ei_dbus_required_header_field_missing;
178 static expert_field ei_dbus_padding_invalid;
179 static expert_field ei_dbus_field_signature_wrong;
180 static expert_field ei_dbus_interface_invalid;
181 static expert_field ei_dbus_member_invalid;
182 static expert_field ei_dbus_error_name_invalid;
183 static expert_field ei_dbus_bus_name_invalid;
184 static expert_field ei_dbus_type_boolean_invalid;
185 static expert_field ei_dbus_string_invalid;
186 static expert_field ei_dbus_type_signature_invalid;
187 static expert_field ei_dbus_type_array_too_long;
188 static expert_field ei_dbus_type_array_content_out_of_bounds;
189 static expert_field ei_dbus_type_object_path_invalid;
190 static expert_field ei_dbus_type_variant_signature_invalid;
191 static expert_field ei_dbus_nested_too_deeply;
193 typedef struct {
194 ptvcursor_t *cursor;
195 packet_info *pinfo;
196 unsigned enc;
197 uint32_t message_type;
198 uint8_t flags;
199 uint32_t body_len;
200 uint32_t serial;
202 proto_item *current_pi;
203 const char *path;
204 const char *interface;
205 const char *member;
206 const char *error_name;
207 uint32_t reply_serial;
208 const char *destination;
209 const char *sender;
210 const char *signature;
211 uint32_t unix_fds;
212 } dbus_packet_t;
214 typedef struct _dbus_type_reader_t {
215 dbus_packet_t *packet;
216 const char *signature;
217 uint32_t level;
218 uint32_t array_level;
219 uint32_t struct_level;
220 uint32_t dict_entry_level;
221 const char *array_type_start;
222 int array_end_offset;
223 bool is_in_variant;
224 bool is_basic_variant;
225 bool is_in_dict_entry;
226 bool is_basic_dict_entry;
227 proto_item *container;
228 struct _dbus_type_reader_t *parent;
229 } dbus_type_reader_t;
231 typedef union {
232 bool bool_;
233 uint32_t uint;
234 int32_t int_;
235 uint64_t uint64;
236 int64_t int64;
237 double double_;
238 const char *string;
239 } dbus_val_t;
241 typedef struct {
242 uint32_t req_frame;
243 uint32_t rep_frame;
244 nstime_t req_time;
245 const char *path;
246 const char *interface;
247 const char *member;
248 } dbus_transaction_t;
250 typedef struct {
251 wmem_map_t *packets;
252 } dbus_conv_info_t;
254 static wmem_map_t *request_info_map;
255 static wmem_map_t *unique_name_map;
257 static bool
258 is_ascii_digit(char c) {
259 return (unsigned)c - '0' < 10;
262 static bool
263 is_ascii_alpha(char c) {
264 return ((unsigned)c | 0x20) - 'a' <= 'z' - 'a';
267 static bool
268 is_dbus_object_path_valid(const char *path) {
269 // - The path may be of any length.
270 // - The path must begin with an ASCII '/' (integer 47) character, and must consist of elements separated by
271 // slash characters.
272 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
273 // - No element may be the empty string.
274 // - Multiple '/' characters cannot occur in sequence.
275 // - A trailing '/' character is not allowed unless the path is the root path (a single '/' character).
276 if (*path == '/' && *(path + 1) == '\0') {
277 return true;
280 while (*path == '/') {
281 path++;
283 if (*path == '/') {
284 return false;
287 while (is_ascii_alpha(*path) || is_ascii_digit(*path) || *path == '_') {
288 path++;
291 if (*path == '\0') {
292 return *(path - 1) != '/';
296 return false;
299 static bool
300 is_dbus_interface_valid(const char *interface) {
301 // - Interface names are composed of 2 or more elements separated by a period ('.') character. All elements
302 // must contain at least one character.
303 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_" and must not begin with a digit.
304 // - Interface names must not exceed the maximum name length.
305 int elements = 0;
306 const char *p = interface;
307 do {
308 if (!(is_ascii_alpha(*p) || *p == '_')) {
309 return false;
311 p++;
312 elements++;
314 while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_') {
315 p++;
318 if (*p == '\0') {
319 size_t length = p - interface;
320 return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
322 } while (*p++ == '.');
324 return false;
327 static bool
328 is_dbus_member_name_valid(const char *member_name) {
329 // - Must only contain the ASCII characters "[A-Z][a-z][0-9]_" and may not begin with a digit.
330 // - Must not contain the '.' (period) character.
331 // - Must not exceed the maximum name length.
332 // - Must be at least 1 byte in length.
333 const char *p = member_name;
335 if (!(is_ascii_alpha(*p) || *p == '_')) {
336 return false;
339 do {
340 p++;
341 } while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_');
343 if (*p == '\0') {
344 size_t length = p - member_name;
345 return length <= DBUS_MAX_NAME_LENGTH;
348 return false;
351 static bool
352 is_dbus_bus_name_valid(const char *bus_name) {
353 // - Bus names that start with a colon (':') character are unique connection names. Other bus names are called
354 // well-known bus names.
355 // - Bus names are composed of 1 or more elements separated by a period ('.') character. All elements must
356 // contain at least one character.
357 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-", with "-" discouraged in new bus
358 // names. Only elements that are part of a unique connection name may begin with a digit, elements in other
359 // bus names must not begin with a digit.
360 // - Bus names must contain at least one '.' (period) character (and thus at least two elements).
361 // - Bus names must not begin with a '.' (period) character.
362 // - Bus names must not exceed the maximum name length.
363 int elements = 0;
364 const char *p = bus_name;
365 bool is_unique_name = false;
367 if (*p == ':') {
368 is_unique_name = true;
369 p++;
372 do {
373 if (!(is_ascii_alpha(*p) || *p == '_' || *p == '-' || (is_unique_name && is_ascii_digit(*p)))) {
374 return false;
376 p++;
377 elements++;
379 while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_' || *p == '-') {
380 p++;
383 if (*p == '\0') {
384 size_t length = p - bus_name;
385 return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
387 } while (*p++ == '.');
389 return false;
392 static bool
393 is_basic_type(char sig_code) {
394 switch (sig_code) {
395 case SIG_CODE_BYTE:
396 case SIG_CODE_BOOLEAN:
397 case SIG_CODE_INT16:
398 case SIG_CODE_UINT16:
399 case SIG_CODE_INT32:
400 case SIG_CODE_UINT32:
401 case SIG_CODE_INT64:
402 case SIG_CODE_UINT64:
403 case SIG_CODE_DOUBLE:
404 case SIG_CODE_STRING:
405 case SIG_CODE_OBJECT_PATH:
406 case SIG_CODE_SIGNATURE:
407 case SIG_CODE_UNIX_FD:
408 return true;
409 default:
410 return false;
414 static const char *
415 skip_enclosed_container(const char *signature, char open_bracket, char closed_bracket) {
416 int nested = 0;
417 for (char sig_code = *signature++; sig_code != '\0'; sig_code = *signature++) {
418 if (sig_code == closed_bracket) {
419 if (nested == 0) {
420 return signature;
422 nested--;
423 } else if (sig_code == open_bracket) {
424 nested++;
427 return NULL;
430 static const char *
431 skip_single_complete_type(const char *signature) {
432 char sig_code;
433 while (1) {
434 sig_code = *signature++;
435 switch (sig_code) {
436 case SIG_CODE_BYTE:
437 case SIG_CODE_BOOLEAN:
438 case SIG_CODE_INT16:
439 case SIG_CODE_UINT16:
440 case SIG_CODE_INT32:
441 case SIG_CODE_UINT32:
442 case SIG_CODE_INT64:
443 case SIG_CODE_UINT64:
444 case SIG_CODE_DOUBLE:
445 case SIG_CODE_STRING:
446 case SIG_CODE_OBJECT_PATH:
447 case SIG_CODE_SIGNATURE:
448 case SIG_CODE_VARIANT:
449 case SIG_CODE_UNIX_FD:
450 return signature;
451 case SIG_CODE_ARRAY:
452 continue;
453 case SIG_CODE_STRUCT_OPEN:
454 return skip_enclosed_container(signature, SIG_CODE_STRUCT_OPEN, SIG_CODE_STRUCT_CLOSE);
455 case SIG_CODE_DICT_ENTRY_OPEN:
456 return skip_enclosed_container(signature, SIG_CODE_DICT_ENTRY_OPEN, SIG_CODE_DICT_ENTRY_CLOSE);
457 default:
458 return NULL;
463 static bool
464 is_dbus_signature_valid(const char *signature, dbus_packet_t *packet) {
465 char sig_code;
466 size_t length = 0;
467 char prev_sig_code = '\0';
468 wmem_stack_t *expected_chars = wmem_stack_new(packet->pinfo->pool);
470 while ((sig_code = *signature++) != '\0') {
471 if (++length >= DBUS_MAX_SIGNATURE_LENGTH) {
472 return false;
475 switch (sig_code) {
476 case SIG_CODE_BYTE:
477 case SIG_CODE_SIGNATURE:
478 case SIG_CODE_VARIANT:
479 case SIG_CODE_INT16:
480 case SIG_CODE_UINT16:
481 case SIG_CODE_INT32:
482 case SIG_CODE_UINT32:
483 case SIG_CODE_BOOLEAN:
484 case SIG_CODE_OBJECT_PATH:
485 case SIG_CODE_STRING:
486 case SIG_CODE_UNIX_FD:
487 case SIG_CODE_INT64:
488 case SIG_CODE_UINT64:
489 case SIG_CODE_DOUBLE:
490 break;
491 case SIG_CODE_ARRAY:
492 switch (*signature) {
493 case '\0':
494 case SIG_CODE_STRUCT_CLOSE:
495 case SIG_CODE_DICT_ENTRY_CLOSE:
496 // arrays must be followed by a single complete type
497 return false;
499 // invalid signature codes are detected in the next iteration
500 break;
501 case SIG_CODE_STRUCT_OPEN:
502 if (*signature == SIG_CODE_STRUCT_CLOSE) {
503 // empty structures are not allowed
504 return false;
506 wmem_stack_push(expected_chars, (void *)SIG_CODE_STRUCT_CLOSE);
507 break;
508 case SIG_CODE_DICT_ENTRY_OPEN: {
509 // dict entries must be an array element type
510 // the first single complete type (the "key") must be a basic type
511 if (prev_sig_code != SIG_CODE_ARRAY || !is_basic_type(*signature)) {
512 return false;
515 // dict entries must contain exactly two single complete types
516 // + 1 can be used here, since the key is a basic type
517 const char *sig_code_close = skip_single_complete_type(signature + 1);
518 if (!sig_code_close || *sig_code_close != SIG_CODE_DICT_ENTRY_CLOSE) {
519 return false;
521 wmem_stack_push(expected_chars, (void *)SIG_CODE_DICT_ENTRY_CLOSE);
522 break;
524 case SIG_CODE_STRUCT_CLOSE:
525 case SIG_CODE_DICT_ENTRY_CLOSE:
526 if (wmem_stack_count(expected_chars) == 0 ||
527 (char)(uintptr_t)wmem_stack_pop(expected_chars) != sig_code) {
528 return false;
530 break;
531 default:
532 return false;
535 prev_sig_code = sig_code;
537 return wmem_stack_count(expected_chars) == 0;
540 static void
541 add_expert(dbus_packet_t *packet, expert_field *ei) {
542 expert_add_info(packet->pinfo, packet->current_pi, ei);
545 static uint32_t
546 add_uint(dbus_packet_t *packet, int hf) {
547 header_field_info *info = proto_registrar_get_nth(hf);
548 int length;
549 uint32_t value;
550 switch (info->type) {
551 case FT_UINT8:
552 length = 1;
553 break;
554 case FT_UINT32:
555 length = 4;
556 break;
557 default:
558 DISSECTOR_ASSERT_NOT_REACHED();
560 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf, length, packet->enc, &value);
561 return value;
564 static const uint8_t *
565 add_dbus_string(dbus_packet_t *packet, int hf, int uint_length) {
566 const uint8_t *string;
567 int start_offset = ptvcursor_current_offset(packet->cursor);
568 proto_item *pi = ptvcursor_add_ret_string(packet->cursor, hf, uint_length,
569 packet->enc | ENC_UTF_8, packet->pinfo->pool, &string);
570 int item_length = ptvcursor_current_offset(packet->cursor) - start_offset;
571 uint8_t term_byte = tvb_get_uint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
572 proto_item_set_len(pi, item_length + 1);
573 ptvcursor_advance(packet->cursor, 1);
574 packet->current_pi = pi;
576 if ((strlen(string) != (size_t)(item_length - uint_length)) || (term_byte != '\0')) {
577 return NULL;
579 return string;
582 static int
583 calculate_padding_len(int offset, char sig) {
584 int alignment;
585 switch (sig) {
586 case SIG_CODE_BYTE:
587 case SIG_CODE_SIGNATURE:
588 case SIG_CODE_VARIANT:
589 default:
590 alignment = 1;
591 break;
592 case SIG_CODE_INT16:
593 case SIG_CODE_UINT16:
594 alignment = 2;
595 break;
596 case SIG_CODE_INT32:
597 case SIG_CODE_UINT32:
598 case SIG_CODE_BOOLEAN:
599 case SIG_CODE_OBJECT_PATH:
600 case SIG_CODE_ARRAY:
601 case SIG_CODE_STRING:
602 case SIG_CODE_UNIX_FD:
603 alignment = 4;
604 break;
605 case SIG_CODE_INT64:
606 case SIG_CODE_UINT64:
607 case SIG_CODE_DOUBLE:
608 case SIG_CODE_STRUCT_OPEN:
609 case SIG_CODE_DICT_ENTRY_OPEN:
610 alignment = 8;
611 break;
613 return (alignment - (offset % alignment)) % alignment;
616 static int
617 add_padding(dbus_packet_t *packet, char sig) {
618 uint8_t value;
619 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
620 int offset = ptvcursor_current_offset(packet->cursor);
621 int padding_len = calculate_padding_len(offset, sig);
623 if (padding_len != 0) {
624 packet->current_pi = ptvcursor_add(packet->cursor, hf_dbus_padding, padding_len, packet->enc);
625 for (int i = offset; i < (offset + padding_len); i++) {
626 value = tvb_get_uint8(tvb, i);
627 if (value != 0) {
628 add_expert(packet, &ei_dbus_padding_invalid);
629 return 1;
632 proto_item_set_hidden(packet->current_pi);
634 return 0;
637 static void
638 reader_cleanup(dbus_type_reader_t *reader) {
639 for (dbus_type_reader_t *r = reader; r->parent; r = r->parent) {
640 ptvcursor_pop_subtree(r->packet->cursor);
644 static dbus_type_reader_t *
645 reader_next(dbus_type_reader_t *reader, int hf, int ett, dbus_val_t *value) {
646 int err = 0;
647 char sig_code = *reader->signature++;
648 dbus_packet_t *packet = reader->packet;
649 bool is_single_complete_type = true;
650 add_padding(packet, sig_code);
652 switch (sig_code) {
653 case SIG_CODE_BYTE:
654 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
655 hf != -1 ? hf : hf_dbus_type_byte, 1, packet->enc, &value->uint);
656 break;
657 case SIG_CODE_BOOLEAN: {
658 int offset = ptvcursor_current_offset(packet->cursor);
659 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
660 uint8_t val = tvb_get_uint8(tvb, offset);
661 packet->current_pi = ptvcursor_add_ret_boolean(packet->cursor,
662 hf != -1 ? hf : hf_dbus_type_boolean, 4, packet->enc, &value->bool_);
663 if (val >= 2) {
664 add_expert(packet, &ei_dbus_type_boolean_invalid);
665 err = 1;
667 break;
669 case SIG_CODE_INT16:
670 packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
671 hf != -1 ? hf : hf_dbus_type_int16, 2, packet->enc, &value->int_);
672 break;
673 case SIG_CODE_UINT16:
674 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
675 hf != -1 ? hf : hf_dbus_type_uint16, 2, packet->enc, &value->uint);
676 break;
677 case SIG_CODE_INT32:
678 packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
679 hf != -1 ? hf : hf_dbus_type_int32, 4, packet->enc, &value->int_);
680 break;
681 case SIG_CODE_UINT32:
682 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
683 hf != -1 ? hf : hf_dbus_type_uint32, 4, packet->enc, &value->uint);
684 break;
685 case SIG_CODE_INT64: {
686 int offset = ptvcursor_current_offset(packet->cursor);
687 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
688 value->int64 = tvb_get_int64(tvb, offset, packet->enc);
689 packet->current_pi = ptvcursor_add(packet->cursor,
690 hf != -1 ? hf : hf_dbus_type_int64, 8, packet->enc);
691 break;
693 case SIG_CODE_UINT64: {
694 int offset = ptvcursor_current_offset(packet->cursor);
695 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
696 value->uint64 = tvb_get_uint64(tvb, offset, packet->enc);
697 packet->current_pi = ptvcursor_add(packet->cursor,
698 hf != -1 ? hf : hf_dbus_type_uint64, 8, packet->enc);
699 break;
701 case SIG_CODE_DOUBLE: {
702 int offset = ptvcursor_current_offset(packet->cursor);
703 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
704 value->double_ = tvb_get_ieee_double(tvb, offset, packet->enc);
705 packet->current_pi = ptvcursor_add(packet->cursor,
706 hf != -1 ? hf : hf_dbus_type_double, 8, packet->enc);
707 break;
709 case SIG_CODE_STRING: {
710 const char *val = add_dbus_string(packet,
711 hf != -1 ? hf : hf_dbus_type_string, 4);
712 if (!val || !g_utf8_validate(val, -1, NULL)) {
713 add_expert(packet, &ei_dbus_string_invalid);
714 err = 1;
716 value->string = val;
717 break;
719 case SIG_CODE_OBJECT_PATH: {
720 const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_object_path, 4);
721 if (!val || !is_dbus_object_path_valid(val)) {
722 add_expert(packet, &ei_dbus_type_object_path_invalid);
723 err = 1;
725 value->string = val;
726 break;
728 case SIG_CODE_SIGNATURE: {
729 const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_signature, 1);
730 if (!val || !is_dbus_signature_valid(val, packet)) {
731 add_expert(packet, &ei_dbus_type_signature_invalid);
732 err = 1;
734 value->string = val;
735 break;
737 case SIG_CODE_ARRAY: {
738 is_single_complete_type = false;
739 proto_item *array = ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_array,
740 SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_array);
741 if (*reader->signature == SIG_CODE_DICT_ENTRY_OPEN) {
742 proto_item_append_text(array, " (Dict)");
744 uint32_t array_len = add_uint(packet, hf_dbus_type_array_length);
745 value->uint = array_len;
746 add_padding(packet, *reader->signature);
747 if (array_len == 0) {
748 reader->signature = skip_single_complete_type(reader->signature);
749 // all signatures are validated
750 DISSECTOR_ASSERT(reader->signature);
751 ptvcursor_pop_subtree(packet->cursor);
752 is_single_complete_type = true;
753 } else if (array_len <= DBUS_MAX_ARRAY_LEN) {
754 int end_offset = ptvcursor_current_offset(packet->cursor) + array_len;
755 dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
756 *child = (dbus_type_reader_t){
757 .packet = reader->packet,
758 .signature = reader->signature,
759 .level = reader->level + 1,
760 .array_level = reader->array_level + 1,
761 .array_type_start = reader->signature,
762 .array_end_offset = end_offset,
763 .container = array,
764 .parent = reader,
766 reader = child;
767 } else {
768 add_expert(packet, &ei_dbus_type_array_too_long);
769 err = 1;
770 ptvcursor_pop_subtree(packet->cursor);
772 break;
774 case SIG_CODE_STRUCT_OPEN: {
775 is_single_complete_type = false;
776 ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_struct,
777 SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_struct);
778 dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
779 *child = (dbus_type_reader_t){
780 .packet = reader->packet,
781 .signature = reader->signature,
782 .level = reader->level + 1,
783 .struct_level = reader->struct_level + 1,
784 .parent = reader,
786 reader = child;
787 break;
789 case SIG_CODE_VARIANT: {
790 is_single_complete_type = false;
791 proto_item *variant = ptvcursor_add_with_subtree(packet->cursor,
792 hf != -1 ? hf : hf_dbus_type_variant,
793 SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_variant);
794 const char *variant_signature = add_dbus_string(packet, hf_dbus_type_variant_signature, 1);
795 value->string = variant_signature;
796 if (variant_signature && is_dbus_signature_valid(variant_signature, packet)) {
797 if (variant_signature[0] != '\0') {
798 dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
799 *child = (dbus_type_reader_t){
800 .packet = reader->packet,
801 .signature = variant_signature,
802 .level = reader->level + 1,
803 .is_in_variant = true,
804 .is_basic_variant = is_basic_type(*variant_signature)
805 && *(variant_signature + 1) == '\0',
806 .container = variant,
807 .parent = reader,
809 if (reader->is_in_dict_entry && child->is_basic_variant) {
810 reader->is_basic_dict_entry = true;
812 reader = child;
813 } else {
814 ptvcursor_pop_subtree(packet->cursor);
816 } else {
817 add_expert(packet, &ei_dbus_type_variant_signature_invalid);
818 err = 1;
819 ptvcursor_pop_subtree(packet->cursor);
821 break;
823 case SIG_CODE_DICT_ENTRY_OPEN: {
824 is_single_complete_type = false;
825 proto_item *dict_entry = ptvcursor_add_with_subtree(packet->cursor,
826 hf != -1 ? hf : hf_dbus_type_dict_entry,
827 SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_dict_entry);
828 dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
829 *child = (dbus_type_reader_t){
830 .packet = reader->packet,
831 .signature = reader->signature,
832 .level = reader->level + 1,
833 .dict_entry_level = reader->dict_entry_level + 1,
834 .is_in_dict_entry = true,
835 .is_basic_dict_entry = is_basic_type(*(reader->signature + 1)),
836 .container = dict_entry,
837 .parent = reader,
839 reader = child;
840 break;
842 case SIG_CODE_STRUCT_CLOSE:
843 case SIG_CODE_DICT_ENTRY_CLOSE:
844 ptvcursor_pop_subtree(packet->cursor);
845 reader->parent->signature = reader->signature;
846 reader = reader->parent;
847 break;
848 case SIG_CODE_UNIX_FD:
849 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
850 hf != -1 ? hf : hf_dbus_type_unix_fd, 4, packet->enc, &value->uint);
851 break;
852 default:
853 // all signatures are validated
854 DISSECTOR_ASSERT_NOT_REACHED();
857 if (reader->level > DBUS_MAX_TOTAL_NESTING_LEVEL ||
858 reader->array_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
859 reader->struct_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
860 reader->dict_entry_level > DBUS_MAX_TYPE_NESTING_LEVEL) {
861 add_expert(packet, &ei_dbus_nested_too_deeply);
862 err= 1;
863 } else if (is_single_complete_type) {
864 // Arrays and variants don't have a closing signature code, but they end after a single complete type.
865 // Close them here recursively, e.g. "aav"
866 while (1) {
867 if (reader->array_type_start) { // inside array
868 int offset = ptvcursor_current_offset(packet->cursor);
870 if (offset < reader->array_end_offset) {
871 // parse next array element -> reset signature
872 reader->signature = reader->array_type_start;
873 break;
874 } else if (offset == reader->array_end_offset) {
875 // all array elements parsed
876 ptvcursor_pop_subtree(packet->cursor);
877 reader->parent->signature = reader->signature;
878 reader = reader->parent;
879 } else {
880 // array elements don't fit into array
881 expert_add_info(packet->pinfo, reader->container,
882 &ei_dbus_type_array_content_out_of_bounds);
883 err = 1;
884 break;
886 } else if (reader->is_in_variant) {
887 if (reader->is_basic_variant) {
888 proto_item_append_text(reader->container, ": %s",
889 proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
891 ptvcursor_pop_subtree(packet->cursor);
892 reader = reader->parent;
893 } else {
894 break;
897 if (reader->is_in_dict_entry) {
898 // add "key: value" to dict entry item to make it readable without expanding the tree
899 if (*(reader->signature - 2) == SIG_CODE_DICT_ENTRY_OPEN) { // == key
900 // key is always a basic type
901 proto_item_append_text(reader->container, ", %s",
902 proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
903 } else if (reader->is_basic_dict_entry) { // == value
904 proto_item_append_text(reader->container, ": %s",
905 proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
910 if (err) {
911 reader_cleanup(reader);
912 return NULL;
914 return reader;
917 static bool
918 reader_is_finished(dbus_type_reader_t *reader) {
919 return *reader->signature == '\0' && reader->parent == NULL;
922 static int
923 dissect_dbus_signature(dbus_packet_t *packet, const char *signature) {
924 dbus_type_reader_t root_reader = {
925 .packet = packet,
926 .signature = signature,
928 dbus_type_reader_t *reader = &root_reader;
929 dbus_val_t value;
930 while (!reader_is_finished(reader)) {
931 reader = reader_next(reader, -1, -1, &value);
932 if (!reader) {
933 return 1;
936 return 0;
939 static int
940 dissect_dbus_body(dbus_packet_t *packet) {
941 int err = 0;
942 if (packet->signature[0]) {
943 ptvcursor_add_with_subtree(packet->cursor, hf_dbus_body,
944 SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett_dbus_body);
945 err = dissect_dbus_signature(packet, packet->signature);
946 ptvcursor_pop_subtree(packet->cursor);
948 return err;
951 static void
952 update_unique_name_map(const char *name1, const char *name2) {
953 const char *unique_name;
954 const char *well_known_name;
956 if (!dbus_resolve_names) {
957 return;
960 if (name1[0] == ':' && name2[0] != ':') {
961 unique_name = name1;
962 well_known_name = name2;
963 } else if (name2[0] == ':' && name1[0] != ':') {
964 unique_name = name2;
965 well_known_name = name1;
966 } else {
967 // both are well-known or both are unique names
968 return;
970 if (!wmem_map_contains(unique_name_map, unique_name)) {
971 wmem_map_insert(unique_name_map,
972 wmem_strdup(wmem_file_scope(), unique_name),
973 wmem_strdup(wmem_file_scope(), well_known_name));
977 static void
978 add_conversation(dbus_packet_t *packet, proto_tree *header_field_tree) {
979 bool is_request;
980 char *request_dest;
981 char *key;
983 if (!packet->sender || !packet->destination) {
984 // in a peer-to-peer setup, sender and destination can be unset, in which case conversation tracking
985 // doesn't make sense.
986 return;
989 switch (packet->message_type) {
990 case DBUS_MESSAGE_TYPE_METHOD_CALL:
991 if (packet->flags & DBUS_FLAGS_NO_REPLY_EXPECTED_MASK) {
992 // there won't be a response, no need to track
993 return;
995 is_request = true;
997 // There are cases where the destination address of the request doesn't match the sender address of the
998 // response, for example:
999 // - The request is sent to the well-known bus name (e.g. org.freedesktop.PolicyKit1), but the reply is
1000 // sent from the unique connection name (e.g. :1.10). Both names refer to the same connection and for
1001 // every unique connection name, there can be multiple well-known names.
1002 // - The D-Bus daemon (org.freedesktop.DBus) sends the reply, instead of the recipient, e.g.
1003 // org.freedesktop.DBus.Error.AccessDenied
1004 // To find the correct response, match the request sender + serial with the response destination +
1005 // reply serial.
1006 if (!PINFO_FD_VISITED(packet->pinfo)) {
1007 request_dest = wmem_strdup(wmem_file_scope(), packet->destination);
1008 key = wmem_strdup_printf(wmem_file_scope(), "%s %u", packet->sender, packet->serial);
1009 wmem_map_insert(request_info_map, key, request_dest);
1011 break;
1012 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1013 case DBUS_MESSAGE_TYPE_ERROR:
1014 is_request = false;
1016 key = wmem_strdup_printf(packet->pinfo->pool, "%s %u", packet->destination, packet->reply_serial);
1017 request_dest = (char *)wmem_map_lookup(request_info_map, key);
1018 if (request_dest && !g_str_equal(request_dest, packet->sender)) {
1019 // Replace the sender address of the response with the destination address of the request, so
1020 // the conversation can be found.
1021 address sender_addr;
1022 set_address(&sender_addr, AT_STRINGZ, (int)strlen(request_dest)+1, request_dest);
1023 conversation_set_conv_addr_port_endpoints(packet->pinfo, &sender_addr, &packet->pinfo->dst,
1024 conversation_pt_to_endpoint_type(packet->pinfo->ptype),
1025 packet->pinfo->srcport, packet->pinfo->destport);
1027 if (!PINFO_FD_VISITED(packet->pinfo) && packet->message_type == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
1028 update_unique_name_map(request_dest, packet->sender);
1031 break;
1032 case DBUS_MESSAGE_TYPE_SIGNAL:
1033 default:
1034 // signals don't have a response, no need to track
1035 return;
1038 conversation_t *conversation = find_or_create_conversation(packet->pinfo);
1039 dbus_conv_info_t *conv_info = (dbus_conv_info_t *)conversation_get_proto_data(conversation, proto_dbus);
1041 if (!conv_info) {
1042 conv_info = wmem_new(wmem_file_scope(), dbus_conv_info_t);
1043 conv_info->packets = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1044 conversation_add_proto_data(conversation, proto_dbus, conv_info);
1047 dbus_transaction_t *trans;
1048 if (!PINFO_FD_VISITED(packet->pinfo)) {
1049 if (is_request) {
1050 trans = wmem_new(wmem_file_scope(), dbus_transaction_t);
1051 *trans = (dbus_transaction_t){
1052 .req_frame = packet->pinfo->num,
1053 .req_time = packet->pinfo->fd->abs_ts,
1054 .path = wmem_strdup(wmem_file_scope(), packet->path),
1055 .interface = wmem_strdup(wmem_file_scope(), packet->interface),
1056 .member = wmem_strdup(wmem_file_scope(), packet->member),
1058 wmem_map_insert(conv_info->packets, GUINT_TO_POINTER(packet->serial), (void *)trans);
1059 } else {
1060 trans = (dbus_transaction_t *)wmem_map_lookup(conv_info->packets, GUINT_TO_POINTER(packet->reply_serial));
1061 if (trans) {
1062 trans->rep_frame = packet->pinfo->num;
1065 } else {
1066 uint32_t request_serial = is_request ? packet->serial : packet->reply_serial;
1067 trans = (dbus_transaction_t *)wmem_map_lookup(conv_info->packets, GUINT_TO_POINTER(request_serial));
1070 if (!trans) {
1071 return;
1074 if (is_request) {
1075 proto_item *it = proto_tree_add_uint(header_field_tree, hf_dbus_response_in, ptvcursor_tvbuff(packet->cursor), 0, 0, trans->rep_frame);
1076 proto_item_set_generated(it);
1077 } else {
1078 nstime_t ns;
1079 proto_item *it;
1080 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
1082 it = proto_tree_add_string(header_field_tree, hf_dbus_path, tvb, 0, 0, trans->path);
1083 proto_item_set_generated(it);
1084 packet->path = trans->path;
1086 it = proto_tree_add_string(header_field_tree, hf_dbus_interface, tvb, 0, 0, trans->interface);
1087 proto_item_set_generated(it);
1088 packet->interface = trans->interface;
1090 it = proto_tree_add_string(header_field_tree, hf_dbus_member, tvb, 0, 0, trans->member);
1091 proto_item_set_generated(it);
1092 packet->member = trans->member;
1094 it = proto_tree_add_uint(header_field_tree, hf_dbus_response_to, tvb, 0, 0, trans->req_frame);
1095 proto_item_set_generated(it);
1097 nstime_delta(&ns, &packet->pinfo->fd->abs_ts, &trans->req_time);
1098 it = proto_tree_add_time(header_field_tree, hf_dbus_response_time, tvb, 0, 0, &ns);
1099 proto_item_set_generated(it);
1103 static void
1104 resolve_unique_name(dbus_packet_t *packet, proto_tree *header_field_tree) {
1105 proto_item *it;
1106 tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
1108 if (packet->sender) {
1109 const char *sender_well_known = (const char *)wmem_map_lookup(unique_name_map, packet->sender);
1110 if (sender_well_known) {
1111 set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(sender_well_known)+1, sender_well_known);
1112 it = proto_tree_add_string(header_field_tree, hf_dbus_sender, tvb, 0, 0, sender_well_known);
1113 proto_item_set_generated(it);
1117 if (packet->destination) {
1118 const char *destination_well_known = (const char *)wmem_map_lookup(unique_name_map, packet->destination);
1119 if (destination_well_known) {
1120 set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(destination_well_known)+1, destination_well_known);
1121 it = proto_tree_add_string(header_field_tree, hf_dbus_destination, tvb, 0, 0, destination_well_known);
1122 proto_item_set_generated(it);
1127 static int
1128 dissect_dbus_header_fields(dbus_packet_t *packet) {
1129 dbus_type_reader_t root_reader = {
1130 .packet = packet,
1131 .signature = "a{yv}",
1133 dbus_type_reader_t *reader = &root_reader;
1134 dbus_val_t value;
1135 #define NEXT_OR_RETURN(hf, ett) if (!(reader = reader_next(reader, hf, ett, &value))) return 1;
1137 // Header Field Array
1138 NEXT_OR_RETURN(-1, ett_dbus_header_field_array);
1139 proto_item *header_field_array_pi = reader->container;
1140 proto_item_set_text(header_field_array_pi, "Header Field Array");
1141 while (reader->level > 0) {
1142 // Header Field (Dict)
1143 NEXT_OR_RETURN(-1, ett_dbus_header_field);
1144 // Field Code
1145 NEXT_OR_RETURN(hf_dbus_field_code, -1);
1146 uint32_t field_code = value.uint;
1147 const char *field_code_str = val_to_str_const(field_code, field_code_vals, "Unknown field code");
1148 proto_item_append_text(reader->container, ", %s", field_code_str);
1149 if (field_code == DBUS_HEADER_FIELD_INVALID) {
1150 add_expert(packet, &ei_dbus_field_code_invalid);
1151 reader_cleanup(reader);
1152 return 1;
1155 // Header Field Value (Variant)
1156 NEXT_OR_RETURN(-1, -1);
1157 const char *header_field_signature = value.string;
1159 const char *expected_signature;
1160 switch (field_code) {
1161 case DBUS_HEADER_FIELD_PATH:
1162 expected_signature = "o";
1163 break;
1164 case DBUS_HEADER_FIELD_INTERFACE:
1165 case DBUS_HEADER_FIELD_MEMBER:
1166 case DBUS_HEADER_FIELD_ERROR_NAME:
1167 case DBUS_HEADER_FIELD_DESTINATION:
1168 case DBUS_HEADER_FIELD_SENDER:
1169 expected_signature = "s";
1170 break;
1171 case DBUS_HEADER_FIELD_REPLY_SERIAL:
1172 expected_signature = "u";
1173 break;
1174 case DBUS_HEADER_FIELD_UNIX_FDS:
1175 expected_signature = "u";
1176 break;
1177 case DBUS_HEADER_FIELD_SIGNATURE:
1178 expected_signature = "g";
1179 break;
1180 default:
1181 expected_signature = NULL;
1184 if (expected_signature && strcmp(header_field_signature, expected_signature) != 0) {
1185 add_expert(packet, &ei_dbus_field_signature_wrong);
1186 reader_cleanup(reader);
1187 return 1;
1190 // Variant Value
1191 switch (field_code) {
1192 case DBUS_HEADER_FIELD_PATH:
1193 NEXT_OR_RETURN(hf_dbus_path, -1);
1194 packet->path = value.string;
1195 break;
1196 case DBUS_HEADER_FIELD_INTERFACE:
1197 NEXT_OR_RETURN(hf_dbus_interface, -1);
1198 packet->interface = value.string;
1199 if (!is_dbus_interface_valid(packet->interface)) {
1200 add_expert(packet, &ei_dbus_interface_invalid);
1201 reader_cleanup(reader);
1202 return 1;
1204 break;
1205 case DBUS_HEADER_FIELD_MEMBER:
1206 NEXT_OR_RETURN(hf_dbus_member, -1);
1207 packet->member = value.string;
1208 if (!is_dbus_member_name_valid(packet->member)) {
1209 add_expert(packet, &ei_dbus_member_invalid);
1210 reader_cleanup(reader);
1211 return 1;
1213 break;
1214 case DBUS_HEADER_FIELD_ERROR_NAME:
1215 NEXT_OR_RETURN(hf_dbus_error_name, -1);
1216 packet->error_name = value.string;
1217 if (!is_dbus_interface_valid(packet->error_name)) {
1218 add_expert(packet, &ei_dbus_error_name_invalid);
1219 reader_cleanup(reader);
1220 return 1;
1222 break;
1223 case DBUS_HEADER_FIELD_DESTINATION:
1224 NEXT_OR_RETURN(hf_dbus_destination, -1);
1225 packet->destination = value.string;
1226 if (!is_dbus_bus_name_valid(packet->destination)) {
1227 add_expert(packet, &ei_dbus_bus_name_invalid);
1228 reader_cleanup(reader);
1229 return 1;
1231 set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(packet->destination)+1,
1232 wmem_strdup(packet->pinfo->pool, packet->destination));
1233 break;
1234 case DBUS_HEADER_FIELD_SENDER:
1235 NEXT_OR_RETURN(hf_dbus_sender, -1);
1236 packet->sender = value.string;
1237 if (!is_dbus_bus_name_valid(packet->sender)) {
1238 add_expert(packet, &ei_dbus_bus_name_invalid);
1239 reader_cleanup(reader);
1240 return 1;
1242 set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(packet->sender)+1,
1243 wmem_strdup(packet->pinfo->pool, packet->sender));
1244 break;
1245 case DBUS_HEADER_FIELD_SIGNATURE:
1246 NEXT_OR_RETURN(hf_dbus_signature, -1);
1247 packet->signature = value.string;
1248 break;
1249 case DBUS_HEADER_FIELD_REPLY_SERIAL:
1250 NEXT_OR_RETURN(hf_dbus_reply_serial, -1);
1251 packet->reply_serial = value.uint;
1252 if (packet->reply_serial == 0) {
1253 add_expert(packet, &ei_dbus_serial_invalid);
1254 reader_cleanup(reader);
1255 return 1;
1257 break;
1258 case DBUS_HEADER_FIELD_UNIX_FDS:
1259 NEXT_OR_RETURN(hf_dbus_unix_fds, -1);
1260 packet->unix_fds = value.uint;
1261 break;
1262 default:
1263 // Unknown Field code must be skipped without error
1264 do {
1265 NEXT_OR_RETURN(-1, -1);
1266 // Skip while inside Header Field Array -> Header Field Dict -> Variant
1267 } while (reader->level >= 3);
1269 // end of dict
1270 NEXT_OR_RETURN(-1, -1);
1273 bool is_field_missing = false;
1274 switch (packet->message_type) {
1275 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1276 is_field_missing = !packet->path || !packet->member;
1277 break;
1278 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1279 is_field_missing = !packet->reply_serial;
1280 break;
1281 case DBUS_MESSAGE_TYPE_ERROR:
1282 is_field_missing = !packet->error_name || !packet->reply_serial;
1283 break;
1284 case DBUS_MESSAGE_TYPE_SIGNAL:
1285 is_field_missing = !packet->path || !packet->interface || !packet->member;
1286 break;
1287 default:
1288 DISSECTOR_ASSERT_NOT_REACHED();
1289 break;
1291 if (is_field_missing) {
1292 expert_add_info(packet->pinfo, header_field_array_pi, &ei_dbus_required_header_field_missing);
1293 return 1;
1296 add_conversation(packet, proto_item_get_subtree(header_field_array_pi));
1297 if (dbus_resolve_names) {
1298 resolve_unique_name(packet, proto_item_get_subtree(header_field_array_pi));
1301 switch(packet->message_type) {
1302 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1303 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "%s(%s) @ %s", packet->member, packet->signature, packet->path);
1304 break;
1305 case DBUS_MESSAGE_TYPE_SIGNAL:
1306 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "* %s(%s) @ %s", packet->member, packet->signature, packet->path);
1307 break;
1308 case DBUS_MESSAGE_TYPE_ERROR:
1309 if (packet->member) {
1310 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "! %s: %s", packet->member, packet->error_name);
1311 } else {
1312 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "! %s", packet->error_name);
1314 break;
1315 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1316 if (packet->member) {
1317 if (*packet->signature != '\0') {
1318 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s: '%s'", packet->member, packet->signature);
1319 } else {
1320 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s: OK", packet->member);
1323 } else {
1324 col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> '%s'", packet->signature);
1326 break;
1327 default:
1328 DISSECTOR_ASSERT_NOT_REACHED();
1329 break;
1332 // Header length must be a multiple of 8 bytes
1333 return add_padding(packet, SIG_CODE_STRUCT_OPEN);
1336 static int
1337 dissect_dbus_header(dbus_packet_t *packet) {
1338 uint32_t val;
1340 // Endianness
1341 packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf_dbus_endianness, 1, ENC_NA, &val);
1342 switch (val) {
1343 case 'l':
1344 packet->enc = ENC_LITTLE_ENDIAN;
1345 break;
1346 case 'B':
1347 packet->enc = ENC_BIG_ENDIAN;
1348 break;
1349 default:
1350 add_expert(packet, &ei_dbus_endianness_invalid);
1351 return 1;
1354 // Message Type
1355 packet->message_type = add_uint(packet, hf_dbus_message_type);
1356 const char *info = try_val_to_str(packet->message_type, message_type_vals);
1357 if (packet->message_type == DBUS_MESSAGE_TYPE_INVALID) {
1358 col_set_str(packet->pinfo->cinfo, COL_INFO, info);
1359 add_expert(packet, &ei_dbus_message_type_invalid);
1360 return 1;
1361 } else if (!info) {
1362 col_set_str(packet->pinfo->cinfo, COL_INFO, "Unknown message type");
1363 add_expert(packet, &ei_dbus_message_type_unknown);
1364 return 1;
1366 col_set_str(packet->pinfo->cinfo, COL_INFO, info);
1368 // Flags
1369 ptvcursor_add_with_subtree(packet->cursor, hf_dbus_flags, 1, packet->enc, ett_dbus_flags);
1370 ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_reply_expected, 1, packet->enc);
1371 ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_auto_start, 1, packet->enc);
1372 ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_allow_interactive_authorization, 1, packet->enc);
1373 packet->flags = tvb_get_uint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
1374 ptvcursor_advance(packet->cursor, 1);
1375 ptvcursor_pop_subtree(packet->cursor);
1377 // Version
1378 if (add_uint(packet, hf_dbus_version) != 1) {
1379 add_expert(packet, &ei_dbus_version_invalid);
1380 return 1;
1383 // Body Length
1384 packet->body_len = add_uint(packet, hf_dbus_body_length);
1386 // Serial
1387 packet->serial = add_uint(packet, hf_dbus_serial);
1388 if (packet->serial == 0) {
1389 add_expert(packet, &ei_dbus_serial_invalid);
1390 return 1;
1393 return 0;
1396 static int
1397 dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1398 dbus_packet_t packet = { .pinfo = pinfo, .signature = "" };
1400 col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-Bus");
1401 col_set_str(pinfo->cinfo, COL_INFO, "D-Bus");
1403 proto_item *pi = proto_tree_add_protocol_format(tree, proto_dbus, tvb, 0, -1, "D-Bus");
1404 proto_tree *dbus_tree = proto_item_add_subtree(pi, ett_dbus);
1406 int offset = 0;
1407 packet.cursor = ptvcursor_new(pinfo->pool, dbus_tree, tvb, offset);
1409 (void)(dissect_dbus_header(&packet) ||
1410 dissect_dbus_header_fields(&packet) ||
1411 dissect_dbus_body(&packet));
1413 offset = ptvcursor_current_offset(packet.cursor);
1414 proto_item_set_end(pi, tvb, offset);
1415 ptvcursor_free(packet.cursor);
1416 return offset;
1419 #define DBUS_HEADER_LEN 16
1421 static unsigned
1422 get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1423 int offset, void *data _U_) {
1424 uint32_t (*get_uint32)(tvbuff_t *, const int);
1426 uint32_t len_body, len_hdr;
1428 switch (tvb_get_uint8(tvb, offset)) {
1429 case 'l':
1430 get_uint32 = tvb_get_letohl;
1431 break;
1432 case 'B':
1433 default:
1434 get_uint32 = tvb_get_ntohl;
1435 break;
1438 len_hdr = DBUS_HEADER_LEN + get_uint32(tvb, offset + 12);
1439 len_hdr = WS_ROUNDUP_8(len_hdr);
1440 len_body = get_uint32(tvb, offset + 4);
1442 return len_hdr + len_body;
1445 static int
1446 dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1447 return dissect_dbus(tvb, pinfo, tree, data);
1450 static int
1451 dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1452 tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN,
1453 get_dbus_message_len, dissect_dbus_pdu, data);
1454 return tvb_reported_length(tvb);
1457 void
1458 proto_register_dbus(void) {
1459 static hf_register_info hf[] = {
1460 { &hf_dbus_endianness, { "Endianness", "dbus.endianness",
1461 FT_UINT8, BASE_NONE, VALS(endianness_vals), 0x00, NULL, HFILL }},
1462 { &hf_dbus_message_type, { "Message Type", "dbus.message_type",
1463 FT_UINT8, BASE_NONE, VALS(message_type_vals), 0x00, NULL, HFILL }},
1464 { &hf_dbus_flags, { "Message Flags", "dbus.flags",
1465 FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
1466 { &hf_dbus_flags_no_reply_expected, { "No Reply Expected", "dbus.flags.no_reply_expected",
1467 FT_BOOLEAN, 8, TFS(&not_expected_vals),
1468 DBUS_FLAGS_NO_REPLY_EXPECTED_MASK, NULL, HFILL }},
1469 { &hf_dbus_flags_no_auto_start, { "No Auto Start", "dbus.flags.no_auto_start",
1470 FT_BOOLEAN, 8, TFS(&no_start_vals),
1471 DBUS_FLAGS_NO_AUTO_START_MASK, NULL, HFILL }},
1472 { &hf_dbus_flags_allow_interactive_authorization, { "Allow Interactive Authorization", "dbus.flags.allow_interactive_authorization",
1473 FT_BOOLEAN, 8, TFS(&allow_vals),
1474 DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK, NULL, HFILL }},
1475 { &hf_dbus_version, { "Protocol Version", "dbus.version",
1476 FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1477 { &hf_dbus_body_length, { "Message Body Length", "dbus.body_length",
1478 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1479 { &hf_dbus_serial, { "Message Serial", "dbus.serial",
1480 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1481 { &hf_dbus_field_code, { "Field Code", "dbus.field_code",
1482 FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL }},
1483 { &hf_dbus_padding, { "Padding", "dbus.padding",
1484 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1485 { &hf_dbus_path, { "Path", "dbus.path",
1486 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1487 { &hf_dbus_interface, { "Interface", "dbus.interface",
1488 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1489 { &hf_dbus_member, { "Member", "dbus.member",
1490 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1491 { &hf_dbus_error_name, { "Error name", "dbus.error_name",
1492 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1493 { &hf_dbus_reply_serial, { "Reply serial", "dbus.reply_serial",
1494 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1495 { &hf_dbus_destination, { "Destination", "dbus.destination",
1496 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1497 { &hf_dbus_sender, { "Sender", "dbus.sender",
1498 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1499 { &hf_dbus_signature, { "Signature", "dbus.signature",
1500 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1501 { &hf_dbus_unix_fds, { "Unix FDs", "dbus.unix_fds",
1502 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1503 { &hf_dbus_body, { "Body", "dbus.body",
1504 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1505 { &hf_dbus_type_byte, { "Byte", "dbus.type.byte",
1506 FT_UINT8, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1507 { &hf_dbus_type_boolean, { "Boolean", "dbus.type.boolean",
1508 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1509 { &hf_dbus_type_int16, { "Int16", "dbus.type.int16",
1510 FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1511 { &hf_dbus_type_uint16, { "Uint16", "dbus.type.uint16",
1512 FT_UINT16, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1513 { &hf_dbus_type_int32, { "Int32", "dbus.type.int32",
1514 FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1515 { &hf_dbus_type_uint32, { "Uint32", "dbus.type.uint32",
1516 FT_UINT32, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1517 { &hf_dbus_type_int64, { "Int64", "dbus.type.int64",
1518 FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1519 { &hf_dbus_type_uint64, { "Uint64", "dbus.type.uint64",
1520 FT_UINT64, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1521 { &hf_dbus_type_double, { "Double", "dbus.type.double",
1522 FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1523 { &hf_dbus_type_string, { "String", "dbus.type.string",
1524 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1525 { &hf_dbus_type_object_path, { "Object Path", "dbus.type.object_path",
1526 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1527 { &hf_dbus_type_signature, { "Signature", "dbus.type.signature",
1528 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1529 { &hf_dbus_type_array, { "Array", "dbus.type.array",
1530 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1531 { &hf_dbus_type_array_length, { "Array Length", "dbus.type.array.length",
1532 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1533 { &hf_dbus_type_struct, { "Struct", "dbus.type.struct",
1534 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1535 { &hf_dbus_type_variant, { "Variant", "dbus.type.variant",
1536 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1537 { &hf_dbus_type_variant_signature, { "Variant Signature", "dbus.type.variant.signature",
1538 FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1539 { &hf_dbus_type_dict_entry, { "Dict Entry", "dbus.type.dict_entry",
1540 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1541 { &hf_dbus_type_dict_entry_key, { "Key", "dbus.type.dict_entry.key",
1542 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1543 { &hf_dbus_type_unix_fd, { "Unix FD", "dbus.type.unix_fd",
1544 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1545 { &hf_dbus_response_in, { "Response In", "dbus.response_in",
1546 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
1547 "The response to this D-Bus call is in this frame", HFILL }},
1548 { &hf_dbus_response_to, { "Response To", "dbus.response_to",
1549 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
1550 "This is a response to the D-Bus call in this frame", HFILL }},
1551 { &hf_dbus_response_time, { "Response Time", "dbus.response_time",
1552 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1553 "The time between the Call and the Reply", HFILL }},
1556 static int *ett[] = {
1557 &ett_dbus,
1558 &ett_dbus_flags,
1559 &ett_dbus_header_field_array,
1560 &ett_dbus_header_field,
1561 &ett_dbus_body,
1562 &ett_dbus_type_array,
1563 &ett_dbus_type_struct,
1564 &ett_dbus_type_variant,
1565 &ett_dbus_type_dict_entry,
1568 static ei_register_info ei[] = {
1569 { &ei_dbus_endianness_invalid, { "dbus.endianness.invalid",
1570 PI_PROTOCOL, PI_ERROR, "Invalid endianness flag", EXPFILL }},
1571 { &ei_dbus_message_type_invalid, { "dbus.message_type.invalid",
1572 PI_PROTOCOL, PI_ERROR, "Invalid message type", EXPFILL }},
1573 { &ei_dbus_message_type_unknown, { "dbus.message_type.unknown",
1574 PI_PROTOCOL, PI_WARN, "Unknown message type", EXPFILL }},
1575 { &ei_dbus_version_invalid, { "dbus.version.invalid",
1576 PI_PROTOCOL, PI_ERROR, "Invalid version", EXPFILL }},
1577 { &ei_dbus_serial_invalid, { "dbus.serial.invalid",
1578 PI_PROTOCOL, PI_ERROR, "Invalid serial", EXPFILL }},
1579 { &ei_dbus_field_code_invalid, { "dbus.field_code.invalid",
1580 PI_PROTOCOL, PI_ERROR, "Invalid field code", EXPFILL }},
1581 { &ei_dbus_required_header_field_missing, { "dbus.required_header_field_missing",
1582 PI_PROTOCOL, PI_ERROR, "Required header field is missing", EXPFILL }},
1583 { &ei_dbus_padding_invalid, { "dbus.padding.invalid",
1584 PI_PROTOCOL, PI_ERROR, "Padding bytes must be zero", EXPFILL }},
1585 { &ei_dbus_field_signature_wrong, { "dbus.field_signature_wrong",
1586 PI_PROTOCOL, PI_ERROR, "Wrong header field variant signature", EXPFILL }},
1587 { &ei_dbus_interface_invalid, { "dbus.interface.invalid",
1588 PI_PROTOCOL, PI_ERROR, "Invalid interface name", EXPFILL }},
1589 { &ei_dbus_member_invalid, { "dbus.member.invalid",
1590 PI_PROTOCOL, PI_ERROR, "Invalid member name", EXPFILL }},
1591 { &ei_dbus_error_name_invalid, { "dbus.error_name.invalid",
1592 PI_PROTOCOL, PI_ERROR, "Invalid error name", EXPFILL }},
1593 { &ei_dbus_bus_name_invalid, { "dbus.bus_name.invalid",
1594 PI_PROTOCOL, PI_ERROR, "Invalid bus name", EXPFILL }},
1595 { &ei_dbus_type_boolean_invalid, { "dbus.type.boolean.invalid",
1596 PI_PROTOCOL, PI_ERROR, "Invalid boolean value", EXPFILL }},
1597 { &ei_dbus_string_invalid, { "dbus.type.string.invalid",
1598 PI_PROTOCOL, PI_ERROR, "Invalid string value", EXPFILL }},
1599 { &ei_dbus_type_signature_invalid, { "dbus.type.signature.invalid",
1600 PI_PROTOCOL, PI_ERROR, "Invalid signature", EXPFILL }},
1601 { &ei_dbus_type_array_too_long, { "dbus.type.array.too_long",
1602 PI_PROTOCOL, PI_ERROR, "Array too long", EXPFILL }},
1603 { &ei_dbus_type_array_content_out_of_bounds, { "dbus.type.array.content_out_of_bounds",
1604 PI_PROTOCOL, PI_ERROR, "Array content is out of bounds", EXPFILL }},
1605 { &ei_dbus_type_object_path_invalid, { "dbus.type.object_path.invalid",
1606 PI_PROTOCOL, PI_ERROR, "Invalid object path", EXPFILL }},
1607 { &ei_dbus_type_variant_signature_invalid, { "dbus.type.variant.signature.invalid",
1608 PI_PROTOCOL, PI_ERROR, "Invalid variant signature", EXPFILL }},
1609 { &ei_dbus_nested_too_deeply, { "dbus.nested_too_deeply",
1610 PI_PROTOCOL, PI_ERROR, "Containers nested too deeply", EXPFILL }},
1613 expert_module_t *expert_dbus;
1614 module_t *dbus_module;
1616 proto_dbus = proto_register_protocol("D-Bus", "D-Bus", "dbus");
1617 proto_register_field_array(proto_dbus, hf, array_length(hf));
1618 proto_register_subtree_array(ett, array_length(ett));
1619 expert_dbus = expert_register_protocol(proto_dbus);
1620 expert_register_field_array(expert_dbus, ei, array_length(ei));
1622 dbus_handle = register_dissector("dbus", dissect_dbus, proto_dbus);
1623 dbus_handle_tcp = register_dissector("dbus.tcp", dissect_dbus_tcp, proto_dbus);
1625 dbus_module = prefs_register_protocol(proto_dbus, NULL);
1626 prefs_register_bool_preference(dbus_module, "resolve_names",
1627 "Resolve unique names into well-known names",
1628 "Show the first inferred well-known bus name (e.g. \"com.example.MusicPlayer1\") instead of the unique connection name (e.g. \":1.18\"). Might be confusing if a connection owns more than one well-known name.", &dbus_resolve_names);
1630 request_info_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
1631 unique_name_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
1634 void
1635 proto_reg_handoff_dbus(void) {
1636 dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS, dbus_handle);
1637 dissector_add_for_decode_as_with_preference("tcp.port", dbus_handle_tcp);
1641 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1643 * Local variables:
1644 * c-basic-offset: 8
1645 * tab-width: 8
1646 * indent-tabs-mode: t
1647 * End:
1649 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1650 * :indentSize=8:tabSize=8:noTabs=false: