blob: b8fa940f5f526bd9b16dc6b85865499952f5f5de [file] [log] [blame]
/**
* @file test_client_ssh.c
* @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
* @brief client SSH test
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _GNU_SOURCE
#include <errno.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <cmocka.h>
#include <config.h>
#include <libyang/libyang.h>
#include <log.h>
#include <session_client.h>
#include <session_client_ch.h>
#include <session_p.h>
#include "tests/config.h"
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/server.h>
static int
setup_f(void **state)
{
(void)state;
int ret;
nc_verbosity(NC_VERB_VERBOSE);
/* init client */
nc_client_init();
ret = nc_client_ssh_set_username("username");
assert_int_equal(ret, 0);
ret = nc_client_ssh_ch_set_username("ch_username");
assert_int_equal(ret, 0);
/* skip all hostkey and known_hosts checks */
nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
return 0;
}
static int
teardown_f(void **state)
{
(void)state;
/* destroy client */
nc_client_destroy();
return 0;
}
MOCK int
__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
(void)sockfd;
(void)addr;
(void)addrlen;
return (int)mock();
}
MOCK int
__wrap_ssh_connect(ssh_session session)
{
(void)session;
/* set support of all authentication methods by fake server */
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
return (int)mock();
}
MOCK int
__wrap_ssh_userauth_none(ssh_session session, const char *username)
{
(void)session;
(void)username;
return (int)mock();
}
MOCK int
__wrap_ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods)
{
(void)session;
(void)user;
(void)submethods;
return (int)mock();
}
MOCK int
__wrap_ssh_is_connected(ssh_session session)
{
(void)session;
return (int)mock();
}
MOCK int
__wrap_ssh_channel_open_session(ssh_channel channel)
{
(void)channel;
return (int)mock();
}
MOCK int
__wrap_ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem)
{
(void)channel;
(void)subsystem;
return (int)mock();
}
MOCK int
__wrap_ssh_channel_is_closed(ssh_channel channel)
{
(void)channel;
return 0;
}
MOCK int
__wrap_ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
{
(void)channel;
(void)data;
return len;
}
MOCK int
__wrap_ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
{
(void)channel;
(void)timeout;
(void)is_stderr;
return (int)mock();
}
MOCK int
__wrap_ssh_userauth_password(ssh_session session, const char *username, const char *password)
{
(void)session;
check_expected(password);
check_expected(username);
return (int)mock();
}
MOCK int
__wrap_nc_handshake_io(struct nc_session *session)
{
(void)session;
return (int)mock();
}
MOCK int
__wrap_nc_ctx_check_and_fill(struct nc_session *session)
{
(void)session;
return (int)mock();
}
MOCK int
__wrap_ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey)
{
(void)session;
(void)username;
(void)pubkey;
return (int)mock();
}
MOCK int
__wrap_ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey)
{
(void)session;
(void)username;
(void)privkey;
return (int)mock();
}
MOCK int
__wrap_nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
{
(void)address;
(void)port;
(void)ka;
return (int)mock();
}
MOCK int
__wrap_nc_sock_accept_binds(struct nc_bind *binds, uint16_t bind_count, pthread_mutex_t *bind_lock, int timeout, char **host, uint16_t *port, uint16_t *idx)
{
(void)binds;
(void)bind_count;
(void)bind_lock;
(void)timeout;
(void)host;
(void)port;
*idx = 0;
return (int)mock();
}
MOCK struct nc_session *
__wrap_nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout)
{
(void)sock;
(void)host;
(void)port;
(void)ctx;
(void)timeout;
return mock_ptr_type(struct nc_session *);
}
char *
test_pwd_clb1(const char *username, const char *hostname, void *priv)
{
char *pass, *pass_to_return;
check_expected(username);
check_expected(hostname);
check_expected(priv);
pass = (char *)mock();
pass_to_return = malloc(sizeof *pass * (strlen(pass) + 1));
strcpy(pass_to_return, pass);
return pass_to_return;
}
char *
test_pwd_clb2(const char *username, const char *hostname, void *priv)
{
(void)username;
(void)hostname;
(void)priv;
return 0;
}
static void
test_nc_client_ssh_setting_auth_password_clb(void **state)
{
(void)state;
char *(*ret_f)(const char *username, const char *hostname, void *priv);
char *priv_data_ret;
/* set callback */
nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "DATA");
nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(test_pwd_clb1, ret_f);
assert_string_equal("DATA", priv_data_ret);
/* set different callback */
nc_client_ssh_set_auth_password_clb(test_pwd_clb2, "NEW DATA");
nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(test_pwd_clb2, ret_f);
assert_string_equal("NEW DATA", priv_data_ret);
}
char *
test_inter_clb1(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
{
(void)auth_name;
(void)instruction;
(void)prompt;
(void)echo;
(void)priv;
return 0;
}
char *
test_inter_clb2(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
{
(void)auth_name;
(void)instruction;
(void)prompt;
(void)echo;
(void)priv;
return 0;
}
static void
test_nc_client_ssh_setting_auth_interactive_clb(void **state)
{
(void)state;
char *(*ret_f)(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv);
char *priv_data_ret;
/* set callback */
nc_client_ssh_set_auth_interactive_clb(test_inter_clb1, "DATA");
nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(test_inter_clb1, ret_f);
assert_string_equal("DATA", priv_data_ret);
/* set diferent callback */
nc_client_ssh_set_auth_interactive_clb(test_inter_clb2, "NEW DATA");
nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(test_inter_clb2, ret_f);
assert_string_equal("NEW DATA", priv_data_ret);
}
char *
test_passphrase_clb1(const char *privkey_path, void *priv)
{
(void)privkey_path;
(void)priv;
return 0;
}
char *
test_passphrase_clb2(const char *privkey_path, void *priv)
{
(void)privkey_path;
(void)priv;
return 0;
}
static void
test_nc_client_ssh_setting_auth_privkey_passphrase_clb(void **state)
{
(void)state;
char *(*ret_f)(const char *privkey_path, void *priv);
char *priv_data_ret;
/* set first callback */
nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb1, "DATA");
nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(ret_f, test_passphrase_clb1);
assert_string_equal("DATA", priv_data_ret);
/* set different callback */
nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb2, "NEW DATA");
nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
assert_ptr_equal(ret_f, test_passphrase_clb2);
assert_string_equal("NEW DATA", priv_data_ret);
}
static void
test_nc_client_ssh_adding_keypair(void **state)
{
(void)state;
int ret;
const char *pubkey1, *pubkey2;
/* at the beginning keypair count should be 0 */
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 0);
/* add first key pair */
ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_ecdsa.pub", TESTS_DIR "/data/key_ecdsa");
assert_int_equal(ret, 0);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 1);
/* add second keypair */
ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
assert_int_equal(ret, 0);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 2);
ret = nc_client_ssh_get_keypair(1, &pubkey1, &pubkey2);
assert_int_equal(ret, 0);
assert_string_equal(pubkey1, "key_pub");
assert_string_equal(pubkey2, "key_priv");
/* delete first keypair */
ret = nc_client_ssh_del_keypair(0);
assert_int_equal(ret, 0);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 1);
/* try to get deleted keypair */
ret = nc_client_ssh_get_keypair(5, &pubkey1, &pubkey2);
assert_int_equal(ret, -1);
/* try to add keypair that is already set */
ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
assert_int_equal(ret, -1);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 1);
/* try to delete keypair with id that is not used */
ret = nc_client_ssh_del_keypair(42);
assert_int_equal(ret, -1);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 1);
/* remove remaining keypairs */
ret = nc_client_ssh_del_keypair(0);
assert_int_equal(ret, 0);
ret = nc_client_ssh_get_keypair_count();
assert_int_equal(ret, 0);
}
static void
test_nc_client_ssh_setting_auth_pref(void **state)
{
(void)state;
int ret;
/* check default prefference settings according to documentation */
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
assert_int_equal(ret, 1);
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
assert_int_equal(ret, 2);
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
assert_int_equal(ret, 3);
/* try to set prefetence of non existing method */
nc_client_ssh_set_auth_pref(42, 22);
/* try to get preference of non existing method */
ret = nc_client_ssh_get_auth_pref(42);
assert_int_equal(ret, 0);
/* change values of all methods and check if they actually changed */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 9);
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
assert_int_equal(ret, 9);
/* negative value should be set as -1 */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -5);
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
assert_int_equal(ret, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 11);
ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
assert_int_equal(ret, 11);
}
static void
test_nc_client_ssh_setting_username(void **state)
{
(void)state;
int ret;
const char *username_ret;
username_ret = nc_client_ssh_get_username();
/* username is set to "username" in setup_f */
assert_string_equal(username_ret, "username");
/* set new username and check if it changes */
ret = nc_client_ssh_set_username("new_username");
assert_int_equal(ret, 0);
username_ret = nc_client_ssh_get_username();
assert_string_equal(username_ret, "new_username");
}
static void
test_nc_connect_ssh_interactive_succesfull(void **state)
{
(void)state;
struct nc_session *session;
/* set authentication method to use interactive authentication */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 20);
/* prepare return values for functions used by nc_connect_ssh */
will_return(__wrap_connect, 0);
will_return(__wrap_ssh_connect, 0);
will_return(__wrap_ssh_userauth_none, 1);
will_return(__wrap_ssh_userauth_kbdint, 0);
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_ssh_channel_open_session, 0);
will_return(__wrap_ssh_channel_request_subsystem, 0);
will_return(__wrap_nc_handshake_io, 3);
will_return(__wrap_nc_ctx_check_and_fill, 0);
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
assert_non_null(session);
will_return(__wrap_ssh_channel_poll_timeout, 0);
nc_session_free(session, NULL);
}
static void
test_nc_connect_ssh_password_succesfull(void **state)
{
(void)state;
struct nc_session *session;
/* set authentication method to use password authentication */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
/* set authentication callback */
nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "private_data");
will_return(test_pwd_clb1, "secret password");
/* set values that are expected as parameters for authentication callback */
expect_string(test_pwd_clb1, username, "username");
expect_string(test_pwd_clb1, hostname, "127.0.0.1");
expect_string(test_pwd_clb1, priv, "private_data");
/* fake succesfull connection */
will_return(__wrap_connect, 0);
will_return(__wrap_ssh_connect, 0);
/* do not authenticate using no authentication method */
will_return(__wrap_ssh_userauth_none, 1);
/* succesfully authenticate via password authentication */
expect_string(__wrap_ssh_userauth_password, password, "secret password");
expect_string(__wrap_ssh_userauth_password, username, "username");
will_return(__wrap_ssh_userauth_password, 0);
/* fake ssh functions that are used to open netconf channel */
will_return(__wrap_ssh_channel_open_session, 0);
will_return(__wrap_ssh_channel_request_subsystem, 0);
/* fake that connection is still alive*/
will_return(__wrap_ssh_is_connected, 1);
/* fake ssh function for recieving hello message */
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_nc_handshake_io, 3);
will_return(__wrap_nc_ctx_check_and_fill, 0);
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
assert_non_null(session);
/* disconnect */
will_return(__wrap_ssh_channel_poll_timeout, 0);
nc_session_free(session, NULL);
}
static void
test_nc_connect_ssh_pubkey_succesfull(void **state)
{
(void)state;
struct nc_session *session;
int ret = 0;
/* set authentication method to use password authentication */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
/* add keypair for authentication */
ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_ecdsa.pub", TESTS_DIR "/data/key_ecdsa");
assert_int_equal(ret, 0);
/* fake succesfull connection */
will_return(__wrap_connect, 0);
will_return(__wrap_ssh_connect, 0);
/* do not authenticate using no authentication method */
will_return(__wrap_ssh_userauth_none, 1);
will_return(__wrap_ssh_userauth_try_publickey, 0);
will_return(__wrap_ssh_userauth_publickey, 0);
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_ssh_channel_open_session, 0);
will_return(__wrap_ssh_channel_request_subsystem, 0);
/* fake ssh function for recieving hello message */
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_nc_handshake_io, 3);
will_return(__wrap_nc_ctx_check_and_fill, 0);
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
assert_non_null(session);
/* disconnect */
will_return(__wrap_ssh_channel_poll_timeout, 0);
nc_session_free(session, NULL);
}
static void
test_nc_connect_connection_failed(void **state)
{
(void)state;
struct nc_session *session;
errno = ECONNREFUSED;
will_return(__wrap_connect, -1);
will_return(__wrap_ssh_is_connected, 0);
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
assert_null(session);
}
static void
test_nc_connect_ssh_bad_hello(void **state)
{
(void)state;
struct nc_session *session;
/* set authentication method to use interactive authentication */
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
nc_client_ssh_set_auth_password_clb(test_pwd_clb2, NULL);
will_return(__wrap_connect, 0);
will_return(__wrap_ssh_connect, 0);
will_return(__wrap_ssh_userauth_none, 1);
will_return(__wrap_ssh_userauth_kbdint, 0);
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_ssh_is_connected, 1);
will_return(__wrap_ssh_channel_open_session, 0);
will_return(__wrap_ssh_channel_request_subsystem, 0);
will_return(__wrap_nc_handshake_io, 4);
session = nc_connect_ssh("127.0.0.1", 8080, NULL);
assert_null(session);
}
static void
test_nc_client_ssh_ch_setting_username(void **state)
{
(void)state;
const char *username_ret;
int ret;
/* username is set to "ch_username" in setup_f */
username_ret = nc_client_ssh_ch_get_username();
assert_string_equal(username_ret, "ch_username");
/* set new username and check if it changes */
ret = nc_client_ssh_ch_set_username("new_ch_username");
assert_int_equal(ret, 0);
username_ret = nc_client_ssh_ch_get_username();
assert_string_equal(username_ret, "new_ch_username");
}
static void
test_nc_client_ssh_ch_add_bind_listen(void **state)
{
(void)state;
int ret;
/* invalid parameters, address NULL or port 0 */
ret = nc_client_ssh_ch_add_bind_listen(NULL, 4334);
assert_int_equal(ret, -1);
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 0);
assert_int_equal(ret, -1);
/* failed to create an ssh listening socket */
will_return(__wrap_nc_sock_listen_inet, -1);
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
assert_int_equal(ret, -1);
/* fake a successful CH ssh listening socket */
will_return(__wrap_nc_sock_listen_inet, 5);
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
assert_int_equal(ret, 0);
/* remove ssh listening client binds */
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
assert_int_equal(ret, 0);
}
static void
test_nc_accept_callhome(void **state)
{
(void)state;
struct nc_session *session = NULL;
int timeout = 10;
int ret;
/* invalid parameter session */
ret = nc_accept_callhome(timeout, NULL, NULL);
assert_int_equal(ret, -1);
/* no client bind */
ret = nc_accept_callhome(timeout, NULL, &session);
assert_int_equal(ret, -1);
/* successfully add a client Call Home bind */
will_return(__wrap_nc_sock_listen_inet, 1);
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
assert_int_equal(ret, 0);
/* failed to accept a client bind */
will_return(__wrap_nc_sock_accept_binds, -1);
ret = nc_accept_callhome(timeout, NULL, &session);
assert_int_equal(ret, -1);
/* failed to accept a server Call Home connection */
will_return(__wrap_nc_accept_callhome_ssh_sock, NULL);
will_return(__wrap_nc_sock_accept_binds, 2);
ret = nc_accept_callhome(timeout, NULL, &session);
assert_int_equal(ret, -1);
/* create session structure to fake a successful server call home connection */
session = nc_new_session(NC_CLIENT, 0);
assert_non_null(session);
will_return(__wrap_nc_sock_accept_binds, 2);
will_return(__wrap_nc_accept_callhome_ssh_sock, session);
ret = nc_accept_callhome(timeout, NULL, &session);
assert_int_equal(ret, 1);
/* remove ssh listening client binds */
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
assert_int_equal(ret, 0);
/* free session */
nc_session_free(session, NULL);
}
static void
test_nc_client_ssh_callhome_successful(void **state)
{
(void)state;
struct nc_session *session = NULL;
int timeout = 10;
int ret;
/* create session structure */
session = nc_new_session(NC_CLIENT, 0);
assert_non_null(session);
/* prepare to fake return values for functions used by nc_accept_callhome */
will_return(__wrap_nc_sock_listen_inet, 1);
will_return(__wrap_nc_sock_accept_binds, 2);
will_return(__wrap_nc_accept_callhome_ssh_sock, session);
ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
assert_int_equal(ret, 0);
ret = nc_accept_callhome(timeout, NULL, &session);
assert_int_equal(ret, 1);
/* remove ssh listening client binds */
ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
assert_int_equal(ret, 0);
/* free session */
nc_session_free(session, NULL);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_pref, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_password_clb, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_interactive_clb, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_privkey_passphrase_clb, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_adding_keypair, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_username, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_interactive_succesfull, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_password_succesfull, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_succesfull, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_connect_connection_failed, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_connect_ssh_bad_hello, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_setting_username, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_add_bind_listen, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_accept_callhome, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_nc_client_ssh_callhome_successful, setup_f, teardown_f),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}