diff options
Diffstat (limited to 'projects/openvpn/fuzz_forward.c')
-rw-r--r-- | projects/openvpn/fuzz_forward.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/projects/openvpn/fuzz_forward.c b/projects/openvpn/fuzz_forward.c new file mode 100644 index 000000000..dff3e93d3 --- /dev/null +++ b/projects/openvpn/fuzz_forward.c @@ -0,0 +1,228 @@ +/* Copyright 2021 Google LLC +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "config.h" +#include <sys/time.h> +#include "syshead.h" +#include "interval.h" +#include "init.h" +#include "buffer.h" +#include "forward.h" + +#include "fuzz_randomizer.h" + + +static int init_c2_outgoing_link(struct context_2 *c2, struct gc_arena *gc) { + struct link_socket_actual *to_link_addr = NULL; + struct link_socket *link_socket = NULL; + struct socks_proxy_info *socks_proxy = NULL; + struct buffer buf; + + c2->tun_write_bytes = 0; + ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc); + memset(link_socket, 0, sizeof(*link_socket)); + + c2->link_socket = link_socket; + + if (fuzz_randomizer_get_int(0, 2) != 0) { + c2->link_socket->info.proto = PROTO_UDP; + } else { + c2->link_socket->info.proto = PROTO_TCP_SERVER; + } + + ALLOC_ARRAY_GC(socks_proxy, struct socks_proxy_info, 1, gc); + memset(socks_proxy, 0, sizeof(*socks_proxy)); + c2->link_socket->socks_proxy = socks_proxy; + + c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff); + c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff); + c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff); + c2->frame.link_mtu = fuzz_randomizer_get_int(0, 0xfffffff); + + ALLOC_ARRAY_GC(to_link_addr, struct link_socket_actual, 1, gc); + memset(to_link_addr, 0, sizeof(*to_link_addr)); + c2->to_link_addr = to_link_addr; + + c2->to_link_addr->dest.addr.sa.sa_family = AF_INET; + c2->to_link_addr->dest.addr.in4.sin_addr.s_addr = 1; + + char *tmp = get_random_string(); + buf = alloc_buf_gc(strlen(tmp), gc); + buf_write(&buf, tmp, strlen(tmp)); + int val = fuzz_randomizer_get_int(0, strlen(tmp)); + buf.offset = val; + free(tmp); + + c2->link_socket->stream_buf.maxlen = BLEN(&buf); + c2->to_link = buf; + + if (buf.offset < 10) { + return -1; + } + return 0; +} + +void fuzz_process_outgoing_link(const uint8_t *data, size_t size) { + struct context ctx; + struct gc_arena gc = gc_new(); + memset(&ctx, 0, sizeof(ctx)); + + if (init_c2_outgoing_link(&ctx.c2, &gc) == 0) { + process_outgoing_link(&ctx); + } + + gc_free(&gc); +} + +static int _init_options(struct options *options, struct client_nat_entry **cne, + struct gc_arena *gc) { + options->passtos = false; + options->mode = MODE_POINT_TO_POINT; + options->allow_recursive_routing = true; + options->client_nat = new_client_nat_list(gc); + + struct client_nat_entry *_cne; + ALLOC_ARRAY_GC(cne[0], struct client_nat_entry, 1, gc); + _cne = cne[0]; + memset(_cne, 0, sizeof(struct client_nat_entry)); + + struct client_nat_option_list clist; + clist.n = 1; + clist.entries[0] = *_cne; + copy_client_nat_option_list(options->client_nat, &clist); + options->route_gateway_via_dhcp = false; + + return 0; +} + +static int init_c2_incoming_tun(struct context_2 *c2, struct gc_arena *gc) { + struct buffer buf; + memset(&buf, 0, sizeof(buf)); + + struct link_socket *link_socket = NULL; + ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc); + c2->link_socket = link_socket; + + ALLOC_OBJ_GC(c2->link_socket_info, struct link_socket_info, gc); + ALLOC_OBJ_GC(c2->link_socket_info->lsa, struct link_socket_addr, gc); + c2->link_socket_info->lsa->bind_local = NULL; + c2->link_socket_info->lsa->remote_list = NULL; + c2->link_socket_info->lsa->current_remote = NULL; + c2->link_socket_info->lsa->remote_list = NULL; + c2->es = env_set_create(gc); + + c2->frame.link_mtu_dynamic = 0; + c2->frame.extra_frame = 0; + c2->frame.extra_tun = 0; + c2->to_link_addr = NULL; + + char *tmp = get_random_string(); + buf = alloc_buf(strlen(tmp)); + buf_write(&buf, tmp, strlen(tmp)); + + int retval; + if (strlen(tmp) > 5) { + retval = 0; + } else { + retval = 1; + } + + free(tmp); + + c2->buf = buf; + c2->buffers = init_context_buffers(&c2->frame); + c2->log_rw = false; + + return retval; +} + +int run_process_incoming_tun(const uint8_t *data, size_t size) { + struct gc_arena gc; + struct context ctx; + struct client_nat_entry *cne[MAX_CLIENT_NAT]; + struct route_list route_list; + + memset(&ctx, 0, sizeof(ctx)); + memset(cne, 0, sizeof(cne)); + + gc = gc_new(); + + _init_options(&ctx.options, cne, &gc); + + // Init tuntap + struct tuntap tuntap; + tuntap.type = DEV_TYPE_TAP; + + ctx.c1.tuntap = &tuntap; + + int retval = init_c2_incoming_tun(&ctx.c2, &gc); + ctx.c1.route_list = &route_list; + if (retval == 0) { + process_incoming_tun(&ctx); + } + + free(ctx.c2.buf.data); + free_context_buffers(ctx.c2.buffers); + gc_free(&gc); +} + +static int init_c2_outgoing_tun(struct context_2 *c2, struct gc_arena *gc) { + struct buffer buf; + + c2->tun_write_bytes = 0; + c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff); + c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff); + c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff); + + char *tmp = get_random_string(); + buf = alloc_buf_gc(strlen(tmp), gc); + buf_write(&buf, tmp, strlen(tmp)); + free(tmp); + + c2->to_tun = buf; + return 0; +} + +void run_process_outgoing_tun(uint8_t *data, size_t size) { + struct gc_arena gc; + struct context ctx; + struct tuntap tuntap; + + memset(&ctx, 0, sizeof(ctx)); + gc = gc_new(); + + tuntap.type = DEV_TYPE_TAP; + ctx.c1.tuntap = &tuntap; + + init_c2_outgoing_tun(&ctx.c2, &gc); + process_outgoing_tun(&ctx); + + gc_free(&gc); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + fuzz_random_init(data, size); + + int dec = fuzz_randomizer_get_int(0, 2); + if (dec == 0) { + run_process_incoming_tun(data, size); + } + else if (dec == 1) { + run_process_outgoing_tun(data, size); + } + else { + fuzz_process_outgoing_link(data, size); + } + + fuzz_random_destroy(); + return 0; +} |