浏览代码

PuTTY snapshot d73a1716 (Remove static list of primes in sshprime.c - 2018-12-31)

Source commit: ea09c6e71ed7d7d8cce0c59845a5341af5415613
Martin Prikryl 6 年之前
父节点
当前提交
5ea824662f

+ 4 - 5
source/putty/WINDOWS/winucs.c

@@ -504,15 +504,14 @@ void init_ucs(Conf *conf, struct unicode_data *ucsdata)
     }
 
 #if 0
-    debug(
-	  ("Line cp%d, Font cp%d%s\n", ucsdata->line_codepage,
-	   ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : ""));
+    debug("Line cp%d, Font cp%d%s\n", ucsdata->line_codepage,
+          ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : "");
 
     for (i = 0; i < 256; i += 16) {
 	for (j = 0; j < 16; j++) {
-	    debug(("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ","));
+	    debug("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ",");
 	}
-	debug(("\n"));
+	debug("\n");
     }
 #endif
 

+ 6 - 0
source/putty/defs.h

@@ -113,4 +113,10 @@ typedef struct PacketProtocolLayer PacketProtocolLayer;
     TYPECHECK(object == &((type *)0)->field,                            \
               ((type *)(((char *)(object)) - offsetof(type, field))))
 
+#if defined __GNUC__ || defined __clang__
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#endif
+
 #endif /* PUTTY_DEFS_H */

+ 28 - 28
source/putty/mainchan.c

@@ -127,7 +127,7 @@ static void mainchan_open_confirmation(Channel *chan)
     PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
 
     seat_update_specials_menu(mc->ppl->seat);
-    ppl_logevent(("Opened main channel"));
+    ppl_logevent("Opened main channel");
 
     if (mc->is_simple)
         sshfwd_hint_channel_is_simple(mc->sc);
@@ -146,8 +146,8 @@ static void mainchan_open_confirmation(Channel *chan)
             if ((x11disp = x11_setup_display(
                      conf_get_str(mc->conf, CONF_x11_display),
                      mc->conf, &x11_setup_err)) == NULL) {
-                ppl_logevent(("X11 forwarding not enabled: unable to"
-                              " initialise X display: %s", x11_setup_err));
+                ppl_logevent("X11 forwarding not enabled: unable to"
+                             " initialise X display: %s", x11_setup_err);
                 sfree(x11_setup_err);
             } else {
                 x11auth = ssh_add_x11_display(
@@ -178,7 +178,7 @@ static void mainchan_open_confirmation(Channel *chan)
             mc->n_req_env++;
         }
         if (mc->n_req_env)
-            ppl_logevent(("Sent %d environment variables", mc->n_req_env));
+            ppl_logevent("Sent %d environment variables", mc->n_req_env);
 
         cmd = conf_get_str(mc->conf, CONF_remote_cmd);
         if (conf_get_bool(mc->conf, CONF_ssh_subsys)) {
@@ -222,10 +222,10 @@ static void mainchan_request_response(Channel *chan, bool success)
         mc->req_x11 = false;
 
         if (success) {
-            ppl_logevent(("X11 forwarding enabled"));
+            ppl_logevent("X11 forwarding enabled");
             ssh_enable_x_fwd(mc->cl);
         } else {
-            ppl_logevent(("X11 forwarding refused"));
+            ppl_logevent("X11 forwarding refused");
         }
         return;
     }
@@ -234,10 +234,10 @@ static void mainchan_request_response(Channel *chan, bool success)
         mc->req_agent = false;
 
         if (success) {
-            ppl_logevent(("Agent forwarding enabled"));
+            ppl_logevent("Agent forwarding enabled");
             ssh_enable_agent_fwd(mc->cl);
         } else {
-            ppl_logevent(("Agent forwarding refused"));
+            ppl_logevent("Agent forwarding refused");
         }
         return;
     }
@@ -246,11 +246,11 @@ static void mainchan_request_response(Channel *chan, bool success)
         mc->req_pty = false;
 
         if (success) {
-            ppl_logevent(("Allocated pty"));
+            ppl_logevent("Allocated pty");
             mc->got_pty = true;
         } else {
-            ppl_logevent(("Server refused to allocate pty"));
-            ppl_printf(("Server refused to allocate pty\r\n"));
+            ppl_logevent("Server refused to allocate pty");
+            ppl_printf("Server refused to allocate pty\r\n");
             ssh_set_ldisc_option(mc->cl, LD_ECHO, true);
             ssh_set_ldisc_option(mc->cl, LD_EDIT, true);
         }
@@ -260,22 +260,22 @@ static void mainchan_request_response(Channel *chan, bool success)
     if (mc->n_env_replies < mc->n_req_env) {
         int j = mc->n_env_replies++;
         if (!success) {
-            ppl_logevent(("Server refused to set environment variable %s",
-                          conf_get_str_nthstrkey(mc->conf,
-                                                 CONF_environmt, j)));
+            ppl_logevent("Server refused to set environment variable %s",
+                         conf_get_str_nthstrkey(mc->conf,
+                                                CONF_environmt, j));
             mc->n_env_fails++;
         }
 
         if (mc->n_env_replies == mc->n_req_env) {
             if (mc->n_env_fails == 0) {
-                ppl_logevent(("All environment variables successfully set"));
+                ppl_logevent("All environment variables successfully set");
             } else if (mc->n_env_fails == mc->n_req_env) {
-                ppl_logevent(("All environment variables refused"));
-                ppl_printf(("Server refused to set environment "
-                            "variables\r\n"));
+                ppl_logevent("All environment variables refused");
+                ppl_printf("Server refused to set environment "
+                           "variables\r\n");
             } else {
-                ppl_printf(("Server refused to set all environment "
-                            "variables\r\n"));
+                ppl_printf("Server refused to set all environment "
+                           "variables\r\n");
             }
         }
         return;
@@ -285,10 +285,10 @@ static void mainchan_request_response(Channel *chan, bool success)
         mc->req_cmd_primary = false;
 
         if (success) {
-            ppl_logevent(("Started a shell/command"));
+            ppl_logevent("Started a shell/command");
             mainchan_ready(mc);
         } else if (*conf_get_str(mc->conf, CONF_remote_cmd2)) {
-            ppl_logevent(("Primary command failed; attempting fallback"));
+            ppl_logevent("Primary command failed; attempting fallback");
             mainchan_try_fallback_command(mc);
         } else {
             /*
@@ -305,7 +305,7 @@ static void mainchan_request_response(Channel *chan, bool success)
         mc->req_cmd_fallback = false;
 
         if (success) {
-            ppl_logevent(("Started a shell/command"));
+            ppl_logevent("Started a shell/command");
             ssh_got_fallback_cmd(mc->ppl->ssh);
             mainchan_ready(mc);
         } else {
@@ -385,7 +385,7 @@ static void mainchan_send_eof(Channel *chan)
          * isn't a particularly meaningful concept.
          */
         sshfwd_write_eof(mc->sc);
-        ppl_logevent(("Sent EOF message"));
+        ppl_logevent("Sent EOF message");
         mc->eof_sent = true;
         ssh_set_wants_user_input(mc->cl, false); /* stop reading from stdin */
     }
@@ -417,7 +417,7 @@ static bool mainchan_rcvd_exit_status(Channel *chan, int status)
     PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
 
     ssh_got_exitcode(mc->ppl->ssh, status);
-    ppl_logevent(("Session sent command exit status %d", status));
+    ppl_logevent("Session sent command exit status %d", status);
     return true;
 }
 
@@ -430,8 +430,8 @@ static void mainchan_log_exit_signal_common(
     const char *core_msg = core_dumped ? " (core dumped)" : "";
     const char *msg_pre = (msg.len ? " (" : "");
     const char *msg_post = (msg.len ? ")" : "");
-    ppl_logevent(("Session exited on %s%s%s%.*s%s",
-                  sigdesc, core_msg, msg_pre, PTRLEN_PRINTF(msg), msg_post));
+    ppl_logevent("Session exited on %s%s%s%.*s%s",
+                 sigdesc, core_msg, msg_pre, PTRLEN_PRINTF(msg), msg_post);
 }
 
 static bool mainchan_rcvd_exit_signal(
@@ -544,7 +544,7 @@ void mainchan_special_cmd(mainchan *mc, SessionSpecialCode code, int arg)
     } else if ((signame = ssh_signal_lookup(code)) != NULL) {
         /* It's a signal. */
         sshfwd_send_signal(mc->sc, false, signame);
-        ppl_logevent(("Sent signal SIG%s", signame));
+        ppl_logevent("Sent signal SIG%s", signame);
     }
 }
 

+ 104 - 0
source/putty/memory.c

@@ -0,0 +1,104 @@
+/*
+ * PuTTY's memory allocation wrappers.
+ */
+
+#include <stdlib.h>
+
+#include "putty.h"
+
+void *safemalloc(size_t n, size_t size)
+{
+    void *p;
+
+    if (n > INT_MAX / size) {
+	p = NULL;
+    } else {
+	size *= n;
+	if (size == 0) size = 1;
+#ifdef MINEFIELD
+	p = minefield_c_malloc(size);
+#else
+	p = malloc(size);
+#endif
+    }
+
+    if (!p) {
+	char str[200];
+#ifdef MALLOC_LOG
+	sprintf(str, "Out of memory! (%s:%d, size=%d)",
+		mlog_file, mlog_line, size);
+	fprintf(fp, "*** %s\n", str);
+	fclose(fp);
+#else
+	strcpy(str, "Out of memory!");
+#endif
+	modalfatalbox("%s", str);
+    }
+#ifdef MALLOC_LOG
+    if (fp)
+	fprintf(fp, "malloc(%d) returns %p\n", size, p);
+#endif
+    return p;
+}
+
+void *saferealloc(void *ptr, size_t n, size_t size)
+{
+    void *p;
+
+    if (n > INT_MAX / size) {
+	p = NULL;
+    } else {
+	size *= n;
+	if (!ptr) {
+#ifdef MINEFIELD
+	    p = minefield_c_malloc(size);
+#else
+	    p = malloc(size);
+#endif
+	} else {
+#ifdef MINEFIELD
+	    p = minefield_c_realloc(ptr, size);
+#else
+	    p = realloc(ptr, size);
+#endif
+	}
+    }
+
+    if (!p) {
+	char str[200];
+#ifdef MALLOC_LOG
+	sprintf(str, "Out of memory! (%s:%d, size=%d)",
+		mlog_file, mlog_line, size);
+	fprintf(fp, "*** %s\n", str);
+	fclose(fp);
+#else
+	strcpy(str, "Out of memory!");
+#endif
+	modalfatalbox("%s", str);
+    }
+#ifdef MALLOC_LOG
+    if (fp)
+	fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
+#endif
+    return p;
+}
+
+void safefree(void *ptr)
+{
+    if (ptr) {
+#ifdef MALLOC_LOG
+	if (fp)
+	    fprintf(fp, "free(%p)\n", ptr);
+#endif
+#ifdef MINEFIELD
+	minefield_c_free(ptr);
+#else
+	free(ptr);
+#endif
+    }
+#ifdef MALLOC_LOG
+    else if (fp)
+	fprintf(fp, "freeing null pointer - no action taken\n");
+#endif
+}
+

+ 9 - 102
source/putty/misc.c

@@ -813,6 +813,15 @@ bool bufchain_try_fetch_consume(bufchain *ch, void *data, int len)
     }
 }
 
+int bufchain_fetch_consume_up_to(bufchain *ch, void *data, int len)
+{
+    if (len > ch->buffersize)
+        len = ch->buffersize;
+    if (len)
+        bufchain_fetch_consume(ch, data, len);
+    return len;
+}
+
 /* ----------------------------------------------------------------------
  * Sanitise terminal output that we have reason not to trust, e.g.
  * because it appears in the login banner or password prompt from a
@@ -850,12 +859,6 @@ void sanitise_term_data(bufchain *out, const void *vdata, int len)
  * one.
  */
 
-#ifdef MINEFIELD
-void *minefield_c_malloc(size_t size);
-void minefield_c_free(void *p);
-void *minefield_c_realloc(void *p, size_t size);
-#endif
-
 #ifdef MALLOC_LOG
 static FILE *fp = NULL;
 
@@ -875,102 +878,6 @@ void mlog(char *file, int line)
 }
 #endif
 
-void *safemalloc(size_t n, size_t size)
-{
-    void *p;
-
-    if (n > INT_MAX / size) {
-	p = NULL;
-    } else {
-	size *= n;
-	if (size == 0) size = 1;
-#ifdef MINEFIELD
-	p = minefield_c_malloc(size);
-#else
-	p = malloc(size);
-#endif
-    }
-
-    if (!p) {
-	char str[200];
-#ifdef MALLOC_LOG
-	sprintf(str, "Out of memory! (%s:%d, size=%d)",
-		mlog_file, mlog_line, size);
-	fprintf(fp, "*** %s\n", str);
-	fclose(fp);
-#else
-	strcpy(str, "Out of memory!");
-#endif
-	modalfatalbox("%s", str);
-    }
-#ifdef MALLOC_LOG
-    if (fp)
-	fprintf(fp, "malloc(%d) returns %p\n", size, p);
-#endif
-    return p;
-}
-
-void *saferealloc(void *ptr, size_t n, size_t size)
-{
-    void *p;
-
-    if (n > INT_MAX / size) {
-	p = NULL;
-    } else {
-	size *= n;
-	if (!ptr) {
-#ifdef MINEFIELD
-	    p = minefield_c_malloc(size);
-#else
-	    p = malloc(size);
-#endif
-	} else {
-#ifdef MINEFIELD
-	    p = minefield_c_realloc(ptr, size);
-#else
-	    p = realloc(ptr, size);
-#endif
-	}
-    }
-
-    if (!p) {
-	char str[200];
-#ifdef MALLOC_LOG
-	sprintf(str, "Out of memory! (%s:%d, size=%d)",
-		mlog_file, mlog_line, size);
-	fprintf(fp, "*** %s\n", str);
-	fclose(fp);
-#else
-	strcpy(str, "Out of memory!");
-#endif
-	modalfatalbox("%s", str);
-    }
-#ifdef MALLOC_LOG
-    if (fp)
-	fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
-#endif
-    return p;
-}
-
-void safefree(void *ptr)
-{
-    if (ptr) {
-#ifdef MALLOC_LOG
-	if (fp)
-	    fprintf(fp, "free(%p)\n", ptr);
-#endif
-#ifdef MINEFIELD
-	minefield_c_free(ptr);
-#else
-	free(ptr);
-#endif
-    }
-#ifdef MALLOC_LOG
-    else if (fp)
-	fprintf(fp, "freeing null pointer - no action taken\n");
-#endif
-}
-
 /* ----------------------------------------------------------------------
  * Debugging routines.
  */

+ 4 - 3
source/putty/misc.h

@@ -106,6 +106,7 @@ void bufchain_consume(bufchain *ch, int len);
 void bufchain_fetch(bufchain *ch, void *data, int len);
 void bufchain_fetch_consume(bufchain *ch, void *data, int len);
 bool bufchain_try_fetch_consume(bufchain *ch, void *data, int len);
+int bufchain_fetch_consume_up_to(bufchain *ch, void *data, int len);
 
 void sanitise_term_data(bufchain *out, const void *vdata, int len);
 
@@ -173,7 +174,7 @@ char *buildinfo(const char *newline);
  *
  * Output goes to debug.log
  *
- * debug(()) (note the double brackets) is like printf().
+ * debug() is like printf().
  *
  * dmemdump() and dmemdumpl() both do memory dumps.  The difference
  * is that dmemdumpl() is more suited for when the memory address is
@@ -184,11 +185,11 @@ char *buildinfo(const char *newline);
 #ifdef DEBUG
 void debug_printf(const char *fmt, ...);
 void debug_memdump(const void *buf, int len, bool L);
-#define debug(x) (debug_printf x)
+#define debug(...) (debug_printf(__VA_ARGS__))
 #define dmemdump(buf,len) debug_memdump (buf, len, false);
 #define dmemdumpl(buf,len) debug_memdump (buf, len, true);
 #else
-#define debug(x)
+#define debug(...)
 #define dmemdump(buf,len)
 #define dmemdumpl(buf,len)
 #endif

+ 24 - 74
source/putty/proxy.c

@@ -1276,15 +1276,8 @@ int proxy_socks5_negotiate (ProxySocket *p, int change)
 char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 {
     char *fmt = conf_get_str(conf, CONF_proxy_telnet_command);
-    char *ret = NULL;
-    int retlen = 0, retsize = 0;
     int so = 0, eo = 0;
-#define ENSURE(n) do { \
-    if (retsize < retlen + n) { \
-	retsize = retlen + n + 512; \
-	ret = sresize(ret, retsize, char); \
-    } \
-} while (0)
+    strbuf *buf = strbuf_new();
 
     /* we need to escape \\, \%, \r, \n, \t, \x??, \0???, 
      * %%, %host, %port, %user, and %pass
@@ -1302,11 +1295,8 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 
 	/* if there was any unescaped text before the escape
 	 * character, send that now */
-	if (eo != so) {
-	    ENSURE(eo - so);
-	    memcpy(ret + retlen, fmt + so, eo - so);
-	    retlen += eo - so;
-	}
+	if (eo != so)
+            put_data(buf, fmt + so, eo - so);
 
 	so = eo++;
 
@@ -1323,32 +1313,27 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 	    switch (fmt[eo]) {
 
 	      case '\\':
-		ENSURE(1);
-		ret[retlen++] = '\\';
+		put_byte(buf, '\\');
 		eo++;
 		break;
 
 	      case '%':
-		ENSURE(1);
-		ret[retlen++] = '%';
+                put_byte(buf, '%');
 		eo++;
 		break;
 
 	      case 'r':
-		ENSURE(1);
-		ret[retlen++] = '\r';
+                put_byte(buf, '\r');
 		eo++;
 		break;
 
 	      case 'n':
-		ENSURE(1);
-		ret[retlen++] = '\n';
+                put_byte(buf, '\n');
 		eo++;
 		break;
 
 	      case 't':
-		ENSURE(1);
-		ret[retlen++] = '\t';
+                put_byte(buf, '\t');
 		eo++;
 		break;
 
@@ -1371,16 +1356,14 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 			    /* non hex character, so we abort and just
 			     * send the whole thing unescaped (including \x)
 			     */
-			    ENSURE(1);
-			    ret[retlen++] = '\\';
+                            put_byte(buf, '\\');
 			    eo = so + 1;
 			    break;
 			}
 
 			/* we only extract two hex characters */
 			if (i == 1) {
-			    ENSURE(1);
-			    ret[retlen++] = v;
+                            put_byte(buf, v);
 			    eo++;
 			    break;
 			}
@@ -1392,9 +1375,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 		break;
 
 	      default:
-		ENSURE(2);
-		memcpy(ret+retlen, fmt + so, 2);
-		retlen += 2;
+                put_data(buf, fmt + so, 2);
 		eo++;
 		break;
 	    }
@@ -1406,61 +1387,37 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 	     */
 
 	    if (fmt[eo] == '%') {
-		ENSURE(1);
-		ret[retlen++] = '%';
+                put_byte(buf, '%');
 		eo++;
 	    }
 	    else if (strnicmp(fmt + eo, "host", 4) == 0) {
 		char dest[512];
-		int destlen;
 		sk_getaddr(addr, dest, lenof(dest));
-		destlen = strlen(dest);
-		ENSURE(destlen);
-		memcpy(ret+retlen, dest, destlen);
-		retlen += destlen;
+		put_data(buf, dest, strlen(dest));
 		eo += 4;
 	    }
 	    else if (strnicmp(fmt + eo, "port", 4) == 0) {
-		char portstr[8], portlen;
-		portlen = sprintf(portstr, "%i", port);
-		ENSURE(portlen);
-		memcpy(ret + retlen, portstr, portlen);
-		retlen += portlen;
+                strbuf_catf(buf, "%d", port);
 		eo += 4;
 	    }
 	    else if (strnicmp(fmt + eo, "user", 4) == 0) {
-		char *username = conf_get_str(conf, CONF_proxy_username);
-		int userlen = strlen(username);
-		ENSURE(userlen);
-		memcpy(ret+retlen, username, userlen);
-		retlen += userlen;
+		const char *username = conf_get_str(conf, CONF_proxy_username);
+		put_data(buf, username, strlen(username));
 		eo += 4;
 	    }
 	    else if (strnicmp(fmt + eo, "pass", 4) == 0) {
-		char *password = conf_get_str(conf, CONF_proxy_password);
-		int passlen = strlen(password);
-		ENSURE(passlen);
-		memcpy(ret+retlen, password, passlen);
-		retlen += passlen;
+		const char *password = conf_get_str(conf, CONF_proxy_password);
+		put_data(buf, password, strlen(password));
 		eo += 4;
 	    }
 	    else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) {
-		char *host = conf_get_str(conf, CONF_proxy_host);
-		int phlen = strlen(host);
-		ENSURE(phlen);
-		memcpy(ret+retlen, host, phlen);
-		retlen += phlen;
+		const char *host = conf_get_str(conf, CONF_proxy_host);
+		put_data(buf, host, strlen(host));
 		eo += 9;
 	    }
 	    else if (strnicmp(fmt + eo, "proxyport", 9) == 0) {
 		int port = conf_get_int(conf, CONF_proxy_port);
-                char pport[50];
-		int pplen;
-                sprintf(pport, "%d", port);
-                pplen = strlen(pport);
-		ENSURE(pplen);
-		memcpy(ret+retlen, pport, pplen);
-		retlen += pplen;
+                strbuf_catf(buf, "%d", port);
 		eo += 9;
 	    }
 	    else {
@@ -1468,8 +1425,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 		 * don't advance eo, so that we'll consider the
 		 * text immediately following the % as unescaped.
 		 */
-		ENSURE(1);
-		ret[retlen++] = '%';
+                put_byte(buf, '%');
 	    }
 	}
 
@@ -1479,16 +1435,10 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
 
     /* if there is any unescaped text at the end of the line, send it */
     if (eo != so) {
-	ENSURE(eo - so);
-	memcpy(ret + retlen, fmt + so, eo - so);
-	retlen += eo - so;
+	put_data(buf, fmt + so, eo - so);
     }
 
-    ENSURE(1);
-    ret[retlen] = '\0';
-    return ret;
-
-#undef ENSURE
+    return strbuf_to_str(buf);
 }
 
 int proxy_telnet_negotiate (ProxySocket *p, int change)

+ 10 - 5
source/putty/putty.h

@@ -1141,11 +1141,8 @@ struct TermWinVtable {
  * Global functions not specific to a connection instance.
  */
 void nonfatal(const char *, ...);
-void modalfatalbox(const char *, ...);
-#ifdef macintosh
-#pragma noreturn(modalfatalbox)
-#endif
-void cleanup_exit(int);
+NORETURN void modalfatalbox(const char *, ...);
+NORETURN void cleanup_exit(int);
 
 /*
  * Exports from conf.c, and a big enum (via parametric macro) of
@@ -1536,7 +1533,15 @@ void term_set_focus(Terminal *term, bool has_focus);
 char *term_get_ttymode(Terminal *term, const char *mode);
 int term_get_userpass_input(Terminal *term, prompts_t *p, bufchain *input);
 
+typedef enum SmallKeypadKey {
+    SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN,
+} SmallKeypadKey;
 int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl);
+int format_function_key(char *buf, Terminal *term, int key_number,
+                        bool shift, bool ctrl);
+int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key);
+int format_numeric_keypad_key(char *buf, Terminal *term, char key,
+                              bool shift, bool ctrl);
 
 /*
  * Exports from logging.c.

+ 4 - 8
source/putty/ssh.h

@@ -506,14 +506,13 @@ void BinarySource_get_rsa_ssh1_priv(
 bool rsa_ssh1_encrypt(unsigned char *data, int length, struct RSAKey *key);
 Bignum rsa_ssh1_decrypt(Bignum input, struct RSAKey *key);
 bool rsa_ssh1_decrypt_pkcs1(Bignum input, struct RSAKey *key, strbuf *outbuf);
-void rsasanitise(struct RSAKey *key);
-int rsastr_len(struct RSAKey *key);
-void rsastr_fmt(char *str, struct RSAKey *key);
+char *rsastr_fmt(struct RSAKey *key);
 char *rsa_ssh1_fingerprint(struct RSAKey *key);
 bool rsa_verify(struct RSAKey *key);
 void rsa_ssh1_public_blob(BinarySink *bs, struct RSAKey *key,
                           RsaSsh1Order order);
 int rsa_ssh1_public_blob_len(void *data, int maxlen);
+void freersapriv(struct RSAKey *key);
 void freersakey(struct RSAKey *key);
 
 unsigned long crc32_compute(const void *s, size_t len);
@@ -833,12 +832,12 @@ struct ssh_compression_alg {
     const char *delayed_name;
     ssh_compressor *(*compress_new)(void);
     void (*compress_free)(ssh_compressor *);
-    void (*compress)(ssh_compressor *, unsigned char *block, int len,
+    void (*compress)(ssh_compressor *, const unsigned char *block, int len,
                      unsigned char **outblock, int *outlen,
                      int minlen);
     ssh_decompressor *(*decompress_new)(void);
     void (*decompress_free)(ssh_decompressor *);
-    bool (*decompress)(ssh_decompressor *, unsigned char *block, int len,
+    bool (*decompress)(ssh_decompressor *, const unsigned char *block, int len,
                        unsigned char **outblock, int *outlen);
     const char *text_name;
 };
@@ -1529,9 +1528,6 @@ unsigned alloc_channel_id_general(tree234 *channels, size_t localid_offset);
     TYPECHECK(&((type *)0)->localid == (unsigned *)0, \
               alloc_channel_id_general(tree, offsetof(type, localid)))
 
-bool first_in_commasep_string(char const *needle, char const *haystack,
-                              int haylen);
-bool in_commasep_string(char const *needle, char const *haystack, int haylen);
 void add_to_commasep(strbuf *buf, const char *data);
 bool get_commasep_word(ptrlen *list, ptrlen *word);
 

+ 10 - 9
source/putty/ssh1bpp.c

@@ -85,7 +85,7 @@ void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
         assert(!s->crcda_ctx);
         s->crcda_ctx = crcda_make_context();
 
-        bpp_logevent(("Initialised %s encryption", cipher->text_name));
+        bpp_logevent("Initialised %s encryption", cipher->text_name);
     }
 }
 
@@ -101,16 +101,17 @@ void ssh1_bpp_start_compression(BinaryPacketProtocol *bpp)
     s->compctx = ssh_compressor_new(&ssh_zlib);
     s->decompctx = ssh_decompressor_new(&ssh_zlib);
 
-    bpp_logevent(("Started zlib (RFC1950) compression"));
+    bpp_logevent("Started zlib (RFC1950) compression");
 }
 
-#define BPP_READ(ptr, len) do                                   \
-    {                                                           \
-        crMaybeWaitUntilV(s->bpp.input_eof ||                   \
-                          bufchain_try_fetch_consume(           \
-                              s->bpp.in_raw, ptr, len));        \
-        if (s->bpp.input_eof)                                   \
-            goto eof;                                           \
+#define BPP_READ(ptr, len) do                                           \
+    {                                                                   \
+        bool success;                                                   \
+        crMaybeWaitUntilV((success = bufchain_try_fetch_consume(        \
+                               s->bpp.in_raw, ptr, len)) ||             \
+                          s->bpp.input_eof);                            \
+        if (!success)                                                   \
+            goto eof;                                                   \
     } while (0)
 
 static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)

+ 13 - 13
source/putty/ssh1connection-client.c

@@ -126,7 +126,7 @@ bool ssh1_handle_direction_specific_packet(
                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
             put_uint32(pktout, remid);
             pq_push(s->ppl.out_pq, pktout);
-            ppl_logevent(("Rejected X11 connect request"));
+            ppl_logevent("Rejected X11 connect request");
         } else {
             c = snew(struct ssh1_channel);
             c->connlayer = s;
@@ -142,7 +142,7 @@ bool ssh1_handle_direction_specific_packet(
             put_uint32(pktout, c->remoteid);
             put_uint32(pktout, c->localid);
             pq_push(s->ppl.out_pq, pktout);
-            ppl_logevent(("Opened X11 forward channel"));
+            ppl_logevent("Opened X11 forward channel");
         }
 
         return true;
@@ -183,8 +183,8 @@ bool ssh1_handle_direction_specific_packet(
         pfp = find234(s->rportfwds, &pf, NULL);
 
         if (!pfp) {
-            ppl_logevent(("Rejected remote port open request for %s:%d",
-                          pf.dhost, port));
+            ppl_logevent("Rejected remote port open request for %s:%d",
+                         pf.dhost, port);
             pktout = ssh_bpp_new_pktout(
                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
             put_uint32(pktout, remid);
@@ -194,14 +194,14 @@ bool ssh1_handle_direction_specific_packet(
 
             c = snew(struct ssh1_channel);
             c->connlayer = s;
-            ppl_logevent(("Received remote port open request for %s:%d",
-                          pf.dhost, port));
+            ppl_logevent("Received remote port open request for %s:%d",
+                         pf.dhost, port);
             err = portfwdmgr_connect(
                 s->portfwdmgr, &c->chan, pf.dhost, port,
                 &c->sc, pfp->addressfamily);
 
             if (err) {
-                ppl_logevent(("Port open failed: %s", err));
+                ppl_logevent("Port open failed: %s", err);
                 sfree(err);
                 ssh1_channel_free(c);
                 pktout = ssh_bpp_new_pktout(
@@ -217,7 +217,7 @@ bool ssh1_handle_direction_specific_packet(
                 put_uint32(pktout, c->remoteid);
                 put_uint32(pktout, c->localid);
                 pq_push(s->ppl.out_pq, pktout);
-                ppl_logevent(("Forwarded port opened successfully"));
+                ppl_logevent("Forwarded port opened successfully");
             }
         }
 
@@ -243,7 +243,7 @@ bool ssh1_handle_direction_specific_packet(
       case SSH1_SMSG_EXIT_STATUS:
         {
             int exitcode = get_uint32(pktin);
-            ppl_logevent(("Server sent command exit status %d", exitcode));
+            ppl_logevent("Server sent command exit status %d", exitcode);
             ssh_got_exitcode(s->ppl.ssh, exitcode);
 
             s->session_terminated = true;
@@ -468,11 +468,11 @@ static void ssh1_rportfwd_response(struct ssh1_connection_state *s,
     struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
 
     if (success) {
-	ppl_logevent(("Remote port forwarding from %s enabled",
-                      rpf->log_description));
+	ppl_logevent("Remote port forwarding from %s enabled",
+                     rpf->log_description);
     } else {
-	ppl_logevent(("Remote port forwarding from %s refused",
-                      rpf->log_description));
+	ppl_logevent("Remote port forwarding from %s refused",
+                     rpf->log_description);
 
 	struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
 	assert(realpf == rpf);

+ 3 - 3
source/putty/ssh1connection.c

@@ -482,7 +482,7 @@ static void ssh1_channel_close_local(struct ssh1_channel *c,
     const char *msg = chan_log_close_msg(c->chan);
 
     if (msg != NULL)
-        ppl_logevent(("%s%s%s", msg, reason ? " " : "", reason ? reason : ""));
+        ppl_logevent("%s%s%s", msg, reason ? " " : "", reason ? reason : "");
 
     chan_free(c->chan);
     c->chan = zombiechan_new();
@@ -637,8 +637,8 @@ static SshChannel *ssh1_lportfwd_open(
     c->halfopen = true;
     c->chan = chan;
 
-    ppl_logevent(("Opening connection to %s:%d for %s",
-                  hostname, port, description));
+    ppl_logevent("Opening connection to %s:%d for %s",
+                 hostname, port, description);
 
     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_MSG_PORT_OPEN);
     put_uint32(pktout, c->localid);

+ 81 - 97
source/putty/ssh1login.c

@@ -157,7 +157,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         return;
     }
 
-    ppl_logevent(("Received public keys"));
+    ppl_logevent("Received public keys");
 
     {
         ptrlen pl = get_data(pktin, 8);
@@ -174,8 +174,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
      */
     if (!get_err(pktin)) {
         char *fingerprint = rsa_ssh1_fingerprint(&s->hostkey);
-        ppl_logevent(("Host key fingerprint is:"));
-        ppl_logevent(("      %s", fingerprint));
+        ppl_logevent("Host key fingerprint is:");
+        ppl_logevent("      %s", fingerprint);
         sfree(fingerprint);
     }
 
@@ -222,16 +222,14 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         /*
          * First format the key into a string.
          */
-        int len = rsastr_len(&s->hostkey);
         char *fingerprint;
-        char *keystr = snewn(len, char);
-        rsastr_fmt(keystr, &s->hostkey);
+        char *keystr = rsastr_fmt(&s->hostkey);
         fingerprint = rsa_ssh1_fingerprint(&s->hostkey);
 
         /* First check against manually configured host keys. */
         s->dlgret = verify_ssh_manual_host_key(s->conf, fingerprint, NULL);
-        sfree(fingerprint);
         if (s->dlgret == 0) {          /* did not match */
+            sfree(fingerprint);
             sfree(keystr);
             ssh_proto_error(s->ppl.ssh, "Host key did not appear in manually "
                             "configured list");
@@ -240,6 +238,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
             s->dlgret = seat_verify_ssh_host_key(
                 s->ppl.seat, s->savedhost, s->savedport,
                 "rsa", keystr, fingerprint, ssh1_login_dialog_callback, s);
+            sfree(fingerprint);
             sfree(keystr);
 #ifdef FUZZING
             s->dlgret = 1;
@@ -276,7 +275,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         }
     }
 
-    ppl_logevent(("Encrypted session key"));
+    ppl_logevent("Encrypted session key");
 
     {
         bool cipher_chosen = false, warn = false;
@@ -290,7 +289,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                 warn = true;
             } else if (next_cipher == CIPHER_AES) {
                 /* XXX Probably don't need to mention this. */
-                ppl_logevent(("AES not supported in SSH-1, skipping"));
+                ppl_logevent("AES not supported in SSH-1, skipping");
             } else {
                 switch (next_cipher) {
                   case CIPHER_3DES:     s->cipher_type = SSH_CIPHER_3DES;
@@ -330,13 +329,13 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
 
     switch (s->cipher_type) {
       case SSH_CIPHER_3DES:
-        ppl_logevent(("Using 3DES encryption"));
+        ppl_logevent("Using 3DES encryption");
         break;
       case SSH_CIPHER_DES:
-        ppl_logevent(("Using single-DES encryption"));
+        ppl_logevent("Using single-DES encryption");
         break;
       case SSH_CIPHER_BLOWFISH:
-        ppl_logevent(("Using Blowfish encryption"));
+        ppl_logevent("Using Blowfish encryption");
         break;
     }
 
@@ -348,7 +347,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
     put_uint32(pkt, s->local_protoflags);
     pq_push(s->ppl.out_pq, pkt);
 
-    ppl_logevent(("Trying to enable encryption..."));
+    ppl_logevent("Trying to enable encryption...");
 
     sfree(s->rsabuf);
     s->rsabuf = NULL;
@@ -367,22 +366,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         ssh1_bpp_new_cipher(s->ppl.bpp, cipher, s->session_key);
     }
 
-    if (s->servkey.modulus) {
-        sfree(s->servkey.modulus);
-        s->servkey.modulus = NULL;
-    }
-    if (s->servkey.exponent) {
-        sfree(s->servkey.exponent);
-        s->servkey.exponent = NULL;
-    }
-    if (s->hostkey.modulus) {
-        sfree(s->hostkey.modulus);
-        s->hostkey.modulus = NULL;
-    }
-    if (s->hostkey.exponent) {
-        sfree(s->hostkey.exponent);
-        s->hostkey.exponent = NULL;
-    }
+    freersakey(&s->servkey);
+    freersakey(&s->hostkey);
     crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
 
     if (pktin->type != SSH1_SMSG_SUCCESS) {
@@ -390,7 +375,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         return;
     }
 
-    ppl_logevent(("Successfully started encryption"));
+    ppl_logevent("Successfully started encryption");
 
     if ((s->username = get_remote_username(s->conf)) == NULL) {
         s->cur_prompt = new_prompts();
@@ -428,9 +413,9 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
     put_stringz(pkt, s->username);
     pq_push(s->ppl.out_pq, pkt);
 
-    ppl_logevent(("Sent username \"%s\"", s->username));
+    ppl_logevent("Sent username \"%s\"", s->username);
     if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE))
-        ppl_printf(("Sent username \"%s\"\r\n", s->username));
+        ppl_printf("Sent username \"%s\"\r\n", s->username);
 
     crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
 
@@ -448,8 +433,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
     s->keyfile = conf_get_filename(s->conf, CONF_keyfile);
     if (!filename_is_null(s->keyfile)) {
         int keytype;
-        ppl_logevent(("Reading key file \"%.150s\"",
-                      filename_to_str(s->keyfile)));
+        ppl_logevent("Reading key file \"%s\"", filename_to_str(s->keyfile));
         keytype = key_type(s->keyfile);
         if (keytype == SSH_KEYTYPE_SSH1 ||
             keytype == SSH_KEYTYPE_SSH1_PUBLIC) {
@@ -460,22 +444,22 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                  &s->publickey_comment, &error)) {
                 s->privatekey_available = (keytype == SSH_KEYTYPE_SSH1);
                 if (!s->privatekey_available)
-                    ppl_logevent(("Key file contains public key only"));
+                    ppl_logevent("Key file contains public key only");
                 s->privatekey_encrypted = rsa_ssh1_encrypted(s->keyfile, NULL);
             } else {
-                ppl_logevent(("Unable to load key (%s)", error));
-                ppl_printf(("Unable to load key file \"%s\" (%s)\r\n",
-                            filename_to_str(s->keyfile), error));
+                ppl_logevent("Unable to load key (%s)", error);
+                ppl_printf("Unable to load key file \"%s\" (%s)\r\n",
+                           filename_to_str(s->keyfile), error);
 
                 strbuf_free(s->publickey_blob);
                 s->publickey_blob = NULL;
             }
         } else {
-            ppl_logevent(("Unable to use this key file (%s)",
-                          key_type_to_str(keytype)));
-            ppl_printf(("Unable to use key file \"%s\" (%s)\r\n",
-                        filename_to_str(s->keyfile),
-                        key_type_to_str(keytype)));
+            ppl_logevent("Unable to use this key file (%s)",
+                         key_type_to_str(keytype));
+            ppl_printf("Unable to use key file \"%s\" (%s)\r\n",
+                       filename_to_str(s->keyfile),
+                       key_type_to_str(keytype));
         }
     }
 
@@ -493,7 +477,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
              */
             s->authed = false;
             s->tried_agent = true;
-            ppl_logevent(("Pageant is running. Requesting keys."));
+            ppl_logevent("Pageant is running. Requesting keys.");
 
             /* Request the keys held by the agent. */
             {
@@ -510,11 +494,11 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
             if (get_byte(s->asrc) == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
                 s->nkeys = toint(get_uint32(s->asrc));
                 if (s->nkeys < 0) {
-                    ppl_logevent(("Pageant reported negative key count %d",
-                                  s->nkeys));
+                    ppl_logevent("Pageant reported negative key count %d",
+                                 s->nkeys);
                     s->nkeys = 0;
                 }
-                ppl_logevent(("Pageant has %d SSH-1 keys", s->nkeys));
+                ppl_logevent("Pageant has %d SSH-1 keys", s->nkeys);
                 for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
                     size_t start, end;
                     start = s->asrc->pos;
@@ -523,7 +507,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                     end = s->asrc->pos;
                     s->comment = get_string(s->asrc);
                     if (get_err(s->asrc)) {
-                        ppl_logevent(("Pageant key list packet was truncated"));
+                        ppl_logevent("Pageant key list packet was truncated");
                         break;
                     }
                     if (s->publickey_blob) {
@@ -533,24 +517,24 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                         if (keystr.len == s->publickey_blob->len &&
                             !memcmp(keystr.ptr, s->publickey_blob->s,
                                     s->publickey_blob->len)) {
-                            ppl_logevent(("Pageant key #%d matches "
-                                          "configured key file", s->keyi));
+                            ppl_logevent("Pageant key #%d matches "
+                                         "configured key file", s->keyi);
                             s->tried_publickey = true;
                         } else
                             /* Skip non-configured key */
                             continue;
                     }
-                    ppl_logevent(("Trying Pageant key #%d", s->keyi));
+                    ppl_logevent("Trying Pageant key #%d", s->keyi);
                     pkt = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_AUTH_RSA);
                     put_mp_ssh1(pkt, s->key.modulus);
                     pq_push(s->ppl.out_pq, pkt);
                     crMaybeWaitUntilV((pktin = ssh1_login_pop(s))
                                       != NULL);
                     if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
-                        ppl_logevent(("Key refused"));
+                        ppl_logevent("Key refused");
                         continue;
                     }
-                    ppl_logevent(("Received RSA challenge"));
+                    ppl_logevent("Received RSA challenge");
                     s->challenge = get_mp_ssh1(pktin);
                     if (get_err(pktin)) {
                         freebn(s->challenge);
@@ -579,7 +563,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                         if (ret) {
                             if (s->agent_response.len >= 5+16 &&
                                 ret[4] == SSH1_AGENT_RSA_RESPONSE) {
-                                ppl_logevent(("Sending Pageant's response"));
+                                ppl_logevent("Sending Pageant's response");
                                 pkt = ssh_bpp_new_pktout(
                                     s->ppl.bpp, SSH1_CMSG_AUTH_RSA_RESPONSE);
                                 put_data(pkt, ret + 5, 16);
@@ -589,25 +573,25 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                     (pktin = ssh1_login_pop(s))
                                     != NULL);
                                 if (pktin->type == SSH1_SMSG_SUCCESS) {
-                                    ppl_logevent(("Pageant's response "
-                                                  "accepted"));
+                                    ppl_logevent("Pageant's response "
+                                                 "accepted");
                                     if (flags & FLAG_VERBOSE) {
-                                        ppl_printf(("Authenticated using RSA "
-                                                    "key \"%.*s\" from "
-                                                    "agent\r\n", PTRLEN_PRINTF(
-                                                        s->comment)));
+                                        ppl_printf("Authenticated using RSA "
+                                                   "key \"%.*s\" from "
+                                                   "agent\r\n", PTRLEN_PRINTF(
+                                                       s->comment));
                                     }
                                     s->authed = true;
                                 } else
-                                    ppl_logevent(("Pageant's response not "
-                                                  "accepted"));
+                                    ppl_logevent("Pageant's response not "
+                                                 "accepted");
                             } else {
-                                ppl_logevent(("Pageant failed to answer "
-                                              "challenge"));
+                                ppl_logevent("Pageant failed to answer "
+                                             "challenge");
                                 sfree((char *)ret);
                             }
                         } else {
-                            ppl_logevent(("No reply received from Pageant"));
+                            ppl_logevent("No reply received from Pageant");
                         }
                     }
                     freebn(s->key.exponent);
@@ -619,9 +603,9 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                 sfree(s->agent_response_to_free);
                 s->agent_response_to_free = NULL;
                 if (s->publickey_blob && !s->tried_publickey)
-                    ppl_logevent(("Configured key file not in Pageant"));
+                    ppl_logevent("Configured key file not in Pageant");
             } else {
-                ppl_logevent(("Failed to get reply from Pageant"));
+                ppl_logevent("Failed to get reply from Pageant");
             }
             if (s->authed)
                 break;
@@ -634,9 +618,9 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
              */
             bool got_passphrase; /* need not be kept over crReturn */
             if (flags & FLAG_VERBOSE)
-                ppl_printf(("Trying public key authentication.\r\n"));
-            ppl_logevent(("Trying public key \"%s\"",
-                          filename_to_str(s->keyfile)));
+                ppl_printf("Trying public key authentication.\r\n");
+            ppl_logevent("Trying public key \"%s\"",
+                         filename_to_str(s->keyfile));
             s->tried_publickey = true;
             got_passphrase = false;
             while (!got_passphrase) {
@@ -648,14 +632,14 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                 const char *error;
                 if (!s->privatekey_encrypted) {
                     if (flags & FLAG_VERBOSE)
-                        ppl_printf(("No passphrase required.\r\n"));
+                        ppl_printf("No passphrase required.\r\n");
                     passphrase = NULL;
                 } else {
                     s->cur_prompt = new_prompts(s->ppl.seat);
                     s->cur_prompt->to_server = false;
                     s->cur_prompt->name = dupstr("SSH key passphrase");
                     add_prompt(s->cur_prompt,
-                               dupprintf("Passphrase for key \"%.100s\": ",
+                               dupprintf("Passphrase for key \"%s\": ",
                                          s->publickey_comment), false);
                     s->userpass_ret = seat_get_userpass_input(
                         s->ppl.seat, s->cur_prompt, NULL);
@@ -695,12 +679,12 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                     /* Correct passphrase. */
                     got_passphrase = true;
                 } else if (retd == 0) {
-                    ppl_printf(("Couldn't load private key from %s (%s).\r\n",
-                                filename_to_str(s->keyfile), error));
+                    ppl_printf("Couldn't load private key from %s (%s).\r\n",
+                               filename_to_str(s->keyfile), error);
                     got_passphrase = false;
                     break;             /* go and try something else */
                 } else if (retd == -1) {
-                    ppl_printf(("Wrong passphrase.\r\n"));
+                    ppl_printf("Wrong passphrase.\r\n");
                     got_passphrase = false;
                     /* and try again */
                 } else {
@@ -721,7 +705,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                 crMaybeWaitUntilV((pktin = ssh1_login_pop(s))
                                   != NULL);
                 if (pktin->type == SSH1_SMSG_FAILURE) {
-                    ppl_printf(("Server refused our public key.\r\n"));
+                    ppl_printf("Server refused our public key.\r\n");
                     continue;          /* go and try something else */
                 }
                 if (pktin->type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
@@ -745,7 +729,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                         return;
                     }
                     response = rsa_ssh1_decrypt(challenge, &s->key);
-                    freebn(s->key.private_exponent);/* burn the evidence */
+                    freersapriv(&s->key);   /* burn the evidence */
 
                     for (i = 0; i < 32; i++) {
                         buffer[i] = bignum_byte(response, 31 - i);
@@ -772,8 +756,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                   != NULL);
                 if (pktin->type == SSH1_SMSG_FAILURE) {
                     if (flags & FLAG_VERBOSE)
-                        ppl_printf(("Failed to authenticate with"
-                                    " our public key.\r\n"));
+                        ppl_printf("Failed to authenticate with"
+                                   " our public key.\r\n");
                     continue;          /* go and try something else */
                 } else if (pktin->type != SSH1_SMSG_SUCCESS) {
                     ssh_proto_error(s->ppl.ssh, "Received unexpected packet"
@@ -797,14 +781,14 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
             (s->supported_auths_mask & (1 << SSH1_AUTH_TIS)) &&
             !s->tis_auth_refused) {
             s->pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
-            ppl_logevent(("Requested TIS authentication"));
+            ppl_logevent("Requested TIS authentication");
             pkt = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_AUTH_TIS);
             pq_push(s->ppl.out_pq, pkt);
             crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
             if (pktin->type == SSH1_SMSG_FAILURE) {
-                ppl_logevent(("TIS authentication declined"));
+                ppl_logevent("TIS authentication declined");
                 if (flags & FLAG_INTERACTIVE)
-                    ppl_printf(("TIS authentication refused.\r\n"));
+                    ppl_printf("TIS authentication refused.\r\n");
                 s->tis_auth_refused = true;
                 continue;
             } else if (pktin->type == SSH1_SMSG_AUTH_TIS_CHALLENGE) {
@@ -817,7 +801,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                     "badly formed");
                     return;
                 }
-                ppl_logevent(("Received TIS challenge"));
+                ppl_logevent("Received TIS challenge");
                 s->cur_prompt->to_server = true;
                 s->cur_prompt->name = dupstr("SSH TIS authentication");
                 /* Prompt heuristic comes from OpenSSH */
@@ -846,13 +830,13 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
             (s->supported_auths_mask & (1 << SSH1_AUTH_CCARD)) &&
             !s->ccard_auth_refused) {
             s->pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
-            ppl_logevent(("Requested CryptoCard authentication"));
+            ppl_logevent("Requested CryptoCard authentication");
             pkt = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_AUTH_CCARD);
             pq_push(s->ppl.out_pq, pkt);
             crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
             if (pktin->type == SSH1_SMSG_FAILURE) {
-                ppl_logevent(("CryptoCard authentication declined"));
-                ppl_printf(("CryptoCard authentication refused.\r\n"));
+                ppl_logevent("CryptoCard authentication declined");
+                ppl_printf("CryptoCard authentication refused.\r\n");
                 s->ccard_auth_refused = true;
                 continue;
             } else if (pktin->type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
@@ -865,7 +849,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                     "was badly formed");
                     return;
                 }
-                ppl_logevent(("Received CryptoCard challenge"));
+                ppl_logevent("Received CryptoCard challenge");
                 s->cur_prompt->to_server = true;
                 s->cur_prompt->name = dupstr("SSH CryptoCard authentication");
                 s->cur_prompt->name_reqd = false;
@@ -1008,7 +992,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                         pq_push(s->ppl.out_pq, pkt);
                     }
                 }
-                ppl_logevent(("Sending password with camouflage packets"));
+                ppl_logevent("Sending password with camouflage packets");
             } 
             else if (!(s->ppl.remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
                 /*
@@ -1018,7 +1002,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                  */
                 strbuf *padded_pw = strbuf_new();
 
-                ppl_logevent(("Sending length-padded password"));
+                ppl_logevent("Sending length-padded password");
                 pkt = ssh_bpp_new_pktout(s->ppl.bpp, s->pwpkt_type);
                 put_asciz(padded_pw, s->cur_prompt->prompts[0]->result);
                 do {
@@ -1031,7 +1015,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                  * The server is believed unable to cope with
                  * any of our password camouflage methods.
                  */
-                ppl_logevent(("Sending unpadded password"));
+                ppl_logevent("Sending unpadded password");
                 pkt = ssh_bpp_new_pktout(s->ppl.bpp, s->pwpkt_type);
                 put_stringz(pkt, s->cur_prompt->prompts[0]->result);
                 pq_push(s->ppl.out_pq, pkt);
@@ -1041,14 +1025,14 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
             put_stringz(pkt, s->cur_prompt->prompts[0]->result);
             pq_push(s->ppl.out_pq, pkt);
         }
-        ppl_logevent(("Sent password"));
+        ppl_logevent("Sent password");
         free_prompts(s->cur_prompt);
         s->cur_prompt = NULL;
         crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
         if (pktin->type == SSH1_SMSG_FAILURE) {
             if (flags & FLAG_VERBOSE)
-                ppl_printf(("Access denied\r\n"));
-            ppl_logevent(("Authentication refused"));
+                ppl_printf("Access denied\r\n");
+            ppl_logevent("Authentication refused");
         } else if (pktin->type != SSH1_SMSG_SUCCESS) {
             ssh_proto_error(s->ppl.ssh, "Received unexpected packet"
                             " in response to password authentication, type %d "
@@ -1057,10 +1041,10 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
         }
     }
 
-    ppl_logevent(("Authentication successful"));
+    ppl_logevent("Authentication successful");
 
     if (conf_get_bool(s->conf, CONF_compression)) {
-        ppl_logevent(("Requesting compression"));
+        ppl_logevent("Requesting compression");
         pkt = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_REQUEST_COMPRESSION);
         put_uint32(pkt, 6);         /* gzip compression level */
         pq_push(s->ppl.out_pq, pkt);
@@ -1075,8 +1059,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
              * cross in transit.)
              */
 	} else if (pktin->type == SSH1_SMSG_FAILURE) {
-            ppl_logevent(("Server refused to enable compression"));
-	    ppl_printf(("Server refused to compress\r\n"));
+            ppl_logevent("Server refused to enable compression");
+	    ppl_printf("Server refused to compress\r\n");
         } else {
             ssh_proto_error(s->ppl.ssh, "Received unexpected packet"
                             " in response to compression request, type %d "

+ 8 - 7
source/putty/ssh2bpp-bare.c

@@ -51,13 +51,14 @@ static void ssh2_bare_bpp_free(BinaryPacketProtocol *bpp)
     sfree(s);
 }
 
-#define BPP_READ(ptr, len) do                                   \
-    {                                                           \
-        crMaybeWaitUntilV(s->bpp.input_eof ||                   \
-                          bufchain_try_fetch_consume(           \
-                              s->bpp.in_raw, ptr, len));        \
-        if (s->bpp.input_eof)                                   \
-            goto eof;                                           \
+#define BPP_READ(ptr, len) do                                           \
+    {                                                                   \
+        bool success;                                                   \
+        crMaybeWaitUntilV((success = bufchain_try_fetch_consume(        \
+                               s->bpp.in_raw, ptr, len)) ||             \
+                          s->bpp.input_eof);                            \
+        if (!success)                                                   \
+            goto eof;                                                   \
     } while (0)
 
 static void ssh2_bare_bpp_handle_input(BinaryPacketProtocol *bpp)

+ 36 - 35
source/putty/ssh2bpp.c

@@ -113,8 +113,8 @@ void ssh2_bpp_new_outgoing_crypto(
             (ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
             !(s->bpp.remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE));
 
-        bpp_logevent(("Initialised %.200s outbound encryption",
-                      ssh2_cipher_alg(s->out.cipher)->text_name));
+        bpp_logevent("Initialised %s outbound encryption",
+                     ssh2_cipher_alg(s->out.cipher)->text_name);
     } else {
         s->out.cipher = NULL;
         s->cbc_ignore_workaround = false;
@@ -124,12 +124,12 @@ void ssh2_bpp_new_outgoing_crypto(
         s->out.mac = ssh2_mac_new(mac, s->out.cipher);
         mac->setkey(s->out.mac, mac_key);
 
-        bpp_logevent(("Initialised %.200s outbound MAC algorithm%s%s",
-                      ssh2_mac_alg(s->out.mac)->text_name,
-                      etm_mode ? " (in ETM mode)" : "",
-                      (s->out.cipher &&
-                       ssh2_cipher_alg(s->out.cipher)->required_mac ?
-                       " (required by cipher)" : "")));
+        bpp_logevent("Initialised %s outbound MAC algorithm%s%s",
+                     ssh2_mac_alg(s->out.mac)->text_name,
+                     etm_mode ? " (in ETM mode)" : "",
+                     (s->out.cipher &&
+                      ssh2_cipher_alg(s->out.cipher)->required_mac ?
+                      " (required by cipher)" : ""));
     } else {
         s->out.mac = NULL;
     }
@@ -138,8 +138,8 @@ void ssh2_bpp_new_outgoing_crypto(
         s->out.pending_compression = compression;
         s->out_comp = NULL;
 
-        bpp_logevent(("Will enable %s compression after user authentication",
-                      s->out.pending_compression->text_name));
+        bpp_logevent("Will enable %s compression after user authentication",
+                     s->out.pending_compression->text_name);
     } else {
         s->out.pending_compression = NULL;
 
@@ -149,8 +149,8 @@ void ssh2_bpp_new_outgoing_crypto(
         s->out_comp = ssh_compressor_new(compression);
 
         if (s->out_comp)
-            bpp_logevent(("Initialised %s compression",
-                          ssh_compressor_alg(s->out_comp)->text_name));
+            bpp_logevent("Initialised %s compression",
+                         ssh_compressor_alg(s->out_comp)->text_name);
     }
 }
 
@@ -176,8 +176,8 @@ void ssh2_bpp_new_incoming_crypto(
         ssh2_cipher_setkey(s->in.cipher, ckey);
         ssh2_cipher_setiv(s->in.cipher, iv);
 
-        bpp_logevent(("Initialised %.200s inbound encryption",
-                      ssh2_cipher_alg(s->in.cipher)->text_name));
+        bpp_logevent("Initialised %s inbound encryption",
+                     ssh2_cipher_alg(s->in.cipher)->text_name);
     } else {
         s->in.cipher = NULL;
     }
@@ -186,12 +186,12 @@ void ssh2_bpp_new_incoming_crypto(
         s->in.mac = ssh2_mac_new(mac, s->in.cipher);
         mac->setkey(s->in.mac, mac_key);
 
-        bpp_logevent(("Initialised %.200s inbound MAC algorithm%s%s",
-                      ssh2_mac_alg(s->in.mac)->text_name,
-                      etm_mode ? " (in ETM mode)" : "",
-                      (s->in.cipher &&
-                       ssh2_cipher_alg(s->in.cipher)->required_mac ?
-                       " (required by cipher)" : "")));
+        bpp_logevent("Initialised %s inbound MAC algorithm%s%s",
+                     ssh2_mac_alg(s->in.mac)->text_name,
+                     etm_mode ? " (in ETM mode)" : "",
+                     (s->in.cipher &&
+                      ssh2_cipher_alg(s->in.cipher)->required_mac ?
+                      " (required by cipher)" : ""));
     } else {
         s->in.mac = NULL;
     }
@@ -200,8 +200,8 @@ void ssh2_bpp_new_incoming_crypto(
         s->in.pending_compression = compression;
         s->in_decomp = NULL;
 
-        bpp_logevent(("Will enable %s decompression after user authentication",
-                      s->in.pending_compression->text_name));
+        bpp_logevent("Will enable %s decompression after user authentication",
+                     s->in.pending_compression->text_name);
     } else {
         s->in.pending_compression = NULL;
 
@@ -211,8 +211,8 @@ void ssh2_bpp_new_incoming_crypto(
         s->in_decomp = ssh_decompressor_new(compression);
 
         if (s->in_decomp)
-            bpp_logevent(("Initialised %s decompression",
-                          ssh_decompressor_alg(s->in_decomp)->text_name));
+            bpp_logevent("Initialised %s decompression",
+                         ssh_decompressor_alg(s->in_decomp)->text_name);
     }
 
     /* Clear the pending_newkeys flag, so that handle_input below will
@@ -239,25 +239,26 @@ static void ssh2_bpp_enable_pending_compression(struct ssh2_bpp_state *s)
 
     if (s->in.pending_compression) {
         s->in_decomp = ssh_decompressor_new(s->in.pending_compression);
-        bpp_logevent(("Initialised delayed %s decompression",
-                      ssh_decompressor_alg(s->in_decomp)->text_name));
+        bpp_logevent("Initialised delayed %s decompression",
+                     ssh_decompressor_alg(s->in_decomp)->text_name);
         s->in.pending_compression = NULL;
     }
     if (s->out.pending_compression) {
         s->out_comp = ssh_compressor_new(s->out.pending_compression);
-        bpp_logevent(("Initialised delayed %s compression",
-                      ssh_compressor_alg(s->out_comp)->text_name));
+        bpp_logevent("Initialised delayed %s compression",
+                     ssh_compressor_alg(s->out_comp)->text_name);
         s->out.pending_compression = NULL;
     }
 }
 
-#define BPP_READ(ptr, len) do                                   \
-    {                                                           \
-        crMaybeWaitUntilV(s->bpp.input_eof ||                   \
-                          bufchain_try_fetch_consume(           \
-                              s->bpp.in_raw, ptr, len));        \
-        if (s->bpp.input_eof)                                   \
-            goto eof;                                           \
+#define BPP_READ(ptr, len) do                                           \
+    {                                                                   \
+        bool success;                                                   \
+        crMaybeWaitUntilV((success = bufchain_try_fetch_consume(        \
+                               s->bpp.in_raw, ptr, len)) ||             \
+                          s->bpp.input_eof);                            \
+        if (!success)                                                   \
+            goto eof;                                                   \
     } while (0)
 
 #define userauth_range(pkttype) ((unsigned)((pkttype) - 50) < 20)

+ 17 - 17
source/putty/ssh2connection-client.c

@@ -20,8 +20,8 @@ static ChanopenResult chan_open_x11(
     char *peeraddr_str;
     Channel *ch;
 
-    ppl_logevent(("Received X11 connect request from %.*s:%d",
-                  PTRLEN_PRINTF(peeraddr), peerport));
+    ppl_logevent("Received X11 connect request from %.*s:%d",
+                 PTRLEN_PRINTF(peeraddr), peerport);
 
     if (!s->X11_fwd_enabled && !s->connshare) {
         CHANOPEN_RETURN_FAILURE(
@@ -33,7 +33,7 @@ static ChanopenResult chan_open_x11(
     ch = x11_new_channel(
         s->x11authtree, sc, peeraddr_str, peerport, s->connshare != NULL);
     sfree(peeraddr_str);
-    ppl_logevent(("Opened X11 forward channel"));
+    ppl_logevent("Opened X11 forward channel");
     CHANOPEN_RETURN_SUCCESS(ch);
 }
 
@@ -46,9 +46,9 @@ static ChanopenResult chan_open_forwarded_tcpip(
     Channel *ch;
     char *err;
 
-    ppl_logevent(("Received remote port %.*s:%d open request from %.*s:%d",
-                  PTRLEN_PRINTF(fwdaddr), fwdport,
-                  PTRLEN_PRINTF(peeraddr), peerport));
+    ppl_logevent("Received remote port %.*s:%d open request from %.*s:%d",
+                 PTRLEN_PRINTF(fwdaddr), fwdport,
+                 PTRLEN_PRINTF(peeraddr), peerport);
 
     pf.shost = mkstr(fwdaddr);
     pf.sport = fwdport;
@@ -72,17 +72,17 @@ static ChanopenResult chan_open_forwarded_tcpip(
     err = portfwdmgr_connect(
         s->portfwdmgr, &ch, realpf->dhost, realpf->dport,
         sc, realpf->addressfamily);
-    ppl_logevent(("Attempting to forward remote port to %s:%d",
-                  realpf->dhost, realpf->dport));
+    ppl_logevent("Attempting to forward remote port to %s:%d",
+                 realpf->dhost, realpf->dport);
     if (err != NULL) {
-        ppl_logevent(("Port open failed: %s", err));
+        ppl_logevent("Port open failed: %s", err);
         sfree(err);
         CHANOPEN_RETURN_FAILURE(
             SSH2_OPEN_CONNECT_FAILED,
             ("Port open failed"));
     }
 
-    ppl_logevent(("Forwarded port opened successfully"));
+    ppl_logevent("Forwarded port opened successfully");
     CHANOPEN_RETURN_SUCCESS(ch);
 }
 
@@ -150,8 +150,8 @@ PktOut *ssh2_portfwd_chanopen(
      * connect _to_.
      */
 
-    ppl_logevent(("Opening connection to %s:%d for %s",
-                  hostname, port, description));
+    ppl_logevent("Opening connection to %s:%d for %s",
+                 hostname, port, description);
 
     pktout = ssh2_chanopen_init(c, "direct-tcpip");
     {
@@ -196,11 +196,11 @@ static void ssh2_rportfwd_globreq_response(struct ssh2_connection_state *s,
     struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
 
     if (pktin->type == SSH2_MSG_REQUEST_SUCCESS) {
-	ppl_logevent(("Remote port forwarding from %s enabled",
-                      rpf->log_description));
+	ppl_logevent("Remote port forwarding from %s enabled",
+                     rpf->log_description);
     } else {
-	ppl_logevent(("Remote port forwarding from %s refused",
-                      rpf->log_description));
+	ppl_logevent("Remote port forwarding from %s refused",
+                     rpf->log_description);
 
 	struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
 	assert(realpf == rpf);
@@ -293,7 +293,7 @@ SshChannel *ssh2_session_open(ConnectionLayer *cl, Channel *chan)
     c->halfopen = true;
     c->chan = chan;
 
-    ppl_logevent(("Opening main session channel"));
+    ppl_logevent("Opening main session channel");
 
     pktout = ssh2_chanopen_init(c, "session");
     pq_push(s->ppl.out_pq, pktout);

+ 4 - 5
source/putty/ssh2connection.c

@@ -407,8 +407,8 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
                 put_stringz(pktout, chanopen_result.u.failure.wire_message);
                 put_stringz(pktout, "en");	/* language tag */
                 pq_push(s->ppl.out_pq, pktout);
-                ppl_logevent(("Rejected channel open: %s",
-                              chanopen_result.u.failure.wire_message));
+                ppl_logevent("Rejected channel open: %s",
+                             chanopen_result.u.failure.wire_message);
                 sfree(chanopen_result.u.failure.wire_message);
                 sfree(c);
             } else {
@@ -685,8 +685,7 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
                         bs_modes, encoded_modes.ptr, encoded_modes.len);
                     modes = read_ttymodes_from_packet(bs_modes, 2);
                     if (get_err(bs_modes) || get_avail(bs_modes) > 0) {
-                        ppl_logevent(("Unable to decode terminal mode "
-                                      "string"));
+                        ppl_logevent("Unable to decode terminal mode string");
                         reply_success = false;
                     } else {
                         reply_success = chan_allocate_pty(
@@ -1151,7 +1150,7 @@ static void ssh2_channel_close_local(struct ssh2_channel *c,
     msg = chan_log_close_msg(c->chan);
 
     if (msg)
-        ppl_logevent(("%s%s%s", msg, reason ? " " : "", reason ? reason : ""));
+        ppl_logevent("%s%s%s", msg, reason ? " " : "", reason ? reason : "");
 
     sfree(msg);
 

+ 73 - 44
source/putty/ssh2kex-client.c

@@ -12,7 +12,7 @@
 #include "storage.h"
 #include "ssh2transport.h"
 
-void ssh2kex_coroutine(struct ssh2_transport_state *s)
+void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
 {
     PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
     PktIn *pktin;
@@ -43,7 +43,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
          * requesting a group.
          */
         if (dh_is_gex(s->kex_alg)) {
-            ppl_logevent(("Doing Diffie-Hellman group exchange"));
+            ppl_logevent("Doing Diffie-Hellman group exchange");
             s->ppl.bpp->pls->kctx = SSH2_PKTCTX_DHGEX;
             /*
              * Work out how big a DH group we will need to allow that
@@ -75,6 +75,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                                 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                               s->ppl.bpp->pls->actx,
                                               pktin->type));
+                *aborted = true;
                 return;
             }
             s->p = get_mp_ssh2(pktin);
@@ -82,27 +83,28 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             if (get_err(pktin)) {
                 ssh_proto_error(s->ppl.ssh,
                                 "Unable to parse Diffie-Hellman group packet");
+                *aborted = true;
                 return;
             }
             s->dh_ctx = dh_setup_gex(s->p, s->g);
             s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
             s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
 
-            ppl_logevent(("Doing Diffie-Hellman key exchange using %d-bit "
-                          "modulus and hash %s with a server-supplied group",
-                          dh_modulus_bit_size(s->dh_ctx),
-                          s->kex_alg->hash->text_name));
+            ppl_logevent("Doing Diffie-Hellman key exchange using %d-bit "
+                         "modulus and hash %s with a server-supplied group",
+                         dh_modulus_bit_size(s->dh_ctx),
+                         s->kex_alg->hash->text_name);
         } else {
             s->ppl.bpp->pls->kctx = SSH2_PKTCTX_DHGROUP;
             s->dh_ctx = dh_setup_group(s->kex_alg);
             s->kex_init_value = SSH2_MSG_KEXDH_INIT;
             s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;
 
-            ppl_logevent(("Doing Diffie-Hellman key exchange using %d-bit "
-                          "modulus and hash %s with standard group \"%s\"",
-                          dh_modulus_bit_size(s->dh_ctx),
-                          s->kex_alg->hash->text_name,
-                          s->kex_alg->groupname));
+            ppl_logevent("Doing Diffie-Hellman key exchange using %d-bit "
+                         "modulus and hash %s with standard group \"%s\"",
+                         dh_modulus_bit_size(s->dh_ctx),
+                         s->kex_alg->hash->text_name,
+                         s->kex_alg->groupname);
         }
 
         /*
@@ -123,6 +125,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                             ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                           s->ppl.bpp->pls->actx,
                                           pktin->type));
+            *aborted = true;
             return;
         }
         seat_set_busy_status(s->ppl.seat, BUSY_CPU);
@@ -133,6 +136,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         if (get_err(pktin)) {
             ssh_proto_error(s->ppl.ssh,
                             "Unable to parse Diffie-Hellman reply packet");
+            *aborted = true;
             return;
         }
 
@@ -141,6 +145,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             if (err) {
                 ssh_proto_error(s->ppl.ssh, "Diffie-Hellman reply failed "
                                 "validation: %s", err);
+                *aborted = true;
                 return;
             }
         }
@@ -172,14 +177,15 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         }
     } else if (s->kex_alg->main_type == KEXTYPE_ECDH) {
 
-        ppl_logevent(("Doing ECDH key exchange with curve %s and hash %s",
-                      ssh_ecdhkex_curve_textname(s->kex_alg),
-                      s->kex_alg->hash->text_name));
+        ppl_logevent("Doing ECDH key exchange with curve %s and hash %s",
+                     ssh_ecdhkex_curve_textname(s->kex_alg),
+                     s->kex_alg->hash->text_name);
         s->ppl.bpp->pls->kctx = SSH2_PKTCTX_ECDHKEX;
 
         s->ecdh_key = ssh_ecdhkex_newkey(s->kex_alg);
         if (!s->ecdh_key) {
             ssh_sw_abort(s->ppl.ssh, "Unable to generate key for ECDH");
+            *aborted = true;
             return;
         }
 
@@ -199,6 +205,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                             ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                           s->ppl.bpp->pls->actx,
                                           pktin->type));
+            *aborted = true;
             return;
         }
 
@@ -220,6 +227,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             if (!get_err(pktin) && !s->K) {
                 ssh_proto_error(s->ppl.ssh, "Received invalid elliptic curve "
                                 "point in ECDH reply");
+                *aborted = true;
                 return;
             }
         }
@@ -227,6 +235,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         s->sigdata = get_string(pktin);
         if (get_err(pktin)) {
             ssh_proto_error(s->ppl.ssh, "Unable to parse ECDH reply packet");
+            *aborted = true;
             return;
         }
 
@@ -268,8 +277,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
              * much data.
              */
             s->pbits = 512 << ((s->nbits - 1) / 64);
-            ppl_logevent(("Doing GSSAPI (with Kerberos V5) Diffie-Hellman "
-                          "group exchange, with minimum %d bits", s->pbits));
+            ppl_logevent("Doing GSSAPI (with Kerberos V5) Diffie-Hellman "
+                         "group exchange, with minimum %d bits", s->pbits);
             pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXGSS_GROUPREQ);
             put_uint32(pktout, s->pbits); /* min */
             put_uint32(pktout, s->pbits); /* preferred */
@@ -285,6 +294,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                                 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                               s->ppl.bpp->pls->actx,
                                               pktin->type));
+                *aborted = true;
                 return;
             }
             s->p = get_mp_ssh2(pktin);
@@ -292,23 +302,24 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             if (get_err(pktin)) {
                 ssh_proto_error(s->ppl.ssh,
                                 "Unable to parse Diffie-Hellman group packet");
+                *aborted = true;
                 return;
             }
             s->dh_ctx = dh_setup_gex(s->p, s->g);
         } else {
             s->dh_ctx = dh_setup_group(s->kex_alg);
-            ppl_logevent(("Using GSSAPI (with Kerberos V5) Diffie-Hellman with"
-                          " standard group \"%s\"", s->kex_alg->groupname));
+            ppl_logevent("Using GSSAPI (with Kerberos V5) Diffie-Hellman with"
+                         " standard group \"%s\"", s->kex_alg->groupname);
         }
 
-        ppl_logevent(("Doing GSSAPI (with Kerberos V5) Diffie-Hellman key "
-                      "exchange with hash %s", s->kex_alg->hash->text_name));
+        ppl_logevent("Doing GSSAPI (with Kerberos V5) Diffie-Hellman key "
+                     "exchange with hash %s", s->kex_alg->hash->text_name);
         /* Now generate e for Diffie-Hellman. */
         seat_set_busy_status(s->ppl.seat, BUSY_CPU);
         s->e = dh_create_e(s->dh_ctx, s->nbits * 2);
 
         if (s->shgss->lib->gsslogmsg)
-            ppl_logevent(("%s", s->shgss->lib->gsslogmsg));
+            ppl_logevent("%s", s->shgss->lib->gsslogmsg);
 
         /* initial tokens are empty */
         SSH_GSS_CLEAR_BUF(&s->gss_rcvtok);
@@ -319,6 +330,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         if (s->gss_stat != SSH_GSS_OK) {
             ssh_sw_abort(s->ppl.ssh,
                          "GSSAPI key exchange failed to initialise");
+            *aborted = true;
             return;
         }
 
@@ -349,6 +361,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                                  "GSSAPI key exchange failed to initialise "
                                  "context: %s", err);
                     sfree(err);
+                    *aborted = true;
                     return;
                 }
             }
@@ -362,6 +375,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                 if (s->gss_sndtok.length == 0) {
                     ssh_sw_abort(s->ppl.ssh, "GSSAPI key exchange failed: "
                                  "no initial context token");
+                    *aborted = true;
                     return;
                 }
                 put_string(pktout,
@@ -369,7 +383,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                 put_mp_ssh2(pktout, s->e);
                 pq_push(s->ppl.out_pq, pktout);
                 s->shgss->lib->free_tok(s->shgss->lib, &s->gss_sndtok);
-                ppl_logevent(("GSSAPI key exchange initialised"));
+                ppl_logevent("GSSAPI key exchange initialised");
             } else if (s->gss_sndtok.length != 0) {
                 pktout = ssh_bpp_new_pktout(
                     s->ppl.bpp, SSH2_MSG_KEXGSS_CONTINUE);
@@ -435,8 +449,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                 get_uint32(pktin); /* server's major status */
                 get_uint32(pktin); /* server's minor status */
                 data = get_string(pktin);
-                ppl_logevent(("GSSAPI key exchange failed; "
-                              "server's message: %.*s", PTRLEN_PRINTF(data)));
+                ppl_logevent("GSSAPI key exchange failed; "
+                             "server's message: %.*s", PTRLEN_PRINTF(data));
                 /* Language tag, but we have no use for it */
                 get_string(pktin);
                 /*
@@ -453,6 +467,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                                 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                               s->ppl.bpp->pls->actx,
                                               pktin->type));
+                *aborted = true;
                 return;
             }
         } while (s->gss_rcvtok.length ||
@@ -496,8 +511,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         ptrlen rsakeydata;
 
         assert(s->kex_alg->main_type == KEXTYPE_RSA);
-        ppl_logevent(("Doing RSA key exchange with hash %s",
-                      s->kex_alg->hash->text_name));
+        ppl_logevent("Doing RSA key exchange with hash %s",
+                     s->kex_alg->hash->text_name);
         s->ppl.bpp->pls->kctx = SSH2_PKTCTX_RSAKEX;
         /*
          * RSA key exchange. First expect a KEXRSA_PUBKEY packet
@@ -511,6 +526,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                             ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                           s->ppl.bpp->pls->actx,
                                           pktin->type));
+            *aborted = true;
             return;
         }
 
@@ -524,6 +540,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         if (!s->rsa_kex_key) {
             ssh_proto_error(s->ppl.ssh,
                             "Unable to parse RSA public key packet");
+            *aborted = true;
             return;
         }
 
@@ -590,12 +607,14 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                             ssh2_pkt_type(s->ppl.bpp->pls->kctx,
                                           s->ppl.bpp->pls->actx,
                                           pktin->type));
+            *aborted = true;
             return;
         }
 
         s->sigdata = get_string(pktin);
         if (get_err(pktin)) {
             ssh_proto_error(s->ppl.ssh, "Unable to parse RSA kex signature");
+            *aborted = true;
             return;
         }
     }
@@ -622,6 +641,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                 ssh_sw_abort(s->ppl.ssh, "GSSAPI key exchange MIC was "
                              "not valid");
             }
+            *aborted = true;
             return;
         }
 
@@ -643,7 +663,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
         if (s->got_session_id) {
             s->shgss->lib->release_cred(s->shgss->lib, &s->shgss->ctx);
         }
-        ppl_logevent(("GSSAPI Key Exchange complete!"));
+        ppl_logevent("GSSAPI Key Exchange complete!");
     }
 #endif
 
@@ -653,6 +673,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
     if (s->kex_alg->main_type != KEXTYPE_GSS) {
         if (!s->hkey) {
             ssh_proto_error(s->ppl.ssh, "Server's host key is invalid");
+            *aborted = true;
             return;
         }
 
@@ -662,6 +683,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
 #ifndef FUZZING
             ssh_proto_error(s->ppl.ssh, "Signature from server's host key "
                             "is invalid");
+            *aborted = true;
             return;
 #endif
         }
@@ -682,8 +704,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
              */
             if (s->hkey) {
                 s->fingerprint = ssh2_fingerprint(s->hkey);
-                ppl_logevent(("GSS kex provided fallback host key:"));
-                ppl_logevent(("%s", s->fingerprint));
+                ppl_logevent("GSS kex provided fallback host key:");
+                ppl_logevent("%s", s->fingerprint);
                 sfree(s->fingerprint);
                 s->fingerprint = NULL;
                 ssh_transient_hostkey_cache_add(s->thc, s->hkey);
@@ -724,7 +746,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                      * consequence.
                      */
                     if (!s->warned_about_no_gss_transient_hostkey) {
-                        ppl_logevent(("No fallback host key available"));
+                        ppl_logevent("No fallback host key available");
                         s->warned_about_no_gss_transient_hostkey = true;
                     }
                 }
@@ -742,16 +764,17 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             s->fingerprint = ssh2_fingerprint(s->hkey);
 
             if (s->need_gss_transient_hostkey) {
-                ppl_logevent(("Post-GSS rekey provided fallback host key:"));
-                ppl_logevent(("%s", s->fingerprint));
+                ppl_logevent("Post-GSS rekey provided fallback host key:");
+                ppl_logevent("%s", s->fingerprint);
                 ssh_transient_hostkey_cache_add(s->thc, s->hkey);
                 s->need_gss_transient_hostkey = false;
             } else if (!ssh_transient_hostkey_cache_verify(s->thc, s->hkey)) {
-                ppl_logevent(("Non-GSS rekey after initial GSS kex "
-                              "used host key:"));
-                ppl_logevent(("%s", s->fingerprint));
+                ppl_logevent("Non-GSS rekey after initial GSS kex "
+                             "used host key:");
+                ppl_logevent("%s", s->fingerprint);
                 ssh_sw_abort(s->ppl.ssh, "Server's host key did not match any "
                              "used in previous GSS kex");
+                *aborted = true;
                 return;
             }
 
@@ -790,10 +813,10 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                     }
                 }
                 if (list) {
-                    ppl_logevent(("Server also has %s host key%s, but we "
-                                  "don't know %s", list,
-                                  nkeys > 1 ? "s" : "",
-                                  nkeys > 1 ? "any of them" : "it"));
+                    ppl_logevent("Server also has %s host key%s, but we "
+                                 "don't know %s", list,
+                                 nkeys > 1 ? "s" : "",
+                                 nkeys > 1 ? "any of them" : "it");
                     sfree(list);
                 }
             }
@@ -803,14 +826,15 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
              * checked the signature of the exchange hash.)
              */
             s->fingerprint = ssh2_fingerprint(s->hkey);
-            ppl_logevent(("Host key fingerprint is:"));
-            ppl_logevent(("%s", s->fingerprint));
+            ppl_logevent("Host key fingerprint is:");
+            ppl_logevent("%s", s->fingerprint);
             /* First check against manually configured host keys. */
             s->dlgret = verify_ssh_manual_host_key(
                 s->conf, s->fingerprint, s->hkey);
             if (s->dlgret == 0) {          /* did not match */
                 ssh_sw_abort(s->ppl.ssh, "Host key did not appear in manually "
                              "configured list");
+                *aborted = true;
                 return;
             } else if (s->dlgret < 0) { /* none configured; use standard handling */
                 s->dlgret = seat_verify_ssh_host_key(
@@ -824,6 +848,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
                 if (s->dlgret == 0) {
                     ssh_user_close(s->ppl.ssh,
                                    "User aborted at host key verification");
+                    *aborted = true;
                     return;
                 }
             }
@@ -836,14 +861,16 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
             s->hostkey_str = s->keystr;
             s->keystr = NULL;
         } else if (s->cross_certifying) {
+            assert(s->hkey);
+            assert(ssh_key_alg(s->hkey) == s->cross_certifying);
+
             s->fingerprint = ssh2_fingerprint(s->hkey);
-            ppl_logevent(("Storing additional host key for this host:"));
-            ppl_logevent(("%s", s->fingerprint));
+            ppl_logevent("Storing additional host key for this host:");
+            ppl_logevent("%s", s->fingerprint);
             sfree(s->fingerprint);
             s->fingerprint = NULL;
             store_host_key(s->savedhost, s->savedport,
                            ssh_key_cache_id(s->hkey), s->keystr);
-            s->cross_certifying = false;
             /*
              * Don't forget to store the new key as the one we'll be
              * re-checking in future normal rekeys.
@@ -857,10 +884,12 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s)
              * enforce that the key we're seeing this time is identical to
              * the one we saw before.
              */
+            assert(s->keystr);         /* filled in by prior key exchange */
             if (strcmp(s->hostkey_str, s->keystr)) {
 #ifndef FUZZING
                 ssh_sw_abort(s->ppl.ssh,
                              "Host key was different in repeat key exchange");
+                *aborted = true;
                 return;
 #endif
             }

+ 30 - 25
source/putty/ssh2transport.c

@@ -39,13 +39,13 @@ static void ssh_decomp_none_cleanup(ssh_decompressor *handle)
 {
 }
 static void ssh_comp_none_block(ssh_compressor *handle,
-                                unsigned char *block, int len,
+                                const unsigned char *block, int len,
                                 unsigned char **outblock, int *outlen,
                                 int minlen)
 {
 }
 static bool ssh_decomp_none_block(ssh_decompressor *handle,
-                                  unsigned char *block, int len,
+                                  const unsigned char *block, int len,
                                   unsigned char **outblock, int *outlen)
 {
     return false;
@@ -344,7 +344,7 @@ bool ssh2_common_filter_queue(PacketProtocolLayer *ppl)
             /* XXX maybe we should actually take notice of the return value */
             get_bool(pktin);
             msg = get_string(pktin);
-            ppl_logevent(("Remote debug message: %.*s", PTRLEN_PRINTF(msg)));
+            ppl_logevent("Remote debug message: %.*s", PTRLEN_PRINTF(msg));
             pq_pop(ppl->in_pq);
             break;
 
@@ -940,11 +940,14 @@ static bool ssh2_scan_kexinits(
          */
         *n_server_hostkeys = 0;
 
-        for (i = 0; i < lenof(ssh2_hostkey_algs); i++)
-            if (in_commasep_string(ssh2_hostkey_algs[i].alg->ssh_id,
-                                   slists[KEXLIST_HOSTKEY].ptr,
-                                   slists[KEXLIST_HOSTKEY].len))
-                server_hostkeys[(*n_server_hostkeys)++] = i;
+        ptrlen list = slists[KEXLIST_HOSTKEY];
+        for (ptrlen word; get_commasep_word(&list, &word) ;) {
+            for (i = 0; i < lenof(ssh2_hostkey_algs); i++)
+                if (ptrlen_eq_string(word, ssh2_hostkey_algs[i].alg->ssh_id)) {
+                    server_hostkeys[(*n_server_hostkeys)++] = i;
+                    break;
+                }
+        }
     }
 
     return true;
@@ -958,7 +961,7 @@ void ssh2transport_finalise_exhash(struct ssh2_transport_state *s)
     s->exhash = NULL;
 
 #if 0
-    debug(("Exchange hash is:\n"));
+    debug("Exchange hash is:\n");
     dmemdump(s->exchange_hash, s->kex_alg->hash->hlen);
 #endif
 }
@@ -1233,9 +1236,12 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
     put_string(s->exhash, s->server_kexinit->u, s->server_kexinit->len);
     s->crStateKex = 0;
     while (1) {
-        ssh2kex_coroutine(s);
+        bool aborted = false;
+        ssh2kex_coroutine(s, &aborted);
+        if (aborted)
+            return;    /* disaster: our entire state has been freed */
         if (!s->crStateKex)
-            break;
+            break;     /* kex phase has terminated normally */
         crReturnV;
     }
 
@@ -1372,7 +1378,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
      * deferred rekey reason.
      */
     if (s->deferred_rekey_reason) {
-        ppl_logevent(("%s", s->deferred_rekey_reason));
+        ppl_logevent("%s", s->deferred_rekey_reason);
         pktin = NULL;
         s->deferred_rekey_reason = NULL;
         goto begin_key_exchange;
@@ -1459,7 +1465,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
                 return;
             }
             pq_push_front(s->ppl.in_pq, pktin);
-            ppl_logevent(("Remote side initiated key re-exchange"));
+            ppl_logevent("Remote side initiated key re-exchange");
             s->rekey_class = RK_SERVER;
         }
 
@@ -1504,8 +1510,8 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
              * rekey, we process it anyway!)
              */
             if ((s->ppl.remote_bugs & BUG_SSH2_REKEY)) {
-                ppl_logevent(("Remote bug prevents key re-exchange (%s)",
-                              s->rekey_reason));
+                ppl_logevent("Remote bug prevents key re-exchange (%s)",
+                             s->rekey_reason);
                 /* Reset the counters, so that at least this message doesn't
                  * hit the event log _too_ often. */
                 s->stats->in.running = s->stats->out.running = true;
@@ -1514,8 +1520,8 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
                 (void) ssh2_transport_timer_update(s, 0);
                 s->rekey_class = RK_NONE;
             } else {
-                ppl_logevent(("Initiating key re-exchange (%s)",
-                              s->rekey_reason));
+                ppl_logevent("Initiating key re-exchange (%s)",
+                             s->rekey_reason);
             }
         }
     } while (s->rekey_class == RK_NONE);
@@ -1691,11 +1697,11 @@ static void ssh2_transport_gss_update(struct ssh2_transport_state *s,
             s->shgss->lib, s->fullhostname, &s->shgss->srv_name);
         if (gss_stat != SSH_GSS_OK) {
             if (gss_stat == SSH_GSS_BAD_HOST_NAME)
-                ppl_logevent(("GSSAPI import name failed - Bad service name;"
-                              " won't use GSS key exchange"));
+                ppl_logevent("GSSAPI import name failed - Bad service name;"
+                             " won't use GSS key exchange");
             else
-                ppl_logevent(("GSSAPI import name failed;"
-                              " won't use GSS key exchange"));
+                ppl_logevent("GSSAPI import name failed;"
+                             " won't use GSS key exchange");
             return;
         }
     }
@@ -1737,7 +1743,7 @@ static void ssh2_transport_gss_update(struct ssh2_transport_state *s,
          * it shouldn't pop up all the time regardless.
          */
         if (definitely_rekeying)
-            ppl_logevent(("No GSSAPI security context available"));
+            ppl_logevent("No GSSAPI security context available");
 
         return;
     }
@@ -1803,7 +1809,7 @@ static bool ssh2_transport_get_specials(
     struct ssh2_transport_state *s =
         container_of(ppl, struct ssh2_transport_state, ppl);
     bool need_separator = false;
-    bool toret;
+    bool toret = false;
 
     if (ssh_ppl_get_specials(s->higher_layer, add_special, ctx)) {
         need_separator = true;
@@ -1856,8 +1862,7 @@ static void ssh2_transport_special_cmd(PacketProtocolLayer *ppl,
 	}
     } else if (code == SS_XCERT) {
 	if (!s->kex_in_progress) {
-            s->hostkey_alg = ssh2_hostkey_algs[arg].alg;
-            s->cross_certifying = true;
+            s->cross_certifying = s->hostkey_alg = ssh2_hostkey_algs[arg].alg;
             s->rekey_reason = "cross-certifying new host key";
             s->rekey_class = RK_NORMAL;
             queue_idempotent_callback(&s->ppl.ic_process_queue);

+ 10 - 5
source/putty/ssh2transport.h

@@ -204,10 +204,12 @@ struct ssh2_transport_state {
     int n_uncert_hostkeys;
 
     /*
-     * Flag indicating that the current rekey is intended to finish
-     * with a newly cross-certified host key.
+     * Indicate that the current rekey is intended to finish with a
+     * newly cross-certified host key. To double-check that we
+     * certified the right one, we set this to point to the host key
+     * algorithm we expect it to be.
      */
-    bool cross_certifying;
+    const ssh_keyalg *cross_certifying;
 
     ssh_key *const *hostkeys;
     int nhostkeys;
@@ -222,7 +224,10 @@ void ssh2_transport_dialog_callback(void *, int);
 /* Provided by transport for use in kex */
 void ssh2transport_finalise_exhash(struct ssh2_transport_state *s);
 
-/* Provided by kex for use in transport */
-void ssh2kex_coroutine(struct ssh2_transport_state *s);
+/* Provided by kex for use in transport. Must set the 'aborted' flag
+ * if it throws a connection-terminating error, so that the caller
+ * won't have to check that by looking inside its state parameter
+ * which might already have been freed. */
+void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted);
 
 #endif /* PUTTY_SSH2TRANSPORT_H */

+ 144 - 112
source/putty/ssh2userauth.c

@@ -53,6 +53,8 @@ struct ssh2_userauth_state {
     Ssh_gss_buf gss_rcvtok, gss_sndtok;
     Ssh_gss_stat gss_stat;
 #endif
+    bool suppress_wait_for_response_packet;
+    strbuf *last_methods_string;
     bool kbd_inter_refused;
     prompts_t *cur_prompt;
     int num_prompts;
@@ -135,6 +137,7 @@ PacketProtocolLayer *ssh2_userauth_new(
     s->try_gssapi_kex_auth = try_gssapi_kex_auth;
     s->gssapi_fwd = gssapi_fwd;
     s->shgss = shgss;
+    s->last_methods_string = strbuf_new();
     bufchain_init(&s->banner);
 
     return &s->ppl;
@@ -164,6 +167,7 @@ static void ssh2_userauth_free(PacketProtocolLayer *ppl)
     sfree(s->default_username);
     sfree(s->hostname);
     sfree(s->fullhostname);
+    strbuf_free(s->last_methods_string);
     sfree(s);
 }
 
@@ -221,8 +225,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
      */
     if (!filename_is_null(s->keyfile)) {
         int keytype;
-        ppl_logevent(("Reading key file \"%.150s\"",
-                      filename_to_str(s->keyfile)));
+        ppl_logevent("Reading key file \"%s\"",
+                     filename_to_str(s->keyfile));
         keytype = key_type(s->keyfile);
         if (keytype == SSH_KEYTYPE_SSH2 ||
             keytype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 ||
@@ -235,22 +239,22 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                                      &s->publickey_comment, &error)) {
                 s->privatekey_available = (keytype == SSH_KEYTYPE_SSH2);
                 if (!s->privatekey_available)
-                    ppl_logevent(("Key file contains public key only"));
+                    ppl_logevent("Key file contains public key only");
                 s->privatekey_encrypted =
                     ssh2_userkey_encrypted(s->keyfile, NULL);
             } else {
-                ppl_logevent(("Unable to load key (%s)", error));
-                ppl_printf(("Unable to load key file \"%s\" (%s)\r\n",
-                            filename_to_str(s->keyfile), error));
+                ppl_logevent("Unable to load key (%s)", error);
+                ppl_printf("Unable to load key file \"%s\" (%s)\r\n",
+                           filename_to_str(s->keyfile), error);
                 strbuf_free(s->publickey_blob);
                 s->publickey_blob = NULL;
             }
         } else {
-            ppl_logevent(("Unable to use this key file (%s)",
-                          key_type_to_str(keytype)));
-            ppl_printf(("Unable to use key file \"%s\" (%s)\r\n",
-                        filename_to_str(s->keyfile),
-                        key_type_to_str(keytype)));
+            ppl_logevent("Unable to use this key file (%s)",
+                         key_type_to_str(keytype));
+            ppl_printf("Unable to use key file \"%s\" (%s)\r\n",
+                       filename_to_str(s->keyfile),
+                       key_type_to_str(keytype));
             s->publickey_blob = NULL;
         }
     }
@@ -262,7 +266,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
     s->nkeys = 0;
     s->pkblob_pos_in_agent = 0;
     if (s->tryagent && agent_exists()) {
-        ppl_logevent(("Pageant is running. Requesting keys."));
+        ppl_logevent("Pageant is running. Requesting keys.");
 
         /* Request the keys held by the agent. */
         {
@@ -286,12 +290,12 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
              * and blob lengths make sense.
              */
             if (s->nkeys < 0) {
-                ppl_logevent(("Pageant response contained a negative"
-                              " key count %d", s->nkeys));
+                ppl_logevent("Pageant response contained a negative"
+                             " key count %d", s->nkeys);
                 s->nkeys = 0;
                 goto done_agent_query;
             } else {
-                ppl_logevent(("Pageant has %d SSH-2 keys", s->nkeys));
+                ppl_logevent("Pageant has %d SSH-2 keys", s->nkeys);
 
                 /* See if configured key is in agent. */
                 for (keyi = 0; keyi < s->nkeys; keyi++) {
@@ -299,7 +303,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     ptrlen blob = get_string(s->asrc);
                     get_string(s->asrc); /* skip comment */
                     if (get_err(s->asrc)) {
-                        ppl_logevent(("Pageant response was truncated"));
+                        ppl_logevent("Pageant response was truncated");
                         s->nkeys = 0;
                         goto done_agent_query;
                     }
@@ -308,20 +312,20 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         blob.len == s->publickey_blob->len &&
                         !memcmp(blob.ptr, s->publickey_blob->s,
                                 s->publickey_blob->len)) {
-                        ppl_logevent(("Pageant key #%d matches "
-                                      "configured key file", keyi));
+                        ppl_logevent("Pageant key #%d matches "
+                                     "configured key file", keyi);
                         s->keyi = keyi;
                         s->pkblob_pos_in_agent = pos;
                         break;
                     }
                 }
                 if (s->publickey_blob && !s->pkblob_pos_in_agent) {
-                    ppl_logevent(("Configured key file not in Pageant"));
+                    ppl_logevent("Configured key file not in Pageant");
                     s->nkeys = 0;
                 }
             }
         } else {
-            ppl_logevent(("Failed to get reply from Pageant"));
+            ppl_logevent("Failed to get reply from Pageant");
         }
       done_agent_query:;
     }
@@ -394,7 +398,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
             free_prompts(s->cur_prompt);
         } else {
             if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE))
-                ppl_printf(("Using username \"%s\".\r\n", s->username));
+                ppl_printf("Using username \"%s\".\r\n", s->username);
         }
         s->got_username = true;
 
@@ -427,15 +431,17 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
         }
 
         while (1) {
-            ptrlen methods;
-
-            methods.ptr = "";
-            methods.len = 0;
-
             /*
-             * Wait for the result of the last authentication request.
+             * Wait for the result of the last authentication request,
+             * unless the request terminated for some reason on our
+             * own side.
              */
-            crMaybeWaitUntilV((pktin = ssh2_userauth_pop(s)) != NULL);
+            if (s->suppress_wait_for_response_packet) {
+                pktin = NULL;
+                s->suppress_wait_for_response_packet = false;
+            } else {
+                crMaybeWaitUntilV((pktin = ssh2_userauth_pop(s)) != NULL);
+            }
 
             /*
              * Now is a convenient point to spew any banner material
@@ -468,12 +474,12 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 }
                 bufchain_clear(&s->banner);
             }
-            if (pktin->type == SSH2_MSG_USERAUTH_SUCCESS) {
-                ppl_logevent(("Access granted"));
+            if (pktin && pktin->type == SSH2_MSG_USERAUTH_SUCCESS) {
+                ppl_logevent("Access granted");
                 goto userauth_success;
             }
 
-            if (pktin->type != SSH2_MSG_USERAUTH_FAILURE &&
+            if (pktin && pktin->type != SSH2_MSG_USERAUTH_FAILURE &&
                 s->type != AUTH_TYPE_GSSAPI) {
                 ssh_proto_error(s->ppl.ssh, "Received unexpected packet "
                                 "in response to authentication request, "
@@ -489,9 +495,11 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
              * we can look at the string in it and know what we can
              * helpfully try next.
              */
-            if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
-                methods = get_string(pktin);
-                if (!get_bool(pktin)) {
+            if (pktin && pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
+                ptrlen methods = get_string(pktin);
+                bool partial_success = get_bool(pktin);
+
+                if (!partial_success) {
                     /*
                      * We have received an unequivocal Access
                      * Denied. This can translate to a variety of
@@ -520,32 +528,32 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     } else if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD ||
                                s->type == AUTH_TYPE_PUBLICKEY_OFFER_QUIET) {
                         if (s->type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD)
-                            ppl_printf(("Server refused our key\r\n"));
-                        ppl_logevent(("Server refused our key"));
+                            ppl_printf("Server refused our key\r\n");
+                        ppl_logevent("Server refused our key");
                     } else if (s->type == AUTH_TYPE_PUBLICKEY) {
                         /* This _shouldn't_ happen except by a
                          * protocol bug causing client and server to
                          * disagree on what is a correct signature. */
-                        ppl_printf(("Server refused public-key signature"
-                                    " despite accepting key!\r\n"));
-                        ppl_logevent(("Server refused public-key signature"
-                                      " despite accepting key!"));
+                        ppl_printf("Server refused public-key signature"
+                                   " despite accepting key!\r\n");
+                        ppl_logevent("Server refused public-key signature"
+                                     " despite accepting key!");
                     } else if (s->type==AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET) {
                         /* quiet, so no ppl_printf */
-                        ppl_logevent(("Server refused keyboard-interactive "
-                                      "authentication"));
+                        ppl_logevent("Server refused keyboard-interactive "
+                                     "authentication");
                     } else if (s->type==AUTH_TYPE_GSSAPI) {
                         /* always quiet, so no ppl_printf */
                         /* also, the code down in the GSSAPI block has
                          * already logged this in the Event Log */
                     } else if (s->type == AUTH_TYPE_KEYBOARD_INTERACTIVE) {
-                        ppl_logevent(("Keyboard-interactive authentication "
-                                      "failed"));
-                        ppl_printf(("Access denied\r\n"));
+                        ppl_logevent("Keyboard-interactive authentication "
+                                     "failed");
+                        ppl_printf("Access denied\r\n");
                     } else {
                         assert(s->type == AUTH_TYPE_PASSWORD);
-                        ppl_logevent(("Password authentication failed"));
-                        ppl_printf(("Access denied\r\n"));
+                        ppl_logevent("Password authentication failed");
+                        ppl_printf("Access denied\r\n");
 
                         if (s->change_username) {
                             /* XXX perhaps we should allow
@@ -554,30 +562,49 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         }
                     }
                 } else {
-                    ppl_printf(("Further authentication required\r\n"));
-                    ppl_logevent(("Further authentication required"));
+                    ppl_printf("Further authentication required\r\n");
+                    ppl_logevent("Further authentication required");
                 }
 
-                s->can_pubkey =
-                    in_commasep_string("publickey", methods.ptr, methods.len);
-                s->can_passwd =
-                    in_commasep_string("password", methods.ptr, methods.len);
-                s->can_keyb_inter =
-                    s->try_ki_auth &&
-                    in_commasep_string("keyboard-interactive",
-                                       methods.ptr, methods.len);
+                /*
+                 * Save the methods string for use in error messages.
+                 */
+                s->last_methods_string->len = 0;
+                put_data(s->last_methods_string, methods.ptr, methods.len);
+
+                /*
+                 * Scan it for method identifiers we know about.
+                 */
+                bool srv_pubkey = false, srv_passwd = false;
+                bool srv_keyb_inter = false, srv_gssapi = false;
+                bool srv_gssapi_keyex_auth = false;
+
+                for (ptrlen method; get_commasep_word(&methods, &method) ;) {
+                    if (ptrlen_eq_string(method, "publickey"))
+                        srv_pubkey = true;
+                    else if (ptrlen_eq_string(method, "password"))
+                        srv_passwd = true;
+                    else if (ptrlen_eq_string(method, "keyboard-interactive"))
+                        srv_keyb_inter = true;
+                    else if (ptrlen_eq_string(method, "gssapi-with-mic"))
+                        srv_gssapi = true;
+                    else if (ptrlen_eq_string(method, "gssapi-keyex"))
+                        srv_gssapi_keyex_auth = true;
+                }
+
+                /*
+                 * And combine those flags with our own configuration
+                 * and context to set the main can_foo variables.
+                 */
+                s->can_pubkey = srv_pubkey;
+                s->can_passwd = srv_passwd;
+                s->can_keyb_inter = s->try_ki_auth && srv_keyb_inter;
 #ifndef NO_GSSAPI
-                s->can_gssapi =
-                    s->try_gssapi_auth &&
-                    in_commasep_string("gssapi-with-mic",
-                                       methods.ptr, methods.len) &&
+                s->can_gssapi = s->try_gssapi_auth && srv_gssapi &&
                     s->shgss->libs->nlibraries > 0;
-                s->can_gssapi_keyex_auth =
-                    s->try_gssapi_kex_auth &&
-                    in_commasep_string("gssapi-keyex",
-                                       methods.ptr, methods.len) &&
-                    s->shgss->libs->nlibraries > 0 &&
-                    s->shgss->ctx;
+                s->can_gssapi_keyex_auth = s->try_gssapi_kex_auth &&
+                    srv_gssapi_keyex_auth &&
+                    s->shgss->libs->nlibraries > 0 && s->shgss->ctx;
 #endif
             }
 
@@ -593,9 +620,9 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 s->ppl.bpp->pls->actx = SSH2_PKTCTX_GSSAPI;
 
                 if (s->shgss->lib->gsslogmsg)
-                    ppl_logevent(("%s", s->shgss->lib->gsslogmsg));
+                    ppl_logevent("%s", s->shgss->lib->gsslogmsg);
 
-                ppl_logevent(("Trying gssapi-keyex..."));
+                ppl_logevent("Trying gssapi-keyex...");
                 s->pktout = ssh2_userauth_gss_packet(s, "gssapi-keyex");
                 pq_push(s->ppl.out_pq, s->pktout);
                 s->shgss->lib->release_cred(s->shgss->lib, &s->shgss->ctx);
@@ -613,7 +640,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
 
                 s->ppl.bpp->pls->actx = SSH2_PKTCTX_PUBLICKEY;
 
-                ppl_logevent(("Trying Pageant key #%d", s->keyi));
+                ppl_logevent("Trying Pageant key #%d", s->keyi);
 
                 /* Unpack key from agent response */
                 s->pk = get_string(s->asrc);
@@ -648,9 +675,9 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     strbuf *agentreq, *sigdata;
 
                     if (flags & FLAG_VERBOSE)
-                        ppl_printf(("Authenticating with public key "
-                                    "\"%.*s\" from agent\r\n",
-                                    PTRLEN_PRINTF(s->comment)));
+                        ppl_printf("Authenticating with public key "
+                                   "\"%.*s\" from agent\r\n",
+                                   PTRLEN_PRINTF(s->comment));
 
                     /*
                      * Server is willing to accept the key.
@@ -690,7 +717,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         get_uint32(src); /* skip length field */
                         if (get_byte(src) == SSH2_AGENT_SIGN_RESPONSE &&
                             (sigblob = get_string(src), !get_err(src))) {
-                            ppl_logevent(("Sending Pageant's response"));
+                            ppl_logevent("Sending Pageant's response");
                             ssh2_userauth_add_sigblob(s, s->pktout,
                                                       s->pk, sigblob);
                             pq_push(s->ppl.out_pq, s->pktout);
@@ -741,7 +768,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 put_string(s->pktout, s->publickey_blob->s,
                            s->publickey_blob->len);
                 pq_push(s->ppl.out_pq, s->pktout);
-                ppl_logevent(("Offered public key"));
+                ppl_logevent("Offered public key");
 
                 crMaybeWaitUntilV((pktin = ssh2_userauth_pop(s)) != NULL);
                 if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
@@ -750,15 +777,15 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     s->type = AUTH_TYPE_PUBLICKEY_OFFER_LOUD;
                     continue; /* process this new message */
                 }
-                ppl_logevent(("Offer of public key accepted"));
+                ppl_logevent("Offer of public key accepted");
 
                 /*
                  * Actually attempt a serious authentication using
                  * the key.
                  */
                 if (flags & FLAG_VERBOSE)
-                    ppl_printf(("Authenticating with public key \"%s\"\r\n",
-                                s->publickey_comment));
+                    ppl_printf("Authenticating with public key \"%s\"\r\n",
+                               s->publickey_comment);
 
                 key = NULL;
                 while (!key) {
@@ -771,7 +798,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         s->cur_prompt->to_server = false;
                         s->cur_prompt->name = dupstr("SSH key passphrase");
                         add_prompt(s->cur_prompt,
-                                   dupprintf("Passphrase for key \"%.100s\": ",
+                                   dupprintf("Passphrase for key \"%s\": ",
                                              s->publickey_comment),
                                    false);
                         s->userpass_ret = seat_get_userpass_input(
@@ -819,12 +846,12 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
                         if (passphrase &&
                             (key == SSH2_WRONG_PASSPHRASE)) {
-                            ppl_printf(("Wrong passphrase\r\n"));
+                            ppl_printf("Wrong passphrase\r\n");
                             key = NULL;
                             /* and loop again */
                         } else {
-                            ppl_printf(("Unable to load private key (%s)\r\n",
-                                        error));
+                            ppl_printf("Unable to load private key (%s)\r\n",
+                                       error);
                             key = NULL;
                             break; /* try something else */
                         }
@@ -873,7 +900,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     strbuf_free(sigblob);
 
                     pq_push(s->ppl.out_pq, s->pktout);
-                    ppl_logevent(("Sent public key signature"));
+                    ppl_logevent("Sent public key signature");
                     s->type = AUTH_TYPE_PUBLICKEY;
                     ssh_key_free(key->key);
                     sfree(key->comment);
@@ -892,16 +919,16 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 s->ppl.bpp->pls->actx = SSH2_PKTCTX_GSSAPI;
 
                 if (s->shgss->lib->gsslogmsg)
-                    ppl_logevent(("%s", s->shgss->lib->gsslogmsg));
+                    ppl_logevent("%s", s->shgss->lib->gsslogmsg);
 
                 /* Sending USERAUTH_REQUEST with "gssapi-with-mic" method */
-                ppl_logevent(("Trying gssapi-with-mic..."));
+                ppl_logevent("Trying gssapi-with-mic...");
                 s->pktout = ssh_bpp_new_pktout(
                     s->ppl.bpp, SSH2_MSG_USERAUTH_REQUEST);
                 put_stringz(s->pktout, s->username);
                 put_stringz(s->pktout, s->successor_layer->vt->name);
                 put_stringz(s->pktout, "gssapi-with-mic");
-                ppl_logevent(("Attempting GSSAPI authentication"));
+                ppl_logevent("Attempting GSSAPI authentication");
 
                 /* add mechanism info */
                 s->shgss->lib->indicate_mech(s->shgss->lib, &s->gss_buf);
@@ -920,7 +947,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 pq_push(s->ppl.out_pq, s->pktout);
                 crMaybeWaitUntilV((pktin = ssh2_userauth_pop(s)) != NULL);
                 if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) {
-                    ppl_logevent(("GSSAPI authentication request refused"));
+                    ppl_logevent("GSSAPI authentication request refused");
                     pq_push_front(s->ppl.in_pq, pktin);
                     continue;
                 }
@@ -935,8 +962,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     ((char *)s->gss_rcvtok.value)[1] != s->gss_buf.length ||
                     memcmp((char *)s->gss_rcvtok.value + 2,
                            s->gss_buf.value,s->gss_buf.length) ) {
-                    ppl_logevent(("GSSAPI authentication - wrong response "
-                                  "from server"));
+                    ppl_logevent("GSSAPI authentication - wrong response "
+                                 "from server");
                     continue;
                 }
 
@@ -946,10 +973,10 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         s->shgss->lib, s->fullhostname, &s->shgss->srv_name);
                     if (s->gss_stat != SSH_GSS_OK) {
                         if (s->gss_stat == SSH_GSS_BAD_HOST_NAME)
-                            ppl_logevent(("GSSAPI import name failed -"
-                                          " Bad service name"));
+                            ppl_logevent("GSSAPI import name failed -"
+                                         " Bad service name");
                         else
-                            ppl_logevent(("GSSAPI import name failed"));
+                            ppl_logevent("GSSAPI import name failed");
                         continue;
                     }
                 }
@@ -958,8 +985,13 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 s->gss_stat = s->shgss->lib->acquire_cred(
                     s->shgss->lib, &s->shgss->ctx, NULL);
                 if (s->gss_stat != SSH_GSS_OK) {
-                    ppl_logevent(("GSSAPI authentication failed to get "
-                                  "credentials"));
+                    ppl_logevent("GSSAPI authentication failed to get "
+                                 "credentials");
+                    /* The failure was on our side, so the server
+                     * won't be sending a response packet indicating
+                     * failure. Avoid waiting for it next time round
+                     * the loop. */
+                    s->suppress_wait_for_response_packet = true;
                     continue;
                 }
 
@@ -985,19 +1017,19 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
 
                     if (s->gss_stat!=SSH_GSS_S_COMPLETE &&
                         s->gss_stat!=SSH_GSS_S_CONTINUE_NEEDED) {
-                        ppl_logevent(("GSSAPI authentication initialisation "
-                                      "failed"));
+                        ppl_logevent("GSSAPI authentication initialisation "
+                                     "failed");
 
                         if (s->shgss->lib->display_status(s->shgss->lib,
                                 s->shgss->ctx, &s->gss_buf) == SSH_GSS_OK) {
-                            ppl_logevent(("%s", (char *)s->gss_buf.value));
+                            ppl_logevent("%s", (char *)s->gss_buf.value);
                             sfree(s->gss_buf.value);
                         }
 
                         pq_push_front(s->ppl.in_pq, pktin);
                         break;
                     }
-                    ppl_logevent(("GSSAPI authentication initialised"));
+                    ppl_logevent("GSSAPI authentication initialised");
 
                     /*
                      * Client and server now exchange tokens until GSSAPI
@@ -1044,14 +1076,14 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                         }
 
                         if (pktin->type == SSH2_MSG_USERAUTH_FAILURE) {
-                            ppl_logevent(("GSSAPI authentication failed"));
+                            ppl_logevent("GSSAPI authentication failed");
                             s->gss_stat = SSH_GSS_FAILURE;
                             pq_push_front(s->ppl.in_pq, pktin);
                             break;
                         } else if (pktin->type !=
                                    SSH2_MSG_USERAUTH_GSSAPI_TOKEN) {
-                            ppl_logevent(("GSSAPI authentication -"
-                                          " bad server response"));
+                            ppl_logevent("GSSAPI authentication -"
+                                         " bad server response");
                             s->gss_stat = SSH_GSS_FAILURE;
                             break;
                         }
@@ -1065,7 +1097,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     s->shgss->lib->release_cred(s->shgss->lib, &s->shgss->ctx);
                     continue;
                 }
-                ppl_logevent(("GSSAPI authentication loop finished OK"));
+                ppl_logevent("GSSAPI authentication loop finished OK");
 
                 /* Now send the MIC */
 
@@ -1095,7 +1127,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 put_stringz(s->pktout, "");     /* submethods */
                 pq_push(s->ppl.out_pq, s->pktout);
                 
-                ppl_logevent(("Attempting keyboard-interactive authentication"));
+                ppl_logevent("Attempting keyboard-interactive authentication");
 
                 crMaybeWaitUntilV((pktin = ssh2_userauth_pop(s)) != NULL);
                 if (pktin->type != SSH2_MSG_USERAUTH_INFO_REQUEST) {
@@ -1310,7 +1342,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                 put_stringz(s->pktout, s->password);
                 s->pktout->minlen = 256;
                 pq_push(s->ppl.out_pq, s->pktout);
-                ppl_logevent(("Sent password"));
+                ppl_logevent("Sent password");
                 s->type = AUTH_TYPE_PASSWORD;
 
                 /*
@@ -1337,8 +1369,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                             msg = "Server requested password change";
                         else
                             msg = "Server rejected new password";
-                        ppl_logevent(("%s", msg));
-                        ppl_printf(("%s\r\n", msg));
+                        ppl_logevent("%s", msg);
+                        ppl_printf("%s\r\n", msg);
                     }
 
                     prompt = get_string(pktin);
@@ -1428,7 +1460,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                                    == 0);
                         if (!got_new)
                             /* They don't. Silly user. */
-                            ppl_printf(("Passwords do not match\r\n"));
+                            ppl_printf("Passwords do not match\r\n");
 
                     }
 
@@ -1448,7 +1480,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     free_prompts(s->cur_prompt);
                     s->pktout->minlen = 256;
                     pq_push(s->ppl.out_pq, s->pktout);
-                    ppl_logevent(("Sent new password"));
+                    ppl_logevent("Sent new password");
                     
                     /*
                      * Now see what the server has to say about it.
@@ -1488,8 +1520,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
                     "No supported authentication methods available",
                     SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE);
                 ssh_sw_abort(s->ppl.ssh, "No supported authentication methods "
-                             "available (server sent: %.*s)",
-                             PTRLEN_PRINTF(methods));
+                             "available (server sent: %s)",
+                             s->last_methods_string->s);
                 return;
             }
 
@@ -1603,8 +1635,8 @@ static void ssh2_userauth_add_sigblob(
             mod_mp.ptr = (const char *)mod_mp.ptr + 1;
         }
 
-	/* debug(("modulus length is %d\n", len)); */
-	/* debug(("signature length is %d\n", siglen)); */
+	/* debug("modulus length is %d\n", len); */
+	/* debug("signature length is %d\n", siglen); */
 
 	if (mod_mp.len != sig_mp.len) {
             strbuf *substr = strbuf_new();

+ 3 - 5
source/putty/sshaes.c

@@ -1520,20 +1520,18 @@ static void aes_encrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
 FUNC_ISA
 static void aes_decrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
 {
-    __m128i dec = _mm_setzero_si128();
-    __m128i last, iv;
     __m128i* block = (__m128i*)blk;
     const __m128i* finish = (__m128i*)(blk + len);
 
     assert((len & 15) == 0);
 
     /* Load IV */
-    iv = _mm_loadu_si128((__m128i*)(ctx->iv));
+    __m128i iv = _mm_loadu_si128((__m128i*)(ctx->iv));
     while (block < finish) {
         /* Key schedule ptr   */
         __m128i* keysched = (__m128i*)ctx->invkeysched;
-        last = _mm_loadu_si128(block);
-        dec  = _mm_xor_si128(last, *keysched);
+        __m128i last = _mm_loadu_si128(block);
+        __m128i dec = _mm_xor_si128(last, *keysched);
         switch (ctx->Nr) {
           case 14:
             dec = _mm_aesdec_si128(dec, *(++keysched));

+ 4 - 5
source/putty/sshbn.c

@@ -1938,20 +1938,19 @@ void diagbn(char *prefix, Bignum md)
     int i, nibbles, morenibbles;
     static const char hex[] = "0123456789ABCDEF";
 
-    debug(("%s0x", prefix ? prefix : ""));
+    debug("%s0x", prefix ? prefix : "");
 
     nibbles = (3 + bignum_bitcount(md)) / 4;
     if (nibbles < 1)
 	nibbles = 1;
     morenibbles = 4 * md[0] - nibbles;
     for (i = 0; i < morenibbles; i++)
-	debug(("-"));
+	debug("-");
     for (i = nibbles; i--;)
-	debug(("%c",
-	       hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF]));
+        debug("%c", hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF]);
 
     if (prefix)
-	debug(("\n"));
+	debug("\n");
 }
 #endif
 

+ 3 - 5
source/putty/sshbpp.h

@@ -71,11 +71,9 @@ void ssh2_bpp_queue_disconnect(BinaryPacketProtocol *bpp,
 bool ssh2_bpp_check_unimplemented(BinaryPacketProtocol *bpp, PktIn *pktin);
 
 /* Convenience macro for BPPs to send formatted strings to the Event
- * Log. Assumes a function parameter called 'bpp' is in scope, and
- * takes a double pair of parens because it passes a whole argument
- * list to dupprintf. */
-#define bpp_logevent(params) ( \
-        logevent_and_free((bpp)->logctx, dupprintf params))
+ * Log. Assumes a function parameter called 'bpp' is in scope. */
+#define bpp_logevent(...) ( \
+    logevent_and_free((bpp)->logctx, dupprintf(__VA_ARGS__)))
 
 /*
  * Structure that tracks how much data is sent and received, for

+ 1 - 40
source/putty/sshcommon.c

@@ -687,45 +687,6 @@ unsigned alloc_channel_id_general(tree234 *channels, size_t localid_offset)
  * lists of protocol identifiers in SSH-2.
  */
 
-bool first_in_commasep_string(char const *needle, char const *haystack,
-                              int haylen)
-{
-    int needlen;
-    if (!needle || !haystack)          /* protect against null pointers */
-        return false;
-    needlen = strlen(needle);
-
-    if (haylen >= needlen &&       /* haystack is long enough */
-        !memcmp(needle, haystack, needlen) &&   /* initial match */
-        (haylen == needlen || haystack[needlen] == ',')
-        /* either , or EOS follows */
-        )
-        return true;
-    return false;
-}
-
-bool in_commasep_string(char const *needle, char const *haystack, int haylen)
-{
-    char *p;
-
-    if (!needle || !haystack)          /* protect against null pointers */
-        return false;
-    /*
-     * Is it at the start of the string?
-     */
-    if (first_in_commasep_string(needle, haystack, haylen))
-        return true;
-    /*
-     * If not, search for the next comma and resume after that.
-     * If no comma found, terminate.
-     */
-    p = memchr(haystack, ',', haylen);
-    if (!p)
-        return false;
-    /* + 1 to skip over comma */
-    return in_commasep_string(needle, p + 1, haylen - (p + 1 - haystack));
-}
-
 void add_to_commasep(strbuf *buf, const char *data)
 {
     if (buf->len > 0)
@@ -1025,7 +986,7 @@ bool ssh1_common_filter_queue(PacketProtocolLayer *ppl)
 
           case SSH1_MSG_DEBUG:
             msg = get_string(pktin);
-            ppl_logevent(("Remote debug message: %.*s", PTRLEN_PRINTF(msg)));
+            ppl_logevent("Remote debug message: %.*s", PTRLEN_PRINTF(msg));
             pq_pop(ppl->in_pq);
             break;
 

+ 1 - 0
source/putty/sshcrcda.c

@@ -149,6 +149,7 @@ bool detect_attack(
         for (i = HASH(c) & (ctx->n - 1); ctx->h[i] != HASH_UNUSED;
              i = (i + 1) & (ctx->n - 1)) {
             if (ctx->h[i] == HASH_IV) {
+                assert(IV); /* or we wouldn't have stored HASH_IV above */
                 if (!CMP(c, IV)) {
                     if (check_crc(c, buf, len, IV))
                         return true;      /* attack detected */

+ 21 - 42
source/putty/sshdss.c

@@ -54,54 +54,33 @@ static void dss_freekey(ssh_key *key)
     sfree(dss);
 }
 
+static void append_hex_to_strbuf(strbuf *sb, Bignum *x)
+{
+    if (sb->len > 0)
+        put_byte(sb, ',');
+    put_data(sb, "0x", 2);
+    int nibbles = (3 + bignum_bitcount(x)) / 4;
+    if (nibbles < 1)
+	nibbles = 1;
+    static const char hex[] = "0123456789abcdef";
+    for (int i = nibbles; i--;)
+	put_byte(sb, hex[(bignum_byte(x, i / 2) >> (4 * (i % 2))) & 0xF]);
+}
+
 static char *dss_cache_str(ssh_key *key)
 {
     struct dss_key *dss = container_of(key, struct dss_key, sshk);
-    char *p;
-    int len, i, pos, nibbles;
-    static const char hex[] = "0123456789abcdef";
+    strbuf *sb = strbuf_new();
+
     if (!dss->p)
 	return NULL;
-    len = 8 + 4 + 1;		       /* 4 x "0x", punctuation, \0 */
-    len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
-    len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
-    len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
-    len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
-    p = snewn(len, char);
-    if (!p)
-	return NULL;
 
-    pos = 0;
-    pos += sprintf(p + pos, "0x");
-    nibbles = (3 + bignum_bitcount(dss->p)) / 4;
-    if (nibbles < 1)
-	nibbles = 1;
-    for (i = nibbles; i--;)
-	p[pos++] =
-	    hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
-    pos += sprintf(p + pos, ",0x");
-    nibbles = (3 + bignum_bitcount(dss->q)) / 4;
-    if (nibbles < 1)
-	nibbles = 1;
-    for (i = nibbles; i--;)
-	p[pos++] =
-	    hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
-    pos += sprintf(p + pos, ",0x");
-    nibbles = (3 + bignum_bitcount(dss->g)) / 4;
-    if (nibbles < 1)
-	nibbles = 1;
-    for (i = nibbles; i--;)
-	p[pos++] =
-	    hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF];
-    pos += sprintf(p + pos, ",0x");
-    nibbles = (3 + bignum_bitcount(dss->y)) / 4;
-    if (nibbles < 1)
-	nibbles = 1;
-    for (i = nibbles; i--;)
-	p[pos++] =
-	    hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF];
-    p[pos] = '\0';
-    return p;
+    append_hex_to_strbuf(sb, dss->p);
+    append_hex_to_strbuf(sb, dss->q);
+    append_hex_to_strbuf(sb, dss->g);
+    append_hex_to_strbuf(sb, dss->y);
+
+    return strbuf_to_str(sb);
 }
 
 static bool dss_verify(ssh_key *key, ptrlen sig, ptrlen data)

+ 6 - 8
source/putty/sshppl.h

@@ -118,16 +118,14 @@ void ssh2_userauth_set_transport_layer(PacketProtocolLayer *userauth,
 
 /* Convenience macro for protocol layers to send formatted strings to
  * the Event Log. Assumes a function parameter called 'ppl' is in
- * scope, and takes a double pair of parens because it passes a whole
- * argument list to dupprintf. */
-#define ppl_logevent(params) ( \
-        logevent_and_free((ppl)->logctx, dupprintf params))
+ * scope. */
+#define ppl_logevent(...) ( \
+        logevent_and_free((ppl)->logctx, dupprintf(__VA_ARGS__)))
 
 /* Convenience macro for protocol layers to send formatted strings to
- * the terminal. Also expects 'ppl' to be in scope and takes double
- * parens. */
-#define ppl_printf(params) \
-    ssh_ppl_user_output_string_and_free(ppl, dupprintf params)
+ * the terminal. Also expects 'ppl' to be in scope. */
+#define ppl_printf(...) \
+    ssh_ppl_user_output_string_and_free(ppl, dupprintf(__VA_ARGS__))
 void ssh_ppl_user_output_string_and_free(PacketProtocolLayer *ppl, char *text);
 
 /* Methods for userauth to communicate back to the transport layer */

+ 94 - 101
source/putty/sshrsa.c

@@ -321,44 +321,27 @@ bool rsa_ssh1_decrypt_pkcs1(Bignum input, struct RSAKey *key, strbuf *outbuf)
     return success;
 }
 
-int rsastr_len(struct RSAKey *key)
+static void append_hex_to_strbuf(strbuf *sb, Bignum *x)
 {
-    Bignum md, ex;
-    int mdlen, exlen;
-
-    md = key->modulus;
-    ex = key->exponent;
-    mdlen = (bignum_bitcount(md) + 15) / 16;
-    exlen = (bignum_bitcount(ex) + 15) / 16;
-    return 4 * (mdlen + exlen) + 20;
-}
-
-void rsastr_fmt(char *str, struct RSAKey *key)
-{
-    Bignum md, ex;
-    int len = 0, i, nibbles;
-    static const char hex[] = "0123456789abcdef";
-
-    md = key->modulus;
-    ex = key->exponent;
-
-    len += sprintf(str + len, "0x");
-
-    nibbles = (3 + bignum_bitcount(ex)) / 4;
+    if (sb->len > 0)
+        put_byte(sb, ',');
+    put_data(sb, "0x", 2);
+    int nibbles = (3 + bignum_bitcount(x)) / 4;
     if (nibbles < 1)
 	nibbles = 1;
-    for (i = nibbles; i--;)
-	str[len++] = hex[(bignum_byte(ex, i / 2) >> (4 * (i % 2))) & 0xF];
+    static const char hex[] = "0123456789abcdef";
+    for (int i = nibbles; i--;)
+	put_byte(sb, hex[(bignum_byte(x, i / 2) >> (4 * (i % 2))) & 0xF]);
+}
 
-    len += sprintf(str + len, ",0x");
+char *rsastr_fmt(struct RSAKey *key)
+{
+    strbuf *sb = strbuf_new();
 
-    nibbles = (3 + bignum_bitcount(md)) / 4;
-    if (nibbles < 1)
-	nibbles = 1;
-    for (i = nibbles; i--;)
-	str[len++] = hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF];
+    append_hex_to_strbuf(sb, key->exponent);
+    append_hex_to_strbuf(sb, key->modulus);
 
-    str[len] = '\0';
+    return strbuf_to_str(sb);
 }
 
 /*
@@ -486,22 +469,41 @@ int rsa_ssh1_public_blob_len(void *data, int maxlen)
     return src->pos;
 }
 
-void freersakey(struct RSAKey *key)
+void freersapriv(struct RSAKey *key)
 {
-    if (key->modulus)
-	freebn(key->modulus);
-    if (key->exponent)
-	freebn(key->exponent);
-    if (key->private_exponent)
+    if (key->private_exponent) {
 	freebn(key->private_exponent);
-    if (key->p)
+        key->private_exponent = NULL;
+    }
+    if (key->p) {
 	freebn(key->p);
-    if (key->q)
+        key->p = NULL;
+    }
+    if (key->q) {
 	freebn(key->q);
-    if (key->iqmp)
+        key->q = NULL;
+    }
+    if (key->iqmp) {
 	freebn(key->iqmp);
-    if (key->comment)
+        key->iqmp = NULL;
+    }
+}
+
+void freersakey(struct RSAKey *key)
+{
+    freersapriv(key);
+    if (key->modulus) {
+	freebn(key->modulus);
+        key->modulus = NULL;
+    }
+    if (key->exponent) {
+	freebn(key->exponent);
+        key->exponent = NULL;
+    }
+    if (key->comment) {
 	sfree(key->comment);
+        key->comment = NULL;
+    }
 }
 
 /* ----------------------------------------------------------------------
@@ -545,13 +547,7 @@ static void rsa2_freekey(ssh_key *key)
 static char *rsa2_cache_str(ssh_key *key)
 {
     struct RSAKey *rsa = container_of(key, struct RSAKey, sshk);
-    char *p;
-    int len;
-
-    len = rsastr_len(rsa);
-    p = snewn(len, char);
-    rsastr_fmt(p, rsa);
-    return p;
+    return rsastr_fmt(rsa);
 }
 
 static void rsa2_public_blob(ssh_key *key, BinarySink *bs)
@@ -699,15 +695,51 @@ static const unsigned char sha512_asn1_prefix[] = {
 
 #define SHA1_ASN1_PREFIX_LEN sizeof(sha1_asn1_prefix)
 
+static unsigned char *rsa_pkcs1_signature_string(
+    size_t nbytes, const struct ssh_hashalg *halg, ptrlen data)
+{
+    const unsigned char *asn1_prefix;
+    unsigned asn1_prefix_size;
+
+    if (halg == &ssh_sha256) {
+        asn1_prefix = sha256_asn1_prefix;
+        asn1_prefix_size = sizeof(sha256_asn1_prefix);
+    } else if (halg == &ssh_sha512) {
+        asn1_prefix = sha512_asn1_prefix;
+        asn1_prefix_size = sizeof(sha512_asn1_prefix);
+    } else {
+        assert(halg == &ssh_sha1);
+        asn1_prefix = sha1_asn1_prefix;
+        asn1_prefix_size = sizeof(sha1_asn1_prefix);
+    }
+
+    size_t fixed_parts = halg->hlen + asn1_prefix_size + 2;
+    assert(nbytes >= fixed_parts);
+    size_t padding = nbytes - fixed_parts;
+
+    unsigned char *bytes = snewn(nbytes, unsigned char);
+
+    bytes[0] = 0;
+    bytes[1] = 1;
+
+    memset(bytes + 2, 0xFF, padding);
+
+    memcpy(bytes + 2 + padding, asn1_prefix, asn1_prefix_size);
+
+    ssh_hash *h = ssh_hash_new(halg);
+    put_data(h, data.ptr, data.len);
+    ssh_hash_final(h, bytes + 2 + padding + asn1_prefix_size);
+
+    return bytes;
+}
+
 static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data)
 {
     struct RSAKey *rsa = container_of(key, struct RSAKey, sshk);
     BinarySource src[1];
     ptrlen type, in_pl;
     Bignum in, out;
-    int bytes, i, j;
     bool toret;
-    unsigned char hash[20];
 
     BinarySource_BARE_INIT(src, sig.ptr, sig.len);
     type = get_string(src);
@@ -731,29 +763,13 @@ static bool rsa2_verify(ssh_key *key, ptrlen sig, ptrlen data)
 
     toret = true;
 
-    bytes = (bignum_bitcount(rsa->modulus)+7) / 8;
-    /* Top (partial) byte should be zero. */
-    if (bignum_byte(out, bytes - 1) != 0)
-	toret = false;
-    /* First whole byte should be 1. */
-    if (bignum_byte(out, bytes - 2) != 1)
-	toret = false;
-    /* Most of the rest should be FF. */
-    for (i = bytes - 3; i >= 20 + SHA1_ASN1_PREFIX_LEN; i--) {
-	if (bignum_byte(out, i) != 0xFF)
-	    toret = false;
-    }
-    /* Then we expect to see the sha1_asn1_prefix. */
-    for (i = 20 + SHA1_ASN1_PREFIX_LEN - 1, j = 0; i >= 20; i--, j++) {
-	if (bignum_byte(out, i) != sha1_asn1_prefix[j])
-	    toret = false;
-    }
-    /* Finally, we expect to see the SHA-1 hash of the signed data. */
-    SHA_Simple(data.ptr, data.len, hash);
-    for (i = 19, j = 0; i >= 0; i--, j++) {
-	if (bignum_byte(out, i) != hash[j])
+    size_t nbytes = (bignum_bitcount(rsa->modulus) + 7) / 8;
+    unsigned char *bytes = rsa_pkcs1_signature_string(nbytes, &ssh_sha1, data);
+    for (size_t i = 0; i < nbytes; i++)
+	if (bytes[nbytes-1 - i] != bignum_byte(out, i))
 	    toret = false;
-    }
+    smemclr(bytes, nbytes);
+    sfree(bytes);
     freebn(out);
 
     return toret;
@@ -765,50 +781,27 @@ static void rsa2_sign(ssh_key *key, const void *data, int datalen,
     struct RSAKey *rsa = container_of(key, struct RSAKey, sshk);
     unsigned char *bytes;
     int nbytes;
-    unsigned char hash[64];
     Bignum in, out;
-    int i, j;
     const struct ssh_hashalg *halg;
-    ssh_hash *h;
-    const unsigned char *asn1_prefix;
-    unsigned asn1_prefix_size;
     const char *sign_alg_name;
 
     if (flags & SSH_AGENT_RSA_SHA2_256) {
         halg = &ssh_sha256;
-        asn1_prefix = sha256_asn1_prefix;
-        asn1_prefix_size = sizeof(sha256_asn1_prefix);
         sign_alg_name = "rsa-sha2-256";
     } else if (flags & SSH_AGENT_RSA_SHA2_512) {
         halg = &ssh_sha512;
-        asn1_prefix = sha512_asn1_prefix;
-        asn1_prefix_size = sizeof(sha512_asn1_prefix);
         sign_alg_name = "rsa-sha2-512";
     } else {
         halg = &ssh_sha1;
-        asn1_prefix = sha1_asn1_prefix;
-        asn1_prefix_size = sizeof(sha1_asn1_prefix);
         sign_alg_name = "ssh-rsa";
     }
 
-    h = ssh_hash_new(halg);
-    put_data(h, data, datalen);
-    ssh_hash_final(h, hash);
-
-    nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
-    assert(1 <= nbytes - halg->hlen - asn1_prefix_size);
-    bytes = snewn(nbytes, unsigned char);
-
-    bytes[0] = 1;
-    for (i = 1; i < nbytes - halg->hlen - asn1_prefix_size; i++)
-	bytes[i] = 0xFF;
-    for (i = nbytes - halg->hlen - asn1_prefix_size, j = 0;
-         i < nbytes - halg->hlen; i++, j++)
-	bytes[i] = asn1_prefix[j];
-    for (i = nbytes - halg->hlen, j = 0; i < nbytes; i++, j++)
-	bytes[i] = hash[j];
+    nbytes = (bignum_bitcount(rsa->modulus) + 7) / 8;
 
+    bytes = rsa_pkcs1_signature_string(
+        nbytes, halg, make_ptrlen(data, datalen));
     in = bignum_from_bytes(bytes, nbytes);
+    smemclr(bytes, nbytes);
     sfree(bytes);
 
     out = rsa_privkey_op(in, rsa);
@@ -817,7 +810,7 @@ static void rsa2_sign(ssh_key *key, const void *data, int datalen,
     put_stringz(bs, sign_alg_name);
     nbytes = (bignum_bitcount(out) + 7) / 8;
     put_uint32(bs, nbytes);
-    for (i = 0; i < nbytes; i++)
+    for (size_t i = 0; i < nbytes; i++)
 	put_byte(bs, bignum_byte(out, nbytes - 1 - i));
 
     freebn(out);

+ 30 - 29
source/putty/sshverstring.c

@@ -201,16 +201,17 @@ static void ssh_verstring_send(struct ssh_verstring_state *s)
         bufchain_add(s->bpp.out_raw, "\015", 1);
     bufchain_add(s->bpp.out_raw, "\012", 1);
 
-    bpp_logevent(("We claim version: %s", s->our_vstring));
+    bpp_logevent("We claim version: %s", s->our_vstring);
 }
 
 #define BPP_WAITFOR(minlen) do                          \
-    {                                                   \
-        crMaybeWaitUntilV(                              \
-            s->bpp.input_eof ||                         \
-            bufchain_size(s->bpp.in_raw) >= (minlen));  \
-        if (s->bpp.input_eof)                           \
-            goto eof;                                   \
+    {                                                                   \
+        bool success;                                                   \
+        crMaybeWaitUntilV(                                              \
+            (success = (bufchain_size(s->bpp.in_raw) >= (minlen))) ||   \
+            s->bpp.input_eof);                                          \
+        if (!success)                                                   \
+            goto eof;                                                   \
     } while (0)
 
 void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
@@ -284,7 +285,7 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
         void *data;
         char *nl;
 
-        crMaybeWaitUntilV(bufchain_size(s->bpp.in_raw) > 0);
+        BPP_WAITFOR(1);
         bufchain_prefix(s->bpp.in_raw, &data, &len);
         if ((nl = memchr(data, '\012', len)) != NULL) {
             len = nl - (char *)data + 1;
@@ -311,7 +312,7 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
         s->vslen--;
     s->vstring[s->vslen] = '\0';
 
-    bpp_logevent(("Remote version: %s", s->vstring));
+    bpp_logevent("Remote version: %s", s->vstring);
 
     /*
      * Pick out the protocol version and software version. The former
@@ -377,7 +378,7 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
         crStopV;
     }
 
-    bpp_logevent(("Using SSH protocol version %d", s->major_protoversion));
+    bpp_logevent("Using SSH protocol version %d", s->major_protoversion);
 
     if (!s->send_early) {
         /*
@@ -449,7 +450,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * sniffing.
          */
         s->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
-        bpp_logevent(("We believe remote version has SSH-1 ignore bug"));
+        bpp_logevent("We believe remote version has SSH-1 ignore bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_plainpw1) == FORCE_ON ||
@@ -461,8 +462,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * the password.
          */
         s->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
-        bpp_logevent(("We believe remote version needs a "
-                      "plain SSH-1 password"));
+        bpp_logevent("We believe remote version needs a "
+                     "plain SSH-1 password");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_rsa1) == FORCE_ON ||
@@ -474,8 +475,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * an AUTH_RSA message.
          */
         s->remote_bugs |= BUG_CHOKES_ON_RSA;
-        bpp_logevent(("We believe remote version can't handle SSH-1 "
-                      "RSA authentication"));
+        bpp_logevent("We believe remote version can't handle SSH-1 "
+                     "RSA authentication");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_hmac2) == FORCE_ON ||
@@ -488,7 +489,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * These versions have the HMAC bug.
          */
         s->remote_bugs |= BUG_SSH2_HMAC;
-        bpp_logevent(("We believe remote version has SSH-2 HMAC bug"));
+        bpp_logevent("We believe remote version has SSH-2 HMAC bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_derivekey2) == FORCE_ON ||
@@ -501,8 +502,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * generate the keys).
          */
         s->remote_bugs |= BUG_SSH2_DERIVEKEY;
-        bpp_logevent(("We believe remote version has SSH-2 "
-                      "key-derivation bug"));
+        bpp_logevent("We believe remote version has SSH-2 "
+                     "key-derivation bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
@@ -515,7 +516,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * These versions have the SSH-2 RSA padding bug.
          */
         s->remote_bugs |= BUG_SSH2_RSA_PADDING;
-        bpp_logevent(("We believe remote version has SSH-2 RSA padding bug"));
+        bpp_logevent("We believe remote version has SSH-2 RSA padding bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_pksessid2) == FORCE_ON ||
@@ -526,8 +527,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * public-key authentication.
          */
         s->remote_bugs |= BUG_SSH2_PK_SESSIONID;
-        bpp_logevent(("We believe remote version has SSH-2 "
-                      "public-key-session-ID bug"));
+        bpp_logevent("We believe remote version has SSH-2 "
+                     "public-key-session-ID bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_rekey2) == FORCE_ON ||
@@ -543,7 +544,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * These versions have the SSH-2 rekey bug.
          */
         s->remote_bugs |= BUG_SSH2_REKEY;
-        bpp_logevent(("We believe remote version has SSH-2 rekey bug"));
+        bpp_logevent("We believe remote version has SSH-2 rekey bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_maxpkt2) == FORCE_ON ||
@@ -554,8 +555,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * This version ignores our makpkt and needs to be throttled.
          */
         s->remote_bugs |= BUG_SSH2_MAXPKT;
-        bpp_logevent(("We believe remote version ignores SSH-2 "
-                      "maximum packet size"));
+        bpp_logevent("We believe remote version ignores SSH-2 "
+                     "maximum packet size");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_ignore2) == FORCE_ON) {
@@ -564,7 +565,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * none detected automatically.
          */
         s->remote_bugs |= BUG_CHOKES_ON_SSH2_IGNORE;
-        bpp_logevent(("We believe remote version has SSH-2 ignore bug"));
+        bpp_logevent("We believe remote version has SSH-2 ignore bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
@@ -576,7 +577,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * we use the newer version.
          */
         s->remote_bugs |= BUG_SSH2_OLDGEX;
-        bpp_logevent(("We believe remote version has outdated SSH-2 GEX"));
+        bpp_logevent("We believe remote version has outdated SSH-2 GEX");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_winadj) == FORCE_ON) {
@@ -585,7 +586,7 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * reason or another. Currently, none detected automatically.
          */
         s->remote_bugs |= BUG_CHOKES_ON_WINADJ;
-        bpp_logevent(("We believe remote version has winadj bug"));
+        bpp_logevent("We believe remote version has winadj bug");
     }
 
     if (conf_get_int(s->conf, CONF_sshbug_chanreq) == FORCE_ON ||
@@ -602,8 +603,8 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
          * https://secure.ucc.asn.au/hg/dropbear/rev/cd02449b709c
          */
         s->remote_bugs |= BUG_SENDS_LATE_REQUEST_REPLY;
-        bpp_logevent(("We believe remote version has SSH-2 "
-                      "channel request bug"));
+        bpp_logevent("We believe remote version has SSH-2 "
+                     "channel request bug");
     }
 }
 

+ 9 - 114
source/putty/sshzlib.c

@@ -42,30 +42,7 @@
 #include <assert.h>
 
 #include "defs.h"
-
-#ifdef ZLIB_STANDALONE
-
-/*
- * This module also makes a handy zlib decoding tool for when
- * you're picking apart Zip files or PDFs or PNGs. If you compile
- * it with ZLIB_STANDALONE defined, it builds on its own and
- * becomes a command-line utility.
- * 
- * Therefore, here I provide a self-contained implementation of the
- * macros required from the rest of the PuTTY sources.
- */
-#define snew(type) ( (type *) malloc(sizeof(type)) )
-#define snewn(n, type) ( (type *) malloc((n) * sizeof(type)) )
-#define sresize(x, n, type) ( (type *) realloc((x), (n) * sizeof(type)) )
-#define sfree(x) ( free((x)) )
-
-typedef struct { const struct dummy *vt; } ssh_compressor;
-typedef struct { const struct dummy *vt; } ssh_decompressor;
-static const struct dummy { int i; } ssh_zlib;
-
-#else
 #include "ssh.h"
-#endif
 
 /* ----------------------------------------------------------------------
  * Basic LZ77 code. This bit is designed modularly, so it could be
@@ -94,7 +71,7 @@ static int lz77_init(struct LZ77Context *ctx);
  * instead call literal() for everything.
  */
 static void lz77_compress(struct LZ77Context *ctx,
-			  unsigned char *data, int len, bool compress);
+			  const unsigned char *data, int len);
 
 /*
  * Modifiable parameters.
@@ -136,7 +113,7 @@ struct LZ77InternalContext {
     int npending;
 };
 
-static int lz77_hash(unsigned char *data)
+static int lz77_hash(const unsigned char *data)
 {
     return (257 * data[0] + 263 * data[1] + 269 * data[2]) % HASHMAX;
 }
@@ -199,7 +176,7 @@ static void lz77_advance(struct LZ77InternalContext *st,
 #define CHARAT(k) ( (k)<0 ? st->data[(st->winpos+k)&(WINSIZE-1)] : data[k] )
 
 static void lz77_compress(struct LZ77Context *ctx,
-			  unsigned char *data, int len, bool compress)
+			  const unsigned char *data, int len)
 {
     struct LZ77InternalContext *st = ctx->ictx;
     int i, distance, off, nmatch, matchlen, advance;
@@ -238,8 +215,7 @@ static void lz77_compress(struct LZ77Context *ctx,
     deferchr = '\0';
     while (len > 0) {
 
-	/* Don't even look for a match, if we're not compressing. */
-	if (compress && len >= HASHCHARS) {
+	if (len >= HASHCHARS) {
 	    /*
 	     * Hash the next few characters.
 	     */
@@ -629,7 +605,8 @@ void zlib_compress_cleanup(ssh_compressor *sc)
     sfree(comp);
 }
 
-void zlib_compress_block(ssh_compressor *sc, unsigned char *block, int len,
+void zlib_compress_block(ssh_compressor *sc,
+                         const unsigned char *block, int len,
                          unsigned char **outblock, int *outlen,
                          int minlen)
 {
@@ -667,7 +644,7 @@ void zlib_compress_block(ssh_compressor *sc, unsigned char *block, int len,
     /*
      * Do the compression.
      */
-    lz77_compress(&comp->ectx, block, len, true);
+    lz77_compress(&comp->ectx, block, len);
 
     /*
      * End the block (by transmitting code 256, which is
@@ -967,7 +944,8 @@ static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
 
 #define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )
 
-bool zlib_decompress_block(ssh_decompressor *dc, unsigned char *block, int len,
+bool zlib_decompress_block(ssh_decompressor *dc,
+                           const unsigned char *block, int len,
                            unsigned char **outblock, int *outlen)
 {
     struct zlib_decompress_ctx *dctx =
@@ -1218,87 +1196,6 @@ bool zlib_decompress_block(ssh_decompressor *dc, unsigned char *block, int len,
     return false;
 }
 
-#ifdef ZLIB_STANDALONE
-
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
-    unsigned char buf[16], *outbuf;
-    int ret, outlen;
-    ssh_decompressor *handle;
-    int noheader = false, opts = true;
-    char *filename = NULL;
-    FILE *fp;
-
-    while (--argc) {
-        char *p = *++argv;
-
-        if (p[0] == '-' && opts) {
-            if (!strcmp(p, "-d"))
-                noheader = true;
-            else if (!strcmp(p, "--"))
-                opts = false;          /* next thing is filename */
-            else {
-                fprintf(stderr, "unknown command line option '%s'\n", p);
-                return 1;
-            }
-        } else if (!filename) {
-            filename = p;
-        } else {
-            fprintf(stderr, "can only handle one filename\n");
-            return 1;
-        }
-    }
-
-    handle = zlib_decompress_init();
-
-    if (noheader) {
-        /*
-         * Provide missing zlib header if -d was specified.
-         */
-        zlib_decompress_block(handle, "\x78\x9C", 2, &outbuf, &outlen);
-        assert(outlen == 0);
-    }
-
-    if (filename)
-        fp = fopen(filename, "rb");
-    else
-        fp = stdin;
-
-    if (!fp) {
-        assert(filename);
-        fprintf(stderr, "unable to open '%s'\n", filename);
-        return 1;
-    }
-
-    while (1) {
-	ret = fread(buf, 1, sizeof(buf), fp);
-	if (ret <= 0)
-	    break;
-	zlib_decompress_block(handle, buf, ret, &outbuf, &outlen);
-        if (outbuf) {
-            if (outlen)
-                fwrite(outbuf, 1, outlen, stdout);
-            sfree(outbuf);
-        } else {
-            fprintf(stderr, "decoding error\n");
-            fclose(fp);
-            return 1;
-        }
-    }
-
-    zlib_decompress_cleanup(handle);
-
-    if (filename)
-        fclose(fp);
-
-    return 0;
-}
-
-#else
-
 const struct ssh_compression_alg ssh_zlib = {
     "zlib",
     "[email protected]", /* delayed version */
@@ -1310,5 +1207,3 @@ const struct ssh_compression_alg ssh_zlib = {
     zlib_decompress_block,
     "zlib (RFC1950)"
 };
-
-#endif

+ 2 - 5
source/putty/tree234.c

@@ -639,13 +639,10 @@ void search234_step(search234_state *state, int direction)
         assert(direction);
         assert(node);
 
-        if (direction > 0) {
+        if (direction > 0)
             state->_lo = state->_last + 1;
-            direction = +1;
-        } else {
+        else
             state->_hi = state->_last - 1;
-            direction = -1;
-        }
 
         if (state->_lo > state->_hi) {
             /*

+ 11 - 0
source/putty/windows/winstuff.h

@@ -693,4 +693,15 @@ char *get_jumplist_registry_entries(void);
 #define CLIPUI_DEFAULT_MOUSE CLIPUI_EXPLICIT
 #define CLIPUI_DEFAULT_INS CLIPUI_EXPLICIT
 
+#ifdef MINEFIELD
+/*
+ * Definitions for Minefield, PuTTY's own Windows-specific malloc
+ * debugger in the style of Electric Fence. Implemented in winmisc.c,
+ * and referred to by the main malloc wrappers in memory.c.
+ */
+void *minefield_c_malloc(size_t size);
+void minefield_c_free(void *p);
+void *minefield_c_realloc(void *p, size_t size);
+#endif
+
 #endif

+ 5 - 5
source/putty/x11fwd.c

@@ -540,7 +540,7 @@ void x11_get_auth_from_authfile(struct X11Display *disp,
         family = get_uint16(src);
         addr = get_string_xauth(src);
         displaynum_string = mkstr(get_string_xauth(src));
-        displaynum = atoi(displaynum_string);
+        displaynum = displaynum_string[0] ? atoi(displaynum_string) : -1;
         sfree(displaynum_string);
         protoname = get_string_xauth(src);
         data = get_string_xauth(src);
@@ -570,9 +570,8 @@ void x11_get_auth_from_authfile(struct X11Display *disp,
 	 *    authority entries for Unix-domain displays on
 	 *    several machines without them clashing).
 	 * 
-	 *  - 'displaynum' is the display number. I've no idea why
-	 *    .Xauthority stores this as a string when it has a
-	 *    perfectly good integer format, but there we go.
+	 *  - 'displaynum' is the display number. An empty display
+	 *    number is a wildcard for any display number.
 	 * 
 	 *  - 'protoname' is the authorisation protocol, encoded as
 	 *    its canonical string name (i.e. "MIT-MAGIC-COOKIE-1",
@@ -582,7 +581,8 @@ void x11_get_auth_from_authfile(struct X11Display *disp,
 	 *    binary form.
 	 */
 
-	if (disp->displaynum < 0 || disp->displaynum != displaynum)
+	if (disp->displaynum < 0 ||
+	    (displaynum >= 0 && disp->displaynum != displaynum))
 	    continue;		       /* not the one */
 
 	for (protocol = 1; protocol < lenof(x11_authnames); protocol++)