aboutsummaryrefslogtreecommitdiff
path: root/src/known_hosts.c
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2014-02-01 16:35:13 +0100
committerAris Adamantiadis <aris@0xbadc0de.be>2014-02-01 16:42:29 +0100
commitc433ac02bdfb5ec8d9a16074794be587cced59c1 (patch)
tree4cc01035d110b428b70e5bd4870bf78c7f8c3671 /src/known_hosts.c
parent1c24a0508f6fdd30257003b874327772320c5ee0 (diff)
downloadlibssh-c433ac02bdfb5ec8d9a16074794be587cced59c1.tar.gz
libssh-c433ac02bdfb5ec8d9a16074794be587cced59c1.tar.xz
libssh-c433ac02bdfb5ec8d9a16074794be587cced59c1.zip
known_hosts: add ssh_knownhosts_algorithms()
Goal of that function is to test the preferred key exchange methods based on what's available in the known_hosts file
Diffstat (limited to 'src/known_hosts.c')
-rw-r--r--src/known_hosts.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/known_hosts.c b/src/known_hosts.c
index ded36a90..2d90a41d 100644
--- a/src/known_hosts.c
+++ b/src/known_hosts.c
@@ -647,6 +647,83 @@ int ssh_write_knownhost(ssh_session session) {
return 0;
}
+/**
+ * @brief Check which kind of host keys should be preferred for connection
+ * by reading the known_hosts file.
+ *
+ * @param[in] session The SSH session to use.
+ *
+ * @returns Bitfield of supported SSH hostkey algorithms
+ * SSH_ERROR on error
+ */
+int ssh_knownhosts_algorithms(ssh_session session) {
+ FILE *file = NULL;
+ char **tokens;
+ char *host;
+ char *hostport;
+ const char *type;
+ int match;
+ int ret = 0;
+
+ 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_ERROR;
+ }
+ }
+
+ if (session->opts.host == NULL) {
+ return 0;
+ }
+
+ host = ssh_lowercase(session->opts.host);
+ hostport = ssh_hostport(host, session->opts.port);
+ if (host == NULL || hostport == NULL) {
+ ssh_set_error_oom(session);
+ SAFE_FREE(host);
+ SAFE_FREE(hostport);
+
+ return SSH_ERROR;
+ }
+
+ do {
+ tokens = ssh_get_knownhost_line(&file,
+ session->opts.knownhosts, &type);
+
+ /* End of file, return the current state */
+ if (tokens == NULL) {
+ break;
+ }
+ match = match_hashed_host(host, tokens[0]);
+ if (match == 0){
+ match = match_hostname(hostport, tokens[0], strlen(tokens[0]));
+ }
+ if (match == 0) {
+ match = match_hostname(host, tokens[0], strlen(tokens[0]));
+ }
+ if (match == 0) {
+ match = match_hashed_host(hostport, tokens[0]);
+ }
+ if (match) {
+ /* We got a match. Now check the key type */
+ SSH_LOG(SSH_LOG_DEBUG, "server %s:%d has %s in known_hosts",
+ host, session->opts.port, type);
+ ret |= 1 << ssh_key_type_from_name(type);
+ }
+ tokens_free(tokens);
+ } while (1);
+
+ SAFE_FREE(host);
+ SAFE_FREE(hostport);
+ if (file != NULL) {
+ fclose(file);
+ }
+
+ /* Return the current state at end of file */
+ return ret;
+}
+
/** @} */
/* vim: set ts=4 sw=4 et cindent: */