Dmitry Belyavskiy 6f7478
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
Dmitry Belyavskiy 6f7478
index d29a03b4..d7283136 100644
Dmitry Belyavskiy 6f7478
--- a/ssh-keyscan.c
Dmitry Belyavskiy 6f7478
+++ b/ssh-keyscan.c
Dmitry Belyavskiy 6f7478
@@ -490,6 +490,15 @@ congreet(int s)
Dmitry Belyavskiy 6f7478
 		return;
Dmitry Belyavskiy 6f7478
 	}
Dmitry Belyavskiy 6f7478
 
Dmitry Belyavskiy 6f7478
+	/*
Dmitry Belyavskiy 6f7478
+	 * Read the server banner as per RFC4253 section 4.2.  The "SSH-"
Dmitry Belyavskiy 6f7478
+	 * protocol identification string may be preceeded by an arbitarily
Dmitry Belyavskiy 6f7478
+	 * large banner which we must read and ignore.  Loop while reading
Dmitry Belyavskiy 6f7478
+	 * newline-terminated lines until we have one starting with "SSH-".
Dmitry Belyavskiy 6f7478
+	 * The ID string cannot be longer than 255 characters although the
Dmitry Belyavskiy 6f7478
+	 * preceeding banner lines may (in which case they'll be discarded
Dmitry Belyavskiy 6f7478
+	 * in multiple iterations of the outer loop).
Dmitry Belyavskiy 6f7478
+	 */
Dmitry Belyavskiy 6f7478
 	for (;;) {
Dmitry Belyavskiy 6f7478
 		memset(buf, '\0', sizeof(buf));
Dmitry Belyavskiy 6f7478
 		bufsiz = sizeof(buf);
Dmitry Belyavskiy 6f7478
@@ -517,6 +526,11 @@ congreet(int s)
Dmitry Belyavskiy 6f7478
 		conrecycle(s);
Dmitry Belyavskiy 6f7478
 		return;
Dmitry Belyavskiy 6f7478
 	}
Dmitry Belyavskiy 6f7478
+	if (cp >= buf + sizeof(buf)) {
Dmitry Belyavskiy 6f7478
+		error("%s: greeting exceeds allowable length", c->c_name);
Dmitry Belyavskiy 6f7478
+		confree(s);
Dmitry Belyavskiy 6f7478
+		return;
Dmitry Belyavskiy 6f7478
+	}
Dmitry Belyavskiy 6f7478
 	if (*cp != '\n' && *cp != '\r') {
Dmitry Belyavskiy 6f7478
 		error("%s: bad greeting", c->c_name);
Dmitry Belyavskiy 6f7478
 		confree(s);
Dmitry Belyavskiy 6f7478
diff --git a/sshsig.c b/sshsig.c
Dmitry Belyavskiy 6f7478
index 1e3b6398..eb2a931e 100644
Dmitry Belyavskiy 6f7478
--- a/sshsig.c
Dmitry Belyavskiy 6f7478
+++ b/sshsig.c
Dmitry Belyavskiy 6f7478
@@ -491,7 +491,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
Dmitry Belyavskiy 6f7478
 {
Dmitry Belyavskiy 6f7478
 	char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
Dmitry Belyavskiy 6f7478
 	ssize_t n, total = 0;
Dmitry Belyavskiy 6f7478
-	struct ssh_digest_ctx *ctx;
Dmitry Belyavskiy 6f7478
+	struct ssh_digest_ctx *ctx = NULL;
Dmitry Belyavskiy 6f7478
 	int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
Dmitry Belyavskiy 6f7478
 	struct sshbuf *b = NULL;
Dmitry Belyavskiy 6f7478
 
Dmitry Belyavskiy 6f7478
@@ -549,9 +548,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
Dmitry Belyavskiy 6f7478
 	/* success */
Dmitry Belyavskiy 6f7478
 	r = 0;
Dmitry Belyavskiy 6f7478
  out:
Dmitry Belyavskiy 6f7478
+	oerrno = errno;
Dmitry Belyavskiy 6f7478
 	sshbuf_free(b);
Dmitry Belyavskiy 6f7478
 	ssh_digest_free(ctx);
Dmitry Belyavskiy 6f7478
 	explicit_bzero(hash, sizeof(hash));
Dmitry Belyavskiy 6f7478
+	errno = oerrno;
Dmitry Belyavskiy 6f7478
 	return r;
Dmitry Belyavskiy 6f7478
 }
Dmitry Belyavskiy 6f7478