mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-06-09 00:42:51 -04:00
Create fuzzing basis + base64 fuzzer
Signed-off-by: Guido Vranken <guidovranken@gmail.com>
This commit is contained in:
parent
0402c7faad
commit
c48481d1bc
8 changed files with 405 additions and 11 deletions
|
|
@ -364,6 +364,7 @@ esac
|
|||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_SED
|
||||
|
|
@ -582,6 +583,11 @@ AC_COMPILE_IFELSE(
|
|||
[AC_MSG_RESULT([no])]
|
||||
)
|
||||
|
||||
CFLAGS="${CFLAGS} -DFUZZING -g3 -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp -fsanitize=address -fsanitize=undefined -fsanitize-recover=alignment"
|
||||
CXXFLAGS="${CXXFLAGS} -DFUZZING -g3 -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp -fsanitize=address -fsanitize=undefined -fsanitize-recover=alignment"
|
||||
CC="clang"
|
||||
CXX="clang++"
|
||||
|
||||
saved_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -Wl,--wrap=exit"
|
||||
AC_MSG_CHECKING([linker supports --wrap])
|
||||
|
|
|
|||
|
|
@ -35,9 +35,8 @@ if WIN32
|
|||
AM_CFLAGS += -municode -UUNICODE
|
||||
endif
|
||||
|
||||
sbin_PROGRAMS = openvpn
|
||||
|
||||
openvpn_SOURCES = \
|
||||
lib_LTLIBRARIES = libopenvpn.la
|
||||
libopenvpn_la_SOURCES = \
|
||||
argv.c argv.h \
|
||||
base64.c base64.h \
|
||||
basic.h \
|
||||
|
|
@ -120,17 +119,39 @@ openvpn_SOURCES = \
|
|||
tun.c tun.h \
|
||||
win32.h win32.c \
|
||||
cryptoapi.h cryptoapi.c
|
||||
openvpn_LDADD = \
|
||||
$(top_builddir)/src/compat/libcompat.la \
|
||||
|
||||
libopenvpn_la_SOURCES += \
|
||||
fuzzing.h fuzzing.c
|
||||
|
||||
extra_PROGRAMS = \
|
||||
openvpn-fuzzer-base64 openvpn-fuzzer-base64-standalone
|
||||
extradir = .
|
||||
fuzzer_sources = dummy.cpp
|
||||
fuzzer_cflags = \
|
||||
$(TAP_CFLAGS) \
|
||||
$(OPTIONAL_CRYPTO_CFLAGS) \
|
||||
$(OPTIONAL_LZO_CFLAGS) \
|
||||
$(OPTIONAL_LZ4_CFLAGS) \
|
||||
$(OPTIONAL_PKCS11_HELPER_CFLAGS) \
|
||||
-DPLUGIN_LIBDIR=\"${plugindir}\"
|
||||
fuzzer_ldflags = -static
|
||||
fuzzer_ldadd = \
|
||||
$(SOCKETS_LIBS) \
|
||||
$(OPTIONAL_LZO_LIBS) \
|
||||
$(OPTIONAL_LZ4_LIBS) \
|
||||
$(OPTIONAL_PKCS11_HELPER_LIBS) \
|
||||
$(OPTIONAL_CRYPTO_LIBS) \
|
||||
$(OPTIONAL_SELINUX_LIBS) \
|
||||
$(OPTIONAL_SYSTEMD_LIBS) \
|
||||
$(OPTIONAL_DL_LIBS)
|
||||
if WIN32
|
||||
openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h
|
||||
openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4
|
||||
endif
|
||||
$(OPTIONAL_DL_LIBS) \
|
||||
libopenvpn.la \
|
||||
$(top_builddir)/src/compat/libcompat.la \
|
||||
$(OPTIONAL_LZO_LIBS)
|
||||
|
||||
openvpn_fuzzer_base64_SOURCES = $(fuzzer_sources)
|
||||
openvpn_fuzzer_base64_LDFLAGS = $(fuzzer_ldflags)
|
||||
openvpn_fuzzer_base64_CFLAGS = $(fuzzer_cflags)
|
||||
openvpn_fuzzer_base64_LDADD = $(fuzzer_ldadd) fuzzer-base64.o libFuzzer.a
|
||||
openvpn_fuzzer_base64_standalone_SOURCES = fuzzer-standalone-loader.c
|
||||
openvpn_fuzzer_base64_standalone_LDFLAGS = $(fuzzer_ldflags)
|
||||
openvpn_fuzzer_base64_standalone_CFLAGS = $(fuzzer_cflags)
|
||||
openvpn_fuzzer_base64_standalone_LDADD = $(fuzzer_ldadd) fuzzer-base64.o
|
||||
|
|
|
|||
0
src/openvpn/dummy.cpp
Normal file
0
src/openvpn/dummy.cpp
Normal file
52
src/openvpn/fuzzer-base64.c
Normal file
52
src/openvpn/fuzzer-base64.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include "config.h"
|
||||
#include "syshead.h"
|
||||
#ifdef FUZZING
|
||||
#if defined(ENABLE_CRYPTO) && defined(ENABLE_CRYPTO_OPENSSL)
|
||||
#elif defined(ENABLE_CRYPTO) && defined(ENABLE_CRYPTO_MBEDTLS)
|
||||
#else
|
||||
#error "This fuzzing target cannot be built"
|
||||
#endif
|
||||
|
||||
|
||||
#include "fuzzing.h"
|
||||
#include "base64.h"
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
char* str = NULL;
|
||||
unsigned char* outbuf;
|
||||
uint16_t* outsize;
|
||||
int ret;
|
||||
if ( size < sizeof(*outsize) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
outsize = (uint16_t*)data;
|
||||
data += sizeof(*outsize);
|
||||
size -= sizeof(*outsize);
|
||||
if ( openvpn_base64_encode(data, size, &str) > 0 )
|
||||
{
|
||||
#ifdef MSAN
|
||||
test_undefined_memory(str, strlen(str)+1);
|
||||
#endif
|
||||
}
|
||||
free(str);
|
||||
str = malloc(size+1);
|
||||
memcpy(str, (char*)data, size);
|
||||
str[size] = 0;
|
||||
outbuf = malloc(*outsize);
|
||||
if ( (ret = openvpn_base64_decode(str, outbuf, *outsize)) > 0 )
|
||||
{
|
||||
#ifdef MSAN
|
||||
test_undefined_memory(outbuf, ret);
|
||||
#endif
|
||||
}
|
||||
free(str);
|
||||
free(outbuf);
|
||||
return 0;
|
||||
}
|
||||
#endif /* FUZZING */
|
||||
30
src/openvpn/fuzzer-standalone-loader.c
Normal file
30
src/openvpn/fuzzer-standalone-loader.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int n;
|
||||
|
||||
for (n = 1; n < argc; ++n) {
|
||||
struct stat st;
|
||||
FILE *f;
|
||||
unsigned char *buf;
|
||||
size_t s;
|
||||
|
||||
stat(argv[n], &st);
|
||||
f = fopen(argv[n], "rb");
|
||||
if (f == NULL)
|
||||
continue;
|
||||
buf = malloc(st.st_size);
|
||||
s = fread(buf, 1, st.st_size, f);
|
||||
LLVMFuzzerInitialize(NULL, NULL);
|
||||
LLVMFuzzerTestOneInput(buf, s);
|
||||
free(buf);
|
||||
fclose(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
236
src/openvpn/fuzzing.c
Normal file
236
src/openvpn/fuzzing.c
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
#ifdef FUZZING
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include "config-msvc.h"
|
||||
#endif
|
||||
#include "syshead.h"
|
||||
#include "buffer.h"
|
||||
#include "fuzzing.h"
|
||||
|
||||
static unsigned char* fuzzer_data = NULL;
|
||||
static size_t fuzzer_data_size = 0;
|
||||
|
||||
void fuzzer_set_input(unsigned char* data, size_t size)
|
||||
{
|
||||
fuzzer_data = data;
|
||||
fuzzer_data_size = size;
|
||||
}
|
||||
|
||||
unsigned char* fuzzer_get_current_data(void)
|
||||
{
|
||||
return fuzzer_data;
|
||||
}
|
||||
|
||||
size_t fuzzer_get_current_size(void)
|
||||
{
|
||||
return fuzzer_data_size;
|
||||
}
|
||||
|
||||
static int recv_no_rnd = 0;
|
||||
void fuzzer_set_recv_no_rnd(int yesno)
|
||||
{
|
||||
recv_no_rnd = yesno;
|
||||
}
|
||||
|
||||
ssize_t fuzzer_get_data(void* dest, size_t size)
|
||||
{
|
||||
if ( size > fuzzer_data_size )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dest, fuzzer_data, size);
|
||||
|
||||
fuzzer_data += size;
|
||||
fuzzer_data_size -= size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
|
||||
{
|
||||
size_t realsize;
|
||||
unsigned int realsize_ui;
|
||||
unsigned short realsize_us;
|
||||
unsigned char realsize_uc;
|
||||
|
||||
if ( size == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( size > 0x7FFFFFFF )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( size > 65535 )
|
||||
{
|
||||
if ( fuzzer_get_data(&realsize_ui, sizeof(realsize_ui)) < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
realsize = realsize_ui;
|
||||
}
|
||||
else if ( size > 255 )
|
||||
{
|
||||
if ( fuzzer_get_data(&realsize_us, sizeof(realsize_us)) < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
realsize = realsize_us;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( fuzzer_get_data(&realsize_uc, sizeof(realsize_uc)) < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
realsize = realsize_uc;
|
||||
}
|
||||
|
||||
realsize %= (size+1);
|
||||
|
||||
return fuzzer_get_data(dest, realsize);
|
||||
}
|
||||
|
||||
ssize_t fuzzer_get_integer(size_t max)
|
||||
{
|
||||
size_t s;
|
||||
|
||||
if ( max == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( max > 0x7FFFFFFF )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
if ( fuzzer_get_data(&s, sizeof(s)) < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s % (max+1);
|
||||
}
|
||||
|
||||
static char* fuzzer_get_string_inner(size_t maxsize, struct gc_arena* gc)
|
||||
{
|
||||
ssize_t strsize;
|
||||
char* ret;
|
||||
|
||||
if ( (strsize = fuzzer_get_integer(maxsize)) < 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( gc == NULL )
|
||||
{
|
||||
ret = malloc(strsize+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ALLOC_ARRAY_GC(ret, char, strsize+1, gc);
|
||||
}
|
||||
|
||||
if ( ret == NULL )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( fuzzer_get_data(ret, strsize) < 0 )
|
||||
{
|
||||
if ( gc == NULL )
|
||||
{
|
||||
free(ret);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret[strsize] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* fuzzer_get_string(size_t maxsize)
|
||||
{
|
||||
return fuzzer_get_string_inner(maxsize, NULL);
|
||||
}
|
||||
|
||||
char* fuzzer_get_string_gc(size_t maxsize, struct gc_arena* gc)
|
||||
{
|
||||
return fuzzer_get_string_inner(maxsize, gc);
|
||||
}
|
||||
|
||||
ssize_t fuzzer_read(void* dest, size_t size)
|
||||
{
|
||||
if ( recv_no_rnd )
|
||||
{
|
||||
return fuzzer_get_data(dest, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fuzzer_get_data_rnd(dest, size);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fuzzer_recv(void* dest, size_t size)
|
||||
{
|
||||
if ( recv_no_rnd )
|
||||
{
|
||||
return fuzzer_get_data(dest, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fuzzer_get_data_rnd(dest, size);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fuzzer_send(size_t size)
|
||||
{
|
||||
/*
|
||||
ssize_t r = fuzzer_get_integer(size);
|
||||
|
||||
if ( r < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
return size;
|
||||
//return r;
|
||||
}
|
||||
|
||||
void fuzzer_alter_buffer(struct buffer* buffer)
|
||||
{
|
||||
ssize_t newoffset, newlen;
|
||||
if ( buffer->capacity == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
FUZZER_GET_INTEGER(newoffset, buffer->capacity);
|
||||
newlen = buffer->capacity - newoffset;
|
||||
if ( newlen != 0 )
|
||||
{
|
||||
FUZZER_GET_INTEGER(newlen, newlen);
|
||||
}
|
||||
buffer->offset = newoffset;
|
||||
buffer->len = newlen;
|
||||
|
||||
return;
|
||||
cleanup:
|
||||
return;
|
||||
}
|
||||
|
||||
void test_undefined_memory(void* vp, size_t s)
|
||||
{
|
||||
FILE* fp = fopen("/dev/null", "wb");
|
||||
unsigned char* p = (unsigned char*)vp;
|
||||
fwrite(p, s, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
47
src/openvpn/fuzzing.h
Normal file
47
src/openvpn/fuzzing.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifdef FUZZING
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include "config-msvc.h"
|
||||
#endif
|
||||
#include "syshead.h"
|
||||
#include "buffer.h"
|
||||
void fuzzer_set_input(unsigned char* data, size_t size);
|
||||
unsigned char* fuzzer_get_current_data(void);
|
||||
size_t fuzzer_get_current_size(void);
|
||||
void fuzzer_set_recv_no_rnd(int yesno);
|
||||
ssize_t fuzzer_get_data(void* dest, size_t size);
|
||||
ssize_t fuzzer_get_data_rnd(void* dest, size_t size);
|
||||
ssize_t fuzzer_get_integer(size_t max);
|
||||
char* fuzzer_get_string(size_t maxsize);
|
||||
char* fuzzer_get_string_gc(size_t maxsize, struct gc_arena* gc);
|
||||
ssize_t fuzzer_read(void* dest, size_t size);
|
||||
ssize_t fuzzer_recv(void* dest, size_t size);
|
||||
ssize_t fuzzer_send(size_t size);
|
||||
void fuzzer_alter_buffer(struct buffer* buffer);
|
||||
void test_undefined_memory(void* vp, size_t s);
|
||||
#define FUZZER_GET_DATA(dest, size) { \
|
||||
if ( fuzzer_get_data((dest), (size)) < 0 ) { \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
#define FUZZER_GET_INTEGER(dest, max) { \
|
||||
(dest) = fuzzer_get_integer(max); \
|
||||
if ( (dest) < 0 ) { \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
#define FUZZER_GET_STRING(dest, max) { \
|
||||
(dest) = NULL; \
|
||||
if ( ((dest) = fuzzer_get_string(max)) == NULL ) { \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FUZZER_GET_STRING_GC(dest, max, gc) { \
|
||||
(dest) = NULL; \
|
||||
if ( ((dest) = fuzzer_get_string_gc((max), (gc))) == NULL ) { \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
|
@ -329,6 +329,7 @@ openvpn_main(int argc, char *argv[])
|
|||
return 0; /* NOTREACHED */
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef _WIN32
|
||||
int
|
||||
wmain(int argc, wchar_t *wargv[])
|
||||
|
|
@ -366,3 +367,4 @@ main(int argc, char *argv[])
|
|||
return openvpn_main(argc, argv);
|
||||
}
|
||||
#endif /* ifdef _WIN32 */
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue