view fuzz.h @ 1790:42745af83b7d

Introduce extra delay before closing unauthenticated sessions To make it harder for attackers, introduce a delay to keep an unauthenticated session open a bit longer, thus blocking a connection slot until after the delay. Without this, while there is a limit on the amount of attempts an attacker can make at the same time (MAX_UNAUTH_PER_IP), the time taken by dropbear to handle one attempt is still short and thus for each of the allowed parallel attempts many attempts can be chained one after the other. The attempt rate is then: "MAX_UNAUTH_PER_IP / <process time of one attempt>". With the delay, this rate becomes: "MAX_UNAUTH_PER_IP / UNAUTH_CLOSE_DELAY".
author Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
date Wed, 15 Feb 2017 13:53:04 +0100
parents a3b39df57c8b
children 685b47d8faf7
line wrap: on
line source

#ifndef DROPBEAR_FUZZ_H
#define DROPBEAR_FUZZ_H

#include "config.h"

#if DROPBEAR_FUZZ

#include "includes.h"
#include "buffer.h"
#include "algo.h"
#include "netio.h"
#include "fuzz-wrapfd.h"

// once per process
void fuzz_common_setup(void);
void fuzz_svr_setup(void);
void fuzz_cli_setup(void);

// constructor attribute so it runs before main(), including
// in non-fuzzing mode.
void fuzz_early_setup(void) __attribute__((constructor));

// must be called once per fuzz iteration. 
// 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 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);

// fuzzer functions that intrude into general code
void fuzz_kex_fakealgos(void);
int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
        const char* algo, unsigned int algolen,
        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,
    connect_callback cb, void* cb_data,
    const char* bind_address, const char* bind_port);

int fuzz_dropbear_listen(const char* address, const char* port,
        int *socks, unsigned int sockcount, char **errstring, int *maxfd);

// helpers
void fuzz_get_socket_address(int fd, char **local_host, char **local_port,
                        char **remote_host, char **remote_port, int host_lookup);
void fuzz_fake_send_kexdh_reply(void);
int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid);
void fuzz_dump(const unsigned char* data, size_t len);

// fake IO wrappers
#ifndef FUZZ_SKIP_WRAP
#define select(nfds, readfds, writefds, exceptfds, timeout) \
        wrapfd_select(nfds, readfds, writefds, exceptfds, timeout)
#define write(fd, buf, count) wrapfd_write(fd, buf, count)
#define read(fd, buf, count) wrapfd_read(fd, buf, count)
#define close(fd) wrapfd_close(fd)
#endif // FUZZ_SKIP_WRAP

struct dropbear_fuzz_options {
    int fuzzing;

    // fuzzing input
    buffer *input;
    struct dropbear_cipher recv_cipher;
    struct dropbear_hash recv_mac;
    int wrapfds;

    // whether to skip slow bignum maths
    int skip_kexmaths;
    // whether is svr_postauth mode
    int svr_postauth;

    // dropbear_exit() jumps back
    int do_jmp;
    sigjmp_buf jmp;

    // write out decrypted session data to this FD if it's set
    // flag - this needs to be set manually in cli-main.c etc
    int dumping;
    // the file descriptor
    int recv_dumpfd;

    // avoid filling fuzzing logs, this points to /dev/null
    FILE *fake_stderr;
};

extern struct dropbear_fuzz_options fuzz;

/* guard for when fuzz.h is included by fuzz-common.c */
#ifndef FUZZ_NO_REPLACE_STDERR

/* This is a bodge but seems to work.
 glibc stdio.h has the comment 
 "C89/C99 say they're macros.  Make them happy." */
/* OS X has it as a macro */
#ifdef stderr
#undef stderr
#endif
#define stderr (fuzz.fake_stderr)

#endif /* FUZZ_NO_REPLACE_STDERR */

struct passwd* fuzz_getpwuid(uid_t uid);
struct passwd* fuzz_getpwnam(const char *login);
/* guard for when fuzz.h is included by fuzz-common.c */
#ifndef FUZZ_NO_REPLACE_GETPW
#define getpwnam(x) fuzz_getpwnam(x)
#define getpwuid(x) fuzz_getpwuid(x)
#endif // FUZZ_NO_REPLACE_GETPW

#endif // DROPBEAR_FUZZ

#endif /* DROPBEAR_FUZZ_H */