From 2b76abb74c75a6e378d373f8cc2d3d63d2e7d6b3 Mon Sep 17 00:00:00 2001 From: Sahana Prasad Date: Fri, 20 Dec 2019 09:16:29 +0100 Subject: [PATCH] clienttest: Adds a client test that authenticates to the ssh server using ssh_connect through key obtained through PKCS11 URIs. Signed-Off-by: Sahana Prasad Reviewed-by: Jakub Jelen Reviewed-by: Andreas Schneider --- tests/client/CMakeLists.txt | 6 + tests/client/torture_auth_pkcs11.c | 260 +++++++++++++++++++++++++++++ tests/torture.h | 1 + 3 files changed, 267 insertions(+) create mode 100644 tests/client/torture_auth_pkcs11.c diff --git a/tests/client/CMakeLists.txt b/tests/client/CMakeLists.txt index 70b5de3e..e6adfe36 100644 --- a/tests/client/CMakeLists.txt +++ b/tests/client/CMakeLists.txt @@ -24,6 +24,12 @@ if (SCP_EXECUTABLE) torture_scp) endif() +if (WITH_PKCS11_URI) + set(LIBSSH_CLIENT_TESTS + ${LIBSSH_CLIENT_TESTS} + torture_auth_pkcs11) +endif() + if (DEFAULT_C_NO_DEPRECATION_FLAGS) set_source_files_properties(torture_knownhosts.c PROPERTIES diff --git a/tests/client/torture_auth_pkcs11.c b/tests/client/torture_auth_pkcs11.c new file mode 100644 index 00000000..7c7db8c9 --- /dev/null +++ b/tests/client/torture_auth_pkcs11.c @@ -0,0 +1,260 @@ +/* + * 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. + */ + +#include "config.h" + +#define LIBSSH_STATIC + +#include "torture.h" +#include "libssh/libssh.h" +#include "libssh/priv.h" +#include "libssh/session.h" + +#include +#include +#include + +/* agent_is_running */ +#include "agent.c" + +#define LIBSSH_RSA_TESTKEY "id_pkcs11_rsa" +#define LIBSSH_ECDSA_256_TESTKEY "id_pkcs11_ecdsa_256" +#define LIBSSH_ECDSA_384_TESTKEY "id_pkcs11_ecdsa_384" +#define LIBSSH_ECDSA_521_TESTKEY "id_pkcs11_ecdsa_521" +#define SOFTHSM_CONF "softhsm.conf" + +const char template[] = "temp_dir_XXXXXX"; + +struct pki_st { + char *temp_dir; + char *orig_dir; + char *keys_dir; +}; + +static int setup_tokens(void **state, const char *type, const char *obj_name) +{ + struct torture_state *s = *state; + struct pki_st *test_state = s->private_data; + char priv_filename[1024]; + char *cwd = NULL; + + cwd = test_state->temp_dir; + assert_non_null(cwd); + + snprintf(priv_filename, sizeof(priv_filename), "%s%s", test_state->keys_dir, type); + + torture_setup_tokens(cwd, priv_filename, obj_name); + + return 0; +} +static int session_setup(void **state) +{ + int verbosity = torture_libssh_verbosity(); + struct torture_state *s = *state; + struct passwd *pwd; + bool b = false; + int rc; + + 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); + + ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); + /* 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); + + /* Make sure we do not interfere with another ssh-agent */ + unsetenv("SSH_AUTH_SOCK"); + unsetenv("SSH_AGENT_PID"); + + return 0; +} + +static int session_teardown(void **state) +{ + struct torture_state *s = *state; + + ssh_disconnect(s->ssh.session); + ssh_free(s->ssh.session); + + return 0; +} +static int setup_session(void **state) +{ + struct torture_state *s = *state; + struct pki_st *test_state = NULL; + int rc; + char conf_path[1024] = {0}; + char keys_dir[1024] = {0}; + char *temp_dir; + + test_state = malloc(sizeof(struct pki_st)); + assert_non_null(test_state); + + s->private_data = test_state; + + test_state->orig_dir = strdup(torture_get_current_working_dir()); + assert_non_null(test_state->orig_dir); + + temp_dir = torture_make_temp_dir(template); + assert_non_null(temp_dir); + + rc = torture_change_dir(temp_dir); + assert_int_equal(rc, 0); + + test_state->temp_dir = strdup(torture_get_current_working_dir()); + assert_non_null(test_state->temp_dir); + + snprintf(keys_dir, sizeof(keys_dir), "%s/tests/keys/pkcs11/", SOURCEDIR); + + test_state->keys_dir = strdup(keys_dir); + + snprintf(conf_path, sizeof(conf_path), "%s/softhsm.conf", test_state->temp_dir); + setenv("SOFTHSM2_CONF", conf_path, 1); + + setup_tokens(state, LIBSSH_RSA_TESTKEY, "rsa"); + setup_tokens(state, LIBSSH_ECDSA_256_TESTKEY, "ecdsa256"); + setup_tokens(state, LIBSSH_ECDSA_384_TESTKEY, "ecdsa384"); + setup_tokens(state, LIBSSH_ECDSA_521_TESTKEY, "ecdsa521"); + + return 0; +} + +static int sshd_setup(void **state) +{ + + torture_setup_sshd_server(state, true); + setup_session(state); + + return 0; +} + +static int sshd_teardown(void **state) { + + struct torture_state *s = *state; + struct pki_st *test_state = s->private_data; + int rc; + + unsetenv("SOFTHSM2_CONF"); + + rc = torture_change_dir(test_state->orig_dir); + assert_int_equal(rc, 0); + + rc = torture_rmdirs(test_state->temp_dir); + assert_int_equal(rc, 0); + + SAFE_FREE(test_state->temp_dir); + SAFE_FREE(test_state->orig_dir); + SAFE_FREE(test_state->keys_dir); + SAFE_FREE(test_state); + + torture_teardown_sshd_server(state); + + return 0; +} + +static void torture_auth_autopubkey(void **state, const char *obj_name, const char *pin) { + struct torture_state *s = *state; + ssh_session session = s->ssh.session; + int rc; + int verbosity = 4; + char priv_uri[1042]; + /* Authenticate as charlie with bob his pubkey */ + rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_CHARLIE); + assert_int_equal(rc, SSH_OK); + + rc = ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + assert_int_equal(rc, SSH_OK); + + //rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, "pkcs11"); + //assert_int_equal(rc, SSH_OK); + + snprintf(priv_uri, sizeof(priv_uri), "pkcs11:token=%s;object=%s;type=private?pin-value=%s", + obj_name, obj_name, pin); + + rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, priv_uri); + assert_int_equal(rc, SSH_OK); + assert_string_equal(session->opts.identity->root->data, priv_uri); + + 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_int_equal(rc, SSH_AUTH_SUCCESS); +} + +static void torture_auth_autopubkey_rsa(void **state) { + torture_auth_autopubkey(state, "rsa", "1234"); +} + +static void torture_auth_autopubkey_ecdsa_key_256(void **state) { + torture_auth_autopubkey(state, "ecdsa256", "1234"); +} + +static void torture_auth_autopubkey_ecdsa_key_384(void **state) { + torture_auth_autopubkey(state, "ecdsa384", "1234"); +} + +static void torture_auth_autopubkey_ecdsa_key_521(void **state) { + torture_auth_autopubkey(state, "ecdsa521", "1234"); +} + +int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(torture_auth_autopubkey_rsa, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_autopubkey_ecdsa_key_256, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_autopubkey_ecdsa_key_384, + session_setup, + session_teardown), + cmocka_unit_test_setup_teardown(torture_auth_autopubkey_ecdsa_key_521, + session_setup, + session_teardown), + }; + + ssh_session session = ssh_new(); + int verbosity = SSH_LOG_FUNCTIONS; + ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); + ssh_init(); + torture_filter_tests(tests); + rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); + ssh_finalize(); + + return rc; +} diff --git a/tests/torture.h b/tests/torture.h index 771130fb..da406cce 100644 --- a/tests/torture.h +++ b/tests/torture.h @@ -81,6 +81,7 @@ struct torture_state { #ifdef WITH_PCAP ssh_pcap_file plain_pcap; #endif + void *private_data; }; #ifndef ZERO_STRUCT