diff options
author | Stef Walter <stefw@redhat.com> | 2015-11-09 14:24:54 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2016-11-05 17:12:07 +0100 |
commit | 857ce2376eb82286461d39176fa51551a7bfaee7 (patch) | |
tree | f41eaf81c0b828be8f75f554c27c8ad1f8a75955 /src/known_hosts.c | |
parent | 1bf6c965e491e1851c8102dafa4a87c4deb085d9 (diff) | |
download | libssh-857ce2376eb82286461d39176fa51551a7bfaee7.tar.gz libssh-857ce2376eb82286461d39176fa51551a7bfaee7.tar.xz libssh-857ce2376eb82286461d39176fa51551a7bfaee7.zip |
known_hosts: Add ssh_dump_knownhost() function
This works similarly to ssh_write_knownhost(), but allows the caller
to get a line with the known_hosts line.
BUG: https://red.libssh.org/issues/207
Signed-off-by: Stef Walter <stefw@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'src/known_hosts.c')
-rw-r--r-- | src/known_hosts.c | 141 |
1 files changed, 84 insertions, 57 deletions
diff --git a/src/known_hosts.c b/src/known_hosts.c index ab8a3dcb..2f66cc27 100644 --- a/src/known_hosts.c +++ b/src/known_hosts.c @@ -514,30 +514,29 @@ int ssh_is_server_known(ssh_session session) { } /** - * @brief Write the current server as known in the known hosts file. + * @brief Output the current server as a known host line. * - * This will create the known hosts file if it does not exist. You generaly use - * it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN. + * This could be placed in a known hosts file after user confirmation. + * The return value should be passed to free() after the caller is done with it. * * @param[in] session The ssh session to use. * - * @return SSH_OK on success, SSH_ERROR on error. + * @return string on success, NULL on error. */ -int ssh_write_knownhost(ssh_session session) { - ssh_key key; +char * ssh_dump_knownhost(ssh_session session) { ssh_string pubkey_s; - char *b64_key; - char buffer[4096] = {0}; - FILE *file; - char *dir; + ssh_key key; char *host; char *hostport; + size_t len = 4096; + char *buffer; + char *b64_key; int rc; if (session->opts.host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't write host in known hosts if the hostname isn't known"); - return SSH_ERROR; + return NULL; } host = ssh_lowercase(session->opts.host); @@ -546,88 +545,58 @@ int ssh_write_knownhost(ssh_session session) { hostport = ssh_hostport(host, session->opts.port); SAFE_FREE(host); if (hostport == NULL) { - return SSH_ERROR; + return NULL; } host = hostport; hostport = NULL; } - if (session->opts.knownhosts == NULL) { - if (ssh_options_apply(session) < 0) { - ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); - SAFE_FREE(host); - return SSH_ERROR; - } - } - if (session->current_crypto==NULL) { ssh_set_error(session, SSH_FATAL, "No current crypto context"); SAFE_FREE(host); - return SSH_ERROR; + return NULL; } pubkey_s = session->current_crypto->server_pubkey; if (pubkey_s == NULL){ ssh_set_error(session, SSH_FATAL, "No public key present"); SAFE_FREE(host); - return SSH_ERROR; + return NULL; } - /* Check if ~/.ssh exists and create it if not */ - dir = ssh_dirname(session->opts.knownhosts); - if (dir == NULL) { - ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); + rc = ssh_pki_import_pubkey_blob(pubkey_s, &key); + if (rc < 0) { SAFE_FREE(host); - return SSH_ERROR; + return NULL; } - if (!ssh_file_readaccess_ok(dir)) { - if (ssh_mkdir(dir, 0700) < 0) { - ssh_set_error(session, SSH_FATAL, - "Cannot create %s directory.", dir); - SAFE_FREE(dir); - SAFE_FREE(host); - return SSH_ERROR; - } - } - SAFE_FREE(dir); - - file = fopen(session->opts.knownhosts, "a"); - if (file == NULL) { - ssh_set_error(session, SSH_FATAL, - "Couldn't open known_hosts file %s for appending: %s", - session->opts.knownhosts, strerror(errno)); + buffer = calloc (1, 4096); + if (!buffer) { + ssh_key_free(key); SAFE_FREE(host); - return SSH_ERROR; - } - - rc = ssh_pki_import_pubkey_blob(pubkey_s, &key); - if (rc < 0) { - fclose(file); - SAFE_FREE(host); - return -1; + return NULL; } if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) { /* openssh uses a different format for ssh-rsa1 keys. Be compatible --kv */ - rc = ssh_pki_export_pubkey_rsa1(key, host, buffer, sizeof(buffer)); + rc = ssh_pki_export_pubkey_rsa1(key, host, buffer, len); ssh_key_free(key); SAFE_FREE(host); if (rc < 0) { - fclose(file); - return -1; + SAFE_FREE(buffer); + return NULL; } } else { rc = ssh_pki_export_pubkey_base64(key, &b64_key); if (rc < 0) { ssh_key_free(key); - fclose(file); + SAFE_FREE(buffer); SAFE_FREE(host); - return -1; + return NULL; } - snprintf(buffer, sizeof(buffer), + snprintf(buffer, len, "%s %s %s\n", host, key->type_c, @@ -638,11 +607,69 @@ int ssh_write_knownhost(ssh_session session) { SAFE_FREE(b64_key); } + return buffer; +} + +/** + * @brief Write the current server as known in the known hosts file. + * + * This will create the known hosts file if it does not exist. You generaly use + * it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN. + * + * @param[in] session The ssh session to use. + * + * @return SSH_OK on success, SSH_ERROR on error. + */ +int ssh_write_knownhost(ssh_session session) { + FILE *file; + char *buffer; + char *dir; + + if (session->opts.knownhosts == NULL) { + if (ssh_options_apply(session) < 0) { + ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); + return SSH_ERROR; + } + } + + /* Check if directory exists and create it if not */ + dir = ssh_dirname(session->opts.knownhosts); + if (dir == NULL) { + ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); + return SSH_ERROR; + } + + if (!ssh_file_readaccess_ok(dir)) { + if (ssh_mkdir(dir, 0700) < 0) { + ssh_set_error(session, SSH_FATAL, + "Cannot create %s directory.", dir); + SAFE_FREE(dir); + return SSH_ERROR; + } + } + SAFE_FREE(dir); + + file = fopen(session->opts.knownhosts, "a"); + if (file == NULL) { + ssh_set_error(session, SSH_FATAL, + "Couldn't open known_hosts file %s for appending: %s", + session->opts.knownhosts, strerror(errno)); + return SSH_ERROR; + } + + buffer = ssh_dump_knownhost(session); + if (buffer == NULL) { + fclose(file); + return SSH_ERROR; + } + if (fwrite(buffer, strlen(buffer), 1, file) != 1 || ferror(file)) { + SAFE_FREE(buffer); fclose(file); return -1; } + SAFE_FREE(buffer); fclose(file); return 0; } |