/src/wireshark/epan/dissectors/packet-cbor.c
Line | Count | Source |
1 | | /* packet-cbor.c |
2 | | * Routines for Concise Binary Object Representation (CBOR) (STD 94) dissection |
3 | | * References: |
4 | | * RFC 8949: https://tools.ietf.org/html/rfc8949 |
5 | | * RFC 8742: https://tools.ietf.org/html/rfc8742 |
6 | | * RFC 8610: https://tools.ietf.org/html/rfc8610 |
7 | | * |
8 | | * Copyright 2015, Hauke Mehrtens <hauke@hauke-m.de> |
9 | | * Copyright 2022, Stig Bjorlykke <stig@bjorlykke.org> |
10 | | * |
11 | | * Wireshark - Network traffic analyzer |
12 | | * By Gerald Combs <gerald@wireshark.org> |
13 | | * Copyright 1998 Gerald Combs |
14 | | * |
15 | | * SPDX-License-Identifier: GPL-2.0-or-later |
16 | | */ |
17 | | |
18 | | #include "config.h" |
19 | | |
20 | | #include <math.h> |
21 | | |
22 | | #include "packet-cbor.h" |
23 | | #include <epan/packet.h> |
24 | | #include <epan/exceptions.h> |
25 | | #include <epan/expert.h> |
26 | | #include <epan/proto_data.h> |
27 | | #include <epan/wscbor.h> |
28 | | #include <wsutil/str_util.h> |
29 | | #include <wsutil/to_str.h> |
30 | | |
31 | | void proto_register_cbor(void); |
32 | | void proto_reg_handoff_cbor(void); |
33 | | |
34 | | enum { |
35 | | /// No diagnostic text |
36 | | CBOR_DIAG_NONE, |
37 | | /// One diagnostic at the top of the tree |
38 | | CBOR_DIAG_TOP, |
39 | | /// One diagnostic for each CBOR item, including the top |
40 | | CBOR_DIAG_ALL, |
41 | | }; |
42 | | static const enum_val_t cbor_display_diagnostic_choices[] = { |
43 | | {"none", "Disabled", CBOR_DIAG_NONE}, |
44 | | {"top", "Only for the top item", CBOR_DIAG_TOP}, |
45 | | {"all", "For all items recursively", CBOR_DIAG_ALL}, |
46 | | {NULL, NULL, 0}, |
47 | | }; |
48 | | |
49 | | // Protocol preferences and defaults |
50 | | static bool cbor_dissect_embeded_bstr = false; |
51 | | static int cbor_display_diagnostic = CBOR_DIAG_NONE; |
52 | | static bool cbor_diagnostic_bstr_text = true; |
53 | | |
54 | | static int proto_cbor; |
55 | | |
56 | | static int hf_cbor_item_major_type; |
57 | | static int hf_cbor_item_integer_size; |
58 | | static int hf_cbor_item_length_size; |
59 | | static int hf_cbor_item_length5; |
60 | | static int hf_cbor_item_length; |
61 | | static int hf_cbor_item_items5; |
62 | | static int hf_cbor_item_items; |
63 | | static int hf_cbor_item_pairs5; |
64 | | static int hf_cbor_item_pairs; |
65 | | static int hf_cbor_item_float_simple_type; |
66 | | static int hf_cbor_item_unsigned_integer; |
67 | | static int hf_cbor_item_negative_integer; |
68 | | static int hf_cbor_item_text_string; |
69 | | static int hf_cbor_item_byte_string; |
70 | | static int hf_cbor_item_array; |
71 | | static int hf_cbor_item_map; |
72 | | static int hf_cbor_item_tag; |
73 | | static int hf_cbor_item_float_simple; |
74 | | static int hf_cbor_type_uint5; |
75 | | static int hf_cbor_type_uint; |
76 | | static int hf_cbor_type_nint; |
77 | | static int hf_cbor_type_byte_string; |
78 | | static int hf_cbor_type_byte_string_indef; |
79 | | static int hf_cbor_type_text_string; |
80 | | static int hf_cbor_type_text_string_indef; |
81 | | static int hf_cbor_type_tag; |
82 | | static int hf_cbor_type_simple_data5; |
83 | | static int hf_cbor_type_simple_data8; |
84 | | static int hf_cbor_type_float16; |
85 | | static int hf_cbor_type_float32; |
86 | | static int hf_cbor_type_float64; |
87 | | static int hf_cbor_seq_len; |
88 | | static int hf_cbor_diag_text; |
89 | | |
90 | | static int ett_cbor; |
91 | | static int ett_cbor_type; |
92 | | static int ett_cbor_unsigned_integer; |
93 | | static int ett_cbor_negative_integer; |
94 | | static int ett_cbor_byte_string; |
95 | | static int ett_cbor_byte_string_indef; |
96 | | static int ett_cbor_text_string; |
97 | | static int ett_cbor_text_string_indef; |
98 | | static int ett_cbor_array; |
99 | | static int ett_cbor_map; |
100 | | static int ett_cbor_tag; |
101 | | static int ett_cbor_float_simple; |
102 | | |
103 | | static expert_field ei_cbor_invalid_minor_type; |
104 | | static expert_field ei_cbor_invalid_element; |
105 | | static expert_field ei_cbor_too_long_length; |
106 | | static expert_field ei_cbor_max_recursion_depth_reached; |
107 | | static expert_field ei_cbor_embedded_bstr; |
108 | | |
109 | | static dissector_handle_t cbor_handle; |
110 | | static dissector_handle_t cborseq_handle; |
111 | | |
112 | | static heur_dissector_list_t cbor_bstr_heur; |
113 | | |
114 | 21.9k | #define CBOR_TYPE_USIGNED_INT 0 |
115 | 6.10k | #define CBOR_TYPE_NEGATIVE_INT 1 |
116 | 1.84k | #define CBOR_TYPE_BYTE_STRING 2 |
117 | 2.20k | #define CBOR_TYPE_TEXT_STRING 3 |
118 | 5.22k | #define CBOR_TYPE_ARRAY 4 |
119 | 6.02k | #define CBOR_TYPE_MAP 5 |
120 | 4.83k | #define CBOR_TYPE_TAGGED 6 |
121 | 10.2k | #define CBOR_TYPE_FLOAT 7 |
122 | | |
123 | | static const value_string major_type_vals[] = { |
124 | | { 0, "Unsigned Integer" }, |
125 | | { 1, "Negative Integer" }, |
126 | | { 2, "Byte String" }, |
127 | | { 3, "Text String" }, |
128 | | { 4, "Array" }, |
129 | | { 5, "Map" }, |
130 | | { 6, "Tagged" }, |
131 | | { 7, "Floating-Point or Simple" }, |
132 | | { 0, NULL } |
133 | | }; |
134 | | |
135 | | static const value_string integer_size_vals[] = { |
136 | | { 24, "1 byte" }, |
137 | | { 25, "2 bytes" }, |
138 | | { 26, "4 bytes" }, |
139 | | { 27, "8 bytes" }, |
140 | | { 28, "Reserved for future additions" }, |
141 | | { 29, "Reserved for future additions" }, |
142 | | { 30, "Reserved for future additions" }, |
143 | | { 31, "No argument value is derived" }, |
144 | | { 0, NULL } |
145 | | }; |
146 | | |
147 | | static const value_string length_size_vals[] = { |
148 | | { 24, "1 byte" }, |
149 | | { 25, "2 bytes" }, |
150 | | { 26, "4 bytes" }, |
151 | | { 27, "8 bytes" }, |
152 | | { 28, "Reserved for future additions" }, |
153 | | { 29, "Reserved for future additions" }, |
154 | | { 30, "Reserved for future additions" }, |
155 | | { 31, "Indefinite Length" }, |
156 | | { 0, NULL } |
157 | | }; |
158 | | |
159 | | static const value_string float_simple_type_vals[] = { |
160 | | { 24, "Simple value" }, |
161 | | { 25, "IEEE 754 Half-Precision Float" }, |
162 | | { 26, "IEEE 754 Single-Precision Float" }, |
163 | | { 27, "IEEE 754 Double-Precision Float" }, |
164 | | { 28, "Reserved for future additions" }, |
165 | | { 29, "Reserved for future additions" }, |
166 | | { 30, "Reserved for future additions" }, |
167 | | { 31, "Break indefinite length" }, |
168 | | { 0, NULL } |
169 | | }; |
170 | | |
171 | | /* see https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags */ |
172 | | static const val64_string tag64_vals[] = { |
173 | | { 0, "Standard date/time string" }, |
174 | | { 1, "Epoch-based date/time" }, |
175 | | { 2, "Positive bignum" }, |
176 | | { 3, "Negative bignum" }, |
177 | | { 4, "Decimal fraction" }, |
178 | | { 5, "Bigfloat" }, |
179 | | { 16, "COSE Single Recipient Encrypted Data Object" }, |
180 | | { 17, "COSE Mac w/o Recipients Object" }, |
181 | | { 18, "COSE Single Signer Data Object" }, |
182 | | { 19, "COSE standalone V2 countersignature" }, |
183 | | { 21, "Expected conversion to base64url encoding" }, |
184 | | { 22, "Expected conversion to base64 encoding" }, |
185 | | { 23, "Expected conversion to base16 encoding" }, |
186 | | { 24, "Encoded CBOR data item" }, |
187 | | { 25, "reference the nth previously seen string" }, |
188 | | { 26, "Serialised Perl object with classname and constructor arguments" }, |
189 | | { 27, "Serialised language-independent object with type name and constructor arguments" }, |
190 | | { 28, "mark value as (potentially) shared" }, |
191 | | { 29, "reference nth marked value" }, |
192 | | { 30, "Rational number" }, |
193 | | { 32, "URI" }, |
194 | | { 33, "base64url" }, |
195 | | { 34, "base64" }, |
196 | | { 35, "Regular expression" }, |
197 | | { 36, "MIME message" }, |
198 | | { 37, "Binary UUID" }, |
199 | | { 38, "Language-tagged string" }, |
200 | | { 39, "Identifier" }, |
201 | | { 61, "CBOR Web Token (CWT)" }, |
202 | | { 63, "Encoded CBOR Sequence" }, |
203 | | { 100, "Number of days since the epoch date 1970-01-01" }, |
204 | | { 256, "mark value as having string references" }, |
205 | | { 257, "Binary MIME message" }, |
206 | | { 264, "Decimal fraction with arbitrary exponent" }, |
207 | | { 265, "Bigfloat with arbitrary exponent" }, |
208 | | { 1004, "RFC 3339 full-date string" }, |
209 | | { 22098, "hint that indicates an additional level of indirection" }, |
210 | | { 55799, "Self-describe CBOR" }, |
211 | | { 0, NULL }, |
212 | | }; |
213 | | /// Display text for simple values |
214 | | static const value_string vals_simple_data[] = { |
215 | | { 20, "False" }, |
216 | | { 21, "True" }, |
217 | | { 22, "Null" }, |
218 | | { 23, "Undefined" }, |
219 | | { 0, NULL }, |
220 | | }; |
221 | | /// Diagnostic form of simple values |
222 | | static const value_string vals_simple_diag[] = { |
223 | | { 20, "false" }, |
224 | | { 21, "true" }, |
225 | | { 22, "null" }, |
226 | | { 23, "undefined" }, |
227 | | { 0, NULL }, |
228 | | }; |
229 | | |
230 | | /// Context for CBOR diagnostic notation text |
231 | | typedef struct { |
232 | | /// Working buffer to append to |
233 | | wmem_strbuf_t *buf; |
234 | | /// Stack of parent item buffers |
235 | | wmem_stack_t *stack; |
236 | | } cbor_diag_ctx_t; |
237 | | |
238 | | /** Initialize a diagnostic text context. |
239 | | * |
240 | | * @param[out] ptr The pointer to replace if NULL. |
241 | | * @param[in] alloc The packet allocator to use. |
242 | | * @param is_sequence True if decoding a sequence with diagnostic above the top items. |
243 | | */ |
244 | 9.03k | static void cbor_diag_ctx_init(cbor_diag_ctx_t **ptr, wmem_allocator_t *alloc, bool is_sequence) { |
245 | 9.03k | if (!*ptr && (cbor_display_diagnostic != CBOR_DIAG_NONE)) { |
246 | 0 | *ptr = wmem_new0(alloc, cbor_diag_ctx_t); |
247 | 0 | (*ptr)->buf = is_sequence ? wmem_strbuf_new(alloc, NULL) : NULL; |
248 | 0 | (*ptr)->stack = wmem_stack_new(alloc); |
249 | 0 | } |
250 | 9.03k | } |
251 | | |
252 | | /** Extract the current value from a diagnostic context. |
253 | | * |
254 | | * @param[in] ctx The context to read from or NULL if not valid. |
255 | | * @param type_major Used for specific cases of indefinite length strings. |
256 | | * @return The diagnostic text, which may be augmented from the direct buffer. |
257 | | */ |
258 | 0 | static const char * cbor_diag_ctx_get(const cbor_diag_ctx_t *ctx, uint8_t type_major) { |
259 | 0 | if (!ctx) { |
260 | 0 | return "/invalid/"; |
261 | 0 | } |
262 | 0 | const char *got = wmem_strbuf_get_str(ctx->buf); |
263 | 0 | if (strcmp(got, "(_ )") == 0) { |
264 | 0 | got = (type_major == CBOR_TYPE_BYTE_STRING) ? "''_" : "\"\"_"; |
265 | 0 | } |
266 | 0 | return got; |
267 | 0 | } |
268 | | |
269 | | static bool |
270 | | dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, cbor_diag_ctx_t *ctx); |
271 | | |
272 | | static bool |
273 | | dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx); |
274 | | |
275 | | static bool |
276 | | dissect_cbor_unsigned_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
277 | 21.9k | { |
278 | 21.9k | uint64_t value = 0; |
279 | 21.9k | proto_item *item; |
280 | 21.9k | proto_tree *subtree; |
281 | | |
282 | 21.9k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_unsigned_integer, tvb, *offset, -1, ENC_NA); |
283 | 21.9k | subtree = proto_item_add_subtree(item, ett_cbor_unsigned_integer); |
284 | | |
285 | 21.9k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
286 | 21.9k | if (type_minor <= 0x17) { |
287 | 21.3k | proto_tree_add_item(subtree, hf_cbor_type_uint5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
288 | 21.3k | value = type_minor; |
289 | 21.3k | } else { |
290 | 629 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
291 | 629 | } |
292 | 21.9k | *offset += 1; |
293 | | |
294 | 21.9k | switch (type_minor) { |
295 | 243 | case 0x18: |
296 | 243 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 1, ENC_BIG_ENDIAN, &value); |
297 | 243 | *offset += 1; |
298 | 243 | break; |
299 | 255 | case 0x19: |
300 | 255 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 2, ENC_BIG_ENDIAN, &value); |
301 | 255 | *offset += 2; |
302 | 255 | break; |
303 | 62 | case 0x1a: |
304 | 62 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 4, ENC_BIG_ENDIAN, &value); |
305 | 62 | *offset += 4; |
306 | 62 | break; |
307 | 52 | case 0x1b: |
308 | 52 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_uint, tvb, *offset, 8, ENC_BIG_ENDIAN, &value); |
309 | 52 | *offset += 8; |
310 | 52 | break; |
311 | 21.3k | default: |
312 | 21.3k | if (type_minor > 0x17) { |
313 | 17 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
314 | 17 | "invalid minor type %i in unsigned integer", type_minor); |
315 | 17 | return false; |
316 | 17 | } |
317 | 21.3k | break; |
318 | 21.9k | } |
319 | | |
320 | 21.9k | proto_item_append_text(item, ": %" PRIu64, value); |
321 | 21.9k | proto_item_set_end(item, tvb, *offset); |
322 | | |
323 | 21.9k | if (ctx) { |
324 | 0 | wmem_strbuf_append_printf(ctx->buf, "%" PRIu64, value); |
325 | 0 | } |
326 | | |
327 | 21.9k | return true; |
328 | 21.9k | } |
329 | | |
330 | | static bool |
331 | | dissect_cbor_negative_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
332 | 6.10k | { |
333 | 6.10k | uint64_t arg = 0; |
334 | 6.10k | int64_t value = 0; |
335 | 6.10k | proto_item *item; |
336 | 6.10k | proto_tree *subtree; |
337 | | |
338 | 6.10k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_negative_integer, tvb, *offset, -1, ENC_NA); |
339 | 6.10k | subtree = proto_item_add_subtree(item, ett_cbor_negative_integer); |
340 | | |
341 | 6.10k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
342 | 6.10k | if (type_minor <= 0x17) { |
343 | 5.17k | arg = type_minor; |
344 | 5.17k | value = (int64_t)-1 - arg; |
345 | | /* Keep correct bit representation with a modified value. */ |
346 | 5.17k | proto_tree_add_int64_bits_format_value(subtree, hf_cbor_type_nint, tvb, 3, 5, type_minor, ENC_BIG_ENDIAN, "%" PRId64, value); |
347 | 5.17k | } else { |
348 | 928 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
349 | 928 | } |
350 | 6.10k | *offset += 1; |
351 | | |
352 | 6.10k | switch (type_minor) { |
353 | 236 | case 0x18: |
354 | 236 | arg = tvb_get_uint8(tvb, *offset); |
355 | 236 | value = (int64_t)-1 - arg; |
356 | 236 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 1, value); |
357 | 236 | *offset += 1; |
358 | 236 | break; |
359 | 259 | case 0x19: |
360 | 259 | arg = tvb_get_ntohs(tvb, *offset); |
361 | 259 | value = (int64_t)-1 - arg; |
362 | 259 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 2, value); |
363 | 259 | *offset += 2; |
364 | 259 | break; |
365 | 193 | case 0x1a: |
366 | 193 | arg = tvb_get_ntohl(tvb, *offset); |
367 | 193 | value = (int64_t)-1 - arg; |
368 | 193 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 4, value); |
369 | 193 | *offset += 4; |
370 | 193 | break; |
371 | 210 | case 0x1b: |
372 | 210 | arg = tvb_get_ntoh64(tvb, *offset); |
373 | | /* TODO: an overflow could happen here, for negative int < INT64_MIN */ |
374 | 210 | value = (int64_t)-1 - arg; |
375 | 210 | if (value > -1) { |
376 | 88 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
377 | 88 | "The value is too negative, Wireshark can not display it correctly"); |
378 | 88 | } |
379 | 210 | proto_tree_add_int64(subtree, hf_cbor_type_nint, tvb, *offset, 8, value); |
380 | 210 | *offset += 8; |
381 | 210 | break; |
382 | 5.20k | default: |
383 | 5.20k | if (type_minor > 0x17) { |
384 | 30 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
385 | 30 | "invalid minor type %i in negative integer", type_minor); |
386 | 30 | return false; |
387 | 30 | } |
388 | 5.17k | break; |
389 | 6.10k | } |
390 | | |
391 | 6.06k | if (arg == UINT64_MAX) { |
392 | 1 | proto_item_append_text(item, ": -18446744073709551616"); |
393 | 1 | } |
394 | 6.06k | else { |
395 | 6.06k | proto_item_append_text(item, ": -%" PRIu64, arg + 1); |
396 | 6.06k | } |
397 | 6.06k | proto_item_set_end(item, tvb, *offset); |
398 | | |
399 | 6.06k | if (ctx) { |
400 | 0 | if (arg == UINT64_MAX) { |
401 | 0 | wmem_strbuf_append(ctx->buf, "-18446744073709551616"); |
402 | 0 | } |
403 | 0 | else { |
404 | 0 | wmem_strbuf_append_printf(ctx->buf, "-%" PRIu64, arg + 1); |
405 | 0 | } |
406 | 0 | } |
407 | | |
408 | 6.06k | return true; |
409 | 6.10k | } |
410 | | |
411 | | /** Escape the quote character itself after escaping non-printable text. |
412 | | */ |
413 | | static char * |
414 | 0 | cbor_diag_escape(wmem_allocator_t *alloc, const char *in, char quote) { |
415 | 0 | const char reject[2] = { quote }; |
416 | |
|
417 | 0 | wmem_strbuf_t *buf = wmem_strbuf_new(alloc, NULL); |
418 | 0 | while (*in) { |
419 | 0 | size_t width = strcspn(in, reject); |
420 | 0 | if (width) { |
421 | 0 | wmem_strbuf_append_len(buf, in, width); |
422 | 0 | in += width; |
423 | 0 | } |
424 | 0 | if (*in) { |
425 | 0 | wmem_strbuf_append_printf(buf, "\\%c", quote); |
426 | 0 | ++in; |
427 | 0 | } |
428 | 0 | } |
429 | 0 | return wmem_strbuf_finalize(buf); |
430 | 0 | } |
431 | | |
432 | | static bool |
433 | | // NOLINTNEXTLINE(misc-no-recursion) |
434 | | dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
435 | 1.82k | { |
436 | 1.82k | uint64_t length; |
437 | 1.82k | int eof_type; |
438 | 1.82k | proto_tree *subtree; |
439 | 1.82k | proto_item *item; |
440 | | |
441 | 1.82k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_byte_string, tvb, *offset, -1, ENC_NA); |
442 | 1.82k | subtree = proto_item_add_subtree(item, ett_cbor_byte_string); |
443 | | |
444 | 1.82k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
445 | 1.82k | if (type_minor <= 0x17) { |
446 | 1.36k | proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
447 | 1.36k | length = type_minor; |
448 | 1.36k | } else { |
449 | 467 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
450 | 467 | } |
451 | 1.82k | *offset += 1; |
452 | | |
453 | 1.82k | switch (type_minor) { |
454 | 71 | case 0x18: |
455 | 71 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
456 | 71 | *offset += 1; |
457 | 71 | break; |
458 | 7 | case 0x19: |
459 | 7 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
460 | 7 | *offset += 2; |
461 | 7 | break; |
462 | 7 | case 0x1a: |
463 | 7 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
464 | 7 | *offset += 4; |
465 | 7 | break; |
466 | 29 | case 0x1b: |
467 | 29 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
468 | 29 | *offset += 8; |
469 | 29 | break; |
470 | 345 | case 0x1f: { |
471 | 345 | proto_item_append_text(item, ": (indefinite length)"); |
472 | 345 | item = proto_tree_add_item(subtree, hf_cbor_type_byte_string_indef, tvb, *offset, 1, ENC_NA); |
473 | 345 | subtree = proto_item_add_subtree(item, ett_cbor_byte_string_indef); |
474 | 345 | if (ctx) { |
475 | 0 | wmem_strbuf_append_printf(ctx->buf, "(_ "); |
476 | 0 | } |
477 | 345 | bool first = true; |
478 | 382 | while (1) { |
479 | 382 | eof_type = tvb_get_uint8(tvb, *offset); |
480 | 382 | if (eof_type == 0xff) { |
481 | 66 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx); |
482 | 66 | proto_item_set_end(item, tvb, *offset); |
483 | 66 | if (ctx) { |
484 | 0 | wmem_strbuf_append_printf(ctx->buf, ")"); |
485 | 0 | } |
486 | 66 | return true; |
487 | 66 | } |
488 | | |
489 | 316 | if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_BYTE_STRING) { |
490 | 16 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element, |
491 | 16 | "invalid element %i, expected byte string", (eof_type & 0xe0) >> 5); |
492 | 16 | return false; |
493 | 16 | } |
494 | | |
495 | 300 | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
496 | 300 | if (recursion_depth > prefs.gui_max_tree_depth) { |
497 | 0 | proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
498 | 0 | return false; |
499 | 0 | } |
500 | 300 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
501 | | |
502 | 300 | if (ctx) { |
503 | 0 | if (first) { |
504 | 0 | first = false; |
505 | 0 | } |
506 | 0 | else { |
507 | 0 | wmem_strbuf_append(ctx->buf, ", "); |
508 | 0 | } |
509 | 0 | } |
510 | 300 | bool recursed = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f, ctx); |
511 | 300 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
512 | | |
513 | 300 | if (!recursed) { |
514 | 263 | return false; |
515 | 263 | } |
516 | 300 | } |
517 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
518 | 0 | return false; |
519 | 345 | } |
520 | 1.37k | default: |
521 | 1.37k | if (type_minor > 0x17) { |
522 | 8 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
523 | 8 | "invalid minor type %i in byte string", type_minor); |
524 | 8 | return false; |
525 | 8 | } |
526 | 1.36k | break; |
527 | 1.82k | } |
528 | | |
529 | 1.47k | if (length > INT32_MAX) { |
530 | 20 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
531 | 20 | "the length (%" PRIu64 ") of the byte string too long", length); |
532 | 20 | return false; |
533 | 20 | } |
534 | | |
535 | 1.45k | proto_item *item_data = proto_tree_add_item(subtree, hf_cbor_type_byte_string, tvb, *offset, (int)length, ENC_NA); |
536 | 1.45k | if (ckd_add(offset, *offset, length)) { |
537 | 0 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
538 | 0 | "the length (%" PRIu64 ") of the byte string too long", length); |
539 | 0 | return false; |
540 | 0 | } |
541 | | |
542 | 1.45k | proto_item_append_text(item, ": (%" PRIu64 " byte%s)", length, plurality(length, "", "s")); |
543 | 1.45k | proto_item_set_end(item, tvb, *offset); |
544 | 1.45k | unsigned int_start = *offset - (unsigned)length; |
545 | | |
546 | 1.45k | tvbuff_t *content_tvb = tvb_new_subset_length(tvb, int_start, (unsigned)length); |
547 | | |
548 | 1.45k | bool heur_valid = false; |
549 | 1.45k | if (cbor_dissect_embeded_bstr && length) { |
550 | 0 | heur_dtbl_entry_t *entry = NULL; |
551 | 0 | heur_valid = dissector_try_heuristic(cbor_bstr_heur, content_tvb, pinfo, subtree, &entry, ctx); |
552 | 0 | if (heur_valid) { |
553 | 0 | expert_add_info_format(pinfo, item_data, &ei_cbor_embedded_bstr, "Heuristic dissection matched as: %s", entry->display_name); |
554 | 0 | } |
555 | 0 | } |
556 | | |
557 | 1.45k | if (ctx && !heur_valid) { |
558 | 0 | if (cbor_diagnostic_bstr_text && tvb_utf_8_isprint_remaining(content_tvb, 0)) { |
559 | 0 | char *text = tvb_format_text(pinfo->pool, content_tvb, 0, (unsigned)length); |
560 | 0 | wmem_strbuf_append_printf(ctx->buf, "'%s'", cbor_diag_escape(pinfo->pool, text, '\'')); |
561 | 0 | } |
562 | 0 | else { |
563 | 0 | char *hexstr = bytes_to_str_maxlen(pinfo->pool, tvb_get_ptr(content_tvb, 0, (unsigned)length), length, length); |
564 | 0 | wmem_strbuf_append_printf(ctx->buf, "h'%s'", hexstr); |
565 | 0 | } |
566 | 0 | } |
567 | | |
568 | 1.45k | return true; |
569 | 1.45k | } |
570 | | |
571 | | static bool |
572 | | // NOLINTNEXTLINE(misc-no-recursion) |
573 | | dissect_cbor_text_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
574 | 2.18k | { |
575 | 2.18k | const uint8_t *value = NULL; |
576 | 2.18k | uint64_t length = 0; |
577 | 2.18k | int eof_type, new_offset; |
578 | 2.18k | proto_tree *subtree; |
579 | 2.18k | proto_item *item; |
580 | | |
581 | 2.18k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_text_string, tvb, *offset, -1, ENC_NA); |
582 | 2.18k | subtree = proto_item_add_subtree(item, ett_cbor_text_string); |
583 | | |
584 | 2.18k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
585 | 2.18k | if (type_minor <= 0x17) { |
586 | 1.79k | proto_tree_add_item(subtree, hf_cbor_item_length5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
587 | 1.79k | length = type_minor; |
588 | 1.79k | } else { |
589 | 385 | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
590 | 385 | } |
591 | 2.18k | *offset += 1; |
592 | | |
593 | 2.18k | switch (type_minor) { |
594 | 27 | case 0x18: |
595 | 27 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
596 | 27 | *offset += 1; |
597 | 27 | break; |
598 | 14 | case 0x19: |
599 | 14 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
600 | 14 | *offset += 2; |
601 | 14 | break; |
602 | 17 | case 0x1a: |
603 | 17 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
604 | 17 | *offset += 4; |
605 | 17 | break; |
606 | 4 | case 0x1b: |
607 | 4 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_length, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
608 | 4 | *offset += 8; |
609 | 4 | break; |
610 | 306 | case 0x1f: { |
611 | 306 | proto_item_append_text(item, ": (indefinite length)"); |
612 | 306 | item = proto_tree_add_item(subtree, hf_cbor_type_text_string_indef, tvb, *offset, 1, ENC_NA); |
613 | 306 | subtree = proto_item_add_subtree(item, ett_cbor_text_string_indef); |
614 | 306 | if (ctx) { |
615 | 0 | wmem_strbuf_append_printf(ctx->buf, "(_ "); |
616 | 0 | } |
617 | 306 | bool first = true; |
618 | 437 | while (1) { |
619 | 389 | eof_type = tvb_get_uint8(tvb, *offset); |
620 | 389 | if (eof_type == 0xff) { |
621 | 119 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx); |
622 | 119 | proto_item_set_end(item, tvb, *offset); |
623 | 119 | if (ctx) { |
624 | 0 | wmem_strbuf_append_printf(ctx->buf, ")"); |
625 | 0 | } |
626 | 119 | return true; |
627 | 119 | } |
628 | | |
629 | 270 | if (((eof_type & 0xe0) >> 5) != CBOR_TYPE_TEXT_STRING) { |
630 | 15 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_element, |
631 | 15 | "invalid element %i, expected text string", (eof_type & 0xe0) >> 5); |
632 | 15 | return false; |
633 | 15 | } |
634 | | |
635 | 255 | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
636 | 255 | if (recursion_depth > prefs.gui_max_tree_depth) { |
637 | 0 | proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
638 | 0 | return false; |
639 | 0 | } |
640 | 255 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
641 | | |
642 | 255 | if (ctx) { |
643 | 0 | if (first) { |
644 | 0 | first = false; |
645 | 0 | } |
646 | 0 | else { |
647 | 0 | wmem_strbuf_append(ctx->buf, ", "); |
648 | 0 | } |
649 | 0 | } |
650 | 255 | bool recursed = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f, ctx); |
651 | 255 | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
652 | | |
653 | 255 | if (!recursed) { |
654 | 124 | return false; |
655 | 124 | } |
656 | 255 | } |
657 | 48 | DISSECTOR_ASSERT_NOT_REACHED(); |
658 | 48 | return false; |
659 | 306 | } |
660 | 1.81k | default: |
661 | 1.81k | if (type_minor > 0x17) { |
662 | 17 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
663 | 17 | "invalid minor type %i in text string", type_minor); |
664 | 17 | return false; |
665 | 17 | } |
666 | 1.79k | break; |
667 | 2.18k | } |
668 | | |
669 | 1.85k | if (ckd_add(&new_offset, *offset, length)) { |
670 | 9 | expert_add_info_format(pinfo, subtree, &ei_cbor_too_long_length, |
671 | 9 | "the length (%" PRIu64 ") of the text string too long", length); |
672 | 9 | return false; |
673 | 9 | } |
674 | | |
675 | 1.84k | tvbuff_t *content_tvb = tvb_new_subset_length(tvb, *offset, (unsigned)length); |
676 | 1.84k | proto_tree_add_item_ret_string(subtree, hf_cbor_type_text_string, content_tvb, 0, (int)length, ENC_BIG_ENDIAN|ENC_UTF_8, pinfo->pool, &value); |
677 | 1.84k | *offset = new_offset; |
678 | | |
679 | 1.84k | proto_item_append_text(item, ": %s", value); |
680 | 1.84k | proto_item_set_end(item, tvb, *offset); |
681 | | |
682 | 1.84k | if (ctx) { |
683 | 0 | char *text = tvb_format_text(pinfo->pool, content_tvb, 0, (unsigned)length); |
684 | 0 | wmem_strbuf_append_printf(ctx->buf, "\"%s\"", cbor_diag_escape(pinfo->pool, text, '"')); |
685 | 0 | } |
686 | | |
687 | 1.84k | return true; |
688 | 1.85k | } |
689 | | |
690 | | static bool |
691 | | // NOLINTNEXTLINE(misc-no-recursion) |
692 | | dissect_cbor_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
693 | 5.22k | { |
694 | 5.22k | uint64_t length = 0; |
695 | 5.22k | proto_tree *subtree; |
696 | 5.22k | proto_item *item; |
697 | 5.22k | bool indefinite = false; |
698 | | |
699 | 5.22k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_array, tvb, *offset, -1, ENC_NA); |
700 | 5.22k | subtree = proto_item_add_subtree(item, ett_cbor_array); |
701 | | |
702 | 5.22k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
703 | | |
704 | 5.22k | if (type_minor <= 0x17) { |
705 | 3.88k | proto_tree_add_item(subtree, hf_cbor_item_items5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
706 | 3.88k | length = type_minor; |
707 | 3.88k | } else { |
708 | 1.33k | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
709 | 1.33k | } |
710 | 5.22k | *offset += 1; |
711 | | |
712 | 5.22k | switch (type_minor) { |
713 | 445 | case 0x18: |
714 | 445 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
715 | 445 | *offset += 1; |
716 | 445 | break; |
717 | 70 | case 0x19: |
718 | 70 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
719 | 70 | *offset += 2; |
720 | 70 | break; |
721 | 93 | case 0x1a: |
722 | 93 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
723 | 93 | *offset += 4; |
724 | 93 | break; |
725 | 117 | case 0x1b: |
726 | 117 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_items, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
727 | 117 | *offset += 8; |
728 | 117 | break; |
729 | 608 | case 0x1f: |
730 | 608 | length = INT_MAX; |
731 | 608 | indefinite = true; |
732 | 608 | break; |
733 | 3.89k | default: |
734 | 3.89k | if (type_minor > 0x17) { |
735 | 5 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
736 | 5 | "invalid minor type %i in array", type_minor); |
737 | 5 | return false; |
738 | 5 | } |
739 | 3.88k | break; |
740 | 5.22k | } |
741 | | |
742 | 5.22k | if (ctx) { |
743 | 0 | wmem_strbuf_append(ctx->buf, indefinite ? "[_ " : "["); |
744 | 0 | } |
745 | | |
746 | 21.3k | for (uint64_t i = 0; i < length; i++) { |
747 | 17.9k | if (indefinite) { |
748 | 1.52k | int value = tvb_get_uint8(tvb, *offset); |
749 | 1.52k | if (value == 0xff) { |
750 | 152 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx); |
751 | 152 | break; |
752 | 152 | } |
753 | 1.52k | } |
754 | | |
755 | 17.7k | if (ctx && (i != 0)) { |
756 | 0 | wmem_strbuf_append(ctx->buf, ", "); |
757 | 0 | } |
758 | | |
759 | 17.7k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) { |
760 | 1.67k | return false; |
761 | 1.67k | } |
762 | 17.7k | } |
763 | | |
764 | 3.54k | if (ctx) { |
765 | 0 | wmem_strbuf_append(ctx->buf, "]"); |
766 | 0 | } |
767 | | |
768 | 3.54k | if (indefinite) { |
769 | 152 | proto_item_append_text(item, ": (indefinite length)"); |
770 | 3.39k | } else { |
771 | 3.39k | proto_item_append_text(item, ": (%" PRIu64 " item%s)", length, plurality(length, "", "s")); |
772 | 3.39k | } |
773 | 3.54k | proto_item_set_end(item, tvb, *offset); |
774 | | |
775 | 3.54k | return true; |
776 | 5.22k | } |
777 | | |
778 | | static bool |
779 | | // NOLINTNEXTLINE(misc-no-recursion) |
780 | | dissect_cbor_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
781 | 6.02k | { |
782 | 6.02k | uint64_t length = 0; |
783 | 6.02k | proto_tree *subtree; |
784 | 6.02k | proto_item *item; |
785 | 6.02k | bool indefinite = false; |
786 | | |
787 | 6.02k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_map, tvb, *offset, -1, ENC_NA); |
788 | 6.02k | subtree = proto_item_add_subtree(item, ett_cbor_map); |
789 | | |
790 | 6.02k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
791 | | |
792 | 6.02k | if (type_minor <= 0x17) { |
793 | 4.66k | proto_tree_add_item(subtree, hf_cbor_item_pairs5, tvb, *offset, 1, ENC_BIG_ENDIAN); |
794 | 4.66k | length = type_minor; |
795 | 4.66k | } else { |
796 | 1.35k | proto_tree_add_item(subtree, hf_cbor_item_length_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
797 | 1.35k | } |
798 | 6.02k | *offset += 1; |
799 | | |
800 | 6.02k | switch (type_minor) { |
801 | 380 | case 0x18: |
802 | 380 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 1, ENC_BIG_ENDIAN, &length); |
803 | 380 | *offset += 1; |
804 | 380 | break; |
805 | 176 | case 0x19: |
806 | 176 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 2, ENC_BIG_ENDIAN, &length); |
807 | 176 | *offset += 2; |
808 | 176 | break; |
809 | 224 | case 0x1a: |
810 | 224 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 4, ENC_BIG_ENDIAN, &length); |
811 | 224 | *offset += 4; |
812 | 224 | break; |
813 | 236 | case 0x1b: |
814 | 236 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_item_pairs, tvb, *offset, 8, ENC_BIG_ENDIAN, &length); |
815 | 236 | *offset += 8; |
816 | 236 | break; |
817 | 335 | case 0x1f: |
818 | 335 | length = INT_MAX; |
819 | 335 | indefinite = true; |
820 | 335 | break; |
821 | 4.67k | default: |
822 | 4.67k | if (type_minor > 0x17) { |
823 | 4 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
824 | 4 | "invalid minor type %i in map", type_minor); |
825 | 4 | return false; |
826 | 4 | } |
827 | 4.66k | break; |
828 | 6.02k | } |
829 | | |
830 | 6.01k | if (ctx) { |
831 | 0 | wmem_strbuf_append(ctx->buf, indefinite ? "{_ " : "{"); |
832 | 0 | } |
833 | | |
834 | 15.0k | for (uint64_t i = 0; i < length; i++) { |
835 | 11.7k | if (indefinite) { |
836 | 1.38k | int value = tvb_get_uint8(tvb, *offset); |
837 | 1.38k | if (value == 0xff) { |
838 | 93 | dissect_cbor_float_simple_data(tvb, pinfo, subtree, offset, 0x1f, ctx); |
839 | 93 | break; |
840 | 93 | } |
841 | 1.38k | } |
842 | | |
843 | 11.6k | if (ctx && (i != 0)) { |
844 | 0 | wmem_strbuf_append(ctx->buf, ", "); |
845 | 0 | } |
846 | | |
847 | 11.6k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) { |
848 | 2.41k | return false; |
849 | 2.41k | } |
850 | | |
851 | 9.23k | if (ctx) { |
852 | 0 | wmem_strbuf_append(ctx->buf, ": "); |
853 | 0 | } |
854 | | |
855 | 9.23k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) { |
856 | 243 | return false; |
857 | 243 | } |
858 | 9.23k | } |
859 | | |
860 | 3.35k | if (ctx) { |
861 | 0 | wmem_strbuf_append(ctx->buf, "}"); |
862 | 0 | } |
863 | | |
864 | 3.35k | if (indefinite) { |
865 | 93 | proto_item_append_text(item, ": (indefinite length)"); |
866 | 3.25k | } else { |
867 | 3.25k | proto_item_append_text(item, ": (%" PRIu64 " pair%s)", length, plurality(length, "", "s")); |
868 | 3.25k | } |
869 | 3.35k | proto_item_set_end(item, tvb, *offset); |
870 | | |
871 | 3.35k | return true; |
872 | 6.01k | } |
873 | | |
874 | | static bool |
875 | | // NOLINTNEXTLINE(misc-no-recursion) |
876 | | dissect_cbor_tag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
877 | 4.83k | { |
878 | 4.83k | uint64_t tag = 0; |
879 | 4.83k | proto_item *item; |
880 | 4.83k | proto_tree *subtree; |
881 | | |
882 | 4.83k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_tag, tvb, *offset, -1, ENC_NA); |
883 | 4.83k | subtree = proto_item_add_subtree(item, ett_cbor_tag); |
884 | | |
885 | 4.83k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
886 | | |
887 | 4.83k | if (type_minor <= 0x17) { |
888 | 4.13k | tag = type_minor; |
889 | 4.13k | proto_tree_add_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, tag); |
890 | 4.13k | } else { |
891 | 701 | proto_tree_add_item(subtree, hf_cbor_item_integer_size, tvb, *offset, 1, ENC_BIG_ENDIAN); |
892 | 701 | } |
893 | 4.83k | *offset += 1; |
894 | | |
895 | 4.83k | switch (type_minor) { |
896 | 187 | case 0x18: |
897 | 187 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 1, ENC_BIG_ENDIAN, &tag); |
898 | 187 | *offset += 1; |
899 | 187 | break; |
900 | 230 | case 0x19: |
901 | 230 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 2, ENC_BIG_ENDIAN, &tag); |
902 | 230 | *offset += 2; |
903 | 230 | break; |
904 | 131 | case 0x1a: |
905 | 131 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 4, ENC_BIG_ENDIAN, &tag); |
906 | 131 | *offset += 4; |
907 | 131 | break; |
908 | 138 | case 0x1b: |
909 | 138 | proto_tree_add_item_ret_uint64(subtree, hf_cbor_type_tag, tvb, *offset, 8, ENC_BIG_ENDIAN, &tag); |
910 | 138 | *offset += 8; |
911 | 138 | break; |
912 | 4.15k | default: |
913 | 4.15k | if (type_minor > 0x17) { |
914 | 15 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
915 | 15 | "invalid minor type %i in tag", type_minor); |
916 | 15 | return false; |
917 | 15 | } |
918 | 4.13k | break; |
919 | 4.83k | } |
920 | | |
921 | 4.82k | if (ctx) { |
922 | 0 | wmem_strbuf_append_printf(ctx->buf, "%" PRIu64 "(", tag); |
923 | 0 | } |
924 | | |
925 | 4.82k | if (!dissect_cbor_main_type(tvb, pinfo, subtree, offset, ctx)) { |
926 | 401 | return false; |
927 | 401 | } |
928 | | |
929 | 4.42k | if (ctx) { |
930 | 0 | wmem_strbuf_append(ctx->buf, ")"); |
931 | 0 | } |
932 | | |
933 | 4.42k | proto_item_append_text(item, ": %s (%" PRIu64 ")", val64_to_str_wmem(pinfo->pool, tag, tag64_vals, "Unknown"), tag); |
934 | 4.42k | proto_item_set_end(item, tvb, *offset); |
935 | | |
936 | 4.42k | return true; |
937 | 4.82k | } |
938 | | |
939 | | /* based on code from rfc7049 appendix-D */ |
940 | | static float |
941 | | decode_half(tvbuff_t *tvb, proto_tree *tree, proto_item *item, int *offset, int hfindex) |
942 | 314 | { |
943 | 314 | int half, exponent, mantissa; |
944 | 314 | float val = 0; |
945 | | |
946 | 314 | half = tvb_get_ntohs(tvb, *offset); |
947 | 314 | exponent = (half >> 10) & 0x1f; |
948 | 314 | mantissa = half & 0x3ff; |
949 | | |
950 | 314 | if (exponent == 0) { |
951 | 51 | val = ldexpf((float)mantissa, -24); |
952 | 51 | if (half & 0x8000) { |
953 | 21 | val = -val; |
954 | 21 | } |
955 | 51 | proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val); |
956 | 51 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val); |
957 | 263 | } else if (exponent != 31) { |
958 | 233 | val = ldexpf((float)(mantissa + 1024), exponent - 25); |
959 | 233 | if (half & 0x8000) { |
960 | 202 | val = -val; |
961 | 202 | } |
962 | 233 | proto_tree_add_float(tree, hfindex, tvb, *offset, 2, val); |
963 | 233 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", val); |
964 | 233 | } else { |
965 | 30 | val = (mantissa == 0) ? INFINITY : NAN; |
966 | 30 | if (half & 0x8000) { |
967 | 22 | val = -val; |
968 | 22 | } |
969 | 30 | proto_tree_add_float_format_value(tree, hfindex, tvb, *offset, 2, 0, "%f", val); |
970 | 30 | proto_item_set_text(item, "Float: %f", val); |
971 | 30 | } |
972 | 314 | return val; |
973 | 314 | } |
974 | | |
975 | | #define CBOR_DIAG_FLOAT(buf, fmt, val) \ |
976 | 0 | if (isnan(val)) { \ |
977 | 0 | wmem_strbuf_append(buf, "NaN"); \ |
978 | 0 | } \ |
979 | 0 | else if (isinf(val)) { \ |
980 | 0 | if (val < 0) { \ |
981 | 0 | wmem_strbuf_append(buf, "-"); \ |
982 | 0 | } \ |
983 | 0 | wmem_strbuf_append(buf, "Infinity"); \ |
984 | 0 | } \ |
985 | 0 | else { \ |
986 | 0 | char tmp[G_ASCII_DTOSTR_BUF_SIZE]; \ |
987 | 0 | g_ascii_formatd(tmp, sizeof(tmp), fmt, val); \ |
988 | 0 | wmem_strbuf_append(buf, tmp); \ |
989 | 0 | } |
990 | | |
991 | | |
992 | | static bool |
993 | | dissect_cbor_float_simple_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, uint8_t type_minor, cbor_diag_ctx_t *ctx) |
994 | 10.7k | { |
995 | 10.7k | uint32_t simple; |
996 | 10.7k | float f_value; |
997 | 10.7k | double d_value; |
998 | 10.7k | proto_item *item; |
999 | 10.7k | proto_tree *subtree; |
1000 | | |
1001 | 10.7k | item = proto_tree_add_item(cbor_tree, hf_cbor_item_float_simple, tvb, *offset, -1, ENC_NA); |
1002 | 10.7k | subtree = proto_item_add_subtree(item, ett_cbor_float_simple); |
1003 | | |
1004 | 10.7k | proto_tree_add_item(subtree, hf_cbor_item_major_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
1005 | | |
1006 | 10.7k | if (type_minor <= 0x17) { |
1007 | 2.88k | proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data5, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple); |
1008 | 2.88k | proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple); |
1009 | 2.88k | if (ctx) { |
1010 | 0 | wmem_strbuf_append_printf(ctx->buf, "%s", val_to_str(pinfo->pool, simple, vals_simple_diag, "simple(%u)")); |
1011 | 0 | } |
1012 | 7.84k | } else { |
1013 | 7.84k | proto_tree_add_item(subtree, hf_cbor_item_float_simple_type, tvb, *offset, 1, ENC_BIG_ENDIAN); |
1014 | 7.84k | } |
1015 | 10.7k | *offset += 1; |
1016 | | |
1017 | 10.7k | switch (type_minor) { |
1018 | 199 | case 0x18: |
1019 | 199 | proto_tree_add_item_ret_uint(subtree, hf_cbor_type_simple_data8, tvb, *offset, 1, ENC_BIG_ENDIAN, &simple); |
1020 | 199 | proto_item_set_text(item, "Simple: %s (%u)", val_to_str_const(simple, vals_simple_data, "Unknown"), simple); |
1021 | 199 | *offset += 1; |
1022 | 199 | if (ctx) { |
1023 | 0 | wmem_strbuf_append_printf(ctx->buf, "%s", val_to_str(pinfo->pool, simple, vals_simple_diag, "simple(%u)")); |
1024 | 0 | } |
1025 | 199 | break; |
1026 | 314 | case 0x19: |
1027 | 314 | f_value = decode_half(tvb, subtree, item, offset, hf_cbor_type_float16); |
1028 | 314 | *offset += 2; |
1029 | 314 | if (ctx) { |
1030 | 0 | CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(FLT_DIG) "g", f_value); |
1031 | 0 | } |
1032 | 314 | break; |
1033 | 138 | case 0x1a: |
1034 | 138 | f_value = tvb_get_ntohieee_float(tvb, *offset); |
1035 | 138 | proto_tree_add_item(subtree, hf_cbor_type_float32, tvb, *offset, 4, ENC_BIG_ENDIAN); |
1036 | 138 | proto_item_set_text(item, "Float: %." G_STRINGIFY(FLT_DIG) "g", f_value); |
1037 | 138 | *offset += 4; |
1038 | 138 | if (ctx) { |
1039 | 0 | CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(DBL_DIG) "g", f_value); |
1040 | 0 | } |
1041 | 138 | break; |
1042 | 107 | case 0x1b: |
1043 | 107 | d_value = tvb_get_ntohieee_double(tvb, *offset); |
1044 | 107 | proto_tree_add_item(subtree, hf_cbor_type_float64, tvb, *offset, 8, ENC_BIG_ENDIAN); |
1045 | 107 | proto_item_set_text(item, "Float: %." G_STRINGIFY(DBL_DIG) "g", d_value); |
1046 | 107 | *offset += 8; |
1047 | 107 | if (ctx) { |
1048 | 0 | CBOR_DIAG_FLOAT(ctx->buf, "%#." G_STRINGIFY(DBL_DIG) "g", d_value); |
1049 | 0 | } |
1050 | 107 | break; |
1051 | 7.06k | case 0x1f: |
1052 | 7.06k | proto_item_set_text(item, "Break indefinite length (%u)", type_minor); |
1053 | 7.06k | break; |
1054 | 2.90k | default: |
1055 | 2.90k | if (type_minor > 0x17) { |
1056 | 25 | expert_add_info_format(pinfo, subtree, &ei_cbor_invalid_minor_type, |
1057 | 25 | "invalid minor type %i in simple data and float", type_minor); |
1058 | 25 | return false; |
1059 | 25 | } |
1060 | 2.88k | break; |
1061 | 10.7k | } |
1062 | | |
1063 | 10.6k | proto_item_set_end(item, tvb, *offset); |
1064 | | |
1065 | 10.6k | return true; |
1066 | 10.7k | } |
1067 | | |
1068 | | |
1069 | | static bool |
1070 | | // NOLINTNEXTLINE(misc-no-recursion) |
1071 | | dissect_cbor_main_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, int *offset, cbor_diag_ctx_t *ctx) |
1072 | 57.9k | { |
1073 | 57.9k | uint8_t type; |
1074 | 57.9k | uint8_t type_major; |
1075 | 57.9k | uint8_t type_minor; |
1076 | 57.9k | int init_offset = *offset; |
1077 | | |
1078 | 57.9k | type = tvb_get_uint8(tvb, *offset); |
1079 | | |
1080 | 57.9k | type_major = (type & 0xe0) >> 5; |
1081 | 57.9k | type_minor = (type & 0x1f); |
1082 | | |
1083 | 57.9k | unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); |
1084 | | /* dissect_cbor_main_type and dissect_cbor_tag/dissect_cbor_map can exhaust |
1085 | | * the stack calling each other recursively on malformed packets otherwise */ |
1086 | 57.9k | if (recursion_depth > prefs.gui_max_tree_depth) { |
1087 | 0 | proto_tree_add_expert(cbor_tree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); |
1088 | 0 | return false; |
1089 | 0 | } |
1090 | 57.9k | p_set_proto_depth(pinfo, proto_cbor, recursion_depth + 1); |
1091 | | |
1092 | 57.9k | if (ctx) { |
1093 | 0 | wmem_stack_push(ctx->stack, ctx->buf); |
1094 | 0 | ctx->buf = wmem_strbuf_new(pinfo->pool, NULL); |
1095 | 0 | } |
1096 | | |
1097 | 57.9k | bool valid = false; |
1098 | 57.9k | switch (type_major) { |
1099 | 21.9k | case CBOR_TYPE_USIGNED_INT: |
1100 | 21.9k | valid = dissect_cbor_unsigned_integer(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1101 | 21.9k | break; |
1102 | 6.10k | case CBOR_TYPE_NEGATIVE_INT: |
1103 | 6.10k | valid = dissect_cbor_negative_integer(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1104 | 6.10k | break; |
1105 | 1.52k | case CBOR_TYPE_BYTE_STRING: |
1106 | 1.52k | valid = dissect_cbor_byte_string(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1107 | 1.52k | break; |
1108 | 1.93k | case CBOR_TYPE_TEXT_STRING: |
1109 | 1.93k | valid = dissect_cbor_text_string(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1110 | 1.93k | break; |
1111 | 5.22k | case CBOR_TYPE_ARRAY: |
1112 | 5.22k | valid = dissect_cbor_array(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1113 | 5.22k | break; |
1114 | 6.02k | case CBOR_TYPE_MAP: |
1115 | 6.02k | valid = dissect_cbor_map(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1116 | 6.02k | break; |
1117 | 4.83k | case CBOR_TYPE_TAGGED: |
1118 | 4.83k | valid = dissect_cbor_tag(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1119 | 4.83k | break; |
1120 | 10.2k | case CBOR_TYPE_FLOAT: |
1121 | 10.2k | valid = dissect_cbor_float_simple_data(tvb, pinfo, cbor_tree, offset, type_minor, ctx); |
1122 | 10.2k | break; |
1123 | 0 | default: |
1124 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1125 | 57.9k | } |
1126 | | |
1127 | 54.0k | if (ctx) { |
1128 | 0 | const char *item_text = cbor_diag_ctx_get(valid ? ctx : NULL, type_major); |
1129 | 0 | if ((cbor_display_diagnostic == CBOR_DIAG_ALL) |
1130 | 0 | || ((cbor_display_diagnostic == CBOR_DIAG_TOP) && (wmem_stack_count(ctx->stack) == 1))) { |
1131 | 0 | proto_item_set_generated( |
1132 | 0 | proto_tree_add_string(cbor_tree, hf_cbor_diag_text, tvb, init_offset, *offset - init_offset, item_text) |
1133 | 0 | ); |
1134 | 0 | } |
1135 | |
|
1136 | 0 | wmem_strbuf_t *top = wmem_stack_pop(ctx->stack); |
1137 | 0 | if (top) { |
1138 | 0 | wmem_strbuf_append(top, item_text); |
1139 | |
|
1140 | 0 | wmem_strbuf_destroy(ctx->buf); |
1141 | 0 | } |
1142 | 0 | ctx->buf = top; |
1143 | 0 | } |
1144 | | |
1145 | 54.0k | p_set_proto_depth(pinfo, proto_cbor, recursion_depth); |
1146 | 54.0k | return valid; |
1147 | 57.9k | } |
1148 | | |
1149 | | /** Internal dissector with context. |
1150 | | */ |
1151 | | static int |
1152 | 8.82k | dissect_cbor_ctx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
1153 | 8.82k | cbor_diag_ctx_t *ctx = data; |
1154 | 8.82k | cbor_diag_ctx_init(&ctx, pinfo->pool, false); |
1155 | | |
1156 | 8.82k | int offset = 0; |
1157 | 8.82k | proto_item *cbor_root; |
1158 | 8.82k | proto_tree *cbor_tree; |
1159 | | |
1160 | 8.82k | cbor_root = proto_tree_add_item(tree, proto_cbor, tvb, offset, -1, ENC_NA); |
1161 | 8.82k | cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor); |
1162 | | |
1163 | 8.82k | dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset, ctx); |
1164 | | |
1165 | 8.82k | proto_item_set_len(cbor_root, offset); |
1166 | 8.82k | return offset; |
1167 | 8.82k | } |
1168 | | |
1169 | | /** External dissector ignoring user data. |
1170 | | */ |
1171 | | static int |
1172 | 8.82k | dissect_cbor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1173 | 8.82k | return dissect_cbor_ctx(tvb, pinfo, tree, NULL); |
1174 | 8.82k | } |
1175 | | |
1176 | | static int |
1177 | 207 | dissect_cborseq_ctx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
1178 | 207 | cbor_diag_ctx_t *ctx = data; |
1179 | 207 | cbor_diag_ctx_init(&ctx, pinfo->pool, true); |
1180 | | |
1181 | 207 | int offset = 0; |
1182 | 207 | proto_item *cbor_root; |
1183 | 207 | proto_tree *cbor_tree; |
1184 | | |
1185 | 207 | cbor_root = proto_tree_add_item(tree, proto_cbor, tvb, offset, -1, ENC_NA); |
1186 | 207 | proto_item_append_text(cbor_root, " Sequence"); |
1187 | 207 | cbor_tree = proto_item_add_subtree(cbor_root, ett_cbor); |
1188 | | |
1189 | 207 | unsigned count = 0; |
1190 | 7.39k | while ((unsigned)offset < tvb_reported_length(tvb)) { |
1191 | 7.30k | if (ctx && (offset != 0)) { |
1192 | 0 | wmem_strbuf_append(ctx->buf, ", "); |
1193 | 0 | } |
1194 | | |
1195 | 7.30k | if (!dissect_cbor_main_type(tvb, pinfo, cbor_tree, &offset, ctx)) { |
1196 | 118 | break; |
1197 | 118 | } |
1198 | 7.18k | ++count; |
1199 | 7.18k | } |
1200 | | |
1201 | 207 | proto_item_set_generated( |
1202 | 207 | proto_tree_add_uint64(cbor_tree, hf_cbor_seq_len, tvb, 0, offset, count) |
1203 | 207 | ); |
1204 | | |
1205 | 207 | if (ctx && (cbor_display_diagnostic != CBOR_DIAG_NONE)) { |
1206 | 0 | const char *item_text = cbor_diag_ctx_get(ctx, CBOR_TYPE_ARRAY); |
1207 | | // show for top sequence |
1208 | 0 | proto_item_set_generated( |
1209 | 0 | proto_tree_add_string(cbor_tree, hf_cbor_diag_text, tvb, 0, offset, item_text) |
1210 | 0 | ); |
1211 | 0 | } |
1212 | | |
1213 | 207 | proto_item_set_len(cbor_root, offset); |
1214 | 207 | return offset; |
1215 | 207 | } |
1216 | | |
1217 | | /** External dissector ignoring user data. |
1218 | | */ |
1219 | | static int |
1220 | 207 | dissect_cborseq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1221 | 207 | return dissect_cborseq_ctx(tvb, pinfo, tree, NULL); |
1222 | 207 | } |
1223 | | |
1224 | | /** Internal heuristic dissector which uses user data context. |
1225 | | */ |
1226 | | static bool |
1227 | 0 | cbor_ctx_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
1228 | 0 | cbor_diag_ctx_t *ctx = data; |
1229 | | // do not create one if not already present |
1230 | |
|
1231 | 0 | int offset = 0; |
1232 | 0 | volatile int count = 0; |
1233 | |
|
1234 | 0 | while ((unsigned)offset < tvb_reported_length(tvb)) { |
1235 | 0 | volatile bool valid = false; |
1236 | 0 | TRY { |
1237 | 0 | valid = wscbor_skip_next_item(pinfo->pool, tvb, &offset); |
1238 | 0 | } |
1239 | 0 | CATCH_BOUNDS_AND_DISSECTOR_ERRORS {} |
1240 | 0 | ENDTRY; |
1241 | 0 | if (!valid) { |
1242 | | // A failure in any one item is a failure of the heuristic |
1243 | 0 | count = 0; |
1244 | 0 | break; |
1245 | 0 | } |
1246 | 0 | ++count; |
1247 | 0 | } |
1248 | | |
1249 | | // Anything went wrong with any part of the data |
1250 | 0 | if ((count == 0) || ((unsigned)offset != tvb_reported_length(tvb))) { |
1251 | 0 | return false; |
1252 | 0 | } |
1253 | | |
1254 | 0 | if (ctx) { |
1255 | 0 | wmem_strbuf_append(ctx->buf, "<<"); |
1256 | 0 | } |
1257 | |
|
1258 | 0 | if (count == 1) { |
1259 | 0 | dissect_cbor_ctx(tvb, pinfo, tree, ctx); |
1260 | 0 | } |
1261 | 0 | else { |
1262 | 0 | dissect_cborseq_ctx(tvb, pinfo, tree, ctx); |
1263 | 0 | } |
1264 | |
|
1265 | 0 | if (ctx) { |
1266 | 0 | wmem_strbuf_append(ctx->buf, ">>"); |
1267 | 0 | } |
1268 | |
|
1269 | 0 | return true; |
1270 | 0 | } |
1271 | | |
1272 | | bool |
1273 | 0 | cbor_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { |
1274 | 0 | return cbor_ctx_heuristic(tvb, pinfo, tree, NULL); |
1275 | 0 | } |
1276 | | |
1277 | | void |
1278 | | proto_register_cbor(void) |
1279 | 16 | { |
1280 | 16 | static hf_register_info hf[] = { |
1281 | 16 | { &hf_cbor_item_major_type, |
1282 | 16 | { "Major Type", "cbor.item.major_type", |
1283 | 16 | FT_UINT8, BASE_DEC, VALS(major_type_vals), 0xe0, |
1284 | 16 | NULL, HFILL } |
1285 | 16 | }, |
1286 | 16 | { &hf_cbor_item_integer_size, |
1287 | 16 | { "Size", "cbor.item.size", |
1288 | 16 | FT_UINT8, BASE_DEC, VALS(integer_size_vals), 0x1f, |
1289 | 16 | NULL, HFILL } |
1290 | 16 | }, |
1291 | 16 | { &hf_cbor_item_length_size, |
1292 | 16 | { "Size", "cbor.item.size", |
1293 | 16 | FT_UINT8, BASE_DEC, VALS(length_size_vals), 0x1f, |
1294 | 16 | NULL, HFILL } |
1295 | 16 | }, |
1296 | 16 | { &hf_cbor_item_length5, |
1297 | 16 | { "Length", "cbor.item.length5", |
1298 | 16 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
1299 | 16 | NULL, HFILL } |
1300 | 16 | }, |
1301 | 16 | { &hf_cbor_item_length, |
1302 | 16 | { "Length", "cbor.item.length", |
1303 | 16 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1304 | 16 | NULL, HFILL } |
1305 | 16 | }, |
1306 | 16 | { &hf_cbor_item_items5, |
1307 | 16 | { "Items", "cbor.item.items5", |
1308 | 16 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
1309 | 16 | NULL, HFILL } |
1310 | 16 | }, |
1311 | 16 | { &hf_cbor_item_items, |
1312 | 16 | { "Items", "cbor.item.items", |
1313 | 16 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1314 | 16 | NULL, HFILL } |
1315 | 16 | }, |
1316 | 16 | { &hf_cbor_item_pairs5, |
1317 | 16 | { "Pairs", "cbor.item.pairs", |
1318 | 16 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
1319 | 16 | NULL, HFILL } |
1320 | 16 | }, |
1321 | 16 | { &hf_cbor_item_pairs, |
1322 | 16 | { "Pairs", "cbor.item.pairs", |
1323 | 16 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1324 | 16 | NULL, HFILL } |
1325 | 16 | }, |
1326 | 16 | { &hf_cbor_item_float_simple_type, |
1327 | 16 | { "Type", "cbor.item.float_simple_type", |
1328 | 16 | FT_UINT8, BASE_DEC, VALS(float_simple_type_vals), 0x1f, |
1329 | 16 | NULL, HFILL } |
1330 | 16 | }, |
1331 | 16 | { &hf_cbor_item_unsigned_integer, |
1332 | 16 | { "Unsigned Integer", "cbor.item.unsigned_integer", |
1333 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1334 | 16 | NULL, HFILL } |
1335 | 16 | }, |
1336 | 16 | { &hf_cbor_item_negative_integer, |
1337 | 16 | { "Negative Integer", "cbor.item.negative_integer", |
1338 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1339 | 16 | NULL, HFILL } |
1340 | 16 | }, |
1341 | 16 | { &hf_cbor_item_text_string, |
1342 | 16 | { "Text String", "cbor.item.textstring", |
1343 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1344 | 16 | NULL, HFILL } |
1345 | 16 | }, |
1346 | 16 | { &hf_cbor_item_byte_string, |
1347 | 16 | { "Byte String", "cbor.item.bytestring", |
1348 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1349 | 16 | NULL, HFILL } |
1350 | 16 | }, |
1351 | 16 | { &hf_cbor_item_array, |
1352 | 16 | { "Array", "cbor.item.array", |
1353 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1354 | 16 | NULL, HFILL } |
1355 | 16 | }, |
1356 | 16 | { &hf_cbor_item_map, |
1357 | 16 | { "Map", "cbor.item.map", |
1358 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1359 | 16 | NULL, HFILL } |
1360 | 16 | }, |
1361 | 16 | { &hf_cbor_item_tag, |
1362 | 16 | { "Tag", "cbor.item.tag", |
1363 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1364 | 16 | NULL, HFILL } |
1365 | 16 | }, |
1366 | 16 | { &hf_cbor_item_float_simple, |
1367 | 16 | { "Floating-point or Simple", "cbor.item.float_or_simple", |
1368 | 16 | FT_NONE, BASE_NONE, NULL, 0x00, |
1369 | 16 | NULL, HFILL } |
1370 | 16 | }, |
1371 | 16 | { &hf_cbor_type_uint5, |
1372 | 16 | { "Unsigned Integer", "cbor.type.uint", |
1373 | 16 | FT_UINT8, BASE_DEC, NULL, 0x1f, |
1374 | 16 | NULL, HFILL } |
1375 | 16 | }, |
1376 | 16 | { &hf_cbor_type_uint, |
1377 | 16 | { "Unsigned Integer", "cbor.type.uint", |
1378 | 16 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1379 | 16 | NULL, HFILL } |
1380 | 16 | }, |
1381 | 16 | { &hf_cbor_type_nint, |
1382 | 16 | { "Negative Integer", "cbor.type.nint", |
1383 | 16 | FT_INT64, BASE_DEC, NULL, 0x00, |
1384 | 16 | NULL, HFILL } |
1385 | 16 | }, |
1386 | 16 | { &hf_cbor_type_byte_string, |
1387 | 16 | { "Byte String", "cbor.type.bytestring", |
1388 | 16 | FT_BYTES, BASE_NONE, NULL, 0x00, |
1389 | 16 | NULL, HFILL } |
1390 | 16 | }, |
1391 | 16 | { &hf_cbor_type_byte_string_indef, |
1392 | 16 | { "Byte String (indefinite length)", "cbor.type.bytestring.indef", |
1393 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
1394 | 16 | NULL, HFILL } |
1395 | 16 | }, |
1396 | 16 | { &hf_cbor_type_text_string, |
1397 | 16 | { "Text String", "cbor.type.textstring", |
1398 | 16 | FT_STRING, BASE_NONE, NULL, 0x00, |
1399 | 16 | NULL, HFILL } |
1400 | 16 | }, |
1401 | 16 | { &hf_cbor_type_text_string_indef, |
1402 | 16 | { "Text String (indefinite length)", "cbor.type.textstring.indef", |
1403 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
1404 | 16 | NULL, HFILL } |
1405 | 16 | }, |
1406 | 16 | { &hf_cbor_type_tag, |
1407 | 16 | { "Tag", "cbor.type.tag", |
1408 | 16 | FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(tag64_vals), 0x00, |
1409 | 16 | NULL, HFILL } |
1410 | 16 | }, |
1411 | 16 | { &hf_cbor_type_simple_data5, |
1412 | 16 | { "Simple data", "cbor.type.simple_data", |
1413 | 16 | FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x1f, |
1414 | 16 | NULL, HFILL } |
1415 | 16 | }, |
1416 | 16 | { &hf_cbor_type_simple_data8, |
1417 | 16 | { "Simple data", "cbor.type.simple_data", |
1418 | 16 | FT_UINT8, BASE_DEC, VALS(vals_simple_data), 0x00, |
1419 | 16 | NULL, HFILL } |
1420 | 16 | }, |
1421 | 16 | { &hf_cbor_type_float16, |
1422 | 16 | { "Float 16 Bit", "cbor.type.float16", |
1423 | 16 | FT_FLOAT, BASE_NONE, NULL, 0x00, |
1424 | 16 | NULL, HFILL } |
1425 | 16 | }, |
1426 | 16 | { &hf_cbor_type_float32, |
1427 | 16 | { "Float 32 Bit", "cbor.type.float32", |
1428 | 16 | FT_FLOAT, BASE_NONE, NULL, 0x00, |
1429 | 16 | NULL, HFILL } |
1430 | 16 | }, |
1431 | 16 | { &hf_cbor_type_float64, |
1432 | 16 | { "Float 64 Bit", "cbor.type.float64", |
1433 | 16 | FT_DOUBLE, BASE_NONE, NULL, 0x00, |
1434 | 16 | NULL, HFILL } |
1435 | 16 | }, |
1436 | 16 | { &hf_cbor_seq_len, |
1437 | 16 | { "Sequence length", "cbor.seq_len", |
1438 | 16 | FT_UINT64, BASE_DEC, NULL, 0x00, |
1439 | 16 | "Number of items in the sequence", HFILL } |
1440 | 16 | }, |
1441 | 16 | { &hf_cbor_diag_text, |
1442 | 16 | { "Diagnostic Notation", "cbor.diagnostic", |
1443 | 16 | FT_STRINGZ, BASE_NONE, NULL, 0x00, |
1444 | 16 | "CBOR extended diagnostic notation of preceding data", HFILL } |
1445 | 16 | }, |
1446 | 16 | }; |
1447 | | |
1448 | 16 | static int *ett[] = { |
1449 | 16 | &ett_cbor, |
1450 | 16 | &ett_cbor_type, |
1451 | 16 | &ett_cbor_unsigned_integer, |
1452 | 16 | &ett_cbor_negative_integer, |
1453 | 16 | &ett_cbor_byte_string, |
1454 | 16 | &ett_cbor_byte_string_indef, |
1455 | 16 | &ett_cbor_text_string, |
1456 | 16 | &ett_cbor_text_string_indef, |
1457 | 16 | &ett_cbor_array, |
1458 | 16 | &ett_cbor_map, |
1459 | 16 | &ett_cbor_tag, |
1460 | 16 | &ett_cbor_float_simple |
1461 | 16 | }; |
1462 | | |
1463 | 16 | static ei_register_info ei[] = { |
1464 | 16 | { &ei_cbor_invalid_minor_type, |
1465 | 16 | { "cbor.invalid_minor_type", PI_MALFORMED, PI_WARN, "Invalid minor type", EXPFILL }}, |
1466 | 16 | { &ei_cbor_invalid_element, |
1467 | 16 | { "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }}, |
1468 | 16 | { &ei_cbor_too_long_length, |
1469 | 16 | { "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }}, |
1470 | 16 | { &ei_cbor_max_recursion_depth_reached, |
1471 | 16 | { "cbor.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached. Dissection stopped.", EXPFILL }}, |
1472 | 16 | { &ei_cbor_embedded_bstr, |
1473 | 16 | { "cbor.embedded_bstr", PI_COMMENTS_GROUP, PI_COMMENT, "Heuristic dissection of data in a byte string", EXPFILL }}, |
1474 | 16 | }; |
1475 | | |
1476 | 16 | expert_module_t *expert_cbor; |
1477 | | |
1478 | 16 | proto_cbor = proto_register_protocol("Concise Binary Object Representation", "CBOR", "cbor"); |
1479 | 16 | proto_register_field_array(proto_cbor, hf, array_length(hf)); |
1480 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
1481 | 16 | expert_cbor = expert_register_protocol(proto_cbor); |
1482 | 16 | expert_register_field_array(expert_cbor, ei, array_length(ei)); |
1483 | | |
1484 | 16 | cbor_handle = register_dissector("cbor", dissect_cbor, proto_cbor); |
1485 | 16 | cborseq_handle = register_dissector_with_description("cborseq", "CBOR Sequence", dissect_cborseq, proto_cbor); |
1486 | | |
1487 | 16 | module_t *module_cbor = prefs_register_protocol(proto_cbor, NULL); |
1488 | 16 | prefs_register_bool_preference( |
1489 | 16 | module_cbor, |
1490 | 16 | "dissect_embeded_bstr", /* mispelt but best leave */ |
1491 | 16 | "Attempt heuristic dissection of byte strings", |
1492 | 16 | "If enabled, a heuristic dissection of byte string contents is performed.", |
1493 | 16 | &cbor_dissect_embeded_bstr |
1494 | 16 | ); |
1495 | 16 | prefs_register_enum_preference( |
1496 | 16 | module_cbor, |
1497 | 16 | "display_diagnostic", |
1498 | 16 | "Display CBOR diagnostic notation", |
1499 | 16 | "If enabled, a field is added to the topmost CBOR tree to display the data " |
1500 | 16 | "in CBOR extended diagnostic notation (EDN) text.", |
1501 | 16 | &cbor_display_diagnostic, |
1502 | 16 | cbor_display_diagnostic_choices, |
1503 | | false // radio buttons |
1504 | 16 | ); |
1505 | 16 | prefs_register_bool_preference( |
1506 | 16 | module_cbor, |
1507 | 16 | "diagnostic_bstr_text", |
1508 | 16 | "Diagnostic byte strings as text", |
1509 | 16 | "If enabled, a diagnostic display of byte string values which contain only " |
1510 | 16 | "UTF-8 text will be displayed as text without a quote prefix.", |
1511 | 16 | &cbor_diagnostic_bstr_text |
1512 | 16 | ); |
1513 | | |
1514 | 16 | cbor_bstr_heur = register_heur_dissector_list_with_description("cbor.bstr", "CBOR byte string content", proto_cbor); |
1515 | 16 | } |
1516 | | |
1517 | | void |
1518 | | proto_reg_handoff_cbor(void) |
1519 | 16 | { |
1520 | 16 | dissector_add_string("media_type", "application/cbor", cbor_handle); /* RFC 8949 */ |
1521 | 16 | dissector_add_string("media_type", "application/cwt", cbor_handle); /* RFC 8392 */ |
1522 | 16 | dissector_add_string("media_type", "application/cbor-seq", cborseq_handle); /* RFC 8742 */ |
1523 | | |
1524 | 16 | dissector_add_string("media_type.suffix", "cbor", cbor_handle); /* RFC 8949 */ |
1525 | 16 | dissector_add_string("media_type.suffix", "cbor-seq", cborseq_handle); /* RFC 8742 */ |
1526 | | |
1527 | 16 | heur_dissector_add("http", cbor_heuristic, "CBOR over HTTP", "cbor_http", proto_cbor, HEURISTIC_DISABLE); |
1528 | | // register for CBOR-in-CBOR heuristic |
1529 | 16 | heur_dissector_add("cbor.bstr", cbor_ctx_heuristic, "CBOR in CBOR byte string", "cbor_cbor", proto_cbor, HEURISTIC_ENABLE); |
1530 | 16 | } |
1531 | | |
1532 | | /* |
1533 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1534 | | * |
1535 | | * Local variables: |
1536 | | * c-basic-offset: 8 |
1537 | | * tab-width: 8 |
1538 | | * indent-tabs-mode: t |
1539 | | * End: |
1540 | | * |
1541 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1542 | | * :indentSize=8:tabSize=8:noTabs=false: |
1543 | | */ |