28#include <radcli/radcli.h>
47#include <gnutls/gnutls.h>
48#include <gnutls/dtls.h>
52#define DEFAULT_DTLS_SECRET "radius/dtls"
53#define DEFAULT_TLS_SECRET "radsec"
55typedef struct tls_int_st {
58 struct sockaddr_storage our_sockaddr;
59 gnutls_session_t session;
62 unsigned need_restart;
63 unsigned skip_hostname_check;
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;
77static int restart_session(rc_handle *rh, tls_st *st);
79static int tls_get_fd(
void *ptr,
struct sockaddr *our_sockaddr)
82 return st->ctx.sockfd;
85static int tls_get_active_fd(
void *ptr)
88 return st->ctx.sockfd;
91static ssize_t tls_sendto(
void *ptr,
int sockfd,
92 const void *buf,
size_t len,
93 int flags,
const struct sockaddr *dest_addr,
99 if (st->ctx.need_restart != 0) {
100 if (restart_session(st->rh, st) < 0) {
106 ret = gnutls_record_send(st->ctx.session, buf, len);
107 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
113 rc_log(LOG_ERR,
"%s: error in sending: %s", __func__,
114 gnutls_strerror(ret));
116 st->ctx.need_restart = 1;
120 st->ctx.last_msg = time(0);
124static int tls_lock(
void *ptr)
128 return pthread_mutex_lock(&st->ctx.lock);
131static int tls_unlock(
void *ptr)
135 return pthread_mutex_unlock(&st->ctx.lock);
138static ssize_t tls_recvfrom(
void *ptr,
int sockfd,
139 void *buf,
size_t len,
140 int flags,
struct sockaddr *src_addr,
146 ret = gnutls_record_recv(st->ctx.session, buf, len);
147 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED ||
148 ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED || ret == GNUTLS_E_HEARTBEAT_PONG_RECEIVED) {
153 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) {
154 rc_log(LOG_ERR,
"%s: received alert: %s", __func__,
155 gnutls_alert_get_name(gnutls_alert_get(st->ctx.session)));
173 rc_log(LOG_ERR,
"%s: error in receiving: %s", __func__,
174 gnutls_strerror(ret));
176 st->ctx.need_restart = 1;
180 st->ctx.last_msg = time(0);
187static int cert_verify_callback(gnutls_session_t session)
191 struct tls_int_st *ctx;
195 ctx = gnutls_session_get_ptr(session);
197 return GNUTLS_E_CERTIFICATE_ERROR;
199 if (ctx->skip_hostname_check)
200 ret = gnutls_certificate_verify_peers2(session, &status);
202 ret = gnutls_certificate_verify_peers3(session, ctx->hostname, &status);
204 rc_log(LOG_ERR,
"%s: error in certificate verification: %s",
205 __func__, gnutls_strerror(ret));
206 return GNUTLS_E_CERTIFICATE_ERROR;
211 gnutls_certificate_verification_status_print(status,
212 gnutls_certificate_type_get
216 return GNUTLS_E_CERTIFICATE_ERROR;
218 rc_log(LOG_INFO,
"%s: certificate: %s", __func__, out.data);
219 gnutls_free(out.data);
220 return GNUTLS_E_CERTIFICATE_ERROR;
226static void deinit_session(tls_int_st *ses)
228 if (ses->init != 0) {
234 if (ses->sockfd != -1) {
236 ret = gnutls_bye(ses->session, GNUTLS_SHUT_WR);
237 }
while (ret == GNUTLS_E_INTERRUPTED);
239 gnutls_deinit(ses->session);
241 pthread_mutex_destroy(&ses->lock);
242 if (ses->sockfd != -1)
247static int init_session(rc_handle *rh, tls_int_st *ses,
248 const char *hostname,
unsigned port,
249 struct sockaddr_storage *our_sockaddr,
254 struct addrinfo *info;
257 unsigned cred_set = 0;
258 tls_st *st = rh->so.ptr;
263 pthread_mutex_init(&ses->lock, NULL);
264 sockfd = socket(our_sockaddr->ss_family, (secflags&SEC_FLAG_DTLS)?SOCK_DGRAM:SOCK_STREAM, 0);
267 "%s: cannot open socket", __func__);
272 if (our_sockaddr->ss_family == AF_INET)
273 ((
struct sockaddr_in *)our_sockaddr)->sin_port = 0;
275 ((
struct sockaddr_in6 *)our_sockaddr)->sin6_port = 0;
277 ses->sockfd = sockfd;
281 flags = GNUTLS_CLIENT;
282 if (secflags&SEC_FLAG_DTLS)
283 flags |= GNUTLS_DATAGRAM;
284 ret = gnutls_init(&ses->session, flags);
287 "%s: error in gnutls_init(): %s", __func__, gnutls_strerror(ret));
292 memcpy(&ses->our_sockaddr, our_sockaddr,
sizeof(*our_sockaddr));
293 if (!(secflags&SEC_FLAG_DTLS)) {
295 gnutls_handshake_set_timeout(ses->session, timeout*1000);
297 gnutls_handshake_set_timeout(ses->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
301 gnutls_dtls_set_timeouts(ses->session, 1000, timeout*1000);
304 gnutls_transport_set_int(ses->session, sockfd);
305 gnutls_session_set_ptr(ses->session, ses);
307 gnutls_heartbeat_enable(ses->session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND);
310 if (p && (strcasecmp(p,
"false") == 0 || strcasecmp(p,
"no"))) {
311 ses->skip_hostname_check = 1;
314 if (st && st->psk_cred) {
316 gnutls_credentials_set(ses->session,
317 GNUTLS_CRD_PSK, st->psk_cred);
319 ret = gnutls_priority_set_direct(ses->session,
"NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:-VERS-TLS1.0", NULL);
323 "%s: error in setting PSK priorities: %s",
324 __func__, gnutls_strerror(ret));
330 gnutls_credentials_set(ses->session,
331 GNUTLS_CRD_CERTIFICATE,
335 gnutls_set_default_priority(ses->session);
338 gnutls_server_name_set(ses->session, GNUTLS_NAME_DNS,
339 hostname, strlen(hostname));
342 rc_getaddrinfo(hostname, PW_AI_AUTH);
345 rc_log(LOG_ERR,
"%s: cannot resolve %s", __func__,
351 if (info->ai_addr->sa_family == AF_INET)
352 ((
struct sockaddr_in *)info->ai_addr)->sin_port =
355 ((
struct sockaddr_in6 *)info->ai_addr)->sin6_port =
358 rc_log(LOG_ERR,
"%s: no port specified for server %s",
364 strlcpy(ses->hostname, hostname,
sizeof(ses->hostname));
369 "%s: neither tls-ca-file or a PSK key are configured",
376 ret = connect(sockfd, info->ai_addr, info->ai_addrlen);
381 rc_log(LOG_CRIT,
"%s: cannot connect to %s: %s",
382 __func__, hostname, strerror(e));
387 "%s: performing TLS/DTLS handshake with [%s]:%d",
388 __func__, hostname, port);
390 ret = gnutls_handshake(ses->session);
391 if (ret == GNUTLS_E_LARGE_PACKET)
393 }
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
396 rc_log(LOG_ERR,
"%s: error in handshake: %s",
397 __func__, gnutls_strerror(ret));
411#define TIME_ALIVE 120
413static int restart_session(rc_handle *rh, tls_st *st)
415 struct tls_int_st tmps;
416 time_t now = time(0);
425 if (now - st->ctx.last_restart < TIME_ALIVE && !st->ctx.need_restart)
428 st->ctx.last_restart = now;
430 timeout = rc_conf_int(rh,
"radius_timeout");
433 ret = init_session(rh, &tmps, st->ctx.hostname, st->ctx.port, &st->ctx.our_sockaddr, timeout, st->flags);
435 rc_log(LOG_ERR,
"%s: error in re-initializing TLS session", __func__);
439 if (tmps.sockfd == st->ctx.sockfd)
441 deinit_session(&st->ctx);
442 memcpy(&st->ctx, &tmps,
sizeof(tmps));
443 st->ctx.need_restart = 0;
465 if (st->ctx.init != 0) {
466 return st->ctx.sockfd;
490 time_t now = time(0);
498 if (st->ctx.init != 0) {
499 if (st->ctx.need_restart != 0) {
500 restart_session(rh, st);
501 }
else if (now - st->ctx.last_msg > TIME_ALIVE) {
502 ret = gnutls_heartbeat_ping(st->ctx.session, 64, 4, GNUTLS_HEARTBEAT_WAIT);
504 restart_session(rh, st);
506 st->ctx.last_msg = now;
518void rc_deinit_tls(rc_handle * rh)
520 tls_st *st = rh->so.ptr;
527 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
528 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
532 if (st->ctx.init != 0)
533 deinit_session(&st->ctx);
535 gnutls_certificate_free_credentials(st->x509_cred);
537 gnutls_psk_free_client_credentials(st->psk_cred);
539 if(-1 == rc_reset_netns(&ns_def_hdl))
540 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
554int rc_init_tls(rc_handle * rh,
unsigned flags)
558 struct sockaddr_storage our_sockaddr;
559 const char *ca_file =
rc_conf_str(rh,
"tls-ca-file");
560 const char *cert_file =
rc_conf_str(rh,
"tls-cert-file");
561 const char *key_file =
rc_conf_str(rh,
"tls-key-file");
562 const char *pskkey = NULL;
569 memset(&rh->so, 0,
sizeof(rh->so));
573 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
574 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
579 if (flags & SEC_FLAG_DTLS) {
581 rh->so.static_secret = DEFAULT_DTLS_SECRET;
584 rh->so.static_secret = DEFAULT_TLS_SECRET;
589 st = calloc(1,
sizeof(tls_st));
600 if (ca_file || (key_file && cert_file)) {
601 ret = gnutls_certificate_allocate_credentials(&st->x509_cred);
605 "%s: error in setting X.509 credentials: %s",
606 __func__, gnutls_strerror(ret));
612 gnutls_certificate_set_x509_trust_file(st->x509_cred,
614 GNUTLS_X509_FMT_PEM);
618 "%s: error in setting X.509 trust file: %s: %s",
619 __func__, gnutls_strerror(ret), ca_file);
624 if (cert_file && key_file) {
626 gnutls_certificate_set_x509_key_file(st->x509_cred,
629 GNUTLS_X509_FMT_PEM);
633 "%s: error in setting X.509 cert and key files: %s: %s - %s",
634 __func__, gnutls_strerror(ret), cert_file, key_file);
639 gnutls_certificate_set_verify_function(st->x509_cred,
640 cert_verify_callback);
645 if (authservers == NULL) {
647 "%s: cannot find authserver", __func__);
651 if (authservers->max > 1) {
654 "%s: too many auth servers for TLS/DTLS; only one is allowed",
658 strlcpy(hostname, authservers->name[0],
sizeof(hostname));
659 port = authservers->port[0];
660 if (authservers->secret[0])
661 pskkey = authservers->secret[0];
663 if (pskkey && pskkey[0] != 0) {
666 gnutls_datum_t hexkey;
669 if (strncmp(pskkey,
"psk@", 4) != 0) {
672 "%s: server secret is set but does not start with 'psk@'",
678 if ((p = strchr(pskkey,
'@')) == NULL) {
681 "%s: PSK key is not in 'username@hexkey' format",
686 username_len = p - pskkey;
687 if (username_len + 1 >
sizeof(username)) {
689 "%s: PSK username too big", __func__);
694 strlcpy(username, pskkey, username_len + 1);
697 hexkey.data = (uint8_t*)p;
698 hexkey.size = strlen(p);
700 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
704 "%s: error in setting PSK credentials: %s",
705 __func__, gnutls_strerror(ret));
710 gnutls_psk_set_client_credentials(st->psk_cred,
716 "%s: error in setting PSK key: %s",
717 __func__, gnutls_strerror(ret));
722 ret = init_session(rh, &st->ctx, hostname, port, &our_sockaddr, 0, flags);
728 rh->so.get_fd = tls_get_fd;
729 rh->so.get_active_fd = tls_get_active_fd;
730 rh->so.sendto = tls_sendto;
731 rh->so.recvfrom = tls_recvfrom;
732 rh->so.lock = tls_lock;
733 rh->so.unlock = tls_unlock;
735 if(-1 == rc_reset_netns(&ns_def_hdl)) {
736 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
743 if (st->ctx.init != 0)
744 deinit_session(&st->ctx);
746 gnutls_certificate_free_credentials(st->x509_cred);
748 gnutls_psk_free_client_credentials(st->psk_cred);
753 if(-1 == rc_reset_netns(&ns_def_hdl))
754 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
void rc_own_bind_addr(rc_handle *rh, struct sockaddr_storage *lia)
char * rc_conf_str(rc_handle const *rh, char const *optname)
SERVER * rc_conf_srv(rc_handle const *rh, char const *optname)
@ RC_SOCKET_DTLS
DTLS socket.
@ RC_SOCKET_TLS
TLS socket.
int rc_tls_fd(rc_handle *rh)
int rc_check_tls(rc_handle *rh)