mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
fuzzing: move harnesses from oss-fuzz to repo
This commit is contained in:
parent
50a6b663e4
commit
c3a79422c8
19 changed files with 3149 additions and 0 deletions
25
fuzz/README.md
Normal file
25
fuzz/README.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# OpenVPN fuzzing harnesses
|
||||
|
||||
## How to build
|
||||
```
|
||||
git clone git@github.com:google/oss-fuzz
|
||||
cd oss-fuzz
|
||||
python3 infra_helpers.py build_fuzzers openvpn
|
||||
ls -l ./build/out/openvpn | grep fuzz
|
||||
```
|
||||
|
||||
For more configuration options such as sanitizers and fuzzers, run: ``python3 infra_helpers.py build_fuzzers --help``
|
||||
|
||||
## Harnesses
|
||||
- `fuzz_base64.c`: Fuzzes OpenVPN base64 encode/decode functions.
|
||||
- `fuzz_buffer.c`: Fuzzes buffer and string utility routines.
|
||||
- `fuzz_crypto.c`: Fuzzes key handling plus OpenVPN encrypt/decrypt paths.
|
||||
- `fuzz_dhcp.c`: Fuzzes DHCP router option parsing via `dhcp_extract_router_msg`.
|
||||
- `fuzz_forward.c`: Fuzzes forward path functions for incoming/outgoing tun and link processing.
|
||||
- `fuzz_list.c`: Fuzzes hash/list utilities (init/add/remove/iterate) in `list.h`.
|
||||
- `fuzz_misc.c`: Fuzzes env_set management and misc string helpers like `sanitize_control_message`.
|
||||
- `fuzz_mroute.c`: Fuzzes multicast route parsing/helpers (`mroute_extract_*`, helper init).
|
||||
- `fuzz_packet_id.c`: Fuzzes packet ID tracking, read/write, and persistence load/save.
|
||||
- `fuzz_proxy.c`: Fuzzes HTTP proxy auth/setup via `establish_http_proxy_passthru`.
|
||||
- `fuzz_route.c`: Fuzzes IPv4/IPv6 route option parsing and add/delete routing logic.
|
||||
- `fuzz_verify_cert.c`: Fuzzes X509 parsing and TLS cert verification (`verify_cert`).
|
||||
81
fuzz/build.sh
Executable file
81
fuzz/build.sh
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
#!/bin/bash -eu
|
||||
# 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.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
OPENVPN_ROOT=${SRC}/openvpn
|
||||
FUZZ_DIR=${OPENVPN_ROOT}/fuzz
|
||||
BASE=${OPENVPN_ROOT}/src/openvpn
|
||||
|
||||
apply_sed_changes() {
|
||||
sed -i 's/read(/fuzz_read(/g' ${BASE}/console_systemd.c
|
||||
sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/console_builtin.c
|
||||
sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/misc.c
|
||||
sed -i 's/#include "forward.h"/#include "fuzz_header.h"\n#include "forward.h"/g' ${BASE}/proxy.c
|
||||
sed -i 's/openvpn_select(/fuzz_select(/g' ${BASE}/proxy.c
|
||||
sed -i 's/openvpn_send(/fuzz_send(/g' ${BASE}/proxy.c
|
||||
sed -i 's/recv(/fuzz_recv(/g' ${BASE}/proxy.c
|
||||
sed -i 's/isatty/fuzz_isatty/g' ${BASE}/console_builtin.c
|
||||
|
||||
sed -i 's/fopen/fuzz_fopen/g' ${BASE}/console_builtin.c
|
||||
sed -i 's/fclose/fuzz_fclose/g' ${BASE}/console_builtin.c
|
||||
|
||||
sed -i 's/sendto/fuzz_sendto/g' ${BASE}/socket.h
|
||||
sed -i 's/#include "misc.h"/#include "misc.h"\nextern size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen);/g' ${BASE}/socket.h
|
||||
|
||||
sed -i 's/fp = (flags/fp = stdout;\n\/\//g' ${BASE}/error.c
|
||||
|
||||
sed -i 's/crypto_msg(M_FATAL/crypto_msg(M_WARN/g' ${BASE}/crypto_openssl.c
|
||||
sed -i 's/msg(M_FATAL, \"Cipher/return;msg(M_FATAL, \"Cipher/g' ${BASE}/crypto.c
|
||||
sed -i 's/msg(M_FATAL/msg(M_WARN/g' ${BASE}/crypto.c
|
||||
|
||||
sed -i 's/= write/= fuzz_write/g' ${BASE}/packet_id.c
|
||||
}
|
||||
|
||||
echo "" >> ${BASE}/openvpn.c
|
||||
echo "#include \"fake_fuzz_header.h\"" >> ${BASE}/openvpn.c
|
||||
echo "ssize_t fuzz_get_random_data(void *buf, size_t len) { return 0; }" >> ${BASE}/fake_fuzz_header.h
|
||||
echo "int fuzz_success;" >> ${BASE}/fake_fuzz_header.h
|
||||
|
||||
# Apply hooking changes
|
||||
apply_sed_changes
|
||||
|
||||
# Copy corpuses out
|
||||
zip -r $OUT/fuzz_verify_cert_seed_corpus.zip $SRC/boringssl/fuzz/cert_corpus
|
||||
|
||||
# Build openvpn
|
||||
autoreconf -ivf
|
||||
./configure --disable-lz4 --with-crypto-library=openssl OPENSSL_LIBS="-L/usr/local/ssl/ -lssl -lcrypto" OPENSSL_CFLAGS="-I/usr/local/ssl/include/"
|
||||
make -j$(nproc)
|
||||
|
||||
# Make openvpn object files into a library we can link fuzzers to
|
||||
cd src/openvpn
|
||||
rm openvpn.o
|
||||
ar r libopenvpn.a *.o
|
||||
|
||||
# Compile our fuzz helper
|
||||
$CXX $CXXFLAGS -g -c ${FUZZ_DIR}/fuzz_randomizer.cpp -o ${FUZZ_DIR}/fuzz_randomizer.o
|
||||
|
||||
# Compile the fuzzers
|
||||
for fuzzname in dhcp misc base64 proxy buffer route packet_id mroute list verify_cert; do
|
||||
$CC -DHAVE_CONFIG_H -I. -I../.. -I../../include -I../../src/compat -I/usr/include/libnl3/ \
|
||||
-DPLUGIN_LIBDIR=\"/usr/local/lib/openvpn/plugins\" -std=c99 $CFLAGS \
|
||||
-c ${FUZZ_DIR}/fuzz_${fuzzname}.c -o ${FUZZ_DIR}/fuzz_${fuzzname}.o
|
||||
|
||||
# Link with CXX
|
||||
$CXX ${CXXFLAGS} ${LIB_FUZZING_ENGINE} $FUZZ_DIR/fuzz_${fuzzname}.o -o $OUT/fuzz_${fuzzname} $FUZZ_DIR/fuzz_randomizer.o \
|
||||
libopenvpn.a ../../src/compat/.libs/libcompat.a /usr/lib/x86_64-linux-gnu/libnsl.a \
|
||||
/usr/lib/x86_64-linux-gnu/libresolv.a /usr/lib/x86_64-linux-gnu/liblzo2.a \
|
||||
-lssl -lcrypto -ldl -l:libnl-3.a -l:libnl-genl-3.a -lcap-ng -pthread
|
||||
done
|
||||
47
fuzz/fuzz.h
Normal file
47
fuzz/fuzz.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* 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 <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
// Returns a NULL-terminated C string that should be freed by the caller.
|
||||
char *get_modifiable_string(FuzzedDataProvider &provider) {
|
||||
std::string s1 = provider.ConsumeRandomLengthString();
|
||||
char *tmp = (char *)malloc(s1.size() + 1);
|
||||
memcpy(tmp, s1.c_str(), s1.size());
|
||||
tmp[s1.size()] = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
FuzzedDataProvider *prov = NULL;
|
||||
|
||||
|
||||
extern "C" ssize_t fuzz_get_random_data(void *buf, size_t len) {
|
||||
size_t ret_val;
|
||||
char *cbuf = (char*)buf;
|
||||
|
||||
if (prov->remaining_bytes() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
double prob = prov->ConsumeProbability<double>();
|
||||
if (prob < 0.05) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 1) {
|
||||
ret_val = prov->ConsumeData(buf, 1);
|
||||
return ret_val;
|
||||
}
|
||||
ret_val = prov->ConsumeData(buf, len);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
43
fuzz/fuzz_base64.c
Normal file
43
fuzz/fuzz_base64.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* 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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size > 500) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *new_str = (char *)malloc(size + 1);
|
||||
if (new_str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(new_str, data, size);
|
||||
new_str[size] = '\0';
|
||||
|
||||
char *str = NULL;
|
||||
openvpn_base64_encode(data, size, &str);
|
||||
if(str != NULL) {
|
||||
free(str);
|
||||
}
|
||||
|
||||
uint16_t outsize = 10000;
|
||||
char *output_buf = (char *)malloc(outsize);
|
||||
openvpn_base64_decode(new_str, output_buf, outsize);
|
||||
free(output_buf);
|
||||
|
||||
free(new_str);
|
||||
return 0;
|
||||
}
|
||||
263
fuzz/fuzz_buffer.c
Normal file
263
fuzz/fuzz_buffer.c
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "misc.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
fuzz_random_init(data,size);
|
||||
|
||||
struct gc_arena gc;
|
||||
struct buffer *bufp;
|
||||
struct buffer buf, buf2;
|
||||
struct buffer_list *buflistp = NULL;
|
||||
ssize_t generic_ssizet, _size;
|
||||
char *tmp;
|
||||
char *tmp2;
|
||||
char match;
|
||||
|
||||
gc = gc_new();
|
||||
bufp = NULL;
|
||||
|
||||
int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
|
||||
for (int i = 0; i < total_to_fuzz; i++) {
|
||||
if (bufp == NULL) {
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 1);
|
||||
if (generic_ssizet == 0) {
|
||||
_size = fuzz_randomizer_get_int(0, 100);
|
||||
buf = alloc_buf_gc(_size, &gc);
|
||||
bufp = &buf;
|
||||
} else {
|
||||
tmp = get_random_string();
|
||||
buf = string_alloc_buf(tmp, &gc);
|
||||
bufp = &buf;
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
} else {
|
||||
#define NUM_TARGETS 31
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, NUM_TARGETS);
|
||||
switch (generic_ssizet) {
|
||||
case 0:
|
||||
buf_clear(bufp);
|
||||
break;
|
||||
case 1:
|
||||
buf2 = clone_buf(bufp);
|
||||
free_buf(&buf2);
|
||||
break;
|
||||
case 2:
|
||||
buf_defined(bufp);
|
||||
break;
|
||||
case 3:
|
||||
buf_valid(bufp);
|
||||
break;
|
||||
case 4:
|
||||
buf_bptr(bufp);
|
||||
break;
|
||||
case 5:
|
||||
buf_len(bufp);
|
||||
break;
|
||||
case 6:
|
||||
buf_bend(bufp);
|
||||
break;
|
||||
case 7:
|
||||
buf_blast(bufp);
|
||||
break;
|
||||
case 8:
|
||||
buf_str(bufp);
|
||||
break;
|
||||
case 9:
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 255);
|
||||
buf_rmtail(bufp, (uint8_t)generic_ssizet);
|
||||
break;
|
||||
case 10:
|
||||
buf_chomp(bufp);
|
||||
break;
|
||||
case 11:
|
||||
tmp = get_random_string();
|
||||
skip_leading_whitespace(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 12:
|
||||
tmp = get_random_string();
|
||||
chomp(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 13:
|
||||
tmp = get_random_string();
|
||||
tmp2 = get_random_string();
|
||||
rm_trailing_chars(tmp, tmp2);
|
||||
free(tmp);
|
||||
free(tmp2);
|
||||
tmp = NULL;
|
||||
tmp2 = NULL;
|
||||
break;
|
||||
case 14:
|
||||
tmp = get_random_string();
|
||||
string_clear(tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 15:
|
||||
tmp = get_random_string();
|
||||
buf_string_match_head_str(bufp, tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 16:
|
||||
tmp = get_random_string();
|
||||
buf_string_compare_advance(bufp, tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 17:
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 255);
|
||||
|
||||
tmp = get_random_string();
|
||||
if (strlen(tmp) > 0) {
|
||||
buf_parse(bufp, (int)generic_ssizet, tmp, strlen(tmp));
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 18:
|
||||
tmp = get_random_string();
|
||||
string_mod(tmp, fuzz_randomizer_get_int(0, 12312),
|
||||
fuzz_randomizer_get_int(0, 23141234),
|
||||
(char)fuzz_randomizer_get_int(0, 255));
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 19:
|
||||
tmp = get_random_string();
|
||||
match = (char)fuzz_randomizer_get_int(0, 255);
|
||||
if (match != 0) {
|
||||
string_replace_leading(tmp, match, (char)fuzz_randomizer_get_int(0, 255));
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 20:
|
||||
tmp = get_random_string();
|
||||
buf_write(bufp, tmp, strlen(tmp));
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 21:
|
||||
tmp = get_random_string();
|
||||
|
||||
buf_write_prepend(bufp, tmp, strlen(tmp));
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 22:
|
||||
buf_write_u8(bufp, fuzz_randomizer_get_int(0, 255));
|
||||
break;
|
||||
case 23:
|
||||
buf_write_u16(bufp, fuzz_randomizer_get_int(0, 1024));
|
||||
break;
|
||||
case 24:
|
||||
buf_write_u32(bufp, fuzz_randomizer_get_int(0, 12312));
|
||||
break;
|
||||
case 25:
|
||||
tmp = get_random_string();
|
||||
buf_catrunc(bufp, tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 26:
|
||||
tmp = get_random_string();
|
||||
buf_puts(bufp, tmp);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 27:
|
||||
buf_advance(bufp, fuzz_randomizer_get_int(0, 25523));
|
||||
break;
|
||||
case 28:
|
||||
buf_prepend(bufp, fuzz_randomizer_get_int(0, 251235));
|
||||
break;
|
||||
case 29:
|
||||
buf_reverse_capacity(bufp);
|
||||
break;
|
||||
case 30:
|
||||
buf_forward_capacity_total(bufp);
|
||||
break;
|
||||
case 31:
|
||||
buf_forward_capacity(bufp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (buflistp == NULL) {
|
||||
buflistp = buffer_list_new();
|
||||
} else {
|
||||
#define NUM_LIST_TARGETS 6
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, NUM_LIST_TARGETS);
|
||||
switch (generic_ssizet) {
|
||||
case 0:
|
||||
buffer_list_free(buflistp);
|
||||
buflistp = NULL;
|
||||
break;
|
||||
case 1:
|
||||
buffer_list_defined(buflistp);
|
||||
break;
|
||||
case 2:
|
||||
tmp = get_random_string();
|
||||
if (strlen(tmp) < BUF_SIZE_MAX) {
|
||||
buffer_list_push(buflistp, tmp);
|
||||
}
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 3:
|
||||
buffer_list_peek(buflistp);
|
||||
break;
|
||||
case 4:
|
||||
buffer_list_pop(buflistp);
|
||||
break;
|
||||
case 5:
|
||||
tmp = get_random_string();
|
||||
buffer_list_aggregate_separator(
|
||||
buflistp, fuzz_randomizer_get_int(0, 1024), tmp);
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 6:
|
||||
buffer_list_aggregate(buflistp,
|
||||
fuzz_randomizer_get_int(0, 1024));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
buffer_list_free(buflistp);
|
||||
gc_free(&gc);
|
||||
|
||||
fuzz_random_destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
258
fuzz/fuzz_crypto.c
Normal file
258
fuzz/fuzz_crypto.c
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/* 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 "syshead.h"
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "fuzz_verify_cert.h"
|
||||
#include "misc.h"
|
||||
#include "manage.h"
|
||||
#include "otime.h"
|
||||
#include "base64.h"
|
||||
#include "ssl_verify.h"
|
||||
#include "ssl_verify_backend.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
|
||||
size_t key_len) {
|
||||
//const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
|
||||
|
||||
cipher_ctx_t *cipher_kt = ctx->cipher;
|
||||
/* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
|
||||
if (cipher_ctx_mode_aead(cipher_kt)) {
|
||||
size_t impl_iv_len = 0;
|
||||
ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN);
|
||||
impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type);
|
||||
ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
|
||||
ASSERT(impl_iv_len <= key_len);
|
||||
memcpy(ctx->implicit_iv, key, impl_iv_len);
|
||||
ctx->implicit_iv_len = impl_iv_len;
|
||||
}
|
||||
}
|
||||
|
||||
static int init_frame(struct frame *frame) {
|
||||
frame->link_mtu = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->extra_buffer = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->link_mtu_dynamic = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->extra_frame = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->extra_tun = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->extra_link = fuzz_randomizer_get_int(100, 1000);
|
||||
frame->align_flags = 0;
|
||||
frame->align_adjust = 0;
|
||||
if (TUN_MTU_SIZE(frame) <= 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
OPENSSL_malloc_init();
|
||||
SSL_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
|
||||
SSL_load_error_strings();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
fuzz_random_init(data, size);
|
||||
fuzz_success = 1;
|
||||
bool key_ctx_dec_initialized = false;
|
||||
bool key_ctx_enc_initialized = false;
|
||||
struct key_ctx key_ctx_dec;
|
||||
memset(&key_ctx_dec, 0, sizeof(struct key_ctx));
|
||||
struct key_ctx key_ctx_enc;
|
||||
memset(&key_ctx_enc, 0, sizeof(struct key_ctx));
|
||||
|
||||
struct gc_arena gc;
|
||||
struct tls_session *session = NULL;
|
||||
X509 *x509 = NULL;
|
||||
gc = gc_new();
|
||||
|
||||
gb_init();
|
||||
|
||||
// Read key file
|
||||
struct key2 key2;
|
||||
char *keydata = gb_get_random_string();
|
||||
read_key_file(&key2, keydata, RKF_INLINE);
|
||||
|
||||
// init key type
|
||||
struct key_type kt;
|
||||
memset(&kt, 0, sizeof(struct key_type));
|
||||
|
||||
char *ciphername = gb_get_random_string();
|
||||
char *authname = gb_get_random_string();
|
||||
bool key_type_initialized = false;
|
||||
|
||||
if (strcmp(ciphername, "AES-256-GCM") == 0 ||
|
||||
strcmp(ciphername, "AES-128-GCM") == 0 ||
|
||||
strcmp(ciphername, "AES-192-GCM") == 0 ||
|
||||
strcmp(ciphername, "CAMELLIA-128-CFB128") == 0) {
|
||||
|
||||
int v = fuzz_randomizer_get_int(0, 1);
|
||||
if (v == 0) {
|
||||
init_key_type(&kt, ciphername, authname, true, 0);
|
||||
} else {
|
||||
init_key_type(&kt, ciphername, authname, false, 0);
|
||||
}
|
||||
key_type_initialized = true;
|
||||
}
|
||||
|
||||
if (fuzz_success == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Generate key.
|
||||
// Identify which one we should do, read or generate a random key.
|
||||
int c = fuzz_randomizer_get_int(0, 1);
|
||||
const uint8_t d[1024];
|
||||
int key_read = 0;
|
||||
struct key key;
|
||||
if (c == 0) {
|
||||
if (fuzz_get_random_data(d, 1024) != 1024) {
|
||||
struct buffer buf = alloc_buf(1024);
|
||||
buf_write(&buf, d, 1024);
|
||||
if (read_key(&key, &kt, &buf) == 1) {
|
||||
key_read = 1;
|
||||
}
|
||||
free_buf(&buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (key_type_initialized == true) {
|
||||
generate_key_random(&key, &kt);
|
||||
}
|
||||
}
|
||||
|
||||
if (fuzz_success == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
key_read = 1;
|
||||
|
||||
// init decryption context
|
||||
if (key_type_initialized && key_read) {
|
||||
init_key_ctx(&key_ctx_dec, &key, &kt, OPENVPN_OP_DECRYPT, "x");
|
||||
key_ctx_update_implicit_iv(&key_ctx_dec, &(key.hmac), MAX_HMAC_KEY_LENGTH);
|
||||
key_ctx_dec_initialized = true;
|
||||
}
|
||||
|
||||
// init encryption context
|
||||
if (key_type_initialized && key_read) {
|
||||
init_key_ctx(&key_ctx_enc, &key, &kt, OPENVPN_OP_DECRYPT, "x");
|
||||
key_ctx_update_implicit_iv(&key_ctx_enc, &(key.hmac), MAX_HMAC_KEY_LENGTH);
|
||||
key_ctx_enc_initialized = true;
|
||||
}
|
||||
|
||||
// perform encryption
|
||||
struct frame frame;
|
||||
memset(&frame, 0, sizeof(struct frame));
|
||||
if (key_ctx_enc_initialized == true && key_ctx_dec_initialized == true &&
|
||||
init_frame(&frame) == 0) {
|
||||
struct crypto_options opt;
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
opt.pid_persist = NULL;
|
||||
opt.key_ctx_bi.encrypt = key_ctx_enc;
|
||||
opt.key_ctx_bi.decrypt = key_ctx_dec;
|
||||
opt.key_ctx_bi.initialized = true;
|
||||
opt.packet_id.rec.initialized = true;
|
||||
opt.packet_id.rec.seq_list = NULL;
|
||||
opt.packet_id.rec.name = NULL;
|
||||
|
||||
void *buf_p;
|
||||
|
||||
struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
||||
struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
||||
struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
|
||||
struct buffer buf = clear_buf();
|
||||
|
||||
int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
|
||||
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
|
||||
ASSERT(buf_init(&src, 0));
|
||||
src.len = x;
|
||||
ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
|
||||
|
||||
buf = work;
|
||||
buf_p = buf_write_alloc(&buf, BLEN(&src));
|
||||
ASSERT(buf_p);
|
||||
memcpy(buf_p, BPTR(&src), BLEN(&src));
|
||||
|
||||
ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(&(frame))));
|
||||
|
||||
openvpn_encrypt(&buf, encrypt_workspace, &opt);
|
||||
}
|
||||
|
||||
// perform decryption
|
||||
memset(&frame, 0, sizeof(struct frame));
|
||||
if (key_ctx_dec_initialized == true && key_ctx_enc_initialized == true &&
|
||||
init_frame(&frame) == 0) {
|
||||
struct crypto_options opt;
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
opt.pid_persist = NULL;
|
||||
opt.key_ctx_bi.encrypt = key_ctx_enc;
|
||||
opt.key_ctx_bi.decrypt = key_ctx_dec;
|
||||
opt.key_ctx_bi.initialized = true;
|
||||
opt.packet_id.rec.initialized = true;
|
||||
opt.packet_id.rec.seq_list = NULL;
|
||||
opt.packet_id.rec.name = NULL;
|
||||
|
||||
void *buf_p;
|
||||
|
||||
struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
||||
struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
|
||||
struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
|
||||
struct buffer buf = clear_buf();
|
||||
|
||||
int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
|
||||
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
|
||||
ASSERT(buf_init(&src, 0));
|
||||
src.len = x;
|
||||
ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
|
||||
|
||||
buf = work;
|
||||
buf_p = buf_write_alloc(&buf, BLEN(&src));
|
||||
ASSERT(buf_p);
|
||||
memcpy(buf_p, BPTR(&src), BLEN(&src));
|
||||
|
||||
ASSERT(buf_init(&decrypt_workspace, FRAME_HEADROOM(&(frame))));
|
||||
|
||||
openvpn_decrypt(&buf, decrypt_workspace, &opt, &frame, BPTR(&buf));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
// cleanup
|
||||
gc_free(&gc);
|
||||
|
||||
if (key_ctx_dec_initialized == true) {
|
||||
free_key_ctx(&key_ctx_dec);
|
||||
}
|
||||
|
||||
if (key_ctx_enc_initialized == true) {
|
||||
free_key_ctx(&key_ctx_enc);
|
||||
}
|
||||
fuzz_random_destroy();
|
||||
|
||||
gb_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
37
fuzz/fuzz_dhcp.c
Normal file
37
fuzz/fuzz_dhcp.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "dhcp.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
struct buffer ipbuf;
|
||||
in_addr_t ret;
|
||||
|
||||
fuzz_random_init(data, size);
|
||||
char *ran_val = get_random_string();
|
||||
|
||||
ipbuf = alloc_buf(strlen(ran_val));
|
||||
if (buf_write(&ipbuf, ran_val, strlen(ran_val)) != false) {
|
||||
ret = dhcp_extract_router_msg(&ipbuf);
|
||||
}
|
||||
free_buf(&ipbuf);
|
||||
|
||||
fuzz_random_destroy();
|
||||
free(ran_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
228
fuzz/fuzz_forward.c
Normal file
228
fuzz/fuzz_forward.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
79
fuzz/fuzz_header.h
Normal file
79
fuzz/fuzz_header.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef FUZZ_H
|
||||
#define FUZZ_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
// Forward declared because we want to use FuzzedDataProvider,
|
||||
// which requires CPP.
|
||||
extern ssize_t fuzz_get_random_data(void *buf, size_t len);
|
||||
|
||||
ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags){
|
||||
return fuzz_get_random_data(buf, len);
|
||||
}
|
||||
|
||||
ssize_t fuzz_read(int sockfd, void *buf, size_t len){
|
||||
return fuzz_get_random_data(buf, len);
|
||||
}
|
||||
|
||||
ssize_t fuzz_write(int fd, const void *buf, size_t count) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int fuzz_isatty(int fd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *fuzz_fgets(char *s, int size, FILE *stream) {
|
||||
ssize_t v = fuzz_get_random_data(s, size-1);
|
||||
// We use fgets to get trusted input. As such, assume we have
|
||||
// an ascii printable char at the beginning.
|
||||
printf("Calling into fgets\n");
|
||||
if (s[0] <= 0x21 || s[0] >= 0x7f) {
|
||||
s[0] = 'A';
|
||||
}
|
||||
s[size-1] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
int fuzz_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) {
|
||||
char val;
|
||||
ssize_t c = fuzz_get_random_data(&val, 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) {
|
||||
return len;
|
||||
}
|
||||
|
||||
FILE *fp_p = NULL;
|
||||
FILE *fuzz_fopen(const char *pathname, const char *mode) {
|
||||
if (mode == NULL) return fp_p;
|
||||
return fp_p;
|
||||
}
|
||||
|
||||
int fuzz_fclose(FILE *stream) {
|
||||
if (stream == NULL) return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen) {
|
||||
if (buf == NULL) {
|
||||
return len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
135
fuzz/fuzz_list.c
Normal file
135
fuzz/fuzz_list.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "list.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
#define KEY_SIZE 23
|
||||
|
||||
/* Required for hash_init() */
|
||||
static uint32_t word_hash_function(const void *key, uint32_t iv) {
|
||||
return hash_func(key, KEY_SIZE, iv);
|
||||
}
|
||||
|
||||
/* Required for hash_init() */
|
||||
static bool word_compare_function(const void *key1, const void *key2) {
|
||||
return ((size_t)key1 & 0xFFF) == ((size_t)key1 & 0xFFF);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
struct gc_arena gc;
|
||||
struct hash *hash = NULL;
|
||||
ssize_t generic_ssizet, generic_ssizet2, num_loops;
|
||||
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
gc = gc_new();
|
||||
|
||||
int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
|
||||
for (int i = 0; i < total_to_fuzz; i++) {
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 8);
|
||||
|
||||
switch (generic_ssizet) {
|
||||
case 0:
|
||||
if (hash == NULL) {
|
||||
int n_buckets = fuzz_randomizer_get_int(1, 1000);
|
||||
uint32_t iv;
|
||||
|
||||
hash =
|
||||
hash_init(n_buckets, iv, word_hash_function, word_compare_function);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (hash) {
|
||||
hash_free(hash);
|
||||
hash = NULL;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (hash) {
|
||||
struct hash_iterator hi;
|
||||
struct hash_element *he;
|
||||
hash_iterator_init(hash, &hi);
|
||||
while ((he = hash_iterator_next(&hi))) {
|
||||
void *w = he->value;
|
||||
}
|
||||
hash_iterator_free(&hi);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (hash) {
|
||||
void *key;
|
||||
void *value;
|
||||
char arr[KEY_SIZE];
|
||||
memset(arr, 0, KEY_SIZE);
|
||||
fuzz_get_random_data(arr, KEY_SIZE);
|
||||
key = (void *)arr;
|
||||
if (!hash_lookup(hash, key)) {
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
value = (void *)generic_ssizet;
|
||||
hash_add(hash, key, value, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (hash) {
|
||||
hash_n_elements(hash);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (hash) {
|
||||
hash_n_buckets(hash);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (hash) {
|
||||
uint32_t hv;
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
hv = generic_ssizet;
|
||||
hash_bucket(hash, hv);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (hash) {
|
||||
void *key;
|
||||
char arr[KEY_SIZE];
|
||||
memset(arr, 0, KEY_SIZE);
|
||||
fuzz_get_random_data(arr, KEY_SIZE);
|
||||
key = (void *)arr;
|
||||
hash_remove(hash, key);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (hash) {
|
||||
void *value;
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
value = (void *)generic_ssizet;
|
||||
hash_remove_by_value(hash, value);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
hash_free(hash);
|
||||
}
|
||||
|
||||
gc_free(&gc);
|
||||
|
||||
fuzz_random_destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
fuzz/fuzz_misc.c
Normal file
62
fuzz/fuzz_misc.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "misc.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
struct gc_arena gc;
|
||||
struct env_set *es;
|
||||
gc = gc_new();
|
||||
es = env_set_create(&gc);
|
||||
|
||||
int total_to_fuzz = fuzz_randomizer_get_int(1, 9);
|
||||
for (int i = 0; i <total_to_fuzz; i++) {
|
||||
int type = fuzz_randomizer_get_int(0, 3);
|
||||
char *tmp1 = get_random_string();
|
||||
char *tmp2 = get_random_string();
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
env_set_del(es, tmp1);
|
||||
break;
|
||||
case 1:
|
||||
env_set_add(es, tmp1);
|
||||
break;
|
||||
case 2:
|
||||
env_set_get(es, tmp1);
|
||||
break;
|
||||
case 3:
|
||||
if (strlen(tmp1) > 1 && strlen(tmp2) > 1) {
|
||||
setenv_str(es, tmp2, tmp1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sanitize_control_message(tmp1, &gc);
|
||||
}
|
||||
free(tmp1);
|
||||
free(tmp2);
|
||||
}
|
||||
|
||||
env_set_destroy(es);
|
||||
gc_free(&gc);
|
||||
|
||||
fuzz_random_destroy();
|
||||
return 0;
|
||||
}
|
||||
70
fuzz/fuzz_mroute.c
Normal file
70
fuzz/fuzz_mroute.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "init.h"
|
||||
#include "mroute.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
fuzz_random_init(data, size);
|
||||
struct buffer buf;
|
||||
struct gc_arena gc;
|
||||
|
||||
gc = gc_new();
|
||||
|
||||
char *tmp = get_random_string();
|
||||
buf = string_alloc_buf(tmp, &gc);
|
||||
free(tmp);
|
||||
|
||||
struct mroute_addr src_addr;
|
||||
struct mroute_addr dst_addr;
|
||||
mroute_addr_init(&src_addr);
|
||||
mroute_addr_init(&dst_addr);
|
||||
unsigned int ret = mroute_extract_addr_ip(&src_addr, &dst_addr, &buf);
|
||||
|
||||
if (ret & MROUTE_EXTRACT_SUCCEEDED) {
|
||||
mroute_addr_mask_host_bits(&src_addr);
|
||||
mroute_addr_print(&src_addr, &gc);
|
||||
mroute_learnable_address(&src_addr, &gc);
|
||||
}
|
||||
|
||||
uint16_t vid;
|
||||
struct mroute_addr a1, a2;
|
||||
mroute_addr_init(&a1);
|
||||
mroute_addr_init(&a2);
|
||||
mroute_extract_addr_ether(&a1, &a2, vid, &buf);
|
||||
|
||||
if (size > sizeof(struct openvpn_sockaddr)) {
|
||||
struct openvpn_sockaddr local_sock;
|
||||
memcpy(&local_sock, data, sizeof(struct openvpn_sockaddr));
|
||||
mroute_extract_openvpn_sockaddr(&a1, &local_sock, true);
|
||||
mroute_extract_openvpn_sockaddr(&a1, &local_sock, false);
|
||||
}
|
||||
|
||||
struct mroute_helper *mhelper = NULL;
|
||||
mhelper = mroute_helper_init(fuzz_randomizer_get_int(0, 0xfffffff));
|
||||
if (mhelper != NULL) {
|
||||
mroute_helper_add_iroute46(mhelper, fuzz_randomizer_get_int(0, MR_HELPER_NET_LEN-1));
|
||||
mroute_helper_free(mhelper);
|
||||
}
|
||||
|
||||
gc_free(&gc);
|
||||
|
||||
fuzz_random_destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
104
fuzz/fuzz_packet_id.c
Normal file
104
fuzz/fuzz_packet_id.c
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "init.h"
|
||||
#include "packet_id.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
struct packet_id pid;
|
||||
struct packet_id_net pin;
|
||||
const int seq_backtrack = 10;
|
||||
const int time_backtrack = 10;
|
||||
|
||||
packet_id_init(&pid, seq_backtrack, time_backtrack, "name", 0);
|
||||
|
||||
int total_sends = fuzz_randomizer_get_int(0, 10);
|
||||
for (int i = 0; i < total_sends; i++) {
|
||||
update_time();
|
||||
pin.time = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
pin.id = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
|
||||
packet_id_reap_test(&pid.rec);
|
||||
bool test = packet_id_test(&pid.rec, &pin);
|
||||
if (test) {
|
||||
packet_id_add(&pid.rec, &pin);
|
||||
}
|
||||
}
|
||||
packet_id_free(&pid);
|
||||
|
||||
// packet id send
|
||||
char *tmp2 = get_random_string();
|
||||
if (strlen(tmp2) > sizeof(struct packet_id_send)) {
|
||||
struct packet_id_send pidsend;
|
||||
memcmp(&pidsend, tmp2, sizeof(struct packet_id_send));
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = pidsend.time;
|
||||
tv.tv_usec = 0;
|
||||
if (localtime(&tv)) {
|
||||
struct buffer iv_buffer;
|
||||
buf_set_write(&iv_buffer, tmp2, strlen(tmp2));
|
||||
packet_id_write(&pidsend, &iv_buffer, false, false);
|
||||
packet_id_write(&pidsend, &iv_buffer, false, true);
|
||||
packet_id_write(&pidsend, &iv_buffer, true, true);
|
||||
packet_id_write(&pidsend, &iv_buffer, true, false);
|
||||
}
|
||||
}
|
||||
free(tmp2);
|
||||
|
||||
struct gc_arena gc;
|
||||
gc = gc_new();
|
||||
struct buffer buf;
|
||||
char *tmp = get_random_string();
|
||||
buf = string_alloc_buf(tmp, &gc);
|
||||
free(tmp);
|
||||
packet_id_read(&pid, &buf, false);
|
||||
packet_id_read(&pid, &buf, true);
|
||||
gc_free(&gc);
|
||||
|
||||
char filename[256];
|
||||
sprintf(filename, "/tmp/libfuzzer.%d", getpid());
|
||||
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
if (!fp) {
|
||||
return 0;
|
||||
}
|
||||
fwrite(data, size, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
struct packet_id_persist p;
|
||||
memset(&p, 0, sizeof(struct packet_id_persist));
|
||||
packet_id_persist_init(&p);
|
||||
packet_id_persist_load(&p, filename);
|
||||
//p.time = NULL;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = p.time;
|
||||
tv.tv_usec = 0;
|
||||
if (localtime(&tv) != NULL) {
|
||||
gc = gc_new();
|
||||
p.id_last_written = fuzz_randomizer_get_int(0, 0xfffffff);
|
||||
//packet_id_persist_print(&p, &gc);
|
||||
packet_id_persist_save(&p);
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
packet_id_persist_close(&p);
|
||||
|
||||
fuzz_random_destroy();
|
||||
return 0;
|
||||
}
|
||||
144
fuzz/fuzz_proxy.c
Normal file
144
fuzz/fuzz_proxy.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/* 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 "proxy.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include "sig.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||
{
|
||||
OPENSSL_malloc_init();
|
||||
SSL_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
OpenSSL_add_all_digests();
|
||||
|
||||
SSL_load_error_strings();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
char *tmp = NULL;
|
||||
char *tmp2 = NULL;
|
||||
|
||||
if (size < 500) {
|
||||
return 0;
|
||||
}
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
struct gc_arena gc = gc_new();
|
||||
struct http_proxy_info pi;
|
||||
ssize_t generic_ssizet;
|
||||
struct signal_info signal_received = {0};
|
||||
// TODO: This coul be randomized
|
||||
register_signal(&signal_received, SIGUSR1, "remote-exit");
|
||||
struct buffer lookahead = alloc_buf(1024);
|
||||
struct event_timeout evt;
|
||||
|
||||
memset(&evt, 0, sizeof(struct event_timeout));
|
||||
memset(&pi, 0, sizeof(struct http_proxy_info));
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
|
||||
generic_ssizet = 0;
|
||||
char *fuzz_usrnm = fuzz_random_get_string_max_length(USER_PASS_LEN);
|
||||
strcpy(pi.up.username, fuzz_usrnm);
|
||||
if (strlen(pi.up.username) == 0) {
|
||||
gc_free(&gc);
|
||||
free_buf(&lookahead);
|
||||
free(fuzz_usrnm);
|
||||
fuzz_random_destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *pswd = fuzz_random_get_string_max_length(USER_PASS_LEN);
|
||||
strcpy(pi.up.password, pswd);
|
||||
if (strlen(pi.up.password) == 0) {
|
||||
gc_free(&gc);
|
||||
free_buf(&lookahead);
|
||||
|
||||
free(pswd);
|
||||
free(fuzz_usrnm);
|
||||
fuzz_random_destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 3);
|
||||
switch (generic_ssizet) {
|
||||
case 0:
|
||||
pi.auth_method = HTTP_AUTH_NONE;
|
||||
break;
|
||||
case 1:
|
||||
pi.auth_method = HTTP_AUTH_BASIC;
|
||||
break;
|
||||
case 2:
|
||||
pi.auth_method = HTTP_AUTH_DIGEST;
|
||||
break;
|
||||
case 3:
|
||||
pi.auth_method = HTTP_AUTH_NTLM2;
|
||||
break;
|
||||
}
|
||||
pi.options.http_version = "1.1";
|
||||
|
||||
generic_ssizet = fuzz_randomizer_get_int(0, 2);
|
||||
switch (generic_ssizet) {
|
||||
case 0:
|
||||
pi.options.auth_retry = PAR_NO;
|
||||
break;
|
||||
case 1:
|
||||
pi.options.auth_retry = PAR_ALL;
|
||||
break;
|
||||
case 2:
|
||||
pi.options.auth_retry = PAR_NCT;
|
||||
break;
|
||||
}
|
||||
|
||||
char *tmp_authenticate = get_random_string();
|
||||
pi.proxy_authenticate = tmp_authenticate;
|
||||
|
||||
//if (provider.ConsumeProbability<double>() < 0.5) {
|
||||
//tmp = get_modifiable_string(provider);
|
||||
tmp = get_random_string();
|
||||
pi.options.custom_headers[0].name = tmp;
|
||||
//if (provider.ConsumeProbability<double>() < 0.5) {
|
||||
//tmp2 = get_modifiable_string(provider);
|
||||
tmp2 = get_random_string();
|
||||
pi.options.custom_headers[0].content = tmp2;
|
||||
//}
|
||||
//}
|
||||
|
||||
establish_http_proxy_passthru(&pi, 0, "1.2.3.4", "777", &evt, &lookahead,
|
||||
&signal_received);
|
||||
free(pi.proxy_authenticate);
|
||||
gc_free(&gc);
|
||||
free_buf(&lookahead);
|
||||
|
||||
if (tmp != NULL) free(tmp);
|
||||
if (tmp2 != NULL) free(tmp2);
|
||||
|
||||
free(pswd);
|
||||
free(fuzz_usrnm);
|
||||
fuzz_random_destroy();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
107
fuzz/fuzz_randomizer.cpp
Normal file
107
fuzz/fuzz_randomizer.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* 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 <fuzzer/FuzzedDataProvider.h>
|
||||
#include <assert.h>
|
||||
|
||||
FuzzedDataProvider *prov = NULL;
|
||||
|
||||
extern "C" void fuzz_random_init(const uint8_t *data, size_t size) {
|
||||
assert(prov == NULL);
|
||||
prov = new FuzzedDataProvider(data, size);
|
||||
}
|
||||
|
||||
extern "C" void fuzz_random_destroy() {
|
||||
assert(prov != NULL);
|
||||
delete prov;
|
||||
prov = NULL;
|
||||
}
|
||||
|
||||
extern "C" char *get_random_string() {
|
||||
assert(prov != NULL);
|
||||
|
||||
std::string s1 = prov->ConsumeRandomLengthString();
|
||||
char *tmp = (char *)malloc(s1.size() + 1);
|
||||
memcpy(tmp, s1.c_str(), s1.size());
|
||||
tmp[s1.size()] = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
extern "C" int fuzz_randomizer_get_int(int min, int max) {
|
||||
assert(prov != NULL);
|
||||
return prov->ConsumeIntegralInRange<int>(min, max);
|
||||
}
|
||||
|
||||
extern "C" char *fuzz_random_get_string_max_length(int max_len) {
|
||||
assert(prov != NULL);
|
||||
|
||||
std::string s1 = prov->ConsumeBytesAsString(
|
||||
prov->ConsumeIntegralInRange<uint32_t>(1, max_len));
|
||||
char *tmp123 = (char*)malloc(s1.size()+1);
|
||||
memcpy(tmp123, s1.c_str(), s1.size());
|
||||
tmp123[s1.size()] = '\0';
|
||||
|
||||
return tmp123;
|
||||
}
|
||||
|
||||
extern "C" size_t fuzz_get_random_data(void *buf, size_t len) {
|
||||
assert(prov != NULL);
|
||||
size_t ret_val;
|
||||
char *cbuf = (char*)buf;
|
||||
|
||||
if (prov->remaining_bytes() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
double prob = prov->ConsumeProbability<double>();
|
||||
if (prob < 0.05) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//if (len == 1) {
|
||||
// ret_val = prov->ConsumeData(buf, 1);
|
||||
// return ret_val;
|
||||
//}
|
||||
ret_val = prov->ConsumeData(buf, len);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
// Simple garbage collector
|
||||
#define GB_SIZE 100
|
||||
void *pointer_arr[GB_SIZE];
|
||||
static int pointer_idx = 0;
|
||||
|
||||
// If the garbage collector is used then this must be called as first thing
|
||||
// during a fuzz run.
|
||||
extern "C" void gb_init() {
|
||||
pointer_idx = 0;
|
||||
|
||||
for (int i = 0; i < GB_SIZE; i++) {
|
||||
pointer_arr[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void gb_cleanup() {
|
||||
for(int i = 0; i < GB_SIZE; i++) {
|
||||
if (pointer_arr[i] != NULL) {
|
||||
free(pointer_arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" char *gb_get_random_string() {
|
||||
char *tmp = get_random_string();
|
||||
pointer_arr[pointer_idx++] = (void*)tmp;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
27
fuzz/fuzz_randomizer.h
Normal file
27
fuzz/fuzz_randomizer.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void fuzz_random_init(const uint8_t *data, size_t size);
|
||||
void fuzz_random_destroy();
|
||||
char *get_random_string();
|
||||
int fuzz_randomizer_get_int(int min, int max);
|
||||
size_t fuzz_get_random_data(void *buf, size_t len);
|
||||
char *fuzz_random_get_string_max_length(int max_len);
|
||||
|
||||
void gb_init();
|
||||
void gb_cleanup();
|
||||
char *gb_get_random_string();
|
||||
|
||||
int fuzz_success;
|
||||
207
fuzz/fuzz_route.c
Normal file
207
fuzz/fuzz_route.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/* 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 "syshead.h"
|
||||
#include "init.h"
|
||||
#include "proxy.h"
|
||||
#include "interval.h"
|
||||
#include "route.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
gb_init();
|
||||
|
||||
struct route_option_list *opt;
|
||||
struct route_list rl;
|
||||
|
||||
int route_list_inited = 0;
|
||||
int route_list_ipv6_inited = 0;
|
||||
|
||||
struct context c;
|
||||
memset(&c, 0, sizeof(struct context));
|
||||
gc_init(&c.gc);
|
||||
c.es = env_set_create(&c.gc);
|
||||
init_options(&c.options, true);
|
||||
net_ctx_init(&c, &c.net_ctx);
|
||||
init_verb_mute(&c, IVM_LEVEL_1);
|
||||
|
||||
init_options_dev(&c.options);
|
||||
|
||||
// options_postprocess(&c.options);
|
||||
pre_setup(&c.options);
|
||||
|
||||
setenv_settings(c.es, &c.options);
|
||||
|
||||
ALLOC_OBJ_CLEAR_GC(c.options.ce.local_list, struct local_list, &c.options.gc);
|
||||
ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list,
|
||||
&c.options.gc);
|
||||
context_init_1(&c);
|
||||
|
||||
in_addr_t remote_host;
|
||||
ssize_t default_metric;
|
||||
|
||||
struct route_ipv6_list rl6;
|
||||
struct route_ipv6_option_list *opt6;
|
||||
|
||||
memset(&rl, 0, sizeof(rl));
|
||||
memset(&rl6, 0, sizeof(rl6));
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
memset(&opt6, 0, sizeof(opt6));
|
||||
|
||||
opt6 = new_route_ipv6_option_list(&c.gc);
|
||||
opt = new_route_option_list(&c.gc);
|
||||
|
||||
int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
|
||||
for (int i = 0; i < total_to_fuzz; i++) {
|
||||
int selector = fuzz_randomizer_get_int(0, 13);
|
||||
switch (selector) {
|
||||
case 0:
|
||||
if (route_list_inited == 0) {
|
||||
const char *remote_endpoint = gb_get_random_string();
|
||||
memset(&rl, 0, sizeof(struct route_list));
|
||||
rl.flags = fuzz_randomizer_get_int(0, 0xffffff);
|
||||
|
||||
init_route_list(&rl, opt, remote_endpoint, default_metric, remote_host,
|
||||
c.es, &c);
|
||||
route_list_inited = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (route_list_inited) {
|
||||
in_addr_t addr;
|
||||
route_list_add_vpn_gateway(&rl, c.es, addr);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (route_list_inited && route_list_ipv6_inited) {
|
||||
struct tuntap tt;
|
||||
memset(&tt, 0, sizeof(tt));
|
||||
add_routes(&rl, &rl6, &tt, 0, c.es, &c);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (route_list_inited) {
|
||||
setenv_routes(c.es, &rl);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (route_list_inited) {
|
||||
struct route_ipv4 r;
|
||||
struct route_option ro;
|
||||
ro.network = gb_get_random_string();
|
||||
ro.netmask = gb_get_random_string();
|
||||
ro.gateway = gb_get_random_string();
|
||||
ro.metric = gb_get_random_string();
|
||||
ro.next = NULL;
|
||||
|
||||
memset(&r, 0, sizeof(struct route_ipv4));
|
||||
r.option = &ro;
|
||||
r.flags = RT_DEFINED;
|
||||
add_route(&r, NULL, 0, NULL, c.es, &c);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (route_list_inited) {
|
||||
char *s1 = get_random_string();
|
||||
is_special_addr(s1);
|
||||
free(s1);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (route_list_ipv6_inited == 0) {
|
||||
const char *remote_endpoint = gb_get_random_string();
|
||||
memset(&rl, 0, sizeof(struct route_list));
|
||||
struct in6_addr remote_host;
|
||||
|
||||
rl6.rgi6.flags = fuzz_randomizer_get_int(0, 0xffffff);
|
||||
fuzz_get_random_data(&rl6.rgi6.hwaddr, 6);
|
||||
|
||||
char *t1 = gb_get_random_string();
|
||||
if (strlen(t1) > 16) {
|
||||
memcpy(rl6.rgi6.iface, t1, 16);
|
||||
} else {
|
||||
memcpy(rl6.rgi6.iface, t1, strlen(t1));
|
||||
}
|
||||
|
||||
init_route_ipv6_list(&rl6, opt6, remote_endpoint, 0, &remote_host, c.es,
|
||||
&c);
|
||||
route_list_ipv6_inited = 1;
|
||||
}
|
||||
break;
|
||||
case 7: {
|
||||
unsigned int flags;
|
||||
struct route_ipv6 r6;
|
||||
struct tuntap tt;
|
||||
memset(&tt, 0, sizeof(tt));
|
||||
tt.actual_name = gb_get_random_string();
|
||||
r6.iface = gb_get_random_string();
|
||||
r6.flags = fuzz_randomizer_get_int(0, 0xfffff);
|
||||
r6.netbits = fuzz_randomizer_get_int(0, 0xfffff);
|
||||
r6.metric = fuzz_randomizer_get_int(0, 0xfffff);
|
||||
|
||||
r6.next = NULL;
|
||||
|
||||
add_route_ipv6(&r6, &tt, 0, c.es, &c);
|
||||
} break;
|
||||
case 8:
|
||||
if (route_list_ipv6_inited && route_list_inited) {
|
||||
delete_routes(&rl, &rl6, NULL, 0, c.es, &c);
|
||||
route_list_ipv6_inited = 0;
|
||||
route_list_inited = 0;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (route_list_ipv6_inited) {
|
||||
setenv_routes_ipv6(c.es, &rl6);
|
||||
}
|
||||
break;
|
||||
case 10: {
|
||||
add_route_ipv6_to_option_list(opt6,
|
||||
gb_get_random_string(),
|
||||
gb_get_random_string(),
|
||||
gb_get_random_string(),
|
||||
fuzz_randomizer_get_int(0, 100));
|
||||
} break;
|
||||
case 11: {
|
||||
print_route_options(opt, M_NONFATAL);
|
||||
} break;
|
||||
case 12: {
|
||||
add_route_to_option_list(opt,
|
||||
gb_get_random_string(),
|
||||
gb_get_random_string(),
|
||||
gb_get_random_string(),
|
||||
gb_get_random_string(),
|
||||
fuzz_randomizer_get_int(0, 100));
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (route_list_inited) {
|
||||
gc_free(&rl.gc);
|
||||
}
|
||||
env_set_destroy(c.es);
|
||||
context_gc_free(&c);
|
||||
|
||||
fuzz_random_destroy();
|
||||
|
||||
gb_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
167
fuzz/fuzz_verify_cert.c
Normal file
167
fuzz/fuzz_verify_cert.c
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/* 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 "syshead.h"
|
||||
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "fuzz_verify_cert.h"
|
||||
#include "misc.h"
|
||||
#include "manage.h"
|
||||
#include "otime.h"
|
||||
#include "base64.h"
|
||||
#include "ssl_verify.h"
|
||||
#include "ssl_verify_backend.h"
|
||||
|
||||
#include "fuzz_randomizer.h"
|
||||
|
||||
|
||||
static int parse_x509(const uint8_t *data, size_t size, X509 **out) {
|
||||
*out = d2i_X509(NULL, (const unsigned char **)&data, size);
|
||||
if (*out == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
OPENSSL_malloc_init();
|
||||
SSL_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
|
||||
SSL_load_error_strings();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int init_session_opt(struct tls_options **_opt, struct gc_arena *gc) {
|
||||
ssize_t nid;
|
||||
ssize_t generic_ssizet;
|
||||
struct tls_options *opt;
|
||||
int r;
|
||||
|
||||
ALLOC_OBJ_GC(*_opt, struct tls_options, gc);
|
||||
if (opt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt = *_opt;
|
||||
|
||||
memset(opt, 0xFE, sizeof(struct tls_options));
|
||||
|
||||
opt->es = env_set_create(gc);
|
||||
opt->x509_username_field[0] = NULL;
|
||||
opt->remote_cert_eku = NULL;
|
||||
|
||||
/* Prevents failure if x509 sha1 hashes do not match */
|
||||
opt->verify_hash = NULL;
|
||||
|
||||
/* Prevent attempt to run --tls-verify script */
|
||||
opt->verify_command = NULL;
|
||||
|
||||
/* Do not verify against CRL file */
|
||||
opt->crl_file = NULL;
|
||||
|
||||
/* Do not run --tls-verify plugins */
|
||||
opt->plugins = NULL;
|
||||
|
||||
r = fuzz_randomizer_get_int(0, 1);
|
||||
if (r == 0) {
|
||||
opt->x509_username_field[0] = nidstrs[fuzz_randomizer_get_int(0, (sizeof(nidstrs)/sizeof(nidstrs[0])) - 1)];
|
||||
}
|
||||
else {
|
||||
opt->x509_username_field[0] = "ext:subjectAltName";
|
||||
}
|
||||
opt->x509_username_field[1] = NULL;
|
||||
|
||||
r = fuzz_randomizer_get_int(0, 2);
|
||||
if (r == 0)
|
||||
opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
|
||||
else if (r == 1)
|
||||
opt->ns_cert_type = NS_CERT_CHECK_SERVER;
|
||||
else
|
||||
opt->ns_cert_type = NS_CERT_CHECK_NONE;
|
||||
|
||||
opt->x509_track = NULL;
|
||||
|
||||
r = fuzz_randomizer_get_int(0, 1);
|
||||
if (r == 0)
|
||||
opt->remote_cert_eku = NULL;
|
||||
else
|
||||
opt->remote_cert_eku = get_random_string();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init_session(struct tls_session **_session, struct gc_arena *gc) {
|
||||
struct tls_session *session;
|
||||
|
||||
ALLOC_OBJ_GC(*_session, struct tls_session, gc);
|
||||
if (*_session == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
session = *_session;
|
||||
memset(session, 0xFE, sizeof(struct tls_session));
|
||||
|
||||
/* Accessed in set_common_name() */
|
||||
session->common_name = get_random_string();;
|
||||
|
||||
/* Initialize the session->opt structure */
|
||||
if (init_session_opt(&(session->opt), gc) == -1) {
|
||||
free(session->common_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Accessed in server_untrusted() */
|
||||
session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
fuzz_random_init(data, size);
|
||||
|
||||
struct gc_arena gc;
|
||||
struct tls_session *session = NULL;
|
||||
X509 *x509 = NULL;
|
||||
gc = gc_new();
|
||||
|
||||
if (parse_x509(data, size, &x509) == 0) {
|
||||
if (init_session(&session, &gc) == 0) {
|
||||
verify_cert(session, x509, 100);
|
||||
if (session->opt->remote_cert_eku != NULL) {
|
||||
free(session->opt->remote_cert_eku);
|
||||
}
|
||||
free(session->common_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
X509_free(x509);
|
||||
gc_free(&gc);
|
||||
|
||||
fuzz_random_destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
1065
fuzz/fuzz_verify_cert.h
Normal file
1065
fuzz/fuzz_verify_cert.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue