blob: 0b10c1bb3b313ab0d3af5a0477280b0084902d00 [file] [log] [blame]
roman27215242023-03-10 14:55:00 +01001/**
2 * @file test_keystore.c
3 * @author Roman Janota <xjanot04@fit.vutbr.cz>
4 * @brief libnetconf2 Linux PAM keyboard-interactive authentication test
5 *
6 * @copyright
7 * Copyright (c) 2022 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#include <errno.h>
17#include <pthread.h>
18#include <setjmp.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <cmocka.h>
24
25#include <libnetconf.h>
26#include <libyang/libyang.h>
27#include <log.h>
28#include <server_config.h>
29#include <session_client.h>
30#include <session_server.h>
31#include "config_new.h"
32
33#include "tests/config.h"
34
35#define NC_ACCEPT_TIMEOUT 2000
36#define NC_PS_POLL_TIMEOUT 2000
37
38struct ly_ctx *ctx;
39
40struct test_state {
41 pthread_barrier_t barrier;
42};
43
44static void *
45server_thread(void *arg)
46{
47 int ret;
48 NC_MSG_TYPE msgtype;
49 struct nc_session *session;
50 struct nc_pollsession *ps;
51 struct test_state *state = arg;
52
53 ps = nc_ps_new();
54 assert_non_null(ps);
55
56 /* accept a session and add it to the poll session structure */
57 pthread_barrier_wait(&state->barrier);
58 msgtype = nc_accept(NC_ACCEPT_TIMEOUT, ctx, &session);
59 assert_int_equal(msgtype, NC_MSG_HELLO);
60
61 ret = nc_ps_add_session(ps, session);
62 assert_int_equal(ret, 0);
63
64 do {
65 ret = nc_ps_poll(ps, NC_PS_POLL_TIMEOUT, NULL);
66 assert_int_equal(ret & NC_PSPOLL_RPC, NC_PSPOLL_RPC);
67 } while (!(ret & NC_PSPOLL_SESSION_TERM));
68
69 nc_ps_clear(ps, 1, NULL);
70 nc_ps_free(ps);
71 nc_thread_destroy();
72 return NULL;
73}
74
75static int
76ssh_hostkey_check_clb(const char *hostname, ssh_session session, void *priv)
77{
78 (void)hostname;
79 (void)session;
80 (void)priv;
81 /* skip the knownhost check */
82
83 return 0;
84}
85
86static void *
87client_thread_pubkey(void *arg)
88{
89 int ret;
90 struct nc_session *session = NULL;
91 struct test_state *state = arg;
92
93 ret = nc_client_set_schema_searchpath(MODULES_DIR);
94 assert_int_equal(ret, 0);
95
roman4f9bb442023-03-24 09:05:37 +010096 ret = nc_client_ssh_set_username("test_config_new_openssh");
roman27215242023-03-10 14:55:00 +010097 assert_int_equal(ret, 0);
98
99 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
100 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
101 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
102
103 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_rsa.pub", TESTS_DIR "/data/key_rsa");
104 assert_int_equal(ret, 0);
105
106 pthread_barrier_wait(&state->barrier);
107 session = nc_connect_ssh("127.0.0.1", 10005, NULL);
108 assert_non_null(session);
109
110 nc_session_free(session, NULL);
111 nc_thread_destroy();
112 return NULL;
113}
114
115static void
116test_nc_auth_pubkey(void **state)
117{
118 int ret, i;
119 pthread_t tids[2];
120
121 assert_non_null(state);
122
123 ret = pthread_create(&tids[0], NULL, client_thread_pubkey, *state);
124 assert_int_equal(ret, 0);
125 ret = pthread_create(&tids[1], NULL, server_thread, *state);
126 assert_int_equal(ret, 0);
127
128 for (i = 0; i < 2; i++) {
129 pthread_join(tids[i], NULL);
130 }
131}
132
133static int
134setup_f(void **state)
135{
136 int ret;
137 struct lyd_node *tree = NULL;
138 struct test_state *test_state;
139
140 nc_verbosity(NC_VERB_VERBOSE);
141
142 /* init barrier */
143 test_state = malloc(sizeof *test_state);
144 assert_non_null(test_state);
145
146 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
147 assert_int_equal(ret, 0);
148
149 *state = test_state;
150
151 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
152 assert_int_equal(ret, 0);
153
154 ret = nc_server_init_ctx(&ctx);
155 assert_int_equal(ret, 0);
156
157 ret = nc_server_config_load_modules(&ctx);
158 assert_int_equal(ret, 0);
159
160 ret = nc_server_config_ssh_new_hostkey(TESTS_DIR "/data/server.key", NULL, ctx, "endpt", "hostkey", &tree);
161 assert_int_equal(ret, 0);
162
163 ret = nc_server_config_ssh_new_address_port("127.0.0.1", "10005", ctx, "endpt", &tree);
164 assert_int_equal(ret, 0);
165
166 ret = nc_server_config_ssh_new_host_key_algs(ctx, "endpt", &tree, 1, "rsa-sha2-512");
167 assert_int_equal(ret, 0);
168
roman4f9bb442023-03-24 09:05:37 +0100169 ret = nc_server_config_ssh_new_user(TESTS_DIR "/data/key_rsa.pub", ctx, "endpt", "test_config_new_openssh", "pubkey", &tree);
170 assert_int_equal(ret, 0);
171
roman27215242023-03-10 14:55:00 +0100172 /* configure the server based on the data */
173 ret = nc_server_config_setup(tree);
174 assert_int_equal(ret, 0);
175
176 /* initialize client */
177 nc_client_init();
178
179 ret = nc_server_init();
180 assert_int_equal(ret, 0);
181
182 /* skip the knownhost check */
183 nc_client_ssh_set_auth_hostkey_check_clb(ssh_hostkey_check_clb, NULL);
184
185 lyd_free_all(tree);
186
187 return 0;
188}
189
190static int
191teardown_f(void **state)
192{
193 int ret = 0;
194 struct test_state *test_state;
195
196 assert_non_null(state);
197 test_state = *state;
198
199 ret = pthread_barrier_destroy(&test_state->barrier);
200 assert_int_equal(ret, 0);
201
202 free(*state);
203 nc_client_destroy();
204 nc_server_destroy();
205 ly_ctx_destroy(ctx);
206
207 return 0;
208}
209
210int
211main(void)
212{
213 const struct CMUnitTest tests[] = {
214 cmocka_unit_test_setup_teardown(test_nc_auth_pubkey, setup_f, teardown_f),
215 };
216
217 setenv("CMOCKA_TEST_ABORT", "1", 1);
218 return cmocka_run_group_tests(tests, NULL, NULL);
219}