From 2c64335d9cfab7674ff5c247208abb4661335c43 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Thu, 3 Dec 2020 22:18:51 +0800
Subject: [PATCH] fuzz: make postauth set authdone properly

---
 fuzz-wrapfd.h      |  4 ++--
 fuzz.h             |  5 ++++-
 fuzz/fuzz-common.c | 16 ++++++++++------
 svr-session.c      |  6 ++++++
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/fuzz-wrapfd.h b/fuzz-wrapfd.h
index 56bbc6e..6677e62 100644
--- a/fuzz-wrapfd.h
+++ b/fuzz-wrapfd.h
@@ -12,8 +12,8 @@ enum wrapfd_mode {
 // 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_fuzzinput();
-int wrapfd_new_dummy();
+int wrapfd_new_fuzzinput(void);
+int wrapfd_new_dummy(void);
 
 // called via #defines for read/write/select
 int wrapfd_read(int fd, void *out, size_t count);
diff --git a/fuzz.h b/fuzz.h
index cc013cb..21fb1f9 100644
--- a/fuzz.h
+++ b/fuzz.h
@@ -24,7 +24,7 @@ void fuzz_early_setup(void) __attribute__((constructor));
 // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE
 int fuzz_set_input(const uint8_t *Data, size_t Size);
 
-int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone);
+int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth);
 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);
 
@@ -35,6 +35,7 @@ int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
         const unsigned char* keyblob, unsigned int keybloblen);
 extern const char * const * fuzz_signkey_names;
 void fuzz_seed(const unsigned char* dat, unsigned int len);
+void fuzz_svr_hook_preloop(void);
 
 typedef void(*connect_callback)(int result, int sock, void* data, const char* errstring);
 struct dropbear_progress_connection *fuzz_connect_remote(const char* remotehost, const char* remoteport,
@@ -68,6 +69,8 @@ struct dropbear_fuzz_options {
 
     // whether to skip slow bignum maths
     int skip_kexmaths;
+    // whether is svr_postauth mode
+    int svr_postauth;
 
     // dropbear_exit() jumps back
     int do_jmp;
diff --git a/fuzz/fuzz-common.c b/fuzz/fuzz-common.c
index 4a9634a..b43ba9b 100644
--- a/fuzz/fuzz-common.c
+++ b/fuzz/fuzz-common.c
@@ -102,6 +102,13 @@ void fuzz_svr_setup(void) {
     load_fixed_hostkeys();
 }
 
+void fuzz_svr_hook_preloop() {
+    if (fuzz.svr_postauth) {
+        ses.authstate.authdone = 1;
+        fill_passwd("root");
+    }
+}
+
 void fuzz_cli_setup(void) {
     fuzz_common_setup();
     
@@ -242,7 +249,7 @@ struct dropbear_progress_connection *fuzz_connect_remote(const char* UNUSED(remo
     return NULL;
 }
 
-int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int authdone) {
+int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth) {
     static int once = 0;
     if (!once) {
         fuzz_svr_setup();
@@ -250,6 +257,8 @@ int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int aut
         once = 1;
     }
 
+    fuzz.svr_postauth = postauth;
+
     if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) {
         return 0;
     }
@@ -260,11 +269,6 @@ int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int aut
 
     int fakesock = wrapfd_new_fuzzinput();
 
-    if (authdone) {
-        ses.authstate.authdone = 1;
-        fill_passwd("root");
-    }
-
     m_malloc_set_epoch(1);
     fuzz.do_jmp = 1;
     if (setjmp(fuzz.jmp) == 0) {
diff --git a/svr-session.c b/svr-session.c
index 6c3147f..63c675c 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -195,6 +195,12 @@ void svr_session(int sock, int childpipe) {
 	/* start off with key exchange */
 	send_msg_kexinit();
 
+#if DROPBEAR_FUZZ
+    if (fuzz.fuzzing) {
+        fuzz_svr_hook_preloop();
+    }
+#endif
+
 	/* Run the main for loop. NULL is for the dispatcher - only the client
 	 * code makes use of it */
 	session_loop(svr_chansess_checksignal);