1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-30 13:01:23 +03:00

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>
This commit is contained in:
Jakub Jelen
2018-10-18 14:46:32 +02:00
committed by Andreas Schneider
parent c1a8c41c5d
commit 35a6455489

View File

@@ -26,6 +26,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/buffer.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) static char *ssh_client_select_hostkeys(ssh_session session)
{ {
char methods_buffer[128]={0}; char methods_buffer[128]={0};
char tail_buffer[128]={0};
char *new_hostkeys = NULL;
static const char *preferred_hostkeys[] = { static const char *preferred_hostkeys[] = {
"ssh-ed25519", "ssh-ed25519",
"ecdsa-sha2-nistp521", "ecdsa-sha2-nistp521",
@@ -623,7 +626,7 @@ static char *ssh_client_select_hostkeys(ssh_session session)
struct ssh_iterator *it = NULL; struct ssh_iterator *it = NULL;
size_t algo_count; size_t algo_count;
int needcomma = 0; int needcomma = 0;
int i; size_t i, len;
algo_list = ssh_known_hosts_get_algorithms(session); algo_list = ssh_known_hosts_get_algorithms(session);
if (algo_list == NULL) { 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) { for (i = 0; preferred_hostkeys[i] != NULL; ++i) {
bool found = false;
for (it = ssh_list_get_iterator(algo_list); for (it = ssh_list_get_iterator(algo_list);
it != NULL; it != NULL;
it = it->next) { it = it->next) {
@@ -657,9 +662,19 @@ static char *ssh_client_select_hostkeys(ssh_session session)
algo, algo,
sizeof(methods_buffer) - strlen(methods_buffer) - 1); sizeof(methods_buffer) - strlen(methods_buffer) - 1);
needcomma = 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); ssh_list_free(algo_list);
@@ -669,11 +684,23 @@ static char *ssh_client_select_hostkeys(ssh_session session)
return NULL; 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, SSH_LOG(SSH_LOG_DEBUG,
"Changing host key method to \"%s\"", "Changing host key method to \"%s\"",
methods_buffer); new_hostkeys);
return strdup(methods_buffer); return new_hostkeys;
} }
/** /**