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 if (st->ctx.need_restart != 0) {
83 if (restart_session(st->rh, st) < 0)
86 return st->ctx.sockfd;
89static int tls_get_active_fd(
void *ptr)
92 return st->ctx.sockfd;
95static ssize_t tls_sendto(
void *ptr,
int sockfd,
96 const void *buf,
size_t len,
97 int flags,
const struct sockaddr *dest_addr,
103 if (st->ctx.need_restart != 0) {
104 if (restart_session(st->rh, st) < 0) {
110 ret = gnutls_record_send(st->ctx.session, buf, len);
111 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
117 rc_log(LOG_ERR,
"%s: error in sending: %s", __func__,
118 gnutls_strerror(ret));
120 st->ctx.need_restart = 1;
124 st->ctx.last_msg = time(0);
128static int tls_lock(
void *ptr)
132 return pthread_mutex_lock(&st->ctx.lock);
135static int tls_unlock(
void *ptr)
139 return pthread_mutex_unlock(&st->ctx.lock);
142static ssize_t tls_recvfrom(
void *ptr,
int sockfd,
143 void *buf,
size_t len,
144 int flags,
struct sockaddr *src_addr,
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) {
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)));
177 rc_log(LOG_ERR,
"%s: error in receiving: %s", __func__,
178 gnutls_strerror(ret));
180 st->ctx.need_restart = 1;
184 st->ctx.last_msg = time(0);
191static int cert_verify_callback(gnutls_session_t session)
195 struct tls_int_st *ctx;
199 ctx = gnutls_session_get_ptr(session);
201 return GNUTLS_E_CERTIFICATE_ERROR;
203 if (ctx->skip_hostname_check)
204 ret = gnutls_certificate_verify_peers2(session, &status);
206 ret = gnutls_certificate_verify_peers3(session, ctx->hostname, &status);
208 rc_log(LOG_ERR,
"%s: error in certificate verification: %s",
209 __func__, gnutls_strerror(ret));
210 return GNUTLS_E_CERTIFICATE_ERROR;
215 gnutls_certificate_verification_status_print(status,
216 gnutls_certificate_type_get
220 return GNUTLS_E_CERTIFICATE_ERROR;
222 rc_log(LOG_INFO,
"%s: certificate: %s", __func__, out.data);
223 gnutls_free(out.data);
224 return GNUTLS_E_CERTIFICATE_ERROR;
230static void deinit_session(tls_int_st *ses)
232 if (ses->init != 0) {
238 if (ses->sockfd != -1) {
240 ret = gnutls_bye(ses->session, GNUTLS_SHUT_WR);
241 }
while (ret == GNUTLS_E_INTERRUPTED);
243 gnutls_deinit(ses->session);
245 pthread_mutex_destroy(&ses->lock);
246 if (ses->sockfd != -1)
251static int init_session(rc_handle *rh, tls_int_st *ses,
252 const char *hostname,
unsigned port,
253 struct sockaddr_storage *our_sockaddr,
258 struct addrinfo *info;
261 unsigned cred_set = 0;
262 tls_st *st = rh->so.ptr;
267 pthread_mutex_init(&ses->lock, NULL);
268 sockfd = socket(our_sockaddr->ss_family, (secflags&SEC_FLAG_DTLS)?SOCK_DGRAM:SOCK_STREAM, 0);
271 "%s: cannot open socket", __func__);
276 if (our_sockaddr->ss_family == AF_INET)
277 ((
struct sockaddr_in *)our_sockaddr)->sin_port = 0;
279 ((
struct sockaddr_in6 *)our_sockaddr)->sin6_port = 0;
281 ses->sockfd = sockfd;
285 flags = GNUTLS_CLIENT;
286 if (secflags&SEC_FLAG_DTLS)
287 flags |= GNUTLS_DATAGRAM;
288 ret = gnutls_init(&ses->session, flags);
291 "%s: error in gnutls_init(): %s", __func__, gnutls_strerror(ret));
296 memcpy(&ses->our_sockaddr, our_sockaddr,
sizeof(*our_sockaddr));
297 if (!(secflags&SEC_FLAG_DTLS)) {
299 gnutls_handshake_set_timeout(ses->session, timeout*1000);
301 gnutls_handshake_set_timeout(ses->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
305 gnutls_dtls_set_timeouts(ses->session, 1000, timeout*1000);
308 gnutls_transport_set_int(ses->session, sockfd);
309 gnutls_session_set_ptr(ses->session, ses);
311 gnutls_heartbeat_enable(ses->session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND);
314 if (p && (strcasecmp(p,
"false") == 0 || strcasecmp(p,
"no"))) {
315 ses->skip_hostname_check = 1;
318 if (st && st->psk_cred) {
320 gnutls_credentials_set(ses->session,
321 GNUTLS_CRD_PSK, st->psk_cred);
323 ret = gnutls_priority_set_direct(ses->session,
"NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:-VERS-TLS1.0", NULL);
327 "%s: error in setting PSK priorities: %s",
328 __func__, gnutls_strerror(ret));
334 gnutls_credentials_set(ses->session,
335 GNUTLS_CRD_CERTIFICATE,
339 gnutls_set_default_priority(ses->session);
342 gnutls_server_name_set(ses->session, GNUTLS_NAME_DNS,
343 hostname, strlen(hostname));
346 rc_getaddrinfo(hostname, PW_AI_AUTH);
349 rc_log(LOG_ERR,
"%s: cannot resolve %s", __func__,
355 if (info->ai_addr->sa_family == AF_INET)
356 ((
struct sockaddr_in *)info->ai_addr)->sin_port =
359 ((
struct sockaddr_in6 *)info->ai_addr)->sin6_port =
362 rc_log(LOG_ERR,
"%s: no port specified for server %s",
368 strlcpy(ses->hostname, hostname,
sizeof(ses->hostname));
373 "%s: neither tls-ca-file or a PSK key are configured",
380 ret = connect(sockfd, info->ai_addr, info->ai_addrlen);
385 rc_log(LOG_CRIT,
"%s: cannot connect to %s: %s",
386 __func__, hostname, strerror(e));
391 "%s: performing TLS/DTLS handshake with [%s]:%d",
392 __func__, hostname, port);
394 ret = gnutls_handshake(ses->session);
395 if (ret == GNUTLS_E_LARGE_PACKET)
397 }
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
400 rc_log(LOG_ERR,
"%s: error in handshake: %s",
401 __func__, gnutls_strerror(ret));
415#define TIME_ALIVE 120
417static int restart_session(rc_handle *rh, tls_st *st)
419 struct tls_int_st tmps;
420 time_t now = time(0);
429 if (now - st->ctx.last_restart < TIME_ALIVE && !st->ctx.need_restart)
432 st->ctx.last_restart = now;
434 timeout = rc_conf_int(rh,
"radius_timeout");
437 ret = init_session(rh, &tmps, st->ctx.hostname, st->ctx.port, &st->ctx.our_sockaddr, timeout, st->flags);
439 rc_log(LOG_ERR,
"%s: error in re-initializing TLS session", __func__);
443 if (tmps.sockfd == st->ctx.sockfd)
445 deinit_session(&st->ctx);
446 memcpy(&st->ctx, &tmps,
sizeof(tmps));
447 st->ctx.need_restart = 0;
469 if (st->ctx.init != 0) {
470 return st->ctx.sockfd;
496 time_t now = time(0);
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);
510 restart_session(rh, st);
512 st->ctx.last_msg = now;
524void rc_deinit_tls(rc_handle * rh)
526 tls_st *st = rh->so.ptr;
533 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
534 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
538 if (st->ctx.init != 0)
539 deinit_session(&st->ctx);
541 gnutls_certificate_free_credentials(st->x509_cred);
543 gnutls_psk_free_client_credentials(st->psk_cred);
545 if(-1 == rc_reset_netns(&ns_def_hdl))
546 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
560int rc_init_tls(rc_handle * rh,
unsigned flags)
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;
575 memset(&rh->so, 0,
sizeof(rh->so));
579 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
580 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
585 if (flags & SEC_FLAG_DTLS) {
587 rh->so.static_secret = DEFAULT_DTLS_SECRET;
590 rh->so.static_secret = DEFAULT_TLS_SECRET;
595 st = calloc(1,
sizeof(tls_st));
606 if (ca_file || (key_file && cert_file)) {
607 ret = gnutls_certificate_allocate_credentials(&st->x509_cred);
611 "%s: error in setting X.509 credentials: %s",
612 __func__, gnutls_strerror(ret));
618 gnutls_certificate_set_x509_trust_file(st->x509_cred,
620 GNUTLS_X509_FMT_PEM);
624 "%s: error in setting X.509 trust file: %s: %s",
625 __func__, gnutls_strerror(ret), ca_file);
630 if (cert_file && key_file) {
632 gnutls_certificate_set_x509_key_file(st->x509_cred,
635 GNUTLS_X509_FMT_PEM);
639 "%s: error in setting X.509 cert and key files: %s: %s - %s",
640 __func__, gnutls_strerror(ret), cert_file, key_file);
645 gnutls_certificate_set_verify_function(st->x509_cred,
646 cert_verify_callback);
651 if (authservers == NULL) {
653 "%s: cannot find authserver", __func__);
657 if (authservers->max > 1) {
660 "%s: too many auth servers for TLS/DTLS; only one is allowed",
664 strlcpy(hostname, authservers->name[0],
sizeof(hostname));
665 port = authservers->port[0];
666 if (authservers->secret[0])
667 pskkey = authservers->secret[0];
669 if (pskkey && pskkey[0] != 0) {
672 gnutls_datum_t hexkey;
675 if (strncmp(pskkey,
"psk@", 4) != 0) {
678 "%s: server secret is set but does not start with 'psk@'",
684 if ((p = strchr(pskkey,
'@')) == NULL) {
687 "%s: PSK key is not in 'username@hexkey' format",
692 username_len = p - pskkey;
693 if (username_len + 1 >
sizeof(username)) {
695 "%s: PSK username too big", __func__);
700 strlcpy(username, pskkey, username_len + 1);
703 hexkey.data = (uint8_t*)p;
704 hexkey.size = strlen(p);
706 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
710 "%s: error in setting PSK credentials: %s",
711 __func__, gnutls_strerror(ret));
716 gnutls_psk_set_client_credentials(st->psk_cred,
722 "%s: error in setting PSK key: %s",
723 __func__, gnutls_strerror(ret));
731 strlcpy(st->ctx.hostname, hostname,
sizeof(st->ctx.hostname));
733 memcpy(&st->ctx.our_sockaddr, &our_sockaddr,
sizeof(our_sockaddr));
734 st->ctx.need_restart = 1;
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;
743 if(-1 == rc_reset_netns(&ns_def_hdl)) {
744 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
752 if (st->ctx.init != 0)
753 deinit_session(&st->ctx);
755 gnutls_certificate_free_credentials(st->x509_cred);
757 gnutls_psk_free_client_credentials(st->psk_cred);
762 if(-1 == rc_reset_netns(&ns_def_hdl))
763 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)