/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 | | struct ndpi_workflow_prefs *prefs = NULL; |
12 | | struct ndpi_workflow *workflow = NULL; |
13 | | |
14 | | int nDPI_LogLevel = 0; |
15 | | char *_debug_protocols = NULL; |
16 | | u_int32_t current_ndpi_memory = 0, max_ndpi_memory = 0; |
17 | | u_int8_t enable_protocol_guess = 1, enable_payload_analyzer = 0; |
18 | | u_int8_t enable_flow_stats = 1; |
19 | | u_int8_t human_readeable_string_len = 5; |
20 | | u_int8_t max_num_udp_dissected_pkts = 16 /* 8 is enough for most protocols, Signal requires more */, max_num_tcp_dissected_pkts = 80 /* due to telnet */; |
21 | | ndpi_init_prefs init_prefs = ndpi_track_flow_payload | ndpi_enable_ja3_plus | ndpi_enable_tcp_ack_payload_heuristic; |
22 | | int enable_malloc_bins = 1; |
23 | | int malloc_size_stats = 0; |
24 | | int max_malloc_bins = 14; |
25 | | struct ndpi_bin malloc_bins; /* unused */ |
26 | | |
27 | | extern void ndpi_report_payload_stats(FILE *out); |
28 | | |
29 | | #ifdef CRYPT_FORCE_NO_AESNI |
30 | | extern int force_no_aesni; |
31 | | #endif |
32 | | |
33 | 74.4k | FILE *bufferToFile(const uint8_t *Data, size_t Size) { |
34 | 74.4k | FILE *fd; |
35 | 74.4k | fd = tmpfile(); |
36 | 74.4k | if (fd == NULL) { |
37 | 0 | perror("Error tmpfile"); |
38 | 0 | return NULL; |
39 | 0 | } |
40 | 74.4k | if (fwrite (Data, 1, Size, fd) != Size) { |
41 | 0 | perror("Error fwrite"); |
42 | 0 | fclose(fd); |
43 | 0 | return NULL; |
44 | 0 | } |
45 | 74.4k | rewind(fd); |
46 | 74.4k | return fd; |
47 | 74.4k | } |
48 | | |
49 | 74.4k | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
50 | 74.4k | pcap_t * pkts; |
51 | 74.4k | const u_char *pkt; |
52 | 74.4k | struct pcap_pkthdr *header; |
53 | 74.4k | int r; |
54 | 74.4k | char errbuf[PCAP_ERRBUF_SIZE]; |
55 | 74.4k | NDPI_PROTOCOL_BITMASK all; |
56 | 74.4k | u_int i; |
57 | 74.4k | FILE *fd; |
58 | | |
59 | 74.4k | if (prefs == NULL) { |
60 | 3 | prefs = calloc(sizeof(struct ndpi_workflow_prefs), 1); |
61 | 3 | if (prefs == NULL) { |
62 | | //should not happen |
63 | 0 | return 1; |
64 | 0 | } |
65 | 3 | prefs->decode_tunnels = 1; |
66 | 3 | prefs->num_roots = 16; |
67 | 3 | prefs->max_ndpi_flows = 16 * 1024 * 1024; |
68 | 3 | prefs->quiet_mode = 0; |
69 | | |
70 | 3 | #ifdef ENABLE_MEM_ALLOC_FAILURES |
71 | 3 | fuzz_set_alloc_callbacks(); |
72 | 3 | #endif |
73 | | |
74 | 3 | workflow = ndpi_workflow_init(prefs, NULL /* pcap handler will be set later */, 0, ndpi_serialization_format_json); |
75 | | // enable all protocols |
76 | 3 | NDPI_BITMASK_SET_ALL(all); |
77 | 3 | ndpi_set_protocol_detection_bitmask2(workflow->ndpi_struct, &all); |
78 | | |
79 | 3 | ndpi_load_protocols_file(workflow->ndpi_struct, "protos.txt"); |
80 | 3 | ndpi_load_categories_file(workflow->ndpi_struct, "categories.txt", NULL); |
81 | 3 | ndpi_load_risk_domain_file(workflow->ndpi_struct, "risky_domains.txt"); |
82 | 3 | ndpi_load_malicious_ja3_file(workflow->ndpi_struct, "ja3_fingerprints.csv"); |
83 | 3 | ndpi_load_malicious_sha1_file(workflow->ndpi_struct, "sha1_fingerprints.csv"); |
84 | | |
85 | 3 | memset(workflow->stats.protocol_counter, 0, |
86 | 3 | sizeof(workflow->stats.protocol_counter)); |
87 | 3 | memset(workflow->stats.protocol_counter_bytes, 0, |
88 | 3 | sizeof(workflow->stats.protocol_counter_bytes)); |
89 | 3 | memset(workflow->stats.protocol_flows, 0, |
90 | 3 | sizeof(workflow->stats.protocol_flows)); |
91 | 3 | ndpi_finalize_initialization(workflow->ndpi_struct); |
92 | | |
93 | 3 | #ifdef CRYPT_FORCE_NO_AESNI |
94 | 3 | force_no_aesni = 1; |
95 | 3 | #endif |
96 | | |
97 | | #ifdef ENABLE_PAYLOAD_ANALYZER |
98 | | enable_payload_analyzer = 1; |
99 | | #endif |
100 | 3 | } |
101 | | |
102 | 74.4k | #ifdef ENABLE_MEM_ALLOC_FAILURES |
103 | | /* Don't fail memory allocations until init phase is done */ |
104 | 74.4k | fuzz_set_alloc_seed(Size); |
105 | 74.4k | #endif |
106 | | |
107 | 74.4k | fd = bufferToFile(Data, Size); |
108 | 74.4k | if (fd == NULL) |
109 | 0 | return 0; |
110 | | |
111 | 74.4k | pkts = pcap_fopen_offline(fd, errbuf); |
112 | 74.4k | if (pkts == NULL) { |
113 | 6 | fclose(fd); |
114 | 6 | return 0; |
115 | 6 | } |
116 | 74.4k | if (ndpi_is_datalink_supported(pcap_datalink(pkts)) == 0) |
117 | 132 | { |
118 | | /* Do not fail if the datalink type is not supported (may happen often during fuzzing). */ |
119 | 132 | pcap_close(pkts); |
120 | 132 | return 0; |
121 | 132 | } |
122 | | |
123 | 74.3k | workflow->pcap_handle = pkts; |
124 | | /* Init flow tree */ |
125 | 74.3k | workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *)); |
126 | 74.3k | if(!workflow->ndpi_flows_root) { |
127 | 0 | pcap_close(pkts); |
128 | 0 | return 0; |
129 | 0 | } |
130 | | |
131 | 74.3k | header = NULL; |
132 | 74.3k | r = pcap_next_ex(pkts, &header, &pkt); |
133 | 2.23M | while (r > 0) { |
134 | | /* allocate an exact size buffer to check overflows */ |
135 | 2.15M | uint8_t *packet_checked = malloc(header->caplen); |
136 | | |
137 | 2.15M | if(packet_checked) { |
138 | 2.15M | ndpi_risk flow_risk; |
139 | | |
140 | 2.15M | memcpy(packet_checked, pkt, header->caplen); |
141 | 2.15M | ndpi_workflow_process_packet(workflow, header, packet_checked, &flow_risk); |
142 | 2.15M | free(packet_checked); |
143 | 2.15M | } |
144 | | |
145 | 2.15M | r = pcap_next_ex(pkts, &header, &pkt); |
146 | 2.15M | } |
147 | 74.3k | pcap_close(pkts); |
148 | | |
149 | | /* Free flow trees */ |
150 | 1.26M | for(i = 0; i < workflow->prefs.num_roots; i++) |
151 | 1.18M | ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer); |
152 | 74.3k | ndpi_free(workflow->ndpi_flows_root); |
153 | | /* Free payload analyzer data, without printing */ |
154 | 74.3k | if(enable_payload_analyzer) |
155 | 20.0k | ndpi_report_payload_stats(NULL); |
156 | | |
157 | 74.3k | return 0; |
158 | 74.3k | } |