summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2018-10-18 14:46:32 +0200
committerAndreas Schneider <asn@cryptomilk.org>2018-10-19 17:43:17 +0200
commit35a64554899f142a2b8b68c79007ad9c3ce00cb1 (patch)
tree668c303366a5f23d2ba6415a5b8fa3b997c325f8
parentc1a8c41c5daf79e37aa5fde67dd94c8596e81102 (diff)
downloadlibssh-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.c33
1 files 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 <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;
}
/**