# HG changeset patch # User Matt Johnston # Date 1605280685 -28800 # Node ID 97ad26e397a5a3f08eba459455b3e4ae56e6d526 # Parent 290caf301a4f6c0874321c98e9be1bbd122d53ee Add server postauth fuzzer, wrap connect_remote() diff -r 290caf301a4f -r 97ad26e397a5 Makefile.in --- 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 diff -r 290caf301a4f -r 97ad26e397a5 fuzz-wrapfd.h --- 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); diff -r 290caf301a4f -r 97ad26e397a5 fuzz.h --- 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); diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzz-common.c --- 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; diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzz-wrapfd.c --- 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); diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzzer-postauth_nomaths.c --- /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); +} + diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzzer-preauth.c --- 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); } diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzzer-preauth_nomaths.c --- 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); } diff -r 290caf301a4f -r 97ad26e397a5 fuzz/fuzzer-pubkey.c --- 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"); } diff -r 290caf301a4f -r 97ad26e397a5 netio.c --- 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);