Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/disabled_protos.c
Line
Count
Source
1
/* disabled_protos.c
2
 * Declarations of routines for reading and writing protocols file that determine
3
 * enabling and disabling of protocols.
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
0
#define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
14
15
#include <stdio.h>
16
#include <string.h>
17
#include <errno.h>
18
19
#include <glib.h>
20
21
#include <wsutil/filesystem.h>
22
#include <epan/proto.h>
23
#include <epan/packet.h>
24
25
#include "disabled_protos.h"
26
#include <wsutil/file_util.h>
27
#include <wsutil/report_message.h>
28
#include <wsutil/wslog.h>
29
30
15
#define ENABLED_PROTOCOLS_FILE_NAME     "enabled_protos"
31
15
#define DISABLED_PROTOCOLS_FILE_NAME    "disabled_protos"
32
30
#define HEURISTICS_FILE_NAME            "heuristic_protos"
33
34
/*
35
 * Item in a list of disabled protocols.
36
 */
37
typedef struct {
38
  char *name;   /* protocol name */
39
} protocol_def;
40
41
/*
42
 * Item in a list of heuristic dissectors and their enabled state.
43
 */
44
typedef struct {
45
  char *name;   /* heuristic short name */
46
  bool enabled; /* heuristic enabled */
47
} heur_protocol_def;
48
49
/*
50
 * List of disabled protocols
51
 */
52
/* Use the same list for Global and personal dissabled protocols */
53
static GList *disabled_protos;
54
/*
55
 * List of enabled protocols (that are disabled by default)
56
 * Use the same list for Global and personal files
57
 */
58
static GList *enabled_protos;
59
/*
60
 * List of disabled heuristics
61
 * Use the same list for Global and personal files
62
 */
63
static GList *disabled_heuristics;
64
65
static bool unsaved_changes;
66
67
0
#define INIT_BUF_SIZE   128
68
69
bool
70
enabled_protos_unsaved_changes(void)
71
0
{
72
0
  return unsaved_changes;
73
0
}
74
75
static void
76
discard_existing_list (GList **flp)
77
30
{
78
30
  GList      *fl_ent;
79
30
  protocol_def *prot;
80
81
30
  if (*flp != NULL) {
82
0
    fl_ent = g_list_first(*flp);
83
0
    while (fl_ent != NULL) {
84
0
      prot = (protocol_def *) fl_ent->data;
85
0
      g_free(prot->name);
86
0
      g_free(prot);
87
0
      fl_ent = fl_ent->next;
88
0
    }
89
0
    g_list_free(*flp);
90
0
    *flp = NULL;
91
0
  }
92
30
}
93
94
static void
95
heur_discard_existing_list (GList **flp)
96
15
{
97
15
  GList      *fl_ent;
98
15
  heur_protocol_def *prot;
99
100
15
  if (*flp != NULL) {
101
0
    fl_ent = g_list_first(*flp);
102
0
    while (fl_ent != NULL) {
103
0
      prot = (heur_protocol_def *) fl_ent->data;
104
0
      g_free(prot->name);
105
0
      g_free(prot);
106
0
      fl_ent = fl_ent->next;
107
0
    }
108
0
    g_list_free(*flp);
109
0
    *flp = NULL;
110
0
  }
111
15
}
112
113
/*
114
 * Enable/Disable protocols as per the stored configuration
115
 */
116
static void
117
set_protos_list(GList *protos_list, bool enable)
118
30
{
119
30
  int i;
120
30
  GList *fl_ent;
121
30
  protocol_def *prot;
122
123
  /*
124
   * Assume no protocols disabled by default wants to be enabled
125
   */
126
30
  if (protos_list == NULL)
127
30
    return;
128
129
0
  fl_ent = g_list_first(protos_list);
130
131
0
  while (fl_ent != NULL) {
132
0
    prot = (protocol_def *) fl_ent->data;
133
0
    i = proto_get_id_by_filter_name(prot->name);
134
0
    if (i == -1) {
135
      /* XXX - complain here? */
136
0
    } else {
137
0
      if (proto_can_toggle_protocol(i))
138
0
        proto_set_decoding(i, enable);
139
0
    }
140
141
0
    fl_ent = fl_ent->next;
142
0
  }
143
0
}
144
145
/*
146
 * Write out a list of protocols based on condition
147
 *
148
 * On success, "*pref_path_return" is set to NULL.
149
 * On error, "*pref_path_return" is set to point to the pathname of
150
 * the file we tried to read - it should be freed by our caller -
151
 * and "*errno_return" is set to the error.
152
 */
153
static void
154
save_protos_list(char **pref_path_return, int *errno_return, const char* filename,
155
                const char* header_comment, const char* app_env_var_prefix, bool (*protocol_check)(protocol_t  *protocol))
156
0
{
157
0
  char        *ff_path, *ff_path_new;
158
0
  FILE        *ff;
159
0
  int          i;
160
0
  protocol_t  *protocol;
161
0
  void        *cookie;
162
0
  bool        first = true;
163
164
0
  *pref_path_return = NULL;     /* assume no error */
165
166
0
  ff_path = get_persconffile_path(filename, true, app_env_var_prefix);
167
168
  /* Write to "XXX.new", and rename if that succeeds.
169
     That means we don't trash the file if we fail to write it out
170
     completely. */
171
0
  ff_path_new = ws_strdup_printf("%s.new", ff_path);
172
173
0
  if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
174
0
    *pref_path_return = ff_path;
175
0
    *errno_return = errno;
176
0
    g_free(ff_path_new);
177
0
    return;
178
0
  }
179
180
  /* Iterate over all the protocols */
181
0
  for (i = proto_get_first_protocol(&cookie); i != -1;
182
0
       i = proto_get_next_protocol(&cookie)) {
183
184
0
    if (!proto_can_toggle_protocol(i)) {
185
0
      continue;
186
0
    }
187
188
0
    protocol = find_protocol_by_id(i);
189
0
    if (protocol_check(protocol) == false)
190
0
      continue;
191
192
0
    if (first) {
193
0
      if (header_comment != NULL) {
194
        /* Write out a comment explaining what the file is */
195
0
        fprintf(ff, "%s\n", header_comment);
196
0
      }
197
0
      first = false;
198
0
    }
199
200
    /* Write out the protocol name. */
201
0
    fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
202
0
  }
203
204
0
  if (fclose(ff) == EOF) {
205
0
    *pref_path_return = ff_path;
206
0
    *errno_return = errno;
207
0
    ws_unlink(ff_path_new);
208
0
    g_free(ff_path_new);
209
0
    return;
210
0
  }
211
212
#ifdef _WIN32
213
  /* ANSI C doesn't say whether "rename()" removes the target if it
214
     exists; the Win32 call to rename files doesn't do so, which I
215
     infer is the reason why the MSVC++ "rename()" doesn't do so.
216
     We must therefore remove the target file first, on Windows.
217
218
     XXX - ws_rename() should be ws_stdio_rename() on Windows,
219
     and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
220
     so it should remove the target if it exists, so this stuff
221
     shouldn't be necessary.  Perhaps it dates back to when we were
222
     calling rename(), with that being a wrapper around Microsoft's
223
     _rename(), which didn't remove the target. */
224
  if (ws_remove(ff_path) < 0 && errno != ENOENT) {
225
    /* It failed for some reason other than "it's not there"; if
226
       it's not there, we don't need to remove it, so we just
227
       drive on. */
228
    *pref_path_return = ff_path;
229
    *errno_return = errno;
230
    ws_unlink(ff_path_new);
231
    g_free(ff_path_new);
232
    return;
233
  }
234
#endif
235
236
0
  if (ws_rename(ff_path_new, ff_path) < 0) {
237
0
    *pref_path_return = ff_path;
238
0
    *errno_return = errno;
239
0
    ws_unlink(ff_path_new);
240
0
    g_free(ff_path_new);
241
0
    return;
242
0
  }
243
0
  g_free(ff_path_new);
244
0
  g_free(ff_path);
245
0
}
246
247
static int
248
read_protos_list_file(const char *ff_path, FILE *ff, GList **flp)
249
0
{
250
0
  protocol_def *prot;
251
0
  int         c;
252
0
  char       *prot_name;
253
0
  int         prot_name_len;
254
0
  int         prot_name_index;
255
0
  int         line = 1;
256
0
  bool        in_comment = false;
257
258
259
  /* Allocate the protocol name buffer. */
260
0
  prot_name_len = INIT_BUF_SIZE;
261
0
  prot_name = (char *)g_malloc(prot_name_len + 1);
262
263
0
  for (line = 1; ; line++) {
264
    /* Lines in a protocol file contain the "filter name" of a protocol
265
       to be enabled or disabled. */
266
267
    /* Skip over leading white space, if any. */
268
0
    while ((c = ws_getc_unlocked(ff)) != EOF && g_ascii_isspace(c)) {
269
0
      if (c == '\n') {
270
        /* Blank line. */
271
0
        continue;
272
0
      }
273
0
    }
274
275
0
    if (c == EOF) {
276
0
      if (ferror(ff))
277
0
        goto error;     /* I/O error */
278
0
      else
279
0
        break;  /* Nothing more to read */
280
0
    }
281
0
    ungetc(c, ff);      /* Unread the non-white-space character. */
282
283
    /* Get the name of the protocol. */
284
0
    prot_name_index = 0;
285
0
    for (;;) {
286
0
      c = ws_getc_unlocked(ff);
287
0
      if (c == EOF)
288
0
        break;  /* End of file, or I/O error */
289
0
      if (g_ascii_isspace(c))
290
0
        break;  /* Trailing white space, or end of line. */
291
0
      if (c == '#') {
292
0
        in_comment = true;
293
0
        break;  /* Start of comment, running to end of line. */
294
0
      }
295
      /* Add this character to the protocol name string. */
296
0
      if (prot_name_index >= prot_name_len) {
297
        /* protocol name buffer isn't long enough; double its length. */
298
0
        prot_name_len *= 2;
299
0
        prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
300
0
      }
301
0
      prot_name[prot_name_index] = c;
302
0
      prot_name_index++;
303
0
    }
304
305
0
    if (g_ascii_isspace(c) && c != '\n') {
306
      /* Skip over trailing white space. */
307
0
      while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
308
0
        ;
309
0
      if (c != EOF && c != '\n' && c != '#') {
310
        /* Non-white-space after the protocol name; warn about it,
311
           in case we come up with a reason to use it. */
312
0
        ws_warning("'%s' line %d has extra stuff after the protocol name.",
313
0
                  ff_path, line);
314
0
      }
315
0
    }
316
0
    if (c != EOF && c != '\n' && in_comment == true) {
317
      /* Skip to end of line. */
318
0
      while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n')
319
0
        ;
320
0
    }
321
322
0
    if (c == EOF) {
323
0
      if (ferror(ff))
324
0
        goto error;     /* I/O error */
325
0
      else {
326
        /* EOF, not error; no newline seen before EOF */
327
0
        ws_warning("'%s' line %d doesn't have a newline.", ff_path,
328
0
                  line);
329
0
      }
330
0
      break;    /* nothing more to read */
331
0
    }
332
333
0
    if (in_comment) {
334
0
      in_comment = false;
335
0
      continue;
336
0
    }
337
338
    /* Null-terminate the protocol name. */
339
0
    if (prot_name_index >= prot_name_len) {
340
      /* protocol name buffer isn't long enough; double its length. */
341
0
      prot_name_len *= 2;
342
0
      prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
343
0
    }
344
0
    prot_name[prot_name_index] = '\0';
345
346
    /* Add the new protocol to the list of disabled protocols */
347
0
    prot         = g_new(protocol_def, 1);
348
0
    prot->name   = g_strdup(prot_name);
349
0
    *flp = g_list_append(*flp, prot);
350
0
  }
351
0
  g_free(prot_name);
352
0
  return 0;
353
354
0
error:
355
0
  g_free(prot_name);
356
0
  return errno;
357
0
}
358
359
/*
360
 * Read in global and personal versions of a list of protocols.
361
 *
362
 * If we can open and read the global version, *gpath_return is set to
363
 * NULL.  Otherwise, *gpath_return is set to point to the pathname of
364
 * the file we tried to read - it should be freed by our caller - and
365
 * *gopen_errno_return is set to the error if an open failed or
366
 * *gread_errno_return is set to the error if a read failed.
367
 *
368
 * If we can open and read the personal version, *path_return is set to
369
 * NULL.  Otherwise, *path_return is set to point to the pathname of
370
 * the file we tried to read - it should be freed by our caller - and
371
 * *open_errno_return is set to the error if an open failed or
372
 * *read_errno_return is set to the error if a read failed.
373
 */
374
static void
375
read_protos_list(char **gpath_return, int *gopen_errno_return,
376
                 int *gread_errno_return,
377
                 char **path_return, int *open_errno_return,
378
                 int *read_errno_return,
379
                 const char* filename, const char* app_env_var_prefix,
380
                 GList **protos_list)
381
30
{
382
30
  int         err;
383
30
  char       *gff_path, *ff_path;
384
30
  FILE       *ff;
385
386
  /* Construct the pathname of the global disabled protocols file. */
387
30
  gff_path = get_datafile_path(filename, app_env_var_prefix);
388
389
  /* If we already have a list of protocols, discard it. */
390
30
  discard_existing_list (protos_list);
391
392
  /* Read the global disabled protocols file, if it exists. */
393
30
  *gpath_return = NULL;
394
30
  if ((ff = ws_fopen(gff_path, "r")) != NULL) {
395
    /* We succeeded in opening it; read it. */
396
0
    err = read_protos_list_file(gff_path, ff, protos_list);
397
0
    if (err != 0) {
398
      /* We had an error reading the file; return the errno and the
399
         pathname, so our caller can report the error. */
400
0
      *gopen_errno_return = 0;
401
0
      *gread_errno_return = err;
402
0
      *gpath_return = gff_path;
403
0
    } else
404
0
      g_free(gff_path);
405
0
    fclose(ff);
406
30
  } else {
407
    /* We failed to open it.  If we failed for some reason other than
408
       "it doesn't exist", return the errno and the pathname, so our
409
       caller can report the error. */
410
30
    if (errno != ENOENT) {
411
0
      *gopen_errno_return = errno;
412
0
      *gread_errno_return = 0;
413
0
      *gpath_return = gff_path;
414
0
    } else
415
30
      g_free(gff_path);
416
30
  }
417
418
  /* Construct the pathname of the user's disabled protocols file. */
419
30
  ff_path = get_persconffile_path(filename, true, app_env_var_prefix);
420
421
  /* Read the user's disabled protocols file, if it exists. */
422
30
  *path_return = NULL;
423
30
  if ((ff = ws_fopen(ff_path, "r")) != NULL) {
424
    /* We succeeded in opening it; read it. */
425
0
    err = read_protos_list_file(ff_path, ff, protos_list);
426
0
    if (err != 0) {
427
      /* We had an error reading the file; return the errno and the
428
         pathname, so our caller can report the error. */
429
0
      *open_errno_return = 0;
430
0
      *read_errno_return = err;
431
0
      *path_return = ff_path;
432
0
    } else
433
0
      g_free(ff_path);
434
0
    fclose(ff);
435
30
  } else {
436
    /* We failed to open it.  If we failed for some reason other than
437
       "it doesn't exist", return the errno and the pathname, so our
438
       caller can report the error. */
439
30
    if (errno != ENOENT) {
440
0
      *open_errno_return = errno;
441
0
      *read_errno_return = 0;
442
0
      *path_return = ff_path;
443
0
    } else
444
30
      g_free(ff_path);
445
30
  }
446
30
}
447
448
/************************************************************************
449
 * Disabling dissectors
450
 ************************************************************************/
451
452
/*
453
 * Disable a particular protocol by name
454
 */
455
bool
456
proto_disable_proto_by_name(const char *name)
457
108
{
458
108
  protocol_t *protocol;
459
108
  int proto_id;
460
461
108
  proto_id = proto_get_id_by_filter_name(name);
462
108
  if (proto_id >= 0 ) {
463
108
    protocol = find_protocol_by_id(proto_id);
464
108
    if (proto_is_protocol_enabled(protocol) == true) {
465
108
      if (proto_can_toggle_protocol(proto_id) == true) {
466
108
        unsaved_changes = true;
467
108
        proto_set_decoding(proto_id, false);
468
108
      }
469
108
    }
470
108
    return true;
471
108
  }
472
0
  else if (!strcmp(name, "ALL")) {
473
0
    unsaved_changes = true;
474
0
    proto_disable_all();
475
0
    return true;
476
0
  }
477
0
  else {
478
0
    return false;
479
0
  }
480
108
}
481
482
static bool disable_proto_list_check(protocol_t  *protocol)
483
0
{
484
0
    if (proto_is_protocol_enabled(protocol) == false)
485
0
      return true;
486
487
0
    return false;
488
0
}
489
490
/************************************************************************
491
 * Enabling dissectors (that are disabled by default)
492
 ************************************************************************/
493
494
bool
495
proto_enable_proto_by_name(const char *name)
496
0
{
497
0
  protocol_t *protocol;
498
0
  int proto_id;
499
500
0
  proto_id = proto_get_id_by_filter_name(name);
501
0
  if (proto_id >= 0 ) {
502
0
    protocol = find_protocol_by_id(proto_id);
503
0
    if ((proto_is_protocol_enabled(protocol) == false)) {
504
0
      if (proto_can_toggle_protocol(proto_id) == true) {
505
0
        unsaved_changes = true;
506
0
        proto_set_decoding(proto_id, true);
507
0
      }
508
0
    }
509
0
    return true;
510
0
  }
511
0
  else if (!strcmp(name, "ALL")) {
512
0
    unsaved_changes = true;
513
0
    proto_reenable_all();
514
0
    return true;
515
0
  }
516
0
  else {
517
0
    return false;
518
0
  }
519
0
}
520
521
static bool enable_proto_list_check(protocol_t  *protocol)
522
0
{
523
0
  if ((proto_is_protocol_enabled_by_default(protocol) == false) &&
524
0
      (proto_is_protocol_enabled(protocol) == true))
525
0
    return true;
526
527
0
  return false;
528
0
}
529
530
/************************************************************************
531
 * Heuristic dissectors
532
 ************************************************************************/
533
534
535
static void
536
set_disabled_heur_dissector_list(void)
537
15
{
538
15
  GList *fl_ent;
539
15
  heur_protocol_def *heur;
540
15
  heur_dtbl_entry_t* h;
541
542
15
  if (disabled_heuristics == NULL)
543
15
    return;
544
545
0
  fl_ent = g_list_first(disabled_heuristics);
546
547
0
  while (fl_ent != NULL) {
548
0
    heur = (heur_protocol_def *) fl_ent->data;
549
0
    h = find_heur_dissector_by_unique_short_name(heur->name);
550
0
    if (h != NULL) {
551
0
      h->enabled = heur->enabled;
552
0
    }
553
554
0
    fl_ent = fl_ent->next;
555
0
  }
556
557
0
}
558
559
static int
560
read_heur_dissector_list_file(const char *ff_path, FILE *ff, GList **flp)
561
0
{
562
0
  heur_protocol_def *heur;
563
0
  int         c;
564
0
  char       *heuristic_name;
565
0
  int         heuristic_name_len;
566
0
  int         name_index;
567
0
  bool        parse_enabled;
568
0
  bool        enabled;
569
0
  int         line = 1;
570
571
572
  /* Allocate the protocol name buffer. */
573
0
  heuristic_name_len = INIT_BUF_SIZE;
574
0
  heuristic_name = (char *)g_malloc(heuristic_name_len + 1);
575
576
0
  for (line = 1; ; line++) {
577
    /* Lines in a disabled protocol file contain the "filter name" of
578
       a protocol to be disabled. */
579
580
    /* Skip over leading white space, if any. */
581
0
    while ((c = ws_getc_unlocked(ff)) != EOF && g_ascii_isspace(c)) {
582
0
      if (c == '\n') {
583
        /* Blank line. */
584
0
        continue;
585
0
      }
586
0
    }
587
588
0
    if (c == EOF) {
589
0
      if (ferror(ff))
590
0
        goto error;     /* I/O error */
591
0
      else
592
0
        break;  /* Nothing more to read */
593
0
    }
594
0
    ungetc(c, ff);      /* Unread the non-white-space character. */
595
596
    /* Get the name of the protocol. */
597
0
    name_index = 0;
598
0
    enabled = false;
599
0
    parse_enabled = false;
600
0
    for (;;) {
601
0
      c = ws_getc_unlocked(ff);
602
0
      if (c == EOF)
603
0
        break;  /* End of file, or I/O error */
604
0
      if (g_ascii_isspace(c))
605
0
        break;  /* Trailing white space, or end of line. */
606
0
      if (c == ',') {/* Separator for enable/disable */
607
0
        parse_enabled = true;
608
0
        continue;
609
0
      }
610
0
      if (c == '#')
611
0
        break;  /* Start of comment, running to end of line. */
612
0
      if (parse_enabled) {
613
0
          enabled = ((c == '1') ? true : false);
614
0
          break;
615
0
      }
616
      /* Add this character to the protocol name string. */
617
0
      if (name_index >= heuristic_name_len) {
618
        /* protocol name buffer isn't long enough; double its length. */
619
0
        heuristic_name_len *= 2;
620
0
        heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
621
0
      }
622
0
      heuristic_name[name_index] = c;
623
0
      name_index++;
624
0
    }
625
626
0
    if (g_ascii_isspace(c) && c != '\n') {
627
      /* Skip over trailing white space. */
628
0
      while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
629
0
        ;
630
0
      if (c != EOF && c != '\n' && c != '#') {
631
        /* Non-white-space after the protocol name; warn about it,
632
           in case we come up with a reason to use it. */
633
0
        ws_warning("'%s' line %d has extra stuff after the protocol name.",
634
0
                  ff_path, line);
635
0
      }
636
0
    }
637
0
    if (c != EOF && c != '\n') {
638
      /* Skip to end of line. */
639
0
      while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n')
640
0
        ;
641
0
    }
642
643
0
    if (c == EOF) {
644
0
      if (ferror(ff))
645
0
        goto error;     /* I/O error */
646
0
      else {
647
        /* EOF, not error; no newline seen before EOF */
648
0
        ws_warning("'%s' line %d doesn't have a newline.", ff_path,
649
0
                  line);
650
0
      }
651
0
      break;    /* nothing more to read */
652
0
    }
653
654
    /* Null-terminate the protocol name. */
655
0
    if (name_index >= heuristic_name_len) {
656
      /* protocol name buffer isn't long enough; double its length. */
657
0
      heuristic_name_len *= 2;
658
0
      heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
659
0
    }
660
0
    heuristic_name[name_index] = '\0';
661
662
    /* Add the new protocol to the list of protocols */
663
0
    heur         = g_new(heur_protocol_def, 1);
664
0
    heur->name   = g_strdup(heuristic_name);
665
0
    heur->enabled = enabled;
666
0
    *flp = g_list_append(*flp, heur);
667
0
  }
668
0
  g_free(heuristic_name);
669
0
  return 0;
670
671
0
error:
672
0
  g_free(heuristic_name);
673
0
  return errno;
674
0
}
675
676
static void
677
read_heur_dissector_list(const char* app_env_var_prefix, char **gpath_return, int *gopen_errno_return,
678
       int *gread_errno_return,
679
       char **path_return, int *open_errno_return,
680
       int *read_errno_return)
681
15
{
682
15
  int         err;
683
15
  char       *gff_path, *ff_path;
684
15
  FILE       *ff;
685
686
  /* If we already have a list of protocols, discard it. */
687
15
  heur_discard_existing_list(&disabled_heuristics);
688
689
  /* Construct the pathname of the global disabled heuristic dissectors file. */
690
15
  gff_path = get_datafile_path(HEURISTICS_FILE_NAME, app_env_var_prefix);
691
692
  /* Read the global disabled protocols file, if it exists. */
693
15
  *gpath_return = NULL;
694
15
  if ((ff = ws_fopen(gff_path, "r")) != NULL) {
695
    /* We succeeded in opening it; read it. */
696
0
    err = read_heur_dissector_list_file(gff_path, ff,
697
0
                                        &disabled_heuristics);
698
0
    if (err != 0) {
699
      /* We had an error reading the file; return the errno and the
700
         pathname, so our caller can report the error. */
701
0
      *gopen_errno_return = 0;
702
0
      *gread_errno_return = err;
703
0
      *gpath_return = gff_path;
704
0
    } else
705
0
      g_free(gff_path);
706
0
    fclose(ff);
707
15
  } else {
708
    /* We failed to open it.  If we failed for some reason other than
709
       "it doesn't exist", return the errno and the pathname, so our
710
       caller can report the error. */
711
15
    if (errno != ENOENT) {
712
0
      *gopen_errno_return = errno;
713
0
      *gread_errno_return = 0;
714
0
      *gpath_return = gff_path;
715
0
    } else
716
15
      g_free(gff_path);
717
15
  }
718
719
  /* Construct the pathname of the user's disabled protocols file. */
720
15
  ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, true, app_env_var_prefix);
721
722
  /* Read the user's disabled protocols file, if it exists. */
723
15
  *path_return = NULL;
724
15
  if ((ff = ws_fopen(ff_path, "r")) != NULL) {
725
    /* We succeeded in opening it; read it. */
726
0
    err = read_heur_dissector_list_file(ff_path, ff, &disabled_heuristics);
727
0
    if (err != 0) {
728
      /* We had an error reading the file; return the errno and the
729
         pathname, so our caller can report the error. */
730
0
      *open_errno_return = 0;
731
0
      *read_errno_return = err;
732
0
      *path_return = ff_path;
733
0
    } else
734
0
      g_free(ff_path);
735
0
    fclose(ff);
736
15
  } else {
737
    /* We failed to open it.  If we failed for some reason other than
738
       "it doesn't exist", return the errno and the pathname, so our
739
       caller can report the error. */
740
15
    if (errno != ENOENT) {
741
0
      *open_errno_return = errno;
742
0
      *read_errno_return = 0;
743
0
      *path_return = ff_path;
744
0
    } else
745
15
      g_free(ff_path);
746
15
  }
747
15
}
748
749
static int
750
heur_compare(const void *a, const void *b)
751
0
{
752
0
  return strcmp(((const heur_dtbl_entry_t *)a)->short_name,
753
0
                ((const heur_dtbl_entry_t *)b)->short_name);
754
0
}
755
756
static void
757
write_heur_dissector(void *data, void *user_data)
758
0
{
759
0
  heur_dtbl_entry_t* dtbl_entry = (heur_dtbl_entry_t*)data;
760
0
  FILE *ff = (FILE*)user_data;
761
762
  /* Write out the heuristic short name and its enabled state */
763
0
  fprintf(ff, "%s,%d\n", dtbl_entry->short_name, dtbl_entry->enabled ? 1 : 0);
764
0
}
765
766
static void
767
sort_dissector_table_entries(const char *table_name _U_,
768
    heur_dtbl_entry_t *dtbl_entry, void *user_data)
769
0
{
770
0
  GSList **list = (GSList**)user_data;
771
0
  *list = g_slist_insert_sorted(*list, dtbl_entry, heur_compare);
772
0
}
773
774
static void
775
sort_heur_dissector_tables(const char *table_name, struct heur_dissector_list *list, void *w)
776
0
{
777
0
  if (list) {
778
0
    heur_dissector_table_foreach(table_name, sort_dissector_table_entries, w);
779
0
  }
780
0
}
781
782
static void
783
save_disabled_heur_dissector_list(const char* app_env_var_prefix, char **pref_path_return, int *errno_return)
784
0
{
785
0
  char        *ff_path, *ff_path_new;
786
0
  GSList      *sorted_heur_list = NULL;
787
0
  FILE        *ff;
788
789
0
  *pref_path_return = NULL;     /* assume no error */
790
791
0
  ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, true, app_env_var_prefix);
792
793
  /* Write to "XXX.new", and rename if that succeeds.
794
     That means we don't trash the file if we fail to write it out
795
     completely. */
796
0
  ff_path_new = ws_strdup_printf("%s.new", ff_path);
797
798
0
  if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
799
0
    *pref_path_return = ff_path;
800
0
    *errno_return = errno;
801
0
    g_free(ff_path_new);
802
0
    return;
803
0
  }
804
805
  /* Iterate over all the heuristic dissectors to sort them in alphabetical order by short name */
806
0
  dissector_all_heur_tables_foreach_table(sort_heur_dissector_tables, &sorted_heur_list, NULL);
807
808
  /* Write the list */
809
0
  g_slist_foreach(sorted_heur_list, write_heur_dissector, ff);
810
0
  g_slist_free(sorted_heur_list);
811
812
0
  if (fclose(ff) == EOF) {
813
0
    *pref_path_return = ff_path;
814
0
    *errno_return = errno;
815
0
    ws_unlink(ff_path_new);
816
0
    g_free(ff_path_new);
817
0
    return;
818
0
  }
819
820
#ifdef _WIN32
821
  /* ANSI C doesn't say whether "rename()" removes the target if it
822
     exists; the Win32 call to rename files doesn't do so, which I
823
     infer is the reason why the MSVC++ "rename()" doesn't do so.
824
     We must therefore remove the target file first, on Windows.
825
826
     XXX - ws_rename() should be ws_stdio_rename() on Windows,
827
     and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
828
     so it should remove the target if it exists, so this stuff
829
     shouldn't be necessary.  Perhaps it dates back to when we were
830
     calling rename(), with that being a wrapper around Microsoft's
831
     _rename(), which didn't remove the target. */
832
  if (ws_remove(ff_path) < 0 && errno != ENOENT) {
833
    /* It failed for some reason other than "it's not there"; if
834
       it's not there, we don't need to remove it, so we just
835
       drive on. */
836
    *pref_path_return = ff_path;
837
    *errno_return = errno;
838
    ws_unlink(ff_path_new);
839
    g_free(ff_path_new);
840
    return;
841
  }
842
#endif
843
844
0
  if (ws_rename(ff_path_new, ff_path) < 0) {
845
0
    *pref_path_return = ff_path;
846
0
    *errno_return = errno;
847
0
    ws_unlink(ff_path_new);
848
0
    g_free(ff_path_new);
849
0
    return;
850
0
  }
851
0
  g_free(ff_path_new);
852
0
  g_free(ff_path);
853
0
}
854
855
static bool
856
proto_set_heuristic_by_name(const char *name, bool enable)
857
0
{
858
0
  heur_dtbl_entry_t* heur = find_heur_dissector_by_unique_short_name(name);
859
0
  if (heur != NULL) {
860
0
      unsaved_changes |= (heur->enabled != enable);
861
0
      heur->enabled = enable;
862
0
      return true;
863
0
  } else {
864
0
      return false;
865
0
  }
866
0
}
867
868
bool
869
proto_enable_heuristic_by_name(const char *name)
870
0
{
871
0
  return proto_set_heuristic_by_name(name, true);
872
0
}
873
874
bool
875
proto_disable_heuristic_by_name(const char *name)
876
0
{
877
0
  return proto_set_heuristic_by_name(name, false);
878
0
}
879
880
static void
881
disabled_protos_free(void *p, void *user_data _U_)
882
0
{
883
0
  protocol_def* pd = (protocol_def*)p;
884
0
  g_free(pd->name);
885
0
  g_free(p);
886
0
}
887
888
/*
889
 * Read the files that enable and disable protocols and heuristic
890
 * dissectors.  Report errors through the UI.
891
 */
892
void
893
read_enabled_and_disabled_lists(const char* app_env_var_prefix)
894
15
{
895
15
  char *gpath, *path;
896
15
  int gopen_errno, gread_errno;
897
15
  int open_errno, read_errno;
898
899
  /*
900
   * Read the global and personal disabled protocols files.
901
   */
902
15
  read_protos_list(&gpath, &gopen_errno, &gread_errno,
903
15
                   &path, &open_errno, &read_errno,
904
15
                   DISABLED_PROTOCOLS_FILE_NAME, app_env_var_prefix,
905
15
                   &disabled_protos);
906
15
  if (gpath != NULL) {
907
0
    if (gopen_errno != 0) {
908
0
      report_warning("Could not open global disabled protocols file\n\"%s\": %s.",
909
0
                     gpath, g_strerror(gopen_errno));
910
0
    }
911
0
    if (gread_errno != 0) {
912
0
      report_warning("I/O error reading global disabled protocols file\n\"%s\": %s.",
913
0
                     gpath, g_strerror(gread_errno));
914
0
    }
915
0
    g_free(gpath);
916
0
    gpath = NULL;
917
0
  }
918
15
  if (path != NULL) {
919
0
    if (open_errno != 0) {
920
0
      report_warning("Could not open your disabled protocols file\n\"%s\": %s.",
921
0
                     path, g_strerror(open_errno));
922
0
    }
923
0
    if (read_errno != 0) {
924
0
      report_warning("I/O error reading your disabled protocols file\n\"%s\": %s.",
925
0
                     path, g_strerror(read_errno));
926
0
    }
927
0
    g_free(path);
928
0
    path = NULL;
929
0
  }
930
931
  /*
932
   * Read the global and personal enabled protocols files.
933
   */
934
15
  read_protos_list(&gpath, &gopen_errno, &gread_errno,
935
15
                   &path, &open_errno, &read_errno,
936
15
                   ENABLED_PROTOCOLS_FILE_NAME, app_env_var_prefix,
937
15
                   &enabled_protos);
938
15
  if (gpath != NULL) {
939
0
    if (gopen_errno != 0) {
940
0
      report_warning("Could not open global enabled protocols file\n\"%s\": %s.",
941
0
                     gpath, g_strerror(gopen_errno));
942
0
    }
943
0
    if (gread_errno != 0) {
944
0
      report_warning("I/O error reading global enabled protocols file\n\"%s\": %s.",
945
0
                     gpath, g_strerror(gread_errno));
946
0
    }
947
0
    g_free(gpath);
948
0
    gpath = NULL;
949
0
  }
950
15
  if (path != NULL) {
951
0
    if (open_errno != 0) {
952
0
      report_warning("Could not open your enabled protocols file\n\"%s\": %s.",
953
0
                     path, g_strerror(open_errno));
954
0
    }
955
0
    if (read_errno != 0) {
956
0
      report_warning("I/O error reading your enabled protocols file\n\"%s\": %s.",
957
0
                     path, g_strerror(read_errno));
958
0
    }
959
0
    g_free(path);
960
0
    path = NULL;
961
0
  }
962
963
  /*
964
   * Read the global and personal heuristic dissector list files.
965
   */
966
15
  read_heur_dissector_list(app_env_var_prefix, &gpath, &gopen_errno, &gread_errno,
967
15
                           &path, &open_errno, &read_errno);
968
15
  if (gpath != NULL) {
969
0
    if (gopen_errno != 0) {
970
0
      report_warning("Could not open global heuristic dissectors file\n\"%s\": %s.",
971
0
                     gpath, g_strerror(gopen_errno));
972
0
    }
973
0
    if (gread_errno != 0) {
974
0
      report_warning("I/O error reading global heuristic dissectors file\n\"%s\": %s.",
975
0
                     gpath, g_strerror(gread_errno));
976
0
    }
977
0
    g_free(gpath);
978
0
    gpath = NULL;
979
0
  }
980
15
  if (path != NULL) {
981
0
    if (open_errno != 0) {
982
0
      report_warning("Could not open your heuristic dissectors file\n\"%s\": %s.",
983
0
                     path, g_strerror(open_errno));
984
0
    }
985
0
    if (read_errno != 0) {
986
0
      report_warning("I/O error reading your heuristic dissectors file\n\"%s\": %s.",
987
0
                     path, g_strerror(read_errno));
988
0
    }
989
0
    g_free(path);
990
0
    path = NULL;
991
0
  }
992
993
  /*
994
   * Enable/disable protocols and heuristic dissectors as per the
995
   * contents of the files we just read.
996
   */
997
15
  set_protos_list(disabled_protos, false);
998
15
  set_protos_list(enabled_protos, true);
999
15
  set_disabled_heur_dissector_list();
1000
15
  unsaved_changes = false;
1001
15
}
1002
1003
/*
1004
 * Write out the lists of enabled and disabled protocols and heuristic
1005
 * dissectors to the corresponding files.  Report errors through the UI.
1006
 */
1007
void
1008
save_enabled_and_disabled_lists(const char* app_env_var_prefix)
1009
0
{
1010
0
  char *pf_dir_path;
1011
0
  char *pf_path;
1012
0
  int pf_save_errno;
1013
0
  bool ok = true;
1014
1015
  /* Create the directory that holds personal configuration files, if
1016
     necessary.  */
1017
0
  if (create_persconffile_dir(app_env_var_prefix, &pf_dir_path) == -1) {
1018
0
    report_failure("Can't create directory\n\"%s\"\nfor disabled protocols file: %s.",
1019
0
                   pf_dir_path, g_strerror(errno));
1020
0
    g_free(pf_dir_path);
1021
0
    return;
1022
0
  }
1023
1024
0
  save_protos_list(&pf_path, &pf_save_errno, DISABLED_PROTOCOLS_FILE_NAME,
1025
0
                   NULL, app_env_var_prefix, disable_proto_list_check);
1026
0
  if (pf_path != NULL) {
1027
0
    report_failure("Could not save to your disabled protocols file\n\"%s\": %s.",
1028
0
                   pf_path, g_strerror(pf_save_errno));
1029
0
    g_free(pf_path);
1030
0
    ok = false;
1031
0
  }
1032
1033
0
  save_protos_list(&pf_path, &pf_save_errno, ENABLED_PROTOCOLS_FILE_NAME,
1034
0
                   "#This file is for enabling protocols that are disabled by default",
1035
0
                   app_env_var_prefix,
1036
0
                   enable_proto_list_check);
1037
0
  if (pf_path != NULL) {
1038
0
    report_failure("Could not save to your enabled protocols file\n\"%s\": %s.",
1039
0
                   pf_path, g_strerror(pf_save_errno));
1040
0
    g_free(pf_path);
1041
0
    ok = false;
1042
0
  }
1043
1044
0
  save_disabled_heur_dissector_list(app_env_var_prefix, &pf_path, &pf_save_errno);
1045
0
  if (pf_path != NULL) {
1046
0
    report_failure("Could not save to your disabled heuristic protocol file\n\"%s\": %s.",
1047
0
                   pf_path, g_strerror(pf_save_errno));
1048
0
    g_free(pf_path);
1049
0
    ok = false;
1050
0
  }
1051
1052
0
  if (ok)
1053
0
    unsaved_changes = false;
1054
0
}
1055
1056
void
1057
cleanup_enabled_and_disabled_lists(void)
1058
0
{
1059
0
  g_list_foreach(disabled_heuristics, disabled_protos_free, NULL);
1060
0
  g_list_free(disabled_heuristics);
1061
  g_list_foreach(disabled_protos, disabled_protos_free, NULL);
1062
0
  g_list_free(disabled_protos);
1063
0
}
1064
1065
/*
1066
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1067
 *
1068
 * Local Variables:
1069
 * c-basic-offset: 2
1070
 * tab-width: 8
1071
 * indent-tabs-mode: nil
1072
 * End:
1073
 *
1074
 * ex: set shiftwidth=2 tabstop=8 expandtab:
1075
 * :indentSize=2:tabSize=8:noTabs=true:
1076
 */