]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Create fuzzing basis + base64 fuzzer
authorGuido Vranken <guidovranken@gmail.com>
Fri, 23 Jun 2017 12:51:55 +0000 (14:51 +0200)
committerGuido Vranken <guidovranken@gmail.com>
Fri, 23 Jun 2017 12:51:55 +0000 (14:51 +0200)
Signed-off-by: Guido Vranken <guidovranken@gmail.com>
configure.ac
src/openvpn/Makefile.am
src/openvpn/dummy.cpp [new file with mode: 0644]
src/openvpn/fuzzer-base64.c [new file with mode: 0644]
src/openvpn/fuzzer-standalone-loader.c [new file with mode: 0644]
src/openvpn/fuzzing.c [new file with mode: 0644]
src/openvpn/fuzzing.h [new file with mode: 0644]
src/openvpn/openvpn.c

index 22f91cb608afc4bf01ce84581447c0bc46335bce..0d4e00b12320eee57d3105c608a3bc462d18ac61 100644 (file)
@@ -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])
index fcc22d684f90879a4061a721a64ed2305531c9ad..83126a23417534c60bf95c38969c763bd2aafb9e 100644 (file)
@@ -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
diff --git a/src/openvpn/dummy.cpp b/src/openvpn/dummy.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/openvpn/fuzzer-base64.c b/src/openvpn/fuzzer-base64.c
new file mode 100644 (file)
index 0000000..cddd1b1
--- /dev/null
@@ -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 */
diff --git a/src/openvpn/fuzzer-standalone-loader.c b/src/openvpn/fuzzer-standalone-loader.c
new file mode 100644 (file)
index 0000000..c738287
--- /dev/null
@@ -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;
+}
diff --git a/src/openvpn/fuzzing.c b/src/openvpn/fuzzing.c
new file mode 100644 (file)
index 0000000..2bf3175
--- /dev/null
@@ -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
diff --git a/src/openvpn/fuzzing.h b/src/openvpn/fuzzing.h
new file mode 100644 (file)
index 0000000..0dec200
--- /dev/null
@@ -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
index 08c09e6bedb1d56076682ca1705c6e7bf2561308..a89beba89956a87e46ab530695012c38df258afd 100644 (file)
@@ -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