229 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
| /* 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;
 | |
| }
 |