[openssh-commits] [openssh] 03/04: upstream: Introduce a transport-level ping facility

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Aug 28 13:34:43 AEST 2023


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit dce6d80d2ed3cad2c516082682d5f6ca877ef714
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Mon Aug 28 03:28:43 2023 +0000

    upstream: Introduce a transport-level ping facility
    
    This adds a pair of SSH transport protocol messages SSH2_MSG_PING/PONG
    to implement a ping capability. These messages use numbers in the "local
    extensions" number space and are advertised using a "ping at openssh.com"
    ext-info message with a string version number of "0".
    
    ok markus@
    
    OpenBSD-Commit-ID: b6b3c4cb2084c62f85a8dc67cf74954015eb547f
---
 PROTOCOL | 35 ++++++++++++++++++++++++++++++++++-
 kex.c    | 47 ++++++++++++++++++++++++++++++++++-------------
 kex.h    |  3 ++-
 packet.c | 23 +++++++++++++++++++++--
 ssh2.h   |  6 +++++-
 5 files changed, 96 insertions(+), 18 deletions(-)

diff --git a/PROTOCOL b/PROTOCOL
index 27804d0c..d453c779 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -104,6 +104,39 @@ http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.o
 
 This is identical to curve25519-sha256 as later published in RFC8731.
 
+1.9 transport: ping facility
+
+OpenSSH implements a transport level ping message SSH2_MSG_PING
+and a corresponding SSH2_MSG_PONG reply.
+
+#define SSH2_MSG_PING	192
+#define SSH2_MSG_PONG	193
+
+The ping message is simply:
+
+	byte		SSH_MSG_PING
+	string		data
+
+The reply copies the data (which may be the empty string) from the
+ping:
+
+	byte		SSH_MSG_PONG
+	string		data
+
+Replies are sent in order. They are sent immediately except when rekeying
+is in progress, in which case they are queued until rekeying completes.
+
+The server advertises support for these messages using the
+SSH2_MSG_EXT_INFO mechanism (RFC8308), with the following message:
+
+	string		"ping at openssh.com"
+	string		"0" (version)
+
+The ping/reply message is implemented at the transport layer rather
+than as a named global or channel request to allow pings with very
+short packet lengths, which would not be possible with other
+approaches.
+
 2. Connection protocol changes
 
 2.1. connection: Channel write close extension "eow at openssh.com"
@@ -712,4 +745,4 @@ master instance and later clients.
 OpenSSH extends the usual agent protocol. These changes are documented
 in the PROTOCOL.agent file.
 
-$OpenBSD: PROTOCOL,v 1.48 2022/11/07 01:53:01 dtucker Exp $
+$OpenBSD: PROTOCOL,v 1.49 2023/08/28 03:28:43 djm Exp $
diff --git a/kex.c b/kex.c
index 502da12e..8ff92f2a 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.180 2023/08/21 21:16:18 tobhe Exp $ */
+/* $OpenBSD: kex.c,v 1.181 2023/08/28 03:28:43 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -492,12 +492,14 @@ kex_send_ext_info(struct ssh *ssh)
 		return SSH_ERR_ALLOC_FAIL;
 	/* XXX filter algs list by allowed pubkey/hostbased types */
 	if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
-	    (r = sshpkt_put_u32(ssh, 2)) != 0 ||
+	    (r = sshpkt_put_u32(ssh, 3)) != 0 ||
 	    (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
 	    (r = sshpkt_put_cstring(ssh, algs)) != 0 ||
 	    (r = sshpkt_put_cstring(ssh,
 	    "publickey-hostbound at openssh.com")) != 0 ||
 	    (r = sshpkt_put_cstring(ssh, "0")) != 0 ||
+	    (r = sshpkt_put_cstring(ssh, "ping at openssh.com")) != 0 ||
+	    (r = sshpkt_put_cstring(ssh, "0")) != 0 ||
 	    (r = sshpkt_send(ssh)) != 0) {
 		error_fr(r, "compose");
 		goto out;
@@ -527,6 +529,23 @@ kex_send_newkeys(struct ssh *ssh)
 	return 0;
 }
 
+/* Check whether an ext_info value contains the expected version string */
+static int
+kex_ext_info_check_ver(struct kex *kex, const char *name,
+    const u_char *val, size_t len, const char *want_ver, u_int flag)
+{
+	if (memchr(val, '\0', len) != NULL) {
+		error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name);
+		return SSH_ERR_INVALID_FORMAT;
+	}
+	debug_f("%s=<%s>", name, val);
+	if (strcmp(val, want_ver) == 0)
+		kex->flags |= flag;
+	else
+		debug_f("unsupported version of %s extension", name);
+	return 0;
+}
+
 int
 kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
 {
@@ -557,6 +576,8 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
 			/* Ensure no \0 lurking in value */
 			if (memchr(val, '\0', vlen) != NULL) {
 				error_f("nul byte in %s", name);
+				free(name);
+				free(val);
 				return SSH_ERR_INVALID_FORMAT;
 			}
 			debug_f("%s=<%s>", name, val);
@@ -564,18 +585,18 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
 			val = NULL;
 		} else if (strcmp(name,
 		    "publickey-hostbound at openssh.com") == 0) {
-			/* XXX refactor */
-			/* Ensure no \0 lurking in value */
-			if (memchr(val, '\0', vlen) != NULL) {
-				error_f("nul byte in %s", name);
-				return SSH_ERR_INVALID_FORMAT;
+			if ((r = kex_ext_info_check_ver(kex, name, val, vlen,
+			    "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) {
+				free(name);
+				free(val);
+				return r;
 			}
-			debug_f("%s=<%s>", name, val);
-			if (strcmp(val, "0") == 0)
-				kex->flags |= KEX_HAS_PUBKEY_HOSTBOUND;
-			else {
-				debug_f("unsupported version of %s extension",
-				    name);
+		} else if (strcmp(name, "ping at openssh.com") == 0) {
+			if ((r = kex_ext_info_check_ver(kex, name, val, vlen,
+			    "0", KEX_HAS_PING)) != 0) {
+				free(name);
+				free(val);
+				return r;
 			}
 		} else
 			debug_f("%s (unrecognised)", name);
diff --git a/kex.h b/kex.h
index 8b54e3f4..5f7ef784 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.118 2023/03/06 12:14:48 dtucker Exp $ */
+/* $OpenBSD: kex.h,v 1.119 2023/08/28 03:28:43 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -111,6 +111,7 @@ enum kex_exchange {
 #define KEX_HAS_PUBKEY_HOSTBOUND	0x0004
 #define KEX_RSA_SHA2_256_SUPPORTED 	0x0008 /* only set in server for now */
 #define KEX_RSA_SHA2_512_SUPPORTED 	0x0010 /* only set in server for now */
+#define KEX_HAS_PING		 	0x0020
 
 struct sshenc {
 	char	*name;
diff --git a/packet.c b/packet.c
index fdb8783b..77e5c57b 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.310 2023/04/06 03:21:31 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.311 2023/08/28 03:28:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1054,6 +1054,8 @@ int
 ssh_packet_log_type(u_char type)
 {
 	switch (type) {
+	case SSH2_MSG_PING:
+	case SSH2_MSG_PONG:
 	case SSH2_MSG_CHANNEL_DATA:
 	case SSH2_MSG_CHANNEL_EXTENDED_DATA:
 	case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
@@ -1675,7 +1677,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
 		goto out;
 	if (ssh_packet_log_type(*typep))
 		debug3("receive packet: type %u", *typep);
-	if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
+	if (*typep < SSH2_MSG_MIN) {
 		if ((r = sshpkt_disconnect(ssh,
 		    "Invalid ssh2 packet type: %d", *typep)) != 0 ||
 		    (r = ssh_packet_write_wait(ssh)) != 0)
@@ -1710,6 +1712,8 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
 	u_int reason, seqnr;
 	int r;
 	u_char *msg;
+	const u_char *d;
+	size_t len;
 
 	for (;;) {
 		msg = NULL;
@@ -1753,6 +1757,21 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
 			debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
 			    seqnr);
 			break;
+		case SSH2_MSG_PING:
+			if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0)
+				return r;
+			DBG(debug("Received SSH2_MSG_PING len %zu", len));
+			if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 ||
+			    (r = sshpkt_put_string(ssh, d, len)) != 0 ||
+			    (r = sshpkt_send(ssh)) != 0)
+				return r;
+			break;
+		case SSH2_MSG_PONG:
+			if ((r = sshpkt_get_string_direct(ssh,
+			    NULL, &len)) != 0)
+				return r;
+			DBG(debug("Received SSH2_MSG_PONG len %zu", len));
+			break;
 		default:
 			return 0;
 		}
diff --git a/ssh2.h b/ssh2.h
index 288c39f6..0d48d052 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh2.h,v 1.20 2023/08/14 03:37:00 djm Exp $ */
+/* $OpenBSD: ssh2.h,v 1.21 2023/08/28 03:28:43 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -108,6 +108,10 @@
 #define SSH2_MSG_KEX_ECDH_INIT				30
 #define SSH2_MSG_KEX_ECDH_REPLY				31
 
+/* transport layer: OpenSSH extensions */
+#define SSH2_MSG_PING					192
+#define SSH2_MSG_PONG					193
+
 /* user authentication: generic */
 
 #define SSH2_MSG_USERAUTH_REQUEST			50

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list