Radcli library 1.5.2
A simple radius library
Loading...
Searching...
No Matches
tls.c
1/*
2 * Copyright (c) 2014-2026, Nikos Mavrogiannopoulos. All rights reserved.
3 * Copyright (c) 2015, Red Hat, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <config.h>
27#include <includes.h>
28#include <radcli/radcli.h>
29#include "util.h"
30#include "tls.h"
31
32#ifdef HAVE_GNUTLS
33
46
47#include <gnutls/gnutls.h>
48#include <gnutls/dtls.h>
49#include <pthread.h>
50#include <time.h>
51
52#define DEFAULT_DTLS_SECRET "radius/dtls"
53#define DEFAULT_TLS_SECRET "radsec"
54
55typedef struct tls_int_st {
56 char hostname[256]; /* server's hostname */
57 unsigned port; /* server's port */
58 struct sockaddr_storage our_sockaddr;
59 gnutls_session_t session;
60 int sockfd;
61 unsigned init;
62 unsigned need_restart;
63 unsigned skip_hostname_check; /* whether to verify hostname */
64 pthread_mutex_t lock;
65 time_t last_msg;
66 time_t last_restart;
67} tls_int_st;
68
69typedef struct tls_st {
70 gnutls_psk_client_credentials_t psk_cred;
71 gnutls_certificate_credentials_t x509_cred;
72 struct tls_int_st ctx; /* one for ACCT and another for AUTH */
73 unsigned flags; /* the flags set on init */
74 rc_handle *rh; /* a pointer to our owner */
75} tls_st;
76
77static int restart_session(rc_handle *rh, tls_st *st);
78
79static int tls_get_fd(void *ptr, struct sockaddr *our_sockaddr)
80{
81 tls_st *st = ptr;
82 if (st->ctx.need_restart != 0) {
83 if (restart_session(st->rh, st) < 0)
84 return -1;
85 }
86 return st->ctx.sockfd;
87}
88
89static int tls_get_active_fd(void *ptr)
90{
91 tls_st *st = ptr;
92 return st->ctx.sockfd;
93}
94
95static ssize_t tls_sendto(void *ptr, int sockfd,
96 const void *buf, size_t len,
97 int flags, const struct sockaddr *dest_addr,
98 socklen_t addrlen)
99{
100 tls_st *st = ptr;
101 int ret;
102
103 if (st->ctx.need_restart != 0) {
104 if (restart_session(st->rh, st) < 0) {
105 errno = EIO;
106 return -1;
107 }
108 }
109
110 ret = gnutls_record_send(st->ctx.session, buf, len);
111 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
112 errno = EINTR;
113 return -1;
114 }
115
116 if (ret < 0) {
117 rc_log(LOG_ERR, "%s: error in sending: %s", __func__,
118 gnutls_strerror(ret));
119 errno = EIO;
120 st->ctx.need_restart = 1;
121 return -1;
122 }
123
124 st->ctx.last_msg = time(0);
125 return ret;
126}
127
128static int tls_lock(void *ptr)
129{
130 tls_st *st = ptr;
131
132 return pthread_mutex_lock(&st->ctx.lock);
133}
134
135static int tls_unlock(void *ptr)
136{
137 tls_st *st = ptr;
138
139 return pthread_mutex_unlock(&st->ctx.lock);
140}
141
142static ssize_t tls_recvfrom(void *ptr, int sockfd,
143 void *buf, size_t len,
144 int flags, struct sockaddr *src_addr,
145 socklen_t * addrlen)
146{
147 tls_st *st = ptr;
148 int ret;
149
150 ret = gnutls_record_recv(st->ctx.session, buf, len);
151 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED ||
152 ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED || ret == GNUTLS_E_HEARTBEAT_PONG_RECEIVED) {
153 errno = EINTR;
154 return -1;
155 }
156
157 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) {
158 rc_log(LOG_ERR, "%s: received alert: %s", __func__,
159 gnutls_alert_get_name(gnutls_alert_get(st->ctx.session)));
160 errno = EINTR;
161 return -1;
162 }
163
164 /* RFC6614 says: "After the TLS session is established, RADIUS packet payloads are
165 * exchanged over the encrypted TLS tunnel. In RADIUS/UDP, the
166 * packet size can be determined by evaluating the size of the
167 * datagram that arrived. Due to the stream nature of TCP and TLS,
168 * this does not hold true for RADIUS/TLS packet exchange.",
169 *
170 * That is correct in principle but it fails to associate the length with
171 * the TLS record boundaries. Here, when in TLS, we assume that a single TLS
172 * record holds a single radius packet. It wouldn't make sense anyway to send
173 * multiple TLS records for a single packet.
174 */
175
176 if (ret <= 0) {
177 rc_log(LOG_ERR, "%s: error in receiving: %s", __func__,
178 gnutls_strerror(ret));
179 errno = EIO;
180 st->ctx.need_restart = 1;
181 return -1;
182 }
183
184 st->ctx.last_msg = time(0);
185 return ret;
186}
187
188/* This function will verify the peer's certificate, and check
189 * if the hostname matches.
190 */
191static int cert_verify_callback(gnutls_session_t session)
192{
193 unsigned int status;
194 int ret;
195 struct tls_int_st *ctx;
196 gnutls_datum_t out;
197
198 /* read hostname */
199 ctx = gnutls_session_get_ptr(session);
200 if (ctx == NULL)
201 return GNUTLS_E_CERTIFICATE_ERROR;
202
203 if (ctx->skip_hostname_check)
204 ret = gnutls_certificate_verify_peers2(session, &status);
205 else
206 ret = gnutls_certificate_verify_peers3(session, ctx->hostname, &status);
207 if (ret < 0) {
208 rc_log(LOG_ERR, "%s: error in certificate verification: %s",
209 __func__, gnutls_strerror(ret));
210 return GNUTLS_E_CERTIFICATE_ERROR;
211 }
212
213 if (status != 0) {
214 ret =
215 gnutls_certificate_verification_status_print(status,
216 gnutls_certificate_type_get
217 (session),
218 &out, 0);
219 if (ret < 0) {
220 return GNUTLS_E_CERTIFICATE_ERROR;
221 }
222 rc_log(LOG_INFO, "%s: certificate: %s", __func__, out.data);
223 gnutls_free(out.data);
224 return GNUTLS_E_CERTIFICATE_ERROR;
225 }
226
227 return 0;
228}
229
230static void deinit_session(tls_int_st *ses)
231{
232 if (ses->init != 0) {
233 int ret;
234 ses->init = 0;
235 if (ses->session) {
236 /* Send close_notify before closing the socket so the peer
237 * receives a proper TLS/DTLS shutdown alert. */
238 if (ses->sockfd != -1) {
239 do {
240 ret = gnutls_bye(ses->session, GNUTLS_SHUT_WR);
241 } while (ret == GNUTLS_E_INTERRUPTED);
242 }
243 gnutls_deinit(ses->session);
244 }
245 pthread_mutex_destroy(&ses->lock);
246 if (ses->sockfd != -1)
247 close(ses->sockfd);
248 }
249}
250
251static int init_session(rc_handle *rh, tls_int_st *ses,
252 const char *hostname, unsigned port,
253 struct sockaddr_storage *our_sockaddr,
254 int timeout,
255 unsigned secflags)
256{
257 int sockfd, ret, e;
258 struct addrinfo *info;
259 char *p;
260 unsigned flags = 0;
261 unsigned cred_set = 0;
262 tls_st *st = rh->so.ptr;
263
264 ses->sockfd = -1;
265 ses->init = 1;
266
267 pthread_mutex_init(&ses->lock, NULL);
268 sockfd = socket(our_sockaddr->ss_family, (secflags&SEC_FLAG_DTLS)?SOCK_DGRAM:SOCK_STREAM, 0);
269 if (sockfd < 0) {
270 rc_log(LOG_ERR,
271 "%s: cannot open socket", __func__);
272 ret = -1;
273 goto cleanup;
274 }
275
276 if (our_sockaddr->ss_family == AF_INET)
277 ((struct sockaddr_in *)our_sockaddr)->sin_port = 0;
278 else
279 ((struct sockaddr_in6 *)our_sockaddr)->sin6_port = 0;
280
281 ses->sockfd = sockfd;
282
283 /* Initialize DTLS */
284
285 flags = GNUTLS_CLIENT;
286 if (secflags&SEC_FLAG_DTLS)
287 flags |= GNUTLS_DATAGRAM;
288 ret = gnutls_init(&ses->session, flags);
289 if (ret < 0) {
290 rc_log(LOG_ERR,
291 "%s: error in gnutls_init(): %s", __func__, gnutls_strerror(ret));
292 ret = -1;
293 goto cleanup;
294 }
295
296 memcpy(&ses->our_sockaddr, our_sockaddr, sizeof(*our_sockaddr));
297 if (!(secflags&SEC_FLAG_DTLS)) {
298 if (timeout > 0) {
299 gnutls_handshake_set_timeout(ses->session, timeout*1000);
300 } else {
301 gnutls_handshake_set_timeout(ses->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
302 }
303 } else { /* DTLS */
304 if (timeout > 0)
305 gnutls_dtls_set_timeouts(ses->session, 1000, timeout*1000);
306 }
307
308 gnutls_transport_set_int(ses->session, sockfd);
309 gnutls_session_set_ptr(ses->session, ses);
310 /* we only initiate heartbeat messages */
311 gnutls_heartbeat_enable(ses->session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND);
312
313 p = rc_conf_str(rh, "tls-verify-hostname");
314 if (p && (strcasecmp(p, "false") == 0 || strcasecmp(p, "no"))) {
315 ses->skip_hostname_check = 1;
316 }
317
318 if (st && st->psk_cred) {
319 cred_set = 1;
320 gnutls_credentials_set(ses->session,
321 GNUTLS_CRD_PSK, st->psk_cred);
322
323 ret = gnutls_priority_set_direct(ses->session, "NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:-VERS-TLS1.0", NULL);
324 if (ret < 0) {
325 ret = -1;
326 rc_log(LOG_ERR,
327 "%s: error in setting PSK priorities: %s",
328 __func__, gnutls_strerror(ret));
329 goto cleanup;
330 }
331 } else if (st) {
332 cred_set = 1;
333 if (st->x509_cred) {
334 gnutls_credentials_set(ses->session,
335 GNUTLS_CRD_CERTIFICATE,
336 st->x509_cred);
337 }
338
339 gnutls_set_default_priority(ses->session);
340 }
341
342 gnutls_server_name_set(ses->session, GNUTLS_NAME_DNS,
343 hostname, strlen(hostname));
344
345 info =
346 rc_getaddrinfo(hostname, PW_AI_AUTH);
347 if (info == NULL) {
348 ret = -1;
349 rc_log(LOG_ERR, "%s: cannot resolve %s", __func__,
350 hostname);
351 goto cleanup;
352 }
353
354 if (port != 0) {
355 if (info->ai_addr->sa_family == AF_INET)
356 ((struct sockaddr_in *)info->ai_addr)->sin_port =
357 htons(port);
358 else
359 ((struct sockaddr_in6 *)info->ai_addr)->sin6_port =
360 htons(port);
361 } else {
362 rc_log(LOG_ERR, "%s: no port specified for server %s",
363 __func__, hostname);
364 ret = -1;
365 goto cleanup;
366 }
367
368 strlcpy(ses->hostname, hostname, sizeof(ses->hostname));
369 ses->port = port;
370
371 if (cred_set == 0) {
372 rc_log(LOG_CRIT,
373 "%s: neither tls-ca-file or a PSK key are configured",
374 __func__);
375 ret = -1;
376 goto cleanup;
377 }
378
379 /* we connect since we are talking to a single server */
380 ret = connect(sockfd, info->ai_addr, info->ai_addrlen);
381 freeaddrinfo(info);
382 if (ret == -1) {
383 e = errno;
384 ret = -1;
385 rc_log(LOG_CRIT, "%s: cannot connect to %s: %s",
386 __func__, hostname, strerror(e));
387 goto cleanup;
388 }
389
390 rc_log(LOG_DEBUG,
391 "%s: performing TLS/DTLS handshake with [%s]:%d",
392 __func__, hostname, port);
393 do {
394 ret = gnutls_handshake(ses->session);
395 if (ret == GNUTLS_E_LARGE_PACKET)
396 break;
397 } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
398
399 if (ret < 0) {
400 rc_log(LOG_ERR, "%s: error in handshake: %s",
401 __func__, gnutls_strerror(ret));
402 ret = -1;
403 goto cleanup;
404 }
405
406 return 0;
407 cleanup:
408 deinit_session(ses);
409 return ret;
410
411}
412
413/* The time after the last message was received, that
414 * we will try heartbeats */
415#define TIME_ALIVE 120
416
417static int restart_session(rc_handle *rh, tls_st *st)
418{
419 struct tls_int_st tmps;
420 time_t now = time(0);
421 int ret;
422 int timeout;
423
424 /* Bypass the time guard when need_restart is set: the session is
425 * known to be broken (a send or recv already failed), so we must
426 * attempt reconnection regardless of how recently we last tried.
427 * When need_restart is 0 (proactive check from rc_check_tls via a
428 * failed heartbeat), keep the guard to avoid rapid reconnect loops. */
429 if (now - st->ctx.last_restart < TIME_ALIVE && !st->ctx.need_restart)
430 return -1;
431
432 st->ctx.last_restart = now;
433
434 timeout = rc_conf_int(rh, "radius_timeout");
435
436 /* reinitialize this session */
437 ret = init_session(rh, &tmps, st->ctx.hostname, st->ctx.port, &st->ctx.our_sockaddr, timeout, st->flags);
438 if (ret < 0) {
439 rc_log(LOG_ERR, "%s: error in re-initializing TLS session", __func__);
440 return -1;
441 }
442
443 if (tmps.sockfd == st->ctx.sockfd)
444 st->ctx.sockfd = -1;
445 deinit_session(&st->ctx);
446 memcpy(&st->ctx, &tmps, sizeof(tmps));
447 st->ctx.need_restart = 0;
448
449 return 0;
450}
451
460int rc_tls_fd(rc_handle * rh)
461{
462 tls_st *st;
463
464 if (rh->so_type != RC_SOCKET_TLS && rh->so_type != RC_SOCKET_DTLS)
465 return -1;
466
467 st = rh->so.ptr;
468
469 if (st->ctx.init != 0) {
470 return st->ctx.sockfd;
471 }
472 return -1;
473}
474
493int rc_check_tls(rc_handle * rh)
494{
495 tls_st *st;
496 time_t now = time(0);
497 int ret;
498
499 if (rh->so_type != RC_SOCKET_TLS && rh->so_type != RC_SOCKET_DTLS)
500 return 0;
501
502 st = rh->so.ptr;
503
504 if (st->ctx.init != 0) {
505 if (st->ctx.need_restart != 0) {
506 restart_session(rh, st);
507 } else if (now - st->ctx.last_msg > TIME_ALIVE) {
508 ret = gnutls_heartbeat_ping(st->ctx.session, 64, 4, GNUTLS_HEARTBEAT_WAIT);
509 if (ret < 0) {
510 restart_session(rh, st);
511 }
512 st->ctx.last_msg = now;
513 }
514 }
515 return 0;
516}
517
519
520/*- This function will deinitialize a previously initialed DTLS or TLS session.
521 *
522 * @param rh the configuration handle.
523 -*/
524void rc_deinit_tls(rc_handle * rh)
525{
526 tls_st *st = rh->so.ptr;
527 char *ns = NULL;
528 int ns_def_hdl = 0;
529
530 if (st) {
531 ns = rc_conf_str(rh, "namespace"); /* Check for namespace config */
532 if (ns != NULL) {
533 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
534 rc_log(LOG_ERR, "rc_send_server: namespace %s set failed", ns);
535 return;
536 }
537 }
538 if (st->ctx.init != 0)
539 deinit_session(&st->ctx);
540 if (st->x509_cred)
541 gnutls_certificate_free_credentials(st->x509_cred);
542 if (st->psk_cred)
543 gnutls_psk_free_client_credentials(st->psk_cred);
544 if (ns != NULL) {
545 if(-1 == rc_reset_netns(&ns_def_hdl))
546 rc_log(LOG_ERR, "rc_send_server: namespace %s reset failed", ns);
547 }
548 }
549 free(st);
550}
551
552/*- Initialize a configuration for TLS or DTLS
553 *
554 * This function will initialize the handle for TLS or DTLS.
555 *
556 * @param rh a handle to parsed configuration
557 * @param flags must be zero or SEC_FLAG_DTLS
558 * @return 0 on success, -1 on failure.
559 -*/
560int rc_init_tls(rc_handle * rh, unsigned flags)
561{
562 int ret;
563 tls_st *st = NULL;
564 struct sockaddr_storage our_sockaddr;
565 const char *ca_file = rc_conf_str(rh, "tls-ca-file");
566 const char *cert_file = rc_conf_str(rh, "tls-cert-file");
567 const char *key_file = rc_conf_str(rh, "tls-key-file");
568 const char *pskkey = NULL;
569 SERVER *authservers;
570 char hostname[256]; /* server's hostname */
571 unsigned port; /* server's port */
572 char *ns = NULL;
573 int ns_def_hdl = 0;
574
575 memset(&rh->so, 0, sizeof(rh->so));
576
577 ns = rc_conf_str(rh, "namespace"); /* Check for namespace config */
578 if (ns != NULL) {
579 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
580 rc_log(LOG_ERR, "rc_send_server: namespace %s set failed", ns);
581 return -1;
582 }
583 }
584
585 if (flags & SEC_FLAG_DTLS) {
586 rh->so_type = RC_SOCKET_DTLS;
587 rh->so.static_secret = DEFAULT_DTLS_SECRET;
588 } else {
589 rh->so_type = RC_SOCKET_TLS;
590 rh->so.static_secret = DEFAULT_TLS_SECRET;
591 }
592
593 rc_own_bind_addr(rh, &our_sockaddr);
594
595 st = calloc(1, sizeof(tls_st));
596 if (st == NULL) {
597 ret = -1;
598 goto cleanup;
599 }
600
601 st->rh = rh;
602 st->flags = flags;
603
604 rh->so.ptr = st;
605
606 if (ca_file || (key_file && cert_file)) {
607 ret = gnutls_certificate_allocate_credentials(&st->x509_cred);
608 if (ret < 0) {
609 ret = -1;
610 rc_log(LOG_ERR,
611 "%s: error in setting X.509 credentials: %s",
612 __func__, gnutls_strerror(ret));
613 goto cleanup;
614 }
615
616 if (ca_file) {
617 ret =
618 gnutls_certificate_set_x509_trust_file(st->x509_cred,
619 ca_file,
620 GNUTLS_X509_FMT_PEM);
621 if (ret < 0) {
622 ret = -1;
623 rc_log(LOG_ERR,
624 "%s: error in setting X.509 trust file: %s: %s",
625 __func__, gnutls_strerror(ret), ca_file);
626 goto cleanup;
627 }
628 }
629
630 if (cert_file && key_file) {
631 ret =
632 gnutls_certificate_set_x509_key_file(st->x509_cred,
633 cert_file,
634 key_file,
635 GNUTLS_X509_FMT_PEM);
636 if (ret < 0) {
637 ret = -1;
638 rc_log(LOG_ERR,
639 "%s: error in setting X.509 cert and key files: %s: %s - %s",
640 __func__, gnutls_strerror(ret), cert_file, key_file);
641 goto cleanup;
642 }
643 }
644
645 gnutls_certificate_set_verify_function(st->x509_cred,
646 cert_verify_callback);
647 }
648
649 /* Read the PSK key if any */
650 authservers = rc_conf_srv(rh, "authserver");
651 if (authservers == NULL) {
652 rc_log(LOG_ERR,
653 "%s: cannot find authserver", __func__);
654 ret = -1;
655 goto cleanup;
656 }
657 if (authservers->max > 1) {
658 ret = -1;
659 rc_log(LOG_ERR,
660 "%s: too many auth servers for TLS/DTLS; only one is allowed",
661 __func__);
662 goto cleanup;
663 }
664 strlcpy(hostname, authservers->name[0], sizeof(hostname));
665 port = authservers->port[0];
666 if (authservers->secret[0])
667 pskkey = authservers->secret[0];
668
669 if (pskkey && pskkey[0] != 0) {
670 char *p;
671 char username[64];
672 gnutls_datum_t hexkey;
673 int username_len;
674
675 if (strncmp(pskkey, "psk@", 4) != 0) {
676 ret = -1;
677 rc_log(LOG_ERR,
678 "%s: server secret is set but does not start with 'psk@'",
679 __func__);
680 goto cleanup;
681 }
682 pskkey+=4;
683
684 if ((p = strchr(pskkey, '@')) == NULL) {
685 ret = -1;
686 rc_log(LOG_ERR,
687 "%s: PSK key is not in 'username@hexkey' format",
688 __func__);
689 goto cleanup;
690 }
691
692 username_len = p - pskkey;
693 if (username_len + 1 > sizeof(username)) {
694 rc_log(LOG_ERR,
695 "%s: PSK username too big", __func__);
696 ret = -1;
697 goto cleanup;
698 }
699
700 strlcpy(username, pskkey, username_len + 1);
701
702 p++;
703 hexkey.data = (uint8_t*)p;
704 hexkey.size = strlen(p);
705
706 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
707 if (ret < 0) {
708 ret = -1;
709 rc_log(LOG_ERR,
710 "%s: error in setting PSK credentials: %s",
711 __func__, gnutls_strerror(ret));
712 goto cleanup;
713 }
714
715 ret =
716 gnutls_psk_set_client_credentials(st->psk_cred,
717 username, &hexkey,
718 GNUTLS_PSK_KEY_HEX);
719 if (ret < 0) {
720 ret = -1;
721 rc_log(LOG_ERR,
722 "%s: error in setting PSK key: %s",
723 __func__, gnutls_strerror(ret));
724 goto cleanup;
725 }
726 }
727
728 /* Defer TCP connect + TLS handshake to first use.
729 * tls_sendto() checks need_restart != 0 and calls restart_session(),
730 * which calls init_session() with these stored parameters. */
731 strlcpy(st->ctx.hostname, hostname, sizeof(st->ctx.hostname));
732 st->ctx.port = port;
733 memcpy(&st->ctx.our_sockaddr, &our_sockaddr, sizeof(our_sockaddr));
734 st->ctx.need_restart = 1;
735
736 rh->so.get_fd = tls_get_fd;
737 rh->so.get_active_fd = tls_get_active_fd;
738 rh->so.sendto = tls_sendto;
739 rh->so.recvfrom = tls_recvfrom;
740 rh->so.lock = tls_lock;
741 rh->so.unlock = tls_unlock;
742 if (ns != NULL) {
743 if(-1 == rc_reset_netns(&ns_def_hdl)) {
744 rc_log(LOG_ERR, "rc_send_server: namespace %s reset failed", ns);
745 ret = -1;
746 goto cleanup;
747 }
748 }
749 return 0;
750 cleanup:
751 if (st) {
752 if (st->ctx.init != 0)
753 deinit_session(&st->ctx);
754 if (st->x509_cred)
755 gnutls_certificate_free_credentials(st->x509_cred);
756 if (st->psk_cred)
757 gnutls_psk_free_client_credentials(st->psk_cred);
758 }
759 free(st);
760 rh->so.ptr = NULL;
761 if (ns != NULL) {
762 if(-1 == rc_reset_netns(&ns_def_hdl))
763 rc_log(LOG_ERR, "rc_send_server: namespace %s reset failed", ns);
764 }
765 return ret;
766}
767
768#endif
769
void rc_own_bind_addr(rc_handle *rh, struct sockaddr_storage *lia)
Definition ip_util.c:164
char * rc_conf_str(rc_handle const *rh, char const *optname)
Definition config.c:765
SERVER * rc_conf_srv(rc_handle const *rh, char const *optname)
Definition config.c:815
@ RC_SOCKET_DTLS
DTLS socket.
Definition radcli.h:104
@ RC_SOCKET_TLS
TLS socket.
Definition radcli.h:103
int rc_tls_fd(rc_handle *rh)
Definition tls.c:460
int rc_check_tls(rc_handle *rh)
Definition tls.c:493