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

ssh_options_set_algo: ensure we only set known algorithms internally

That way, we will not fail later on key exchange phase when something
unknown is negotiated.

Fixes T37

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Nikos Mavrogiannopoulos
2017-08-24 16:28:39 +02:00
committed by Andreas Schneider
parent de35212789
commit 895055ab38
3 changed files with 81 additions and 7 deletions

View File

@@ -41,6 +41,7 @@ void ssh_list_kex(struct ssh_kex_struct *kex);
int ssh_set_client_kex(ssh_session session); int ssh_set_client_kex(ssh_session session);
int ssh_kex_select_methods(ssh_session session); int ssh_kex_select_methods(ssh_session session);
int ssh_verify_existing_algo(int algo, const char *name); int ssh_verify_existing_algo(int algo, const char *name);
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
char **ssh_space_tokenize(const char *chain); char **ssh_space_tokenize(const char *chain);
int ssh_get_kex1(ssh_session session); int ssh_get_kex1(ssh_session session);
char *ssh_find_matching(const char *in_d, const char *what_d); char *ssh_find_matching(const char *in_d, const char *what_d);

View File

@@ -281,6 +281,71 @@ char *ssh_find_matching(const char *available_d, const char *preferred_d){
return NULL; return NULL;
} }
static char *ssh_find_all_matching(const char *available_d,
const char *preferred_d)
{
char **tok_available, **tok_preferred;
int i_avail, i_pref;
char *ret;
unsigned max, len, pos = 0;
if ((available_d == NULL) || (preferred_d == NULL)) {
return NULL; /* don't deal with null args */
}
max = MAX(strlen(available_d), strlen(preferred_d));
ret = malloc(max+1);
if (ret == NULL) {
return NULL;
}
ret[0] = 0;
tok_available = tokenize(available_d);
if (tok_available == NULL) {
SAFE_FREE(ret);
return NULL;
}
tok_preferred = tokenize(preferred_d);
if (tok_preferred == NULL) {
SAFE_FREE(ret);
SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_available);
return NULL;
}
for (i_pref = 0; tok_preferred[i_pref] ; ++i_pref) {
for (i_avail = 0; tok_available[i_avail]; ++i_avail) {
int cmp = strcmp(tok_available[i_avail],tok_preferred[i_pref]);
if (cmp == 0) {
/* match */
if (pos != 0) {
ret[pos] = ',';
pos++;
}
len = strlen(tok_available[i_avail]);
memcpy(&ret[pos], tok_available[i_avail], len);
pos += len;
ret[pos] = '\0';
}
}
}
if (ret[0] == '\0') {
SAFE_FREE(ret);
ret = NULL;
}
SAFE_FREE(tok_available[0]);
SAFE_FREE(tok_preferred[0]);
SAFE_FREE(tok_available);
SAFE_FREE(tok_preferred);
return ret;
}
/** /**
* @internal * @internal
* @brief returns whether the first client key exchange algorithm or * @brief returns whether the first client key exchange algorithm or
@@ -668,4 +733,13 @@ int ssh_verify_existing_algo(int algo, const char *name){
return 0; return 0;
} }
/* vim: set ts=2 sw=2 et cindent: */ /* returns a copy of the provided list if everything is supported,
* otherwise a new list of the supported algorithms */
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list)
{
if (algo > SSH_LANG_S_C) {
return NULL;
}
return ssh_find_all_matching(supported_methods[algo], list);
}

View File

@@ -164,7 +164,10 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
int ssh_options_set_algo(ssh_session session, int algo, int ssh_options_set_algo(ssh_session session, int algo,
const char *list) { const char *list) {
if (!ssh_verify_existing_algo(algo, list)) { char *p = NULL;
p = ssh_keep_known_algos(algo, list);
if (p == NULL) {
ssh_set_error(session, SSH_REQUEST_DENIED, ssh_set_error(session, SSH_REQUEST_DENIED,
"Setting method: no algorithm for method \"%s\" (%s)", "Setting method: no algorithm for method \"%s\" (%s)",
ssh_kex_get_description(algo), list); ssh_kex_get_description(algo), list);
@@ -172,11 +175,7 @@ int ssh_options_set_algo(ssh_session session, int algo,
} }
SAFE_FREE(session->opts.wanted_methods[algo]); SAFE_FREE(session->opts.wanted_methods[algo]);
session->opts.wanted_methods[algo] = strdup(list); session->opts.wanted_methods[algo] = p;
if (session->opts.wanted_methods[algo] == NULL) {
ssh_set_error_oom(session);
return -1;
}
return 0; return 0;
} }