Coverage Report

Created: 2025-07-02 06:28

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