From 35a64554899f142a2b8b68c79007ad9c3ce00cb1 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 18 Oct 2018 14:46:32 +0200 Subject: [PATCH] kex: Use all supported hostkey algorithms for negotiation Previously, only the algorithms we had a keys for in known_hosts were used, which could lead to no-matching algorithms errors if the one key we used to depend on was removed from the server. This commit adds also the other algorithms, but lists them only after all the key types we have in known_hosts file. Resolves: T105 Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- src/kex.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/kex.c b/src/kex.c index 29329726..bb014baf 100644 --- a/src/kex.c +++ b/src/kex.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "libssh/priv.h" #include "libssh/buffer.h" @@ -608,6 +609,8 @@ void ssh_list_kex(struct ssh_kex_struct *kex) { static char *ssh_client_select_hostkeys(ssh_session session) { char methods_buffer[128]={0}; + char tail_buffer[128]={0}; + char *new_hostkeys = NULL; static const char *preferred_hostkeys[] = { "ssh-ed25519", "ecdsa-sha2-nistp521", @@ -623,7 +626,7 @@ static char *ssh_client_select_hostkeys(ssh_session session) struct ssh_iterator *it = NULL; size_t algo_count; int needcomma = 0; - int i; + size_t i, len; algo_list = ssh_known_hosts_get_algorithms(session); if (algo_list == NULL) { @@ -637,6 +640,8 @@ static char *ssh_client_select_hostkeys(ssh_session session) } for (i = 0; preferred_hostkeys[i] != NULL; ++i) { + bool found = false; + for (it = ssh_list_get_iterator(algo_list); it != NULL; it = it->next) { @@ -657,9 +662,19 @@ static char *ssh_client_select_hostkeys(ssh_session session) algo, sizeof(methods_buffer) - strlen(methods_buffer) - 1); needcomma = 1; + found = true; } } } + /* Collect the rest of the algorithms in other buffer, that will + * follow the preferred buffer. This will signalize all the algorithms + * we are willing to accept. + */ + if (!found) { + snprintf(tail_buffer + strlen(tail_buffer), + sizeof(tail_buffer) - strlen(tail_buffer), + ",%s", preferred_hostkeys[i]); + } } ssh_list_free(algo_list); @@ -669,11 +684,23 @@ static char *ssh_client_select_hostkeys(ssh_session session) return NULL; } + /* Append the supported list to the preferred. + * The length is maximum 128 + 128 + 1, which will not overflow + */ + len = strlen(methods_buffer) + strlen(tail_buffer) + 1; + new_hostkeys = malloc(len); + if (new_hostkeys == NULL) { + ssh_set_error_oom(session); + return NULL; + } + snprintf(new_hostkeys, len, + "%s%s", methods_buffer, tail_buffer); + SSH_LOG(SSH_LOG_DEBUG, "Changing host key method to \"%s\"", - methods_buffer); + new_hostkeys); - return strdup(methods_buffer); + return new_hostkeys; } /**