summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2023-08-28 03:28:44 +0000
committerDamien Miller <djm@cvs.openbsd.org>2023-08-28 03:28:44 +0000
commit31b179c551fdd3ba78c4ad93c807fe0df194eab8 (patch)
tree28ceb343f8de21b883c03d4377166a699b6369cf
parentce28b3d5bab288cfd63eb59a14f4b7f9dbf7c9d8 (diff)
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@openssh.com" ext-info message with a string version number of "0". ok markus@
-rw-r--r--usr.bin/ssh/PROTOCOL35
-rw-r--r--usr.bin/ssh/kex.c47
-rw-r--r--usr.bin/ssh/kex.h3
-rw-r--r--usr.bin/ssh/packet.c23
-rw-r--r--usr.bin/ssh/ssh2.h6
5 files changed, 96 insertions, 18 deletions
diff --git a/usr.bin/ssh/PROTOCOL b/usr.bin/ssh/PROTOCOL
index 0aeefbb1a7d..9e15c11abd3 100644
--- a/usr.bin/ssh/PROTOCOL
+++ b/usr.bin/ssh/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@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@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/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c
index 615ede8321e..a414f962c21 100644
--- a/usr.bin/ssh/kex.c
+++ b/usr.bin/ssh/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.
*
@@ -477,12 +477,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@openssh.com")) != 0 ||
(r = sshpkt_put_cstring(ssh, "0")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "ping@openssh.com")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "0")) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
error_fr(r, "compose");
goto out;
@@ -512,6 +514,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)
{
@@ -542,6 +561,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);
@@ -549,18 +570,18 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
val = NULL;
} else if (strcmp(name,
"publickey-hostbound@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@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/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h
index 1a7584558ae..50738b18d1e 100644
--- a/usr.bin/ssh/kex.h
+++ b/usr.bin/ssh/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.
@@ -104,6 +104,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/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c
index b9a5343bf7b..600d51080fa 100644
--- a/usr.bin/ssh/packet.c
+++ b/usr.bin/ssh/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@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1034,6 +1034,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:
@@ -1654,7 +1656,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)
@@ -1689,6 +1691,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;
@@ -1732,6 +1736,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/usr.bin/ssh/ssh2.h b/usr.bin/ssh/ssh2.h
index 288c39f69e3..0d48d052782 100644
--- a/usr.bin/ssh/ssh2.h
+++ b/usr.bin/ssh/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