- djm@cvs.openbsd.org 2012/08/17 01:30:00
     [compat.c sshconnect.c]
     Send client banner immediately, rather than waiting for the server to
     move first for SSH protocol 2 connections (the default). Patch based on
     one in bz#1999 by tls AT panix.com, feedback dtucker@ ok markus@
diff --git a/sshconnect.c b/sshconnect.c
index 0ee7266..3d44b2e 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.235 2012/08/17 01:30:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -429,6 +429,26 @@
 	return 0;
 }
 
+static void
+send_client_banner(int connection_out, int minor1)
+{
+	char buf[256];
+
+	/* Send our own protocol version identification. */
+	if (compat20) {
+		xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
+		    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
+	} else {
+		xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n",
+		    PROTOCOL_MAJOR_1, minor1, SSH_VERSION);
+	}
+	if (roaming_atomicio(vwrite, connection_out, client_version_string,
+	    strlen(client_version_string)) != strlen(client_version_string))
+		fatal("write: %.100s", strerror(errno));
+	chop(client_version_string);
+	debug("Local version string %.100s", client_version_string);
+}
+
 /*
  * Waits for the server identification string, and sends our own
  * identification string.
@@ -440,7 +460,7 @@
 	int remote_major, remote_minor, mismatch;
 	int connection_in = packet_get_connection_in();
 	int connection_out = packet_get_connection_out();
-	int minor1 = PROTOCOL_MINOR_1;
+	int minor1 = PROTOCOL_MINOR_1, client_banner_sent = 0;
 	u_int i, n;
 	size_t len;
 	int fdsetsz, remaining, rc;
@@ -450,6 +470,16 @@
 	fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
 	fdset = xcalloc(1, fdsetsz);
 
+	/*
+	 * If we are SSH2-only then we can send the banner immediately and
+	 * save a round-trip.
+	 */
+	if (options.protocol == SSH_PROTO_2) {
+		enable_compat20();
+		send_client_banner(connection_out, 0);
+		client_banner_sent = 1;
+	}
+
 	/* Read other side's version identification. */
 	remaining = timeout_ms;
 	for (n = 0;;) {
@@ -552,18 +582,9 @@
 		fatal("Protocol major versions differ: %d vs. %d",
 		    (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
 		    remote_major);
-	/* Send our own protocol version identification. */
-	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
-	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
-	    compat20 ? PROTOCOL_MINOR_2 : minor1,
-	    SSH_VERSION, compat20 ? "\r\n" : "\n");
-	if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
-	    != strlen(buf))
-		fatal("write: %.100s", strerror(errno));
-	client_version_string = xstrdup(buf);
-	chop(client_version_string);
+	if (!client_banner_sent)
+		send_client_banner(connection_out, minor1);
 	chop(server_version_string);
-	debug("Local version string %.100s", client_version_string);
 }
 
 /* defaults to 'no' */