diff options
author | Jakub Jelen <jjelen@redhat.com> | 2018-10-18 14:46:32 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2018-10-19 17:43:17 +0200 |
commit | 35a64554899f142a2b8b68c79007ad9c3ce00cb1 (patch) | |
tree | 668c303366a5f23d2ba6415a5b8fa3b997c325f8 | |
parent | c1a8c41c5daf79e37aa5fde67dd94c8596e81102 (diff) | |
download | libssh-35a64554899f142a2b8b68c79007ad9c3ce00cb1.tar.gz libssh-35a64554899f142a2b8b68c79007ad9c3ce00cb1.tar.xz libssh-35a64554899f142a2b8b68c79007ad9c3ce00cb1.zip |
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 <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
-rw-r--r-- | src/kex.c | 33 |
1 files changed, 30 insertions, 3 deletions
@@ -26,6 +26,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <stdbool.h> #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; } /** |