=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/kex.c,v retrieving revision 1.181.2.1 retrieving revision 1.182 diff -u -r1.181.2.1 -r1.182 --- src/usr.bin/ssh/kex.c 2023/12/18 14:56:35 1.181.2.1 +++ src/usr.bin/ssh/kex.c 2023/10/11 04:46:29 1.182 @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.181.2.1 2023/12/18 14:56:35 bluhm Exp $ */ +/* $OpenBSD: kex.c,v 1.182 2023/10/11 04:46:29 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -60,7 +60,7 @@ #include "xmalloc.h" /* prototype */ -static int kex_choose_conf(struct ssh *, uint32_t seq); +static int kex_choose_conf(struct ssh *); static int kex_input_newkeys(int, u_int32_t, struct ssh *); static const char * const proposal_names[PROPOSAL_MAX] = { @@ -162,18 +162,6 @@ return 1; } -/* returns non-zero if proposal contains any algorithm from algs */ -static int -has_any_alg(const char *proposal, const char *algs) -{ - char *cp; - - if ((cp = match_list(proposal, algs, NULL)) == NULL) - return 0; - free(cp); - return 1; -} - /* * Concatenate algorithm names, avoiding duplicates in the process. * Caller must free returned string. @@ -181,7 +169,7 @@ char * kex_names_cat(const char *a, const char *b) { - char *ret = NULL, *tmp = NULL, *cp, *p; + char *ret = NULL, *tmp = NULL, *cp, *p, *m; size_t len; if (a == NULL || *a == '\0') @@ -198,8 +186,10 @@ } strlcpy(ret, a, len); for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { - if (has_any_alg(ret, p)) + if ((m = match_list(ret, p, NULL)) != NULL) { + free(m); continue; /* Algorithm already present */ + } if (strlcat(ret, ",", len) >= len || strlcat(ret, p, len) >= len) { free(tmp); @@ -329,23 +319,15 @@ const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; const char **defprop = ssh->kex->server ? defpropserver : defpropclient; u_int i; - char *cp; if (prop == NULL) fatal_f("proposal missing"); - /* Append EXT_INFO signalling to KexAlgorithms */ - if (kexalgos == NULL) - kexalgos = defprop[PROPOSAL_KEX_ALGS]; - if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? - "kex-strict-s-v00@openssh.com" : - "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) - fatal_f("kex_names_cat"); - for (i = 0; i < PROPOSAL_MAX; i++) { switch(i) { case PROPOSAL_KEX_ALGS: - prop[i] = compat_kex_proposal(ssh, cp); + prop[i] = compat_kex_proposal(ssh, + kexalgos ? kexalgos : defprop[i]); break; case PROPOSAL_ENC_ALGS_CTOS: case PROPOSAL_ENC_ALGS_STOC: @@ -366,7 +348,6 @@ prop[i] = xstrdup(defprop[i]); } } - free(cp); } void @@ -470,12 +451,7 @@ { int r; - /* If in strict mode, any unexpected message is an error */ - if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { - ssh_packet_disconnect(ssh, "strict KEX violation: " - "unexpected packet type %u (seqnr %u)", type, seq); - } - error_f("type %u seq %u", type, seq); + error("kex protocol error: type %d seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0) @@ -572,7 +548,7 @@ if (ninfo >= 1024) { error("SSH2_MSG_EXT_INFO with too many entries, expected " "<=1024, received %u", ninfo); - return dispatch_protocol_error(type, seq, ssh); + return SSH_ERR_INVALID_FORMAT; } for (i = 0; i < ninfo; i++) { if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) @@ -690,7 +666,7 @@ error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } - ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); + ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; @@ -726,7 +702,7 @@ if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; - if ((r = kex_choose_conf(ssh, seq)) != 0) + if ((r = kex_choose_conf(ssh)) != 0) return r; if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) @@ -988,14 +964,20 @@ return (1); } +/* returns non-zero if proposal contains any algorithm from algs */ static int -kexalgs_contains(char **peer, const char *ext) +has_any_alg(const char *proposal, const char *algs) { - return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); + char *cp; + + if ((cp = match_list(proposal, algs, NULL)) == NULL) + return 0; + free(cp); + return 1; } static int -kex_choose_conf(struct ssh *ssh, uint32_t seq) +kex_choose_conf(struct ssh *ssh) { struct kex *kex = ssh->kex; struct newkeys *newkeys; @@ -1020,23 +1002,13 @@ sprop=peer; } - /* Check whether peer supports ext_info/kex_strict */ - if ((kex->flags & KEX_INITIAL) != 0) { - if (kex->server) { - kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); - kex->kex_strict = kexalgs_contains(peer, - "kex-strict-c-v00@openssh.com"); - } else { - kex->kex_strict = kexalgs_contains(peer, - "kex-strict-s-v00@openssh.com"); - } - if (kex->kex_strict) { - debug3_f("will use strict KEX ordering"); - if (seq != 0) - ssh_packet_disconnect(ssh, - "strict KEX violation: " - "KEXINIT was not the first packet"); - } + /* Check whether client supports ext_info_c */ + if (kex->server && (kex->flags & KEX_INITIAL)) { + char *ext; + + ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); + kex->ext_info_c = (ext != NULL); + free(ext); } /* Check whether client supports rsa-sha2 algorithms */ @@ -1321,7 +1293,7 @@ sshbuf_reset(our_version); if (version_addendum != NULL && *version_addendum == '\0') version_addendum = NULL; - if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", + if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n", PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, version_addendum == NULL ? "" : " ", version_addendum == NULL ? "" : version_addendum)) != 0) {