blob: 159b6cff20fb8c21359c3f1f8da1f3470e974e4b [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
roman67af8982023-08-08 10:56:04 +0200144 ret = nc_server_config_new_ssh_keystore_ref(ctx, "endpt", "hostkey", "test_keystore", &tree);
roman142718b2023-06-29 09:15:29 +0200145 assert_int_equal(ret, 0);
146
roman67af8982023-08-08 10:56:04 +0200147 ret = nc_server_config_new_ssh_truststore_ref(ctx, "endpt", "client", "test_truststore", &tree);
roman142718b2023-06-29 09:15:29 +0200148 assert_int_equal(ret, 0);
149
roman13145912023-08-17 15:36:54 +0200150 ret = nc_server_config_new_keystore_asym_key(ctx, NC_TI_LIBSSH, "test_keystore", TESTS_DIR "/data/key_rsa", NULL, &tree);
roman142718b2023-06-29 09:15:29 +0200151 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
romaneadc4782023-09-14 10:10:08 +0200163 /* initialize client */
164 ret = nc_client_init();
165 assert_int_equal(ret, 0);
166
roman45cec4e2023-02-17 10:21:39 +0100167 lyd_free_all(tree);
168
169 return 0;
170}
171
roman12c3d522023-07-26 13:39:30 +0200172static void *
173client_thread_tls(void *arg)
174{
175 int ret;
176 struct nc_session *session = NULL;
177 struct test_state *state = arg;
178
179 ret = nc_client_set_schema_searchpath(MODULES_DIR);
180 assert_int_equal(ret, 0);
181
182 /* set client cert */
183 ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
184 assert_int_equal(ret, 0);
185
186 /* set client ca */
187 ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
188 assert_int_equal(ret, 0);
189
190 pthread_barrier_wait(&state->barrier);
191 session = nc_connect_tls("127.0.0.1", 10005, NULL);
192 assert_non_null(session);
193
194 nc_session_free(session, NULL);
195 return NULL;
196}
197
198static void
199test_nc_ks_ts_tls(void **state)
200{
201 int ret, i;
202 pthread_t tids[2];
203
204 assert_non_null(state);
205
206 ret = pthread_create(&tids[0], NULL, client_thread_tls, *state);
207 assert_int_equal(ret, 0);
208 ret = pthread_create(&tids[1], NULL, server_thread, *state);
209 assert_int_equal(ret, 0);
210
211 for (i = 0; i < 2; i++) {
212 pthread_join(tids[i], NULL);
213 }
214}
215
216static int
217setup_tls(void **state)
218{
219 int ret;
220 struct lyd_node *tree = NULL;
221 struct test_state *test_state;
222
223 nc_verbosity(NC_VERB_VERBOSE);
224
225 /* init barrier */
226 test_state = malloc(sizeof *test_state);
227 assert_non_null(test_state);
228
229 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
230 assert_int_equal(ret, 0);
231
232 *state = test_state;
233
234 /* new ctx */
235 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
236 assert_int_equal(ret, 0);
237
238 /* init ctx */
239 ret = nc_server_init_ctx(&ctx);
240 assert_int_equal(ret, 0);
241
242 /* load ietf netconf server module and its requisities */
243 ret = nc_server_config_load_modules(&ctx);
244 assert_int_equal(ret, 0);
245
246 /* new tls bind */
247 ret = nc_server_config_new_address_port(ctx, "endpt", NC_TI_OPENSSL, "127.0.0.1", 10005, &tree);
248 assert_int_equal(ret, 0);
249
250 /* new keystore asym key pair */
roman13145912023-08-17 15:36:54 +0200251 ret = nc_server_config_new_keystore_asym_key(ctx, NC_TI_OPENSSL, "server_key", TESTS_DIR "/data/server.key", NULL, &tree);
roman12c3d522023-07-26 13:39:30 +0200252 assert_int_equal(ret, 0);
253
254 /* new keystore cert belonging to the key pair */
255 ret = nc_server_config_new_keystore_cert(ctx, "server_key", "server_cert", TESTS_DIR "/data/server.crt", &tree);
256 assert_int_equal(ret, 0);
257
258 /* new truststore client cert */
259 ret = nc_server_config_new_truststore_cert(ctx, "ee_cert_bag", "ee_cert", TESTS_DIR "/data/client.crt", &tree);
260 assert_int_equal(ret, 0);
261
262 /* new truststore client CA cert */
263 ret = nc_server_config_new_truststore_cert(ctx, "ca_cert_bag", "ca_cert", TESTS_DIR "/data/serverca.pem", &tree);
264 assert_int_equal(ret, 0);
265
266 /* new keystore ref for the TLS server cert */
roman67af8982023-08-08 10:56:04 +0200267 ret = nc_server_config_new_tls_keystore_ref(ctx, "endpt", "server_key", "server_cert", &tree);
roman12c3d522023-07-26 13:39:30 +0200268 assert_int_equal(ret, 0);
269
270 /* new truststore ref for the client cert */
271 ret = nc_server_config_new_tls_client_cert_truststore_ref(ctx, "endpt", "ee_cert_bag", &tree);
272 assert_int_equal(ret, 0);
273
274 /* new truststore ref for the client CA cert */
275 ret = nc_server_config_new_tls_client_ca_truststore_ref(ctx, "endpt", "ca_cert_bag", &tree);
276 assert_int_equal(ret, 0);
277
278 /* new cert-to-name */
279 ret = nc_server_config_new_tls_ctn(ctx, "endpt", 1,
280 "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",
281 NC_TLS_CTN_SPECIFIED, "client", &tree);
282 assert_int_equal(ret, 0);
283
284 /* configure the server based on the data */
285 ret = nc_server_config_setup_data(tree);
286 assert_int_equal(ret, 0);
287
288 ret = nc_server_init();
289 assert_int_equal(ret, 0);
290
romaneadc4782023-09-14 10:10:08 +0200291 /* initialize client */
292 ret = nc_client_init();
293 assert_int_equal(ret, 0);
294
roman12c3d522023-07-26 13:39:30 +0200295 lyd_free_all(tree);
296
297 return 0;
298}
299
roman45cec4e2023-02-17 10:21:39 +0100300static int
301teardown_f(void **state)
302{
303 int ret = 0;
304 struct test_state *test_state;
305
306 assert_non_null(state);
307 test_state = *state;
308
309 ret = pthread_barrier_destroy(&test_state->barrier);
310 assert_int_equal(ret, 0);
311
312 free(*state);
313 nc_client_destroy();
314 nc_server_destroy();
315 ly_ctx_destroy(ctx);
316
317 return 0;
318}
319
320int
321main(void)
322{
323 const struct CMUnitTest tests[] = {
roman12c3d522023-07-26 13:39:30 +0200324 cmocka_unit_test_setup_teardown(test_nc_ks_ts_ssh, setup_ssh, teardown_f),
325 cmocka_unit_test_setup_teardown(test_nc_ks_ts_tls, setup_tls, teardown_f),
roman45cec4e2023-02-17 10:21:39 +0100326 };
327
328 setenv("CMOCKA_TEST_ABORT", "1", 1);
329 return cmocka_run_group_tests(tests, NULL, NULL);
330}