aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/server/CMakeLists.txt1
-rw-r--r--tests/server/torture_server_algorithms.c364
2 files changed, 365 insertions, 0 deletions
diff --git a/tests/server/CMakeLists.txt b/tests/server/CMakeLists.txt
index ebe2d169..96457cd2 100644
--- a/tests/server/CMakeLists.txt
+++ b/tests/server/CMakeLists.txt
@@ -10,6 +10,7 @@ set(LIBSSH_SERVER_TESTS
torture_server
torture_server_auth_kbdint
torture_server_config
+ torture_server_algorithms
)
include_directories(${libssh_SOURCE_DIR}/include
diff --git a/tests/server/torture_server_algorithms.c b/tests/server/torture_server_algorithms.c
new file mode 100644
index 00000000..3963e368
--- /dev/null
+++ b/tests/server/torture_server_algorithms.c
@@ -0,0 +1,364 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2019 by Red Hat, Inc.
+ *
+ * Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#define LIBSSH_STATIC
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+
+#include "torture.h"
+#include "torture_key.h"
+#include "libssh/libssh.h"
+#include "libssh/priv.h"
+#include "libssh/session.h"
+#include "libssh/token.h"
+
+#include "test_server.h"
+#include "default_cb.h"
+
+const char template[] = "temp_dir_XXXXXX";
+
+struct test_server_st {
+ struct torture_state *state;
+ char *cwd;
+ char *temp_dir;
+ char rsa_hostkey[1024];
+};
+
+static int setup_files(void **state)
+{
+ struct test_server_st *tss;
+ struct torture_state *s;
+ char sshd_path[1024];
+
+ int rc;
+
+ tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st));
+ assert_non_null(tss);
+
+ torture_setup_socket_dir((void **)&s);
+ assert_non_null(s->socket_dir);
+
+ /* Set the default interface for the server */
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
+
+ snprintf(sshd_path,
+ sizeof(sshd_path),
+ "%s/sshd",
+ s->socket_dir);
+
+ rc = mkdir(sshd_path, 0755);
+ assert_return_code(rc, errno);
+
+ snprintf(tss->rsa_hostkey,
+ sizeof(tss->rsa_hostkey),
+ "%s/sshd/ssh_host_rsa_key",
+ s->socket_dir);
+ torture_write_file(tss->rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0));
+
+ tss->state = s;
+ *state = tss;
+
+ return 0;
+}
+
+static int teardown_files(void **state)
+{
+ struct torture_state *s;
+ struct test_server_st *tss;
+
+ tss = *state;
+ assert_non_null(tss);
+
+ s = tss->state;
+ assert_non_null(s);
+
+ torture_teardown_socket_dir((void **)&s);
+ SAFE_FREE(tss);
+
+ return 0;
+}
+
+static int setup_temp_dir(void **state)
+{
+ struct test_server_st *tss = *state;
+ struct torture_state *s;
+
+ char *cwd = NULL;
+ char *tmp_dir = NULL;
+
+ assert_non_null(tss);
+
+ s = tss->state;
+ assert_non_null(s);
+
+ cwd = torture_get_current_working_dir();
+ assert_non_null(cwd);
+
+ tmp_dir = torture_make_temp_dir(template);
+ assert_non_null(tmp_dir);
+
+ tss->cwd = cwd;
+ tss->temp_dir = tmp_dir;
+
+ return 0;
+}
+
+static int teardown_temp_dir(void **state)
+{
+ struct test_server_st *tss = *state;
+ int rc;
+
+ assert_non_null(tss);
+
+ rc = torture_change_dir(tss->cwd);
+ assert_int_equal(rc, 0);
+
+ rc = torture_rmdirs(tss->temp_dir);
+ assert_int_equal(rc, 0);
+
+ SAFE_FREE(tss->temp_dir);
+ SAFE_FREE(tss->cwd);
+
+ return 0;
+}
+
+static int start_server(void **state)
+{
+ struct test_server_st *tss = *state;
+ struct torture_state *s;
+
+ assert_non_null(tss);
+
+ s = tss->state;
+ assert_non_null(s);
+
+ /* Start the server using the default values */
+ torture_setup_libssh_server((void **)&s, "./test_server/test_server");
+ assert_non_null(s);
+
+ return 0;
+}
+
+static int stop_server(void **state)
+{
+ struct torture_state *s;
+ struct test_server_st *tss;
+
+ int rc;
+
+ tss = *state;
+ assert_non_null(tss);
+
+ s = tss->state;
+ assert_non_null(s);
+
+ rc = torture_terminate_process(s->srv_pidfile);
+ assert_return_code(rc, errno);
+
+ unlink(s->srv_pidfile);
+
+ return 0;
+}
+
+static int session_setup(void **state)
+{
+ struct test_server_st *tss = *state;
+ struct torture_state *s;
+ int verbosity = torture_libssh_verbosity();
+ struct passwd *pwd;
+ bool b = false;
+ int rc;
+
+ assert_non_null(tss);
+
+ /* Make sure we do not test the agent */
+ unsetenv("SSH_AUTH_SOCK");
+
+ s = tss->state;
+ assert_non_null(s);
+
+ pwd = getpwnam("bob");
+ assert_non_null(pwd);
+
+ rc = setuid(pwd->pw_uid);
+ assert_return_code(rc, errno);
+
+ s->ssh.session = ssh_new();
+ assert_non_null(s->ssh.session);
+
+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+ assert_ssh_return_code(s->ssh.session, rc);
+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
+ assert_ssh_return_code(s->ssh.session, rc);
+ /* Make sure no other configuration options from system will get used */
+ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
+ assert_ssh_return_code(s->ssh.session, rc);
+
+ return 0;
+}
+
+static int session_teardown(void **state)
+{
+ struct test_server_st *tss = *state;
+ struct torture_state *s;
+
+ assert_non_null(tss);
+
+ s = tss->state;
+ assert_non_null(s);
+
+ ssh_disconnect(s->ssh.session);
+ ssh_free(s->ssh.session);
+
+ return 0;
+}
+
+/*
+ * Check that the handshake works with an AEAD cipher configured
+ * but with no overlap for HMACs. AEAD ciphers have an implied HMAC
+ * so no HMAC overlap in the handshake should not fail the connection.
+ */
+static void test_algorithm_no_hmac_overlap(void **state, const char *algorithm)
+{
+ struct test_server_st *tss = *state;
+ struct torture_state *s = NULL;
+ char config_content[4096];
+
+ ssh_session session = NULL;
+
+ int rc;
+
+ assert_non_null(tss);
+ s = tss->state;
+ assert_non_null(s);
+
+ /* Prepare key files */
+ snprintf(config_content,
+ sizeof(config_content),
+ "HostKey %s\nCiphers %s\nMACs %s\n",
+ tss->rsa_hostkey,
+ algorithm,
+ "hmac-sha2-512-etm@openssh.com");
+
+ assert_non_null(s->srv_config);
+ torture_write_file(s->srv_config, config_content);
+
+ fprintf(stderr, "Config file %s content: \n\n%s\n", s->srv_config,
+ config_content);
+ fflush(stderr);
+
+ /* Start server */
+ rc = start_server(state);
+ assert_int_equal(rc, 0);
+
+ /* Setup session */
+ rc = session_setup(state);
+ assert_int_equal(rc, 0);
+
+ session = s->ssh.session;
+ assert_non_null(session);
+
+ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, algorithm);
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, algorithm);
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, "hmac-sha2-512");
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "hmac-sha2-512");
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_connect(session);
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_userauth_none(session, NULL);
+ /* This request should return a SSH_REQUEST_DENIED error */
+ if (rc == SSH_ERROR) {
+ assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
+ }
+ rc = ssh_userauth_list(session, NULL);
+ assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);
+
+ rc = ssh_userauth_publickey_auto(session, NULL, NULL);
+ assert_ssh_return_code(session, rc);
+
+ rc = session_teardown(state);
+ assert_int_equal(rc, 0);
+
+ rc = stop_server(state);
+ assert_int_equal(rc, 0);
+
+ SAFE_FREE(s->srv_additional_config);
+}
+
+static void torture_algorithm_chacha20_with_no_hmac_overlap(void **state)
+{
+ if (ssh_fips_mode()) {
+ skip();
+ }
+ test_algorithm_no_hmac_overlap(state, "chacha20-poly1305@openssh.com");
+}
+
+static void torture_algorithm_aes256gcm_with_no_hmac_overlap(void **state)
+{
+ test_algorithm_no_hmac_overlap(state, "aes256-gcm@openssh.com");
+}
+
+static void torture_algorithm_aes128gcm_with_no_hmac_overlap(void **state)
+{
+ test_algorithm_no_hmac_overlap(state, "aes128-gcm@openssh.com");
+}
+
+int torture_run_tests(void)
+{
+ int rc;
+ struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(torture_algorithm_chacha20_with_no_hmac_overlap,
+ setup_temp_dir, teardown_temp_dir),
+ cmocka_unit_test_setup_teardown(torture_algorithm_aes256gcm_with_no_hmac_overlap,
+ setup_temp_dir, teardown_temp_dir),
+ cmocka_unit_test_setup_teardown(torture_algorithm_aes128gcm_with_no_hmac_overlap,
+ setup_temp_dir, teardown_temp_dir),
+ };
+
+ ssh_init();
+
+ torture_filter_tests(tests);
+ rc = cmocka_run_group_tests(tests,
+ setup_files,
+ teardown_files);
+
+ ssh_finalize();
+
+ return rc;
+}