blob: 7099d77ea96fe8ea59a589473a679d39c3da4584 [file] [log] [blame]
roman0bbc19c2023-05-26 09:59:09 +02001/**
2 * @file test_endpt_share_clients.c
3 * @author Roman Janota <xjanot04@fit.vutbr.cz>
4 * @brief libnetconf2 Sharing clients between endpoints test
5 *
6 * @copyright
7 * Copyright (c) 2023 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
16#define _GNU_SOURCE
17
18#include <errno.h>
19#include <pthread.h>
20#include <setjmp.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <cmocka.h>
27
28#include "tests/config.h"
29
30#define NC_ACCEPT_TIMEOUT 2000
31#define NC_PS_POLL_TIMEOUT 2000
32
33struct ly_ctx *ctx;
34
35struct test_state {
36 pthread_barrier_t barrier;
37};
38
roman0bbc19c2023-05-26 09:59:09 +020039static void *
40server_thread(void *arg)
41{
42 int ret;
43 NC_MSG_TYPE msgtype;
44 struct nc_session *session;
45 struct nc_pollsession *ps;
46 struct test_state *state = arg;
47
48 ps = nc_ps_new();
49 assert_non_null(ps);
50
51 /* accept a session and add it to the poll session structure */
52 pthread_barrier_wait(&state->barrier);
53 msgtype = nc_accept(NC_ACCEPT_TIMEOUT, ctx, &session);
54 assert_int_equal(msgtype, NC_MSG_HELLO);
55
56 ret = nc_ps_add_session(ps, session);
57 assert_int_equal(ret, 0);
58
59 do {
60 ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
61 assert_int_equal(ret & NC_PSPOLL_RPC, NC_PSPOLL_RPC);
62 } while (!(ret & NC_PSPOLL_SESSION_TERM));
63
64 nc_ps_clear(ps, 1, NULL);
65 nc_ps_free(ps);
roman0bbc19c2023-05-26 09:59:09 +020066 return NULL;
67}
68
69static void *
roman2e797ef2023-06-19 10:47:49 +020070client_thread_ssh(void *arg)
roman0bbc19c2023-05-26 09:59:09 +020071{
72 int ret;
73 struct nc_session *session = NULL;
74 struct test_state *state = arg;
75
76 /* skip all hostkey and known_hosts checks */
77 nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
78
79 /* set directory where to search for modules */
80 ret = nc_client_set_schema_searchpath(MODULES_DIR);
81 assert_int_equal(ret, 0);
82
83 /* set ssh username */
84 ret = nc_client_ssh_set_username("client");
85 assert_int_equal(ret, 0);
86
87 /* add client's key pair */
88 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_rsa.pub", TESTS_DIR "/data/key_rsa");
89 assert_int_equal(ret, 0);
90
91 /* wait for the server to reach polling */
92 pthread_barrier_wait(&state->barrier);
93
94 /* connect */
95 session = nc_connect_ssh("127.0.0.1", 10005, NULL);
96 assert_non_null(session);
97
98 nc_session_free(session, NULL);
roman0bbc19c2023-05-26 09:59:09 +020099 return NULL;
100}
101
102static void
roman2e797ef2023-06-19 10:47:49 +0200103nc_test_endpt_share_clients_ssh(void **state)
roman0bbc19c2023-05-26 09:59:09 +0200104{
105 int ret, i;
106 pthread_t tids[2];
107
108 assert_non_null(state);
109
roman2e797ef2023-06-19 10:47:49 +0200110 ret = pthread_create(&tids[0], NULL, client_thread_ssh, *state);
111 assert_int_equal(ret, 0);
112 ret = pthread_create(&tids[1], NULL, server_thread, *state);
113 assert_int_equal(ret, 0);
114
115 for (i = 0; i < 2; i++) {
116 pthread_join(tids[i], NULL);
117 }
118}
119
120static void *
121client_thread_tls(void *arg)
122{
123 int ret;
124 struct nc_session *session = NULL;
125 struct test_state *state = arg;
126
127 /* set directory where to search for modules */
128 ret = nc_client_set_schema_searchpath(MODULES_DIR);
129 assert_int_equal(ret, 0);
130
131 /* set client cert */
132 ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
133 assert_int_equal(ret, 0);
134
135 /* set client ca */
136 ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
137 assert_int_equal(ret, 0);
138
139 pthread_barrier_wait(&state->barrier);
140 session = nc_connect_tls("127.0.0.1", 10008, NULL);
141 assert_non_null(session);
142
143 nc_session_free(session, NULL);
144 return NULL;
145}
146
147static void
148nc_test_endpt_share_clients_tls(void **state)
149{
150 int ret, i;
151 pthread_t tids[2];
152
153 assert_non_null(state);
154
155 ret = pthread_create(&tids[0], NULL, client_thread_tls, *state);
roman0bbc19c2023-05-26 09:59:09 +0200156 assert_int_equal(ret, 0);
157 ret = pthread_create(&tids[1], NULL, server_thread, *state);
158 assert_int_equal(ret, 0);
159
160 for (i = 0; i < 2; i++) {
161 pthread_join(tids[i], NULL);
162 }
163}
164
165static int
roman2e797ef2023-06-19 10:47:49 +0200166setup_ssh(void **state)
roman0bbc19c2023-05-26 09:59:09 +0200167{
168 int ret;
169 struct lyd_node *tree = NULL;
170 struct test_state *test_state;
171
172 nc_verbosity(NC_VERB_VERBOSE);
173
174 /* init barrier */
175 test_state = malloc(sizeof *test_state);
176 assert_non_null(test_state);
177
178 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
179 assert_int_equal(ret, 0);
180
181 *state = test_state;
182
183 /* create new context */
184 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
185 assert_int_equal(ret, 0);
186
187 /* load default modules into context */
188 ret = nc_server_init_ctx(&ctx);
189 assert_int_equal(ret, 0);
190
191 /* load ietf-netconf-server module and it's imports into context */
192 ret = nc_server_config_load_modules(&ctx);
193 assert_int_equal(ret, 0);
194
roman2e797ef2023-06-19 10:47:49 +0200195 /* create the first SSH endpoint with a client reference to the second endpoint */
Roytakb2794852023-10-18 14:30:22 +0200196 ret = nc_server_config_add_ssh_hostkey(ctx, "SSH_endpt_1", "hostkey", TESTS_DIR "/data/key_rsa", NULL, &tree);
roman2e797ef2023-06-19 10:47:49 +0200197 assert_int_equal(ret, 0);
198
Roytakb2794852023-10-18 14:30:22 +0200199 ret = nc_server_config_add_address_port(ctx, "SSH_endpt_1", NC_TI_LIBSSH, "127.0.0.1", 10005, &tree);
roman2e797ef2023-06-19 10:47:49 +0200200 assert_int_equal(ret, 0);
201
Roytakb2794852023-10-18 14:30:22 +0200202 ret = nc_server_config_add_ssh_endpoint_client_ref(ctx, "SSH_endpt_1", "SSH_endpt_2", &tree);
roman2e797ef2023-06-19 10:47:49 +0200203 assert_int_equal(ret, 0);
204
205 /* create the second SSH endpoint with a single client */
Roytakb2794852023-10-18 14:30:22 +0200206 ret = nc_server_config_add_ssh_hostkey(ctx, "SSH_endpt_2", "hostkey", TESTS_DIR "/data/key_rsa", NULL, &tree);
roman2e797ef2023-06-19 10:47:49 +0200207 assert_int_equal(ret, 0);
208
Roytakb2794852023-10-18 14:30:22 +0200209 ret = nc_server_config_add_address_port(ctx, "SSH_endpt_2", NC_TI_LIBSSH, "127.0.0.1", 10006, &tree);
roman2e797ef2023-06-19 10:47:49 +0200210 assert_int_equal(ret, 0);
211
Roytakb2794852023-10-18 14:30:22 +0200212 ret = nc_server_config_add_ssh_user_pubkey(ctx, "SSH_endpt_2", "client", "pubkey", TESTS_DIR "/data/key_rsa.pub", &tree);
roman0bbc19c2023-05-26 09:59:09 +0200213 assert_int_equal(ret, 0);
214
215 /* configure the server based on the yang data */
roman142718b2023-06-29 09:15:29 +0200216 ret = nc_server_config_setup_data(tree);
roman2e797ef2023-06-19 10:47:49 +0200217 assert_int_equal(ret, 0);
218
219 /* initialize the server */
220 ret = nc_server_init();
221 assert_int_equal(ret, 0);
222
romaneadc4782023-09-14 10:10:08 +0200223 /* initialize client */
224 ret = nc_client_init();
225 assert_int_equal(ret, 0);
226
roman2e797ef2023-06-19 10:47:49 +0200227 lyd_free_all(tree);
228
229 return 0;
230}
231
232static int
233setup_tls(void **state)
234{
235 int ret;
236 struct lyd_node *tree = NULL;
237 struct test_state *test_state;
238
239 nc_verbosity(NC_VERB_VERBOSE);
240
241 /* init barrier */
242 test_state = malloc(sizeof *test_state);
243 assert_non_null(test_state);
244
245 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
246 assert_int_equal(ret, 0);
247
248 *state = test_state;
249
250 /* create new context */
251 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
252 assert_int_equal(ret, 0);
253
254 /* load default modules into context */
255 ret = nc_server_init_ctx(&ctx);
256 assert_int_equal(ret, 0);
257
258 /* load ietf-netconf-server module and it's imports into context */
259 ret = nc_server_config_load_modules(&ctx);
260 assert_int_equal(ret, 0);
261
262 /* create the first TLS endpoint with a single end entity client cert and a CTN entry */
romane6ec60e2023-10-19 15:21:52 +0200263 ret = nc_server_config_add_tls_server_cert(ctx, "TLS_endpt_1", TESTS_DIR "/data/server.key", NULL, TESTS_DIR "/data/server.crt", &tree);
roman2e797ef2023-06-19 10:47:49 +0200264 assert_int_equal(ret, 0);
265
Roytakb2794852023-10-18 14:30:22 +0200266 ret = nc_server_config_add_address_port(ctx, "TLS_endpt_1", NC_TI_OPENSSL, "127.0.0.1", 10007, &tree);
roman2e797ef2023-06-19 10:47:49 +0200267 assert_int_equal(ret, 0);
268
romane6ec60e2023-10-19 15:21:52 +0200269 ret = nc_server_config_add_tls_client_cert(ctx, "TLS_endpt_1", "cert_client", TESTS_DIR "/data/client.crt", &tree);
roman2e797ef2023-06-19 10:47:49 +0200270 assert_int_equal(ret, 0);
271
romane6ec60e2023-10-19 15:21:52 +0200272 ret = nc_server_config_add_tls_ca_cert(ctx, "TLS_endpt_1", "cert_ca", TESTS_DIR "/data/serverca.pem", &tree);
roman2e797ef2023-06-19 10:47:49 +0200273 assert_int_equal(ret, 0);
274
Roytakb2794852023-10-18 14:30:22 +0200275 ret = nc_server_config_add_tls_ctn(ctx, "TLS_endpt_1", 1,
roman2e797ef2023-06-19 10:47:49 +0200276 "04:85:6B:75:D1:1A:86:E0:D8:FE:5B:BD:72:F5:73:1D:07:EA:32:BF:09:11:21:6A:6E:23:78:8E:B6:D5:73:C3:2D",
277 NC_TLS_CTN_SPECIFIED, "client", &tree);
278 assert_int_equal(ret, 0);
279
280 /* create the second TLS endpoint with a reference to the first endpoint */
romane6ec60e2023-10-19 15:21:52 +0200281 ret = nc_server_config_add_tls_server_cert(ctx, "TLS_endpt_2",
roman6c4efcd2023-08-08 10:18:44 +0200282 TESTS_DIR "/data/server.key", NULL, TESTS_DIR "/data/server.crt", &tree);
roman2e797ef2023-06-19 10:47:49 +0200283 assert_int_equal(ret, 0);
284
Roytakb2794852023-10-18 14:30:22 +0200285 ret = nc_server_config_add_address_port(ctx, "TLS_endpt_2", NC_TI_OPENSSL, "127.0.0.1", 10008, &tree);
roman2e797ef2023-06-19 10:47:49 +0200286 assert_int_equal(ret, 0);
287
Roytakb2794852023-10-18 14:30:22 +0200288 ret = nc_server_config_add_tls_endpoint_client_ref(ctx, "TLS_endpt_2", "TLS_endpt_1", &tree);
roman2e797ef2023-06-19 10:47:49 +0200289 assert_int_equal(ret, 0);
290
291 /* configure the server based on the yang data */
roman142718b2023-06-29 09:15:29 +0200292 ret = nc_server_config_setup_data(tree);
roman0bbc19c2023-05-26 09:59:09 +0200293 assert_int_equal(ret, 0);
294
roman0bbc19c2023-05-26 09:59:09 +0200295 /* initialize the server */
296 ret = nc_server_init();
297 assert_int_equal(ret, 0);
298
romaneadc4782023-09-14 10:10:08 +0200299 /* initialize client */
300 ret = nc_client_init();
301 assert_int_equal(ret, 0);
302
roman0bbc19c2023-05-26 09:59:09 +0200303 lyd_free_all(tree);
304
305 return 0;
306}
307
308static int
309teardown_f(void **state)
310{
311 int ret = 0;
312 struct test_state *test_state;
313
314 assert_non_null(state);
315 test_state = *state;
316
317 ret = pthread_barrier_destroy(&test_state->barrier);
318 assert_int_equal(ret, 0);
319
320 free(*state);
321 nc_client_destroy();
322 nc_server_destroy();
323 ly_ctx_destroy(ctx);
324
325 return 0;
326}
327
328int
329main(void)
330{
331 const struct CMUnitTest tests[] = {
roman2e797ef2023-06-19 10:47:49 +0200332 cmocka_unit_test_setup_teardown(nc_test_endpt_share_clients_ssh, setup_ssh, teardown_f),
333 cmocka_unit_test_setup_teardown(nc_test_endpt_share_clients_tls, setup_tls, teardown_f),
roman0bbc19c2023-05-26 09:59:09 +0200334 };
335
336 setenv("CMOCKA_TEST_ABORT", "1", 1);
337 return cmocka_run_group_tests(tests, NULL, NULL);
338}