blob: 61eb7bb71d4f63aa427eb44c5018317081ae848e [file] [log] [blame]
roman44600f42023-04-28 15:54:27 +02001/**
2 * @file test_ed25519.c
3 * @author Roman Janota <xjanot04@fit.vutbr.cz>
4 * @brief libnetconf2 ED25519 key authentication 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
39static 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 (void) arg;
49
50 ps = nc_ps_new();
51 assert_non_null(ps);
52
53 /* accept a session and add it to the poll session structure */
54 pthread_barrier_wait(&state->barrier);
55 msgtype = nc_accept(NC_ACCEPT_TIMEOUT, ctx, &session);
56 assert_int_equal(msgtype, NC_MSG_HELLO);
57
58 ret = nc_ps_add_session(ps, session);
59 assert_int_equal(ret, 0);
60
61 do {
62 ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
63 assert_int_equal(ret & NC_PSPOLL_RPC, NC_PSPOLL_RPC);
64 } while (!(ret & NC_PSPOLL_SESSION_TERM));
65
66 nc_ps_clear(ps, 1, NULL);
67 nc_ps_free(ps);
roman44600f42023-04-28 15:54:27 +020068 return NULL;
69}
70
71static void *
72client_thread(void *arg)
73{
74 int ret;
75 struct nc_session *session = NULL;
76 struct test_state *state = arg;
77
78 /* skip all hostkey and known_hosts checks */
79 nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
80
81 /* set directory where to search for modules */
82 ret = nc_client_set_schema_searchpath(MODULES_DIR);
83 assert_int_equal(ret, 0);
84
85 /* set ssh username */
86 ret = nc_client_ssh_set_username("test_ed25519");
87 assert_int_equal(ret, 0);
88
89 /* add client's key pair */
90 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/id_ed25519.pub", TESTS_DIR "/data/id_ed25519");
91 assert_int_equal(ret, 0);
92
93 pthread_barrier_wait(&state->barrier);
94 /* connect */
Jan Kundrátf8d9e8d2024-04-08 12:13:02 +020095 session = nc_connect_ssh("127.0.0.1", TEST_PORT, NULL);
roman44600f42023-04-28 15:54:27 +020096 assert_non_null(session);
97
98 nc_session_free(session, NULL);
roman44600f42023-04-28 15:54:27 +020099 return NULL;
100}
101
102static void
103test_nc_ed25519(void **state)
104{
105 int ret, i;
106 pthread_t tids[2];
107
108 assert_non_null(state);
109
110 /* client */
111 ret = pthread_create(&tids[0], NULL, client_thread, *state);
112 assert_int_equal(ret, 0);
113
114 /* server */
115 ret = pthread_create(&tids[1], NULL, server_thread, *state);
116 assert_int_equal(ret, 0);
117
118 for (i = 0; i < 2; i++) {
119 pthread_join(tids[i], NULL);
120 }
121}
122
123static int
124setup_f(void **state)
125{
126 int ret;
127 struct lyd_node *tree = NULL;
128 struct test_state *test_state;
129
130 nc_verbosity(NC_VERB_VERBOSE);
131
132 /* init barrier */
133 test_state = malloc(sizeof *test_state);
134 assert_non_null(test_state);
135
136 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
137 assert_int_equal(ret, 0);
138
139 *state = test_state;
140
141 /* create new context */
142 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
143 assert_int_equal(ret, 0);
144
145 /* load default modules into context */
146 ret = nc_server_init_ctx(&ctx);
147 assert_int_equal(ret, 0);
148
149 /* load ietf-netconf-server module and it's imports into context */
150 ret = nc_server_config_load_modules(&ctx);
151 assert_int_equal(ret, 0);
152
Roytakb2794852023-10-18 14:30:22 +0200153 ret = nc_server_config_add_ssh_hostkey(ctx, "endpt", "hostkey", TESTS_DIR "/data/server.key", NULL, &tree);
roman44600f42023-04-28 15:54:27 +0200154 assert_int_equal(ret, 0);
155
romand8973d12024-04-25 14:57:18 +0200156 ret = nc_server_config_add_address_port(ctx, "endpt", NC_TI_SSH, "127.0.0.1", TEST_PORT, &tree);
roman44600f42023-04-28 15:54:27 +0200157 assert_int_equal(ret, 0);
158
Roytakb2794852023-10-18 14:30:22 +0200159 ret = nc_server_config_add_ssh_user_pubkey(ctx, "endpt", "test_ed25519", "pubkey", TESTS_DIR "/data/id_ed25519.pub", &tree);
roman44600f42023-04-28 15:54:27 +0200160 assert_int_equal(ret, 0);
161
162 /* configure the server based on the data */
roman142718b2023-06-29 09:15:29 +0200163 ret = nc_server_config_setup_data(tree);
roman44600f42023-04-28 15:54:27 +0200164 assert_int_equal(ret, 0);
165
roman44600f42023-04-28 15:54:27 +0200166 /* initialize server */
167 ret = nc_server_init();
168 assert_int_equal(ret, 0);
169
romaneadc4782023-09-14 10:10:08 +0200170 /* initialize client */
171 ret = nc_client_init();
172 assert_int_equal(ret, 0);
173
roman44600f42023-04-28 15:54:27 +0200174 lyd_free_all(tree);
175
176 return 0;
177}
178
179static int
180teardown_f(void **state)
181{
182 int ret = 0;
183 struct test_state *test_state;
184
185 assert_non_null(state);
186 test_state = *state;
187
188 ret = pthread_barrier_destroy(&test_state->barrier);
189 assert_int_equal(ret, 0);
190
191 free(*state);
192 nc_client_destroy();
193 nc_server_destroy();
194 ly_ctx_destroy(ctx);
195
196 return 0;
197}
198
199int
200main(void)
201{
202 const struct CMUnitTest tests[] = {
203 cmocka_unit_test_setup_teardown(test_nc_ed25519, setup_f, teardown_f),
204 };
205
206 setenv("CMOCKA_TEST_ABORT", "1", 1);
207 return cmocka_run_group_tests(tests, NULL, NULL);
208}