Coverage Report

Created: 2025-06-13 07:05

/src/ndpi/fuzz/fuzz_ndpi_reader.c
Line
Count
Source (jump to first uncovered line)
1
#include "reader_util.h"
2
#include "ndpi_api.h"
3
#include "fuzz_common_code.h"
4
5
#include <pcap/pcap.h>
6
7
#include <errno.h>
8
#include <stdint.h>
9
#include <stdio.h>
10
11
#ifdef ENABLE_PCAP_L7_MUTATOR
12
#include "pl7m.h"
13
#endif
14
15
struct ndpi_workflow_prefs *prefs = NULL;
16
struct ndpi_workflow *workflow = NULL;
17
struct ndpi_global_context *g_ctx;
18
19
u_int8_t enable_payload_analyzer = 0;
20
u_int8_t enable_flow_stats = 1;
21
u_int8_t human_readeable_string_len = 5;
22
u_int8_t max_num_udp_dissected_pkts = 0, max_num_tcp_dissected_pkts = 0; /* Disable limits at application layer */;
23
int malloc_size_stats = 0;
24
FILE *fingerprint_fp = NULL;
25
bool do_load_lists = true;
26
char *addr_dump_path = NULL;
27
int monitoring_enabled = 1;
28
29
extern void ndpi_report_payload_stats(FILE *out);
30
31
#ifdef CRYPT_FORCE_NO_AESNI
32
extern int force_no_aesni;
33
#endif
34
35
#ifdef ENABLE_PCAP_L7_MUTATOR
36
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
37
0
                               size_t MaxSize, unsigned int Seed) {
38
0
  return pl7m_mutator(Data, Size, MaxSize, Seed);
39
0
}
40
#endif
41
42
7.58M
static void node_cleanup_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
43
7.58M
  struct ndpi_flow_info *flow = *(struct ndpi_flow_info **) node;
44
45
7.58M
  (void)depth;
46
7.58M
  (void)user_data;
47
48
7.58M
  if(flow == NULL) return;
49
50
7.58M
  if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
51
3.34M
    if((!flow->detection_completed) && flow->ndpi_flow) {
52
2.86M
      u_int8_t proto_guessed;
53
54
2.86M
      flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct,
55
2.86M
                                                      flow->ndpi_flow, &proto_guessed);
56
2.86M
    }
57
58
3.34M
    process_ndpi_collected_info(workflow, flow);
59
3.34M
  }
60
7.58M
}
61
62
186k
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
63
186k
  pcap_t * pkts;
64
186k
  const u_char *pkt;
65
186k
  struct pcap_pkthdr *header;
66
186k
  int r;
67
186k
  char errbuf[PCAP_ERRBUF_SIZE];
68
186k
  u_int i;
69
186k
  FILE *fd;
70
71
186k
  if (prefs == NULL) {
72
9
    prefs = calloc(sizeof(struct ndpi_workflow_prefs), 1);
73
9
    if (prefs == NULL) {
74
      //should not happen
75
0
      return 1;
76
0
    }
77
9
    prefs->decode_tunnels = 1;
78
9
    prefs->num_roots = 16;
79
9
    prefs->max_ndpi_flows = 16 * 1024 * 1024;
80
9
    prefs->quiet_mode = 0;
81
82
#ifdef ENABLE_MEM_ALLOC_FAILURES
83
    fuzz_set_alloc_callbacks();
84
#endif
85
86
9
    g_ctx = ndpi_global_init();
87
88
9
    workflow = ndpi_workflow_init(prefs, NULL /* pcap handler will be set later */, 0, ndpi_serialization_format_json, g_ctx, NULL);
89
90
9
    ndpi_workflow_set_flow_callback(workflow, NULL, NULL); /* No real callback */
91
92
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "log.level", "3");
93
9
    ndpi_set_config(workflow->ndpi_struct, "all", "log", "1");
94
95
9
    ndpi_load_domain_suffixes(workflow->ndpi_struct, "public_suffix_list.dat");
96
9
    ndpi_load_categories_dir(workflow->ndpi_struct, "./lists/");
97
9
    ndpi_load_protocols_file(workflow->ndpi_struct, "protos.txt");
98
9
    ndpi_load_categories_file(workflow->ndpi_struct, "categories.txt", NULL);
99
9
    ndpi_load_risk_domain_file(workflow->ndpi_struct, "risky_domains.txt");
100
9
    ndpi_load_malicious_ja4_file(workflow->ndpi_struct, "ja4_fingerprints.csv");
101
9
    ndpi_load_malicious_sha1_file(workflow->ndpi_struct, "sha1_fingerprints.csv");
102
103
#ifdef ENABLE_ONLY_SUBCLASSIFICATION
104
    ndpi_set_config(workflow->ndpi_struct, NULL, "filename.config", "only_classification.conf");
105
#else
106
107
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "packets_limit_per_flow", "255");
108
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "flow.track_payload", "1");
109
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "tcp_ack_payload_heuristic", "1");
110
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "fully_encrypted_heuristic", "1");
111
9
    ndpi_set_config(workflow->ndpi_struct, "dns", "subclassification", "1");
112
9
    ndpi_set_config(workflow->ndpi_struct, "tls", "application_blocks_tracking", "1");
113
#ifndef ENABLE_CONFIG2
114
    ndpi_set_config(workflow->ndpi_struct, "stun", "max_packets_extra_dissection", "40");
115
    ndpi_set_config(workflow->ndpi_struct, "zoom", "max_packets_extra_dissection", "255");
116
    ndpi_set_config(workflow->ndpi_struct, "rtp", "search_for_stun", "1");
117
#endif
118
9
    ndpi_set_config(workflow->ndpi_struct, "openvpn", "dpi.heuristics", "0x01");
119
9
    ndpi_set_config(workflow->ndpi_struct, "openvpn", "dpi.heuristics.num_messages", "20");
120
9
    ndpi_set_config(workflow->ndpi_struct, "tls", "metadata.ja4r_fingerprint", "1");
121
9
    ndpi_set_config(workflow->ndpi_struct, "tls", "dpi.heuristics", "0x07");
122
9
    ndpi_set_config(workflow->ndpi_struct, "tls", "dpi.heuristics.max_packets_extra_dissection", "40");
123
9
    ndpi_set_config(workflow->ndpi_struct, "stun", "monitoring", "1");
124
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "dpi.address_cache_size", "8192");
125
126
9
#ifdef ENABLE_CONFIG2
127
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "flow_risk.all.info", "0");
128
9
    ndpi_set_config(workflow->ndpi_struct, NULL, "metadata.tcp_fingerprint_format", "1");
129
9
#endif
130
131
9
#endif /* ENABLE_ONLY_SUBCLASSIFICATION */
132
133
9
    ndpi_finalize_initialization(workflow->ndpi_struct);
134
135
#ifdef ENABLE_FINGERPRINT_FP
136
    fingerprint_fp = stdout;
137
#endif
138
139
#ifdef CRYPT_FORCE_NO_AESNI
140
    force_no_aesni = 1;
141
#endif
142
143
#ifdef ENABLE_PAYLOAD_ANALYZER
144
   enable_payload_analyzer = 1;
145
#endif
146
9
  }
147
148
#ifdef ENABLE_MEM_ALLOC_FAILURES
149
  /* Don't fail memory allocations until init phase is done */
150
  fuzz_set_alloc_callbacks_and_seed(Size);
151
#endif
152
153
186k
  fd = buffer_to_file(Data, Size);
154
186k
  if (fd == NULL)
155
0
    return 0;
156
157
186k
  pkts = pcap_fopen_offline(fd, errbuf);
158
186k
  if (pkts == NULL) {
159
18
    fclose(fd);
160
18
    return 0;
161
18
  }
162
186k
  if (ndpi_is_datalink_supported(pcap_datalink(pkts)) == 0)
163
297
  {
164
    /* Do not fail if the datalink type is not supported (may happen often during fuzzing). */
165
297
    pcap_close(pkts);
166
297
    return 0;
167
297
  }
168
169
185k
  workflow->pcap_handle = pkts;
170
  /* Init flow tree */
171
185k
  workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *));
172
185k
  if(!workflow->ndpi_flows_root) {
173
0
    pcap_close(pkts);
174
0
    return 0;
175
0
  }
176
177
185k
  header = NULL;
178
185k
  r = pcap_next_ex(pkts, &header, &pkt);
179
10.3M
  while (r > 0) {
180
    /* allocate an exact size buffer to check overflows */
181
10.1M
    uint8_t *packet_checked = malloc(header->caplen);
182
183
10.1M
    if(packet_checked) {
184
10.1M
      ndpi_risk flow_risk;
185
10.1M
      struct ndpi_flow_info *flow = NULL; /* unused */
186
187
10.1M
      memcpy(packet_checked, pkt, header->caplen);
188
10.1M
      ndpi_workflow_process_packet(workflow, header, packet_checked, &flow_risk, &flow);
189
10.1M
      free(packet_checked);
190
10.1M
    }
191
192
10.1M
    r = pcap_next_ex(pkts, &header, &pkt);
193
10.1M
  }
194
185k
  pcap_close(pkts);
195
196
  /* Free flow trees */
197
3.15M
  for(i = 0; i < workflow->prefs.num_roots; i++) {
198
2.97M
    ndpi_twalk(workflow->ndpi_flows_root[i], node_cleanup_walker, NULL);
199
2.97M
    ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer);
200
2.97M
  }
201
185k
  ndpi_free(workflow->ndpi_flows_root);
202
  /* Free payload analyzer data */
203
185k
  if(enable_payload_analyzer)
204
16.2k
    ndpi_report_payload_stats(stdout);
205
206
#ifdef ENABLE_PAYLOAD_ANALYZER
207
  ndpi_update_params(SPLT_PARAM_TYPE, "splt_param.txt");
208
  ndpi_update_params(BD_PARAM_TYPE, "bd_param.txt");
209
  ndpi_update_params(2, ""); /* invalid */
210
#endif
211
212
185k
  return 0;
213
185k
}