changeset 1510:eb4c7052f51d coverity

merge coverity up to date
author Matt Johnston <matt@ucc.asn.au>
date Sat, 17 Feb 2018 11:29:17 +0800
parents 3520d7c25363 (current diff) 47f36d8565cf (diff)
children 1d163552145f
files .travis.yml
diffstat 33 files changed, 255 insertions(+), 215 deletions(-) [+]
line wrap: on
line diff
--- a/INSTALL	Sat Feb 10 19:06:13 2018 +0800
+++ b/INSTALL	Sat Feb 17 11:29:17 2018 +0800
@@ -1,20 +1,26 @@
 Basic Dropbear build instructions:
 
-- Edit options.h to set which features you want.
-- Edit debug.h if you want any debug options (not usually required).
+- Edit localoptions.h to set which features you want. Available options
+  are described in default_options.h.in, these will be overridden by
+  anything set in localoptions.h
 
-(If using a non-tarball copy, "autoconf; autoheader")
+- If using a Mercurial or Git checkout, "autoconf; autoheader"
 
-./configure      (optionally with --disable-zlib or --disable-syslog,
+- Configure for your system:
+  ./configure     (optionally with --disable-zlib or --disable-syslog,
                   or --help for other options)
 
-Now compile:
+- Compile:
 
-make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
+  make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
+
+- Optionally install, or copy the binaries another way
 
-And install (/usr/local/bin is usual default):
+  make install (/usr/local/bin is usual default):
 
-make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
+  or
+
+  make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install
 
 (you can leave items out of the PROGRAMS list to avoid compiling them. If you
 recompile after changing the PROGRAMS list, you *MUST* "make clean" before
@@ -25,7 +31,7 @@
 If you want to compile statically use ./configure --enable-static
 
 By default Dropbear adds various build flags that improve robustness 
-against programming bugs (good for security) - if these cause problems
+against programming bugs (good for security). If these cause problems
 they can be disabled with ./configure --disable-harden
 
 Binaries can be stripped with "make strip"
--- a/Makefile.in	Sat Feb 10 19:06:13 2018 +0800
+++ b/Makefile.in	Sat Feb 17 11:29:17 2018 +0800
@@ -20,11 +20,12 @@
 ifeq (@BUNDLED_LIBTOM@, 1)
 LIBTOM_DEPS=$(STATIC_LTC) $(STATIC_LTM) 
 CFLAGS+=-I$(srcdir)/libtomcrypt/src/headers/
-LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM) 
+LIBTOM_LIBS=$(STATIC_LTC) $(STATIC_LTM)
 endif
 
 ifneq ($(wildcard localoptions.h),)
 CFLAGS+=-DLOCALOPTIONS_H_EXISTS
+LOCALOPTIONS_H=localoptions.h
 endif
 
 COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
@@ -56,13 +57,6 @@
 
 SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o
 
-HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \
-		dss.h bignum.h signkey.h rsa.h dbrandom.h service.h auth.h \
-		debug.h channel.h chansession.h config.h queue.h sshpty.h \
-		termcodes.h gendss.h genrsa.h runopts.h includes.h \
-		loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd.h compat.h \
-		listener.h fake-rfc2553.h ecc.h ecdsa.h
-
 dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
 dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
 dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
@@ -97,7 +91,6 @@
 
 # whether we're building client, server, or both for the common objects.
 # evilness so we detect 'dropbear' by itself as a word
-space:= $(empty) $(empty)
 ifneq (,$(strip $(foreach prog, $(PROGRAMS), $(findstring ZdropbearZ, Z$(prog)Z))))
 	CFLAGS+= -DDROPBEAR_SERVER
 endif
@@ -128,6 +121,10 @@
 
 all: $(TARGETS)
 
+# a bit lazy, but safer
+HEADERS=$(wildcard $(srcdir)/*.h *.h)
+*.o: $(HEADERS)
+
 strip: $(TARGETS)
 	$(STRIP) $(addsuffix $(EXEEXT), $(TARGETS))
 
@@ -200,10 +197,10 @@
 	-rm -f $*$(EXEEXT)
 	-ln -s dropbearmulti$(EXEEXT) $*$(EXEEXT)
 
-$(STATIC_LTC): options.h
+$(STATIC_LTC): 
 	$(MAKE) -C libtomcrypt
 
-$(STATIC_LTM): options.h
+$(STATIC_LTM):
 	$(MAKE) -C libtommath
 
 .PHONY : clean sizes thisclean distclean tidy ltc-clean ltm-clean
@@ -234,7 +231,7 @@
 # default_options.h is stored in version control, could not find a workaround
 # for parallel "make -j" and dependency rules.
 default_options.h: default_options.h.in 
-	echo "# > > > Generated from $^, edit that file instead !" > [email protected]
-	echo >> [email protected]
-	$(srcdir)/ifndef_wrapper.sh < $^ > [email protected]
-	mv [email protected] $@
+	@echo Creating $@
+	@echo "/*\n > > > Do not edit this file (default_options.h) < < <\nGenerated from "$^"\nLocal customisation goes in localoptions.h\n*/\n\n" > [email protected]
+	@$(srcdir)/ifndef_wrapper.sh < $^ >> [email protected]
+	@mv [email protected] $@
--- a/channel.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/channel.h	Sat Feb 17 11:29:17 2018 +0800
@@ -94,9 +94,9 @@
 struct ChanType {
 
 	int sepfds; /* Whether this channel has separate pipes for in/out or not */
-	char *name;
+	const char *name;
 	int (*inithandler)(struct Channel*);
-	int (*check_close)(struct Channel*);
+	int (*check_close)(const struct Channel*);
 	void (*reqhandler)(struct Channel*);
 	void (*closehandler)(const struct Channel*);
 };
--- a/chansession.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/chansession.h	Sat Feb 17 11:29:17 2018 +0800
@@ -94,6 +94,7 @@
 #endif
 
 void svr_chansessinitialise(void);
+void svr_chansess_checksignal(void);
 extern const struct ChanType svrchansess;
 
 struct SigMap {
--- a/cli-auth.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/cli-auth.c	Sat Feb 17 11:29:17 2018 +0800
@@ -60,9 +60,11 @@
 	*/
 	if (ses.keys->trans.algo_comp != DROPBEAR_COMP_ZLIB_DELAY) {
 		ses.authstate.authtypes = AUTH_TYPE_PUBKEY;
+#if DROPBEAR_USE_DROPBEAR_PASSWORD
 		if (getenv(DROPBEAR_PASSWORD_ENV)) {
 			ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT;
 		}
+#endif
 		if (cli_auth_try() == DROPBEAR_SUCCESS) {
 			TRACE(("skipped initial none auth query"))
 			/* Note that there will be two auth responses in-flight */
@@ -335,7 +337,7 @@
 {
 	char* password = NULL;
 	
-#ifdef DROPBEAR_PASSWORD_ENV
+#if DROPBEAR_USE_DROPBEAR_PASSWORD
 	/* Password provided in an environment var */
 	password = getenv(DROPBEAR_PASSWORD_ENV);
 	if (password)
--- a/cli-main.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/cli-main.c	Sat Feb 17 11:29:17 2018 +0800
@@ -108,7 +108,7 @@
 	vsnprintf(exitmsg, sizeof(exitmsg), format, param);
 
 	/* Add the prefix depending on session/auth state */
-	if (!sessinitdone) {
+	if (!ses.init_done) {
 		snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg);
 	} else {
 		snprintf(fullmsg, sizeof(fullmsg), 
--- a/cli-runopts.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/cli-runopts.c	Sat Feb 17 11:29:17 2018 +0800
@@ -306,10 +306,10 @@
 				case 'm':
 #endif
 				case 'D':
-#ifndef DROPBEAR_CLI_REMOTETCPFWD
+#if !DROPBEAR_CLI_REMOTETCPFWD
 				case 'R':
 #endif
-#ifndef DROPBEAR_CLI_LOCALTCPFWD
+#if !DROPBEAR_CLI_LOCALTCPFWD
 				case 'L':
 #endif
 				case 'V':
--- a/cli-session.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/cli-session.c	Sat Feb 17 11:29:17 2018 +0800
@@ -118,7 +118,7 @@
 	cli_session_init(proxy_cmd_pid);
 
 	/* Ready to go */
-	sessinitdone = 1;
+	ses.init_done = 1;
 
 	/* Exchange identification */
 	send_session_identification();
@@ -338,7 +338,7 @@
 
 static void cli_session_cleanup(void) {
 
-	if (!sessinitdone) {
+	if (!ses.init_done) {
 		return;
 	}
 
--- a/common-session.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/common-session.c	Sat Feb 17 11:29:17 2018 +0800
@@ -43,13 +43,6 @@
 
 struct sshsession ses; /* GLOBAL */
 
-/* need to know if the session struct has been initialised, this way isn't the
- * cleanest, but works OK */
-int sessinitdone = 0; /* GLOBAL */
-
-/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
-int exitflag = 0; /* GLOBAL */
-
 /* called only at the start of a session, set up initial state */
 void common_session_init(int sock_in, int sock_out) {
 	time_t now;
@@ -162,7 +155,6 @@
 		/* We get woken up when signal handlers write to this pipe.
 		   SIGCHLD in svr-chansession is the only one currently. */
 		FD_SET(ses.signal_pipe[0], &readfd);
-		ses.channel_signal_pending = 0;
 
 		/* set up for channels which can be read/written */
 		setchannelfds(&readfd, &writefd, writequeue_has_space);
@@ -190,7 +182,7 @@
 
 		val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
 
-		if (exitflag) {
+		if (ses.exitflag) {
 			dropbear_exit("Terminated by signal");
 		}
 		
@@ -210,6 +202,7 @@
 		/* We'll just empty out the pipe if required. We don't do
 		any thing with the data, since the pipe's purpose is purely to
 		wake up the select() above. */
+		ses.channel_signal_pending = 0;
 		if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
 			char x;
 			TRACE(("signal pipe set"))
@@ -244,6 +237,10 @@
 
 		handle_connect_fds(&writefd);
 
+		/* loop handler prior to channelio, in case the server loophandler closes
+		channels on process exit */
+		loophandler();
+
 		/* process pipes etc for the channels, ses.dataallowed == 0
 		 * during rekeying ) */
 		channelio(&readfd, &writefd);
@@ -255,11 +252,6 @@
 			}
 		}
 
-
-		if (loophandler) {
-			loophandler();
-		}
-
 	} /* for(;;) */
 	
 	/* Not reached */
@@ -280,8 +272,8 @@
 	TRACE(("enter session_cleanup"))
 	
 	/* we can't cleanup if we don't know the session state */
-	if (!sessinitdone) {
-		TRACE(("leave session_cleanup: !sessinitdone"))
+	if (!ses.init_done) {
+		TRACE(("leave session_cleanup: !ses.init_done"))
 		return;
 	}
 
--- a/configure.ac	Sat Feb 10 19:06:13 2018 +0800
+++ b/configure.ac	Sat Feb 17 11:29:17 2018 +0800
@@ -11,7 +11,6 @@
 
 # Checks for programs.
 AC_PROG_CC
-AC_PROG_MAKE_SET
 
 if test -z "$LD" ; then
 	LD=$CC
@@ -111,6 +110,11 @@
 	    )
 	# FORTIFY_SOURCE
 	DB_TRYADDCFLAGS([-D_FORTIFY_SOURCE=2])
+
+	# Spectre v2 mitigations
+	DB_TRYADDCFLAGS([-mfunction-return=thunk])
+	DB_TRYADDCFLAGS([-mindirect-branch=thunk])
+
 fi
 
 # large file support is useful for scp
--- a/dbrandom.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/dbrandom.c	Sat Feb 17 11:29:17 2018 +0800
@@ -59,7 +59,7 @@
 	unsigned int readcount;
 	int ret = DROPBEAR_FAILURE;
 
-#ifdef DROPBEAR_PRNGD_SOCKET
+#if DROPBEAR_USE_PRNGD
 	if (prngd)
 	{
 		readfd = connect_unix(filename);
@@ -107,7 +107,7 @@
 			wantread = MIN(sizeof(readbuf), len-readcount);
 		}
 
-#ifdef DROPBEAR_PRNGD_SOCKET
+#if DROPBEAR_USE_PRNGD
 		if (prngd)
 		{
 			char egdcmd[2];
@@ -157,7 +157,7 @@
 
 static void write_urandom()
 {
-#ifndef DROPBEAR_PRNGD_SOCKET
+#if !DROPBEAR_USE_PRNGD
 	/* This is opportunistic, don't worry about failure */
 	unsigned char buf[INIT_SEED_SIZE];
 	FILE *f = fopen(DROPBEAR_URANDOM_DEV, "w");
@@ -185,7 +185,7 @@
 	/* existing state */
 	sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
 
-#ifdef DROPBEAR_PRNGD_SOCKET
+#if DROPBEAR_USE_PRNGD
 	if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) 
 			!= DROPBEAR_SUCCESS) {
 		dropbear_exit("Failure reading random device %s", 
--- a/dbutil.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/dbutil.c	Sat Feb 17 11:29:17 2018 +0800
@@ -214,7 +214,7 @@
 #endif /* DEBUG_TRACE */
 
 /* Connect to a given unix socket. The socket is blocking */
-#ifdef ENABLE_CONNECT_UNIX
+#if ENABLE_CONNECT_UNIX
 int connect_unix(const char* path) {
 	struct sockaddr_un addr;
 	int fd = -1;
--- a/dbutil.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/dbutil.h	Sat Feb 17 11:29:17 2018 +0800
@@ -59,7 +59,7 @@
 int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
 		int *writefd, int *readfd, int *errfd, pid_t *pid);
 void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
-#ifdef ENABLE_CONNECT_UNIX
+#if ENABLE_CONNECT_UNIX
 int connect_unix(const char* addr);
 #endif
 int buf_readfile(buffer* buf, const char* filename);
--- a/debug.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/debug.h	Sat Feb 17 11:29:17 2018 +0800
@@ -33,16 +33,6 @@
  * etc. Don't use this normally, it might cause problems */
 /* #define DEBUG_VALGRIND */
 
-/* Define this to compile in trace debugging printf()s. 
- * You'll need to run programs with "-v" to turn this on.
- *
- * Caution: Don't use this in an unfriendly environment (ie unfirewalled),
- * since the printing may not sanitise strings etc. This will add a reasonable
- * amount to your executable size. */
-#ifndef DEBUG_TRACE
-#define DEBUG_TRACE 0
-#endif
-
 /* All functions writing to the cleartext payload buffer call
  * CHECKCLEARTOWRITE() before writing. This is only really useful if you're
  * attempting to track down a problem */
--- a/default_options.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/default_options.h	Sat Feb 17 11:29:17 2018 +0800
@@ -1,14 +1,20 @@
+/*
+ > > > Do not edit this file (default_options.h) < < <
+Generated from ../default_options.h.in
+Local customisation goes in localoptions.h
+*/
+
+
 #ifndef DROPBEAR_DEFAULT_OPTIONS_H_
 #define DROPBEAR_DEFAULT_OPTIONS_H_
 /*
                      > > > Read This < < <
 
-default_options.h.in (this file) documents compile-time options, and provides 
-default values.
+default_options.h.in  documents compile-time options, and provides default values.
 
 Local customisation should be added to localoptions.h which is
 used if it exists. Options defined there will override any options in this
-file (#ifndef guards added by ifndef_wrapper.sh).
+file.
 
 Options can also be defined with -DDROPBEAR_XXX in Makefile CFLAGS
 
@@ -381,7 +387,7 @@
 #endif
 
 /* Default maximum number of failed authentication tries (server option) */
-/* -T runtime option overrides */
+/* -T server option overrides */
 #ifndef MAX_AUTH_TRIES
 #define MAX_AUTH_TRIES 10
 #endif
--- a/default_options.h.in	Sat Feb 10 19:06:13 2018 +0800
+++ b/default_options.h.in	Sat Feb 17 11:29:17 2018 +0800
@@ -3,12 +3,11 @@
 /*
                      > > > Read This < < <
 
-default_options.h.in (this file) documents compile-time options, and provides 
-default values.
+default_options.h.in  documents compile-time options, and provides default values.
 
 Local customisation should be added to localoptions.h which is
 used if it exists. Options defined there will override any options in this
-file (#ifndef guards added by ifndef_wrapper.sh).
+file.
 
 Options can also be defined with -DDROPBEAR_XXX in Makefile CFLAGS
 
@@ -37,10 +36,9 @@
 #define NON_INETD_MODE 1
 #define INETD_MODE 1
 
-/* Setting this disables the fast exptmod bignum code. It saves ~5kB, but is
- * perhaps 20% slower for pubkey operations (it is probably worth experimenting
- * if you want to use this) */
-/*#define NO_FAST_EXPTMOD*/
+#if !(NON_INETD_MODE || INETD_MODE)
+	#error "NON_INETD_MODE or INETD_MODE (or both) must be enabled."
+#endif
 
 /* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save
 several kB in binary size however will make the symmetrical ciphers and hashes
@@ -78,7 +76,7 @@
 #define DROPBEAR_CLI_NETCAT 1
 
 /* Whether to support "-c" and "-m" flags to choose ciphers/MACs at runtime */
-#define ENABLE_USER_ALGO_LIST 1
+#define DROPBEAR_USER_ALGO_LIST 1
 
 /* Encryption - at least one required.
  * Protocol RFC requires 3DES and recommends AES128 for interoperability.
@@ -87,10 +85,15 @@
 #define DROPBEAR_AES128 1
 #define DROPBEAR_3DES 1
 #define DROPBEAR_AES256 1
-/* Compiling in Blowfish will add ~6kB to runtime heap memory usage */
-/*#define DROPBEAR_BLOWFISH*/
 #define DROPBEAR_TWOFISH256 1
 #define DROPBEAR_TWOFISH128 1
+/* Compiling in Blowfish will add ~6kB to runtime heap memory usage */
+#define DROPBEAR_BLOWFISH 0
+
+#if !(DROPBEAR_AES128 || DROPBEAR_3DES || DROPBEAR_AES256 || DROPBEAR_BLOWFISH \
+      || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128)
+	#error "At least one encryption algorithm must be enabled; 3DES and AES128 are recommended."
+#endif
 
 /* Enable CBC mode for ciphers. This has security issues though
  * is the most compatible with older SSH implementations */
@@ -130,6 +133,10 @@
  * on x86-64 */
 #define DROPBEAR_ECDSA 1
 
+#if !(DROPBEAR_RSA || DROPBEAR_DSS || DROPBEAR_ECDSA)
+	#error "At least one hostkey or public-key algorithm must be enabled; RSA is recommended."
+#endif
+
 /* RSA must be >=1024 */
 #define DROPBEAR_DEFAULT_RSA_SIZE 2048
 /* DSS is always 1024 */
@@ -194,15 +201,38 @@
  * PAM challenge/response.
  * You can't enable both PASSWORD and PAM. */
 
+/* PAM requires ./configure --enable-pam */
+#if defined(HAVE_LIBPAM) && !DROPBEAR_SVR_PASSWORD_AUTH
+	#define DROPBEAR_SVR_PAM_AUTH 1
+#else
+	#define DROPBEAR_SVR_PAM_AUTH 0
+#endif
+
 /* This requires crypt() */
-#ifdef HAVE_CRYPT
-#define DROPBEAR_SVR_PASSWORD_AUTH 1
+#if defined(HAVE_CRYPT) && !DROPBEAR_SVR_PAM_AUTH
+	#define DROPBEAR_SVR_PASSWORD_AUTH 1
 #else
-#define DROPBEAR_SVR_PASSWORD_AUTH 0
+	#define DROPBEAR_SVR_PASSWORD_AUTH 0
+#endif
+
+#define DROPBEAR_SVR_PUBKEY_AUTH 1
+
+#if !(DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH || DROPBEAR_SVR_PUBKEY_AUTH)
+	#error "At least one server authentication type must be enabled; PUBKEY and PASSWORD are recommended."
 #endif
-/* PAM requires ./configure --enable-pam */
-#define DROPBEAR_SVR_PAM_AUTH 0
-#define DROPBEAR_SVR_PUBKEY_AUTH 1
+
+#if DROPBEAR_SVR_PASSWORD_AUTH && !HAVE_CRYPT
+	#error "DROPBEAR_SVR_PASSWORD_AUTH requires `crypt()'."
+#endif
+
+#if DROPBEAR_SVR_PAM_AUTH
+	#if DISABLE_PAM
+		#error "DROPBEAR_SVR_PAM_AUTH requires 'configure --enable-pam' to succeed."
+	#endif
+	#if DROPBEAR_SVR_PASSWORD_AUTH
+		#error "DROPBEAR_SVR_PASSWORD_AUTH cannot be enabled at the same time as DROPBEAR_SVR_PAM_AUTH."
+	#endif
+#endif
 
 /* Whether to take public key options in 
  * authorized_keys file into account */
@@ -210,11 +240,18 @@
 
 /* This requires getpass. */
 #ifdef HAVE_GETPASS
-#define DROPBEAR_CLI_PASSWORD_AUTH 1
-#define DROPBEAR_CLI_INTERACT_AUTH 1
+	#define DROPBEAR_CLI_PASSWORD_AUTH 1
+	#define DROPBEAR_CLI_INTERACT_AUTH 1
+#else
+	#define DROPBEAR_CLI_PASSWORD_AUTH 0
+	#define DROPBEAR_CLI_INTERACT_AUTH 0
 #endif
 #define DROPBEAR_CLI_PUBKEY_AUTH 1
 
+#if !(DROPBEAR_CLI_PASSWORD_AUTH || DROPBEAR_CLI_PUBKEY_AUTH)
+	#error "At least one client authentication type must be enabled; PUBKEY and PASSWORD are recommended."
+#endif
+
 /* A default argument for dbclient -i <privatekey>. 
 Homedir is prepended unless path begins with / */
 #define DROPBEAR_DEFAULT_CLI_AUTHKEY ".ssh/id_dropbear"
@@ -225,7 +262,7 @@
  * note that it will be provided for all "hidden" client-interactive
  * style prompts - if you want something more sophisticated, use 
  * SSH_ASKPASS instead. Comment out this var to remove this functionality.*/
-#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"
+#define DROPBEAR_USE_DROPBEAR_PASSWORD 1
 
 /* Define this (as well as DROPBEAR_CLI_PASSWORD_AUTH) to allow the use of
  * a helper program for the ssh client. The helper program should be
@@ -234,6 +271,10 @@
  * return the password on standard output */
 #define DROPBEAR_CLI_ASKPASS_HELPER 0
 
+#if DROPBEAR_CLI_ASKPASS_HELPER
+	#define DROPBEAR_CLI_PASSWORD_AUTH 1
+#endif
+
 /* Save a network roundtrip by sendng a real auth request immediately after
  * sending a query for the available methods.  It is at the expense of < 100
  * bytes of extra network traffic. This is not yet enabled by default since it
@@ -246,8 +287,8 @@
 #define DROPBEAR_URANDOM_DEV "/dev/urandom"
 
 /* Set this to use PRNGD or EGD instead of /dev/urandom or /dev/random */
-/*#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"*/
-
+#define DROPBEAR_USE_PRNGD 0
+#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"
 
 /* Specify the number of clients we will allow to be connected but
  * not yet authenticated. After this limit, connections are rejected */
@@ -270,6 +311,8 @@
  * "-q" for quiet */
 #define XAUTH_COMMAND "/usr/bin/xauth -q"
 
+#define DROPBEAR_SFTPSERVER 1
+
 /* if you want to enable running an sftp server (such as the one included with
  * OpenSSH), set the path below. If the path isn't defined, sftp will not
  * be enabled */
@@ -315,4 +358,8 @@
 /* The default path. This will often get replaced by the shell */
 #define DEFAULT_PATH "/usr/bin:/bin"
 
+/* Include verbose debug output, enabled with -v at runtime. 
+ * This will add a reasonable amount to your executable size. */
+#define DEBUG_TRACE 0
+
 #endif /* DROPBEAR_DEFAULT_OPTIONS_H_ */
--- a/ecc.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/ecc.c	Sat Feb 17 11:29:17 2018 +0800
@@ -221,46 +221,41 @@
 
    /* type valid? */
 	if (private_key->type != PK_PRIVATE) {
-		goto done;
+		goto out;
 	}
 
 	if (private_key->dp != public_key->dp) {
-		goto done;
+		goto out;
 	}
 
    /* make new point */
 	result = ltc_ecc_new_point();
 	if (result == NULL) {
-		goto done;
+		goto out;
 	}
 
 	prime = m_malloc(sizeof(*prime));
 	m_mp_init(prime);
 
 	if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) { 
-		goto done; 
+		goto out;
 	}
 	if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) { 
-		goto done; 
+		goto out;
 	}
 
+	shared_secret = m_malloc(sizeof(*shared_secret));
+	m_mp_init(shared_secret);
+	if (mp_copy(result->x, shared_secret) != CRYPT_OK) {
+		goto out;
+	}
+
+	mp_clear(prime);
+	m_free(prime);
+	ltc_ecc_del_point(result);
+
 	err = DROPBEAR_SUCCESS;
-	done:
-	if (err == DROPBEAR_SUCCESS) {
-		shared_secret = m_malloc(sizeof(*shared_secret));
-		m_mp_init(shared_secret);
-		mp_copy(result->x, shared_secret);
-	}
-
-	if (prime) {
-		mp_clear(prime);
-		m_free(prime);
-	}
-	if (result)
-	{
-		ltc_ecc_del_point(result);
-	}
-
+	out:
 	if (err == DROPBEAR_FAILURE) {
 		dropbear_exit("ECC error");
 	}
--- a/keyimport.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/keyimport.c	Sat Feb 17 11:29:17 2018 +0800
@@ -870,7 +870,7 @@
 		 */
 		numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';
 
-	#ifdef DROPBEAR_RSA
+	#if DROPBEAR_RSA
 		if (key->type == DROPBEAR_SIGNKEY_RSA) {
 
 			if (key->rsakey->p == NULL || key->rsakey->q == NULL) {
@@ -966,7 +966,7 @@
 		}
 	#endif /* DROPBEAR_RSA */
 
-	#ifdef DROPBEAR_DSS
+	#if DROPBEAR_DSS
 		if (key->type == DROPBEAR_SIGNKEY_DSS) {
 
 			/* p */
--- a/libtomcrypt/src/ciphers/aes/aes.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/libtomcrypt/src/ciphers/aes/aes.c	Sat Feb 17 11:29:17 2018 +0800
@@ -124,7 +124,6 @@
     int i;
     ulong32 temp, *rk;
 #ifndef ENCRYPT_ONLY
-    int j;
     ulong32 *rrk;
 #endif    
     LTC_ARGCHK(key  != NULL);
--- a/libtomcrypt/src/headers/tomcrypt_custom.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/libtomcrypt/src/headers/tomcrypt_custom.h	Sat Feb 17 11:29:17 2018 +0800
@@ -68,8 +68,8 @@
   #define LTC_NO_MODES
   #define LTC_NO_HASHES
   #define LTC_NO_MACS
-  #define LTC_NO_PRNGS
-  #define LTC_NO_PK
+   #define LTC_NO_PRNGS
+   #define LTC_NO_PK
   #define LTC_NO_PKCS
   #define LTC_NO_MISC
 #endif /* LTC_NOTHING */
--- a/netio.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/netio.c	Sat Feb 17 11:29:17 2018 +0800
@@ -488,7 +488,7 @@
 	 * caller can do a get_socket_address to discover assigned-port
 	 * hence, use same port for all address families
 	 */
-	u_int16_t *allocated_lport_p = 0;
+	u_int16_t *allocated_lport_p = NULL;
 	int allocated_lport = 0;
 
 	nsock = 0;
@@ -613,7 +613,7 @@
 	
 	int flags = NI_NUMERICSERV | NI_NUMERICHOST;
 
-#ifndef DO_HOST_LOOKUP
+#if !DO_HOST_LOOKUP
 	host_lookup = 0;
 #endif
 	
--- a/packet.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/packet.c	Sat Feb 17 11:29:17 2018 +0800
@@ -331,10 +331,6 @@
 		ses.payload = ses.readbuf;
 		ses.payload_beginning = ses.payload->pos;
 		buf_setlen(ses.payload, ses.payload->pos + len);
-		/* copy payload */
-		//ses.payload = buf_new(len);
-		//memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len);
-		//buf_incrlen(ses.payload, len);
 	}
 	ses.readbuf = NULL;
 
--- a/runopts.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/runopts.h	Sat Feb 17 11:29:17 2018 +0800
@@ -86,7 +86,7 @@
 	int ipv6;
 	*/
 
-#ifdef DO_MOTD
+#if DO_MOTD
 	/* whether to print the MOTD */
 	int domotd;
 #endif
--- a/session.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/session.h	Sat Feb 17 11:29:17 2018 +0800
@@ -40,9 +40,6 @@
 #include "dbutil.h"
 #include "netio.h"
 
-extern int sessinitdone; /* Is set to 0 somewhere */
-extern int exitflag;
-
 void common_session_init(int sock_in, int sock_out);
 void session_loop(void(*loophandler)()) ATTRIB_NORETURN;
 void session_cleanup(void);
@@ -157,6 +154,7 @@
 	
 	int signal_pipe[2]; /* stores endpoints of a self-pipe used for
 						   race-free signal handling */
+	int channel_signal_pending; /* Flag set when the signal pipe is triggered */
 
 	m_list conn_pending;
 						
@@ -203,7 +201,6 @@
 	unsigned int chansize; /* the number of Channel*s allocated for channels */
 	unsigned int chancount; /* the number of Channel*s in use */
 	const struct ChanType **chantypes; /* The valid channel types */
-	int channel_signal_pending; /* Flag set by sigchld handler */
 
 	/* TCP priority level for the main "port 22" tcp socket */
 	enum dropbear_prio socket_prio;
@@ -216,6 +213,10 @@
 	 * really belong here, but nowhere else fits nicely */
 	int allowprivport;
 
+	/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
+	volatile int exitflag;
+	/* set once the ses structure (and cli_ses/svr_ses) have been populated to their initial state */
+	int init_done;
 };
 
 struct serversession {
@@ -283,7 +284,7 @@
 	/* for escape char handling */
 	int last_char;
 
-	int winchange; /* Set to 1 when a windowchange signal happens */
+	volatile int winchange; /* Set to 1 when a windowchange signal happens */
 
 	int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
 						 for the last type of auth we tried */
--- a/signkey.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/signkey.c	Sat Feb 17 11:29:17 2018 +0800
@@ -78,13 +78,13 @@
 #if DROPBEAR_ECDSA
 			/* Some of the ECDSA key sizes are defined even if they're not compiled in */
 			if (0
-#ifndef DROPBEAR_ECC_256
+#if !DROPBEAR_ECC_256
 				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP256
 #endif
-#ifndef DROPBEAR_ECC_384
+#if !DROPBEAR_ECC_384
 				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP384
 #endif
-#ifndef DROPBEAR_ECC_521
+#if !DROPBEAR_ECC_521
 				|| i == DROPBEAR_SIGNKEY_ECDSA_NISTP521
 #endif
 				) {
--- a/svr-authpubkey.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-authpubkey.c	Sat Feb 17 11:29:17 2018 +0800
@@ -473,12 +473,4 @@
 	return DROPBEAR_SUCCESS;
 }
 
-#ifdef DROPBEAR_FUZZ
-int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename,
-		const char* algo, unsigned int algolen,
-		const unsigned char* keyblob, unsigned int keybloblen) {
-	return checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen);
-}
 #endif
-
-#endif
--- a/svr-authpubkeyoptions.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-authpubkeyoptions.c	Sat Feb 17 11:29:17 2018 +0800
@@ -100,7 +100,7 @@
 			chansess->original_command = m_strdup("");
 		}
 		chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command);
-#ifdef LOG_COMMANDS
+#if LOG_COMMANDS
 		dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command);
 #endif
 	}
--- a/svr-chansession.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-chansession.c	Sat Feb 17 11:29:17 2018 +0800
@@ -80,6 +80,55 @@
 	return chansess->exit.exitpid != -1;
 }
 
+void svr_chansess_checksignal(void) {
+	int status;
+	pid_t pid;
+
+	if (!ses.channel_signal_pending) {
+		return;
+	}
+
+	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+		unsigned int i;
+		struct exitinfo *ex = NULL;
+		TRACE(("sigchld handler: pid %d", pid))
+
+		ex = NULL;
+		/* find the corresponding chansess */
+		for (i = 0; i < svr_ses.childpidsize; i++) {
+			if (svr_ses.childpids[i].pid == pid) {
+				TRACE(("found match session"));
+				ex = &svr_ses.childpids[i].chansess->exit;
+				break;
+			}
+		}
+
+		/* If the pid wasn't matched, then we might have hit the race mentioned
+		 * above. So we just store the info for the parent to deal with */
+		if (ex == NULL) {
+			TRACE(("using lastexit"));
+			ex = &svr_ses.lastexit;
+		}
+
+		ex->exitpid = pid;
+		if (WIFEXITED(status)) {
+			ex->exitstatus = WEXITSTATUS(status);
+		}
+		if (WIFSIGNALED(status)) {
+			ex->exitsignal = WTERMSIG(status);
+#if !defined(AIX) && defined(WCOREDUMP)
+			ex->exitcore = WCOREDUMP(status);
+#else
+			ex->exitcore = 0;
+#endif
+		} else {
+			/* we use this to determine how pid exited */
+			ex->exitsignal = -1;
+		}
+		
+	}
+}
+
 /* Handler for childs exiting, store the state for return to the client */
 
 /* There's a particular race we have to watch out for: if the forked child
@@ -89,63 +138,19 @@
  * the parent when it runs. This work correctly at least in the case of a
  * single shell spawned (ie the usual case) */
 static void sesssigchild_handler(int UNUSED(dummy)) {
-
-	int status;
-	pid_t pid;
-	unsigned int i;
 	struct sigaction sa_chld;
-	struct exitinfo *exit = NULL;
 
 	const int saved_errno = errno;
 
-	/* Make channel handling code look for closed channels */
-	ses.channel_signal_pending = 1;
-
 	TRACE(("enter sigchld handler"))
-	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-		TRACE(("sigchld handler: pid %d", pid))
-
-		exit = NULL;
-		/* find the corresponding chansess */
-		for (i = 0; i < svr_ses.childpidsize; i++) {
-			if (svr_ses.childpids[i].pid == pid) {
-				TRACE(("found match session"));
-				exit = &svr_ses.childpids[i].chansess->exit;
-				break;
-			}
-		}
-
-		/* If the pid wasn't matched, then we might have hit the race mentioned
-		 * above. So we just store the info for the parent to deal with */
-		if (exit == NULL) {
-			TRACE(("using lastexit"));
-			exit = &svr_ses.lastexit;
-		}
 
-		exit->exitpid = pid;
-		if (WIFEXITED(status)) {
-			exit->exitstatus = WEXITSTATUS(status);
-		}
-		if (WIFSIGNALED(status)) {
-			exit->exitsignal = WTERMSIG(status);
-#if !defined(AIX) && defined(WCOREDUMP)
-			exit->exitcore = WCOREDUMP(status);
-#else
-			exit->exitcore = 0;
-#endif
-		} else {
-			/* we use this to determine how pid exited */
-			exit->exitsignal = -1;
-		}
-		
-		/* Make sure that the main select() loop wakes up */
-		while (1) {
-			/* isserver is just a random byte to write. We can't do anything
-			about an error so should just ignore it */
-			if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
-					|| errno != EINTR) {
-				break;
-			}
+	/* Make sure that the main select() loop wakes up */
+	while (1) {
+		/* isserver is just a random byte to write. We can't do anything
+		about an error so should just ignore it */
+		if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
+				|| errno != EINTR) {
+			break;
 		}
 	}
 
@@ -658,7 +663,7 @@
 			}
 		}
 		if (issubsys) {
-#ifdef SFTPSERVER_PATH
+#if DROPBEAR_SFTPSERVER
 			if ((cmdlen == 4) && strncmp(chansess->cmd, "sftp", 4) == 0) {
 				m_free(chansess->cmd);
 				chansess->cmd = m_strdup(SFTPSERVER_PATH);
@@ -682,7 +687,7 @@
 	}
 
 
-#ifdef LOG_COMMANDS
+#if LOG_COMMANDS
 	if (chansess->cmd) {
 		dropbear_log(LOG_INFO, "User %s executing '%s'", 
 						ses.authstate.pw_name, chansess->cmd);
@@ -769,7 +774,7 @@
 
 	pid_t pid;
 	struct logininfo *li = NULL;
-#ifdef DO_MOTD
+#if DO_MOTD
 	buffer * motdbuf = NULL;
 	int len;
 	struct stat sb;
@@ -821,7 +826,7 @@
 		login_login(li);
 		login_free_entry(li);
 
-#ifdef DO_MOTD
+#if DO_MOTD
 		if (svr_opts.domotd && !chansess->cmd) {
 			/* don't show the motd if ~/.hushlogin exists */
 
@@ -899,7 +904,7 @@
 /* Clean up, drop to user privileges, set up the environment and execute
  * the command/shell. This function does not return. */
 static void execchild(const void *user_data) {
-	struct ChanSess *chansess = user_data;
+	const struct ChanSess *chansess = user_data;
 	char *usershell = NULL;
 
 	/* with uClinux we'll have vfork()ed, so don't want to overwrite the
--- a/svr-main.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-main.c	Sat Feb 17 11:29:17 2018 +0800
@@ -35,10 +35,10 @@
 static void sigchld_handler(int dummy);
 static void sigsegv_handler(int);
 static void sigintterm_handler(int fish);
-#ifdef INETD_MODE
+#if INETD_MODE
 static void main_inetd(void);
 #endif
-#ifdef NON_INETD_MODE
+#if NON_INETD_MODE
 static void main_noinetd(void);
 #endif
 static void commonsetup(void);
@@ -58,7 +58,7 @@
 	/* get commandline options */
 	svr_getopts(argc, argv);
 
-#ifdef INETD_MODE
+#if INETD_MODE
 	/* service program mode */
 	if (svr_opts.inetdmode) {
 		main_inetd();
@@ -66,7 +66,7 @@
 	}
 #endif
 
-#ifdef NON_INETD_MODE
+#if NON_INETD_MODE
 	main_noinetd();
 	/* notreached */
 #endif
@@ -76,13 +76,20 @@
 }
 #endif
 
-#ifdef INETD_MODE
+#if INETD_MODE
 static void main_inetd() {
 	char *host, *port = NULL;
 
 	/* Set up handlers, syslog, seed random */
 	commonsetup();
 
+#if DEBUG_TRACE
+	if (debug_trace) {
+		/* -v output goes to stderr which would get sent over the inetd network socket */
+		dropbear_exit("Dropbear inetd mode is incompatible with debug -v");
+	}
+#endif
+
 	/* In case our inetd was lax in logging source addresses */
 	get_socket_address(0, NULL, NULL, &host, &port, 0);
 	dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port);
@@ -103,7 +110,7 @@
 }
 #endif /* INETD_MODE */
 
-#ifdef NON_INETD_MODE
+#if NON_INETD_MODE
 static void main_noinetd() {
 	fd_set fds;
 	unsigned int i, j;
@@ -188,7 +195,7 @@
 
 		val = select(maxsock+1, &fds, NULL, NULL, NULL);
 
-		if (exitflag) {
+		if (ses.exitflag) {
 			unlink(svr_opts.pidfile);
 			dropbear_exit("Terminated by signal");
 		}
@@ -359,7 +366,7 @@
 /* catch ctrl-c or sigterm */
 static void sigintterm_handler(int UNUSED(unused)) {
 
-	exitflag = 1;
+	ses.exitflag = 1;
 }
 
 /* Things used by inetd and non-inetd modes */
--- a/svr-runopts.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-runopts.c	Sat Feb 17 11:29:17 2018 +0800
@@ -64,7 +64,7 @@
 #else
 					"-E		Log to stderr rather than syslog\n"
 #endif
-#ifdef DO_MOTD
+#if DO_MOTD
 					"-m		Don't display the motd on login\n"
 #endif
 					"-w		Disallow root logins\n"
@@ -88,7 +88,7 @@
 					"		(default port is %s if none specified)\n"
 					"-P PidFile	Create pid file PidFile\n"
 					"		(default %s)\n"
-#ifdef INETD_MODE
+#if INETD_MODE
 					"-i		Start for inetd\n"
 #endif
 					"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
@@ -156,7 +156,7 @@
 	opts.ipv4 = 1;
 	opts.ipv6 = 1;
 	*/
-#ifdef DO_MOTD
+#if DO_MOTD
 	svr_opts.domotd = 1;
 #endif
 #ifndef DISABLE_SYSLOG
@@ -210,7 +210,7 @@
 					opts.listen_fwd_all = 1;
 					break;
 #endif
-#ifdef INETD_MODE
+#if INETD_MODE
 				case 'i':
 					svr_opts.inetdmode = 1;
 					break;
@@ -221,7 +221,7 @@
 				case 'P':
 					next = &svr_opts.pidfile;
 					break;
-#ifdef DO_MOTD
+#if DO_MOTD
 				/* motd is displayed by default, -m turns it off */
 				case 'm':
 					svr_opts.domotd = 0;
--- a/svr-session.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-session.c	Sat Feb 17 11:29:17 2018 +0800
@@ -124,7 +124,7 @@
 	ses.isserver = 1;
 
 	/* We're ready to go now */
-	sessinitdone = 1;
+	ses.init_done = 1;
 
 	/* exchange identification, version etc */
 	send_session_identification();
@@ -136,7 +136,7 @@
 
 	/* Run the main for loop. NULL is for the dispatcher - only the client
 	 * code makes use of it */
-	session_loop(NULL);
+	session_loop(svr_chansess_checksignal);
 
 	/* Not reached */
 
@@ -152,7 +152,7 @@
 	vsnprintf(exitmsg, sizeof(exitmsg), format, param);
 
 	/* Add the prefix depending on session/auth state */
-	if (!sessinitdone) {
+	if (!ses.init_done) {
 		/* before session init */
 		snprintf(fullmsg, sizeof(fullmsg), "Early exit: %s", exitmsg);
 	} else if (ses.authstate.authdone) {
--- a/svr-tcpfwd.c	Sat Feb 10 19:06:13 2018 +0800
+++ b/svr-tcpfwd.c	Sat Feb 17 11:29:17 2018 +0800
@@ -35,7 +35,7 @@
 #include "auth.h"
 #include "netio.h"
 
-#ifndef DROPBEAR_SVR_REMOTETCPFWD
+#if !DROPBEAR_SVR_REMOTETCPFWD
 
 /* This is better than SSH_MSG_UNIMPLEMENTED */
 void recv_msg_global_request_remotetcp() {
@@ -95,7 +95,7 @@
 			buf_putint(ses.writepayload, allocated_listen_port);
 			encrypt_packet();
 			wantreply = 0; //so out does not do so
-	  }
+		}
 	} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
 		ret = svr_cancelremotetcp();
 	} else {
--- a/sysoptions.h	Sat Feb 10 19:06:13 2018 +0800
+++ b/sysoptions.h	Sat Feb 17 11:29:17 2018 +0800
@@ -192,7 +192,7 @@
 
 #define DROPBEAR_CLI_MULTIHOP ((DROPBEAR_CLI_NETCAT) && (DROPBEAR_CLI_PROXYCMD))
 
-#define ENABLE_CONNECT_UNIX ((DROPBEAR_CLI_AGENTFWD) || (DROPBEAR_PRNGD_SOCKET))
+#define ENABLE_CONNECT_UNIX ((DROPBEAR_CLI_AGENTFWD) || (DROPBEAR_USE_PRNGD))
 
 /* if we're using authorized_keys or known_hosts */ 
 #define DROPBEAR_KEY_LINES ((DROPBEAR_CLIENT) || (DROPBEAR_SVR_PUBKEY_AUTH))