changeset 1407:8d9bad0a1c86

Merge pull request #38 from armcc/master Fix libtomcrypt/libtommath linking order
author Matt Johnston <matt@ucc.asn.au>
date Sat, 03 Jun 2017 09:45:55 +0800
parents 2688fec5602c (diff) 96a282e78085 (current diff)
children c721e8c42d2a 8b74d5f876a7
files configure.ac
diffstat 38 files changed, 288 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Sat Jun 03 09:45:55 2017 +0800
@@ -0,0 +1,21 @@
+*~
+*.o
+*.a
+*.da
+*.bb
+*.bbg
+*.prof
+/autom4te.cache
+/config.log
+/config.status
+/dbclient
+/dropbear
+/dropbearconvert
+/dropbearkey
+/dropbearmulti
+/scp
+/scp-progress
+Makefile
+config.h
+config.h.in
+configure
--- a/.hgsigs	Fri Sep 16 12:18:23 2016 -0700
+++ b/.hgsigs	Sat Jun 03 09:45:55 2017 +0800
@@ -22,3 +22,4 @@
 fd1981f41c626a969f07b4823848deaefef3c8aa 0 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
+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
--- a/.hgtags	Fri Sep 16 12:18:23 2016 -0700
+++ b/.hgtags	Sat Jun 03 09:45:55 2017 +0800
@@ -54,3 +54,4 @@
 78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72
 309e1c4a87682b6ca7d80b8555a1db416c3cb7ac DROPBEAR_2016.73
 0ed3d2bbf956cb8a9bf0f4b5a86b7dd9688205cb DROPBEAR_2016.74
+c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75
--- a/CHANGES	Fri Sep 16 12:18:23 2016 -0700
+++ b/CHANGES	Sat Jun 03 09:45:55 2017 +0800
@@ -1,3 +1,30 @@
+2017.75 - 18 May 2017
+
+- Security: Fix double-free in server TCP listener cleanup
+  A double-free in the server could be triggered by an authenticated user if
+  dropbear is running with -a (Allow connections to forwarded ports from any host)
+  This could potentially allow arbitrary code execution as root by an authenticated user.
+  Affects versions 2013.56 to 2016.74. Thanks to Mark Shepard for reporting the crash.
+  CVE-2017-9078 https://secure.ucc.asn.au/hg/dropbear/rev/c8114a48837c
+
+- Security: Fix information disclosure with ~/.ssh/authorized_keys symlink.
+  Dropbear parsed authorized_keys as root, even if it were a symlink. The fix
+  is to switch to user permissions when opening authorized_keys
+
+  A user could symlink their ~/.ssh/authorized_keys to a root-owned file they
+  couldn't normally read. If they managed to get that file to contain valid
+  authorized_keys with command= options it might be possible to read other
+  contents of that file.
+  This information disclosure is to an already authenticated user.
+  Thanks to Jann Horn of Google Project Zero for reporting this.
+  CVE-2017-9079 https://secure.ucc.asn.au/hg/dropbear/rev/0d889b068123
+
+- Generate hostkeys with dropbearkey atomically and flush to disk with fsync
+  Thanks to Andrei Gherzan for a patch
+
+- Fix out of tree builds with bundled libtom
+  Thanks to Henrik Nordström and Peter Krefting for patches.
+
 2016.74 - 21 July 2016
 
 - Security: Message printout was vulnerable to format string injection.
--- a/atomicio.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/atomicio.c	Sat Jun 03 09:45:55 2017 +0800
@@ -1,6 +1,8 @@
+/* $OpenBSD: atomicio.c,v 1.17 2006/04/01 05:51:34 djm Exp $ */
 /*
- * Copied from OpenSSH 3.6.1p2.
+ * Copied from OpenSSH/OpenBSD.
  * 
+ * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -25,39 +27,32 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
+#include "includes.h"
 
 #include "atomicio.h"
 
 /*
- * ensure all of data on socket comes through. f==read || f==write
+ * ensure all of data on socket comes through. f==read || f==vwrite
  */
-ssize_t
-atomicio(f, fd, _s, n)
-	ssize_t (*f) ();
-	int fd;
-	void *_s;
-	size_t n;
+size_t
+atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
 {
 	char *s = _s;
+	size_t pos = 0;
 	ssize_t res;
-	size_t pos = 0;
 
 	while (n > pos) {
 		res = (f) (fd, s + pos, n - pos);
 		switch (res) {
 		case -1:
-#ifdef EWOULDBLOCK
-			if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
-#else
 			if (errno == EINTR || errno == EAGAIN)
-#endif
 				continue;
-			/* FALLTHROUGH */
+			return 0;
 		case 0:
-			return (res);
+			errno = EPIPE;
+			return pos;
 		default:
-			pos += res;
+			pos += (size_t)res;
 		}
 	}
 	return (pos);
--- a/atomicio.h	Fri Sep 16 12:18:23 2016 -0700
+++ b/atomicio.h	Sat Jun 03 09:45:55 2017 +0800
@@ -1,8 +1,7 @@
+/* $OpenBSD: atomicio.h,v 1.7 2006/03/25 22:22:42 djm Exp $ */
 
 /*
- * Copied from OpenSSH 3.6.1p2, required for loginrec.c
- *
- * $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
+ * Copied from OpenSSH/OpenBSD, required for loginrec.c
  *
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
@@ -28,9 +27,9 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "includes.h"
+/*
+ * Ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
 
-/*
- * Ensure all of data on socket comes through. f==read || f==write
- */
-ssize_t	atomicio(ssize_t (*)(), int, void *, size_t);
+#define vwrite (ssize_t (*)(int, void *, size_t))write
--- a/buffer.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/buffer.c	Sat Jun 03 09:45:55 2017 +0800
@@ -109,6 +109,7 @@
 		dropbear_exit("Bad buf_setlen");
 	}
 	buf->len = len;
+	buf->pos = MIN(buf->pos, buf->len);
 }
 
 /* Increment the length of the buffer */
--- a/cli-agentfwd.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/cli-agentfwd.c	Sat Jun 03 09:45:55 2017 +0800
@@ -130,7 +130,7 @@
 	}
 	buf_setpos(payload, 0);
 
-	ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
+	ret = atomicio(vwrite, fd, buf_getptr(payload, payload->len), payload->len);
 	if ((size_t)ret != payload->len) {
 		TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno)))
 		goto out;
--- a/cli-runopts.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/cli-runopts.c	Sat Jun 03 09:45:55 2017 +0800
@@ -106,7 +106,7 @@
 
 void cli_getopts(int argc, char ** argv) {
 	unsigned int i, j;
-	char ** next = 0;
+	char ** next = NULL;
 	enum {
 		OPT_EXTENDED_OPTIONS,
 #if DROPBEAR_CLI_PUBKEY_AUTH
--- a/cli-session.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/cli-session.c	Sat Jun 03 09:45:55 2017 +0800
@@ -81,7 +81,7 @@
 	{SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
 	{SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
 #endif
-	{0, 0} /* End */
+	{0, NULL} /* End */
 };
 
 static const struct ChanType *cli_chantypes[] = {
@@ -287,7 +287,7 @@
 				int devnull;
 				/* keeping stdin open steals input from the terminal and
 				   is confusing, though stdout/stderr could be useful. */
-				devnull = open(_PATH_DEVNULL, O_RDONLY);
+				devnull = open(DROPBEAR_PATH_DEVNULL, O_RDONLY);
 				if (devnull < 0) {
 					dropbear_exit("Opening /dev/null: %d %s",
 							errno, strerror(errno));
--- a/cli-tcpfwd.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/cli-tcpfwd.c	Sat Jun 03 09:45:55 2017 +0800
@@ -234,7 +234,7 @@
 	char *origaddr = NULL;
 	unsigned int origport;
 	m_list_elem * iter = NULL;
-	struct TCPFwdEntry *fwd;
+	struct TCPFwdEntry *fwd = NULL;
 	char portstring[NI_MAXSERV];
 	int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
 
@@ -265,7 +265,7 @@
 	}
 
 
-	if (iter == NULL) {
+	if (iter == NULL || fwd == NULL) {
 		/* We didn't request forwarding on that port */
 		cleantext(origaddr);
 		dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"", 
--- a/common-channel.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/common-channel.c	Sat Jun 03 09:45:55 2017 +0800
@@ -32,7 +32,6 @@
 #include "circbuffer.h"
 #include "dbutil.h"
 #include "channel.h"
-#include "ssh.h"
 #include "listener.h"
 #include "runopts.h"
 #include "netio.h"
--- a/common-kex.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/common-kex.c	Sat Jun 03 09:45:55 2017 +0800
@@ -774,7 +774,7 @@
 	hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize));
 	buf_setlen(ses.hash, hash_desc->hashsize);
 
-#if (DEBUG_KEXHASH) && (DEBUG_TRACE)
+#if defined(DEBUG_KEXHASH) && DEBUG_TRACE
 	if (!debug_trace) {
 		printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len);
 		printhex("kexhash", ses.hash->data, ses.hash->len);
--- a/compat.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/compat.c	Sat Jun 03 09:45:55 2017 +0800
@@ -114,8 +114,8 @@
 #endif /* HAVE_STRLCPY */
 
 #ifndef HAVE_STRLCAT
-/* taken from openbsd-compat for OpenSSH 3.6.1p1 */
-/* "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"
+/* taken from openbsd-compat for OpenSSH 7.2p2 */
+/* "$OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $"
  *
  * Appends src to string dst of size siz (unlike strncat, siz is the
  * full size of dst, not space left).  At most siz-1 characters
@@ -123,15 +123,12 @@
  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
  * If retval >= siz, truncation occurred.
  */
-	size_t
-strlcat(dst, src, siz)
-	char *dst;
-	const char *src;
-	size_t siz;
+size_t
+strlcat(char *dst, const char *src, size_t siz)
 {
-	register char *d = dst;
-	register const char *s = src;
-	register size_t n = siz;
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
 	size_t dlen;
 
 	/* Find the end of dst and adjust bytes left but don't go past end */
@@ -177,7 +174,7 @@
 	if (!nochdir)
 		(void)chdir("/");
 
-	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+	if (!noclose && (fd = open(DROPBEAR_PATH_DEVNULL, O_RDWR, 0)) != -1) {
 		(void)dup2(fd, STDIN_FILENO);
 		(void)dup2(fd, STDOUT_FILENO);
 		(void)dup2(fd, STDERR_FILENO);
--- a/configure.ac	Fri Sep 16 12:18:23 2016 -0700
+++ b/configure.ac	Sat Jun 03 09:45:55 2017 +0800
@@ -45,8 +45,8 @@
 	sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'`
 	if test "$sol2ver" -ge 8; then
 		AC_MSG_RESULT(yes)
-		AC_DEFINE(DISABLE_UTMP,,Disable utmp)
-		AC_DEFINE(DISABLE_WTMP,,Disable wtmp)
+		AC_DEFINE(DISABLE_UTMP,1,Disable utmp)
+		AC_DEFINE(DISABLE_WTMP,1,Disable wtmp)
 	else
 		AC_MSG_RESULT(no)
 	fi
@@ -55,18 +55,18 @@
 	;;
 
 *-*-aix*)
-	AC_DEFINE(AIX,,Using AIX)
+	AC_DEFINE(AIX,1,Using AIX)
 	# OpenSSH thinks it's broken. If it isn't, let me know.
-	AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
+	AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
 	;;
 	
 *-*-hpux*)
 	LIBS="$LIBS -lsec"
 	# It's probably broken.
-	AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
+	AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
 	;;
 *-dec-osf*)
-	AC_DEFINE(BROKEN_GETADDRINFO,,Broken getaddrinfo)
+	AC_DEFINE(BROKEN_GETADDRINFO,1,Broken getaddrinfo)
 	;;
 esac
 
@@ -80,7 +80,7 @@
 	[
 	no_loginfunc_check=1
 	AC_MSG_NOTICE([Using uClibc - login() and logout() probably don't work, so we won't use them.])
-	],,,)
+	],,)
 
 dnl We test for crypt() specially. On Linux (and others?) it resides in libcrypt
 dnl but we don't want link all binaries to -lcrypt, just dropbear server.
@@ -118,7 +118,7 @@
 	[  --disable-zlib          Don't include zlib support],
 	[
 		if test "x$enableval" = "xno"; then
-			AC_DEFINE(DISABLE_ZLIB,, Use zlib)
+			AC_DEFINE(DISABLE_ZLIB,1,Use zlib)
 			AC_MSG_NOTICE(Disabling zlib)
 		else
 			AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR([*** zlib missing - install first or check config.log ***]))
@@ -159,13 +159,13 @@
 			AC_MSG_NOTICE(Enabling PAM)
 			AC_CHECK_FUNCS(pam_fail_delay)
 		else
-			AC_DEFINE(DISABLE_PAM,, Use PAM)
+			AC_DEFINE(DISABLE_PAM,1,Use PAM)
 			AC_MSG_NOTICE(Disabling PAM)
 		fi
 	],
 	[
 		# disable it by default
-		AC_DEFINE(DISABLE_PAM,, Use PAM)
+		AC_DEFINE(DISABLE_PAM,1,Use PAM)
 		AC_MSG_NOTICE(Disabling PAM)
 	]
 )
@@ -177,7 +177,7 @@
 			AC_MSG_NOTICE(Not using openpty)
 		else
 			AC_MSG_NOTICE(Using openpty if available)
-			AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY,,Have openpty() function)])
+			AC_SEARCH_LIBS(openpty, util, [AC_DEFINE(HAVE_OPENPTY,1,[Have openpty() function])])
 		fi
 	],
 	[
@@ -191,7 +191,7 @@
 	[  --disable-syslog        Don't include syslog support],
 	[
 		if test "x$enableval" = "xno"; then
-			AC_DEFINE(DISABLE_SYSLOG,, Using syslog)
+			AC_DEFINE(DISABLE_SYSLOG,1,Using syslog)
 			AC_MSG_NOTICE(Disabling syslog)
 		else
 			AC_MSG_NOTICE(Enabling syslog)
@@ -295,7 +295,7 @@
 	)
 ])
 if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
-	AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6,,Have struct sockaddr_in6)
+	AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6,1,Have struct sockaddr_in6)
 fi
 
 AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
@@ -309,7 +309,7 @@
 	)
 ])
 if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
-	AC_DEFINE(HAVE_STRUCT_IN6_ADDR,,Have struct in6_addr)
+	AC_DEFINE(HAVE_STRUCT_IN6_ADDR,1,Have struct in6_addr)
 fi
 
 AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
@@ -324,7 +324,7 @@
 	)
 ])
 if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
-	AC_DEFINE(HAVE_STRUCT_ADDRINFO,,Have struct addrinfo)
+	AC_DEFINE(HAVE_STRUCT_ADDRINFO,1,Have struct addrinfo)
 fi
 
 
@@ -402,7 +402,7 @@
 )
 
 if test $BUNDLED_LIBTOM = 1 ; then
-	AC_DEFINE(BUNDLED_LIBTOM,,Use bundled libtom) 
+	AC_DEFINE(BUNDLED_LIBTOM,1,Use bundled libtom) 
 fi
 
 AC_SUBST(LIBTOM_LIBS)
@@ -413,36 +413,64 @@
 dnl allow user to disable some login recording features
 AC_ARG_ENABLE(lastlog,
 	[  --disable-lastlog       Disable use of lastlog even if detected [no]],
-	[ AC_DEFINE(DISABLE_LASTLOG,,Disable use of lastlog()) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_LASTLOG,1,Disable use of lastlog())
+		fi
+	]
 )
 AC_ARG_ENABLE(utmp,
 	[  --disable-utmp          Disable use of utmp even if detected [no]],
-	[ AC_DEFINE(DISABLE_UTMP,,Disable use of utmp) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_UTMP,1,Disable use of utmp)
+		fi
+	]
 )
 AC_ARG_ENABLE(utmpx,
 	[  --disable-utmpx         Disable use of utmpx even if detected [no]],
-	[ AC_DEFINE(DISABLE_UTMPX,,Disable use of utmpx) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_UTMPX,1,Disable use of utmpx)
+		fi
+	]
 )
 AC_ARG_ENABLE(wtmp,
 	[  --disable-wtmp          Disable use of wtmp even if detected [no]],
-	[ AC_DEFINE(DISABLE_WTMP,,Disable use of wtmp) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_WTMP,1,Disable use of wtmp)
+		fi
+	]
 )
 AC_ARG_ENABLE(wtmpx,
 	[  --disable-wtmpx         Disable use of wtmpx even if detected [no]],
-	[ AC_DEFINE(DISABLE_WTMPX,,Disable use of wtmpx) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_WTMPX,1,Disable use of wtmpx)
+		fi
+	]
 )
 AC_ARG_ENABLE(loginfunc,
 	[  --disable-loginfunc     Disable use of login() etc. [no]],
 	[ no_loginfunc_check=1
-	AC_MSG_NOTICE(Not using login() etc) ]
+	AC_MSG_NOTICE([Not using login() etc]) ]
 )
 AC_ARG_ENABLE(pututline,
 	[  --disable-pututline     Disable use of pututline() etc. ([uw]tmp) [no]],
-	[ AC_DEFINE(DISABLE_PUTUTLINE,,Disable use of pututline()) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_PUTUTLINE,1,Disable use of pututline())
+		fi
+	]
 )
 AC_ARG_ENABLE(pututxline,
 	[  --disable-pututxline    Disable use of pututxline() etc. ([uw]tmpx) [no]],
-	[ AC_DEFINE(DISABLE_PUTUTXLINE,,Disable use of pututxline()) ]
+	[
+		if test "x$enableval" = "xno" ; then
+			AC_DEFINE(DISABLE_PUTUTXLINE,1,Disable use of pututxline())
+		fi
+	]
 )
 AC_ARG_WITH(lastlog,
   [  --with-lastlog=FILE|DIR specify lastlog location [common locations]],
@@ -457,7 +485,7 @@
 
 if test -z "$no_loginfunc_check"; then
 	dnl    Checks for libutil functions (login(), logout() etc, not openpty() )
-	AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN,,Have login() function)])
+	AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN,1,[Have login() function])])
 	AC_CHECK_FUNCS(logout updwtmp logwtmp)
 fi
 
@@ -653,7 +681,7 @@
 if test -z "$no_ptmx_check" ; then
 	if test x"$cross_compiling" = x"no" ; then
 		if test -e /dev/ptmx ; then
-			AC_DEFINE(USE_DEV_PTMX,,Use /dev/ptmx)
+			AC_DEFINE(USE_DEV_PTMX,1,Use /dev/ptmx)
 		fi
 	else
 		AC_MSG_NOTICE([Not checking for /dev/ptmx, we're cross-compiling])
@@ -663,7 +691,7 @@
 if test -z "$no_ptc_check" ; then
 	if test x"$cross_compiling" = x"no" ; then
 		if test -e /dev/ptc ; then
-			AC_DEFINE(HAVE_DEV_PTS_AND_PTC,,Use /dev/ptc & /dev/pts)
+			AC_DEFINE(HAVE_DEV_PTS_AND_PTC,1,Use /dev/ptc & /dev/pts)
 		fi
 	else
 		AC_MSG_NOTICE([Not checking for /dev/ptc & /dev/pts since we're cross-compiling])
--- a/dbrandom.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/dbrandom.c	Sat Jun 03 09:45:55 2017 +0800
@@ -59,7 +59,7 @@
 	unsigned int readcount;
 	int ret = DROPBEAR_FAILURE;
 
-#if DROPBEAR_PRNGD_SOCKET
+#ifdef DROPBEAR_PRNGD_SOCKET
 	if (prngd)
 	{
 		readfd = connect_unix(filename);
@@ -107,7 +107,7 @@
 			wantread = MIN(sizeof(readbuf), len-readcount);
 		}
 
-#if DROPBEAR_PRNGD_SOCKET
+#ifdef DROPBEAR_PRNGD_SOCKET
 		if (prngd)
 		{
 			char egdcmd[2];
@@ -185,7 +185,7 @@
 	/* existing state */
 	sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
 
-#if DROPBEAR_PRNGD_SOCKET
+#ifdef DROPBEAR_PRNGD_SOCKET
 	if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) 
 			!= DROPBEAR_SUCCESS) {
 		dropbear_exit("Failure reading random device %s", 
--- a/dbutil.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/dbutil.c	Sat Jun 03 09:45:55 2017 +0800
@@ -681,4 +681,21 @@
 	return time(NULL);
 }
 
+void fsync_parent_dir(const char* fn) {
+#ifdef HAVE_LIBGEN_H
+	char *fn_dir = m_strdup(fn);
+	char *dir = dirname(fn_dir);
+	int dirfd = open(dir, O_RDONLY);
 
+	if (dirfd != -1) {
+		if (fsync(dirfd) != 0) {
+			TRACE(("fsync of directory %s failed: %s", dir, strerror(errno)))
+		}
+		m_close(dirfd);
+	} else {
+		TRACE(("error opening directory %s for fsync: %s", dir, strerror(errno)))
+	}
+
+	free(fn_dir);
+#endif
+}
--- a/dbutil.h	Fri Sep 16 12:18:23 2016 -0700
+++ b/dbutil.h	Sat Jun 03 09:45:55 2017 +0800
@@ -89,4 +89,6 @@
 
 char * expand_homedir_path(const char *inpath);
 
+void fsync_parent_dir(const char* fn);
+
 #endif /* DROPBEAR_DBUTIL_H_ */
--- a/debian/changelog	Fri Sep 16 12:18:23 2016 -0700
+++ b/debian/changelog	Sat Jun 03 09:45:55 2017 +0800
@@ -1,3 +1,9 @@
+dropbear (2017.75-0.1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Matt Johnston <[email protected]>  Thu, 18 May 2017 22:51:57 +0800
+
 dropbear (2016.74-0.1) unstable; urgency=low
 
   * New upstream release.
--- a/dropbearkey.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/dropbearkey.c	Sat Jun 03 09:45:55 2017 +0800
@@ -134,7 +134,7 @@
 #endif
 
 	int i;
-	char ** next = 0;
+	char ** next = NULL;
 	char * filename = NULL;
 	enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
 	char * typetext = NULL;
@@ -241,7 +241,7 @@
 	}
 
 	fprintf(stderr, "Generating key, this may take a while...\n");
-	if (signkey_generate(keytype, bits, filename) == DROPBEAR_FAILURE)
+	if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
 	{
 		dropbear_exit("Failed to generate key.\n");
 	}
--- a/gensignkey.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/gensignkey.c	Sat Jun 03 09:45:55 2017 +0800
@@ -76,10 +76,12 @@
 	}
 }
 
-int signkey_generate(enum signkey_type keytype, int bits, const char* filename)
+/* if skip_exist is set it will silently return if the key file exists */
+int signkey_generate(enum signkey_type keytype, int bits, const char* filename, int skip_exist)
 {
 	sign_key * key = NULL;
 	buffer *buf = NULL;
+	char *fn_temp = NULL;
 	int ret = DROPBEAR_FAILURE;
 	if (bits == 0)
 	{
@@ -126,10 +128,37 @@
 	sign_key_free(key);
 	key = NULL;
 	buf_setpos(buf, 0);
-	ret = buf_writefile(buf, filename);
+
+	fn_temp = m_malloc(strlen(filename) + 30);
+	snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid());
+	ret = buf_writefile(buf, fn_temp);
+
+	if (ret == DROPBEAR_FAILURE) {
+		goto out;
+	}
 
-	buf_burn(buf);
-	buf_free(buf);
-	buf = NULL;
+	if (link(fn_temp, filename) < 0) {
+		/* If generating keys on connection (skipexist) it's OK to get EEXIST 
+		- we probably just lost a race with another connection to generate the key */
+		if (!(skip_exist && errno == EEXIST)) {
+			dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename,
+				strerror(errno));
+			/* XXX fallback to non-atomic copy for some filesystems? */
+			ret = DROPBEAR_FAILURE;
+			goto out;
+		}
+	}
+
+out:
+	if (buf) {
+		buf_burn(buf);
+		buf_free(buf);
+	}
+	
+	if (fn_temp) {
+		unlink(fn_temp);
+		m_free(fn_temp);
+	}
+
 	return ret;
 }
--- a/gensignkey.h	Fri Sep 16 12:18:23 2016 -0700
+++ b/gensignkey.h	Sat Jun 03 09:45:55 2017 +0800
@@ -3,6 +3,6 @@
 
 #include "signkey.h"
 
-int signkey_generate(enum signkey_type type, int bits, const char* filename);
+int signkey_generate(enum signkey_type type, int bits, const char* filename, int skip_exist);
 
 #endif
--- a/keyimport.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/keyimport.c	Sat Jun 03 09:45:55 2017 +0800
@@ -694,7 +694,7 @@
 							  &id, &len, &flags);
 		p += ret;
 		/* id==4 for octet string */
-				if (ret < 0 || id != 4 || len < 0 ||
+		if (ret < 0 || id != 4 || len < 0 ||
 			key->keyblob+key->keyblob_len-p < len) {
 			errmsg = "ASN.1 decoding failure";
 			goto error;
@@ -708,7 +708,7 @@
 							  &id, &len, &flags);
 		p += ret;
 		/* id==0 */
-				if (ret < 0 || id != 0 || len < 0) {
+		if (ret < 0 || id != 0 || len < 0) {
 			errmsg = "ASN.1 decoding failure";
 			goto error;
 		}
@@ -717,7 +717,7 @@
 							  &id, &len, &flags);
 		p += ret;
 		/* id==6 for object */
-				if (ret < 0 || id != 6 || len < 0 ||
+		if (ret < 0 || id != 6 || len < 0 ||
 			key->keyblob+key->keyblob_len-p < len) {
 			errmsg = "ASN.1 decoding failure";
 			goto error;
@@ -756,7 +756,7 @@
 							  &id, &len, &flags);
 		p += ret;
 		/* id==1 */
-				if (ret < 0 || id != 1 || len < 0) {
+		if (ret < 0 || id != 1 || len < 0) {
 			errmsg = "ASN.1 decoding failure";
 			goto error;
 		}
@@ -765,7 +765,7 @@
 							  &id, &len, &flags);
 		p += ret;
 		/* id==3 for bit string */
-				if (ret < 0 || id != 3 || len < 0 ||
+		if (ret < 0 || id != 3 || len < 0 ||
 			key->keyblob+key->keyblob_len-p < len) {
 			errmsg = "ASN.1 decoding failure";
 			goto error;
--- a/libtommath/bn_mp_exteuclid.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/libtommath/bn_mp_exteuclid.c	Sat Jun 03 09:45:55 2017 +0800
@@ -29,34 +29,34 @@
 
    /* initialize, (u1,u2,u3) = (1,0,a) */
    mp_set(&u1, 1);
-   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
+   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto LBL_ERR; }
 
    /* initialize, (v1,v2,v3) = (0,1,b) */
    mp_set(&v2, 1);
-   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
+   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto LBL_ERR; }
 
    /* loop while v3 != 0 */
    while (mp_iszero(&v3) == MP_NO) {
        /* q = u3/v3 */
-       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
+       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto LBL_ERR; }
 
        /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
-       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
-       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
-       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
-       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
-       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
-       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto LBL_ERR; }
+       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto LBL_ERR; }
+       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto LBL_ERR; }
+       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto LBL_ERR; }
+       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto LBL_ERR; }
+       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto LBL_ERR; }
 
        /* (u1,u2,u3) = (v1,v2,v3) */
-       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
-       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
-       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto LBL_ERR; }
+       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto LBL_ERR; }
+       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto LBL_ERR; }
 
        /* (v1,v2,v3) = (t1,t2,t3) */
-       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
-       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
-       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto LBL_ERR; }
+       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto LBL_ERR; }
+       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto LBL_ERR; }
    }
 
    /* make sure U3 >= 0 */
@@ -72,7 +72,8 @@
    if (U3 != NULL) { mp_exch(U3, &u3); }
 
    err = MP_OKAY;
-_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+LBL_ERR:
+   mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
    return err;
 }
 #endif
--- a/loginrec.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/loginrec.c	Sat Jun 03 09:45:55 2017 +0800
@@ -706,7 +706,7 @@
 		}
 
 		(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
-		if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut))
+		if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut))
 			dropbear_log(LOG_WARNING, "utmp_write_direct: error writing %s: %s",
 			    UTMP_FILE, strerror(errno));
 
@@ -895,7 +895,7 @@
 		return 0;
 	}
 	if (fstat(fd, &buf) == 0)
-		if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
+		if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
 			ftruncate(fd, buf.st_size);
 			dropbear_log(LOG_WARNING, "wtmp_write: problem writing %s: %s",
 			    WTMP_FILE, strerror(errno));
@@ -1062,7 +1062,7 @@
 	}
 
 	if (fstat(fd, &buf) == 0)
-		if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) {
+		if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) {
 			ftruncate(fd, buf.st_size);
 			dropbear_log(LOG_WARNING, "wtmpx_write: problem writing %s: %s",
 			    WTMPX_FILE, strerror(errno));
@@ -1351,7 +1351,7 @@
 		return(0);
 
 	/* write the entry */
-	if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) {
+	if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {
 		close(fd);
 		dropbear_log(LOG_WARNING, "lastlog_write_filemode: Error writing to %s: %s",
 		    LASTLOG_FILE, strerror(errno));
--- a/rsa.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/rsa.c	Sat Jun 03 09:45:55 2017 +0800
@@ -346,7 +346,7 @@
 	buf_incrwritepos(buf, ssize);
 	mp_clear(&rsa_s);
 
-#if defined(DEBUG_RSA) && defined(DEBUG_TRACE)
+#if defined(DEBUG_RSA) && DEBUG_TRACE
 	if (!debug_trace) {
 		printhex("RSA sig", buf->data, buf->len);
 	}
--- a/scpmisc.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/scpmisc.c	Sat Jun 03 09:45:55 2017 +0800
@@ -235,7 +235,7 @@
 {
 	int nullfd, dupfd;
 
-	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+	if ((nullfd = dupfd = open(DROPBEAR_PATH_DEVNULL, O_RDWR)) == -1) {
 		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
 		exit(1);
 	}
--- a/scpmisc.h	Fri Sep 16 12:18:23 2016 -0700
+++ b/scpmisc.h	Sat Jun 03 09:45:55 2017 +0800
@@ -12,9 +12,6 @@
  * called by a name other than "ssh" or "Secure Shell".
  */
 
-/* actually from atomicio, but is only used in scp code */
-#define vwrite (ssize_t (*)(int, void *, size_t))write
-
 char	*chop(char *);
 char	*strdelim(char **);
 void	 set_nonblock(int);
--- a/svr-authpubkey.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-authpubkey.c	Sat Jun 03 09:45:55 2017 +0800
@@ -201,6 +201,8 @@
 	unsigned int len, pos;
 	buffer * options_buf = NULL;
 	int line_num;
+	uid_t origuid;
+	gid_t origgid;
 
 	TRACE(("enter checkpubkey"))
 
@@ -227,8 +229,21 @@
 	snprintf(filename, len + 22, "%s/.ssh/authorized_keys", 
 				ses.authstate.pw_dir);
 
-	/* open the file */
+	/* open the file as the authenticating user. */
+	origuid = getuid();
+	origgid = getgid();
+	if ((setegid(ses.authstate.pw_gid)) < 0 ||
+		(seteuid(ses.authstate.pw_uid)) < 0) {
+		dropbear_exit("Failed to set euid");
+	}
+
 	authfile = fopen(filename, "r");
+
+	if ((seteuid(origuid)) < 0 ||
+		(setegid(origgid)) < 0) {
+		dropbear_exit("Failed to revert euid");
+	}
+
 	if (authfile == NULL) {
 		goto out;
 	}
--- a/svr-authpubkeyoptions.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-authpubkeyoptions.c	Sat Jun 03 09:45:55 2017 +0800
@@ -95,6 +95,7 @@
 		if (chansess->cmd) {
 			/* original_command takes ownership */
 			chansess->original_command = chansess->cmd;
+			chansess->cmd = NULL;
 		} else {
 			chansess->original_command = m_strdup("");
 		}
@@ -108,6 +109,9 @@
 /* Free potential public key options */
 void svr_pubkey_options_cleanup() {
 	if (ses.authstate.pubkey_options) {
+		if (ses.authstate.pubkey_options->forced_command) {
+			m_free(ses.authstate.pubkey_options->forced_command);
+		}
 		m_free(ses.authstate.pubkey_options);
 		ses.authstate.pubkey_options = NULL;
 	}
@@ -200,8 +204,7 @@
 
 bad_option:
 	ret = DROPBEAR_FAILURE;
-	m_free(ses.authstate.pubkey_options);
-	ses.authstate.pubkey_options = NULL;
+	svr_pubkey_options_cleanup();
 	dropbear_log(LOG_WARNING, "Bad public key options at %s:%d", filename, line_num);
 
 end:
--- a/svr-chansession.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-chansession.c	Sat Jun 03 09:45:55 2017 +0800
@@ -634,7 +634,7 @@
 static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
 		int iscmd, int issubsys) {
 
-	unsigned int cmdlen;
+	unsigned int cmdlen = 0;
 	int ret;
 
 	TRACE(("enter sessioncommand"))
--- a/svr-kex.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-kex.c	Sat Jun 03 09:45:55 2017 +0800
@@ -93,29 +93,9 @@
 
 #if DROPBEAR_DELAY_HOSTKEY
 
-static void fsync_parent_dir(const char* fn) {
-#ifdef HAVE_LIBGEN_H
-	char *fn_dir = m_strdup(fn);
-	char *dir = dirname(fn_dir);
-	int dirfd = open(dir, O_RDONLY);
-
-	if (dirfd != -1) {
-		if (fsync(dirfd) != 0) {
-			TRACE(("fsync of directory %s failed: %s", dir, strerror(errno)))
-		}
-		m_close(dirfd);
-	} else {
-		TRACE(("error opening directory %s for fsync: %s", dir, strerror(errno)))
-	}
-
-	free(fn_dir);
-#endif
-}
-
 static void svr_ensure_hostkey() {
 
 	const char* fn = NULL;
-	char *fn_temp = NULL;
 	enum signkey_type type = ses.newkeys->algo_hostkey;
 	void **hostkey = signkey_key_ptr(svr_opts.hostkey, type);
 	int ret = DROPBEAR_FAILURE;
@@ -151,28 +131,10 @@
 		return;
 	}
 
-	fn_temp = m_malloc(strlen(fn) + 20);
-	snprintf(fn_temp, strlen(fn)+20, "%s.tmp%d", fn, getpid());
-
-	if (signkey_generate(type, 0, fn_temp) == DROPBEAR_FAILURE) {
+	if (signkey_generate(type, 0, fn, 1) == DROPBEAR_FAILURE) {
 		goto out;
 	}
-
-	if (link(fn_temp, fn) < 0) {
-		/* It's OK to get EEXIST - we probably just lost a race
-		with another connection to generate the key */
-		if (errno != EEXIST) {
-			dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", fn,
-				strerror(errno));
-			/* XXX fallback to non-atomic copy for some filesystems? */
-			goto out;
-		}
-	}
-
-	/* ensure directory update is flushed to disk, otherwise we can end up
-	with zero-byte hostkey files if the power goes off */
-	fsync_parent_dir(fn);
-
+	
 	ret = readhostkey(fn, svr_opts.hostkey, &type);
 
 	if (ret == DROPBEAR_SUCCESS) {
@@ -190,11 +152,6 @@
 	}
 
 out:
-	if (fn_temp) {
-		unlink(fn_temp);
-		m_free(fn_temp);
-	}
-
 	if (ret == DROPBEAR_FAILURE)
 	{
 		dropbear_exit("Couldn't read or generate hostkey %s", fn);
--- a/svr-runopts.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-runopts.c	Sat Jun 03 09:45:55 2017 +0800
@@ -114,7 +114,7 @@
 void svr_getopts(int argc, char ** argv) {
 
 	unsigned int i, j;
-	char ** next = 0;
+	char ** next = NULL;
 	int nextisport = 0;
 	char* recv_window_arg = NULL;
 	char* keepalive_arg = NULL;
@@ -289,7 +289,7 @@
 			if (*next == NULL) {
 				dropbear_exit("Invalid null argument");
 			}
-			next = 0x00;
+			next = NULL;
 
 			if (keyfile) {
 				addhostkey(keyfile);
--- a/svr-session.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-session.c	Sat Jun 03 09:45:55 2017 +0800
@@ -66,7 +66,7 @@
 	{SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation},
 	{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
 #endif
-	{0, 0} /* End */
+	{0, NULL} /* End */
 };
 
 static const struct ChanType *svr_chantypes[] = {
--- a/svr-tcpfwd.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/svr-tcpfwd.c	Sat Jun 03 09:45:55 2017 +0800
@@ -199,7 +199,7 @@
 	}
 	else
 	{
-		tcpinfo->listenaddr = request_addr;
+		tcpinfo->listenaddr = m_strdup(request_addr);
 	}
 
 	ret = listen_tcpfwd(tcpinfo);
--- a/sysoptions.h	Fri Sep 16 12:18:23 2016 -0700
+++ b/sysoptions.h	Sat Jun 03 09:45:55 2017 +0800
@@ -4,7 +4,7 @@
  *******************************************************************/
 
 #ifndef DROPBEAR_VERSION
-#define DROPBEAR_VERSION "2016.74"
+#define DROPBEAR_VERSION "2017.75"
 #endif
 
 #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
--- a/tcp-accept.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/tcp-accept.c	Sat Jun 03 09:45:55 2017 +0800
@@ -55,19 +55,19 @@
 static void tcp_acceptor(struct Listener *listener, int sock) {
 
 	int fd;
-	struct sockaddr_storage addr;
+	struct sockaddr_storage sa;
 	socklen_t len;
 	char ipstring[NI_MAXHOST], portstring[NI_MAXSERV];
 	struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata);
 
-	len = sizeof(addr);
+	len = sizeof(sa);
 
-	fd = accept(sock, (struct sockaddr*)&addr, &len);
+	fd = accept(sock, (struct sockaddr*)&sa, &len);
 	if (fd < 0) {
 		return;
 	}
 
-	if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring),
+	if (getnameinfo((struct sockaddr*)&sa, len, ipstring, sizeof(ipstring),
 				portstring, sizeof(portstring), 
 				NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
 		m_close(fd);
--- a/termcodes.c	Fri Sep 16 12:18:23 2016 -0700
+++ b/termcodes.c	Sat Jun 03 09:45:55 2017 +0800
@@ -34,7 +34,11 @@
 		{VKILL, TERMCODE_CONTROLCHAR},
 		{VEOF, TERMCODE_CONTROLCHAR},
 		{VEOL, TERMCODE_CONTROLCHAR},
+#ifdef VEOL2
 		{VEOL2, TERMCODE_CONTROLCHAR},
+#else
+		{0, 0},
+#endif
 		{VSTART, TERMCODE_CONTROLCHAR},
 		{VSTOP, TERMCODE_CONTROLCHAR},
 		{VSUSP, TERMCODE_CONTROLCHAR},
@@ -51,17 +55,25 @@
 #ifdef AIX
 		{CERASE, TERMCODE_CONTROLCHAR},
 #else
+#ifdef VWERASE
 		{VWERASE, TERMCODE_CONTROLCHAR},
+#else
+		{0, 0},
+#endif
 #endif
+#ifdef VLNEXT
 		{VLNEXT, TERMCODE_CONTROLCHAR},
+#else
+		{0, 0},
+#endif
 #ifdef VFLUSH
 		{VFLUSH, TERMCODE_CONTROLCHAR},
-#else	
+#else
 		{0, 0},
 #endif
 #ifdef VSWTCH
 		{VSWTCH, TERMCODE_CONTROLCHAR},
-#else	
+#else
 		{0, 0},
 #endif
 #ifdef VSTATUS
@@ -135,8 +147,16 @@
 		{NOFLSH, TERMCODE_LOCAL},
 		{TOSTOP, TERMCODE_LOCAL},
 		{IEXTEN, TERMCODE_LOCAL},
+#ifdef ECHOCTL
 		{ECHOCTL, TERMCODE_LOCAL},
+#else
+		{0, 0},
+#endif
+#ifdef ECHOKE
 		{ECHOKE, TERMCODE_LOCAL},
+#else
+		{0, 0},
+#endif
 #ifdef PENDIN
 		{PENDIN, TERMCODE_LOCAL},
 #else