diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-05-07 12:58:56 +0200 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-05-07 12:58:56 +0200 |
commit | 7f59662cade9e22d529d731fc3b403d04adc2fb9 (patch) | |
tree | 58596e0812f2242b56caae3c25970c9db8763786 | |
parent | e9d6b15926214706bdc46ea1eccfab812956df1e (diff) | |
download | libssh-7f59662cade9e22d529d731fc3b403d04adc2fb9.tar.gz libssh-7f59662cade9e22d529d731fc3b403d04adc2fb9.tar.xz libssh-7f59662cade9e22d529d731fc3b403d04adc2fb9.zip |
knownhosts writing cherry-pick
Conflicts:
libssh/keyfiles.c
tests/unittests/CMakeLists.txt
-rw-r--r-- | libssh/keyfiles.c | 50 | ||||
-rw-r--r-- | tests/unittests/torture_knownhosts.c | 108 |
2 files changed, 145 insertions, 13 deletions
diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index 49741f3a..7be2d99e 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -1658,10 +1658,15 @@ int ssh_is_server_known(ssh_session session) { return ret; } -/** You generaly use it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN - * \brief write the current server as known in the known hosts file. This will create the known hosts file if it does not exist. - * \param session ssh session - * \return 0 on success, -1 on error +/** + * @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) { ssh_string pubkey = session->current_crypto->server_pubkey; @@ -1669,8 +1674,25 @@ int ssh_write_knownhost(ssh_session session) { char buffer[4096] = {0}; FILE *file; char *dir; + char *host; + char *hostport; size_t len = 0; + if (session->host == NULL) { + ssh_set_error(session, SSH_FATAL, + "Can't write host in known hosts if the hostname isn't known"); + return SSH_ERROR; + } + + host = ssh_lowercase(session->host); + /* If using a nonstandard port, save the host in the [host]:port format */ + if(session->port != 22){ + hostport = ssh_hostport(host,session->port); + SAFE_FREE(host); + host=hostport; + hostport=NULL; + } + if (session->knownhosts == NULL) { if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) { ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); @@ -1678,12 +1700,6 @@ int ssh_write_knownhost(ssh_session session) { } } - if (session->host == NULL) { - ssh_set_error(session, SSH_FATAL, - "Cannot write host in known hosts if the hostname is unknown"); - return -1; - } - /* Check if ~/.ssh exists and create it if not */ dir = ssh_dirname(session->knownhosts); if (dir == NULL) { @@ -1705,6 +1721,7 @@ int ssh_write_knownhost(ssh_session session) { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s for appending: %s", session->knownhosts, strerror(errno)); + SAFE_FREE(host); return -1; } @@ -1724,6 +1741,7 @@ int ssh_write_knownhost(ssh_session session) { key = publickey_from_string(session, pubkey); if (key == NULL) { fclose(file); + SAFE_FREE(host); return -1; } @@ -1732,6 +1750,7 @@ int ssh_write_knownhost(ssh_session session) { if (sexp == NULL) { publickey_free(key); fclose(file); + SAFE_FREE(host); return -1; } e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); @@ -1739,6 +1758,7 @@ int ssh_write_knownhost(ssh_session session) { if (e == NULL) { publickey_free(key); fclose(file); + SAFE_FREE(host); return -1; } @@ -1747,6 +1767,7 @@ int ssh_write_knownhost(ssh_session session) { publickey_free(key); bignum_free(e); fclose(file); + SAFE_FREE(host); return -1; } n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); @@ -1755,6 +1776,7 @@ int ssh_write_knownhost(ssh_session session) { publickey_free(key); bignum_free(e); fclose(file); + SAFE_FREE(host); return -1; } @@ -1779,12 +1801,13 @@ int ssh_write_knownhost(ssh_session session) { #endif publickey_free(key); fclose(file); + SAFE_FREE(host); return -1; } snprintf(buffer, sizeof(buffer), "%s %d %s %s\n", - session->host, + host, rsa_size << 3, e_string, n_string); @@ -1804,18 +1827,19 @@ int ssh_write_knownhost(ssh_session session) { pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey)); if (pubkey_64 == NULL) { fclose(file); + SAFE_FREE(host); return -1; } snprintf(buffer, sizeof(buffer), "%s %s %s\n", - session->host, + host, session->current_crypto->server_pubkey_type, pubkey_64); SAFE_FREE(pubkey_64); } - + SAFE_FREE(host); len = strlen(buffer); if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) { fclose(file); diff --git a/tests/unittests/torture_knownhosts.c b/tests/unittests/torture_knownhosts.c new file mode 100644 index 00000000..29b8f897 --- /dev/null +++ b/tests/unittests/torture_knownhosts.c @@ -0,0 +1,108 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2010 by Aris Adamantiadis + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#define LIBSSH_STATIC + +#include "torture.h" +#include "libssh/libssh.h" +#include "libssh/priv.h" +#include "libssh/session.h" +ssh_session session; + +#define KNOWNHOSTFILES "libssh_torture_knownhosts" + +static void setup(void) { + session = ssh_new(); +} + +static void teardown(void) { + ssh_free(session); + unlink(KNOWNHOSTFILES); +} + +START_TEST (torture_knownhosts_port) +{ + int rc; + char buffer[200]; + FILE *file; + /* Connect to localhost:22, force the port to 1234 and then write + * the known hosts file. Then check that the entry written is + * [localhost]:1234 + */ + ssh_options_set(session,SSH_OPTIONS_HOST,"localhost"); + ssh_options_set(session,SSH_OPTIONS_KNOWNHOSTS,KNOWNHOSTFILES); + rc=ssh_connect(session); + ck_assert_int_eq(rc,SSH_OK); + session->port=1234; + rc=ssh_write_knownhost(session); + ck_assert_int_eq(rc,SSH_OK); + ssh_disconnect(session); + ssh_free(session); + file=fopen(KNOWNHOSTFILES,"r"); + ck_assert(file != NULL); + fgets(buffer,sizeof(buffer),file); + buffer[sizeof(buffer)-1]='\0'; + ck_assert(strstr(buffer,"[localhost]:1234 ") != NULL); + fclose(file); + + /* now, connect back to the ssh server and verify the known host line */ + session=ssh_new(); + ssh_options_set(session,SSH_OPTIONS_HOST,"localhost"); + ssh_options_set(session,SSH_OPTIONS_KNOWNHOSTS,KNOWNHOSTFILES); + rc=ssh_connect(session); + ck_assert_int_eq(rc,SSH_OK); + session->port=1234; + rc=ssh_is_server_known(session); + ck_assert_int_eq(rc,SSH_SERVER_KNOWN_OK); + ssh_disconnect(session); +} +END_TEST + +static Suite *torture_make_suite(void) { + Suite *s = suite_create("libssh_knownhosts"); + + torture_create_case_fixture(s, "torture_knownhosts_port", + torture_knownhosts_port, setup, teardown); + return s; +} + +int main(int argc, char **argv) { + Suite *s = NULL; + SRunner *sr = NULL; + struct argument_s arguments; + int nf; + + ZERO_STRUCT(arguments); + + torture_cmdline_parse(argc, argv, &arguments); + + s = torture_make_suite(); + + sr = srunner_create(s); + if (arguments.nofork) { + srunner_set_fork_status(sr, CK_NOFORK); + } + srunner_run_all(sr, CK_VERBOSE); + nf = srunner_ntests_failed(sr); + srunner_free(sr); + + return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} |