diff options
-rw-r--r-- | .gitignore | 21 | ||||
-rw-r--r-- | .hgsigs | 1 | ||||
-rw-r--r-- | .hgtags | 1 | ||||
-rw-r--r-- | CHANGES | 27 | ||||
-rw-r--r-- | atomicio.c | 29 | ||||
-rw-r--r-- | atomicio.h | 13 | ||||
-rw-r--r-- | buffer.c | 1 | ||||
-rw-r--r-- | cli-agentfwd.c | 2 | ||||
-rw-r--r-- | cli-runopts.c | 2 | ||||
-rw-r--r-- | cli-session.c | 4 | ||||
-rw-r--r-- | cli-tcpfwd.c | 4 | ||||
-rw-r--r-- | common-channel.c | 1 | ||||
-rw-r--r-- | common-kex.c | 2 | ||||
-rw-r--r-- | compat.c | 19 | ||||
-rw-r--r-- | configure.ac | 82 | ||||
-rw-r--r-- | dbrandom.c | 6 | ||||
-rw-r--r-- | dbutil.c | 17 | ||||
-rw-r--r-- | dbutil.h | 2 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | dropbearkey.c | 4 | ||||
-rw-r--r-- | gensignkey.c | 39 | ||||
-rw-r--r-- | gensignkey.h | 2 | ||||
-rw-r--r-- | keyimport.c | 10 | ||||
-rw-r--r-- | libtommath/bn_mp_exteuclid.c | 33 | ||||
-rw-r--r-- | loginrec.c | 8 | ||||
-rw-r--r-- | rsa.c | 2 | ||||
-rw-r--r-- | scpmisc.c | 2 | ||||
-rw-r--r-- | scpmisc.h | 3 | ||||
-rw-r--r-- | svr-authpubkey.c | 17 | ||||
-rw-r--r-- | svr-authpubkeyoptions.c | 7 | ||||
-rw-r--r-- | svr-chansession.c | 2 | ||||
-rw-r--r-- | svr-kex.c | 47 | ||||
-rw-r--r-- | svr-runopts.c | 4 | ||||
-rw-r--r-- | svr-session.c | 2 | ||||
-rw-r--r-- | svr-tcpfwd.c | 2 | ||||
-rw-r--r-- | sysoptions.h | 2 | ||||
-rw-r--r-- | tcp-accept.c | 8 | ||||
-rw-r--r-- | termcodes.c | 24 |
38 files changed, 287 insertions, 171 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b81c1ea --- /dev/null +++ b/.gitignore @@ -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 @@ -22,3 +22,4 @@ af074dbcb68ff8670b3818e0d66d5dc6f1bd5877 0 iQIcBAABCgAGBQJWVdQfAAoJEPSYMBLCC7qs+ fd1981f41c626a969f07b4823848deaefef3c8aa 0 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 @@ -54,3 +54,4 @@ cbd674d63cd4f3781464a8d4056a5506c8ae926f DROPBEAR_2015.67 78b12b6549be08b0bea3da329b2578060a76ca31 DROPBEAR_2016.72 309e1c4a87682b6ca7d80b8555a1db416c3cb7ac DROPBEAR_2016.73 0ed3d2bbf956cb8a9bf0f4b5a86b7dd9688205cb DROPBEAR_2016.74 +c31276613181c5cff7854e7ef586ace03424e55e DROPBEAR_2017.75 @@ -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. @@ -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; - ssize_t res; size_t pos = 0; + ssize_t res; 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); @@ -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==write + * Ensure all of data on socket comes through. f==read || f==vwrite */ -ssize_t atomicio(ssize_t (*)(), int, void *, size_t); +size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); + +#define vwrite (ssize_t (*)(int, void *, size_t))write @@ -109,6 +109,7 @@ void buf_setlen(buffer* buf, unsigned int len) { dropbear_exit("Bad buf_setlen"); } buf->len = len; + buf->pos = MIN(buf->pos, buf->len); } /* Increment the length of the buffer */ diff --git a/cli-agentfwd.c b/cli-agentfwd.c index 5b0ea81..bdca3ea 100644 --- a/cli-agentfwd.c +++ b/cli-agentfwd.c @@ -130,7 +130,7 @@ static buffer * agent_request(unsigned char type, buffer *data) { } 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; diff --git a/cli-runopts.c b/cli-runopts.c index 4a89ba3..ca50709 100644 --- a/cli-runopts.c +++ b/cli-runopts.c @@ -106,7 +106,7 @@ static void printhelp() { 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 diff --git a/cli-session.c b/cli-session.c index d89416f..f1115d6 100644 --- a/cli-session.c +++ b/cli-session.c @@ -81,7 +81,7 @@ static const packettype cli_packettypes[] = { {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 @@ static void cli_sessionloop() { 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)); diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c index 95b2d7c..78f61f7 100644 --- a/cli-tcpfwd.c +++ b/cli-tcpfwd.c @@ -234,7 +234,7 @@ static int newtcpforwarded(struct Channel * channel) { 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 @@ static int newtcpforwarded(struct Channel * channel) { } - 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\"", diff --git a/common-channel.c b/common-channel.c index 835e493..7383f47 100644 --- a/common-channel.c +++ b/common-channel.c @@ -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" diff --git a/common-kex.c b/common-kex.c index 072b6fb..d60b9ea 100644 --- a/common-kex.c +++ b/common-kex.c @@ -774,7 +774,7 @@ static void finish_kexhashbuf(void) { 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); @@ -114,8 +114,8 @@ size_t strlcpy(char *dst, const char *src, size_t size) { #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 @@ size_t strlcpy(char *dst, const char *src, size_t size) { * 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 @@ int daemon(int nochdir, int noclose) { 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); diff --git a/configure.ac b/configure.ac index 551bc2c..767bd05 100644 --- a/configure.ac +++ b/configure.ac @@ -45,8 +45,8 @@ case "$host" in 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 @@ case "$host" in ;; *-*-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 @@ AC_CHECK_DECL(__UCLIBC__, [ 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 @@ AC_ARG_ENABLE(zlib, [ --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_ARG_ENABLE(pam, 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_ARG_ENABLE(openpty, 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 @@ AC_ARG_ENABLE(syslog, [ --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 @@ AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [ ) ]) 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 @@ AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [ ) ]) 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 @@ AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ ) ]) 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 @@ AC_ARG_ENABLE(bundled-libtom, ) 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 Added from OpenSSH 3.6.1p2's configure.ac 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 @@ AC_ARG_WITH(lastlog, 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 @@ AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME)) 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 @@ fi 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]) @@ -59,7 +59,7 @@ process_file(hash_state *hs, const char *filename, 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 @@ process_file(hash_state *hs, const char *filename, wantread = MIN(sizeof(readbuf), len-readcount); } -#if DROPBEAR_PRNGD_SOCKET +#ifdef DROPBEAR_PRNGD_SOCKET if (prngd) { char egdcmd[2]; @@ -185,7 +185,7 @@ void seedrandom() { /* 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", @@ -681,4 +681,21 @@ time_t monotonic_now() { 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 +} @@ -89,4 +89,6 @@ time_t monotonic_now(void); char * expand_homedir_path(const char *inpath); +void fsync_parent_dir(const char* fn); + #endif /* DROPBEAR_DBUTIL_H_ */ diff --git a/debian/changelog b/debian/changelog index 87edb50..037805f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +dropbear (2017.75-0.1) unstable; urgency=low + + * New upstream release. + + -- Matt Johnston <matt@ucc.asn.au> Thu, 18 May 2017 22:51:57 +0800 + dropbear (2016.74-0.1) unstable; urgency=low * New upstream release. diff --git a/dropbearkey.c b/dropbearkey.c index 6ea68b4..5cb12ef 100644 --- a/dropbearkey.c +++ b/dropbearkey.c @@ -134,7 +134,7 @@ int main(int argc, char ** argv) { #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 @@ int main(int argc, char ** argv) { } 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"); } diff --git a/gensignkey.c b/gensignkey.c index 55facc3..4691de0 100644 --- a/gensignkey.c +++ b/gensignkey.c @@ -76,10 +76,12 @@ static int get_default_bits(enum signkey_type keytype) } } -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 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename) sign_key_free(key); key = NULL; buf_setpos(buf, 0); - ret = buf_writefile(buf, filename); - buf_burn(buf); - buf_free(buf); - buf = NULL; + 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; + } + + 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; } diff --git a/gensignkey.h b/gensignkey.h index 508eca0..1cba8d3 100644 --- a/gensignkey.h +++ b/gensignkey.h @@ -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 diff --git a/keyimport.c b/keyimport.c index d64a6f7..6aab273 100644 --- a/keyimport.c +++ b/keyimport.c @@ -694,7 +694,7 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) &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 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) &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 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) &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 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) &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 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) &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; diff --git a/libtommath/bn_mp_exteuclid.c b/libtommath/bn_mp_exteuclid.c index 25ccba9..f4f1c7b 100644 --- a/libtommath/bn_mp_exteuclid.c +++ b/libtommath/bn_mp_exteuclid.c @@ -29,34 +29,34 @@ int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) /* 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 @@ int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) 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 @@ -706,7 +706,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) } (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 @@ wtmp_write(struct logininfo *li, struct utmp *ut) 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 @@ wtmpx_write(struct logininfo *li, struct utmpx *utx) } 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 @@ lastlog_perform_login(struct logininfo *li) 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)); @@ -346,7 +346,7 @@ void buf_put_rsa_sign(buffer* buf, dropbear_rsa_key *key, buffer *data_buf) { 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); } @@ -235,7 +235,7 @@ sanitise_stdfd(void) { 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); } @@ -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); diff --git a/svr-authpubkey.c b/svr-authpubkey.c index 90d0d2c..acc660d 100644 --- a/svr-authpubkey.c +++ b/svr-authpubkey.c @@ -201,6 +201,8 @@ static int checkpubkey(char* algo, unsigned int algolen, unsigned int len, pos; buffer * options_buf = NULL; int line_num; + uid_t origuid; + gid_t origgid; TRACE(("enter checkpubkey")) @@ -227,8 +229,21 @@ static int checkpubkey(char* algo, unsigned int algolen, 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; } diff --git a/svr-authpubkeyoptions.c b/svr-authpubkeyoptions.c index a04426e..d08fc2c 100644 --- a/svr-authpubkeyoptions.c +++ b/svr-authpubkeyoptions.c @@ -95,6 +95,7 @@ void svr_pubkey_set_forced_command(struct ChanSess *chansess) { 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 @@ void svr_pubkey_set_forced_command(struct ChanSess *chansess) { /* 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 @@ next_option: 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: diff --git a/svr-chansession.c b/svr-chansession.c index 6dbc8ad..22fc954 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -634,7 +634,7 @@ static void make_connection_string(struct ChanSess *chansess) { 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")) @@ -93,29 +93,9 @@ void recv_msg_kexdh_init() { #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 @@ static void svr_ensure_hostkey() { 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 @@ static void svr_ensure_hostkey() { } 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); diff --git a/svr-runopts.c b/svr-runopts.c index e6dc8a8..dea4a55 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -114,7 +114,7 @@ static void printhelp(const char * progname) { 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 @@ void svr_getopts(int argc, char ** argv) { if (*next == NULL) { dropbear_exit("Invalid null argument"); } - next = 0x00; + next = NULL; if (keyfile) { addhostkey(keyfile); diff --git a/svr-session.c b/svr-session.c index febe79a..297d07f 100644 --- a/svr-session.c +++ b/svr-session.c @@ -66,7 +66,7 @@ static const packettype svr_packettypes[] = { {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[] = { diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c index e5b6d46..207587c 100644 --- a/svr-tcpfwd.c +++ b/svr-tcpfwd.c @@ -199,7 +199,7 @@ static int svr_remotetcpreq() { } else { - tcpinfo->listenaddr = request_addr; + tcpinfo->listenaddr = m_strdup(request_addr); } ret = listen_tcpfwd(tcpinfo); diff --git a/sysoptions.h b/sysoptions.h index 1f357e7..441e3a1 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -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 diff --git a/tcp-accept.c b/tcp-accept.c index 04fa25f..82f4a86 100644 --- a/tcp-accept.c +++ b/tcp-accept.c @@ -55,19 +55,19 @@ int tcp_prio_inithandler(struct Channel* channel) 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); diff --git a/termcodes.c b/termcodes.c index 490e6ce..c5819c1 100644 --- a/termcodes.c +++ b/termcodes.c @@ -34,7 +34,11 @@ const struct TermCode termcodes[MAX_TERMCODE+1] = { {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 @@ const struct TermCode termcodes[MAX_TERMCODE+1] = { #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 @@ const struct TermCode termcodes[MAX_TERMCODE+1] = { {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 |