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