Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-json.c
Line
Count
Source
1
/* packet-json.c
2
 * Routines for JSON dissection
3
 * References:
4
 *     RFC 4627: https://tools.ietf.org/html/rfc4627
5
 *     Website:  http://json.org/
6
 *
7
 * Copyright 2010, Jakub Zawadzki <darkjames-ws@darkjames.pl>
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/tvbparse.h>
19
#include <epan/proto_data.h>
20
#include <wsutil/wsjson.h>
21
22
#include <wsutil/str_util.h>
23
#include <wsutil/unicode-utils.h>
24
25
#include <wiretap/wtap.h>
26
27
#include "packet-media-type.h"
28
#include "packet-acdr.h"
29
#include "packet-json.h"
30
31
void proto_register_json(void);
32
void proto_reg_handoff_json(void);
33
static char* json_string_unescape(wmem_allocator_t *scope, const char *string, size_t *length_ptr);
34
static const char* get_json_string(wmem_allocator_t *scope, tvbparse_elem_t *tok, bool remove_quotes);
35
36
static dissector_handle_t json_handle;
37
static dissector_handle_t json_file_handle;
38
39
static int proto_json;
40
41
//Used to get AC DR proto data
42
static int proto_acdr;
43
44
static int hf_json_array;
45
static int hf_json_array_compact;
46
static int hf_json_array_item_compact;
47
static int hf_json_array_raw;
48
static int hf_json_array_item_raw;
49
static int hf_json_binary_data;
50
static int hf_json_ignored_leading_bytes;
51
static int hf_json_key;
52
static int hf_json_member;
53
static int hf_json_member_compact;
54
static int hf_json_member_raw;
55
static int hf_json_member_with_value;
56
static int hf_json_object;
57
static int hf_json_object_compact;
58
static int hf_json_object_raw;
59
static int hf_json_path;
60
static int hf_json_path_with_value;
61
static int hf_json_value_false;
62
static int hf_json_value_nan;
63
static int hf_json_value_null;
64
static int hf_json_value_number;
65
static int hf_json_value_string;
66
static int hf_json_value_true;
67
68
static int ett_json;
69
static int ett_json_array;
70
static int ett_json_object;
71
static int ett_json_member;
72
/* Define the trees for json compact form */
73
static int ett_json_compact;
74
static int ett_json_array_compact;
75
static int ett_json_object_compact;
76
static int ett_json_member_compact;
77
/* Define the trees for json raw form */
78
static int ett_json_raw;
79
static int ett_json_array_raw;
80
static int ett_json_object_raw;
81
static int ett_json_member_raw;
82
83
/* Preferences */
84
static bool json_compact;
85
86
static bool json_raw;
87
88
/* Determine whether to hide the tree of original form or root item of compact or raw form
89
 * based on the enabled status of compact_form and raw_form preferences.
90
 * If the preference auto_hide is true and compact_form or raw_form is true, hide the tree of
91
 * original form. If the preference auto_hide is true and only one of preference of
92
 * compact_form or raw_form is true, then hide the root item of compact or raw form and put
93
 * the content of compact or raw form under the tree item of JSON protocol directly.
94
 */
95
static bool auto_hide;
96
97
static bool ignore_leading_bytes;
98
99
static bool hide_extended_path_based_filtering;
100
101
static bool unescape_strings;
102
103
static tvbparse_wanted_t* want;
104
static tvbparse_wanted_t* want_ignore;
105
106
static dissector_handle_t text_lines_handle;
107
static dissector_handle_t falco_json_handle;
108
109
typedef enum {
110
  JSON_TOKEN_INVALID = -1,
111
  JSON_TOKEN_NUMBER = 0,
112
  JSON_TOKEN_STRING,
113
  JSON_TOKEN_FALSE,
114
  JSON_TOKEN_NULL,
115
  JSON_TOKEN_TRUE,
116
  JSON_TOKEN_NAN,
117
118
  /* not really tokens ... */
119
  JSON_OBJECT,
120
  JSON_ARRAY
121
122
} json_token_type_t;
123
124
typedef enum {
125
  JSON_MARK_TYPE_NONE = 0,
126
  JSON_MARK_TYPE_BEGIN_OBJECT,
127
  JSON_MARK_TYPE_END_OBJECT,
128
  JSON_MARK_TYPE_BEGIN_ARRAY,
129
  JSON_MARK_TYPE_END_ARRAY,
130
  JSON_MARK_TYPE_MEMBER_NAME,
131
  JSON_MARK_TYPE_VALUE
132
} json_mark_type_t;
133
134
typedef struct {
135
  wmem_stack_t *stack;
136
  wmem_stack_t *stack_compact; /* Used for compact json form only */
137
  wmem_stack_t *array_idx;  /* Used for compact json form only.
138
                  Top item: -3.
139
                  Object: < 0.
140
                  Array -1: no key, -2: has key  */
141
  wmem_stack_t* stack_path;
142
  packet_info* pinfo;
143
  wmem_stack_t* stack_raw; /* Used for raw json form only */
144
  json_mark_type_t prev_item_type_raw; /* Used for raw json form only */
145
  proto_item* prev_item_raw; /* Used for raw json form only */
146
} json_parser_data_t;
147
148
#define JSON_COMPACT_TOP_ITEM -3
149
0
#define JSON_COMPACT_OBJECT_WITH_KEY -2
150
#define JSON_COMPACT_OBJECT_WITHOUT_KEY -1
151
0
#define JSON_COMPACT_ARRAY 0
152
153
0
#define JSON_ARRAY_BEGIN(json_tvbparse_data) wmem_stack_push(json_tvbparse_data->array_idx, GINT_TO_POINTER(JSON_COMPACT_ARRAY))
154
0
#define JSON_OBJECT_BEGIN(json_tvbparse_data) wmem_stack_push(json_tvbparse_data->array_idx, GINT_TO_POINTER(JSON_COMPACT_OBJECT_WITHOUT_KEY))
155
0
#define JSON_ARRAY_OBJECT_END(json_tvbparse_data) wmem_stack_pop(json_tvbparse_data->array_idx)
156
0
#define JSON_INSIDE_ARRAY(idx) (idx >= JSON_COMPACT_ARRAY)
157
0
#define JSON_OBJECT_SET_HAS_KEY(idx) (idx == JSON_COMPACT_OBJECT_WITH_KEY)
158
159
6.88k
#define json_hide_original_tree() (auto_hide && (json_compact || json_raw))
160
0
#define json_hide_root_item() (auto_hide && ((json_compact && !json_raw) || (!json_compact && json_raw)))
161
162
static void
163
json_array_index_increment(json_parser_data_t *data)
164
0
{
165
0
  int idx = GPOINTER_TO_INT(wmem_stack_pop(data->array_idx));
166
0
  idx++;
167
0
  wmem_stack_push(data->array_idx, GINT_TO_POINTER(idx));
168
0
}
169
170
static void
171
json_object_add_key(json_parser_data_t *data)
172
0
{
173
0
  wmem_stack_pop(data->array_idx);
174
0
  wmem_stack_push(data->array_idx, GINT_TO_POINTER(JSON_COMPACT_OBJECT_WITH_KEY));
175
0
}
176
177
static char*
178
json_string_unescape(wmem_allocator_t *scope, const char *string, size_t *length_ptr)
179
0
{
180
0
  size_t read_index = 0;
181
0
  size_t string_length = strlen(string);
182
183
0
  wmem_strbuf_t* output_string_buffer = wmem_strbuf_new_sized(scope, string_length);
184
185
0
  while (true)
186
0
  {
187
    // Do not overflow input string
188
0
    if (!(read_index < string_length))
189
0
    {
190
0
      break;
191
0
    }
192
193
0
    uint8_t current_character = string[read_index];
194
195
    // character that IS NOT escaped
196
0
    if (current_character != '\\')
197
0
    {
198
      // A single UTF-8 character can cover more than one byte.
199
      // Copy all bytes that belong to that character and forward currend_index by that amount of bytes
200
0
      int utf8_character_length = ws_utf8_char_len(current_character);
201
202
0
      if (utf8_character_length <= 0)
203
0
      {
204
0
        break;
205
0
      }
206
207
0
      for (int i = 0; i < utf8_character_length; i++)
208
0
      {
209
        // Do not overflow input string
210
0
        if (!(read_index < string_length))
211
0
        {
212
0
          break;
213
0
        }
214
215
0
        current_character = string[read_index];
216
0
        read_index++;
217
0
        wmem_strbuf_append_c(output_string_buffer, current_character);
218
0
      }
219
0
    }
220
    // character that IS escaped
221
0
    else
222
0
    {
223
0
      read_index++;
224
225
      // Do not overflow input string
226
0
      if (!(read_index < string_length))
227
0
      {
228
0
        break;
229
0
      }
230
231
0
      current_character = string[read_index];
232
233
0
      if (current_character == '\"' || current_character == '\\' || current_character == '/')
234
0
      {
235
0
        read_index++;
236
0
        wmem_strbuf_append_c(output_string_buffer, current_character);
237
0
      }
238
0
      else if (current_character == 'b')
239
0
      {
240
0
        read_index++;
241
0
        wmem_strbuf_append_c(output_string_buffer, '\b');
242
0
      }
243
0
      else if (current_character == 'f')
244
0
      {
245
0
        read_index++;
246
0
        wmem_strbuf_append_c(output_string_buffer, '\f');
247
0
      }
248
0
      else if (current_character == 'n')
249
0
      {
250
0
        read_index++;
251
0
        wmem_strbuf_append_c(output_string_buffer, '\n');
252
0
      }
253
0
      else if (current_character == 'r')
254
0
      {
255
0
        read_index++;
256
0
        wmem_strbuf_append_c(output_string_buffer, '\r');
257
0
      }
258
0
      else if (current_character == 't')
259
0
      {
260
0
        read_index++;
261
0
        wmem_strbuf_append_c(output_string_buffer, '\t');
262
0
      }
263
0
      else if (current_character == 'u')
264
0
      {
265
0
        read_index++;
266
267
0
        uint32_t code_point = 0;
268
0
        bool is_valid_unicode_character = true;
269
270
0
        for (int i = 0; i < 4; i++)
271
0
        {
272
          // Do not overflow input string
273
0
          if (!(read_index < string_length))
274
0
          {
275
0
            is_valid_unicode_character = false;
276
0
            break;
277
0
          }
278
279
0
          current_character = string[read_index];
280
0
          read_index++;
281
282
0
          int nibble = ws_xton(current_character);
283
284
0
          if(nibble < 0)
285
0
          {
286
0
            is_valid_unicode_character = false;
287
0
            break;
288
0
          }
289
290
0
          code_point <<= 4;
291
0
          code_point |= nibble;
292
0
        }
293
294
0
        if ((IS_LEAD_SURROGATE(code_point)))
295
0
        {
296
          // Do not overflow input string
297
0
          if (!(read_index < string_length))
298
0
          {
299
0
            break;
300
0
          }
301
0
          current_character = string[read_index];
302
303
0
          if (current_character == '\\')
304
0
          {
305
0
            read_index++;
306
307
            // Do not overflow input string
308
0
            if (!(read_index < string_length))
309
0
            {
310
0
              break;
311
0
            }
312
313
0
            current_character = string[read_index];
314
0
            if (current_character == 'u') {
315
0
              uint16_t lead_surrogate = code_point;
316
0
              uint16_t trail_surrogate = 0;
317
318
0
              read_index++;
319
320
0
              for (int i = 0; i < 4; i++)
321
0
              {
322
                // Do not overflow input string
323
0
                if (!(read_index < string_length))
324
0
                {
325
0
                  is_valid_unicode_character = false;
326
0
                  break;
327
0
                }
328
329
0
                current_character = string[read_index];
330
0
                read_index++;
331
332
0
                int nibble = ws_xton(current_character);
333
334
0
                if (nibble < 0)
335
0
                {
336
0
                  is_valid_unicode_character = false;
337
0
                  break;
338
0
                }
339
340
0
                trail_surrogate <<= 4;
341
0
                trail_surrogate |= nibble;
342
0
              }
343
344
0
              if ((IS_TRAIL_SURROGATE(trail_surrogate)))
345
0
              {
346
0
                code_point = SURROGATE_VALUE(lead_surrogate, trail_surrogate);
347
0
              }
348
0
              else
349
0
              {
350
0
                is_valid_unicode_character = false;
351
0
              }
352
0
            }
353
0
            else
354
0
            {
355
0
              read_index++;
356
0
              is_valid_unicode_character = false;
357
0
            }
358
0
          }
359
0
          else
360
0
          {
361
0
            read_index++;
362
0
            is_valid_unicode_character = false;
363
0
          }
364
0
        }
365
0
        else if ((IS_TRAIL_SURROGATE(code_point)))
366
0
        {
367
0
          is_valid_unicode_character = false;
368
0
        }
369
370
0
        if (is_valid_unicode_character)
371
0
        {
372
0
          if (g_unichar_validate(code_point) && g_unichar_isprint(code_point))
373
0
          {
374
0
            char length_test_buffer[6];
375
0
            int utf8_character_length = (int)g_unichar_to_utf8(code_point, length_test_buffer);
376
377
0
            for (int i = 0; i < utf8_character_length; i++)
378
0
            {
379
0
              current_character = length_test_buffer[i];
380
0
              wmem_strbuf_append_c(output_string_buffer, current_character);
381
382
0
            }
383
0
          }
384
0
        }
385
0
        else
386
0
        {
387
0
          wmem_strbuf_append_unichar_repl(output_string_buffer);
388
0
        }
389
0
      }
390
0
      else
391
0
      {
392
        /* not valid by JSON grammar (tvbparse rules should not allow it) */
393
0
        DISSECTOR_ASSERT_NOT_REACHED();
394
0
      }
395
0
    }
396
0
  }
397
398
0
  if (length_ptr)
399
0
    *length_ptr = wmem_strbuf_get_len(output_string_buffer);
400
401
0
  return wmem_strbuf_finalize(output_string_buffer);
402
0
}
403
404
/* This functions allocates memory with packet_scope but the returned pointer
405
 * cannot be freed. */
406
static const char*
407
get_json_string(wmem_allocator_t *scope, tvbparse_elem_t *tok, bool remove_quotes)
408
6.44k
{
409
6.44k
  char *string;
410
6.44k
  size_t length;
411
412
6.44k
  string = (char*)tvb_get_string_enc(scope, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
413
414
6.44k
  if (unescape_strings) {
415
0
    string = json_string_unescape(scope, string, &length);
416
0
  }
417
6.44k
  else {
418
6.44k
    length = strlen(string);
419
6.44k
  }
420
421
6.44k
  if (remove_quotes) {
422
2.39k
    if (string[length - 1] == '"') {
423
2.08k
      string[length - 1] = '\0';
424
2.08k
    }
425
2.39k
    if (string[0] == '"') {
426
2.19k
      string += 1;
427
2.19k
    }
428
2.39k
  }
429
430
6.44k
  return string;
431
6.44k
}
432
433
GHashTable* json_header_fields_hash;
434
435
static proto_item*
436
json_key_lookup(proto_tree* tree, tvbparse_elem_t* tok, const char* key_str, packet_info* pinfo, bool use_compact)
437
3.58k
{
438
3.58k
  proto_item* ti;
439
3.58k
  int hf_id;
440
3.58k
  int offset, len;
441
442
3.58k
  json_data_decoder_t* json_data_decoder_rec = (json_data_decoder_t*)g_hash_table_lookup(json_header_fields_hash, key_str);
443
3.58k
  if (json_data_decoder_rec == NULL) {
444
3.58k
    return NULL;
445
3.58k
  }
446
447
0
  hf_id = *json_data_decoder_rec->hf_id;
448
0
  DISSECTOR_ASSERT(hf_id > 0);
449
450
0
  int proto_id = proto_registrar_is_protocol(hf_id) ? hf_id : proto_registrar_get_parent(hf_id);
451
0
  if (!proto_is_protocol_enabled(find_protocol_by_id(proto_id))) {
452
0
    return NULL;
453
0
  }
454
455
  /*
456
   * use_compact == true: "tok is the composed element of the member"
457
   *  This is only called from before_member when the value is a
458
   /  JSON_TOKEN_STRING.
459
   * use_compact == false: "tok is the composed element whose subelement is the value"
460
   *  For this, arrays with matching key are passed in before_array,
461
   *  strings are passed in after_value, and other types aren't passed in.
462
   */
463
0
  const tvbparse_elem_t* value_tok = tok;
464
0
  if (use_compact) {
465
    /* tok refers to the member ("key":"value")
466
     * tok->sub is the key string
467
     * tok->sub->next is the ':'
468
     * tok->sub->last is a set with one element
469
     * tok->sub->last->sub is the value
470
     */
471
0
    DISSECTOR_ASSERT(tok->sub);
472
0
    value_tok = tok->sub->last;
473
0
  }
474
  /* tok is a set with one element
475
   * tok->sub is the value
476
   */
477
0
  DISSECTOR_ASSERT(value_tok && value_tok->sub);
478
0
  value_tok = value_tok->sub;
479
480
0
  json_token_type_t value_id = (json_token_type_t)value_tok->id;
481
482
0
  offset = value_tok->offset;
483
0
  len = value_tok->len;
484
  /* Remove the quotation marks from strings (the decoder functions
485
   * apparently expect that.)
486
   */
487
0
  if (value_id == JSON_TOKEN_STRING && len >= 2) {
488
0
    offset += 1;
489
0
    len -= 2;
490
0
  }
491
  /* XXX - Every hf_id in packet-json_3gpp.c is a FT_STRING. Should other
492
   * types be supported (perhaps verified against the JSON token type?)
493
   * Should the encoding be ENC_UTF_8? Should the string be unescaped here?
494
   */
495
0
  ti = proto_tree_add_item(tree, hf_id, tok->tvb, offset, len, ENC_ASCII);
496
0
  if (json_data_decoder_rec->json_data_decoder) {
497
0
    (*json_data_decoder_rec->json_data_decoder)(value_tok->tvb, tree, pinfo, offset, len, key_str);
498
0
  }
499
0
  return ti;
500
501
0
}
502
503
static char*
504
join_strings(wmem_allocator_t *pool, const char* string_a, const char* string_b, char separator)
505
13.2k
{
506
13.2k
  if (string_a == NULL)
507
0
  {
508
0
    return NULL;
509
0
  }
510
13.2k
  if (string_b == NULL)
511
0
  {
512
0
    return NULL;
513
0
  }
514
515
13.2k
  wmem_strbuf_t* output_string_buffer = wmem_strbuf_new(pool, string_a);
516
517
13.2k
  if (separator != '\0')
518
13.2k
  {
519
13.2k
    wmem_strbuf_append_c(output_string_buffer, separator);
520
13.2k
  }
521
522
13.2k
  wmem_strbuf_append(output_string_buffer, string_b);
523
524
13.2k
  char* output_string = wmem_strbuf_finalize(output_string_buffer);
525
13.2k
  return output_string;
526
13.2k
}
527
528
static int
529
dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
530
2.62k
{
531
2.62k
  if (falco_json_handle) {
532
0
    int falco_len = call_dissector_only(falco_json_handle, tvb, pinfo, tree, NULL);
533
0
    if (falco_len > 0) {
534
0
      return falco_len;
535
0
    }
536
0
  }
537
538
2.62k
  proto_tree *json_tree = NULL;
539
2.62k
  proto_item *ti = NULL;
540
541
2.62k
  json_parser_data_t parser_data;
542
2.62k
  tvbparse_t *tt;
543
544
2.62k
  media_content_info_t *content_info;
545
2.62k
  const char *data_name;
546
2.62k
  int offset;
547
548
  /* Save pinfo*/
549
2.62k
  parser_data.pinfo = pinfo;
550
  /* JSON dissector can be called in a JSON native file or when transported
551
   * by another protocol; for a JSON file, this dissector is called by the
552
   * frame dissector, which only sets COL_PROTOCOL and COL_INFO if the
553
   * dissector it calls fails, so this will make the entry in the Protocol
554
   * column accordingly.
555
   */
556
2.62k
  col_append_sep_str(pinfo->cinfo, COL_PROTOCOL, "/", "JSON");
557
2.62k
  col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "JSON");
558
559
2.62k
  data_name = pinfo->match_string;
560
2.62k
  if (! (data_name && data_name[0])) {
561
    /*
562
     * No information from "match_string"
563
     */
564
2.62k
    content_info = (media_content_info_t *)data;
565
2.62k
    if (content_info == NULL) {
566
      /*
567
       * No information from dissector data
568
       */
569
2.62k
      data_name = NULL;
570
2.62k
    } else {
571
0
      data_name = content_info->media_str;
572
0
      if (! (data_name && data_name[0])) {
573
        /*
574
         * No information from dissector data
575
         */
576
0
        data_name = NULL;
577
0
      }
578
0
    }
579
2.62k
  }
580
581
2.62k
  if (tree) {
582
2.62k
    ti = proto_tree_add_item(tree, proto_json, tvb, 0, -1, ENC_NA);
583
2.62k
    json_tree = proto_item_add_subtree(ti, ett_json);
584
585
2.62k
    if (data_name)
586
0
      proto_item_append_text(ti, ": %s", data_name);
587
2.62k
  }
588
589
2.62k
  offset = 0;
590
  /* XXX*/
591
2.62k
  p_add_proto_data(pinfo->pool, pinfo, proto_json, 0, tvb);
592
593
2.62k
  parser_data.stack = wmem_stack_new(pinfo->pool);
594
2.62k
  wmem_stack_push(parser_data.stack, json_tree);
595
596
  // extended path based filtering
597
2.62k
  parser_data.stack_path = wmem_stack_new(pinfo->pool);
598
2.62k
  wmem_stack_push(parser_data.stack_path, "");
599
2.62k
  wmem_stack_push(parser_data.stack_path, "");
600
601
2.62k
  int buffer_length = (int)tvb_captured_length(tvb);
602
2.62k
  if (ignore_leading_bytes)
603
0
  {
604
0
    while (offset < buffer_length)
605
0
    {
606
0
      uint8_t current_character = tvb_get_uint8(tvb, offset);
607
0
      if (current_character == '[' || current_character == '{')
608
0
      {
609
0
        break;
610
0
      }
611
0
      offset++;
612
0
    }
613
614
0
    if(offset > 0)
615
0
    {
616
0
      proto_tree_add_item(json_tree ? json_tree : tree, hf_json_ignored_leading_bytes, tvb, 0, offset, ENC_ASCII);
617
0
    }
618
0
  }
619
620
2.62k
  if (json_compact) {
621
0
    proto_tree* json_tree_compact = json_hide_root_item() ? json_tree :
622
0
      proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_compact, NULL, "JSON compact form:");
623
624
0
    parser_data.stack_compact = wmem_stack_new(pinfo->pool);
625
0
    wmem_stack_push(parser_data.stack_compact, json_tree_compact);
626
627
0
    parser_data.array_idx = wmem_stack_new(pinfo->pool);
628
0
    wmem_stack_push(parser_data.array_idx, GINT_TO_POINTER(JSON_COMPACT_TOP_ITEM)); /* top element */
629
0
  }
630
631
2.62k
  if (json_raw) {
632
0
    proto_tree* json_tree_raw = json_hide_root_item() ? json_tree :
633
0
      proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_raw, NULL, "JSON raw form:");
634
635
0
    parser_data.stack_raw = wmem_stack_new(pinfo->pool);
636
0
    wmem_stack_push(parser_data.stack_raw, json_tree_raw);
637
638
0
    parser_data.prev_item_raw = NULL;
639
0
    parser_data.prev_item_type_raw = JSON_MARK_TYPE_NONE;
640
0
  }
641
642
2.62k
  tt = tvbparse_init(pinfo->pool, tvb, offset, buffer_length - offset, &parser_data, want_ignore);
643
644
  /* XXX, only one json in packet? */
645
5.38k
  while (tvbparse_get(tt, want))
646
2.76k
  { }
647
648
2.62k
  offset = tvbparse_curr_offset(tt);
649
650
2.62k
  proto_item_set_len(ti, offset);
651
652
  /* if we have some unparsed data, pass to data-text-lines dissector (?) */
653
2.62k
  if (tvb_reported_length_remaining(tvb, offset) > 0) {
654
1.94k
    tvbuff_t *next_tvb;
655
656
1.94k
    next_tvb = tvb_new_subset_remaining(tvb, offset);
657
658
1.94k
    call_dissector_with_data(text_lines_handle, next_tvb, pinfo, tree, data);
659
1.94k
  } else if (data_name) {
660
0
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name);
661
0
  }
662
663
2.62k
  return tvb_captured_length(tvb);
664
2.62k
}
665
666
/*
667
 * For dissecting JSON in a file; we don't get passed a media type.
668
 */
669
static int
670
dissect_json_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
671
0
{
672
0
  return dissect_json(tvb, pinfo, tree, NULL);
673
0
}
674
675
static void
676
646
before_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok) {
677
646
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
678
679
646
  proto_tree *tree = (proto_tree *)wmem_stack_peek(data->stack);
680
646
  proto_tree *subtree;
681
646
  proto_item *ti;
682
683
646
  ti = proto_tree_add_item(tree, hf_json_object, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
684
646
  if (json_hide_original_tree() && wmem_stack_count(data->stack) == 1) {
685
0
    proto_item_set_hidden(ti);
686
0
  }
687
688
646
  subtree = proto_item_add_subtree(ti, ett_json_object);
689
646
  wmem_stack_push(data->stack, subtree);
690
691
646
  if (json_compact) {
692
0
    proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
693
0
    proto_tree *subtree_compact;
694
0
    proto_item *ti_compact;
695
696
0
    int idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
697
698
0
    if (JSON_INSIDE_ARRAY(idx)) {
699
0
      ti_compact = proto_tree_add_none_format(tree_compact, hf_json_object_compact, tok->tvb, tok->offset, tok->len, "%d:", idx);
700
0
      subtree_compact = proto_item_add_subtree(ti_compact, ett_json_object_compact);
701
0
      json_array_index_increment(data);
702
0
    } else {
703
0
      subtree_compact = tree_compact;
704
0
    }
705
0
    wmem_stack_push(data->stack_compact, subtree_compact);
706
707
0
    JSON_OBJECT_BEGIN(data);
708
0
  }
709
710
646
  if (json_raw) {
711
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
712
0
    proto_tree* subtree_raw;
713
0
    proto_item* ti_raw;
714
715
0
    if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_END_OBJECT) {
716
0
      proto_item_append_text(data->prev_item_raw, ",");
717
0
    }
718
719
0
    if (data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
720
      /* this is an object value of an member, add the "{" just after the member name */
721
0
      ti_raw = data->prev_item_raw;
722
0
      proto_item_append_text(ti_raw, " {");
723
0
    } else {
724
      /* this object is either the top object or an element of an array, add the "{" as a single item */
725
0
      ti_raw = proto_tree_add_none_format(tree_raw, hf_json_object_raw, tok->tvb, tok->offset, tok->len, "{");
726
0
    }
727
728
0
    subtree_raw = proto_item_add_subtree(ti_raw, ett_json_object_raw);
729
0
    wmem_stack_push(data->stack_raw, subtree_raw);
730
731
0
    data->prev_item_raw = ti_raw;
732
0
    data->prev_item_type_raw = JSON_MARK_TYPE_BEGIN_OBJECT;
733
0
  }
734
646
}
735
736
static void
737
646
after_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t* tok) {
738
646
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
739
740
646
  wmem_stack_pop(data->stack);
741
742
646
  if (json_compact) {
743
0
    proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
744
0
    proto_item *parent_item = proto_tree_get_parent(tree_compact);
745
746
0
    int idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
747
748
0
    if (JSON_OBJECT_SET_HAS_KEY(idx))
749
0
      proto_item_append_text(parent_item, " {...}");
750
0
    else
751
0
      proto_item_append_text(parent_item, " {}");
752
753
0
    wmem_stack_pop(data->stack_compact);
754
755
0
    JSON_ARRAY_OBJECT_END(data);
756
0
  }
757
758
646
  if (json_raw) {
759
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
760
0
    proto_tree* parent_tree = proto_tree_get_parent_tree(tree_raw);
761
0
    proto_item* ti_raw;
762
0
    if (data->prev_item_type_raw == JSON_MARK_TYPE_BEGIN_OBJECT) { /* an empty object */
763
0
      ti_raw = data->prev_item_raw;
764
0
      proto_item_append_text(ti_raw, "}");
765
0
    } else {
766
0
      tvbparse_elem_t* tok_last = tok->sub->last;
767
0
      ti_raw = proto_tree_add_none_format(parent_tree, hf_json_object_raw, tok_last->tvb, tok_last->offset, tok_last->len, "}");
768
0
    }
769
0
    wmem_stack_pop(data->stack_raw);
770
771
0
    data->prev_item_raw = ti_raw;
772
0
    data->prev_item_type_raw = JSON_MARK_TYPE_END_OBJECT;
773
0
  }
774
646
}
775
776
static void
777
803
before_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok) {
778
803
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
779
780
803
  proto_tree *tree = (proto_tree *)wmem_stack_peek(data->stack);
781
803
  proto_tree *subtree;
782
803
  proto_item *ti;
783
784
803
  const char* key_string_without_quotation_marks = get_json_string(data->pinfo->pool, tok->sub, true);
785
786
803
  ti = proto_tree_add_string(tree, hf_json_member, tok->tvb, tok->offset, tok->len, key_string_without_quotation_marks);
787
788
803
  subtree = proto_item_add_subtree(ti, ett_json_member);
789
803
  wmem_stack_push(data->stack, subtree);
790
791
  // extended path based filtering
792
803
  char* last_key_string = (char*)wmem_stack_pop(data->stack_path);
793
803
  char* base_path = (char*)wmem_stack_pop(data->stack_path);
794
803
  wmem_stack_push(data->stack_path, base_path);
795
803
  wmem_stack_push(data->stack_path, last_key_string);
796
797
803
  char* path = join_strings(data->pinfo->pool, base_path, key_string_without_quotation_marks, '/');
798
803
  wmem_stack_push(data->stack_path, path);
799
  /* stack won't write/free pointer. */
800
803
  wmem_stack_push(data->stack_path, (void *)key_string_without_quotation_marks);
801
802
803
  if (json_compact) {
803
0
    proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
804
0
    proto_tree *subtree_compact;
805
0
    proto_item *ti_compact = NULL;
806
807
0
    tvbparse_elem_t *key_tok = tok->sub;
808
809
0
    if (key_tok && key_tok->id == JSON_TOKEN_STRING) {
810
0
      ti_compact = json_key_lookup(tree_compact, tok, key_string_without_quotation_marks, data->pinfo, true);
811
0
      if (!ti_compact) {
812
0
        ti_compact = proto_tree_add_none_format(tree_compact, hf_json_member_compact, tok->tvb, tok->offset, tok->len, "\"%s\":", key_string_without_quotation_marks);
813
0
      }
814
0
    } else {
815
0
      ti_compact = proto_tree_add_item(tree_compact, hf_json_member_compact, tok->tvb, tok->offset, tok->len, ENC_NA);
816
0
    }
817
818
0
    subtree_compact = proto_item_add_subtree(ti_compact, ett_json_member_compact);
819
0
    wmem_stack_push(data->stack_compact, subtree_compact);
820
0
  }
821
822
803
  if (json_raw) {
823
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
824
0
    proto_tree* subtree_raw;
825
0
    proto_item* ti_raw = NULL;
826
0
    tvbparse_elem_t* key_tok = tok->sub;
827
828
0
    if (data->prev_item_raw && data->prev_item_type_raw != JSON_MARK_TYPE_BEGIN_OBJECT && data->prev_item_type_raw != JSON_MARK_TYPE_BEGIN_ARRAY) {
829
0
      proto_item_append_text(data->prev_item_raw, ",");
830
0
    }
831
832
0
    if (key_tok && key_tok->id == JSON_TOKEN_STRING) {
833
0
      ti_raw = json_key_lookup(tree_raw, tok, key_string_without_quotation_marks, data->pinfo, true);
834
0
      if (!ti_raw) {
835
0
        ti_raw = proto_tree_add_none_format(tree_raw, hf_json_member_raw, tok->tvb, tok->offset, tok->len, "\"%s\":", key_string_without_quotation_marks);
836
0
      }
837
0
    } else {
838
0
      ti_raw = proto_tree_add_item(tree_raw, hf_json_member_raw, tok->tvb, tok->offset, tok->len, ENC_NA);
839
0
    }
840
841
0
    subtree_raw = proto_item_add_subtree(ti_raw, ett_json_member_raw);
842
0
    wmem_stack_push(data->stack_raw, subtree_raw);
843
844
0
    data->prev_item_raw = ti_raw;
845
0
    data->prev_item_type_raw = JSON_MARK_TYPE_MEMBER_NAME;
846
0
  }
847
803
}
848
849
static void
850
803
after_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok) {
851
803
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
852
853
803
  proto_tree *tree = (proto_tree *)wmem_stack_pop(data->stack);
854
855
803
  tvbparse_elem_t* key_tok = tok->sub;
856
803
  if (tree && key_tok && key_tok->id == JSON_TOKEN_STRING) {
857
858
803
    const char* key_string_without_quotation_marks = get_json_string(data->pinfo->pool, key_tok, true);
859
860
803
    proto_tree_add_string(tree, hf_json_key, key_tok->tvb, key_tok->offset, key_tok->len, key_string_without_quotation_marks);
861
803
  }
862
863
  // extended path based filtering
864
803
  wmem_stack_pop(data->stack_path); // Pop key
865
803
  char* path = (char*)wmem_stack_pop(data->stack_path);
866
803
  if (tree)
867
803
  {
868
803
    proto_item* path_item = proto_tree_add_string(tree, hf_json_path, tok->tvb, tok->offset, tok->len, path);
869
803
    proto_item_set_generated(path_item);
870
803
    if (hide_extended_path_based_filtering)
871
0
    {
872
0
      proto_item_set_hidden(path_item);
873
0
    }
874
803
  }
875
876
803
  if (json_compact) {
877
0
    wmem_stack_pop(data->stack_compact);
878
0
    json_object_add_key(data);
879
0
  }
880
881
803
  if (json_raw) {
882
0
    wmem_stack_pop(data->stack_raw);
883
0
  }
884
803
}
885
886
static void
887
2.79k
before_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok) {
888
2.79k
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
889
890
2.79k
  proto_tree *tree = (proto_tree *)wmem_stack_peek(data->stack);
891
2.79k
  proto_tree *subtree;
892
2.79k
  proto_item *ti;
893
894
2.79k
  ti = proto_tree_add_item(tree, hf_json_array, tok->tvb, tok->offset, tok->len, ENC_NA);
895
2.79k
  if (json_hide_original_tree() && wmem_stack_count(data->stack) == 1) {
896
0
    proto_item_set_hidden(ti);
897
0
  }
898
899
2.79k
  subtree = proto_item_add_subtree(ti, ett_json_array);
900
2.79k
  wmem_stack_push(data->stack, subtree);
901
902
  // extended path based filtering
903
2.79k
  char* last_key_string = (char*)wmem_stack_pop(data->stack_path);
904
2.79k
  char* base_path = (char*)wmem_stack_pop(data->stack_path);
905
2.79k
  wmem_stack_push(data->stack_path, base_path);
906
2.79k
  wmem_stack_push(data->stack_path, last_key_string);
907
908
2.79k
  char* path = join_strings(data->pinfo->pool, base_path, "[]", '/');
909
910
2.79k
  wmem_stack_push(data->stack_path, path);
911
2.79k
  wmem_stack_push(data->stack_path, "[]");
912
913
  // Try key_lookup
914
2.79k
  json_key_lookup(tree, tok, last_key_string, data->pinfo, false);
915
916
2.79k
  if (json_compact) {
917
0
    proto_tree* tree_compact = (proto_tree*)wmem_stack_peek(data->stack_compact);
918
0
    proto_tree* subtree_compact;
919
0
    proto_item* ti_compact;
920
921
0
    int idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
922
923
0
    if (JSON_INSIDE_ARRAY(idx)) {
924
0
      ti_compact = proto_tree_add_none_format(tree_compact, hf_json_array_compact, tok->tvb, tok->offset, tok->len, "%d:", idx);
925
0
      subtree_compact = proto_item_add_subtree(ti_compact, ett_json_array_compact);
926
0
      json_array_index_increment(data);
927
0
    } else {
928
0
      subtree_compact = tree_compact;
929
0
    }
930
0
    wmem_stack_push(data->stack_compact, subtree_compact);
931
932
0
    JSON_ARRAY_BEGIN(data);
933
0
  }
934
935
2.79k
  if (json_raw) {
936
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
937
0
    proto_tree* subtree_raw;
938
0
    proto_item* ti_raw;
939
940
0
    if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_END_ARRAY) {
941
0
      proto_item_append_text(data->prev_item_raw, ",");
942
0
    }
943
944
0
    if (data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
945
      /* this is an array value of an member, add the "[" just after the member name */
946
0
      ti_raw = data->prev_item_raw;
947
0
      proto_item_append_text(ti_raw, " [");
948
0
    } else {
949
      /* this array is either the top element or an element of an array, add the "[" as a single item */
950
0
      ti_raw = proto_tree_add_none_format(tree_raw, hf_json_array_raw, tok->tvb, tok->offset, tok->len, "[");
951
0
    }
952
953
0
    subtree_raw = proto_item_add_subtree(ti_raw, ett_json_array_raw);
954
0
    wmem_stack_push(data->stack_raw, subtree_raw);
955
956
0
    data->prev_item_raw = ti_raw;
957
0
    data->prev_item_type_raw = JSON_MARK_TYPE_BEGIN_ARRAY;
958
0
  }
959
2.79k
}
960
961
static void
962
2.79k
after_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t* tok) {
963
2.79k
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
964
965
2.79k
  wmem_stack_pop(data->stack);
966
967
  // extended path based filtering
968
2.79k
  wmem_stack_pop(data->stack_path); // Pop key
969
2.79k
  wmem_stack_pop(data->stack_path); // Pop path
970
971
2.79k
  if (json_compact) {
972
0
    proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
973
0
    proto_item *parent_item = proto_tree_get_parent(tree_compact);
974
975
0
    int idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
976
0
    if (idx == 0)
977
0
      proto_item_append_text(parent_item, " []");
978
0
    else
979
0
      proto_item_append_text(parent_item, " [...]");
980
981
0
    wmem_stack_pop(data->stack_compact);
982
983
0
    JSON_ARRAY_OBJECT_END(data);
984
0
  }
985
986
2.79k
  if (json_raw) {
987
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
988
0
    proto_tree* parent_tree = proto_tree_get_parent_tree(tree_raw);
989
0
    proto_item* ti_raw;
990
0
    if (data->prev_item_type_raw == JSON_MARK_TYPE_BEGIN_ARRAY) { /* an empty array */
991
0
      ti_raw = data->prev_item_raw;
992
0
      proto_item_append_text(ti_raw, "]");
993
0
    } else {
994
0
      tvbparse_elem_t* tok_last = tok->sub->last;
995
0
      ti_raw = proto_tree_add_none_format(parent_tree, hf_json_array_raw, tok_last->tvb, tok_last->offset, tok_last->len, "]");
996
0
    }
997
0
    wmem_stack_pop(data->stack_raw);
998
999
0
    data->prev_item_raw = ti_raw;
1000
0
    data->prev_item_type_raw = JSON_MARK_TYPE_END_ARRAY;
1001
0
  }
1002
2.79k
}
1003
1004
static void
1005
5.51k
after_value(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok) {
1006
5.51k
  json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
1007
1008
5.51k
  proto_tree *tree = (proto_tree *)wmem_stack_peek(data->stack);
1009
5.51k
  json_token_type_t value_id = tok->sub ? (json_token_type_t)tok->sub->id : JSON_TOKEN_INVALID;
1010
1011
5.51k
  if (!(value_id == JSON_TOKEN_STRING || value_id == JSON_TOKEN_NUMBER || value_id == JSON_TOKEN_FALSE
1012
1.26k
    || value_id == JSON_TOKEN_NULL || value_id == JSON_TOKEN_TRUE || value_id == JSON_TOKEN_NAN))
1013
676
  {
1014
676
    return;
1015
676
  }
1016
1017
  // extended path based filtering
1018
4.83k
  char* key_string = (char*)wmem_stack_pop(data->stack_path);
1019
4.83k
  char* path = (char*)wmem_stack_pop(data->stack_path);
1020
1021
4.83k
  const char* value_str = NULL;
1022
4.83k
  if (value_id == JSON_TOKEN_STRING && tok->len >= 2)
1023
791
  {
1024
791
    value_str = get_json_string(data->pinfo->pool, tok, true);
1025
791
  }
1026
4.04k
  else
1027
4.04k
  {
1028
4.04k
    value_str = get_json_string(data->pinfo->pool, tok, false);
1029
4.04k
  }
1030
1031
4.83k
  char* path_with_value = join_strings(data->pinfo->pool, path, value_str, ':');
1032
4.83k
  char* memeber_with_value = join_strings(data->pinfo->pool, key_string, value_str, ':');
1033
4.83k
  proto_item* path_with_value_item = proto_tree_add_string(tree, hf_json_path_with_value, tok->tvb, tok->offset, tok->len, path_with_value);
1034
4.83k
  proto_item* member_with_value_item = proto_tree_add_string(tree, hf_json_member_with_value, tok->tvb, tok->offset, tok->len, memeber_with_value);
1035
1036
4.83k
  proto_item_set_generated(path_with_value_item);
1037
4.83k
  proto_item_set_generated(member_with_value_item);
1038
1039
4.83k
  if (hide_extended_path_based_filtering)
1040
0
  {
1041
0
    proto_item_set_hidden(path_with_value_item);
1042
0
    proto_item_set_hidden(member_with_value_item);
1043
0
  }
1044
1045
4.83k
  wmem_stack_push(data->stack_path, path);
1046
4.83k
  wmem_stack_push(data->stack_path, key_string);
1047
1048
4.83k
  switch (value_id) {
1049
791
    case JSON_TOKEN_STRING:
1050
791
      if (tok->len >= 2) {
1051
        // Try key_lookup
1052
791
        proto_item *key_lookup = NULL;
1053
791
        key_lookup = json_key_lookup(tree, tok, key_string, data->pinfo, false);
1054
791
        if (!key_lookup) {
1055
791
          proto_tree_add_string(tree, hf_json_value_string, tok->tvb, tok->offset, tok->len, value_str);
1056
791
        }
1057
791
      }
1058
0
      else
1059
0
      {
1060
0
        proto_tree_add_item(tree, hf_json_value_string, tok->tvb, tok->offset, tok->len, ENC_ASCII | ENC_NA);
1061
0
      }
1062
1063
791
      break;
1064
1065
3.26k
    case JSON_TOKEN_NUMBER:
1066
3.26k
      proto_tree_add_double(tree, hf_json_value_number, tok->tvb, tok->offset, tok->len, g_ascii_strtod(value_str, NULL));
1067
1068
3.26k
      break;
1069
1070
194
    case JSON_TOKEN_FALSE:
1071
194
      proto_tree_add_item(tree, hf_json_value_false, tok->tvb, tok->offset, tok->len, ENC_NA);
1072
1073
194
      break;
1074
1075
194
    case JSON_TOKEN_NULL:
1076
194
      proto_tree_add_item(tree, hf_json_value_null, tok->tvb, tok->offset, tok->len, ENC_NA);
1077
1078
194
      break;
1079
1080
196
    case JSON_TOKEN_TRUE:
1081
196
      proto_tree_add_item(tree, hf_json_value_true, tok->tvb, tok->offset, tok->len, ENC_NA);
1082
1083
196
      break;
1084
1085
195
    case JSON_TOKEN_NAN:
1086
195
      proto_tree_add_item(tree, hf_json_value_nan, tok->tvb, tok->offset, tok->len, ENC_NA);
1087
1088
195
      break;
1089
1090
0
    default:
1091
0
      proto_tree_add_format_text(tree, tok->tvb, tok->offset, tok->len);
1092
0
      break;
1093
4.83k
  }
1094
1095
4.83k
  if (json_compact) {
1096
0
    proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
1097
1098
0
    int idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
1099
1100
0
    char *val_str = (char*)tvb_get_string_enc(data->pinfo->pool, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
1101
1102
0
    if (JSON_INSIDE_ARRAY(idx)) {
1103
0
      proto_tree_add_none_format(tree_compact, hf_json_array_item_compact, tok->tvb, tok->offset, tok->len, "%d: %s", idx, val_str);
1104
0
      json_array_index_increment(data);
1105
0
    } else {
1106
0
      proto_item *parent_item = proto_tree_get_parent(tree_compact);
1107
0
      proto_item_append_text(parent_item, " %s", val_str);
1108
0
    }
1109
0
  }
1110
1111
4.83k
  if (json_raw) {
1112
0
    proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
1113
0
    proto_item* ti_raw;
1114
0
    char* val_str = (char*)tvb_get_string_enc(data->pinfo->pool, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
1115
1116
0
    if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_VALUE) {
1117
0
      proto_item_append_text(data->prev_item_raw, ","); /* this value is an element of an array */
1118
0
    }
1119
1120
0
    if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
1121
0
      ti_raw = proto_tree_get_parent(tree_raw);
1122
0
      proto_item_append_text(ti_raw, " %s", val_str);
1123
0
    } else {
1124
0
      ti_raw = proto_tree_add_none_format(tree_raw, hf_json_array_item_raw, tok->tvb, tok->offset, tok->len, "%s", val_str);
1125
0
    }
1126
1127
0
    data->prev_item_raw = ti_raw;
1128
0
    data->prev_item_type_raw = JSON_MARK_TYPE_VALUE;
1129
0
  }
1130
4.83k
}
1131
1132
static void
1133
14
init_json_parser(void) {
1134
14
  static tvbparse_wanted_t _want_object;
1135
14
  static tvbparse_wanted_t _want_array;
1136
1137
14
  tvbparse_wanted_t *want_object, *want_array;
1138
14
  tvbparse_wanted_t *want_member;
1139
14
  tvbparse_wanted_t *want_string;
1140
14
  tvbparse_wanted_t *want_number, *want_int;
1141
14
  tvbparse_wanted_t *want_value;
1142
14
  tvbparse_wanted_t *want_value_separator;
1143
1144
14
#define tvbparse_optional(id, private_data, before_cb, after_cb, wanted) \
1145
84
  tvbparse_some(id, 0, 1, private_data, before_cb, after_cb, wanted)
1146
1147
14
  tvbparse_wanted_t *want_quot = tvbparse_char(-1,"\"",NULL,NULL,NULL);
1148
1149
14
  want_string = tvbparse_set_seq(JSON_TOKEN_STRING, NULL, NULL, NULL,
1150
14
      want_quot,
1151
14
      tvbparse_some(-1, 0, INT_MAX, NULL, NULL, NULL,
1152
14
        tvbparse_set_oneof(-1, NULL, NULL, NULL,
1153
14
          tvbparse_not_chars(-1, 0, 0, "\"" "\\", NULL, NULL, NULL), /* XXX, without invalid unicode characters */
1154
14
          tvbparse_set_seq(-1, NULL, NULL, NULL,
1155
14
            tvbparse_char(-1, "\\", NULL, NULL, NULL),
1156
14
            tvbparse_set_oneof(-1, NULL, NULL, NULL,
1157
14
              tvbparse_chars(-1, 0, 1, "\"" "\\" "/bfnrt", NULL, NULL, NULL),
1158
14
              tvbparse_set_seq(-1, NULL, NULL, NULL,
1159
14
                tvbparse_char(-1, "u", NULL, NULL, NULL),
1160
14
                tvbparse_chars(-1, 4, 4, "0123456789abcdefABCDEF", NULL, NULL, NULL),
1161
14
                NULL),
1162
14
              NULL),
1163
14
            NULL),
1164
14
          NULL)
1165
14
        ),
1166
14
      want_quot,
1167
14
      NULL);
1168
1169
14
  want_value_separator = tvbparse_char(-1, ",", NULL, NULL, NULL);
1170
1171
  /* int = zero / ( digit1-9 *DIGIT ) */
1172
14
  want_int = tvbparse_set_oneof(-1, NULL, NULL, NULL,
1173
14
      tvbparse_char(-1, "0", NULL, NULL, NULL),
1174
14
      tvbparse_set_seq(-1, NULL, NULL, NULL,
1175
14
        tvbparse_chars(-1, 1, 1, "123456789", NULL, NULL, NULL),
1176
14
        tvbparse_optional(-1, NULL, NULL, NULL, /* tvbparse_chars() don't respect 0 as min_len ;/ */
1177
14
          tvbparse_chars(-1, 0, 0, "0123456789", NULL, NULL, NULL)),
1178
14
        NULL),
1179
14
      NULL);
1180
1181
  /* number = [ minus ] int [ frac ] [ exp ] */
1182
14
  want_number = tvbparse_set_seq(JSON_TOKEN_NUMBER, NULL, NULL, NULL,
1183
14
      tvbparse_optional(-1, NULL, NULL, NULL, /* tvbparse_chars() don't respect 0 as min_len ;/ */
1184
14
        tvbparse_chars(-1, 0, 1, "-", NULL, NULL, NULL)),
1185
14
      want_int,
1186
      /* frac = decimal-point 1*DIGIT */
1187
14
      tvbparse_optional(-1, NULL, NULL, NULL,
1188
14
        tvbparse_set_seq(-1, NULL, NULL, NULL,
1189
14
          tvbparse_char(-1, ".", NULL, NULL, NULL),
1190
14
          tvbparse_chars(-1, 1, 0, "0123456789", NULL, NULL, NULL),
1191
14
          NULL)),
1192
      /* exp = e [ minus / plus ] 1*DIGIT */
1193
14
      tvbparse_optional(-1, NULL, NULL, NULL,
1194
14
        tvbparse_set_seq(-1, NULL, NULL, NULL,
1195
14
          tvbparse_char(-1, "eE", NULL, NULL, NULL),
1196
14
          tvbparse_optional(-1, NULL, NULL, NULL, /* tvbparse_chars() don't respect 0 as min_len ;/ */
1197
14
            tvbparse_chars(-1, 0, 1, "-+", NULL, NULL, NULL)),
1198
14
          tvbparse_chars(-1, 1, 0, "0123456789", NULL, NULL, NULL),
1199
14
          NULL)),
1200
14
      NULL);
1201
1202
  /* value = false / null / true / object / array / number / string */
1203
14
  want_value = tvbparse_set_oneof(-1, NULL, NULL, after_value,
1204
14
      tvbparse_string(JSON_TOKEN_FALSE, "false", NULL, NULL, NULL),
1205
14
      tvbparse_string(JSON_TOKEN_NULL, "null", NULL, NULL, NULL),
1206
14
      tvbparse_string(JSON_TOKEN_TRUE, "true", NULL, NULL, NULL),
1207
14
      tvbparse_string(JSON_TOKEN_NAN, "NaN", NULL, NULL, NULL),
1208
14
      &_want_object,
1209
14
      &_want_array,
1210
14
      want_number,
1211
14
      want_string,
1212
14
      NULL);
1213
1214
  /* array = begin-array [ value *( value-separator value ) ] end-array */
1215
14
  want_array = tvbparse_set_seq(JSON_ARRAY, NULL, before_array, after_array,
1216
14
      tvbparse_char(-1, "[", NULL, NULL, NULL),
1217
14
      tvbparse_optional(-1, NULL, NULL, NULL,
1218
14
        tvbparse_set_seq(-1, NULL, NULL, NULL,
1219
14
          want_value,
1220
14
          tvbparse_some(-1, 0, INT_MAX, NULL, NULL, NULL,
1221
14
            tvbparse_set_seq(-1, NULL, NULL, NULL,
1222
14
              want_value_separator,
1223
14
              want_value,
1224
14
              NULL)),
1225
14
          NULL)
1226
14
        ),
1227
14
      tvbparse_char(-1, "]", NULL, NULL, NULL),
1228
14
      NULL);
1229
14
  _want_array = *want_array;
1230
1231
  /* member = string name-separator value */
1232
14
  want_member = tvbparse_set_seq(-1, NULL, before_member, after_member,
1233
14
      want_string,
1234
14
      tvbparse_char(-1, ":", NULL, NULL, NULL),
1235
14
      want_value,
1236
14
      NULL);
1237
1238
  /* object = begin-object [ member *( value-separator member ) ] end-object */
1239
14
  want_object = tvbparse_set_seq(JSON_OBJECT, NULL, before_object, after_object,
1240
14
      tvbparse_char(-1, "{", NULL, NULL, NULL),
1241
14
      tvbparse_optional(-1, NULL, NULL, NULL,
1242
14
        tvbparse_set_seq(-1, NULL, NULL, NULL,
1243
14
          want_member,
1244
14
          tvbparse_some(-1, 0, INT_MAX, NULL, NULL, NULL,
1245
14
            tvbparse_set_seq(-1, NULL, NULL, NULL,
1246
14
              want_value_separator,
1247
14
              want_member,
1248
14
              NULL)),
1249
14
          NULL)
1250
14
        ),
1251
14
      tvbparse_char(-1, "}", NULL, NULL, NULL),
1252
14
      NULL);
1253
14
  _want_object = *want_object;
1254
1255
14
  want_ignore = tvbparse_chars(-1, 1, 0, " \t\r\n", NULL, NULL, NULL);
1256
1257
  /* JSON-text = object / array */
1258
14
  want = tvbparse_set_oneof(-1, NULL, NULL, NULL,
1259
14
    want_object,
1260
14
    want_array,
1261
    /* tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL, NULL, NULL), */
1262
14
    NULL);
1263
1264
  /* XXX, heur? */
1265
14
}
1266
1267
/* This function tries to understand if the payload is json or not */
1268
static bool
1269
dissect_json_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1270
0
{
1271
0
  unsigned len = tvb_captured_length(tvb);
1272
0
  const uint8_t* buf = tvb_get_string_enc(pinfo->pool, tvb, 0, len, ENC_ASCII);
1273
1274
0
  if (json_validate(buf, len) == false)
1275
0
    return false;
1276
1277
0
  return (dissect_json(tvb, pinfo, tree, data) != 0);
1278
0
}
1279
1280
/* This function tries to understand if the payload is sitting on top of AC DR */
1281
static bool
1282
dissect_json_acdr_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1283
0
{
1284
0
  unsigned acdr_prot = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_acdr, 0));
1285
0
  if (acdr_prot == ACDR_VoiceAI)
1286
0
    return dissect_json_heur(tvb, pinfo, tree, data);
1287
0
  return false;
1288
0
}
1289
1290
static void
1291
14
register_static_headers(void) {
1292
1293
14
  json_header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1294
1295
14
}
1296
1297
void
1298
proto_register_json(void)
1299
14
{
1300
14
  static hf_register_info hf[] = {
1301
14
    { &hf_json_array,
1302
14
      { "Array", "json.array",
1303
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1304
14
        "JSON array", HFILL }
1305
14
    },
1306
14
    { &hf_json_object,
1307
14
      { "Object", "json.object",
1308
14
        FT_STRING, BASE_NONE|BASE_NO_DISPLAY_VALUE, NULL, 0x00,
1309
14
        "JSON object", HFILL }
1310
14
    },
1311
14
    { &hf_json_member,
1312
14
      { "Member", "json.member",
1313
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1314
14
        "JSON object member", HFILL }
1315
14
    },
1316
14
    { &hf_json_key,
1317
14
      { "Key", "json.key",
1318
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1319
14
        NULL, HFILL }
1320
14
    },
1321
14
    { &hf_json_path,
1322
14
      { "Path", "json.path",
1323
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1324
14
        NULL, HFILL }
1325
14
    },
1326
14
    { &hf_json_path_with_value,
1327
14
      { "Path with value", "json.path_with_value",
1328
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1329
14
        NULL, HFILL }
1330
14
    },
1331
14
    { &hf_json_member_with_value,
1332
14
      { "Member with value", "json.member_with_value",
1333
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1334
14
        NULL, HFILL }
1335
14
    },
1336
14
    { &hf_json_value_string,
1337
14
      { /* FT_STRINGZ? */    "String value", "json.value.string",
1338
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1339
14
        "JSON string value", HFILL }
1340
14
    },
1341
14
    { &hf_json_value_number,
1342
14
      { "Number value", "json.value.number",
1343
14
        FT_DOUBLE, BASE_NONE, NULL, 0x00,
1344
14
        "JSON number value", HFILL }
1345
14
    },
1346
14
    { &hf_json_value_false,
1347
14
      { "False value", "json.value.false",
1348
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1349
14
        "JSON false value", HFILL }
1350
14
    },
1351
14
    { &hf_json_value_null,
1352
14
      { "Null value", "json.value.null",
1353
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1354
14
        "JSON null value", HFILL }
1355
14
    },
1356
14
    { &hf_json_value_true,
1357
14
      { "True value", "json.value.true",
1358
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1359
14
        "JSON true value", HFILL }
1360
14
    },
1361
14
    { &hf_json_value_nan,
1362
14
      { "NaN value", "json.value.nan",
1363
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1364
14
        "JSON NaN value", HFILL }
1365
14
    },
1366
14
    { &hf_json_array_compact,
1367
14
      { "Array compact", "json.array_compact",
1368
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1369
14
        "JSON array compact", HFILL }
1370
14
    },
1371
14
    { &hf_json_object_compact,
1372
14
      { "Object compact", "json.object_compact",
1373
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1374
14
        "JSON object compact", HFILL }
1375
14
    },
1376
14
    { &hf_json_member_compact,
1377
14
      { "Member compact", "json.member_compact",
1378
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1379
14
        "JSON member compact", HFILL }
1380
14
    },
1381
14
    { &hf_json_array_item_compact,
1382
14
      { "Array item compact", "json.array_item_compact",
1383
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1384
14
        "JSON array item compact", HFILL }
1385
14
    },
1386
14
    { &hf_json_binary_data,
1387
14
      { "Binary data", "json.binary_data",
1388
14
        FT_BYTES, BASE_NONE, NULL, 0x00,
1389
14
        "JSON binary data", HFILL }
1390
14
    },
1391
14
    { &hf_json_ignored_leading_bytes,
1392
14
      { "Ignored leading bytes", "json.ignored_leading_bytes",
1393
14
        FT_STRING, BASE_NONE, NULL, 0x00,
1394
14
        NULL, HFILL }
1395
14
    },
1396
14
    { &hf_json_array_raw,
1397
14
      { "Array raw", "json.array_raw",
1398
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1399
14
        "JSON array raw", HFILL }
1400
14
    },
1401
14
    { &hf_json_object_raw,
1402
14
      { "Object raw", "json.object_raw",
1403
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1404
14
        "JSON object raw", HFILL }
1405
14
    },
1406
14
    { &hf_json_member_raw,
1407
14
      { "Member raw", "json.member_raw",
1408
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1409
14
        "JSON member raw", HFILL }
1410
14
    },
1411
14
    { &hf_json_array_item_raw,
1412
14
      { "Array item raw", "json.array_item_raw",
1413
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1414
14
        "JSON array item raw", HFILL }
1415
14
    },
1416
1417
14
  };
1418
1419
14
  static int *ett[] = {
1420
14
    &ett_json,
1421
14
    &ett_json_array,
1422
14
    &ett_json_object,
1423
14
    &ett_json_member,
1424
14
    &ett_json_compact,
1425
14
    &ett_json_array_compact,
1426
14
    &ett_json_object_compact,
1427
14
    &ett_json_member_compact,
1428
14
    &ett_json_raw,
1429
14
    &ett_json_array_raw,
1430
14
    &ett_json_object_raw,
1431
14
    &ett_json_member_raw,
1432
14
  };
1433
1434
14
  module_t *json_module;
1435
1436
14
  proto_json = proto_register_protocol("JavaScript Object Notation", "JSON", "json");
1437
14
  proto_register_field_array(proto_json, hf, array_length(hf));
1438
14
  proto_register_subtree_array(ett, array_length(ett));
1439
1440
14
  json_handle = register_dissector("json", dissect_json, proto_json);
1441
14
  json_file_handle = register_dissector("json_file", dissect_json_file, proto_json);
1442
1443
14
  init_json_parser();
1444
1445
14
  json_module = prefs_register_protocol(proto_json, NULL);
1446
14
  prefs_register_bool_preference(json_module, "compact_form",
1447
14
    "Display JSON in compact form",
1448
14
    "Display JSON like in browsers devtool",
1449
14
    &json_compact);
1450
1451
14
  prefs_register_bool_preference(json_module, "raw_form",
1452
14
    "Display JSON in raw form",
1453
14
    "Display JSON like in vscode editor",
1454
14
    &json_raw);
1455
1456
14
  prefs_register_bool_preference(json_module, "auto_hide",
1457
14
    "Hide tree or root item automatically",
1458
14
    "Determine whether to hide the tree of original form or root item of compact or raw form"
1459
14
    " based on the enabled status of compact_form and raw_form preferences.",
1460
14
    &auto_hide);
1461
1462
14
  prefs_register_bool_preference(json_module, "ignore_leading_bytes",
1463
14
    "Ignore leading non JSON bytes",
1464
14
    "Leading bytes will be ignored until first '[' or '{' is found.",
1465
14
    &ignore_leading_bytes);
1466
1467
14
  prefs_register_bool_preference(json_module, "hide_extended_path_based_filtering",
1468
14
    "Hide extended path based filtering",
1469
14
    "Hide extended path based filtering",
1470
14
    &hide_extended_path_based_filtering);
1471
1472
14
  prefs_register_bool_preference(json_module, "unescape_strings",
1473
14
    "Replace character escapes with the escaped literal value",
1474
14
    "Replace character escapes with the escaped literal value",
1475
14
    &unescape_strings);
1476
1477
  /* Fill hash table with static headers */
1478
14
  register_static_headers();
1479
14
}
1480
1481
void
1482
proto_reg_handoff_json(void)
1483
14
{
1484
14
  heur_dissector_add("hpfeeds", dissect_json_heur, "JSON over HPFEEDS", "json_hpfeeds", proto_json, HEURISTIC_ENABLE);
1485
14
  heur_dissector_add("db-lsp", dissect_json_heur, "JSON over DB-LSP", "json_db_lsp", proto_json, HEURISTIC_ENABLE);
1486
14
  heur_dissector_add("udp", dissect_json_acdr_heur, "JSON over AC DR", "json_acdr", proto_json, HEURISTIC_ENABLE);
1487
14
  dissector_add_uint("wtap_encap", WTAP_ENCAP_JSON, json_file_handle);
1488
1489
14
  dissector_add_for_decode_as("udp.port", json_file_handle);
1490
1491
14
  dissector_add_string("media_type", "application/json", json_handle); /* RFC 4627 */
1492
14
  dissector_add_string("media_type", "application/senml+json", json_handle); /* RFC 8428 */
1493
14
  dissector_add_string("media_type", "application/sensml+json", json_handle); /* RFC 8428 */
1494
14
  dissector_add_string("media_type", "application/json-rpc", json_handle); /* JSON-RPC over HTTP */
1495
14
  dissector_add_string("media_type", "application/jsonrequest", json_handle); /* JSON-RPC over HTTP */
1496
14
  dissector_add_string("media_type", "application/dds-web+json", json_handle); /* DDS Web Integration Service over HTTP */
1497
14
  dissector_add_string("media_type", "application/vnd.oma.lwm2m+json", json_handle); /* LWM2M JSON over CoAP */
1498
14
  dissector_add_string("media_type", "application/problem+json", json_handle); /* RFC 7807 Problem Details for HTTP APIs*/
1499
14
  dissector_add_string("media_type", "application/merge-patch+json", json_handle); /* RFC 7386 HTTP PATCH methods (RFC 5789) */
1500
14
  dissector_add_string("media_type", "application/json-patch+json", json_handle); /* RFC 6902 JavaScript Object Notation (JSON) Patch */
1501
14
  dissector_add_string("media_type", "application/x-ndjson", json_handle);
1502
14
  dissector_add_string("media_type", "application/3gppHal+json", json_handle);
1503
14
  dissector_add_string("media_type.suffix", "json", json_handle);  /* RFC 6839 */
1504
14
  dissector_add_string("grpc_message_type", "application/grpc+json", json_handle);
1505
14
  dissector_add_uint_range_with_preference("tcp.port", "", json_file_handle); /* JSON-RPC over TCP */
1506
14
  dissector_add_uint_range_with_preference("udp.port", "", json_file_handle); /* JSON-RPC over UDP */
1507
1508
14
  text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_json);
1509
14
  falco_json_handle = find_dissector("falcojson");
1510
1511
14
  proto_acdr = proto_get_id_by_filter_name("acdr");
1512
14
}
1513
1514
/*
1515
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1516
 *
1517
 * Local variables:
1518
 * c-basic-offset: 8
1519
 * tab-width: 8
1520
 * indent-tabs-mode: t
1521
 * End:
1522
 *
1523
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1524
 * :indentSize=8:tabSize=8:noTabs=false:
1525
 */