blob: cb4948b5ed596441810c3689ec00bde22b804797 [file] [log] [blame]
roman27215242023-03-10 14:55:00 +01001/**
2 * @file test_keystore.c
3 * @author Roman Janota <xjanot04@fit.vutbr.cz>
4 * @brief libnetconf2 Linux PAM keyboard-interactive authentication test
5 *
6 * @copyright
7 * Copyright (c) 2022 CESNET, z.s.p.o.
8 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
15
roman9b1379c2023-03-31 10:11:10 +020016#define _GNU_SOURCE
17
roman27215242023-03-10 14:55:00 +010018#include <pthread.h>
19#include <setjmp.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <cmocka.h>
25
roman27215242023-03-10 14:55:00 +010026#include "tests/config.h"
27
28#define NC_ACCEPT_TIMEOUT 2000
29#define NC_PS_POLL_TIMEOUT 2000
30
31struct ly_ctx *ctx;
32
33struct test_state {
34 pthread_barrier_t barrier;
35};
36
37static void *
38server_thread(void *arg)
39{
40 int ret;
41 NC_MSG_TYPE msgtype;
42 struct nc_session *session;
43 struct nc_pollsession *ps;
44 struct test_state *state = arg;
45
46 ps = nc_ps_new();
47 assert_non_null(ps);
48
49 /* accept a session and add it to the poll session structure */
50 pthread_barrier_wait(&state->barrier);
51 msgtype = nc_accept(NC_ACCEPT_TIMEOUT, ctx, &session);
52 assert_int_equal(msgtype, NC_MSG_HELLO);
53
54 ret = nc_ps_add_session(ps, session);
55 assert_int_equal(ret, 0);
56
57 do {
58 ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
59 assert_int_equal(ret & NC_PSPOLL_RPC, NC_PSPOLL_RPC);
60 } while (!(ret & NC_PSPOLL_SESSION_TERM));
61
62 nc_ps_clear(ps, 1, NULL);
63 nc_ps_free(ps);
64 nc_thread_destroy();
65 return NULL;
66}
67
roman9b1379c2023-03-31 10:11:10 +020068static char *
69auth_password(const char *username, const char *hostname, void *priv)
70{
71 (void) username;
72 (void) hostname;
73 (void) priv;
74
75 /* set the reply to password authentication */
76 return strdup("testpassword123");
77}
78
roman27215242023-03-10 14:55:00 +010079static void *
roman9b1379c2023-03-31 10:11:10 +020080client_thread(void *arg)
roman27215242023-03-10 14:55:00 +010081{
82 int ret;
83 struct nc_session *session = NULL;
84 struct test_state *state = arg;
85
roman472420c2023-04-24 16:28:09 +020086 /* skip all hostkey and known_hosts checks */
87 nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
88
roman27215242023-03-10 14:55:00 +010089 ret = nc_client_set_schema_searchpath(MODULES_DIR);
90 assert_int_equal(ret, 0);
91
roman9b1379c2023-03-31 10:11:10 +020092 ret = nc_client_ssh_set_username("client");
roman27215242023-03-10 14:55:00 +010093 assert_int_equal(ret, 0);
94
roman9b1379c2023-03-31 10:11:10 +020095 nc_client_ssh_set_auth_password_clb(auth_password, NULL);
roman27215242023-03-10 14:55:00 +010096
97 pthread_barrier_wait(&state->barrier);
98 session = nc_connect_ssh("127.0.0.1", 10005, NULL);
99 assert_non_null(session);
100
101 nc_session_free(session, NULL);
102 nc_thread_destroy();
103 return NULL;
104}
105
106static void
roman9b1379c2023-03-31 10:11:10 +0200107test_nc_config_new(void **state)
roman27215242023-03-10 14:55:00 +0100108{
109 int ret, i;
110 pthread_t tids[2];
111
112 assert_non_null(state);
113
roman9b1379c2023-03-31 10:11:10 +0200114 ret = pthread_create(&tids[0], NULL, client_thread, *state);
roman27215242023-03-10 14:55:00 +0100115 assert_int_equal(ret, 0);
116 ret = pthread_create(&tids[1], NULL, server_thread, *state);
117 assert_int_equal(ret, 0);
118
119 for (i = 0; i < 2; i++) {
120 pthread_join(tids[i], NULL);
121 }
122}
123
124static int
125setup_f(void **state)
126{
127 int ret;
128 struct lyd_node *tree = NULL;
129 struct test_state *test_state;
130
131 nc_verbosity(NC_VERB_VERBOSE);
132
133 /* init barrier */
134 test_state = malloc(sizeof *test_state);
135 assert_non_null(test_state);
136
137 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
138 assert_int_equal(ret, 0);
139
140 *state = test_state;
141
roman9b1379c2023-03-31 10:11:10 +0200142 /* new context */
roman27215242023-03-10 14:55:00 +0100143 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
144 assert_int_equal(ret, 0);
145
roman9b1379c2023-03-31 10:11:10 +0200146 /* initialize the context by loading default modules */
roman27215242023-03-10 14:55:00 +0100147 ret = nc_server_init_ctx(&ctx);
148 assert_int_equal(ret, 0);
149
roman9b1379c2023-03-31 10:11:10 +0200150 /* load ietf-netconf-server module and it's imports */
roman27215242023-03-10 14:55:00 +0100151 ret = nc_server_config_load_modules(&ctx);
152 assert_int_equal(ret, 0);
153
roman9b1379c2023-03-31 10:11:10 +0200154 /* create new hostkey data */
roman27215242023-03-10 14:55:00 +0100155 ret = nc_server_config_ssh_new_hostkey(TESTS_DIR "/data/server.key", NULL, ctx, "endpt", "hostkey", &tree);
156 assert_int_equal(ret, 0);
157
roman9b1379c2023-03-31 10:11:10 +0200158 /* create new address and port data */
roman27215242023-03-10 14:55:00 +0100159 ret = nc_server_config_ssh_new_address_port("127.0.0.1", "10005", ctx, "endpt", &tree);
160 assert_int_equal(ret, 0);
161
roman9b1379c2023-03-31 10:11:10 +0200162 /* create the host-key algorithms data */
roman27215242023-03-10 14:55:00 +0100163 ret = nc_server_config_ssh_new_host_key_algs(ctx, "endpt", &tree, 1, "rsa-sha2-512");
164 assert_int_equal(ret, 0);
165
roman9b1379c2023-03-31 10:11:10 +0200166 /* create the client authentication data, password only */
167 ret = nc_server_config_ssh_new_client_auth_password("testpassword123", ctx, "endpt", "client", &tree);
roman4f9bb442023-03-24 09:05:37 +0100168 assert_int_equal(ret, 0);
169
roman27215242023-03-10 14:55:00 +0100170 /* configure the server based on the data */
171 ret = nc_server_config_setup(tree);
172 assert_int_equal(ret, 0);
173
174 /* initialize client */
175 nc_client_init();
176
177 ret = nc_server_init();
178 assert_int_equal(ret, 0);
179
roman27215242023-03-10 14:55:00 +0100180 lyd_free_all(tree);
181
182 return 0;
183}
184
185static int
186teardown_f(void **state)
187{
188 int ret = 0;
189 struct test_state *test_state;
190
191 assert_non_null(state);
192 test_state = *state;
193
194 ret = pthread_barrier_destroy(&test_state->barrier);
195 assert_int_equal(ret, 0);
196
197 free(*state);
198 nc_client_destroy();
199 nc_server_destroy();
200 ly_ctx_destroy(ctx);
201
202 return 0;
203}
204
205int
206main(void)
207{
208 const struct CMUnitTest tests[] = {
roman9b1379c2023-03-31 10:11:10 +0200209 cmocka_unit_test_setup_teardown(test_nc_config_new, setup_f, teardown_f),
roman27215242023-03-10 14:55:00 +0100210 };
211
212 setenv("CMOCKA_TEST_ABORT", "1", 1);
213 return cmocka_run_group_tests(tests, NULL, NULL);
214}