28#include <radcli/radcli.h>
29#include <radcli/radcli2.h>
50#include <gnutls/gnutls.h>
51#include <gnutls/dtls.h>
56#define DEFAULT_DTLS_SECRET "radius/dtls"
57#define DEFAULT_TLS_SECRET "radsec"
59typedef struct tls_int_st {
62 struct sockaddr_storage our_sockaddr;
63 gnutls_session_t session;
66 unsigned handshake_done;
70 unsigned need_restart;
71 unsigned skip_hostname_check;
77typedef struct tls_st {
78 gnutls_psk_client_credentials_t psk_cred;
79 gnutls_certificate_credentials_t x509_cred;
80 struct tls_int_st ctx;
87static int restart_session(rc_handle *rh, tls_st *st);
96static int tls_get_fd(
void *ptr,
struct sockaddr *our_sockaddr)
99 if (st->ctx.need_restart != 0) {
100 if (restart_session(st->rh, st) < 0)
103 return st->ctx.sockfd;
112static int tls_get_active_fd(
void *ptr)
115 return st->ctx.sockfd;
134static int tls_wait_or_give_up(tls_st *st,
short events,
const char *what)
136 double start_time = rc_getmtime();
137 int timeout = rc_conf_int_id(st->rh, OPT_RADIUS_TIMEOUT);
142 for (; timeout > 0; timeout -= (int)(rc_getmtime() - start_time)) {
143 struct pollfd pfd = { st->ctx.sockfd, events, 0 };
144 int ret = poll(&pfd, 1, timeout * 1000);
150 if (errno != EINTR) {
151 rc_log(LOG_ERR,
"%s: poll: %s", __func__, strerror(errno));
157 rc_log(LOG_ERR,
"%s: timeout waiting to %s TLS data", __func__, what);
160 st->ctx.need_restart = 1;
177static ssize_t tls_sendto(
void *ptr,
int sockfd,
178 const void *buf,
size_t len,
179 int flags,
const struct sockaddr *dest_addr,
185 if (st->ctx.need_restart != 0) {
186 if (restart_session(st->rh, st) < 0) {
193 ret = gnutls_record_send(st->ctx.session, buf, len);
194 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
195 if (tls_wait_or_give_up(st, POLLOUT,
"send") < 0)
201 rc_log(LOG_ERR,
"%s: error in sending: %s", __func__,
202 gnutls_strerror(ret));
204 st->ctx.need_restart = 1;
211 st->ctx.last_msg = time(0);
220static int tls_lock(
void *ptr)
224 return pthread_mutex_lock(&st->ctx.lock);
232static int tls_unlock(
void *ptr)
236 return pthread_mutex_unlock(&st->ctx.lock);
256static ssize_t tls_recvfrom(
void *ptr,
int sockfd,
257 void *buf,
size_t len,
258 int flags,
struct sockaddr *src_addr,
265 ret = gnutls_record_recv(st->ctx.session, buf, len);
266 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
267 if (tls_wait_or_give_up(st, POLLIN,
"receive") < 0)
281 (((
const uint8_t *)buf)[0] == RADCLI_DISCONNECT_REQUEST ||
282 ((
const uint8_t *)buf)[0] == RADCLI_COA_REQUEST)) {
283 radcli2_priv_dae_on_radsec_packet(st->rh, buf, (
size_t)ret);
289 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) {
290 rc_log(LOG_ERR,
"%s: received alert: %s", __func__,
291 gnutls_alert_get_name(gnutls_alert_get(st->ctx.session)));
309 rc_log(LOG_ERR,
"%s: error in receiving: %s", __func__,
310 gnutls_strerror(ret));
312 st->ctx.need_restart = 1;
316 st->ctx.last_msg = time(0);
317 st->ctx.last_recv = st->ctx.last_msg;
330static int cert_verify_callback(gnutls_session_t session)
334 struct tls_int_st *ctx;
338 ctx = gnutls_session_get_ptr(session);
340 return GNUTLS_E_CERTIFICATE_ERROR;
342 if (ctx->skip_hostname_check)
343 ret = gnutls_certificate_verify_peers2(session, &status);
345 ret = gnutls_certificate_verify_peers3(session, ctx->hostname, &status);
347 rc_log(LOG_ERR,
"%s: error in certificate verification: %s",
348 __func__, gnutls_strerror(ret));
349 return GNUTLS_E_CERTIFICATE_ERROR;
354 gnutls_certificate_verification_status_print(status,
355 gnutls_certificate_type_get
359 return GNUTLS_E_CERTIFICATE_ERROR;
361 rc_log(LOG_INFO,
"%s: certificate: %s", __func__, out.data);
362 gnutls_free(out.data);
363 return GNUTLS_E_CERTIFICATE_ERROR;
375static void deinit_session(tls_int_st *ses)
377 if (ses->init != 0) {
387 if (ses->sockfd != -1 && ses->handshake_done) {
389 ret = gnutls_bye(ses->session, GNUTLS_SHUT_WR);
390 }
while (ret == GNUTLS_E_INTERRUPTED);
392 gnutls_deinit(ses->session);
394 pthread_mutex_destroy(&ses->lock);
395 if (ses->sockfd != -1)
415static int init_session(rc_handle *rh, tls_int_st *ses,
416 const char *hostname,
unsigned port,
417 struct sockaddr_storage *our_sockaddr,
421 int sockfd, ret, e, sock_flags;
422 struct addrinfo *info;
425 unsigned cred_set = 0;
426 tls_st *st = rh->so.ptr;
430 ses->handshake_done = 0;
445 pthread_mutexattr_t attr;
447 pthread_mutexattr_init(&attr);
448 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
449 pthread_mutex_init(&ses->lock, &attr);
450 pthread_mutexattr_destroy(&attr);
452 sockfd = socket(our_sockaddr->ss_family, (secflags&SEC_FLAG_DTLS)?SOCK_DGRAM:SOCK_STREAM, 0);
455 "%s: cannot open socket", __func__);
460 if (our_sockaddr->ss_family == AF_INET)
461 ((
struct sockaddr_in *)our_sockaddr)->sin_port = 0;
463 ((
struct sockaddr_in6 *)our_sockaddr)->sin6_port = 0;
465 ses->sockfd = sockfd;
469 flags = GNUTLS_CLIENT;
470 if (secflags&SEC_FLAG_DTLS)
471 flags |= GNUTLS_DATAGRAM;
472 ret = gnutls_init(&ses->session, flags);
475 "%s: error in gnutls_init(): %s", __func__, gnutls_strerror(ret));
480 memcpy(&ses->our_sockaddr, our_sockaddr,
sizeof(*our_sockaddr));
481 if (!(secflags&SEC_FLAG_DTLS)) {
483 gnutls_handshake_set_timeout(ses->session, timeout*1000);
485 gnutls_handshake_set_timeout(ses->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
489 gnutls_dtls_set_timeouts(ses->session, 1000, timeout*1000);
492 gnutls_transport_set_int(ses->session, sockfd);
493 gnutls_session_set_ptr(ses->session, ses);
495 p = rc_conf_str_id(rh, OPT_TLS_VERIFY_HOSTNAME);
496 if (p && (strcasecmp(p,
"false") == 0 || strcasecmp(p,
"no") == 0)) {
497 ses->skip_hostname_check = 1;
500 if (st && st->psk_cred) {
502 gnutls_credentials_set(ses->session,
503 GNUTLS_CRD_PSK, st->psk_cred);
505 ret = gnutls_priority_set_direct(ses->session,
"NORMAL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:-VERS-TLS1.0", NULL);
509 "%s: error in setting PSK priorities: %s",
510 __func__, gnutls_strerror(ret));
516 gnutls_credentials_set(ses->session,
517 GNUTLS_CRD_CERTIFICATE,
521 gnutls_set_default_priority(ses->session);
524 gnutls_server_name_set(ses->session, GNUTLS_NAME_DNS,
525 hostname, strlen(hostname));
528 rc_getaddrinfo(hostname, PW_AI_AUTH);
531 rc_log(LOG_ERR,
"%s: cannot resolve %s", __func__,
537 if (info->ai_addr->sa_family == AF_INET)
538 ((
struct sockaddr_in *)info->ai_addr)->sin_port =
541 ((
struct sockaddr_in6 *)info->ai_addr)->sin6_port =
544 rc_log(LOG_ERR,
"%s: no port specified for server %s",
550 strlcpy(ses->hostname, hostname,
sizeof(ses->hostname));
555 "%s: neither tls-ca-file or a PSK key are configured",
562 ret = connect(sockfd, info->ai_addr, info->ai_addrlen);
567 rc_log(LOG_CRIT,
"%s: cannot connect to %s: %s",
568 __func__, hostname, strerror(e));
578 sock_flags = fcntl(sockfd, F_GETFL, 0);
579 if (sock_flags == -1 ||
580 fcntl(sockfd, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
583 rc_log(LOG_CRIT,
"%s: cannot set socket non-blocking: %s",
584 __func__, strerror(e));
589 "%s: performing TLS/DTLS handshake with [%s]:%d",
590 __func__, hostname, port);
592 ret = gnutls_handshake(ses->session);
593 if (ret == GNUTLS_E_LARGE_PACKET)
595 }
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
598 rc_log(LOG_ERR,
"%s: error in handshake: %s",
599 __func__, gnutls_strerror(ret));
604 ses->handshake_done = 1;
611 ses->last_msg = time(0);
612 ses->last_recv = ses->last_msg;
631static int restart_session(rc_handle *rh, tls_st *st)
634 struct tls_int_st tmps = { 0 };
638 timeout = rc_conf_int_id(rh, OPT_RADIUS_TIMEOUT);
641 ret = init_session(rh, &tmps, st->ctx.hostname, st->ctx.port, &st->ctx.our_sockaddr, timeout, st->flags);
643 rc_log(LOG_ERR,
"%s: error in re-initializing TLS session", __func__);
647 if (tmps.sockfd == st->ctx.sockfd)
649 deinit_session(&st->ctx);
650 memcpy(&st->ctx, &tmps,
sizeof(tmps));
651 st->ctx.need_restart = 0;
662int radcli2_priv_tls_fd(rc_handle * rh)
671 if (st->ctx.init != 0) {
672 return st->ctx.sockfd;
688time_t radcli2_priv_tls_last_msg(rc_handle * rh)
697 if (st->ctx.init != 0) {
698 return st->ctx.last_msg;
715time_t radcli2_priv_tls_last_recv(rc_handle * rh)
724 if (st->ctx.init != 0) {
725 return st->ctx.last_recv;
740int radcli2_priv_tls_force_reconnect(rc_handle * rh)
748 st->ctx.need_restart = 1;
749 return restart_session(rh, st);
767int radcli2_priv_check_tls(rc_handle * rh)
777 if (st->ctx.init == 0)
780 if (st->ctx.need_restart != 0)
781 return restart_session(rh, st) < 0 ? -1 : 0;
783 interval = rc_conf_int_id(rh, OPT_WATCHDOG_INTERVAL);
784 if (interval > 0 && time(0) - st->ctx.last_msg >= interval)
785 radcli2_priv_dae_send_watchdog((radcli_ctx *)rh);
800int radcli2_priv_tls_ensure_connected(rc_handle *rh)
809 if (st->ctx.init != 0 && st->ctx.need_restart == 0)
812 return restart_session(rh, st);
846int radcli2_priv_tls_dae_poll(rc_handle *rh, uint8_t *buf,
size_t cap)
855 if (st->ctx.init == 0 || st->ctx.need_restart != 0)
866 if (pthread_mutex_trylock(&st->ctx.lock) != 0)
869 ret = gnutls_record_recv(st->ctx.session, buf, cap);
871 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
872 pthread_mutex_unlock(&st->ctx.lock);
877 rc_log(LOG_ERR,
"%s: error in receiving: %s", __func__,
878 gnutls_strerror(ret));
879 st->ctx.need_restart = 1;
880 pthread_mutex_unlock(&st->ctx.lock);
884 st->ctx.last_msg = time(0);
885 st->ctx.last_recv = st->ctx.last_msg;
892void radcli2_priv_tls_dae_poll_done(rc_handle *rh)
899 pthread_mutex_unlock(&st->ctx.lock);
929int radcli2_priv_tls_dae_send(rc_handle *rh,
const void *buf,
size_t len)
938 if (st->ctx.init == 0 || st->ctx.need_restart != 0)
941 pthread_mutex_lock(&st->ctx.lock);
942 ret = gnutls_record_send(st->ctx.session, buf, len);
944 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
945 pthread_mutex_unlock(&st->ctx.lock);
949 rc_log(LOG_ERR,
"%s: error in sending: %s", __func__, gnutls_strerror(ret));
950 st->ctx.need_restart = 1;
951 pthread_mutex_unlock(&st->ctx.lock);
955 st->ctx.last_msg = time(0);
956 pthread_mutex_unlock(&st->ctx.lock);
985int radcli2_priv_tls_try_recv(rc_handle *rh, uint8_t *buf,
size_t cap)
995 ret = gnutls_record_recv(st->ctx.session, buf, cap);
997 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
1000 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) {
1001 rc_log(LOG_ERR,
"%s: received alert: %s", __func__,
1002 gnutls_alert_get_name(gnutls_alert_get(st->ctx.session)));
1014 (((
const uint8_t *)buf)[0] == RADCLI_DISCONNECT_REQUEST ||
1015 ((
const uint8_t *)buf)[0] == RADCLI_COA_REQUEST)) {
1016 radcli2_priv_dae_on_radsec_packet(st->rh, buf, (
size_t)ret);
1021 rc_log(LOG_ERR,
"%s: error in receiving: %s", __func__, gnutls_strerror(ret));
1022 st->ctx.need_restart = 1;
1026 st->ctx.last_msg = time(0);
1034void rc_deinit_tls(rc_handle * rh)
1036 tls_st *st = rh->so.ptr;
1041 ns = rc_conf_str_id(rh, OPT_NAMESPACE);
1043 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
1044 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
1048 if (st->ctx.init != 0)
1049 deinit_session(&st->ctx);
1051 gnutls_certificate_free_credentials(st->x509_cred);
1053 gnutls_psk_free_client_credentials(st->psk_cred);
1055 if(-1 == rc_reset_netns(&ns_def_hdl))
1056 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
1070int rc_init_tls(rc_handle * rh,
unsigned flags)
1074 struct sockaddr_storage our_sockaddr;
1075 const char *ca_file = rc_conf_str_id(rh, OPT_TLS_CA_FILE);
1076 const char *cert_file = rc_conf_str_id(rh, OPT_TLS_CERT_FILE);
1077 const char *key_file = rc_conf_str_id(rh, OPT_TLS_KEY_FILE);
1078 const char *pskkey = NULL;
1079 SERVER *authservers;
1085 memset(&rh->so, 0,
sizeof(rh->so));
1087 ns = rc_conf_str_id(rh, OPT_NAMESPACE);
1089 if(-1 == rc_set_netns(ns, &ns_def_hdl)) {
1090 rc_log(LOG_ERR,
"rc_send_server: namespace %s set failed", ns);
1095 if (flags & SEC_FLAG_DTLS) {
1097 rh->so.static_secret = DEFAULT_DTLS_SECRET;
1100 rh->so.static_secret = DEFAULT_TLS_SECRET;
1103 rc_own_bind_addr(rh, &our_sockaddr);
1105 st = calloc(1,
sizeof(tls_st));
1116 if (ca_file || (key_file && cert_file)) {
1117 ret = gnutls_certificate_allocate_credentials(&st->x509_cred);
1121 "%s: error in setting X.509 credentials: %s",
1122 __func__, gnutls_strerror(ret));
1128 gnutls_certificate_set_x509_trust_file(st->x509_cred,
1130 GNUTLS_X509_FMT_PEM);
1134 "%s: error in setting X.509 trust file: %s: %s",
1135 __func__, gnutls_strerror(ret), ca_file);
1140 if (cert_file && key_file) {
1142 gnutls_certificate_set_x509_key_file(st->x509_cred,
1145 GNUTLS_X509_FMT_PEM);
1149 "%s: error in setting X.509 cert and key files: %s: %s - %s",
1150 __func__, gnutls_strerror(ret), cert_file, key_file);
1155 gnutls_certificate_set_verify_function(st->x509_cred,
1156 cert_verify_callback);
1160 authservers = radcli2_priv_conf_srv(rh,
"authserver");
1161 if (authservers == NULL) {
1163 "%s: cannot find authserver", __func__);
1167 if (authservers->max > 1) {
1170 "%s: too many auth servers for TLS/DTLS; only one is allowed",
1174 strlcpy(hostname, authservers->name[0],
sizeof(hostname));
1175 port = authservers->port[0];
1177 if (rh->tls_psk_key != NULL) {
1182 gnutls_datum_t rawkey;
1184 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
1188 "%s: error in setting PSK credentials: %s",
1189 __func__, gnutls_strerror(ret));
1193 rawkey.data = rh->tls_psk_key;
1194 rawkey.size = rh->tls_psk_key_len;
1196 ret = gnutls_psk_set_client_credentials(st->psk_cred,
1197 rh->tls_psk_identity ? rh->tls_psk_identity :
"",
1198 &rawkey, GNUTLS_PSK_KEY_RAW);
1202 "%s: error in setting PSK key: %s",
1203 __func__, gnutls_strerror(ret));
1218 const char *psk_identity = rc_conf_str_id(rh, OPT_TLS_PSK_IDENTITY);
1219 const char *psk_key = rc_conf_str_id(rh, OPT_TLS_PSK_KEY);
1221 if ((psk_identity != NULL) != (psk_key != NULL)) {
1224 "%s: tls-psk-identity and tls-psk-key must both be set",
1229 if (psk_identity != NULL && psk_key != NULL) {
1230 gnutls_datum_t hexkey;
1232 hexkey.data = (uint8_t *)psk_key;
1233 hexkey.size = strlen(psk_key);
1235 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
1239 "%s: error in setting PSK credentials: %s",
1240 __func__, gnutls_strerror(ret));
1244 ret = gnutls_psk_set_client_credentials(st->psk_cred,
1245 psk_identity, &hexkey,
1246 GNUTLS_PSK_KEY_HEX);
1250 "%s: error in setting PSK key: %s",
1251 __func__, gnutls_strerror(ret));
1259 if (authservers->secret[0])
1260 pskkey = authservers->secret[0];
1262 if (pskkey && pskkey[0] != 0) {
1265 gnutls_datum_t hexkey;
1268 if (strncmp(pskkey,
"psk@", 4) != 0) {
1271 "%s: server secret is set but does not start with 'psk@'",
1277 if ((p = strchr(pskkey,
'@')) == NULL) {
1280 "%s: PSK key is not in 'username@hexkey' format",
1285 username_len = p - pskkey;
1286 if (username_len + 1 >
sizeof(username)) {
1288 "%s: PSK username too big", __func__);
1293 strlcpy(username, pskkey, username_len + 1);
1296 hexkey.data = (uint8_t*)p;
1297 hexkey.size = strlen(p);
1299 ret = gnutls_psk_allocate_client_credentials(&st->psk_cred);
1303 "%s: error in setting PSK credentials: %s",
1304 __func__, gnutls_strerror(ret));
1309 gnutls_psk_set_client_credentials(st->psk_cred,
1311 GNUTLS_PSK_KEY_HEX);
1315 "%s: error in setting PSK key: %s",
1316 __func__, gnutls_strerror(ret));
1325 strlcpy(st->ctx.hostname, hostname,
sizeof(st->ctx.hostname));
1326 st->ctx.port = port;
1327 memcpy(&st->ctx.our_sockaddr, &our_sockaddr,
sizeof(our_sockaddr));
1328 st->ctx.need_restart = 1;
1330 rh->so.get_fd = tls_get_fd;
1331 rh->so.get_active_fd = tls_get_active_fd;
1332 rh->so.sendto = tls_sendto;
1333 rh->so.recvfrom = tls_recvfrom;
1334 rh->so.lock = tls_lock;
1335 rh->so.unlock = tls_unlock;
1337 if(-1 == rc_reset_netns(&ns_def_hdl)) {
1338 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
1346 if (st->ctx.init != 0)
1347 deinit_session(&st->ctx);
1349 gnutls_certificate_free_credentials(st->x509_cred);
1351 gnutls_psk_free_client_credentials(st->psk_cred);
1356 if(-1 == rc_reset_netns(&ns_def_hdl))
1357 rc_log(LOG_ERR,
"rc_send_server: namespace %s reset failed", ns);
1368int radcli2_priv_tls_fd(rc_handle * rh)
1373time_t radcli2_priv_tls_last_msg(rc_handle * rh)
1379time_t radcli2_priv_tls_last_recv(rc_handle * rh)
1385int radcli2_priv_tls_force_reconnect(rc_handle * rh)
1391int radcli2_priv_check_tls(rc_handle * rh)
1396int radcli2_priv_tls_ensure_connected(rc_handle *rh)
1402int radcli2_priv_tls_dae_poll(rc_handle *rh, uint8_t *buf,
size_t cap)
1410void radcli2_priv_tls_dae_poll_done(rc_handle *rh)
1415int radcli2_priv_tls_dae_send(rc_handle *rh,
const void *buf,
size_t len)
1423int radcli2_priv_tls_try_recv(rc_handle *rh, uint8_t *buf,
size_t cap)
@ RC_SOCKET_DTLS
DTLS socket.
@ RC_SOCKET_TLS
TLS socket.