diff --git a/.hgsigs b/.hgsigs
index 5c5eb40498a50296806e8a0d097ff2ba46348a22..79b9f6f472fa6c904776024f12f178ce18967813 100644
--- a/.hgsigs
+++ b/.hgsigs
@@ -4,3 +4,6 @@ aa2f51a6b81d33de5e9898a7f27c792a173d9b26 0 iD8DBQBOuADmjPn4sExkf7wRAv/fAJ9FJFvjD
 9b80981212fe6c01b7c16b3ca7c4e66af56f12f1 0 iEYEABECAAYFAlFLKKcACgkQjPn4sExkf7xK7wCfcioCmJPsysSbQO6+4qZMVe0mmLwAn2/o+wRf4MrUXlohrr7aXEF9vdSB
 095b46180bbc412b029420587736a6185afc17e1 0 iEYEABECAAYFAlFsCnkACgkQjPn4sExkf7xLrwCfeMWjUaSmfU/fvseT5TdrYRqBEVQAoLz5SFLEA40C5f8zE8Ma/vgVJVIC
 f168962bab857ca030829e4cd73d9b32c868c874 0 iEYEABECAAYFAlFwDNwACgkQjPn4sExkf7wJ6QCePVovn/avKXUyNwNBYCcov6JLYqkAnRCPQdkXgv20N3t10r6PRMBBo1/S
+deb211f75ca194e2fcf0d2e5f71c60474e42ec95 0 iEYEABECAAYFAlJO01cACgkQjPn4sExkf7yDqACaA/P+Yl/K2Cv3OC5G0b7ck2Kb75EAoIeW7qpCyclzJLWwk95koED+4lxD
+025237c9f0a1a60a616f984d82fb2a9270d3b0ea 0 iEYEABECAAYFAlJeqDYACgkQjPn4sExkf7y5nQCfW6t+TJySBTTo+gCfDUBPRVxvNe8AoIn/15aWfqH/A2G9uikfoVtWK3pd
+a50a1dc743317fad9b3737bc68fbca640659bb6d 0 iEYEABECAAYFAlJeqL0ACgkQjPn4sExkf7yVqACg6IP0fU29+Feh/TDeemDA+2XAzrIAoIdZfMDvVYlDoWotZD8ACFnf5H1P
diff --git a/.hgtags b/.hgtags
index d3e2f04c157797bd885ba955cbebf9ab7c1b3ed7..7b333934b91d2dc9abb2eb52c5ac2cb2937afc7b 100644
--- a/.hgtags
+++ b/.hgtags
@@ -38,3 +38,5 @@ d7da3b1e15401eb234ec866d5eac992fc4cd5878 t:ltc-0.95-db-merge1
 1b8b2b9d6e94bc3cc5e61b620476ea36cc466e1b DROPBEAR_2013.56
 96b8bcb88017815040949a417caa55686271e8a9 DROPBEAR_2013.57
 e76614145aea67f66e4a4257685c771efba21aa1 DROPBEAR_2013.58
+7b68e581985fd4ea50869f8608ab95cda5d17876 DROPBEAR_2013.59
+a50a1dc743317fad9b3737bc68fbca640659bb6d DROPBEAR_2013.60
diff --git a/CHANGES b/CHANGES
index 65d237bc6723c6b4eb9768c6c016fec6ae834d12..c9a7eda308226fa89c910f6b0bee90654ed44db9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,45 @@
+2013.60 - Wednesday 16 October 2013
+
+- Fix "make install" so that it doesn't always install to /bin and /sbin
+
+- Fix "make install MULTI=1", installing manpages failed
+
+- Fix "make install" when scp is included since it has no manpage
+
+- Make --disable-bundled-libtom work
+
+2013.59 - Friday 4 October 2013
+
+- Fix crash from -J command 
+  Thanks to Lluís Batlle i Rossell and Arnaud Mouiche for patches
+
+- Avoid reading too much from /proc/net/rt_cache since that causes
+  system slowness. 
+
+- Improve EOF handling for half-closed connections
+  Thanks to Catalin Patulea
+
+- Send a banner message to report PAM error messages intended for the user
+  Patch from Martin Donnelly
+
+- Limit the size of decompressed payloads, avoids memory exhaustion denial
+  of service 
+  Thanks to Logan Lamb for reporting and investigating it. CVE-2013-4421
+
+- Avoid disclosing existence of valid users through inconsistent delays
+  Thanks to Logan Lamb for reporting. CVE-2013-4434
+
+- Update config.guess and config.sub for newer architectures
+
+- Avoid segfault in server for locked accounts
+
+- "make install" now installs manpages
+  dropbearkey.8 has been renamed to dropbearkey.1
+  manpage added for dropbearconvert
+
+- Get rid of one second delay when running non-interactive commands
+
+
 2013.58 - Thursday 18 April 2013
 
 - Fix building with Zlib disabled, thanks to Hans Harder and cuma@freetz
@@ -286,7 +328,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
 
 - Security: dbclient previously would prompt to confirm a 
   mismatching hostkey but wouldn't warn loudly. It will now
-  exit upon a mismatch.
+  exit upon a mismatch. CVE-2007-1099
 
 - Compile fixes, make sure that all variable definitions are at the start
   of a scope.
@@ -348,7 +390,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
   (thanks to Tomas Vanek for helping track it down)
 
 - Implement per-IP pre-authentication connection limits 
-  (after some poking from Pablo Fernandez)
+  (after some poking from Pablo Fernandez) CVE-2006-1206
 
 - Exit gracefully if trying to connect to as SSH v1 server 
   (reported by Rushi Lala)
@@ -369,7 +411,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
 - SECURITY: fix for buffer allocation error in server code, could potentially
   allow authenticated users to gain elevated privileges. All multi-user systems
   running the server should upgrade (or apply the patch available on the
-  Dropbear webpage).
+  Dropbear webpage). CVE-2005-4178
 
 - Fix channel handling code so that redirecting to /dev/null doesn't use
   100% CPU.
@@ -576,7 +618,7 @@ https://secure.ucc.asn.au/hg/dropbear/graph/default
 - SECURITY: Don't try to free() uninitialised variables in DSS verification
   code. Thanks to Arne Bernin for pointing out this bug. This is possibly
   exploitable, all users with DSS and pubkey-auth compiled in are advised to
-  upgrade.
+  upgrade. CVE-2004-2486
 
 - Clean up agent forwarding socket files correctly, patch from Gerrit Pape.
 
diff --git a/LICENSE b/LICENSE
index ba11d4fc49f65cf60b8bcad44595825e161ebd49..65af08445f344a3e5c6d63f13531c0aef1ba424d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -8,7 +8,7 @@ The majority of code is written by Matt Johnston, under the license below.
 Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
 same license:
 
-Copyright (c) 2002-2008 Matt Johnston
+Copyright (c) 2002-2013 Matt Johnston
 Portions copyright (c) 2004 Mihnea Stoenescu
 All rights reserved.
 
diff --git a/MULTI b/MULTI
index a50e30eb17f3f7ece30f71bd76841e8550798c9e..606f8150069b073084ef0a83118ac225c3602463 100644
--- a/MULTI
+++ b/MULTI
@@ -20,7 +20,3 @@ etc
 then execute as normal:
 
 ./dropbear <options here>
-
-"make install" doesn't currently work for multi-binary configuration, though
-in most situations where it is being used, the target and build systems will
-differ.
diff --git a/Makefile.in b/Makefile.in
index 4f13d1dca751309e599f55ea9396e2d5520bc6d9..fa88f61d3205e9e6f9bd8759a9ed1ac3347ca5b0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -67,9 +67,11 @@ VPATH=@srcdir@
 srcdir=@srcdir@
 
 prefix=@prefix@
-exec_prefix=${prefix}
-bindir=${exec_prefix}/bin
-sbindir=${exec_prefix}/sbin
+exec_prefix=@exec_prefix@
+datarootdir = @datarootdir@
+bindir=@bindir@
+sbindir=@sbindir@
+mandir=@mandir@
 
 CC=@CC@
 AR=@AR@
@@ -121,36 +123,34 @@ strip: $(TARGETS)
 
 install: $(addprefix inst_, $(TARGETS))
 
-installdropbearmulti: insdbmulti $(addprefix insmulti, $(PROGRAMS)) 
-
-insdbmulti: dropbearmulti
-	$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
-	$(INSTALL) -m 755 dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)
-	-chown root $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
-	-chgrp 0 $(DESTDIR)$(bindir)/dropbearmulti$(EXEEXT)
-
 insmultidropbear: dropbearmulti
-	$(INSTALL) -d -m 755 $(DESTDIR)$(sbindir)
+	$(INSTALL) -d $(DESTDIR)$(sbindir)
 	-rm -f $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
 	-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(sbindir)/dropbear$(EXEEXT) 
+	$(INSTALL) -d $(DESTDIR)$(mandir)/man8
+	$(INSTALL) -m 644 dropbear.8  $(DESTDIR)$(mandir)/man8/dropbear.8
 
 insmulti%: dropbearmulti
-	$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
+	$(INSTALL) -d $(DESTDIR)$(bindir)
 	-rm -f $(DESTDIR)$(bindir)/$*$(EXEEXT) 
 	-ln -s $(bindir)/dropbearmulti$(EXEEXT) $(DESTDIR)$(bindir)/$*$(EXEEXT) 
+	$(INSTALL) -d $(DESTDIR)$(mandir)/man1
+	$(INSTALL) -m 644 $*.1  $(DESTDIR)$(mandir)/man1/$*.1
 
 # dropbear should go in sbin, so it needs a seperate rule
 inst_dropbear: dropbear
-	$(INSTALL) -d -m 755 $(DESTDIR)$(sbindir)
-	$(INSTALL) -m 755 dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
-	-chown root $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
-	-chgrp 0 $(DESTDIR)$(sbindir)/dropbear$(EXEEXT)
+	$(INSTALL) -d $(DESTDIR)$(sbindir)
+	$(INSTALL) dropbear$(EXEEXT) $(DESTDIR)$(sbindir)
+	$(INSTALL) -d $(DESTDIR)$(mandir)/man8
+	$(INSTALL) -m 644 dropbear.8 $(DESTDIR)$(mandir)/man8/dropbear.8
 
 inst_%: $*
-	$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
-	$(INSTALL) -m 755 $*$(EXEEXT) $(DESTDIR)$(bindir)
-	-chown root $(DESTDIR)$(bindir)/$*$(EXEEXT)
-	-chgrp 0 $(DESTDIR)$(bindir)/$*$(EXEEXT)
+	$(INSTALL) -d $(DESTDIR)$(bindir)
+	$(INSTALL) $*$(EXEEXT) $(DESTDIR)$(bindir)
+	$(INSTALL) -d $(DESTDIR)$(mandir)/man1
+	if test -e $*.1; then $(INSTALL) -m 644 $*.1 $(DESTDIR)$(mandir)/man1/$*.1; fi
+
+inst_dropbearmulti: $(addprefix insmulti, $(PROGRAMS)) 
 
 
 # for some reason the rule further down doesn't like $($@objs) as a prereq.
diff --git a/README b/README
index a8ebda337619c063a4c91aab91f1a4ab1331fe54..b5692837f4f539ca8d7584f6424f46f50de71c2b 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is Dropbear, a smallish SSH 2 server and client.
+This is Dropbear, a smallish SSH server and client.
 https://matt.ucc.asn.au/dropbear/dropbear.html
 
 INSTALL has compilation instructions.
diff --git a/auth.h b/auth.h
index df6634e1ce8eeb233555694d22a878fd64417a4c..3aed57bb4626d55199f8828533d9c905d9ba3fbc 100644
--- a/auth.h
+++ b/auth.h
@@ -36,6 +36,7 @@ void cli_authinitialise();
 void recv_msg_userauth_request();
 void send_msg_userauth_failure(int partial, int incrfail);
 void send_msg_userauth_success();
+void send_msg_userauth_banner(buffer *msg);
 void svr_auth_password();
 void svr_auth_pubkey();
 void svr_auth_pam();
diff --git a/cli-chansession.c b/cli-chansession.c
index 37aa13dac380c6560d0431812dfa985afcd19cee..b30fe43033461a177eb669bbee1f1fc0d82910be 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -71,7 +71,9 @@ static void cli_chansessreq(struct Channel *channel) {
 		TRACE(("got exit-signal, ignoring it"))
 	} else {
 		TRACE(("unknown request '%s'", type))
-		send_msg_channel_failure(channel);
+		if (wantreply) {
+			send_msg_channel_failure(channel);
+		}
 		goto out;
 	}
 		
diff --git a/cli-runopts.c b/cli-runopts.c
index 91a2f4217378e9950c493bf00035f114d64e8466..b8d304f1c423d61062a2e85fd1a78d77dfbc7f12 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -383,6 +383,13 @@ void cli_getopts(int argc, char ** argv) {
 		exit(EXIT_FAILURE);
 	}
 
+#ifdef ENABLE_CLI_PROXYCMD                                                                                                                                   
+	if (cli_opts.proxycmd) {
+		/* To match the common path of m_freeing it */
+		cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
+	}
+#endif
+
 	if (cli_opts.remoteport == NULL) {
 		cli_opts.remoteport = "22";
 	}
diff --git a/common-channel.c b/common-channel.c
index 8b7369c06be664235251b67f94650f3fd6cc4eec..206890461b442344ed1a04cb7f82e8e72df3d701 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -307,7 +307,9 @@ static void check_close(struct Channel *channel) {
 		return;
 	}
 
-	if (channel->recv_eof && !write_pending(channel)) {
+	if ((channel->recv_eof && !write_pending(channel))
+		/* have a server "session" and child has exited */
+		|| (channel->type->check_close && close_allowed)) {
 		close_chan_fd(channel, channel->writefd, SHUT_WR);
 	}
 
@@ -336,6 +338,7 @@ static void check_close(struct Channel *channel) {
 
 	/* And if we can't receive any more data from them either, close up */
 	if (channel->readfd == FD_CLOSED
+			&& channel->writefd == FD_CLOSED
 			&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
 			&& !channel->sent_close
 			&& close_allowed
diff --git a/configure.ac b/configure.ac
index 6f824506cf756cdf9f0bc58103475b09bb2bec20..e5bbaf94cd5ed5c519ad68aeba730b594d32786f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,10 +364,20 @@ AC_CHECK_FUNCS(setutxent utmpxname)
 AC_CHECK_FUNCS(logout updwtmp logwtmp)
 
 AC_ARG_ENABLE(bundled-libtom,
-	[  --enable-bundled-libtom       Use bundled libtomcrypt/libtommath even if a system version exists],
-	[ 
-		BUNDLED_LIBTOM=1
-		AC_MSG_NOTICE(Forcing bundled libtom*)
+[  --enable-bundled-libtom       Force using bundled libtomcrypt/libtommath even if a system version exists.
+  --disable-bundled-libtom      Force using system libtomcrypt/libtommath, fail if it does not exist.
+                                Default is to use system if available, otherwise bundled.],
+	[
+		if test "x$enableval" = "xyes"; then
+			BUNDLED_LIBTOM=1
+			AC_MSG_NOTICE(Forcing bundled libtom*)
+		else
+			BUNDLED_LIBTOM=0
+			AC_CHECK_LIB(tomcrypt, register_cipher, , 
+				[AC_MSG_ERROR([Missing system libtomcrypt and --disable-bundled-libtom was specified])] )
+			AC_CHECK_LIB(tommath, mp_exptmod, , 
+				[AC_MSG_ERROR([Missing system libtomcrypt and --disable-bundled-libtom was specified])] )
+		fi
 	],
 	[
 		BUNDLED_LIBTOM=0
diff --git a/dbclient.1 b/dbclient.1
index 7ad550fbf3a9a9adb3dd3df513107466180c8c4b..48399826e874717425ba02e2636ddc513e71f1c3 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -1,6 +1,6 @@
 .TH dbclient 1
 .SH NAME
-dbclient \- lightweight SSH2 client
+dbclient \- lightweight SSH client
 .SH SYNOPSIS
 .B dbclient
 [\-Tt] [\-p
@@ -19,7 +19,7 @@ dbclient \- lightweight SSH2 client
 
 .SH DESCRIPTION
 .B dbclient
-is a SSH 2 client designed to be small enough to be used in small memory
+is a SSH client designed to be small enough to be used in small memory
 environments, while still being functional and secure enough for general use.
 .SH OPTIONS
 .TP
@@ -31,9 +31,10 @@ Default is 22.
 .TP
 .B \-i \fIidfile
 Identity file.
-Read the identity from file
+Read the identity key from file
 .I idfile
-(multiple allowed).
+(multiple allowed). This file is created with dropbearkey(1) or converted
+from OpenSSH with dropbearconvert(1).
 .TP
 .B \-L [\fIlistenaddress\fR]:\fIlistenport\fR:\fIhost\fR:\fIport\fR
 Local port forwarding.
@@ -161,6 +162,6 @@ Mihnea Stoenescu wrote initial Dropbear client support
 .br
 Gerrit Pape (pape@smarden.org) wrote this manual page.
 .SH SEE ALSO
-dropbear(8), dropbearkey(8)
+dropbear(8), dropbearkey(1)
 .P
 https://matt.ucc.asn.au/dropbear/dropbear.html
diff --git a/dbutil.c b/dbutil.c
index bdeb10c32ea314fa6e81c08b036cf5928873ddd3..b194e3da7c071095d73625d88f61eb3d384aa023 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -892,3 +892,16 @@ int m_str_to_uint(const char* str, unsigned int *val) {
 		return DROPBEAR_SUCCESS;
 	}
 }
+
+int constant_time_memcmp(const void* a, const void *b, size_t n)
+{
+	const char *xa = a, *xb = b;
+	uint8_t c = 0;
+	size_t i;
+	for (i = 0; i < n; i++)
+	{
+		c |= (xa[i] ^ xb[i]);
+	}
+	return c;
+}
+
diff --git a/dbutil.h b/dbutil.h
index e13ed131a29e2e0bd5b534c18c507b30270ac962..7c7435c181b705310a8153ed7837ae492c339970 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -95,4 +95,7 @@ int m_str_to_uint(const char* str, unsigned int *val);
 /* Dropbear assertion */
 #define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
 
+/* Returns 0 if a and b have the same contents */
+int constant_time_memcmp(const void* a, const void *b, size_t n);
+
 #endif /* _DBUTIL_H_ */
diff --git a/debian/changelog b/debian/changelog
index d6aeeb84d7b908b022f24107eb11bf6915f92d4a..cc869f57b3f2bb7b0c7c6eb670789be9a7c7ec3c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+dropbear (2013.60-0.1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Matt Johnston <matt@ucc.asn.au>  Wed, 16 Oct 2013 22:54:00 +0800
+
+dropbear (2013.59-0.1) unstable; urgency=low
+
+  * New upstream release.
+  * Build with DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+ -- Matt Johnston <matt@ucc.asn.au>  Fri, 4 Oct 2013 22:54:00 +0800
+
 dropbear (2013.58-0.1) unstable; urgency=low
 
   * New upstream release.
diff --git a/debian/rules b/debian/rules
index 605754e089b35e0d33c467ebbb3a9c2e9fad2316..c6b2e857f258c1f1b81cb8c7181343388f8a8e35 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,5 +1,9 @@
 #!/usr/bin/make -f
 
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/buildflags.mk
+
 #export DH_OPTIONS
 DEB_HOST_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
 DEB_BUILD_GNU_TYPE ?=$(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
@@ -9,13 +13,6 @@ ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
   STRIP =: nostrip
 endif
 
-CFLAGS =-Wall -g
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-  CFLAGS +=-O0
-else
-  CFLAGS +=-O2
-endif
-
 CONFFLAGS =
 CC =gcc
 ifneq (,$(findstring diet,$(DEB_BUILD_OPTIONS)))
@@ -79,12 +76,12 @@ install: deb-checkdir deb-checkuid build-stamp
 	ln -s /var/log/dropbear '$(DIR)'/etc/dropbear/log/main
 	# man pages
 	install -d -m0755 '$(DIR)'/usr/share/man/man8
-	for i in dropbear.8 dropbearkey.8; do \
-	  install -m644 $$i '$(DIR)'/usr/share/man/man8/ || exit 1; \
+	install -d -m0755 '$(DIR)'/usr/share/man/man1
+	install -m644 dropbear.8 '$(DIR)'/usr/share/man/man8/
+	for i in dbclient.1 dropbearkey.1 dropbearconvert.1; do \
+	  install -m644 $$i '$(DIR)'/usr/share/man/man1/ || exit 1; \
 	done
 	gzip -9 '$(DIR)'/usr/share/man/man8/*.8
-	install -d -m0755 '$(DIR)'/usr/share/man/man1
-	install -m644 dbclient.1 '$(DIR)'/usr/share/man/man1/
 	gzip -9 '$(DIR)'/usr/share/man/man1/*.1
 	# copyright, changelog
 	cat debian/copyright.in LICENSE >debian/copyright
diff --git a/dropbear.8 b/dropbear.8
index cdcfb0b522c2be2424a8ce9e1cc841dfcfaed409..f1ad5769c8486bec3dd1f04f670f4044bb3c1fc3 100644
--- a/dropbear.8
+++ b/dropbear.8
@@ -1,6 +1,6 @@
 .TH dropbear 8
 .SH NAME
-dropbear \- lightweight SSH2 server
+dropbear \- lightweight SSH server
 .SH SYNOPSIS
 .B dropbear
 [\-FEmwsgjki] [\-b
@@ -10,7 +10,7 @@ dropbear \- lightweight SSH2 server
 .IR [address:]port ]
 .SH DESCRIPTION
 .B dropbear
-is a SSH 2 server designed to be small enough to be used in small memory
+is a SSH server designed to be small enough to be used in small memory
 environments, while still being functional and secure enough for general use.
 .SH OPTIONS
 .TP
@@ -29,7 +29,7 @@ Note that
 some SSH implementations
 use the term "DSA" rather than "DSS", they mean the same thing.
 This file is generated with
-.BR dropbearkey (8).
+.BR dropbearkey (1).
 .TP
 .B \-r \fIrsakey
 rsakeyfile.
@@ -37,7 +37,7 @@ Use the contents of the file
 .I rsakey
 for the rsa host key (default: /etc/dropbear/dropbear_rsa_host_key).
 This file is generated with
-.BR dropbearkey (8).
+.BR dropbearkey (1).
 .TP
 .B \-F
 Don't fork into background.
@@ -180,13 +180,14 @@ in this variable. If a shell was requested this is set to an empty value.
 .B SSH_AUTH_SOCK
 Set to a forwarded ssh-agent connection.
 
-
+.SH NOTES
+Dropbear only supports SSH protocol version 2.
 
 .SH AUTHOR
 Matt Johnston (matt@ucc.asn.au).
 .br
 Gerrit Pape (pape@smarden.org) wrote this manual page.
 .SH SEE ALSO
-dropbearkey(8), dbclient(1)
+dropbearkey(1), dbclient(1), dropbearconvert(1)
 .P
 https://matt.ucc.asn.au/dropbear/dropbear.html
diff --git a/dropbearconvert.1 b/dropbearconvert.1
new file mode 100644
index 0000000000000000000000000000000000000000..4643f5f96c18e2dfb0dcca285d6d8da42d29a1ce
--- /dev/null
+++ b/dropbearconvert.1
@@ -0,0 +1,50 @@
+.TH dropbearconvert 1
+.SH NAME
+dropbearconvert \- convert between Dropbear and OpenSSH private key formats
+.SH SYNOPSIS
+.B dropbearconvert
+.I input_type
+.I output_type
+.I input_file
+.I output_file
+.SH DESCRIPTION
+.B Dropbear
+and 
+.B OpenSSH
+SSH implementations have different private key formats.
+.B dropbearconvert
+can convert between the two.
+.P
+Dropbear uses the same SSH public key format as OpenSSH, it can be extracted
+from a private key by using
+.B dropbearkey \-y
+.P
+Encrypted private keys are not supported, use ssh-keygen(1) to decrypt them
+first.
+.SH OPTIONS
+.TP
+.B input type
+Either 
+.I dropbear
+or 
+.I openssh
+.TP
+.B output type
+Either 
+.I dropbear
+or 
+.I openssh
+.TP
+.B input file
+An existing Dropbear or OpenSSH private key file
+.TP
+.B output file
+The path to write the converted private key file
+.SH EXAMPLE
+ # dropbearconvert openssh dropbear ~/.ssh/id_rsa ~/.ssh/dropbear_priv
+.SH AUTHOR
+Matt Johnston (matt@ucc.asn.au).
+.SH SEE ALSO
+ dropbearkey(1), ssh-keygen(1)
+.P
+https://matt.ucc.asn.au/dropbear/dropbear.html
diff --git a/dropbearkey.8 b/dropbearkey.1
similarity index 71%
rename from dropbearkey.8
rename to dropbearkey.1
index 953e02a6cf1937e084c8812b9cee594f789f73bd..945d4dad209a9959126f7059219afd8727537806 100644
--- a/dropbearkey.8
+++ b/dropbearkey.1
@@ -1,6 +1,6 @@
-.TH dropbearkey 8
+.TH dropbearkey 1
 .SH NAME
-dropbearkey \- create private keys for the use with dropbear(8)
+dropbearkey \- create private keys for the use with dropbear(8) or dbclient(1)
 .SH SYNOPSIS
 .B dropbearkey
 \-t
@@ -16,8 +16,7 @@ generates a
 or
 .I DSS
 format SSH private key, and saves it to a file for the use with the
-.BR dropbear (8)
-SSH 2 server.
+Dropbear client or server.
 Note that 
 some SSH implementations
 use the term "DSA" rather than "DSS", they mean the same thing.
@@ -38,6 +37,10 @@ Write the secret key to the file
 Set the key size to
 .I bits
 bits, should be multiple of 8 (optional).
+.SH NOTES
+The program dropbearconvert(1) can be used to convert between Dropbear and OpenSSH key formats.
+.P
+Dropbear does not support encrypted keys. 
 .SH EXAMPLE
  # dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
 .SH AUTHOR
@@ -45,6 +48,6 @@ Matt Johnston (matt@ucc.asn.au).
 .br
 Gerrit Pape (pape@smarden.org) wrote this manual page.
 .SH SEE ALSO
-dropbear(8), dbclient(1)
+dropbear(8), dbclient(1), dropbearconvert(1)
 .P
 https://matt.ucc.asn.au/dropbear/dropbear.html
diff --git a/packet.c b/packet.c
index d458ccf791c4fdee369a2af312b5e3ca67bc9dfe..4ebd0d716860b74cc282c463e5709b8074298eab 100644
--- a/packet.c
+++ b/packet.c
@@ -376,7 +376,7 @@ static int checkmac() {
 
 	/* compare the hash */
 	buf_setpos(ses.readbuf, contents_len);
-	if (memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
+	if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
 		return DROPBEAR_FAILURE;
 	} else {
 		return DROPBEAR_SUCCESS;
diff --git a/random.c b/random.c
index 17e3086ab475d7f7a7a16c5a33cca70605a243f9..88c832798c06de622b694b16371ec2f5e8620e5e 100644
--- a/random.c
+++ b/random.c
@@ -78,7 +78,7 @@ process_file(hash_state *hs, const char *filename,
 	while (len == 0 || readcount < len)
 	{
 		int readlen, wantread;
-		unsigned char readbuf[2048];
+		unsigned char readbuf[4096];
 		if (!already_blocked)
 		{
 			int ret;
@@ -209,12 +209,13 @@ void seedrandom() {
 	process_file(&hs, "/proc/loadavg", 0, 0);
 	process_file(&hs, "/proc/sys/kernel/random/entropy_avail", 0, 0);
 
-	/* Mostly network visible but useful in some situations */
-	process_file(&hs, "/proc/net/netstat", 0, 0);
-	process_file(&hs, "/proc/net/dev", 0, 0);
-	process_file(&hs, "/proc/net/tcp", 0, 0);
+	/* Mostly network visible but useful in some situations.
+	 * Limit size to avoid slowdowns on systems with lots of routes */
+	process_file(&hs, "/proc/net/netstat", 4096, 0);
+	process_file(&hs, "/proc/net/dev", 4096, 0);
+	process_file(&hs, "/proc/net/tcp", 4096, 0);
 	/* Also includes interface lo */
-	process_file(&hs, "/proc/net/rt_cache", 0, 0);
+	process_file(&hs, "/proc/net/rt_cache", 4096, 0);
 	process_file(&hs, "/proc/vmstat", 0, 0);
 #endif
 
diff --git a/svr-auth.c b/svr-auth.c
index acac6f88433d0934309aeed1e6be7d3644ed5e2b..86661086c80221c0a81fe44dd1c2dd8fb22206d5 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -37,7 +37,6 @@
 
 static void authclear();
 static int checkusername(unsigned char *username, unsigned int userlen);
-static void send_msg_userauth_banner();
 
 /* initialise the first time for a session, resetting all parameters */
 void svr_authinitialise() {
@@ -82,23 +81,17 @@ static void authclear() {
 
 /* Send a banner message if specified to the client. The client might
  * ignore this, but possibly serves as a legal "no trespassing" sign */
-static void send_msg_userauth_banner() {
+void send_msg_userauth_banner(buffer *banner) {
 
 	TRACE(("enter send_msg_userauth_banner"))
-	if (svr_opts.banner == NULL) {
-		TRACE(("leave send_msg_userauth_banner: banner is NULL"))
-		return;
-	}
 
 	CHECKCLEARTOWRITE();
 
 	buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_BANNER);
-	buf_putbufstring(ses.writepayload, svr_opts.banner);
+	buf_putbufstring(ses.writepayload, banner);
 	buf_putstring(ses.writepayload, "en", 2);
 
 	encrypt_packet();
-	buf_free(svr_opts.banner);
-	svr_opts.banner = NULL;
 
 	TRACE(("leave send_msg_userauth_banner"))
 }
@@ -109,6 +102,7 @@ void recv_msg_userauth_request() {
 
 	unsigned char *username = NULL, *servicename = NULL, *methodname = NULL;
 	unsigned int userlen, servicelen, methodlen;
+	int valid_user = 0;
 
 	TRACE(("enter recv_msg_userauth_request"))
 
@@ -120,10 +114,11 @@ void recv_msg_userauth_request() {
 
 	/* send the banner if it exists, it will only exist once */
 	if (svr_opts.banner) {
-		send_msg_userauth_banner();
+		send_msg_userauth_banner(svr_opts.banner);
+		buf_free(svr_opts.banner);
+		svr_opts.banner = NULL;
 	}
 
-	
 	username = buf_getstring(ses.payload, &userlen);
 	servicename = buf_getstring(ses.payload, &servicelen);
 	methodname = buf_getstring(ses.payload, &methodlen);
@@ -140,12 +135,12 @@ void recv_msg_userauth_request() {
 		dropbear_exit("unknown service in auth");
 	}
 
-	/* check username is good before continuing */
-	if (checkusername(username, userlen) == DROPBEAR_FAILURE) {
-		/* username is invalid/no shell/etc - send failure */
-		TRACE(("sending checkusername failure"))
-		send_msg_userauth_failure(0, 1);
-		goto out;
+	/* check username is good before continuing. 
+	 * the 'incrfail' varies depending on the auth method to
+	 * avoid giving away which users exist on the system through
+	 * the time delay. */
+	if (checkusername(username, userlen) == DROPBEAR_SUCCESS) {
+		valid_user = 1;
 	}
 
 	/* user wants to know what methods are supported */
@@ -153,7 +148,8 @@ void recv_msg_userauth_request() {
 			strncmp(methodname, AUTH_METHOD_NONE,
 				AUTH_METHOD_NONE_LEN) == 0) {
 		TRACE(("recv_msg_userauth_request: 'none' request"))
-		if (svr_opts.allowblankpass
+		if (valid_user
+				&& svr_opts.allowblankpass
 				&& !svr_opts.noauthpass
 				&& !(svr_opts.norootpass && ses.authstate.pw_uid == 0) 
 				&& ses.authstate.pw_passwd[0] == '\0') 
@@ -167,6 +163,7 @@ void recv_msg_userauth_request() {
 		}
 		else
 		{
+			/* 'none' has no failure delay */
 			send_msg_userauth_failure(0, 0);
 			goto out;
 		}
@@ -179,8 +176,10 @@ void recv_msg_userauth_request() {
 		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
 				strncmp(methodname, AUTH_METHOD_PASSWORD,
 					AUTH_METHOD_PASSWORD_LEN) == 0) {
-			svr_auth_password();
-			goto out;
+			if (valid_user) {
+				svr_auth_password();
+				goto out;
+			}
 		}
 	}
 #endif
@@ -192,8 +191,10 @@ void recv_msg_userauth_request() {
 		if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
 				strncmp(methodname, AUTH_METHOD_PASSWORD,
 					AUTH_METHOD_PASSWORD_LEN) == 0) {
-			svr_auth_pam();
-			goto out;
+			if (valid_user) {
+				svr_auth_pam();
+				goto out;
+			}
 		}
 	}
 #endif
@@ -203,12 +204,17 @@ void recv_msg_userauth_request() {
 	if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
 			strncmp(methodname, AUTH_METHOD_PUBKEY,
 				AUTH_METHOD_PUBKEY_LEN) == 0) {
-		svr_auth_pubkey();
+		if (valid_user) {
+			svr_auth_pubkey();
+		} else {
+			/* pubkey has no failure delay */
+			send_msg_userauth_failure(0, 0);
+		}
 		goto out;
 	}
 #endif
 
-	/* nothing matched, we just fail */
+	/* nothing matched, we just fail with a delay */
 	send_msg_userauth_failure(0, 1);
 
 out:
@@ -251,7 +257,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
 		dropbear_log(LOG_WARNING,
 				"Login attempt for nonexistent user from %s",
 				svr_ses.addrstring);
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -263,7 +268,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
 				"Login attempt with wrong user %s from %s",
 				ses.authstate.pw_name,
 				svr_ses.addrstring);
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -271,7 +275,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
 	if (svr_opts.norootlogin && ses.authstate.pw_uid == 0) {
 		TRACE(("leave checkusername: root login disabled"))
 		dropbear_log(LOG_WARNING, "root login rejected");
-		send_msg_userauth_failure(0, 1);
 		return DROPBEAR_FAILURE;
 	}
 
@@ -300,7 +303,6 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
 	TRACE(("no matching shell"))
 	dropbear_log(LOG_WARNING, "User '%s' has invalid shell, rejected",
 				ses.authstate.pw_name);
-	send_msg_userauth_failure(0, 1);
 	return DROPBEAR_FAILURE;
 	
 goodshell:
@@ -310,7 +312,6 @@ goodshell:
 	TRACE(("uid = %d", ses.authstate.pw_uid))
 	TRACE(("leave checkusername"))
 	return DROPBEAR_SUCCESS;
-
 }
 
 /* Send a failure message to the client, in responds to a userauth_request.
@@ -355,8 +356,8 @@ void send_msg_userauth_failure(int partial, int incrfail) {
 	if (incrfail) {
 		unsigned int delay;
 		genrandom((unsigned char*)&delay, sizeof(delay));
-		/* We delay for 300ms +- 50ms, 0.1ms granularity */
-		delay = 250000 + (delay % 1000)*100;
+		/* We delay for 300ms +- 50ms */
+		delay = 250000 + (delay % 100000);
 		usleep(delay);
 		ses.authstate.failcount++;
 	}
diff --git a/svr-authpam.c b/svr-authpam.c
index e84f076d17e3d572588970790baaa61f5a388f9d..0b1d69fcd884982e093203a5fc78e29c8b8a8c54 100644
--- a/svr-authpam.c
+++ b/svr-authpam.c
@@ -142,6 +142,22 @@ pamConvFunc(int num_msg,
 			(*respp) = resp;
 			break;
 
+		case PAM_ERROR_MSG:
+		case PAM_TEXT_INFO:
+
+			if (msg_len > 0) {
+				buffer * pam_err = buf_new(msg_len + 4);
+				buf_setpos(pam_err, 0);
+				buf_putbytes(pam_err, "\r\n", 2);
+				buf_putbytes(pam_err, (*msg)->msg, msg_len);
+				buf_putbytes(pam_err, "\r\n", 2);
+				buf_setpos(pam_err, 0);
+
+				send_msg_userauth_banner(pam_err);
+				buf_free(pam_err);
+			}
+			break;
+
 		default:
 			TRACE(("Unknown message type"))
 			rc = PAM_CONV_ERR;
@@ -196,14 +212,14 @@ void svr_auth_pam() {
 
 	/* Init pam */
 	if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) {
-		dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s\n", 
+		dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s", 
 				rc, pam_strerror(pamHandlep, rc));
 		goto cleanup;
 	}
 
 	/* just to set it to something */
 	if ((rc = pam_set_item(pamHandlep, PAM_TTY, "ssh") != PAM_SUCCESS)) {
-		dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s\n", 
+		dropbear_log(LOG_WARNING, "pam_set_item() failed, rc=%d, %s",
 				rc, pam_strerror(pamHandlep, rc));
 		goto cleanup;
 	}
@@ -216,7 +232,7 @@ void svr_auth_pam() {
 	/* (void) pam_set_item(pamHandlep, PAM_FAIL_DELAY, (void*) pamDelayFunc); */
 
 	if ((rc = pam_authenticate(pamHandlep, 0)) != PAM_SUCCESS) {
-		dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s\n", 
+		dropbear_log(LOG_WARNING, "pam_authenticate() failed, rc=%d, %s", 
 				rc, pam_strerror(pamHandlep, rc));
 		dropbear_log(LOG_WARNING,
 				"Bad PAM password attempt for '%s' from %s",
@@ -227,7 +243,7 @@ void svr_auth_pam() {
 	}
 
 	if ((rc = pam_acct_mgmt(pamHandlep, 0)) != PAM_SUCCESS) {
-		dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s\n", 
+		dropbear_log(LOG_WARNING, "pam_acct_mgmt() failed, rc=%d, %s", 
 				rc, pam_strerror(pamHandlep, rc));
 		dropbear_log(LOG_WARNING,
 				"Bad PAM password attempt for '%s' from %s",
diff --git a/svr-authpasswd.c b/svr-authpasswd.c
index 17dd2a1b166b935feb230449d069b4af474f3f01..7a5a1210235d62fd06bbac94e10d18da57bbf35c 100644
--- a/svr-authpasswd.c
+++ b/svr-authpasswd.c
@@ -33,6 +33,17 @@
 
 #ifdef ENABLE_SVR_PASSWORD_AUTH
 
+static int constant_time_strcmp(const char* a, const char* b) {
+	size_t la = strlen(a);
+	size_t lb = strlen(b);
+
+	if (la != lb) {
+		return 1;
+	}
+
+	return constant_time_memcmp(a, b, la);
+}
+
 /* Process a password auth request, sending success or failure messages as
  * appropriate */
 void svr_auth_password() {
@@ -82,7 +93,7 @@ void svr_auth_password() {
 		return;
 	}
 
-	if (strcmp(testcrypt, passwdcrypt) == 0) {
+	if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
 		/* successful authentication */
 		dropbear_log(LOG_NOTICE, 
 				"Password auth succeeded for '%s' from %s",
diff --git a/svr-chansession.c b/svr-chansession.c
index 88a4b85fea19af1e8dad6838914a152132fe6fce..5dd5540b5002ad05eb6078e178aa6d91d57ff0c6 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -699,8 +699,6 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
 	ses.maxfd = MAX(ses.maxfd, channel->readfd);
 	ses.maxfd = MAX(ses.maxfd, channel->errfd);
 
-	sleep(1);
-
 	addchildpid(chansess, chansess->pid);
 
 	if (svr_ses.lastexit.exitpid != -1) {
diff --git a/sysoptions.h b/sysoptions.h
index c36ab8bd381f03213b8673cd5cf74e54a342b30f..21b153bac0d398f70d93b2cdac1916fc6b71a307 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -4,7 +4,7 @@
  *******************************************************************/
 
 #ifndef DROPBEAR_VERSION
-#define DROPBEAR_VERSION "2013.58"
+#define DROPBEAR_VERSION "2013.60"
 #endif
 
 #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION