mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	fuzz harness
--HG-- branch : fuzz
This commit is contained in:
		
							parent
							
								
									9f24cdf74c
								
							
						
					
					
						commit
						fb719e3d0b
					
				
							
								
								
									
										25
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Makefile.in
									
									
									
									
									
								
							| @ -30,7 +30,7 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \ | ||||
| 		queue.o \
 | ||||
| 		atomicio.o compat.o fake-rfc2553.o \
 | ||||
| 		ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
 | ||||
| 		gensignkey.o gendss.o genrsa.o | ||||
| 		gensignkey.o gendss.o genrsa.o fuzz-common.o  | ||||
| 
 | ||||
| SVROBJS=svr-kex.o svr-auth.o sshpty.o \
 | ||||
| 		svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
 | ||||
| @ -224,8 +224,27 @@ distclean: clean tidy | ||||
| tidy: | ||||
| 	-rm -f *~ *.gcov */*~ | ||||
| 
 | ||||
| # run this manually for fuzzing. hostkeys.c is checked in.
 | ||||
| hostkeys: | ||||
| ## Fuzzing targets
 | ||||
| 
 | ||||
| # exclude svr-main.o to avoid duplicate main
 | ||||
| svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs)) | ||||
| CLANG=clang | ||||
| 
 | ||||
| # fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
 | ||||
| fuzzstandalone: LIBS+=fuzz-harness.o | ||||
| fuzzstandalone: fuzz-harness.o fuzzers | ||||
| 
 | ||||
| # build all the fuzzers. This will require fail to link unless built with
 | ||||
| # make fuzzers LIBS=-lFuzzer.a 
 | ||||
| # or similar - the library provides main().
 | ||||
| fuzzers: fuzzer-preauth | ||||
| 
 | ||||
| fuzzer-preauth: fuzzer-preauth.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) | ||||
| 	$(CC) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@ | ||||
| 
 | ||||
| # run this to update hardcoded hostkeys for for fuzzing. 
 | ||||
| # hostkeys.c is checked in to hg.
 | ||||
| fuzz-hostkeys: | ||||
| 	dropbearkey -t rsa -f keyr | ||||
| 	dropbearkey -t dss -f keyd | ||||
| 	dropbearkey -t ecdsa -size 256 -f keye | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
| #include "bignum.h" | ||||
| #include "dbrandom.h" | ||||
| #include "runopts.h" | ||||
| #include "fuzz.h" | ||||
| 
 | ||||
| 
 | ||||
| /* this is used to generate unique output from the same hashpool */ | ||||
| @ -147,7 +148,7 @@ void addrandom(unsigned char * buf, unsigned int len) | ||||
| 	hash_state hs; | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing || opts.fuzz.recordf) { | ||||
| 	if (fuzz.fuzzing || fuzz.recordf) { | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| @ -165,7 +166,7 @@ void addrandom(unsigned char * buf, unsigned int len) | ||||
| static void write_urandom() | ||||
| { | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing || opts.fuzz.recordf) { | ||||
| 	if (fuzz.fuzzing || fuzz.recordf) { | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| @ -203,7 +204,7 @@ void seedrandom() { | ||||
| 	clock_t clockval; | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing || opts.fuzz.recordf) { | ||||
| 	if (fuzz.fuzzing || fuzz.recordf) { | ||||
| 		seedfuzz(); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										78
									
								
								fuzz-common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								fuzz-common.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| #include "includes.h" | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 
 | ||||
| #include "includes.h" | ||||
| #include "fuzz.h" | ||||
| #include "dbutil.h" | ||||
| #include "runopts.h" | ||||
| 
 | ||||
| struct dropbear_fuzz_options fuzz; | ||||
| 
 | ||||
| static void load_fixed_hostkeys(void); | ||||
| 
 | ||||
| static void common_setup_fuzzer(void) { | ||||
|     fuzz.fuzzing = 1; | ||||
| } | ||||
| 
 | ||||
| void svr_setup_fuzzer(void) { | ||||
|     struct passwd *pw; | ||||
| 
 | ||||
|     common_setup_fuzzer(); | ||||
| 
 | ||||
|     char *argv[] = {  | ||||
|         "-E",  | ||||
|     }; | ||||
| 
 | ||||
|     int argc = sizeof(argv) / sizeof(*argv); | ||||
|     svr_getopts(argc, argv); | ||||
| 
 | ||||
|     /* user lookups might be slow, cache it */ | ||||
|     pw = getpwuid(getuid()); | ||||
|     dropbear_assert(pw); | ||||
|     fuzz.pw_name = m_strdup(pw->pw_name); | ||||
|     fuzz.pw_dir = m_strdup(pw->pw_dir); | ||||
|     fuzz.pw_shell = m_strdup(pw->pw_shell); | ||||
|     fuzz.pw_passwd = m_strdup("!!zzznope"); | ||||
| 
 | ||||
|     load_fixed_hostkeys(); | ||||
| } | ||||
| 
 | ||||
| static void load_fixed_hostkeys(void) { | ||||
| #include "fuzz-hostkeys.c"    | ||||
| 
 | ||||
|     buffer *b = buf_new(3000); | ||||
|     enum signkey_type type; | ||||
| 
 | ||||
|     TRACE(("load fixed hostkeys")) | ||||
| 
 | ||||
|     svr_opts.hostkey = new_sign_key(); | ||||
| 
 | ||||
|     buf_setlen(b, 0); | ||||
|     buf_putbytes(b, keyr, keyr_len); | ||||
|     buf_setpos(b, 0); | ||||
|     type = DROPBEAR_SIGNKEY_RSA; | ||||
|     if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
|         dropbear_exit("failed fixed rsa hostkey"); | ||||
|     } | ||||
| 
 | ||||
|     buf_setlen(b, 0); | ||||
|     buf_putbytes(b, keyd, keyd_len); | ||||
|     buf_setpos(b, 0); | ||||
|     type = DROPBEAR_SIGNKEY_DSS; | ||||
|     if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
|         dropbear_exit("failed fixed dss hostkey"); | ||||
|     } | ||||
| 
 | ||||
|     buf_setlen(b, 0); | ||||
|     buf_putbytes(b, keye, keye_len); | ||||
|     buf_setpos(b, 0); | ||||
|     type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; | ||||
|     if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
|         dropbear_exit("failed fixed ecdsa hostkey"); | ||||
|     } | ||||
| 
 | ||||
|     buf_free(b); | ||||
| } | ||||
| 
 | ||||
| #endif /* DROPBEAR_FUZZ */ | ||||
							
								
								
									
										8
									
								
								fuzz-harness.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								fuzz-harness.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #include "includes.h" | ||||
| 
 | ||||
| extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); | ||||
| 
 | ||||
| int main(int argc, char ** argv) { | ||||
|     LLVMFuzzerTestOneInput("hello", 5); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										35
									
								
								fuzz.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								fuzz.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| #ifndef DROPBEAR_FUZZ_H | ||||
| #define DROPBEAR_FUZZ_H | ||||
| 
 | ||||
| #include "includes.h" | ||||
| #include "buffer.h" | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 
 | ||||
| void svr_setup_fuzzer(void); | ||||
| 
 | ||||
| struct dropbear_fuzz_options { | ||||
|     int fuzzing; | ||||
| 
 | ||||
|     // to record an unencrypted stream
 | ||||
|     FILE* recordf; | ||||
| 
 | ||||
|     // fuzzing input
 | ||||
|     buffer input; | ||||
| 
 | ||||
|     // dropbear_exit() jumps back
 | ||||
|     sigjmp_buf jmp; | ||||
| 
 | ||||
|     uid_t pw_uid; | ||||
|     gid_t pw_gid; | ||||
|     char* pw_name; | ||||
|     char* pw_dir; | ||||
|     char* pw_shell; | ||||
|     char* pw_passwd; | ||||
| }; | ||||
| 
 | ||||
| extern struct dropbear_fuzz_options fuzz; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif /* DROPBEAR_FUZZ_H */ | ||||
							
								
								
									
										31
									
								
								fuzzer-preauth.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								fuzzer-preauth.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #include "fuzz.h" | ||||
| #include "dbrandom.h" | ||||
| #include "session.h" | ||||
| 
 | ||||
| static int setup_fuzzer(void) { | ||||
| 	svr_setup_fuzzer(); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { | ||||
| 	static int once = 0; | ||||
| 	if (!once) { | ||||
| 		setup_fuzzer(); | ||||
| 		once = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	fuzz.input.data = (unsigned char*)Data; | ||||
| 	fuzz.input.size = Size; | ||||
| 	fuzz.input.len = Size; | ||||
| 	fuzz.input.pos = 0; | ||||
| 
 | ||||
| 	seedrandom(); | ||||
| 
 | ||||
| 	if (setjmp(fuzz.jmp) == 0) { | ||||
| 		svr_session(-1, -1); | ||||
| 	} else { | ||||
| 		// dropbear_exit jumped here
 | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										3
									
								
								packet.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								packet.c
									
									
									
									
									
								
							| @ -36,6 +36,7 @@ | ||||
| #include "channel.h" | ||||
| #include "netio.h" | ||||
| #include "runopts.h" | ||||
| #include "fuzz.h" | ||||
| 
 | ||||
| static int read_packet_init(void); | ||||
| static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, | ||||
| @ -78,7 +79,7 @@ void write_packet() { | ||||
| 	calls write_packet() without bothering to test with select() since | ||||
| 	it's likely to be necessary */ | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing) { | ||||
| 	if (fuzz.fuzzing) { | ||||
| 		// pretend to write one packet at a time
 | ||||
| 		// TODO(fuzz): randomise amount written based on the fuzz input
 | ||||
| 		written = iov[0].iov_len; | ||||
|  | ||||
							
								
								
									
										23
									
								
								runopts.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								runopts.h
									
									
									
									
									
								
							| @ -58,29 +58,6 @@ typedef struct runopts { | ||||
| 	char *mac_list; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	struct { | ||||
| 		int fuzzing; | ||||
| 
 | ||||
| 		// to record an unencrypted stream
 | ||||
| 		FILE* recordf; | ||||
| 
 | ||||
| 		// fuzzing input
 | ||||
| 		buffer *input; | ||||
| 
 | ||||
| 		// dropbear_exit() jumps back
 | ||||
| 		sigjmp_buf jmp; | ||||
| 
 | ||||
| 		uid_t pw_uid; | ||||
| 		gid_t pw_gid; | ||||
| 		char* pw_name; | ||||
| 		char* pw_dir; | ||||
| 		char* pw_shell; | ||||
| 		char* pw_passwd; | ||||
| 
 | ||||
| 	} fuzz; | ||||
| #endif | ||||
| 
 | ||||
| } runopts; | ||||
| 
 | ||||
| extern runopts opts; | ||||
|  | ||||
| @ -359,7 +359,7 @@ void send_msg_userauth_failure(int partial, int incrfail) { | ||||
| 		/* We delay for 300ms +- 50ms */ | ||||
| 		delay = 250000 + (delay % 100000); | ||||
| #ifndef DROPBEAR_FUZZ | ||||
| 		if (!opts.fuzz.fuzzing) { | ||||
| 		if (!fuzz.fuzzing) { | ||||
| 			usleep(delay); | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| @ -346,19 +346,6 @@ void svr_getopts(int argc, char ** argv) { | ||||
| 		} | ||||
| 		opts.idle_timeout_secs = val; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing) { | ||||
| 		struct passwd *pw; | ||||
| 		/* user lookups might be slow, cache it */ | ||||
| 		pw = getpwuid(getuid()); | ||||
| 		dropbear_assert(pw); | ||||
| 		opts.fuzz.pw_name = m_strdup(pw->pw_name); | ||||
| 		opts.fuzz.pw_dir = m_strdup(pw->pw_dir); | ||||
| 		opts.fuzz.pw_shell = m_strdup(pw->pw_shell); | ||||
| 		opts.fuzz.pw_passwd = m_strdup("!!zzznope"); | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void addportandaddress(const char* spec) { | ||||
| @ -488,57 +475,12 @@ static void addhostkey(const char *keyfile) { | ||||
| 	svr_opts.num_hostkey_files++; | ||||
| } | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| static void load_fixed_hostkeys() { | ||||
| #include "hostkeys.c"	 | ||||
| 
 | ||||
| 	buffer *b = buf_new(3000); | ||||
| 	enum signkey_type type; | ||||
| 
 | ||||
| 	TRACE(("load fixed hostkeys")) | ||||
| 
 | ||||
| 	svr_opts.hostkey = new_sign_key(); | ||||
| 
 | ||||
| 	buf_setlen(b, 0); | ||||
| 	buf_putbytes(b, keyr, keyr_len); | ||||
| 	buf_setpos(b, 0); | ||||
| 	type = DROPBEAR_SIGNKEY_RSA; | ||||
| 	if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
| 		dropbear_exit("failed fixed rsa hostkey"); | ||||
| 	} | ||||
| 
 | ||||
| 	buf_setlen(b, 0); | ||||
| 	buf_putbytes(b, keyd, keyd_len); | ||||
| 	buf_setpos(b, 0); | ||||
| 	type = DROPBEAR_SIGNKEY_DSS; | ||||
| 	if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
| 		dropbear_exit("failed fixed dss hostkey"); | ||||
| 	} | ||||
| 
 | ||||
| 	buf_setlen(b, 0); | ||||
| 	buf_putbytes(b, keye, keye_len); | ||||
| 	buf_setpos(b, 0); | ||||
| 	type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; | ||||
| 	if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { | ||||
| 		dropbear_exit("failed fixed ecdsa hostkey"); | ||||
| 	} | ||||
| 
 | ||||
|     buf_free(b); | ||||
| } | ||||
| #endif // DROPBEAR_FUZZ
 | ||||
| 
 | ||||
| void load_all_hostkeys() { | ||||
| 	int i; | ||||
| 	int disable_unset_keys = 1; | ||||
| 	int any_keys = 0; | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	if (opts.fuzz.fuzzing) { | ||||
| 		load_fixed_hostkeys(); | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	svr_opts.hostkey = new_sign_key(); | ||||
| 
 | ||||
| 	for (i = 0; i < svr_opts.num_hostkey_files; i++) { | ||||
|  | ||||
| @ -40,6 +40,7 @@ | ||||
| #include "auth.h" | ||||
| #include "runopts.h" | ||||
| #include "crypto_desc.h" | ||||
| #include "fuzz.h" | ||||
| 
 | ||||
| static void svr_remoteclosed(void); | ||||
| 
 | ||||
| @ -182,6 +183,13 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { | ||||
| 		session_cleanup(); | ||||
| 	} | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
| 	// longjmp before cleaning up svr_opts
 | ||||
|     if (fuzz.fuzzing) { | ||||
|         longjmp(fuzz.jmp, 1); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
| 	if (svr_opts.hostkey) { | ||||
| 		sign_key_free(svr_opts.hostkey); | ||||
| 		svr_opts.hostkey = NULL; | ||||
| @ -191,11 +199,6 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { | ||||
| 		m_free(svr_opts.ports[i]); | ||||
| 	} | ||||
| 
 | ||||
| #ifdef DROPBEAR_FUZZ | ||||
|     if (opts.fuzz.fuzzing) { | ||||
|         longjmp(opts.fuzz.jmp, 1); | ||||
|     } | ||||
| #endif | ||||
|      | ||||
| 	exit(exitcode); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user