diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 57 |
1 files changed, 39 insertions, 18 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.178 2023/03/12 10:40:39 dtucker 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@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; @@ -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@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); @@ -1334,7 +1355,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, for (;;) { if (timeout_ms > 0) { r = waitrfd(ssh_packet_get_connection_in(ssh), - &timeout_ms); + &timeout_ms, NULL); if (r == -1 && errno == ETIMEDOUT) { send_error(ssh, "Timed out waiting " "for SSH identification string."); @@ -1353,7 +1374,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, len = atomicio(read, ssh_packet_get_connection_in(ssh), &c, 1); if (len != 1 && errno == EPIPE) { - error_f("Connection closed by remote host"); + verbose_f("Connection closed by remote host"); r = SSH_ERR_CONN_CLOSED; goto out; } else if (len != 1) { @@ -1369,7 +1390,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, if (c == '\n') break; if (c == '\0' || expect_nl) { - error_f("banner line contains invalid " + verbose_f("banner line contains invalid " "characters"); goto invalid; } @@ -1379,7 +1400,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, goto out; } if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { - error_f("banner line too long"); + verbose_f("banner line too long"); goto invalid; } } @@ -1395,7 +1416,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, } /* Do not accept lines before the SSH ident from a client */ if (ssh->kex->server) { - error_f("client sent invalid protocol identifier " + verbose_f("client sent invalid protocol identifier " "\"%.256s\"", cp); free(cp); goto invalid; |