|
| 1 | +/* |
| 2 | + * Copyright (c) 2025, 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 | + |
| 31 | +#include <net-snmp/net-snmp-config.h> |
| 32 | +#include <net-snmp/net-snmp-includes.h> |
| 33 | +#include "../../apps/snmptrapd_handlers.h" |
| 34 | +#include "ada_fuzz_header.h" |
| 35 | + |
| 36 | +static netsnmp_session *add_session(netsnmp_transport *t) |
| 37 | +{ |
| 38 | + netsnmp_session session; |
| 39 | + |
| 40 | + snmp_sess_init(&session); |
| 41 | + session.peername = SNMP_DEFAULT_PEERNAME; |
| 42 | + session.version = SNMP_DEFAULT_VERSION; |
| 43 | + session.community_len = SNMP_DEFAULT_COMMUNITY_LEN; |
| 44 | + session.retries = SNMP_DEFAULT_RETRIES; |
| 45 | + session.timeout = SNMP_DEFAULT_TIMEOUT; |
| 46 | + session.callback = snmp_input; |
| 47 | + session.callback_magic = t; |
| 48 | + session.authenticator = NULL; |
| 49 | + session.isAuthoritative = SNMP_SESS_UNKNOWNAUTH; |
| 50 | + |
| 51 | + return snmp_add(&session, t, NULL, NULL); |
| 52 | +} |
| 53 | + |
| 54 | +int LLVMFuzzerInitialize(int *argc, char ***argv) { |
| 55 | + if (getenv("NETSNMP_DEBUGGING") != NULL) { |
| 56 | + snmp_enable_stderrlog(); |
| 57 | + snmp_set_do_debugging(1); |
| 58 | + debug_register_tokens("sess_process_packet"); |
| 59 | + } |
| 60 | + |
| 61 | + return 0; |
| 62 | +} |
| 63 | + |
| 64 | +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
| 65 | + netsnmp_transport *transport = NULL; |
| 66 | + netsnmp_session *session = NULL; |
| 67 | + const unsigned short pkt_len = size; |
| 68 | + const void *const pkt = data; |
| 69 | + int skt = -1; |
| 70 | + int ret = 1; |
| 71 | + |
| 72 | + if (pkt_len == 0) |
| 73 | + goto cleanup; |
| 74 | + |
| 75 | + netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS, "mibs"); |
| 76 | + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, |
| 77 | + NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); |
| 78 | + netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PERSISTENT_DIR, |
| 79 | + "/tmp"); |
| 80 | + |
| 81 | + init_snmp("snmptrapd"); |
| 82 | + |
| 83 | + transport = netsnmp_transport_open_server("trap_fuzzer", "127.0.0.1:7365"); |
| 84 | + if (!transport) { |
| 85 | + fprintf(stderr, "Error: failed to open Net-SNMP transport.\n"); |
| 86 | + goto cleanup; |
| 87 | + } |
| 88 | + session = add_session(transport); |
| 89 | + if (!session) { |
| 90 | + fprintf(stderr, "Error: failed to add Net-SNMP session.\n"); |
| 91 | + goto cleanup; |
| 92 | + } |
| 93 | + |
| 94 | + skt = socket(AF_INET, SOCK_DGRAM, 0); |
| 95 | + if (skt < 0) { |
| 96 | + perror("socket()"); |
| 97 | + goto shutdown; |
| 98 | + } |
| 99 | + struct sockaddr_in addr = { |
| 100 | + .sin_family = AF_INET, |
| 101 | + .sin_port = htons(7365), |
| 102 | + .sin_addr = { htonl(INADDR_LOOPBACK) } |
| 103 | + }; |
| 104 | + if (connect(skt, &addr, sizeof(addr)) < 0) { |
| 105 | + perror("connect()"); |
| 106 | + goto shutdown; |
| 107 | + } |
| 108 | + if (send(skt, pkt, pkt_len, 0) < 0) { |
| 109 | + perror("send()"); |
| 110 | + goto shutdown; |
| 111 | + } |
| 112 | + { |
| 113 | + fd_set readfds,writefds,exceptfds; |
| 114 | + int numfds = 0, block = 0; |
| 115 | + struct timeval timeout; |
| 116 | + |
| 117 | + FD_ZERO(&readfds); |
| 118 | + FD_ZERO(&writefds); |
| 119 | + FD_ZERO(&exceptfds); |
| 120 | + timerclear(&timeout); |
| 121 | + timeout.tv_sec = 5; |
| 122 | + snmp_select_info(&numfds, &readfds, &timeout, &block); |
| 123 | + if (select(numfds, &readfds, &writefds, &exceptfds, &timeout) > 0) |
| 124 | + snmp_read(&readfds); |
| 125 | + } |
| 126 | + ret = 0; |
| 127 | + |
| 128 | +shutdown: |
| 129 | + snmp_shutdown("snmptrapd"); |
| 130 | + |
| 131 | +cleanup: |
| 132 | + if (skt >= 0) |
| 133 | + close(skt); |
| 134 | + if (session) |
| 135 | + snmp_close(session); |
| 136 | + |
| 137 | + return ret; |
| 138 | +} |
0 commit comments