/src/net-snmp/testing/fuzzing/snmp_api_fuzzer.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Net-snmp authors |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions are met: |
7 | | * |
8 | | * * Redistributions of source code must retain the above copyright notice, this |
9 | | * list of conditions and the following disclaimer. |
10 | | * |
11 | | * * Redistributions in binary form must reproduce the above copyright notice, |
12 | | * this list of conditions and the following disclaimer in the documentation |
13 | | * and/or other materials provided with the distribution. |
14 | | * |
15 | | * * Neither the name of the copyright holder nor the names of its |
16 | | * contributors may be used to endorse or promote products derived from |
17 | | * this software without specific prior written permission. |
18 | | * |
19 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
20 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
23 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
25 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
26 | | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
27 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | | */ |
30 | | #include <net-snmp/net-snmp-config.h> |
31 | | #include <net-snmp/net-snmp-includes.h> |
32 | | /* We build with the agent/mibgroup/agentx dir in an -I */ |
33 | | #include <protocol.h> |
34 | | #include <stddef.h> |
35 | | #include <stdint.h> |
36 | | #include <stdlib.h> |
37 | | |
38 | | #include "ada_fuzz_header.h" |
39 | | |
40 | | int |
41 | | SecmodInMsg_CB(struct snmp_secmod_incoming_params *sp1) |
42 | 0 | { |
43 | 0 | return SNMPERR_SUCCESS; |
44 | 0 | } |
45 | | |
46 | 30 | int LLVMFuzzerInitialize(int *argc, char ***argv) { |
47 | 30 | if (getenv("NETSNMP_DEBUGGING") != NULL) { |
48 | | /* |
49 | | * Turn on all debugging, to help understand what |
50 | | * bits of the parser are running. |
51 | | */ |
52 | 0 | snmp_enable_stderrlog(); |
53 | 0 | snmp_set_do_debugging(1); |
54 | 0 | debug_register_tokens(""); |
55 | 0 | } |
56 | | |
57 | 30 | struct snmp_secmod_def *sndef = SNMP_MALLOC_STRUCT(snmp_secmod_def); |
58 | 30 | sndef->decode = SecmodInMsg_CB; |
59 | 30 | register_sec_mod(-1, "modname", sndef); |
60 | | |
61 | 30 | return 0; |
62 | 30 | } |
63 | | |
64 | 5.10k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
65 | 5.10k | af_gb_init(); |
66 | | |
67 | 5.10k | const uint8_t *data2 = data; |
68 | 5.10k | size_t size2 = size; |
69 | 5.10k | netsnmp_pdu *pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu); |
70 | 5.10k | netsnmp_session session = { .version = AGENTX_VERSION_1 }; |
71 | | |
72 | 5.10k | agentx_parse(&session, pdu, NETSNMP_REMOVE_CONST(uint8_t *, data), size); |
73 | | |
74 | | // Add a variable with random type and value to the PDU |
75 | 5.10k | char *value = af_gb_get_random_data(&data2, &size2, 20); |
76 | 5.10k | if (value != NULL) { |
77 | 4.91k | value[19] = '\0'; |
78 | 4.91k | oid name[] = {2, 1, 0}; |
79 | 4.91k | int name_len = OID_LENGTH(name); |
80 | 4.91k | char c = (char)af_get_short(&data2, &size2); |
81 | 4.91k | snmp_add_var(pdu, name, name_len, c, value); |
82 | 4.91k | } |
83 | | |
84 | 5.10k | netsnmp_ds_set_boolean(af_get_int(&data2, &size2), |
85 | 5.10k | af_get_int(&data2, &size2), af_get_int(&data2, |
86 | 5.10k | &size2)); |
87 | 5.10k | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
88 | 5.10k | NETSNMP_DS_LIB_REVERSE_ENCODE, |
89 | 5.10k | af_get_int(&data2, &size2)); |
90 | | |
91 | 5.10k | void *cp1 = af_gb_get_null_terminated(&data2, &size2); |
92 | 5.10k | if (cp1 != NULL) { |
93 | | // Target snmp_pdu_build |
94 | 3.37k | size_t build_out_length = strlen(cp1); |
95 | 3.37k | snmp_pdu_build(pdu, cp1, &build_out_length); |
96 | | |
97 | | // Target snmp_parse |
98 | 3.37k | void *parse_data = af_gb_get_random_data(&data2, &size2, 200); |
99 | 3.37k | if (parse_data != NULL) { |
100 | 2.31k | ((char *) parse_data)[199] = '\0'; |
101 | 2.31k | } |
102 | 3.37k | netsnmp_session sess = {}; |
103 | 3.37k | sess.contextName = af_gb_get_null_terminated(&data2, &size2); |
104 | 3.37k | if (sess.contextName) { |
105 | 467 | sess.contextNameLen = strlen(sess.contextName); |
106 | 467 | } |
107 | 3.37k | sess.securityLevel = af_get_int(&data2, &size2); |
108 | | |
109 | 3.37k | pdu->securityName = af_get_null_terminated(&data2, &size2); |
110 | 3.37k | if (pdu->securityName) { |
111 | 411 | pdu->securityNameLen = strlen(pdu->securityName); |
112 | 411 | } |
113 | | |
114 | 3.37k | snmp_free_pdu(pdu); |
115 | 3.37k | pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu); |
116 | | |
117 | 3.37k | sess.version = af_get_int(&data2, &size2); |
118 | 3.37k | if (parse_data != NULL) { |
119 | 2.31k | size_t parse_data_len = strlen(parse_data); |
120 | 2.31k | snmp_parse(NULL, &sess, pdu, parse_data, parse_data_len); |
121 | 2.31k | } |
122 | | |
123 | | // Target snmp_build |
124 | 3.37k | u_char *out_pkt = malloc(1000); |
125 | 3.37k | size_t pkt_len = 1000; |
126 | 3.37k | size_t offset = 0; |
127 | 3.37k | snmp_build(&out_pkt, &pkt_len, &offset, &sess, pdu); |
128 | | |
129 | | // Target snmp utils |
130 | 3.37k | snmpv3_make_report(pdu, af_get_int(&data2, &size2)); |
131 | 3.37k | snmpv3_get_report_type(pdu); |
132 | 3.37k | free(out_pkt); |
133 | 3.37k | } |
134 | | |
135 | | /* |
136 | | * We forcefully added securityName which will be garbage collected by af_gb_cleanup. |
137 | | * This means we have to NULL it out here to avoid a double-free. |
138 | | */ |
139 | 5.10k | if (pdu != NULL) { |
140 | 5.10k | pdu->securityName = NULL; |
141 | 5.10k | pdu->securityNameLen = 0; |
142 | 5.10k | } |
143 | | |
144 | 5.10k | snmp_free_pdu(pdu); |
145 | 5.10k | af_gb_cleanup(); |
146 | 5.10k | return 0; |
147 | 5.10k | } |