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_kex_select_methods(ssh_session session);
|
||||
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);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* @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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
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,
|
||||
"Setting method: no algorithm for method \"%s\" (%s)",
|
||||
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]);
|
||||
session->opts.wanted_methods[algo] = strdup(list);
|
||||
if (session->opts.wanted_methods[algo] == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
session->opts.wanted_methods[algo] = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user