# HG changeset patch # User Matt Johnston # Date 1611928752 -28800 # Node ID f90e681b8b8c9dc4692ee7e3cc847c92191c1f97 # Parent 685b47d8faf785da2e65b4246e27b8b0fbd7362b# Parent 2bf1e97ba3cd6fb19317e5e6939ee2f4c1995b42 merge diff -r 2bf1e97ba3cd -r f90e681b8b8c default_options.h --- a/default_options.h Thu Dec 17 04:35:48 2020 -0500 +++ b/default_options.h Fri Jan 29 21:59:12 2021 +0800 @@ -256,6 +256,9 @@ /* -T server option overrides */ #define MAX_AUTH_TRIES 10 +/* Delay introduced before closing an unauthenticated session (seconds) */ +#define UNAUTH_CLOSE_DELAY 30 + /* The default file to store the daemon's process ID, for shutdown scripts etc. This can be overridden with the -P flag */ #define DROPBEAR_PIDFILE "/var/run/dropbear.pid" diff -r 2bf1e97ba3cd -r f90e681b8b8c fuzz-wrapfd.h --- a/fuzz-wrapfd.h Thu Dec 17 04:35:48 2020 -0500 +++ b/fuzz-wrapfd.h Fri Jan 29 21:59:12 2021 +0800 @@ -1,6 +1,7 @@ #ifndef FUZZ_WRAPFD_H #define FUZZ_WRAPFD_H +#include "includes.h" #include "buffer.h" enum wrapfd_mode { @@ -21,5 +22,6 @@ int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); int wrapfd_close(int fd); +int fuzz_kill(pid_t pid, int sig); #endif // FUZZ_WRAPFD_H diff -r 2bf1e97ba3cd -r f90e681b8b8c fuzz.h --- a/fuzz.h Thu Dec 17 04:35:48 2020 -0500 +++ b/fuzz.h Fri Jan 29 21:59:12 2021 +0800 @@ -59,6 +59,7 @@ #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) +#define kill(pid, sig) fuzz_kill(pid, sig) #endif // FUZZ_SKIP_WRAP struct dropbear_fuzz_options { diff -r 2bf1e97ba3cd -r f90e681b8b8c fuzz/fuzz-wrapfd.c --- a/fuzz/fuzz-wrapfd.c Thu Dec 17 04:35:48 2020 -0500 +++ b/fuzz/fuzz-wrapfd.c Fri Jan 29 21:59:12 2021 +0800 @@ -258,3 +258,15 @@ return ret; } +int fuzz_kill(pid_t pid, int sig) { + if (fuzz.fuzzing) { + TRACE(("fuzz_kill ignoring pid %d signal %d", (pid), sig)) + if (sig >= 0) { + return 0; + } else { + errno = EINVAL; + return -1; + } + } + return kill(pid, sig); +} diff -r 2bf1e97ba3cd -r f90e681b8b8c svr-chansession.c --- a/svr-chansession.c Thu Dec 17 04:35:48 2020 -0500 +++ b/svr-chansession.c Fri Jan 29 21:59:12 2021 +0800 @@ -423,12 +423,14 @@ /* Send a signal to a session's process as requested by the client*/ static int sessionsignal(const struct ChanSess *chansess) { + TRACE(("sessionsignal")) int sig = 0; char* signame = NULL; int i; if (chansess->pid == 0) { + TRACE(("sessionsignal: done no pid")) /* haven't got a process pid yet */ return DROPBEAR_FAILURE; } @@ -446,12 +448,14 @@ m_free(signame); + TRACE(("sessionsignal: pid %d signal %d", (int)chansess->pid, sig)) if (sig == 0) { /* failed */ return DROPBEAR_FAILURE; } if (kill(chansess->pid, sig) < 0) { + TRACE(("sessionsignal: kill() errored")) return DROPBEAR_FAILURE; } diff -r 2bf1e97ba3cd -r f90e681b8b8c svr-session.c --- a/svr-session.c Thu Dec 17 04:35:48 2020 -0500 +++ b/svr-session.c Fri Jan 29 21:59:12 2021 +0800 @@ -215,6 +215,7 @@ char fullmsg[300]; char fromaddr[60]; int i; + int add_delay = 0; #if DROPBEAR_PLUGIN if ((ses.plugin_session != NULL)) { @@ -247,13 +248,33 @@ snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: (user '%s', %u fails): %s", fromaddr, ses.authstate.pw_name, ses.authstate.failcount, exitmsg); + add_delay = 1; } else { /* before userauth */ snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: %s", fromaddr, exitmsg); + add_delay = 1; } dropbear_log(LOG_INFO, "%s", fullmsg); + /* 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 / ". + * With the delay, this rate becomes: + * "MAX_UNAUTH_PER_IP / UNAUTH_CLOSE_DELAY". + */ + if ((add_delay != 0) && (UNAUTH_CLOSE_DELAY > 0)) { + TRACE(("svr_dropbear_exit: start delay of %d seconds", UNAUTH_CLOSE_DELAY)); + sleep(UNAUTH_CLOSE_DELAY); + TRACE(("svr_dropbear_exit: end delay of %d seconds", UNAUTH_CLOSE_DELAY)); + } + #if DROPBEAR_VFORK /* For uclinux only the main server process should cleanup - we don't want * forked children doing that */