From: dtucker@openbsd.org Date: Thu, 27 Nov 2025 02:18:48 +0000 (+0000) Subject: upstream: Add Escape option ~I that shows information about the current X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52037ed910a9dcb669b9c9f612ccac711ac586f2;p=thirdparty%2Fopenssh-portable.git upstream: Add Escape option ~I that shows information about the current SSH connection. ok djm@, "I like/want" sthen@ florian@ OpenBSD-Commit-ID: 0483fc0188ec899077e4bc8e1e353f7dfa9f5c1d --- diff --git a/clientloop.c b/clientloop.c index 1f2dad3f1..a78dfa6e0 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.417 2025/10/16 00:00:36 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.418 2025/11/27 02:18:48 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1125,6 +1125,7 @@ static struct escape_help_text esc_txt[] = { SUPPRESS_MUXCLIENT}, {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, {"C", "open a command line", SUPPRESS_MUXCLIENT|SUPPRESS_NOCMDLINE}, + {"I", "show connection information", SUPPRESS_NEVER}, {"R", "request rekey", SUPPRESS_NEVER}, {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, @@ -1247,6 +1248,16 @@ process_escapes(struct ssh *ssh, Channel *c, fatal_fr(r, "send packet"); continue; + case 'I': + if ((r = sshbuf_putf(berr, "%cI\r\n", + efc->escape_char)) != 0) + fatal_fr(r, "sshbuf_putf"); + s = connection_info_message(ssh); + if ((r = sshbuf_put(berr, s, strlen(s))) != 0) + fatal_fr(r, "sshbuf_put"); + free(s); + continue; + case 'R': if (ssh->compat & SSH_BUG_NOREKEY) logit("Server does not " diff --git a/packet.c b/packet.c index 5dd8269c2..361c4f2fe 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.323 2025/09/25 06:33:19 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.324 2025/11/27 02:18:48 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -59,6 +59,7 @@ #include #include #include +#include /* * Explicitly include OpenSSL before zlib as some versions of OpenSSL have @@ -2902,3 +2903,108 @@ sshpkt_add_padding(struct ssh *ssh, u_char pad) ssh->state->extra_pad = pad; return 0; } + +static char * +format_traffic_stats(struct packet_state *ps) +{ + char *stats = NULL, bytes[FMT_SCALED_STRSIZE]; + + if (ps->bytes > LLONG_MAX || fmt_scaled(ps->bytes, bytes) != 0) + strlcpy(bytes, "OVERFLOW", sizeof(bytes)); + + xasprintf(&stats, "%lu pkts %llu blks %sB", + (unsigned long)ps->packets, (unsigned long long)ps->blocks, bytes); + return stats; +} + +static char * +dedupe_alg_names(const char *in, const char *out) +{ + char *names = NULL; + + if (in == NULL) + in = ""; + if (out == NULL) + out = ""; + + if (strcmp(in, out) == 0) { + names = xstrdup(in); + } else { + xasprintf(&names, "%s in, %s out", in, out); + } + return names; +} + +char * +connection_info_message(struct ssh *ssh) +{ + char *ret = NULL, *cipher = NULL, *mac = NULL, *comp = NULL; + char *rekey_volume = NULL, *rekey_time = NULL; + struct kex *kex; + struct session_state *state; + struct newkeys *nk_in, *nk_out; + char *stats_in = NULL, *stats_out = NULL; + u_int64_t epoch = (u_int64_t)time(NULL) - monotime(); + + if (ssh == NULL) + return NULL; + state = ssh->state; + kex = ssh->kex; + + nk_in = ssh->state->newkeys[MODE_IN]; + nk_out = ssh->state->newkeys[MODE_OUT]; + stats_in = format_traffic_stats(&ssh->state->p_read); + stats_out = format_traffic_stats(&ssh->state->p_send); + + cipher = dedupe_alg_names(nk_in->enc.name, nk_out->enc.name); + mac = dedupe_alg_names(nk_in->mac.name, nk_out->mac.name); + comp = dedupe_alg_names(nk_in->comp.name, nk_out->comp.name); + + /* Volume based rekeying. */ + if (state->rekey_limit == 0) { + xasprintf(&rekey_volume, "limit none"); + } else { + char *volumes = NULL, in[32], out[32]; + + snprintf(in, sizeof(in), "%llu", + (unsigned long long)state->max_blocks_in); + snprintf(out, sizeof(out), "%llu", + (unsigned long long)state->max_blocks_out); + volumes = dedupe_alg_names(in, out); + xasprintf(&rekey_volume, "limit blocks %s", volumes); + free(volumes); + } + + /* Time based rekeying. */ + if (state->rekey_interval == 0) { + rekey_time = xstrdup("interval none"); + } else { + char rekey_next[64]; + + format_absolute_time(epoch + state->rekey_time + + state->rekey_interval, rekey_next, sizeof(rekey_next)); + xasprintf(&rekey_time, "interval %s, next %s", + fmt_timeframe(state->rekey_interval), rekey_next); + } + + xasprintf(&ret, "Connection information for peer %s port %d:\r\n" + " kexalgorithm %s\r\n hostkeyalgorithm %s\r\n" + " cipher %s\r\n mac %s\r\n compression %s\r\n" + " rekey %s %s\r\n" + " traffic %s in, %s out\r\n", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + kex->name, kex->hostkey_alg, + cipher, mac, comp, + rekey_volume, rekey_time, + stats_in, stats_out + ); + free(cipher); + free(mac); + free(comp); + free(stats_in); + free(stats_out); + free(rekey_volume); + free(rekey_time); + return ret; +} + diff --git a/packet.h b/packet.h index 072f27425..355fd6bd8 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.103 2025/09/25 06:33:19 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.104 2025/11/27 02:18:48 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -210,6 +210,7 @@ int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp); int sshpkt_get_end(struct ssh *ssh); void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l); const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); +char *connection_info_message(struct ssh *ssh); #if !defined(WITH_OPENSSL) # undef BIGNUM diff --git a/ssh.1 b/ssh.1 index 697f4e42a..391bcdbb6 100644 --- a/ssh.1 +++ b/ssh.1 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.444 2024/12/04 14:37:55 djm Exp $ -.Dd $Mdocdate: December 4 2024 $ +.\" $OpenBSD: ssh.1,v 1.445 2025/11/27 02:18:48 dtucker Exp $ +.Dd $Mdocdate: November 27 2025 $ .Dt SSH 1 .Os .Sh NAME @@ -1156,6 +1156,8 @@ option is enabled in Basic help is available, using the .Fl h option. +.It Cm ~I +Show information about the current SSH connection. .It Cm ~R Request rekeying of the connection (only useful if the peer supports it).