changeset 1793:f90e681b8b8c

merge
author Matt Johnston <matt@ucc.asn.au>
date Fri, 29 Jan 2021 21:59:12 +0800
parents 685b47d8faf7 (diff) 2bf1e97ba3cd (current diff)
children ed20d805b332
files
diffstat 6 files changed, 43 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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"
--- 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
--- 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 {
--- 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);
+}
--- 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;
 	} 
 
--- 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 / <process time of one attempt>".
+	 * 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 */