blob: 2d125fad41b0d2d15bbd453a6dcf955bf1404ed4 [file] [log] [blame]
roman45cec4e2023-02-17 10:21:39 +01001/**
roman142718b2023-06-29 09:15:29 +02002 * @file test_ks_ts.c
roman45cec4e2023-02-17 10:21:39 +01003 * @author Roman Janota <xjanot04@fit.vutbr.cz>
roman142718b2023-06-29 09:15:29 +02004 * @brief libnetconf2 Keystore and trustore usage test.
roman45cec4e2023-02-17 10:21:39 +01005 *
6 * @copyright
roman142718b2023-06-29 09:15:29 +02007 * Copyright (c) 2023 CESNET, z.s.p.o.
roman45cec4e2023-02-17 10:21:39 +01008 *
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
roman45cec4e2023-02-17 10:21:39 +010018#include <errno.h>
19#include <pthread.h>
20#include <setjmp.h>
roman9b1379c2023-03-31 10:11:10 +020021#include <stdarg.h>
roman45cec4e2023-02-17 10:21:39 +010022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <cmocka.h>
27
roman45cec4e2023-02-17 10:21:39 +010028#include "tests/config.h"
29
roman83683fb2023-02-24 09:15:23 +010030#define NC_ACCEPT_TIMEOUT 2000
31#define NC_PS_POLL_TIMEOUT 2000
roman45cec4e2023-02-17 10:21:39 +010032
33struct ly_ctx *ctx;
34
35struct test_state {
roman45cec4e2023-02-17 10:21:39 +010036 pthread_barrier_t barrier;
37};
38
roman45cec4e2023-02-17 10:21:39 +010039static 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);
roman45cec4e2023-02-17 10:21:39 +010066 return NULL;
67}
68
roman45cec4e2023-02-17 10:21:39 +010069static void *
roman12c3d522023-07-26 13:39:30 +020070client_thread_ssh(void *arg)
roman45cec4e2023-02-17 10:21:39 +010071{
72 int ret;
73 struct nc_session *session = NULL;
74 struct test_state *state = arg;
75
roman472420c2023-04-24 16:28:09 +020076 /* skip all hostkey and known_hosts checks */
77 nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
78
roman45cec4e2023-02-17 10:21:39 +010079 ret = nc_client_set_schema_searchpath(MODULES_DIR);
80 assert_int_equal(ret, 0);
81
roman142718b2023-06-29 09:15:29 +020082 ret = nc_client_ssh_set_username("client");
roman45cec4e2023-02-17 10:21:39 +010083 assert_int_equal(ret, 0);
84
roman142718b2023-06-29 09:15:29 +020085 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/id_ed25519.pub", TESTS_DIR "/data/id_ed25519");
roman45cec4e2023-02-17 10:21:39 +010086 assert_int_equal(ret, 0);
87
88 pthread_barrier_wait(&state->barrier);
89 session = nc_connect_ssh("127.0.0.1", 10005, NULL);
90 assert_non_null(session);
91
92 nc_session_free(session, NULL);
roman45cec4e2023-02-17 10:21:39 +010093 return NULL;
94}
95
96static void
roman12c3d522023-07-26 13:39:30 +020097test_nc_ks_ts_ssh(void **state)
roman45cec4e2023-02-17 10:21:39 +010098{
99 int ret, i;
100 pthread_t tids[2];
101
102 assert_non_null(state);
103
roman12c3d522023-07-26 13:39:30 +0200104 ret = pthread_create(&tids[0], NULL, client_thread_ssh, *state);
roman45cec4e2023-02-17 10:21:39 +0100105 assert_int_equal(ret, 0);
106 ret = pthread_create(&tids[1], NULL, server_thread, *state);
107 assert_int_equal(ret, 0);
108
109 for (i = 0; i < 2; i++) {
110 pthread_join(tids[i], NULL);
111 }
112}
113
114static int
roman12c3d522023-07-26 13:39:30 +0200115setup_ssh(void **state)
roman45cec4e2023-02-17 10:21:39 +0100116{
117 int ret;
roman142718b2023-06-29 09:15:29 +0200118 struct lyd_node *tree = NULL;
roman45cec4e2023-02-17 10:21:39 +0100119 struct test_state *test_state;
120
121 nc_verbosity(NC_VERB_VERBOSE);
122
123 /* init barrier */
124 test_state = malloc(sizeof *test_state);
125 assert_non_null(test_state);
126
127 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
128 assert_int_equal(ret, 0);
129
130 *state = test_state;
131
132 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
133 assert_int_equal(ret, 0);
134
135 ret = nc_server_init_ctx(&ctx);
136 assert_int_equal(ret, 0);
137
138 ret = nc_server_config_load_modules(&ctx);
139 assert_int_equal(ret, 0);
140
roman142718b2023-06-29 09:15:29 +0200141 ret = nc_server_config_new_address_port(ctx, "endpt", NC_TI_LIBSSH, "127.0.0.1", 10005, &tree);
142 assert_int_equal(ret, 0);
143
144 ret = nc_server_config_new_ssh_keystore_reference(ctx, "endpt", "hostkey", "test_keystore", &tree);
145 assert_int_equal(ret, 0);
146
147 ret = nc_server_config_new_ssh_truststore_reference(ctx, "endpt", "client", "test_truststore", &tree);
148 assert_int_equal(ret, 0);
149
150 ret = nc_server_config_new_keystore_asym_key(ctx, "test_keystore", TESTS_DIR "/data/key_rsa", NULL, &tree);
151 assert_int_equal(ret, 0);
152
153 ret = nc_server_config_new_truststore_pubkey(ctx, "test_truststore", "pubkey", TESTS_DIR "/data/id_ed25519.pub", &tree);
roman45cec4e2023-02-17 10:21:39 +0100154 assert_int_equal(ret, 0);
155
156 /* configure the server based on the data */
roman142718b2023-06-29 09:15:29 +0200157 ret = nc_server_config_setup_data(tree);
roman45cec4e2023-02-17 10:21:39 +0100158 assert_int_equal(ret, 0);
159
roman45cec4e2023-02-17 10:21:39 +0100160 ret = nc_server_init();
161 assert_int_equal(ret, 0);
162
roman45cec4e2023-02-17 10:21:39 +0100163 lyd_free_all(tree);
164
165 return 0;
166}
167
roman12c3d522023-07-26 13:39:30 +0200168static void *
169client_thread_tls(void *arg)
170{
171 int ret;
172 struct nc_session *session = NULL;
173 struct test_state *state = arg;
174
175 ret = nc_client_set_schema_searchpath(MODULES_DIR);
176 assert_int_equal(ret, 0);
177
178 /* set client cert */
179 ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
180 assert_int_equal(ret, 0);
181
182 /* set client ca */
183 ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
184 assert_int_equal(ret, 0);
185
186 pthread_barrier_wait(&state->barrier);
187 session = nc_connect_tls("127.0.0.1", 10005, NULL);
188 assert_non_null(session);
189
190 nc_session_free(session, NULL);
191 return NULL;
192}
193
194static void
195test_nc_ks_ts_tls(void **state)
196{
197 int ret, i;
198 pthread_t tids[2];
199
200 assert_non_null(state);
201
202 ret = pthread_create(&tids[0], NULL, client_thread_tls, *state);
203 assert_int_equal(ret, 0);
204 ret = pthread_create(&tids[1], NULL, server_thread, *state);
205 assert_int_equal(ret, 0);
206
207 for (i = 0; i < 2; i++) {
208 pthread_join(tids[i], NULL);
209 }
210}
211
212static int
213setup_tls(void **state)
214{
215 int ret;
216 struct lyd_node *tree = NULL;
217 struct test_state *test_state;
218
219 nc_verbosity(NC_VERB_VERBOSE);
220
221 /* init barrier */
222 test_state = malloc(sizeof *test_state);
223 assert_non_null(test_state);
224
225 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
226 assert_int_equal(ret, 0);
227
228 *state = test_state;
229
230 /* new ctx */
231 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
232 assert_int_equal(ret, 0);
233
234 /* init ctx */
235 ret = nc_server_init_ctx(&ctx);
236 assert_int_equal(ret, 0);
237
238 /* load ietf netconf server module and its requisities */
239 ret = nc_server_config_load_modules(&ctx);
240 assert_int_equal(ret, 0);
241
242 /* new tls bind */
243 ret = nc_server_config_new_address_port(ctx, "endpt", NC_TI_OPENSSL, "127.0.0.1", 10005, &tree);
244 assert_int_equal(ret, 0);
245
246 /* new keystore asym key pair */
247 ret = nc_server_config_new_keystore_asym_key(ctx, "server_key", TESTS_DIR "/data/server.key", NULL, &tree);
248 assert_int_equal(ret, 0);
249
250 /* new keystore cert belonging to the key pair */
251 ret = nc_server_config_new_keystore_cert(ctx, "server_key", "server_cert", TESTS_DIR "/data/server.crt", &tree);
252 assert_int_equal(ret, 0);
253
254 /* new truststore client cert */
255 ret = nc_server_config_new_truststore_cert(ctx, "ee_cert_bag", "ee_cert", TESTS_DIR "/data/client.crt", &tree);
256 assert_int_equal(ret, 0);
257
258 /* new truststore client CA cert */
259 ret = nc_server_config_new_truststore_cert(ctx, "ca_cert_bag", "ca_cert", TESTS_DIR "/data/serverca.pem", &tree);
260 assert_int_equal(ret, 0);
261
262 /* new keystore ref for the TLS server cert */
263 ret = nc_server_config_new_tls_keystore_reference(ctx, "endpt", "server_key", "server_cert", &tree);
264 assert_int_equal(ret, 0);
265
266 /* new truststore ref for the client cert */
267 ret = nc_server_config_new_tls_client_cert_truststore_ref(ctx, "endpt", "ee_cert_bag", &tree);
268 assert_int_equal(ret, 0);
269
270 /* new truststore ref for the client CA cert */
271 ret = nc_server_config_new_tls_client_ca_truststore_ref(ctx, "endpt", "ca_cert_bag", &tree);
272 assert_int_equal(ret, 0);
273
274 /* new cert-to-name */
275 ret = nc_server_config_new_tls_ctn(ctx, "endpt", 1,
276 "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 /* configure the server based on the data */
281 ret = nc_server_config_setup_data(tree);
282 assert_int_equal(ret, 0);
283
284 ret = nc_server_init();
285 assert_int_equal(ret, 0);
286
287 lyd_free_all(tree);
288
289 return 0;
290}
291
roman45cec4e2023-02-17 10:21:39 +0100292static int
293teardown_f(void **state)
294{
295 int ret = 0;
296 struct test_state *test_state;
297
298 assert_non_null(state);
299 test_state = *state;
300
301 ret = pthread_barrier_destroy(&test_state->barrier);
302 assert_int_equal(ret, 0);
303
304 free(*state);
305 nc_client_destroy();
306 nc_server_destroy();
307 ly_ctx_destroy(ctx);
308
309 return 0;
310}
311
312int
313main(void)
314{
315 const struct CMUnitTest tests[] = {
roman12c3d522023-07-26 13:39:30 +0200316 cmocka_unit_test_setup_teardown(test_nc_ks_ts_ssh, setup_ssh, teardown_f),
317 cmocka_unit_test_setup_teardown(test_nc_ks_ts_tls, setup_tls, teardown_f),
roman45cec4e2023-02-17 10:21:39 +0100318 };
319
320 setenv("CMOCKA_TEST_ABORT", "1", 1);
321 return cmocka_run_group_tests(tests, NULL, NULL);
322}