mirror of
https://github.com/clearml/dropbear
synced 2025-01-30 18:36:56 +00:00
Add server postauth fuzzer, wrap connect_remote()
This commit is contained in:
parent
15ea6d1106
commit
8ec9016585
@ -269,7 +269,8 @@ lint:
|
||||
|
||||
# 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 @@ $(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS)
|
||||
|
||||
# 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
|
||||
|
@ -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);
|
||||
|
2
fuzz.h
2
fuzz.h
@ -23,7 +23,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_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);
|
||||
|
||||
|
@ -217,16 +217,31 @@ void fuzz_fake_send_kexdh_reply(void) {
|
||||
|
||||
/* 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 @@ int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) {
|
||||
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 @@ int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) {
|
||||
|
||||
// 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;
|
||||
|
@ -35,7 +35,7 @@ void wrapfd_setup(buffer *buf) {
|
||||
// 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 @@ void wrapfd_setseed(uint32_t seed) {
|
||||
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 @@ int wrapfd_new() {
|
||||
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 @@ int wrapfd_read(int fd, void *out, size_t count) {
|
||||
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 @@ int wrapfd_read(int fd, void *out, size_t count) {
|
||||
return maxread;
|
||||
}
|
||||
|
||||
// return fixed output, of random length
|
||||
maxread = MIN(MAX_RANDOM_IN, count);
|
||||
maxread = nrand48(rand_state) % maxread + 1;
|
||||
memset(out, 0xef, maxread);
|
||||
|
6
fuzz/fuzzer-postauth_nomaths.c
Normal file
6
fuzz/fuzzer-postauth_nomaths.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "fuzz.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
return fuzz_run_server(Data, Size, 1, 1);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
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");
|
||||
}
|
||||
|
||||
|
6
netio.c
6
netio.c
@ -179,6 +179,12 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user