blob: 4696735ab1066dad51fa0e6e63864433b85167be [file] [log] [blame]
Radek Krejci9f03b482015-10-22 16:02:10 +02001/**
Michal Vasko95ea9ff2021-11-09 12:29:14 +01002 * @file session_client_tls.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @author Michal Vasko <mvasko@cesnet.cz>
5 * @brief libnetconf2 - TLS specific session client transport functions
Radek Krejci9f03b482015-10-22 16:02:10 +02006 *
Michal Vasko11d4cdb2015-10-29 11:42:52 +01007 * This source is compiled only with libssl.
Radek Krejci9f03b482015-10-22 16:02:10 +02008 *
Michal Vasko95ea9ff2021-11-09 12:29:14 +01009 * @copyright
Radek Krejci9f03b482015-10-22 16:02:10 +020010 * Copyright (c) 2015 CESNET, z.s.p.o.
11 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010012 * This source code is licensed under BSD 3-Clause License (the "License").
13 * You may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
Michal Vaskoafd416b2016-02-25 14:51:46 +010015 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010016 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejci9f03b482015-10-22 16:02:10 +020017 */
18
Michal Vaskoba9f3582023-02-22 10:26:32 +010019#define _GNU_SOURCE /* pthread_rwlock_t, strdup */
20
Radek Krejci9f03b482015-10-22 16:02:10 +020021#include <assert.h>
22#include <errno.h>
roman7731b3a2024-04-23 15:12:32 +020023#include <signal.h>
Radek Krejci9f03b482015-10-22 16:02:10 +020024#include <string.h>
25#include <unistd.h>
26
27#include <libyang/libyang.h>
28
roman7731b3a2024-04-23 15:12:32 +020029#include "compat.h"
roman3f9b65c2023-06-05 14:26:58 +020030#include "config.h"
31#include "log_p.h"
Michal Vaskoe22c6732016-01-29 11:03:02 +010032#include "session_client.h"
33#include "session_client_ch.h"
roman3f9b65c2023-06-05 14:26:58 +020034#include "session_p.h"
roman68ea7d62024-04-05 12:32:49 +020035#include "session_wrapper.h"
Michal Vasko11d4cdb2015-10-29 11:42:52 +010036
Radek Krejci62aa0642017-05-25 16:33:49 +020037struct nc_client_context *nc_client_context_location(void);
38
39#define client_opts nc_client_context_location()->opts
40#define tls_opts nc_client_context_location()->tls_opts
41#define tls_ch_opts nc_client_context_location()->tls_ch_opts
Michal Vasko3031aae2016-01-27 16:07:18 +010042
Kevin Barrettd37d2fb2019-08-28 14:25:34 -040043void
Michal Vaskoe22c6732016-01-29 11:03:02 +010044_nc_client_tls_destroy_opts(struct nc_client_tls_opts *opts)
45{
46 free(opts->cert_path);
47 free(opts->key_path);
48 free(opts->ca_file);
49 free(opts->ca_dir);
Michal Vaskoe22c6732016-01-29 11:03:02 +010050 free(opts->crl_file);
51 free(opts->crl_dir);
Radek Krejci5cebc6b2017-05-26 13:24:38 +020052 memset(opts, 0, sizeof *opts);
Michal Vaskoe22c6732016-01-29 11:03:02 +010053}
54
Michal Vaskob7558c52016-02-26 15:04:19 +010055void
Michal Vaskoe22c6732016-01-29 11:03:02 +010056nc_client_tls_destroy_opts(void)
57{
58 _nc_client_tls_destroy_opts(&tls_opts);
59 _nc_client_tls_destroy_opts(&tls_ch_opts);
60}
61
Michal Vasko3031aae2016-01-27 16:07:18 +010062static int
Michal Vaskoe22c6732016-01-29 11:03:02 +010063_nc_client_tls_set_cert_key_paths(const char *client_cert, const char *client_key, struct nc_client_tls_opts *opts)
Michal Vasko11d4cdb2015-10-29 11:42:52 +010064{
roman40672412023-05-04 11:10:22 +020065 NC_CHECK_ARG_RET(NULL, client_cert, -1);
Michal Vasko11d4cdb2015-10-29 11:42:52 +010066
Michal Vasko3031aae2016-01-27 16:07:18 +010067 free(opts->cert_path);
68 free(opts->key_path);
Michal Vasko11d4cdb2015-10-29 11:42:52 +010069
Michal Vasko9db2a6f2016-02-01 13:26:03 +010070 opts->cert_path = strdup(client_cert);
roman3a95bb22023-10-26 11:07:17 +020071 NC_CHECK_ERRMEM_RET(!opts->cert_path, -1);
Michal Vasko11d4cdb2015-10-29 11:42:52 +010072
Michal Vasko3031aae2016-01-27 16:07:18 +010073 if (client_key) {
74 opts->key_path = strdup(client_key);
roman3a95bb22023-10-26 11:07:17 +020075 NC_CHECK_ERRMEM_RET(!opts->key_path, -1);
Michal Vasko3031aae2016-01-27 16:07:18 +010076 } else {
77 opts->key_path = NULL;
Michal Vasko11d4cdb2015-10-29 11:42:52 +010078 }
79
Michal Vasko7f1c78b2016-01-19 09:52:14 +010080 return 0;
Michal Vasko11d4cdb2015-10-29 11:42:52 +010081}
82
Michal Vasko3031aae2016-01-27 16:07:18 +010083API int
Michal Vaskoe22c6732016-01-29 11:03:02 +010084nc_client_tls_set_cert_key_paths(const char *client_cert, const char *client_key)
Michal Vasko11d4cdb2015-10-29 11:42:52 +010085{
Michal Vaskoe22c6732016-01-29 11:03:02 +010086 return _nc_client_tls_set_cert_key_paths(client_cert, client_key, &tls_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +010087}
88
89API int
Michal Vaskoe22c6732016-01-29 11:03:02 +010090nc_client_tls_ch_set_cert_key_paths(const char *client_cert, const char *client_key)
Michal Vasko3031aae2016-01-27 16:07:18 +010091{
Michal Vaskoe22c6732016-01-29 11:03:02 +010092 return _nc_client_tls_set_cert_key_paths(client_cert, client_key, &tls_ch_opts);
93}
94
95static void
96_nc_client_tls_get_cert_key_paths(const char **client_cert, const char **client_key, struct nc_client_tls_opts *opts)
97{
98 if (!client_cert && !client_key) {
roman40672412023-05-04 11:10:22 +020099 ERRARG(NULL, "client_cert and client_key");
Michal Vaskoe22c6732016-01-29 11:03:02 +0100100 return;
101 }
102
103 if (client_cert) {
104 *client_cert = opts->cert_path;
105 }
106 if (client_key) {
107 *client_key = opts->key_path;
108 }
109}
110
111API void
112nc_client_tls_get_cert_key_paths(const char **client_cert, const char **client_key)
113{
114 _nc_client_tls_get_cert_key_paths(client_cert, client_key, &tls_opts);
115}
116
117API void
118nc_client_tls_ch_get_cert_key_paths(const char **client_cert, const char **client_key)
119{
120 _nc_client_tls_get_cert_key_paths(client_cert, client_key, &tls_ch_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +0100121}
122
123static int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100124_nc_client_tls_set_trusted_ca_paths(const char *ca_file, const char *ca_dir, struct nc_client_tls_opts *opts)
Michal Vasko3031aae2016-01-27 16:07:18 +0100125{
Michal Vasko3031aae2016-01-27 16:07:18 +0100126 if (!ca_file && !ca_dir) {
roman40672412023-05-04 11:10:22 +0200127 ERRARG(NULL, "ca_file and ca_dir");
Michal Vasko3031aae2016-01-27 16:07:18 +0100128 return -1;
129 }
130
Michal Vasko3031aae2016-01-27 16:07:18 +0100131 free(opts->ca_file);
132 free(opts->ca_dir);
133
134 if (ca_file) {
135 opts->ca_file = strdup(ca_file);
roman3a95bb22023-10-26 11:07:17 +0200136 NC_CHECK_ERRMEM_RET(!opts->ca_file, -1);
Michal Vasko3031aae2016-01-27 16:07:18 +0100137 } else {
138 opts->ca_file = NULL;
139 }
140
141 if (ca_dir) {
142 opts->ca_dir = strdup(ca_dir);
roman3a95bb22023-10-26 11:07:17 +0200143 NC_CHECK_ERRMEM_RET(!opts->ca_dir, -1);
Michal Vasko3031aae2016-01-27 16:07:18 +0100144 } else {
145 opts->ca_dir = NULL;
146 }
147
Michal Vasko3031aae2016-01-27 16:07:18 +0100148 return 0;
149}
150
151API int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100152nc_client_tls_set_trusted_ca_paths(const char *ca_file, const char *ca_dir)
Michal Vasko3031aae2016-01-27 16:07:18 +0100153{
Michal Vaskoe22c6732016-01-29 11:03:02 +0100154 return _nc_client_tls_set_trusted_ca_paths(ca_file, ca_dir, &tls_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +0100155}
156
157API int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100158nc_client_tls_ch_set_trusted_ca_paths(const char *ca_file, const char *ca_dir)
Michal Vasko3031aae2016-01-27 16:07:18 +0100159{
Michal Vaskoe22c6732016-01-29 11:03:02 +0100160 return _nc_client_tls_set_trusted_ca_paths(ca_file, ca_dir, &tls_ch_opts);
161}
162
163static void
164_nc_client_tls_get_trusted_ca_paths(const char **ca_file, const char **ca_dir, struct nc_client_tls_opts *opts)
165{
166 if (!ca_file && !ca_dir) {
roman40672412023-05-04 11:10:22 +0200167 ERRARG(NULL, "ca_file and ca_dir");
Michal Vaskoe22c6732016-01-29 11:03:02 +0100168 return;
169 }
170
171 if (ca_file) {
172 *ca_file = opts->ca_file;
173 }
174 if (ca_dir) {
175 *ca_dir = opts->ca_dir;
176 }
177}
178
179API void
180nc_client_tls_get_trusted_ca_paths(const char **ca_file, const char **ca_dir)
181{
182 _nc_client_tls_get_trusted_ca_paths(ca_file, ca_dir, &tls_opts);
183}
184
185API void
186nc_client_tls_ch_get_trusted_ca_paths(const char **ca_file, const char **ca_dir)
187{
188 _nc_client_tls_get_trusted_ca_paths(ca_file, ca_dir, &tls_ch_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +0100189}
190
191static int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100192_nc_client_tls_set_crl_paths(const char *crl_file, const char *crl_dir, struct nc_client_tls_opts *opts)
Michal Vasko3031aae2016-01-27 16:07:18 +0100193{
Michal Vasko3031aae2016-01-27 16:07:18 +0100194 if (!crl_file && !crl_dir) {
roman40672412023-05-04 11:10:22 +0200195 ERRARG(NULL, "crl_file and crl_dir");
Michal Vasko3031aae2016-01-27 16:07:18 +0100196 return -1;
197 }
198
Michal Vasko3031aae2016-01-27 16:07:18 +0100199 free(opts->crl_file);
200 free(opts->crl_dir);
201
202 if (crl_file) {
203 opts->crl_file = strdup(crl_file);
roman3a95bb22023-10-26 11:07:17 +0200204 NC_CHECK_ERRMEM_RET(!opts->crl_file, -1);
Michal Vasko3031aae2016-01-27 16:07:18 +0100205 } else {
206 opts->crl_file = NULL;
207 }
208
209 if (crl_dir) {
210 opts->crl_dir = strdup(crl_dir);
roman3a95bb22023-10-26 11:07:17 +0200211 NC_CHECK_ERRMEM_RET(!opts->crl_dir, -1);
Michal Vasko3031aae2016-01-27 16:07:18 +0100212 } else {
213 opts->crl_dir = NULL;
214 }
215
Michal Vasko3031aae2016-01-27 16:07:18 +0100216 return 0;
217}
218
219API int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100220nc_client_tls_set_crl_paths(const char *crl_file, const char *crl_dir)
Michal Vasko3031aae2016-01-27 16:07:18 +0100221{
Michal Vaskoe22c6732016-01-29 11:03:02 +0100222 return _nc_client_tls_set_crl_paths(crl_file, crl_dir, &tls_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +0100223}
224
225API int
Michal Vaskoe22c6732016-01-29 11:03:02 +0100226nc_client_tls_ch_set_crl_paths(const char *crl_file, const char *crl_dir)
Michal Vasko3031aae2016-01-27 16:07:18 +0100227{
Michal Vaskoe22c6732016-01-29 11:03:02 +0100228 return _nc_client_tls_set_crl_paths(crl_file, crl_dir, &tls_ch_opts);
229}
230
231static void
232_nc_client_tls_get_crl_paths(const char **crl_file, const char **crl_dir, struct nc_client_tls_opts *opts)
233{
234 if (!crl_file && !crl_dir) {
roman40672412023-05-04 11:10:22 +0200235 ERRARG(NULL, "crl_file and crl_dir");
Michal Vaskoe22c6732016-01-29 11:03:02 +0100236 return;
237 }
238
239 if (crl_file) {
240 *crl_file = opts->crl_file;
241 }
242 if (crl_dir) {
243 *crl_dir = opts->crl_dir;
244 }
245}
246
247API void
248nc_client_tls_get_crl_paths(const char **crl_file, const char **crl_dir)
249{
250 _nc_client_tls_get_crl_paths(crl_file, crl_dir, &tls_opts);
251}
252
253API void
254nc_client_tls_ch_get_crl_paths(const char **crl_file, const char **crl_dir)
255{
256 _nc_client_tls_get_crl_paths(crl_file, crl_dir, &tls_ch_opts);
Michal Vasko3031aae2016-01-27 16:07:18 +0100257}
258
259API int
260nc_client_tls_ch_add_bind_listen(const char *address, uint16_t port)
261{
roman506354a2024-04-11 09:37:22 +0200262 return nc_client_ch_add_bind_listen(address, port, NULL, NC_TI_TLS);
Michal Vasko9d4cca52022-09-07 11:19:57 +0200263}
264
265API int
266nc_client_tls_ch_add_bind_hostname_listen(const char *address, uint16_t port, const char *hostname)
267{
roman506354a2024-04-11 09:37:22 +0200268 return nc_client_ch_add_bind_listen(address, port, hostname, NC_TI_TLS);
Michal Vasko3031aae2016-01-27 16:07:18 +0100269}
270
271API int
272nc_client_tls_ch_del_bind(const char *address, uint16_t port)
273{
roman506354a2024-04-11 09:37:22 +0200274 return nc_client_ch_del_bind(address, port, NC_TI_TLS);
Michal Vasko3031aae2016-01-27 16:07:18 +0100275}
276
Michal Vasko3031aae2016-01-27 16:07:18 +0100277static int
roman68ea7d62024-04-05 12:32:49 +0200278nc_client_tls_connect_check(int connect_ret, void *tls_session, const char *peername)
Michal Vasko3031aae2016-01-27 16:07:18 +0100279{
roman68ea7d62024-04-05 12:32:49 +0200280 uint32_t verify;
roman7731b3a2024-04-23 15:12:32 +0200281 char *err;
Michal Vasko9af52322022-07-25 14:39:30 +0200282
283 /* check certificate verification result */
roman68ea7d62024-04-05 12:32:49 +0200284 verify = nc_tls_get_verify_result_wrap(tls_session);
roman008cfe72024-04-05 12:36:18 +0200285 if (!verify && (connect_ret == 1)) {
roman68ea7d62024-04-05 12:32:49 +0200286 VRB(NULL, "Server certificate verified (domain \"%s\").", peername);
287 } else if (verify) {
roman7731b3a2024-04-23 15:12:32 +0200288 err = nc_tls_verify_error_string_wrap(verify);
289 ERR(NULL, "Server certificate error (%s).", err);
290 free(err);
Michal Vasko9af52322022-07-25 14:39:30 +0200291 }
292
293 /* check TLS connection result */
294 if (connect_ret != 1) {
roman7731b3a2024-04-23 15:12:32 +0200295 nc_client_tls_print_connect_err_wrap(connect_ret, peername, tls_session);
Michal Vasko9af52322022-07-25 14:39:30 +0200296 }
297
298 return connect_ret;
Radek Krejci9f03b482015-10-22 16:02:10 +0200299}
300
roman68ea7d62024-04-05 12:32:49 +0200301static void *
302nc_client_tls_session_new(int sock, const char *host, int timeout, struct nc_client_tls_opts *opts, void **out_tls_cfg, struct nc_tls_ctx *tls_ctx)
303{
roman7731b3a2024-04-23 15:12:32 +0200304 int ret = 0, sock_tmp = sock;
roman68ea7d62024-04-05 12:32:49 +0200305 struct timespec ts_timeout;
306 void *tls_session, *tls_cfg, *cli_cert, *cli_pkey, *cert_store, *crl_store;
307
308 tls_session = tls_cfg = cli_cert = cli_pkey = cert_store = crl_store = NULL;
309
310 /* prepare TLS context from which a session will be created */
roman7731b3a2024-04-23 15:12:32 +0200311 tls_cfg = nc_tls_config_new_wrap(NC_CLIENT);
roman68ea7d62024-04-05 12:32:49 +0200312 if (!tls_cfg) {
313 goto fail;
314 }
315
316 /* opaque CA/CRL certificate store */
317 cert_store = nc_tls_cert_store_new_wrap();
318 if (!cert_store) {
319 goto fail;
320 }
321
322 /* load client's key and certificate */
323 if (nc_client_tls_load_cert_key_wrap(opts->cert_path, opts->key_path, &cli_cert, &cli_pkey)) {
324 goto fail;
325 }
326
327 /* load trusted CA certificates */
328 if (nc_client_tls_load_trusted_certs_wrap(cert_store, opts->ca_file, opts->ca_dir)) {
329 goto fail;
330 }
331
332 if (opts->crl_file || opts->crl_dir) {
333 /* opaque CRL store */
334 crl_store = nc_tls_crl_store_new_wrap();
335 if (!crl_store) {
336 goto fail;
337 }
338
roman7731b3a2024-04-23 15:12:32 +0200339 /* load CRLs into the crl store */
340 if (nc_client_tls_load_crl_wrap(crl_store, opts->crl_file, opts->crl_dir)) {
roman68ea7d62024-04-05 12:32:49 +0200341 goto fail;
342 }
343 }
344
roman7731b3a2024-04-23 15:12:32 +0200345 /* set client's verify mode flags */
346 nc_client_tls_set_verify_wrap(tls_cfg);
347
roman68ea7d62024-04-05 12:32:49 +0200348 /* init TLS context and store data which may be needed later in it */
roman7731b3a2024-04-23 15:12:32 +0200349 if (nc_tls_init_ctx_wrap(sock, cli_cert, cli_pkey, cert_store, crl_store, tls_ctx)) {
350 goto fail;
roman68ea7d62024-04-05 12:32:49 +0200351 }
352
353 /* memory is managed by context now */
354 cli_cert = cli_pkey = cert_store = crl_store = NULL;
355
356 /* setup config from ctx */
roman7731b3a2024-04-23 15:12:32 +0200357 if (nc_tls_setup_config_from_ctx_wrap(tls_ctx, NC_CLIENT, tls_cfg)) {
roman68ea7d62024-04-05 12:32:49 +0200358 goto fail;
359 }
360
361 /* session from config */
362 tls_session = nc_tls_session_new_wrap(tls_cfg);
363 if (!tls_session) {
364 goto fail;
365 }
366
367 /* set session fd */
368 nc_server_tls_set_fd_wrap(tls_session, sock, tls_ctx);
369
370 sock = -1;
371
372 /* set session hostname to check against in the server cert */
373 if (nc_client_tls_set_hostname_wrap(tls_session, host)) {
374 goto fail;
375 }
376
377 /* handshake */
378 if (timeout > -1) {
379 nc_timeouttime_get(&ts_timeout, timeout);
380 }
roman7731b3a2024-04-23 15:12:32 +0200381 while ((ret = nc_client_tls_handshake_step_wrap(tls_session, sock_tmp)) == 0) {
roman68ea7d62024-04-05 12:32:49 +0200382 usleep(NC_TIMEOUT_STEP);
383 if ((timeout > -1) && (nc_timeouttime_cur_diff(&ts_timeout) < 1)) {
384 ERR(NULL, "SSL connect timeout.");
385 goto fail;
386 }
387 }
388
389 /* check if handshake was ok */
390 if (nc_client_tls_connect_check(ret, tls_session, host) != 1) {
391 goto fail;
392 }
393
394 *out_tls_cfg = tls_cfg;
395 return tls_session;
396
397fail:
398 if (sock > -1) {
399 close(sock);
400 }
roman7731b3a2024-04-23 15:12:32 +0200401
402 nc_tls_session_destroy_wrap(tls_session);
403 nc_tls_cert_destroy_wrap(cli_cert);
404 nc_tls_privkey_destroy_wrap(cli_pkey);
405 nc_tls_cert_store_destroy_wrap(cert_store);
406 nc_tls_crl_store_destroy_wrap(crl_store);
407 nc_tls_config_destroy_wrap(tls_cfg);
roman68ea7d62024-04-05 12:32:49 +0200408 return NULL;
409}
410
Radek Krejci9f03b482015-10-22 16:02:10 +0200411API struct nc_session *
Michal Vasko9bee18d2015-12-08 14:41:42 +0100412nc_connect_tls(const char *host, unsigned short port, struct ly_ctx *ctx)
Radek Krejci9f03b482015-10-22 16:02:10 +0200413{
Radek Krejci9f03b482015-10-22 16:02:10 +0200414 struct nc_session *session = NULL;
roman68ea7d62024-04-05 12:32:49 +0200415 int sock;
Michal Vasko66032bc2019-01-22 15:03:12 +0100416 char *ip_host = NULL;
roman68ea7d62024-04-05 12:32:49 +0200417 void *tls_cfg = NULL;
418 struct nc_tls_ctx tls_ctx = {0};
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100419
romand82caf12024-03-05 14:21:39 +0100420 if (!tls_opts.cert_path) {
421 ERR(NULL, "Client certificate not set.");
422 return NULL;
423 } else if (!tls_opts.ca_file && !tls_opts.ca_dir) {
424 ERR(NULL, "Certificate authority certificates not set.");
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100425 return NULL;
426 }
Radek Krejci9f03b482015-10-22 16:02:10 +0200427
428 /* process parameters */
roman3f9b65c2023-06-05 14:26:58 +0200429 if (!host || (host[0] == '\0')) {
Radek Krejci9f03b482015-10-22 16:02:10 +0200430 host = "localhost";
431 }
432
433 if (!port) {
434 port = NC_PORT_TLS;
435 }
436
Radek Krejci9f03b482015-10-22 16:02:10 +0200437 /* prepare session structure */
Michal Vasko131120a2018-05-29 15:44:02 +0200438 session = nc_new_session(NC_CLIENT, 0);
roman3a95bb22023-10-26 11:07:17 +0200439 NC_CHECK_ERRMEM_RET(!session, NULL);
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100440 session->status = NC_STATUS_STARTING;
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100441
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100442 /* create and assign socket */
Michal Vaskoe49a15f2019-05-27 14:18:36 +0200443 sock = nc_sock_connect(host, port, -1, &client_opts.ka, NULL, &ip_host);
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100444 if (sock == -1) {
Michal Vasko05532772021-06-03 12:12:38 +0200445 ERR(NULL, "Unable to connect to %s:%u (%s).", host, port, strerror(errno));
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100446 goto fail;
447 }
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100448
roman68ea7d62024-04-05 12:32:49 +0200449 /* fill the session */
roman506354a2024-04-11 09:37:22 +0200450 session->ti_type = NC_TI_TLS;
roman68ea7d62024-04-05 12:32:49 +0200451 if (!(session->ti.tls.session = nc_client_tls_session_new(sock, host, NC_TRANSPORT_TIMEOUT, &tls_opts, &tls_cfg, &tls_ctx))) {
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100452 goto fail;
453 }
roman68ea7d62024-04-05 12:32:49 +0200454 session->ti.tls.config = tls_cfg;
455
456 /* memory belongs to session */
457 memcpy(&session->ti.tls.ctx, &tls_ctx, sizeof tls_ctx);
458 memset(&tls_ctx, 0, sizeof tls_ctx);
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100459
Michal Vasko78939072022-12-12 07:43:18 +0100460 if (nc_client_session_new_ctx(session, ctx) != EXIT_SUCCESS) {
Radek Krejcifd5b6682017-06-13 15:52:53 +0200461 goto fail;
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100462 }
Radek Krejcifd5b6682017-06-13 15:52:53 +0200463 ctx = session->ctx;
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100464
Radek Krejci9f03b482015-10-22 16:02:10 +0200465 /* NETCONF handshake */
Michal Vasko131120a2018-05-29 15:44:02 +0200466 if (nc_handshake_io(session) != NC_MSG_HELLO) {
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100467 goto fail;
Radek Krejci9f03b482015-10-22 16:02:10 +0200468 }
Michal Vaskoad611702015-12-03 13:41:51 +0100469 session->status = NC_STATUS_RUNNING;
Radek Krejci9f03b482015-10-22 16:02:10 +0200470
Michal Vaskoef578332016-01-25 13:20:09 +0100471 if (nc_ctx_check_and_fill(session) == -1) {
Michal Vasko57eb9402015-12-08 14:38:12 +0100472 goto fail;
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100473 }
474
roman7731b3a2024-04-23 15:12:32 +0200475 /* store information into session */
Michal Vasko93224072021-11-09 12:14:28 +0100476 session->host = ip_host;
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100477 session->port = port;
Michal Vasko93224072021-11-09 12:14:28 +0100478 session->username = strdup("certificate-based");
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100479
Radek Krejci9f03b482015-10-22 16:02:10 +0200480 return session;
481
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100482fail:
Michal Vasko66032bc2019-01-22 15:03:12 +0100483 free(ip_host);
Michal Vaskoe1a64ec2016-03-01 12:21:58 +0100484 nc_session_free(session, NULL);
roman68ea7d62024-04-05 12:32:49 +0200485 nc_tls_ctx_destroy_wrap(&tls_ctx);
Radek Krejci9f03b482015-10-22 16:02:10 +0200486 return NULL;
487}
488
489API struct nc_session *
roman68ea7d62024-04-05 12:32:49 +0200490nc_connect_libssl(void *UNUSED(tls), struct ly_ctx *UNUSED(ctx))
Radek Krejci9f03b482015-10-22 16:02:10 +0200491{
roman68ea7d62024-04-05 12:32:49 +0200492 ERR(NULL, "nc_connect_libssl() is deprecated, do not use it.");
493 return NULL;
494}
Radek Krejci9f03b482015-10-22 16:02:10 +0200495
roman68ea7d62024-04-05 12:32:49 +0200496struct nc_session *
497nc_accept_callhome_tls_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout, const char *peername)
498{
499 struct nc_session *session = NULL;
500 void *tls_cfg = NULL;
501 struct nc_tls_ctx tls_ctx = {0};
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100502
503 /* prepare session structure */
Michal Vasko131120a2018-05-29 15:44:02 +0200504 session = nc_new_session(NC_CLIENT, 0);
roman3a95bb22023-10-26 11:07:17 +0200505 NC_CHECK_ERRMEM_RET(!session, NULL);
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100506 session->status = NC_STATUS_STARTING;
roman68ea7d62024-04-05 12:32:49 +0200507
508 /* fill the session */
roman506354a2024-04-11 09:37:22 +0200509 session->ti_type = NC_TI_TLS;
roman68ea7d62024-04-05 12:32:49 +0200510 if (!(session->ti.tls.session = nc_client_tls_session_new(sock, peername, timeout, &tls_ch_opts, &tls_cfg, &tls_ctx))) {
511 goto fail;
512 }
513 session->ti.tls.config = tls_cfg;
roman7731b3a2024-04-23 15:12:32 +0200514
515 /* memory belongs to session */
roman68ea7d62024-04-05 12:32:49 +0200516 memcpy(&session->ti.tls.ctx, &tls_ctx, sizeof tls_ctx);
roman7731b3a2024-04-23 15:12:32 +0200517 memset(&tls_ctx, 0, sizeof tls_ctx);
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100518
Michal Vasko78939072022-12-12 07:43:18 +0100519 if (nc_client_session_new_ctx(session, ctx) != EXIT_SUCCESS) {
Radek Krejcifd5b6682017-06-13 15:52:53 +0200520 goto fail;
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100521 }
Radek Krejcifd5b6682017-06-13 15:52:53 +0200522 ctx = session->ctx;
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100523
524 /* NETCONF handshake */
Michal Vasko131120a2018-05-29 15:44:02 +0200525 if (nc_handshake_io(session) != NC_MSG_HELLO) {
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100526 goto fail;
527 }
Michal Vaskoad611702015-12-03 13:41:51 +0100528 session->status = NC_STATUS_RUNNING;
Michal Vasko11d4cdb2015-10-29 11:42:52 +0100529
Michal Vaskoef578332016-01-25 13:20:09 +0100530 if (nc_ctx_check_and_fill(session) == -1) {
Michal Vasko57eb9402015-12-08 14:38:12 +0100531 goto fail;
Michal Vasko9e2d3a32015-11-10 13:09:18 +0100532 }
533
Michal Vaskoc64c38c2021-07-02 08:43:53 +0200534 session->flags |= NC_SESSION_CALLHOME;
535
roman7731b3a2024-04-23 15:12:32 +0200536 /* store information into session */
Michal Vasko93224072021-11-09 12:14:28 +0100537 session->host = strdup(host);
Michal Vaskoc64c38c2021-07-02 08:43:53 +0200538 session->port = port;
Michal Vasko93224072021-11-09 12:14:28 +0100539 session->username = strdup("certificate-based");
Michal Vaskoc64c38c2021-07-02 08:43:53 +0200540
Michal Vasko80cad7f2015-12-08 14:42:27 +0100541 return session;
roman68ea7d62024-04-05 12:32:49 +0200542
543fail:
roman7731b3a2024-04-23 15:12:32 +0200544 nc_session_free(session, NULL);
545 nc_tls_ctx_destroy_wrap(&tls_ctx);
roman68ea7d62024-04-05 12:32:49 +0200546 return NULL;
Michal Vasko80cad7f2015-12-08 14:42:27 +0100547}