blob: 96c09531338d47ff5d5f4fd272e79f69625facef [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 */
95 session = nc_connect_ssh("127.0.0.1", 10009, NULL);
96 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
roman3f9b65c2023-06-05 14:26:58 +0200153 ret = nc_server_config_new_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
roman3f9b65c2023-06-05 14:26:58 +0200156 ret = nc_server_config_new_address_port(ctx, "endpt", NC_TI_LIBSSH, "127.0.0.1", "10009", &tree);
roman44600f42023-04-28 15:54:27 +0200157 assert_int_equal(ret, 0);
158
roman3f9b65c2023-06-05 14:26:58 +0200159 ret = nc_server_config_new_ssh_client_auth_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 */
romanf6f37a52023-05-25 14:27:51 +0200163 ret = nc_server_config_setup_diff(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
170 lyd_free_all(tree);
171
172 return 0;
173}
174
175static int
176teardown_f(void **state)
177{
178 int ret = 0;
179 struct test_state *test_state;
180
181 assert_non_null(state);
182 test_state = *state;
183
184 ret = pthread_barrier_destroy(&test_state->barrier);
185 assert_int_equal(ret, 0);
186
187 free(*state);
188 nc_client_destroy();
189 nc_server_destroy();
190 ly_ctx_destroy(ctx);
191
192 return 0;
193}
194
195int
196main(void)
197{
198 const struct CMUnitTest tests[] = {
199 cmocka_unit_test_setup_teardown(test_nc_ed25519, setup_f, teardown_f),
200 };
201
202 setenv("CMOCKA_TEST_ABORT", "1", 1);
203 return cmocka_run_group_tests(tests, NULL, NULL);
204}