1
1

knownhosts: Add ssh_session_has_known_hosts_entry()

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
Andreas Schneider 2018-02-03 16:53:21 +01:00
родитель 32c49ea134
Коммит 963c46e4fb
3 изменённых файлов: 127 добавлений и 0 удалений

Просмотреть файл

@ -238,6 +238,15 @@ enum ssh_server_known_e {
SSH_SERVER_FILE_NOT_FOUND
};
enum ssh_known_hosts_e {
SSH_KNOWN_HOSTS_ERROR = -2,
SSH_KNOWN_HOSTS_NOT_FOUND = -1,
SSH_KNOWN_HOSTS_UNKNOWN = 0,
SSH_KNOWN_HOSTS_OK,
SSH_KNOWN_HOSTS_CHANGED,
SSH_KNOWN_HOSTS_OTHER,
};
#ifndef MD5_DIGEST_LEN
#define MD5_DIGEST_LEN 16
#endif
@ -527,6 +536,7 @@ LIBSSH_API void ssh_knownhosts_entry_free(struct ssh_knownhosts_entry *entry);
LIBSSH_API int ssh_known_hosts_parse_line(const char *host,
const char *line,
struct ssh_knownhosts_entry **entry);
LIBSSH_API enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session);
/* LOGGING */
LIBSSH_API int ssh_set_log_level(int level);

Просмотреть файл

@ -229,6 +229,40 @@ error:
return SSH_ERROR;
}
static char *ssh_session_get_host_port(ssh_session session)
{
char *host_port;
char *host;
if (session->opts.host == NULL) {
ssh_set_error(session,
SSH_FATAL,
"Can't verify server inn known hosts if the host we "
"should connect to has not been set");
return NULL;
}
host = ssh_lowercase(session->opts.host);
if (host == NULL) {
ssh_set_error_oom(session);
return NULL;
}
if (session->opts.port == 0 || session->opts.port == 22) {
host_port = host;
} else {
host_port = ssh_hostport(host, session->opts.port);
SAFE_FREE(host);
if (host_port == NULL) {
ssh_set_error_oom(session);
return NULL;
}
}
return host_port;
}
/**
* @brief Parse a line from a known_hosts entry into a structure
*
@ -380,3 +414,60 @@ out:
ssh_knownhosts_entry_free(e);
return rc;
}
/**
* @brief Check if the set hostname and port matches an entry in known_hosts.
*
* This check if the set hostname and port has an entry in the known_hosts file.
* You need to set at least the hostname using ssh_options_set().
*
* @param[in] session The session with with the values set to check.
*
* @return A @ssh_known_hosts_e return value.
*/
enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
{
struct ssh_list *entry_list = NULL;
struct ssh_iterator *it = NULL;
char *host_port = NULL;
int rc;
if (session->opts.knownhosts == NULL) {
if (ssh_options_apply(session) < 0) {
ssh_set_error(session,
SSH_REQUEST_DENIED,
"Can't find a known_hosts file");
return SSH_KNOWN_HOSTS_NOT_FOUND;
}
}
host_port = ssh_session_get_host_port(session);
if (host_port == NULL) {
return SSH_KNOWN_HOSTS_NOT_FOUND;
}
rc = ssh_known_hosts_read_entries(host_port,
session->opts.knownhosts,
&entry_list);
if (rc != 0) {
return SSH_KNOWN_HOSTS_NOT_FOUND;
}
if (ssh_list_count(entry_list) == 0) {
return SSH_KNOWN_HOSTS_NOT_FOUND;
}
for (it = ssh_list_get_iterator(entry_list);
it != NULL;
it = ssh_list_get_iterator(entry_list)) {
struct ssh_knownhosts_entry *entry = NULL;
entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it);
ssh_knownhosts_entry_free(entry);
ssh_list_remove(entry_list, it);
}
ssh_list_free(entry_list);
return SSH_KNOWN_HOSTS_OK;
}

Просмотреть файл

@ -226,6 +226,29 @@ static void torture_knownhosts_read_file(void **state)
}
}
static void torture_knownhosts_host_exists(void **state)
{
const char *knownhosts_file = *state;
enum ssh_known_hosts_e found;
ssh_session session;
session = ssh_new();
assert_non_null(session);
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file);
found = ssh_session_has_known_hosts_entry(session);
assert_int_equal(found, SSH_KNOWN_HOSTS_OK);
assert_true(found == SSH_KNOWN_HOSTS_OK);
ssh_options_set(session, SSH_OPTIONS_HOST, "wurstbrot");
found = ssh_session_has_known_hosts_entry(session);
assert_true(found == SSH_KNOWN_HOSTS_NOT_FOUND);
ssh_free(session);
}
int torture_run_tests(void) {
int rc;
struct CMUnitTest tests[] = {
@ -238,6 +261,9 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_knownhosts_read_file,
setup_knownhosts_file,
teardown_knownhosts_file),
cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists,
setup_knownhosts_file,
teardown_knownhosts_file),
};
ssh_init();