2 * Copyright (C) 2006 Stig Venaas <venaas@uninett.no>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
10 * peers can not yet be specified with literal IPv6 addresses due to port syntax
14 * make our server ignore client retrans and do its own instead?
15 * tls keep alives (server status)
16 * tls certificate validation
19 /* For UDP there is one server instance consisting of udpserverrd and udpserverth
20 * rd is responsible for init and launching wr
21 * For TLS there is a server instance that launches tlsserverrd for each TLS peer
22 * each tlsserverrd launches tlsserverwr
23 * For each UDP/TLS peer there is clientrd and clientwr, clientwr is responsible
24 * for init and launching rd
26 * serverrd will receive a request, processes it and puts it in the requestq of
27 * the appropriate clientwr
28 * clientwr monitors its requestq and sends requests
29 * clientrd looks for responses, processes them and puts them in the replyq of
30 * the peer the request came from
31 * serverwr monitors its reply and sends replies
33 * In addition to the main thread, we have:
34 * If UDP peers are configured, there will be 2 + 2 * #peers UDP threads
35 * If TLS peers are configured, there will initially be 2 * #peers TLS threads
36 * For each TLS peer connecting to us there will be 2 more TLS threads
37 * This is only for connected peers
38 * Example: With 3 UDP peer and 30 TLS peers, there will be a max of
39 * 1 + (2 + 2 * 3) + (2 * 30) + (2 * 30) = 129 threads
46 #include <openssl/ssl.h>
47 #include <openssl/rand.h>
48 #include <openssl/err.h>
49 #include <openssl/md5.h>
50 #include <openssl/hmac.h>
51 #include "radsecproxy.h"
53 static struct client clients[MAX_PEERS];
54 static struct server servers[MAX_PEERS];
56 static int client_count = 0;
57 static int server_count = 0;
59 static struct replyq udp_server_replyq;
60 static int udp_server_sock = -1;
61 static char *udp_server_port = DEFAULT_UDP_PORT;
62 static pthread_mutex_t *ssl_locks;
63 static long *ssl_lock_count;
64 static SSL_CTX *ssl_ctx_cl;
68 /* callbacks for making OpenSSL thread safe */
69 unsigned long ssl_thread_id() {
70 return (unsigned long)pthread_self();
73 void ssl_locking_callback(int mode, int type, const char *file, int line) {
74 if (mode & CRYPTO_LOCK) {
75 pthread_mutex_lock(&ssl_locks[type]);
76 ssl_lock_count[type]++;
78 pthread_mutex_unlock(&ssl_locks[type]);
81 void ssl_locks_setup() {
84 ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
85 ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
86 for (i = 0; i < CRYPTO_num_locks(); i++) {
87 ssl_lock_count[i] = 0;
88 pthread_mutex_init(&ssl_locks[i], NULL);
91 CRYPTO_set_id_callback(ssl_thread_id);
92 CRYPTO_set_locking_callback(ssl_locking_callback);
95 int resolvepeer(struct peer *peer) {
96 struct addrinfo hints, *addrinfo;
98 memset(&hints, 0, sizeof(hints));
99 hints.ai_socktype = (peer->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
100 hints.ai_family = AF_UNSPEC;
101 if (getaddrinfo(peer->host, peer->port, &hints, &addrinfo)) {
102 err("resolvepeer: can't resolve %s port %s", peer->host, peer->port);
107 freeaddrinfo(peer->addrinfo);
108 peer->addrinfo = addrinfo;
112 int connecttoserver(struct addrinfo *addrinfo) {
114 struct addrinfo *res;
116 for (res = addrinfo; res; res = res->ai_next) {
117 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
119 err("connecttoserver: socket failed");
122 if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
124 err("connecttoserver: connect failed");
131 /* returns the client with matching address, or NULL */
132 /* if client argument is not NULL, we only check that one client */
133 struct client *find_client(char type, struct sockaddr *addr, struct client *client) {
134 struct sockaddr_in6 *sa6;
135 struct in_addr *a4 = NULL;
138 struct addrinfo *res;
140 if (addr->sa_family == AF_INET6) {
141 sa6 = (struct sockaddr_in6 *)addr;
142 if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
143 a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
145 a4 = &((struct sockaddr_in *)addr)->sin_addr;
147 c = (client ? client : clients);
148 for (i = 0; i < client_count; i++) {
149 if (c->peer.type == type)
150 for (res = c->peer.addrinfo; res; res = res->ai_next)
151 if ((a4 && res->ai_family == AF_INET &&
152 !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
153 (res->ai_family == AF_INET6 &&
154 !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
163 /* returns the server with matching address, or NULL */
164 /* if server argument is not NULL, we only check that one server */
165 struct server *find_server(char type, struct sockaddr *addr, struct server *server) {
166 struct sockaddr_in6 *sa6;
167 struct in_addr *a4 = NULL;
170 struct addrinfo *res;
172 if (addr->sa_family == AF_INET6) {
173 sa6 = (struct sockaddr_in6 *)addr;
174 if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
175 a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
177 a4 = &((struct sockaddr_in *)addr)->sin_addr;
179 s = (server ? server : servers);
180 for (i = 0; i < server_count; i++) {
181 if (s->peer.type == type)
182 for (res = s->peer.addrinfo; res; res = res->ai_next)
183 if ((a4 && res->ai_family == AF_INET &&
184 !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
185 (res->ai_family == AF_INET6 &&
186 !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
195 /* exactly one of client and server must be non-NULL */
196 /* if *peer == NULL we return who we received from, else require it to be from peer */
197 /* return from in sa if not NULL */
198 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
201 unsigned char buf[65536], *rad;
202 struct sockaddr_storage from;
203 socklen_t fromlen = sizeof(from);
206 cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
208 err("radudpget: recv failed");
211 printf("radudpget: got %d bytes from %s\n", cnt, addr2string((struct sockaddr *)&from, fromlen));
214 printf("radudpget: packet too small\n");
221 printf("radudpget: packet smaller than length field in radius header\n");
225 printf("radudpget: packet was padded with %d bytes\n", cnt - len);
228 ? (void *)find_client('U', (struct sockaddr *)&from, *client)
229 : (void *)find_server('U', (struct sockaddr *)&from, *server));
231 printf("radudpget: got packet from wrong or unknown UDP peer, ignoring\n");
238 err("radudpget: malloc failed");
240 memcpy(rad, buf, len);
242 *client = (struct client *)f; /* only need this if *client == NULL, but if not NULL *client == f here */
244 *server = (struct server *)f; /* only need this if *server == NULL, but if not NULL *server == f here */
250 void tlsconnect(struct server *server, struct timeval *when, char *text) {
255 printf("tlsconnect called from %s\n", text);
256 pthread_mutex_lock(&server->lock);
257 if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
258 /* already reconnected, nothing to do */
259 printf("tlsconnect(%s): seems already reconnected\n", text);
260 pthread_mutex_unlock(&server->lock);
264 printf("tlsconnect %s\n", text);
267 gettimeofday(&now, NULL);
268 elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
269 if (server->connectionok) {
270 server->connectionok = 0;
272 } else if (elapsed < 5)
274 else if (elapsed < 600)
276 else if (elapsed < 10000) /* no sleep at startup */
278 printf("tlsconnect: trying to open TLS connection to %s port %s\n", server->peer.host, server->peer.port);
279 if (server->sock >= 0)
281 if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0)
283 SSL_free(server->peer.ssl);
284 server->peer.ssl = SSL_new(ssl_ctx_cl);
285 SSL_set_fd(server->peer.ssl, server->sock);
286 if (SSL_connect(server->peer.ssl) > 0)
288 while ((error = ERR_get_error()))
289 err("tlsconnect: TLS: %s", ERR_error_string(error, NULL));
291 printf("tlsconnect: TLS connection to %s port %s up\n", server->peer.host, server->peer.port);
292 gettimeofday(&server->lastconnecttry, NULL);
293 pthread_mutex_unlock(&server->lock);
296 unsigned char *radtlsget(SSL *ssl) {
298 unsigned char buf[4], *rad;
301 for (total = 0; total < 4; total += cnt) {
302 cnt = SSL_read(ssl, buf + total, 4 - total);
304 printf("radtlsget: connection lost\n");
312 err("radtlsget: malloc failed");
317 for (; total < len; total += cnt) {
318 cnt = SSL_read(ssl, rad + total, len - total);
320 printf("radtlsget: connection lost\n");
330 printf("radtlsget: packet smaller than minimum radius size\n");
333 printf("radtlsget: got %d bytes\n", total);
337 int clientradput(struct server *server, unsigned char *rad) {
341 struct timeval lastconnecttry;
344 if (server->peer.type == 'U') {
345 if (send(server->sock, rad, len, 0) >= 0) {
346 printf("clienradput: sent UDP of length %d to %s port %s\n", len, server->peer.host, server->peer.port);
349 err("clientradput: send failed");
353 lastconnecttry = server->lastconnecttry;
354 while ((cnt = SSL_write(server->peer.ssl, rad, len)) <= 0) {
355 while ((error = ERR_get_error()))
356 err("clientwr: TLS: %s", ERR_error_string(error, NULL));
357 tlsconnect(server, &lastconnecttry, "clientradput");
358 lastconnecttry = server->lastconnecttry;
361 server->connectionok = 1;
362 printf("clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s\n",
363 cnt, len, server->peer.host);
367 int radsign(unsigned char *rad, unsigned char *sec) {
368 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
369 static unsigned char first = 1;
370 static EVP_MD_CTX mdctx;
374 pthread_mutex_lock(&lock);
376 EVP_MD_CTX_init(&mdctx);
380 result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
381 EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
382 EVP_DigestUpdate(&mdctx, sec, strlen(sec)) &&
383 EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
385 pthread_mutex_unlock(&lock);
389 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
390 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
391 static unsigned char first = 1;
392 static EVP_MD_CTX mdctx;
393 unsigned char hash[EVP_MAX_MD_SIZE];
397 pthread_mutex_lock(&lock);
399 EVP_MD_CTX_init(&mdctx);
405 result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
406 EVP_DigestUpdate(&mdctx, rad, 4) &&
407 EVP_DigestUpdate(&mdctx, reqauth, 16) &&
408 (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
409 EVP_DigestUpdate(&mdctx, sec, strlen(sec)) &&
410 EVP_DigestFinal_ex(&mdctx, hash, &len) &&
412 !memcmp(hash, rad + 4, 16));
413 pthread_mutex_unlock(&lock);
417 int checkmessageauth(char *rad, uint8_t *authattr, char *secret) {
418 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
419 static unsigned char first = 1;
420 static HMAC_CTX hmacctx;
422 uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
424 pthread_mutex_lock(&lock);
426 HMAC_CTX_init(&hmacctx);
430 memcpy(auth, authattr, 16);
431 memset(authattr, 0, 16);
433 HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
434 HMAC_Update(&hmacctx, rad, RADLEN(rad));
435 HMAC_Final(&hmacctx, hash, &md_len);
437 printf("message auth computation failed\n");
438 pthread_mutex_unlock(&lock);
442 if (memcmp(auth, hash, 16)) {
443 printf("message authenticator, wrong value\n");
444 pthread_mutex_unlock(&lock);
448 pthread_mutex_unlock(&lock);
452 int createmessageauth(char *rad, char *authattrval, char *secret) {
453 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
454 static unsigned char first = 1;
455 static HMAC_CTX hmacctx;
461 pthread_mutex_lock(&lock);
463 HMAC_CTX_init(&hmacctx);
467 memset(authattrval, 0, 16);
469 HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
470 HMAC_Update(&hmacctx, rad, RADLEN(rad));
471 HMAC_Final(&hmacctx, authattrval, &md_len);
473 printf("message auth computation failed\n");
474 pthread_mutex_unlock(&lock);
478 pthread_mutex_unlock(&lock);
482 void sendrq(struct server *to, struct client *from, struct request *rq) {
485 pthread_mutex_lock(&to->newrq_mutex);
488 for (i = 0; i < MAX_REQUESTS; i++)
489 if (!to->requests[i].buf)
491 if (i == MAX_REQUESTS) {
492 printf("No room in queue, dropping request\n");
493 pthread_mutex_unlock(&to->newrq_mutex);
496 rq->buf[1] = (char)i;
499 if (!createmessageauth(rq->buf, rq->messageauthattrval, to->peer.secret))
501 gettimeofday(&rq->expiry, NULL);
502 rq->expiry.tv_sec += 30;
503 to->requests[i] = *rq;
507 printf("signalling client writer\n");
508 pthread_cond_signal(&to->newrq_cond);
510 pthread_mutex_unlock(&to->newrq_mutex);
513 void sendreply(struct client *to, struct server *from, char *buf, struct sockaddr_storage *tosa) {
514 struct replyq *replyq = to->replyq;
516 pthread_mutex_lock(&replyq->count_mutex);
517 if (replyq->count == replyq->size) {
518 printf("No room in queue, dropping request\n");
519 pthread_mutex_unlock(&replyq->count_mutex);
523 replyq->replies[replyq->count].buf = buf;
525 replyq->replies[replyq->count].tosa = *tosa;
528 if (replyq->count == 1) {
529 printf("signalling client writer\n");
530 pthread_cond_signal(&replyq->count_cond);
532 pthread_mutex_unlock(&replyq->count_mutex);
535 int pwdcrypt(uint8_t *plain, uint8_t *enc, uint8_t enclen, uint8_t *shared, uint8_t sharedlen,
537 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
538 static unsigned char first = 1;
539 static EVP_MD_CTX mdctx;
540 unsigned char hash[EVP_MAX_MD_SIZE], *input;
542 uint8_t i, offset = 0;
544 pthread_mutex_lock(&lock);
546 EVP_MD_CTX_init(&mdctx);
552 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
553 !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
554 !EVP_DigestUpdate(&mdctx, input, 16) ||
555 !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
557 pthread_mutex_unlock(&lock);
560 for (i = 0; i < 16; i++)
561 plain[offset + i] = hash[i] ^ enc[offset + i];
563 if (offset == enclen)
565 input = enc + offset - 16;
567 pthread_mutex_unlock(&lock);
571 struct server *id2server(char *id, uint8_t len) {
573 char **realm, *idrealm;
575 idrealm = strchr(id, '@');
583 for (i = 0; i < server_count; i++) {
584 for (realm = servers[i].realms; *realm; realm++) {
585 if ((strlen(*realm) == 1 && **realm == '*') ||
586 (strlen(*realm) == len && !memcmp(idrealm, *realm, len))) {
587 printf("found matching realm: %s, host %s\n", *realm, servers[i].peer.host);
595 struct server *radsrv(struct request *rq, char *buf, struct client *from) {
596 uint8_t code, id, *auth, *attr, pwd[128], attrvallen;
597 uint8_t *usernameattr = NULL, *userpwdattr = NULL, *tunnelpwdattr = NULL, *messageauthattr = NULL;
602 unsigned char newauth[16];
604 code = *(uint8_t *)buf;
605 id = *(uint8_t *)(buf + 1);
607 auth = (uint8_t *)(buf + 4);
609 printf("radsrv: code %d, id %d, length %d\n", code, id, len);
611 if (code != RAD_Access_Request) {
612 printf("radsrv: server currently accepts only access-requests, ignoring\n");
620 left -= attr[RAD_Attr_Length];
622 printf("radsrv: attribute length exceeds packet length, ignoring packet\n");
625 switch (attr[RAD_Attr_Type]) {
626 case RAD_Attr_User_Name:
629 case RAD_Attr_User_Password:
632 case RAD_Attr_Tunnel_Password:
633 tunnelpwdattr = attr;
635 case RAD_Attr_Message_Authenticator:
636 messageauthattr = attr;
639 attr += attr[RAD_Attr_Length];
642 printf("radsrv: malformed packet? remaining byte after last attribute\n");
645 printf("radsrv: Username: ");
646 for (i = 0; i < usernameattr[RAD_Attr_Length] - 2; i++)
647 printf("%c", usernameattr[RAD_Attr_Value + i]);
651 to = id2server(&usernameattr[RAD_Attr_Value], usernameattr[RAD_Attr_Length] - 2);
653 printf("radsrv: ignoring request, don't know where to send it\n");
657 if (!RAND_bytes(newauth, 16)) {
658 printf("radsrv: failed to generate random auth\n");
662 if (messageauthattr && (messageauthattr[RAD_Attr_Length] != 18 ||
663 !checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))) {
664 printf("radsrv: message authentication failed\n");
669 printf("radsrv: found userpwdattr of length %d\n", userpwdattr[RAD_Attr_Length]);
670 attrvallen = userpwdattr[RAD_Attr_Length] - 2;
671 if (attrvallen < 16 || attrvallen > 128 || attrvallen % 16) {
672 printf("radsrv: invalid user password length\n");
676 if (!pwdcrypt(pwd, &userpwdattr[RAD_Attr_Value], attrvallen, from->peer.secret, strlen(from->peer.secret), auth)) {
677 printf("radsrv: cannot decrypt password\n");
680 printf("radsrv: password: ");
681 for (i = 0; i < attrvallen; i++)
682 printf("%02x ", pwd[i]);
684 if (!pwdcrypt(&userpwdattr[RAD_Attr_Value], pwd, attrvallen, to->peer.secret, strlen(to->peer.secret), newauth)) {
685 printf("radsrv: cannot encrypt password\n");
691 printf("radsrv: found tunnelpwdattr of length %d\n", tunnelpwdattr[RAD_Attr_Length]);
692 attrvallen = tunnelpwdattr[RAD_Attr_Length] - 2;
693 if (attrvallen < 16 || attrvallen > 128 || attrvallen % 16) {
694 printf("radsrv: invalid user password length\n");
698 if (!pwdcrypt(pwd, &tunnelpwdattr[RAD_Attr_Value], attrvallen, from->peer.secret, strlen(from->peer.secret), auth)) {
699 printf("radsrv: cannot decrypt password\n");
702 printf("radsrv: password: ");
703 for (i = 0; i < attrvallen; i++)
704 printf("%02x ", pwd[i]);
706 if (!pwdcrypt(&tunnelpwdattr[RAD_Attr_Value], pwd, attrvallen, to->peer.secret, strlen(to->peer.secret), newauth)) {
707 printf("radsrv: cannot encrypt password\n");
715 rq->messageauthattrval = (messageauthattr ? &messageauthattr[RAD_Attr_Value] : NULL);
716 memcpy(rq->origauth, auth, 16);
717 memcpy(rq->buf + 4, newauth, 16);
721 void *clientrd(void *arg) {
722 struct server *server = (struct server *)arg;
725 unsigned char *buf, *messageauthattr, *attr;
726 struct sockaddr_storage fromsa;
727 struct timeval lastconnecttry;
730 lastconnecttry = server->lastconnecttry;
731 buf = (server->peer.type == 'U' ? radudpget(server->sock, NULL, &server, NULL) : radtlsget(server->peer.ssl));
732 if (!buf && server->peer.type == 'T') {
733 tlsconnect(server, &lastconnecttry, "clientrd");
737 server->connectionok = 1;
739 if (*buf != RAD_Access_Accept && *buf != RAD_Access_Reject && *buf != RAD_Access_Challenge) {
740 printf("clientrd: discarding, only accept access accept, access reject and access challenge messages\n");
744 i = buf[1]; /* i is the id */
746 pthread_mutex_lock(&server->newrq_mutex);
747 if (!server->requests[i].buf || !server->requests[i].tries) {
748 pthread_mutex_unlock(&server->newrq_mutex);
749 printf("clientrd: no matching request sent with this id, ignoring\n");
753 if (server->requests[i].received) {
754 pthread_mutex_unlock(&server->newrq_mutex);
755 printf("clientrd: already received, ignoring\n");
759 if (!validauth(buf, server->requests[i].buf + 4, server->peer.secret)) {
760 pthread_mutex_unlock(&server->newrq_mutex);
761 printf("clientrd: invalid auth, ignoring\n");
765 from = server->requests[i].from;
767 /* messageauthattr present? */
768 messageauthattr = NULL;
769 left = RADLEN(buf) - 20;
772 left -= attr[RAD_Attr_Length];
774 printf("radsrv: attribute length exceeds packet length, ignoring packet\n");
777 if (attr[RAD_Attr_Type] == RAD_Attr_Message_Authenticator) {
778 messageauthattr = attr;
781 attr += attr[RAD_Attr_Length];
784 if (messageauthattr) {
785 if (messageauthattr[RAD_Attr_Length] != 18)
787 memcpy(buf + 4, server->requests[i].buf + 4, 16);
788 if (!checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], server->peer.secret)) {
789 printf("clientrd: message authentication failed\n");
792 printf("clientrd: message auth ok\n");
795 /* once we set received = 1, requests[i] may be reused */
796 buf[1] = (char)server->requests[i].origid;
797 memcpy(buf + 4, server->requests[i].origauth, 16);
799 if (messageauthattr) {
800 if (!createmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))
802 printf("clientrd: computed messageauthattr\n");
805 if (from->peer.type == 'U')
806 fromsa = server->requests[i].fromsa;
807 server->requests[i].received = 1;
808 pthread_mutex_unlock(&server->newrq_mutex);
810 if (!radsign(buf, from->peer.secret)) {
811 printf("clientrd: failed to sign message\n");
815 printf("clientrd: giving packet back to where it came from\n");
816 sendreply(from, server, buf, from->peer.type == 'U' ? &fromsa : NULL);
820 void *clientwr(void *arg) {
821 struct server *server = (struct server *)arg;
823 pthread_t clientrdth;
827 if (server->peer.type == 'U') {
828 if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0) {
829 printf("clientwr: connecttoserver failed\n");
833 tlsconnect(server, NULL, "new client");
835 if (pthread_create(&clientrdth, NULL, clientrd, (void *)server))
836 errx("clientwr: pthread_create failed");
839 pthread_mutex_lock(&server->newrq_mutex);
840 while (!server->newrq) {
841 printf("clientwr: waiting for signal\n");
842 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
843 printf("clientwr: got signal\n");
846 pthread_mutex_unlock(&server->newrq_mutex);
848 for (i = 0; i < MAX_REQUESTS; i++) {
849 pthread_mutex_lock(&server->newrq_mutex);
850 while (!server->requests[i].buf && i < MAX_REQUESTS)
852 if (i == MAX_REQUESTS) {
853 pthread_mutex_unlock(&server->newrq_mutex);
857 gettimeofday(&now, NULL);
858 rq = server->requests + i;
861 printf("clientwr: removing received packet from queue\n");
863 /* setting this to NULL means that it can be reused */
865 pthread_mutex_unlock(&server->newrq_mutex);
868 if (now.tv_sec > rq->expiry.tv_sec) {
869 printf("clientwr: removing expired packet from queue\n");
871 /* setting this to NULL means that it can be reused */
873 pthread_mutex_unlock(&server->newrq_mutex);
878 continue; // not re-sending (yet)
881 pthread_mutex_unlock(&server->newrq_mutex);
883 clientradput(server, server->requests[i].buf);
886 /* should do more work to maintain TLS connections, keepalives etc */
889 void *udpserverwr(void *arg) {
890 struct replyq *replyq = &udp_server_replyq;
891 struct reply *reply = replyq->replies;
893 pthread_mutex_lock(&replyq->count_mutex);
895 while (!replyq->count) {
896 printf("udp server writer, waiting for signal\n");
897 pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
898 printf("udp server writer, got signal\n");
900 pthread_mutex_unlock(&replyq->count_mutex);
902 if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
903 (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
904 err("sendudp: send failed");
907 pthread_mutex_lock(&replyq->count_mutex);
909 memmove(replyq->replies, replyq->replies + 1,
910 replyq->count * sizeof(struct reply));
914 void *udpserverrd(void *arg) {
919 pthread_t udpserverwrth;
921 if ((udp_server_sock = bindport(SOCK_DGRAM, udp_server_port)) < 0) {
922 printf("udpserverrd: socket/bind failed\n");
925 printf("udpserverrd: listening on UDP port %s\n", udp_server_port);
927 if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
928 errx("pthread_create failed");
932 memset(&rq, 0, sizeof(struct request));
933 buf = radudpget(udp_server_sock, &fr, NULL, &rq.fromsa);
934 to = radsrv(&rq, buf, fr);
936 printf("udpserverrd: ignoring request, no place to send it\n");
943 void *tlsserverwr(void *arg) {
946 struct client *client = (struct client *)arg;
947 struct replyq *replyq;
949 pthread_mutex_lock(&client->replycount_mutex);
951 replyq = client->replyq;
952 while (!replyq->count) {
953 printf("tls server writer, waiting for signal\n");
954 pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
955 printf("tls server writer, got signal\n");
957 pthread_mutex_unlock(&replyq->count_mutex);
958 cnt = SSL_write(client->peer.ssl, replyq->replies->buf, RADLEN(replyq->replies->buf));
960 printf("tlsserverwr: Sent %d bytes, Radius packet of length %d\n",
961 cnt, RADLEN(replyq->replies->buf));
963 while ((error = ERR_get_error()))
964 err("tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
965 free(replyq->replies->buf);
967 pthread_mutex_lock(&replyq->count_mutex);
969 memmove(replyq->replies, replyq->replies + 1, replyq->count * sizeof(struct reply));
973 void *tlsserverrd(void *arg) {
979 struct client *client = (struct client *)arg;
980 pthread_t tlsserverwrth;
982 printf("tlsserverrd starting\n");
983 if (SSL_accept(client->peer.ssl) <= 0) {
984 while ((error = ERR_get_error()))
985 err("tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
986 errx("accept failed, child exiting");
989 if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client))
990 errx("pthread_create failed");
993 buf = radtlsget(client->peer.ssl);
995 printf("tlsserverrd: connection lost\n");
996 s = SSL_get_fd(client->peer.ssl);
997 SSL_free(client->peer.ssl);
998 client->peer.ssl = NULL;
1003 printf("tlsserverrd: got Radius message from %s\n", client->peer.host);
1004 memset(&rq, 0, sizeof(struct request));
1005 to = radsrv(&rq, buf, client);
1007 printf("ignoring request, no place to send it\n");
1010 sendrq(to, client, &rq);
1014 int tlslistener(SSL_CTX *ssl_ctx) {
1015 pthread_t tlsserverth;
1017 struct sockaddr_storage from;
1018 size_t fromlen = sizeof(from);
1019 struct client *client;
1021 if ((s = bindport(SOCK_STREAM, DEFAULT_TLS_PORT)) < 0) {
1022 printf("tlslistener: socket/bind failed\n");
1027 printf("listening for incoming TLS on port %s\n", DEFAULT_TLS_PORT);
1030 snew = accept(s, (struct sockaddr *)&from, &fromlen);
1032 errx("accept failed");
1033 printf("incoming TLS connection from %s\n", addr2string((struct sockaddr *)&from, fromlen));
1035 client = find_client('T', (struct sockaddr *)&from, NULL);
1037 printf("ignoring request, not a known TLS client\n");
1042 if (client->peer.ssl) {
1043 printf("Ignoring incoming connection, already have one from this client\n");
1047 client->peer.ssl = SSL_new(ssl_ctx);
1048 SSL_set_fd(client->peer.ssl, snew);
1049 if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client))
1050 errx("pthread_create failed");
1055 char *parsehostport(char *s, struct peer *peer) {
1060 // allow literal addresses and port, e.g. [2001:db8::1]:1812
1064 for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1066 printf("no ] matching initial [\n");
1072 for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1075 printf("missing host/address\n");
1078 peer->host = malloc(p - field + 1);
1080 errx("malloc failed");
1081 memcpy(peer->host, field, p - field);
1082 peer->host[p - field] = '\0';
1085 if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n') {
1086 printf("unexpected character after ]\n");
1091 /* port number or service name is specified */;
1093 for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1095 printf("syntax error, : but no following port\n");
1098 peer->port = malloc(p - field + 1);
1100 errx("malloc failed");
1101 memcpy(peer->port, field, p - field);
1102 peer->port[p - field] = '\0';
1108 // * is default, else longest match ... ";" used for separator
1109 char *parserealmlist(char *s, struct server *server) {
1113 for (p = s, n = 1; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++)
1118 server->realms = NULL;
1121 server->realmdata = malloc(l + 1);
1122 if (!server->realmdata)
1123 errx("malloc failed");
1124 memcpy(server->realmdata, s, l);
1125 server->realmdata[l] = '\0';
1126 server->realms = malloc((1+n) * sizeof(char *));
1127 if (!server->realms)
1128 errx("malloc failed");
1129 server->realms[0] = server->realmdata;
1130 for (n = 1, i = 0; i < l; i++)
1131 if (server->realmdata[i] == ';') {
1132 server->realmdata[i] = '\0';
1133 server->realms[n++] = server->realmdata + i + 1;
1135 server->realms[n] = NULL;
1139 /* exactly one argument must be non-NULL */
1140 void getconfig(const char *serverfile, const char *clientfile) {
1143 char *p, *field, **r;
1144 struct client *client;
1145 struct server *server;
1150 printf("opening file %s for reading\n", serverfile);
1151 f = fopen(serverfile, "r");
1153 errx("getconfig failed to open %s for reading", serverfile);
1154 count = &server_count;
1156 printf("opening file %s for reading\n", clientfile);
1157 f = fopen(clientfile, "r");
1159 errx("getconfig failed to open %s for reading", clientfile);
1160 udp_server_replyq.replies = malloc(4 * MAX_REQUESTS * sizeof(struct reply));
1161 if (!udp_server_replyq.replies)
1162 errx("malloc failed");
1163 udp_server_replyq.size = 4 * MAX_REQUESTS;
1164 udp_server_replyq.count = 0;
1165 pthread_mutex_init(&udp_server_replyq.count_mutex, NULL);
1166 pthread_cond_init(&udp_server_replyq.count_cond, NULL);
1167 count = &client_count;
1171 while (fgets(line, 1024, f) && *count < MAX_PEERS) {
1173 server = &servers[*count];
1174 memset(server, 0, sizeof(struct server));
1175 peer = &server->peer;
1177 client = &clients[*count];
1178 memset(client, 0, sizeof(struct client));
1179 peer = &client->peer;
1181 for (p = line; *p == ' ' || *p == '\t'; p++);
1182 if (*p == '#' || *p == '\n')
1184 if (*p != 'U' && *p != 'T') {
1185 printf("server type must be U or T, got %c\n", *p);
1189 for (p++; *p == ' ' || *p == '\t'; p++);
1190 p = parsehostport(p, peer);
1192 peer->port = (peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT);
1193 for (; *p == ' ' || *p == '\t'; p++);
1195 p = parserealmlist(p, server);
1196 if (!server->realms) {
1197 printf("realm list must be specified\n");
1200 for (; *p == ' ' || *p == '\t'; p++);
1203 for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1205 /* no secret set and end of line, line is complete if TLS */
1206 if (peer->type == 'U') {
1207 printf("secret must be specified for UDP\n");
1210 peer->secret = DEFAULT_TLS_SECRET;
1212 peer->secret = malloc(p - field + 1);
1214 errx("malloc failed");
1215 memcpy(peer->secret, field, p - field);
1216 peer->secret[p - field] = '\0';
1217 /* check that rest of line only white space */
1218 for (; *p == ' ' || *p == '\t'; p++);
1219 if (*p && *p != '\n') {
1220 printf("max 4 fields per line, found a 5th\n");
1225 if ((serverfile && !resolvepeer(&server->peer)) ||
1226 (clientfile && !resolvepeer(&client->peer))) {
1227 printf("failed to resolve host %s port %s, exiting\n", peer->host, peer->port);
1232 pthread_mutex_init(&server->lock, NULL);
1234 server->requests = malloc(MAX_REQUESTS * sizeof(struct request));
1235 if (!server->requests)
1236 errx("malloc failed");
1237 memset(server->requests, 0, MAX_REQUESTS * sizeof(struct request));
1239 pthread_mutex_init(&server->newrq_mutex, NULL);
1240 pthread_cond_init(&server->newrq_cond, NULL);
1242 if (peer->type == 'U')
1243 client->replyq = &udp_server_replyq;
1245 client->replyq = malloc(sizeof(struct replyq));
1246 if (!client->replyq)
1247 errx("malloc failed");
1248 client->replyq->replies = malloc(MAX_REQUESTS * sizeof(struct reply));
1249 if (!client->replyq->replies)
1250 errx("malloc failed");
1251 client->replyq->size = MAX_REQUESTS;
1252 client->replyq->count = 0;
1253 pthread_mutex_init(&client->replyq->count_mutex, NULL);
1254 pthread_cond_init(&client->replyq->count_cond, NULL);
1257 printf("got type %c, host %s, port %s, secret %s\n", peer->type, peer->host, peer->port, peer->secret);
1259 printf(" with realms:");
1260 for (r = server->realms; *r; r++)
1269 void parseargs(int argc, char **argv) {
1272 while ((c = getopt(argc, argv, "p:")) != -1) {
1275 udp_server_port = optarg;
1285 printf("radsecproxy [ -p UDP-port ]\n");
1289 int main(int argc, char **argv) {
1290 SSL_CTX *ssl_ctx_srv;
1291 unsigned long error;
1292 pthread_t udpserverth;
1293 pthread_attr_t joinable;
1296 parseargs(argc, argv);
1297 getconfig("servers.conf", NULL);
1298 getconfig(NULL, "clients.conf");
1302 pthread_attr_init(&joinable);
1303 pthread_attr_setdetachstate(&joinable, PTHREAD_CREATE_JOINABLE);
1305 /* listen on UDP if at least one UDP client */
1307 for (i = 0; i < client_count; i++)
1308 if (clients[i].peer.type == 'U') {
1309 if (pthread_create(&udpserverth, &joinable, udpserverrd, NULL))
1310 errx("pthread_create failed");
1315 SSL_load_error_strings();
1318 while (!RAND_status()) {
1319 time_t t = time(NULL);
1320 pid_t pid = getpid();
1321 RAND_seed((unsigned char *)&t, sizeof(time_t));
1322 RAND_seed((unsigned char *)&pid, sizeof(pid));
1325 /* initialise client part and start clients */
1326 ssl_ctx_cl = SSL_CTX_new(TLSv1_client_method());
1330 for (i = 0; i < server_count; i++) {
1331 if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
1332 errx("pthread_create failed");
1335 for (i = 0; i < client_count; i++)
1336 if (clients[i].peer.type == 'T')
1339 if (i == client_count) {
1340 printf("No TLS clients defined, not starting TLS listener\n");
1341 /* just hang around doing nothing, anything to do here? */
1346 /* setting up server/daemon part */
1347 ssl_ctx_srv = SSL_CTX_new(TLSv1_server_method());
1350 if (!SSL_CTX_use_certificate_file(ssl_ctx_srv, "/tmp/server.pem", SSL_FILETYPE_PEM)) {
1351 while ((error = ERR_get_error()))
1352 err("SSL: %s", ERR_error_string(error, NULL));
1353 errx("Failed to load certificate");
1355 if (!SSL_CTX_use_PrivateKey_file(ssl_ctx_srv, "/tmp/server.key", SSL_FILETYPE_PEM)) {
1356 while ((error = ERR_get_error()))
1357 err("SSL: %s", ERR_error_string(error, NULL));
1358 errx("Failed to load private key");
1361 return tlslistener(ssl_ctx_srv);