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:
committed by
Andreas Schneider
parent
de35212789
commit
895055ab38
@@ -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);
|
||||||
|
|||||||
76
src/kex.c
76
src/kex.c
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user