changeset 1777:97ad26e397a5

Add server postauth fuzzer, wrap connect_remote()
author Matt Johnston <matt@ucc.asn.au>
date Fri, 13 Nov 2020 23:18:05 +0800
parents 290caf301a4f
children 19cdeb3d2aac
files Makefile.in fuzz-wrapfd.h fuzz.h fuzz/fuzz-common.c fuzz/fuzz-wrapfd.c fuzz/fuzzer-postauth_nomaths.c fuzz/fuzzer-preauth.c fuzz/fuzzer-preauth_nomaths.c fuzz/fuzzer-pubkey.c netio.c
diffstat 10 files changed, 72 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.in	Fri Nov 13 23:16:50 2020 +0800
+++ b/Makefile.in	Fri Nov 13 23:18:05 2020 +0800
@@ -269,7 +269,8 @@
 
 # list of fuzz targets
 FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths \
-	fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths
+	fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths \
+	fuzzer-postauth_nomaths
 
 FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS))
 FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) \
@@ -294,7 +295,7 @@
 
 # fuzzers that use the custom mutator - these expect a SSH network stream
 MUTATOR_FUZZERS=fuzzer-client fuzzer-client_nomaths \
-	fuzzer-preauth fuzzer-preauth_nomaths
+	fuzzer-preauth fuzzer-preauth_nomaths fuzzer-postauth_nomaths
 $(MUTATOR_FUZZERS): allobjs += fuzz/fuzz-sshpacketmutator.o
 
 fuzzer-%.options: Makefile
--- a/fuzz-wrapfd.h	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz-wrapfd.h	Fri Nov 13 23:18:05 2020 +0800
@@ -6,12 +6,14 @@
 enum wrapfd_mode {
     UNUSED = 0,
     COMMONBUF, // using the common buffer
+    DUMMY, // reads return fixed output, of random length
 };
 
 // buf is a common buffer read by all wrapped FDs. doesn't take ownership of buf
 void wrapfd_setup(buffer *buf);
 void wrapfd_setseed(uint32_t seed);
-int wrapfd_new();
+int wrapfd_new_fuzzinput();
+int wrapfd_new_dummy();
 
 // called via #defines for read/write/select
 int wrapfd_read(int fd, void *out, size_t count);
--- a/fuzz.h	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz.h	Fri Nov 13 23:18:05 2020 +0800
@@ -23,7 +23,7 @@
 // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
 int fuzz_set_input(const uint8_t *Data, size_t Size);
 
-int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths);
+int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone);
 int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths);
 const void* fuzz_get_algo(const algo_type *algos, const char* name);
 
--- a/fuzz/fuzz-common.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz/fuzz-common.c	Fri Nov 13 23:18:05 2020 +0800
@@ -217,16 +217,31 @@
 
 /* fake version of spawn_command() */
 int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
-    *ret_writefd = wrapfd_new();
-    *ret_readfd = wrapfd_new();
+    *ret_writefd = wrapfd_new_dummy();
+    *ret_readfd = wrapfd_new_dummy();
     if (ret_errfd) {
-        *ret_errfd = wrapfd_new();
+        *ret_errfd = wrapfd_new_dummy();
     }
     *ret_pid = 999;
     return DROPBEAR_SUCCESS;
 }
 
-int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
+
+struct dropbear_progress_connection *fuzz_connect_remote(const char* UNUSED(remotehost), const char* UNUSED(remoteport),
+    connect_callback cb, void* cb_data, 
+    const char* UNUSED(bind_address), const char* UNUSED(bind_port)) {
+    char r;
+    genrandom((void*)&r, 1);
+    if (r & 1) {
+        int sock = wrapfd_new_dummy();
+        cb(DROPBEAR_SUCCESS, sock, cb_data, NULL);
+    } else {
+        cb(DROPBEAR_FAILURE, -1, cb_data, "errorstring");
+    }
+    return NULL;
+}
+
+int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone) {
     static int once = 0;
     if (!once) {
         fuzz_svr_setup();
@@ -242,7 +257,13 @@
     genrandom((void*)&wrapseed, sizeof(wrapseed));
     wrapfd_setseed(wrapseed);
 
-    int fakesock = wrapfd_new();
+    int fakesock = wrapfd_new_fuzzinput();
+
+    if (authdone) {
+        ses.authstate.authdone = 1;
+        char *me = getpwuid(getuid())->pw_name;
+        fill_passwd(me);
+    }
 
     m_malloc_set_epoch(1);
     fuzz.do_jmp = 1;
@@ -273,12 +294,13 @@
 
     // Allow to proceed sooner
     ses.kexstate.donefirstkex = 1;
+    ses.kexstate.authdone = 1;
 
     uint32_t wrapseed;
     genrandom((void*)&wrapseed, sizeof(wrapseed));
     wrapfd_setseed(wrapseed);
 
-    int fakesock = wrapfd_new();
+    int fakesock = wrapfd_new_fuzzinput();
 
     m_malloc_set_epoch(1);
     fuzz.do_jmp = 1;
--- a/fuzz/fuzz-wrapfd.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz/fuzz-wrapfd.c	Fri Nov 13 23:18:05 2020 +0800
@@ -35,7 +35,7 @@
 	// clean old ones
 	int i;
 	for (i = 0; i <= wrapfd_maxfd; i++) {
-		if (wrap_fds[i].mode == COMMONBUF) {
+		if (wrap_fds[i].mode != UNUSED) {
 			wrapfd_remove(i);
 		}
 	}
@@ -51,7 +51,7 @@
 	nrand48(rand_state);
 }
 
-int wrapfd_new() {
+int wrapfd_new_fuzzinput() {
 	if (devnull_fd == -1) {
 		devnull_fd = open("/dev/null", O_RDONLY);
 		assert(devnull_fd != -1);
@@ -68,6 +68,24 @@
 	return fd;
 }
 
+int wrapfd_new_dummy() {
+	if (devnull_fd == -1) {
+		devnull_fd = open("/dev/null", O_RDONLY);
+		assert(devnull_fd != -1);
+	}
+
+	int fd = dup(devnull_fd);
+	assert(fd != -1);
+	assert(wrap_fds[fd].mode == UNUSED);
+	wrap_fds[fd].mode = DUMMY;
+	wrap_fds[fd].closein = 0;
+	wrap_fds[fd].closeout = 0;
+	wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
+
+	return fd;
+}
+
+
 static void wrapfd_remove(int fd) {
 	TRACE(("wrapfd_remove %d", fd))
 	assert(fd >= 0);
@@ -113,7 +131,7 @@
 		return -1;
 	}
 
-	if (input_buf) {
+	if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
 		maxread = MIN(input_buf->len - input_buf->pos, count);
 		/* returns 0 if buf is EOF, as intended */
 		if (maxread > 0) {
@@ -124,6 +142,7 @@
 		return maxread;
 	}
 
+	// return fixed output, of random length
 	maxread = MIN(MAX_RANDOM_IN, count);
 	maxread = nrand48(rand_state) % maxread + 1;
 	memset(out, 0xef, maxread);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fuzz/fuzzer-postauth_nomaths.c	Fri Nov 13 23:18:05 2020 +0800
@@ -0,0 +1,6 @@
+#include "fuzz.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+	return fuzz_run_server(Data, Size, 1, 1);
+}
+
--- a/fuzz/fuzzer-preauth.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz/fuzzer-preauth.c	Fri Nov 13 23:18:05 2020 +0800
@@ -1,6 +1,6 @@
 #include "fuzz.h"
 
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-	return fuzz_run_preauth(Data, Size, 0);
+	return fuzz_run_server(Data, Size, 0, 0);
 }
 
--- a/fuzz/fuzzer-preauth_nomaths.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz/fuzzer-preauth_nomaths.c	Fri Nov 13 23:18:05 2020 +0800
@@ -1,6 +1,6 @@
 #include "fuzz.h"
 
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-	return fuzz_run_preauth(Data, Size, 1);
+	return fuzz_run_server(Data, Size, 1, 0);
 }
 
--- a/fuzz/fuzzer-pubkey.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/fuzz/fuzzer-pubkey.c	Fri Nov 13 23:18:05 2020 +0800
@@ -27,7 +27,7 @@
 		unsigned int algolen;
 		char* algoname = buf_getstring(keyblob, &algolen);
 
-		if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) {
+		if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNATURE_NONE) {
 			dropbear_exit("fuzzer imagined a bogus algorithm");
 		}
 
--- a/netio.c	Fri Nov 13 23:16:50 2020 +0800
+++ b/netio.c	Fri Nov 13 23:18:05 2020 +0800
@@ -179,6 +179,12 @@
 	int err;
 	struct addrinfo hints;
 
+#if DROPBEAR_FUZZ
+	if (fuzz.fuzzing) {
+		return fuzz_connect_remote(remotehost, remoteport, cb, cb_data, bind_address, bind_port);
+	}
+#endif
+
 	c = m_malloc(sizeof(*c));
 	c->remotehost = m_strdup(remotehost);
 	c->remoteport = m_strdup(remoteport);