blob: 138bc806d431c967cbe9dfa41372bb70b1f22ee7 [file] [log] [blame]
roman3f9b65c2023-06-05 14:26:58 +02001/**
2 * @file test_tls.c
3 * @author Roman Janota <janota@cesnet.cz>
4 * @brief libnetconf2 TLS 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 <pthread.h>
19#include <setjmp.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <cmocka.h>
25
26#include "tests/config.h"
27
28#define NC_ACCEPT_TIMEOUT 2000
29#define NC_PS_POLL_TIMEOUT 2000
30
31struct ly_ctx *ctx;
32
33struct test_state {
34 pthread_barrier_t barrier;
35};
36
37static void *
38server_thread(void *arg)
39{
40 int ret;
41 NC_MSG_TYPE msgtype;
42 struct nc_session *session;
43 struct nc_pollsession *ps;
44 struct test_state *state = arg;
45
46 (void) 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);
roman3f9b65c2023-06-05 14:26:58 +020066 return NULL;
67}
68
69static void *
70client_thread(void *arg)
71{
72 int ret;
73 struct nc_session *session = NULL;
74 struct test_state *state = arg;
75
76 ret = nc_client_set_schema_searchpath(MODULES_DIR);
77 assert_int_equal(ret, 0);
78
79 /* set client cert */
80 ret = nc_client_tls_set_cert_key_paths(TESTS_DIR "/data/client.crt", TESTS_DIR "/data/client.key");
81 assert_int_equal(ret, 0);
82
83 /* set client ca */
84 ret = nc_client_tls_set_trusted_ca_paths(NULL, TESTS_DIR "/data");
85 assert_int_equal(ret, 0);
86
87 pthread_barrier_wait(&state->barrier);
Jan Kundrátf8d9e8d2024-04-08 12:13:02 +020088 session = nc_connect_tls("127.0.0.1", TEST_PORT, NULL);
roman3f9b65c2023-06-05 14:26:58 +020089 assert_non_null(session);
90
91 nc_session_free(session, NULL);
roman3f9b65c2023-06-05 14:26:58 +020092 return NULL;
93}
94
95static void
96test_nc_tls(void **state)
97{
98 int ret, i;
99 pthread_t tids[2];
100
101 assert_non_null(state);
102
103 ret = pthread_create(&tids[0], NULL, client_thread, *state);
104 assert_int_equal(ret, 0);
105 ret = pthread_create(&tids[1], NULL, server_thread, *state);
106 assert_int_equal(ret, 0);
107
108 for (i = 0; i < 2; i++) {
109 pthread_join(tids[i], NULL);
110 }
111}
112
113static int
114setup_f(void **state)
115{
116 int ret;
117 struct lyd_node *tree = NULL;
118 struct test_state *test_state;
119
120 nc_verbosity(NC_VERB_VERBOSE);
121
122 /* init barrier */
123 test_state = malloc(sizeof *test_state);
124 assert_non_null(test_state);
125
126 ret = pthread_barrier_init(&test_state->barrier, NULL, 2);
127 assert_int_equal(ret, 0);
128
129 *state = test_state;
130
131 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
132 assert_int_equal(ret, 0);
133
134 ret = nc_server_init_ctx(&ctx);
135 assert_int_equal(ret, 0);
136
137 ret = nc_server_config_load_modules(&ctx);
138 assert_int_equal(ret, 0);
139
140 /* create new address and port data */
romand8973d12024-04-25 14:57:18 +0200141 ret = nc_server_config_add_address_port(ctx, "endpt", NC_TI_TLS, "127.0.0.1", TEST_PORT, &tree);
roman3f9b65c2023-06-05 14:26:58 +0200142 assert_int_equal(ret, 0);
143
144 /* create new server certificate data */
romane6ec60e2023-10-19 15:21:52 +0200145 ret = nc_server_config_add_tls_server_cert(ctx, "endpt", TESTS_DIR "/data/server.key", NULL, TESTS_DIR "/data/server.crt", &tree);
roman3f9b65c2023-06-05 14:26:58 +0200146 assert_int_equal(ret, 0);
147
148 /* create new end entity client cert data */
romane6ec60e2023-10-19 15:21:52 +0200149 ret = nc_server_config_add_tls_client_cert(ctx, "endpt", "client_cert", TESTS_DIR "/data/client.crt", &tree);
roman3f9b65c2023-06-05 14:26:58 +0200150 assert_int_equal(ret, 0);
151
152 /* create new client ca data */
romane6ec60e2023-10-19 15:21:52 +0200153 ret = nc_server_config_add_tls_ca_cert(ctx, "endpt", "client_ca", TESTS_DIR "/data/serverca.pem", &tree);
roman3f9b65c2023-06-05 14:26:58 +0200154 assert_int_equal(ret, 0);
155
roman12644fe2023-06-08 11:06:42 +0200156 /* create new cert-to-name */
Roytakb2794852023-10-18 14:30:22 +0200157 ret = nc_server_config_add_tls_ctn(ctx, "endpt", 1,
roman3f9b65c2023-06-05 14:26:58 +0200158 "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",
159 NC_TLS_CTN_SPECIFIED, "client", &tree);
160 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);
roman3f9b65c2023-06-05 14:26:58 +0200164 assert_int_equal(ret, 0);
165
roman3f9b65c2023-06-05 14:26:58 +0200166 ret = nc_server_init();
167 assert_int_equal(ret, 0);
168
romaneadc4782023-09-14 10:10:08 +0200169 /* initialize client */
170 ret = nc_client_init();
171 assert_int_equal(ret, 0);
172
roman3f9b65c2023-06-05 14:26:58 +0200173 lyd_free_all(tree);
174
175 return 0;
176}
177
178static int
179teardown_f(void **state)
180{
181 int ret = 0;
182 struct test_state *test_state;
183
184 assert_non_null(state);
185 test_state = *state;
186
187 ret = pthread_barrier_destroy(&test_state->barrier);
188 assert_int_equal(ret, 0);
189
190 free(*state);
191 nc_client_destroy();
192 nc_server_destroy();
193 ly_ctx_destroy(ctx);
194
195 return 0;
196}
197
198int
199main(void)
200{
201 const struct CMUnitTest tests[] = {
202 cmocka_unit_test_setup_teardown(test_nc_tls, setup_f, teardown_f),
203 };
204
205 setenv("CMOCKA_TEST_ABORT", "1", 1);
206 return cmocka_run_group_tests(tests, NULL, NULL);
207}