Module Name:    src
Committed By:   tls
Date:           Fri Apr 27 15:45:37 UTC 2012

Modified Files:
        src/crypto/external/bsd/openssh/dist: readconf.c readconf.h
            sshconnect.c

Log Message:
Add new "SendVersionFirst" option to OpenSSH client.  This option makes
the client send its version string first if it is configured to speak
v2 only (the old hack of waiting to see the server version is only
really useful if you might be speaking v1 to some servers).  The option
is on by default but can be disabled from the config file.

This aligns the OpenSSH client behavior with most other implementations
and eliminates a major source of connection delays and failures when
speaking SSH through particularly stupid proxies, of which, sadly, there
are many.

This change has also been submitted to OpenSSH as their bug #1999.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/crypto/external/bsd/openssh/dist/readconf.c \
    src/crypto/external/bsd/openssh/dist/readconf.h \
    src/crypto/external/bsd/openssh/dist/sshconnect.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/crypto/external/bsd/openssh/dist/readconf.c
diff -u src/crypto/external/bsd/openssh/dist/readconf.c:1.6 src/crypto/external/bsd/openssh/dist/readconf.c:1.7
--- src/crypto/external/bsd/openssh/dist/readconf.c:1.6	Wed Sep  7 17:49:19 2011
+++ src/crypto/external/bsd/openssh/dist/readconf.c	Fri Apr 27 15:45:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: readconf.c,v 1.6 2011/09/07 17:49:19 christos Exp $	*/
+/*	$NetBSD: readconf.c,v 1.7 2012/04/27 15:45:37 tls Exp $	*/
 /* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <y...@cs.hut.fi>
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-__RCSID("$NetBSD: readconf.c,v 1.6 2011/09/07 17:49:19 christos Exp $");
+__RCSID("$NetBSD: readconf.c,v 1.7 2012/04/27 15:45:37 tls Exp $");
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -147,6 +147,7 @@ typedef enum {
 	oKexAlgorithms, oIPQoS, oRequestTTY,
 	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
 	oHPNBufferSize,
+	oSendVersionFirst,
 	oDeprecated, oUnsupported
 } OpCodes;
 
@@ -272,6 +273,7 @@ static struct {
 	{ "noneswitch", oNoneSwitch },
 	{ "hpndisabled", oHPNDisabled },
 	{ "hpnbuffersize", oHPNBufferSize },
+	{ "sendversionfirst", oSendVersionFirst },
 
 	{ NULL, oBadOption }
 };
@@ -1123,6 +1125,10 @@ parse_int:
 			*intptr = value;
 		break;
 
+	case oSendVersionFirst:
+		intptr = &options->send_version_first;
+		goto parse_flag;
+
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1297,6 +1303,7 @@ initialize_options(Options * options)
 	options->hpn_buffer_size = -1;
 	options->tcp_rcv_buf_poll = -1;
 	options->tcp_rcv_buf = -1;
+	options->send_version_first = -1;
 }
 
 /*
@@ -1495,6 +1502,8 @@ fill_default_options(Options * options)
 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
 	if (options->request_tty == -1)
 		options->request_tty = REQUEST_TTY_AUTO;
+	if (options->send_version_first == -1)
+		options->send_version_first = 1;
 	/* options->local_command should not be set by default */
 	/* options->proxy_command should not be set by default */
 	/* options->user will be set in the main program if appropriate */
Index: src/crypto/external/bsd/openssh/dist/readconf.h
diff -u src/crypto/external/bsd/openssh/dist/readconf.h:1.6 src/crypto/external/bsd/openssh/dist/readconf.h:1.7
--- src/crypto/external/bsd/openssh/dist/readconf.h:1.6	Wed Sep  7 17:49:19 2011
+++ src/crypto/external/bsd/openssh/dist/readconf.h	Fri Apr 27 15:45:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: readconf.h,v 1.6 2011/09/07 17:49:19 christos Exp $	*/
+/*	$NetBSD: readconf.h,v 1.7 2012/04/27 15:45:37 tls Exp $	*/
 /* $OpenBSD: readconf.h,v 1.90 2011/05/24 07:15:47 djm Exp $ */
 
 /*
@@ -151,6 +151,7 @@ typedef struct {
 	int	use_roaming;
 
 	int	request_tty;
+	int	send_version_first;
 }       Options;
 
 #define SSHCTL_MASTER_NO	0
Index: src/crypto/external/bsd/openssh/dist/sshconnect.c
diff -u src/crypto/external/bsd/openssh/dist/sshconnect.c:1.6 src/crypto/external/bsd/openssh/dist/sshconnect.c:1.7
--- src/crypto/external/bsd/openssh/dist/sshconnect.c:1.6	Wed Sep  7 17:49:19 2011
+++ src/crypto/external/bsd/openssh/dist/sshconnect.c	Fri Apr 27 15:45:37 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: sshconnect.c,v 1.6 2011/09/07 17:49:19 christos Exp $	*/
+/*	$NetBSD: sshconnect.c,v 1.7 2012/04/27 15:45:37 tls Exp $	*/
 /* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <y...@cs.hut.fi>
@@ -15,7 +15,7 @@
  */
 
 #include "includes.h"
-__RCSID("$NetBSD: sshconnect.c,v 1.6 2011/09/07 17:49:19 christos Exp $");
+__RCSID("$NetBSD: sshconnect.c,v 1.7 2012/04/27 15:45:37 tls Exp $");
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/wait.h>
@@ -474,6 +474,7 @@ ssh_exchange_identification(int timeout_
 	int connection_in = packet_get_connection_in();
 	int connection_out = packet_get_connection_out();
 	int minor1 = PROTOCOL_MINOR_1;
+	int mefirst = 0;
 	u_int i, n;
 	size_t len;
 	int fdsetsz, remaining, rc;
@@ -483,6 +484,32 @@ ssh_exchange_identification(int timeout_
 	fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
 	fdset = xcalloc(1, fdsetsz);
 
+	/*
+	 * If we are configured to do version 2 only, we can send our
+	 * own version string first in order to work around borken
+	 * proxies that elsewise impose a delay while trying to figure
+	 * out what protocol we are speaking.
+	 */
+
+	if (options.send_version_first == 1 && 
+	    ((options.protocol & SSH_PROTO_2) &&
+	    !(options.protocol & SSH_PROTO_1) &&
+	    !(options.protocol & SSH_PROTO_1_PREFERRED))) {
+
+        	/* Send our own protocol version identification. */
+		snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
+			 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
+			 SSH_VERSION, "\r\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);
+		debug("Local version string %.100s", client_version_string);
+
+		mefirst = 1;
+	}
+
 	/* Read other side's version identification. */
 	remaining = timeout_ms;
 	for (n = 0;;) {
@@ -585,16 +612,18 @@ ssh_exchange_identification(int timeout_
 		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_RELEASE, 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 (!mefirst) {
+		/* 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_RELEASE, 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);
+	}
 	chop(server_version_string);
 	debug("Local version string %.100s", client_version_string);
 }

Reply via email to