knownhosts: Add ssh_session_has_known_hosts_entry()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
родитель
32c49ea134
Коммит
963c46e4fb
@ -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();
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user