mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 02:38:09 +09:00
kex, known_hosts: Use new tokens functions
Replace the old tokens handling functions usage with the new implementation. Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
committed by
Andreas Schneider
parent
2c4850cbbd
commit
bc95a51710
126
src/kex.c
126
src/kex.c
@@ -186,92 +186,6 @@ static const char *ssh_kex_descriptions[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/* tokenize will return a token of strings delimited by ",". the first element has to be freed */
|
||||
static char **tokenize(const char *chain){
|
||||
char **tokens;
|
||||
size_t n=1;
|
||||
size_t i=0;
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
|
||||
tmp = strdup(chain);
|
||||
if (tmp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = tmp;
|
||||
while(*ptr){
|
||||
if(*ptr==','){
|
||||
n++;
|
||||
*ptr=0;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
/* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
|
||||
tokens = calloc(n + 1, sizeof(char *)); /* +1 for the null */
|
||||
if (tokens == NULL) {
|
||||
SAFE_FREE(tmp);
|
||||
return NULL;
|
||||
}
|
||||
ptr=tmp;
|
||||
for(i=0;i<n;i++){
|
||||
tokens[i]=ptr;
|
||||
while(*ptr)
|
||||
ptr++; // find a zero
|
||||
ptr++; // then go one step further
|
||||
}
|
||||
tokens[i]=NULL;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/* same as tokenize(), but with spaces instead of ',' */
|
||||
/* TODO FIXME rewrite me! */
|
||||
char **ssh_space_tokenize(const char *chain){
|
||||
char **tokens;
|
||||
size_t n=1;
|
||||
size_t i=0;
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
|
||||
tmp = strdup(chain);
|
||||
if (tmp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = tmp;
|
||||
|
||||
while(*ptr==' ')
|
||||
++ptr; /* skip initial spaces */
|
||||
while(*ptr){
|
||||
if(*ptr==' '){
|
||||
n++; /* count one token per word */
|
||||
*ptr=0;
|
||||
while(*(ptr+1)==' '){ /* don't count if the tokens have more than 2 spaces */
|
||||
*(ptr++)=0;
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
/* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
|
||||
tokens = calloc(n + 1, sizeof(char *)); /* +1 for the null */
|
||||
if (tokens == NULL) {
|
||||
SAFE_FREE(tmp);
|
||||
return NULL;
|
||||
}
|
||||
ptr=tmp; /* we don't pass the initial spaces because the "tmp" pointer is needed by the caller */
|
||||
/* function to free the tokens. */
|
||||
for(i=0;i<n;i++){
|
||||
tokens[i]=ptr;
|
||||
if(i!=n-1){
|
||||
while(*ptr)
|
||||
ptr++; // find a zero
|
||||
while(!*(ptr+1))
|
||||
++ptr; /* if the zero is followed by other zeros, go through them */
|
||||
ptr++; // then go one step further
|
||||
}
|
||||
}
|
||||
tokens[i]=NULL;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
{
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
@@ -306,37 +220,33 @@ const char *ssh_kex_get_description(uint32_t algo) {
|
||||
*/
|
||||
static int cmp_first_kex_algo(const char *client_str,
|
||||
const char *server_str) {
|
||||
size_t client_kex_len;
|
||||
size_t server_kex_len;
|
||||
|
||||
char *colon;
|
||||
|
||||
int is_wrong = 1;
|
||||
char **server_str_tokens = NULL;
|
||||
char **client_str_tokens = NULL;
|
||||
|
||||
if ((client_str == NULL) || (server_str == NULL)) {
|
||||
goto out;
|
||||
colon = strchr(client_str, ',');
|
||||
if (colon == NULL) {
|
||||
client_kex_len = strlen(client_str);
|
||||
} else {
|
||||
client_kex_len = colon - client_str;
|
||||
}
|
||||
|
||||
client_str_tokens = tokenize(client_str);
|
||||
|
||||
if (client_str_tokens == NULL) {
|
||||
goto out;
|
||||
colon = strchr(server_str, ',');
|
||||
if (colon == NULL) {
|
||||
server_kex_len = strlen(server_str);
|
||||
} else {
|
||||
server_kex_len = colon - server_str;
|
||||
}
|
||||
|
||||
if (client_str_tokens[0] == NULL) {
|
||||
goto freeout;
|
||||
if (client_kex_len != server_kex_len) {
|
||||
return is_wrong;
|
||||
}
|
||||
|
||||
server_str_tokens = tokenize(server_str);
|
||||
if (server_str_tokens == NULL) {
|
||||
goto freeout;
|
||||
}
|
||||
is_wrong = (strncmp(client_str, server_str, client_kex_len) != 0);
|
||||
|
||||
is_wrong = (strcmp(client_str_tokens[0], server_str_tokens[0]) != 0);
|
||||
|
||||
SAFE_FREE(server_str_tokens[0]);
|
||||
SAFE_FREE(server_str_tokens);
|
||||
freeout:
|
||||
SAFE_FREE(client_str_tokens[0]);
|
||||
SAFE_FREE(client_str_tokens);
|
||||
out:
|
||||
return is_wrong;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "libssh/knownhosts.h"
|
||||
/*todo: remove this include */
|
||||
#include "libssh/string.h"
|
||||
#include "libssh/token.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <netinet/in.h>
|
||||
@@ -50,23 +51,6 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Free a token array.
|
||||
*/
|
||||
static void tokens_free(char **tokens) {
|
||||
if (tokens == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SAFE_FREE(tokens[0]);
|
||||
/* It's not needed to free other pointers because tokens generated by
|
||||
* space_tokenize fit all in one malloc
|
||||
*/
|
||||
SAFE_FREE(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
@@ -86,11 +70,13 @@ static void tokens_free(char **tokens) {
|
||||
* free that value. NULL if no match was found or the file
|
||||
* was not found.
|
||||
*/
|
||||
static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
||||
const char **found_type) {
|
||||
static struct ssh_tokens_st *ssh_get_knownhost_line(FILE **file,
|
||||
const char *filename,
|
||||
const char **found_type)
|
||||
{
|
||||
char buffer[4096] = {0};
|
||||
char *ptr;
|
||||
char **tokens;
|
||||
struct ssh_tokens_st *tokens;
|
||||
|
||||
if (*file == NULL) {
|
||||
*file = fopen(filename,"r");
|
||||
@@ -114,7 +100,7 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
||||
continue; /* skip empty lines */
|
||||
}
|
||||
|
||||
tokens = ssh_space_tokenize(buffer);
|
||||
tokens = ssh_tokenize(buffer, ' ');
|
||||
if (tokens == NULL) {
|
||||
fclose(*file);
|
||||
*file = NULL;
|
||||
@@ -122,13 +108,16 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(tokens[0] == NULL || tokens[1] == NULL || tokens[2] == NULL) {
|
||||
if (tokens->tokens[0] == NULL ||
|
||||
tokens->tokens[1] == NULL ||
|
||||
tokens->tokens[2] == NULL)
|
||||
{
|
||||
/* it should have at least 3 tokens */
|
||||
tokens_free(tokens);
|
||||
ssh_tokens_free(tokens);
|
||||
continue;
|
||||
}
|
||||
|
||||
*found_type = tokens[1];
|
||||
*found_type = tokens->tokens[1];
|
||||
|
||||
return tokens;
|
||||
}
|
||||
@@ -291,20 +280,23 @@ static int match_hashed_host(const char *host, const char *sourcehash)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function is depcrecated
|
||||
* @brief This function is deprecated
|
||||
*
|
||||
* @deprecated Please use ssh_session_is_known_server()
|
||||
* @see ssh_session_is_known_server()
|
||||
*/
|
||||
int ssh_is_server_known(ssh_session session) {
|
||||
int ssh_is_server_known(ssh_session session)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
char **tokens;
|
||||
char *host;
|
||||
char *hostport;
|
||||
const char *type;
|
||||
int match;
|
||||
int i = 0;
|
||||
char *files[3];
|
||||
|
||||
struct ssh_tokens_st *tokens;
|
||||
|
||||
int ret = SSH_SERVER_NOT_KNOWN;
|
||||
|
||||
if (session->opts.knownhosts == NULL) {
|
||||
@@ -329,6 +321,7 @@ int ssh_is_server_known(ssh_session session) {
|
||||
|
||||
return SSH_SERVER_ERROR;
|
||||
}
|
||||
|
||||
host = ssh_lowercase(session->opts.host);
|
||||
hostport = ssh_hostport(host, session->opts.port > 0 ? session->opts.port : 22);
|
||||
if (host == NULL || hostport == NULL) {
|
||||
@@ -339,7 +332,7 @@ int ssh_is_server_known(ssh_session session) {
|
||||
return SSH_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* set the list of known hosts */
|
||||
/* Set the list of known hosts files */
|
||||
i = 0;
|
||||
if (session->opts.global_knownhosts != NULL){
|
||||
files[i++] = session->opts.global_knownhosts;
|
||||
@@ -361,15 +354,17 @@ int ssh_is_server_known(ssh_session session) {
|
||||
else
|
||||
continue;
|
||||
}
|
||||
match = match_hashed_host(host, tokens[0]);
|
||||
match = match_hashed_host(host, tokens->tokens[0]);
|
||||
if (match == 0){
|
||||
match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
|
||||
match = match_hostname(hostport, tokens->tokens[0],
|
||||
strlen(tokens->tokens[0]));
|
||||
}
|
||||
if (match == 0) {
|
||||
match = match_hostname(host, tokens[0], strlen(tokens[0]));
|
||||
match = match_hostname(host, tokens->tokens[0],
|
||||
strlen(tokens->tokens[0]));
|
||||
}
|
||||
if (match == 0) {
|
||||
match = match_hashed_host(hostport, tokens[0]);
|
||||
match = match_hashed_host(hostport, tokens->tokens[0]);
|
||||
}
|
||||
if (match) {
|
||||
ssh_key pubkey = ssh_dh_get_current_server_publickey(session);
|
||||
@@ -386,12 +381,12 @@ int ssh_is_server_known(ssh_session session) {
|
||||
* more important */
|
||||
if (ret != SSH_SERVER_KNOWN_CHANGED)
|
||||
ret = SSH_SERVER_FOUND_OTHER;
|
||||
tokens_free(tokens);
|
||||
ssh_tokens_free(tokens);
|
||||
continue;
|
||||
}
|
||||
/* so we know the key type is good. We may get a good key or a bad key. */
|
||||
match = check_public_key(session, tokens);
|
||||
tokens_free(tokens);
|
||||
match = check_public_key(session, tokens->tokens);
|
||||
ssh_tokens_free(tokens);
|
||||
|
||||
if (match < 0) {
|
||||
ret = SSH_SERVER_ERROR;
|
||||
@@ -404,7 +399,7 @@ int ssh_is_server_known(ssh_session session) {
|
||||
ret = SSH_SERVER_KNOWN_CHANGED;
|
||||
}
|
||||
} else {
|
||||
tokens_free(tokens);
|
||||
ssh_tokens_free(tokens);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user