2 * Copyright (C) 2006, 2007 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.
9 /* For UDP there is one server instance consisting of udpserverrd and udpserverth
10 * rd is responsible for init and launching wr
11 * For TLS there is a server instance that launches tlsserverrd for each TLS peer
12 * each tlsserverrd launches tlsserverwr
13 * For each UDP/TLS peer there is clientrd and clientwr, clientwr is responsible
14 * for init and launching rd
16 * serverrd will receive a request, processes it and puts it in the requestq of
17 * the appropriate clientwr
18 * clientwr monitors its requestq and sends requests
19 * clientrd looks for responses, processes them and puts them in the replyq of
20 * the peer the request came from
21 * serverwr monitors its reply and sends replies
23 * In addition to the main thread, we have:
24 * If UDP peers are configured, there will be 2 + 2 * #peers UDP threads
25 * If TLS peers are configured, there will initially be 2 * #peers TLS threads
26 * For each TLS peer connecting to us there will be 2 more TLS threads
27 * This is only for connected peers
28 * Example: With 3 UDP peer and 30 TLS peers, there will be a max of
29 * 1 + (2 + 2 * 3) + (2 * 30) + (2 * 30) = 129 threads
32 #include <sys/socket.h>
33 #include <netinet/in.h>
38 #include <sys/types.h>
39 #include <arpa/inet.h>
43 #include <openssl/ssl.h>
44 #include <openssl/rand.h>
45 #include <openssl/err.h>
46 #include <openssl/md5.h>
47 #include <openssl/hmac.h>
48 #include <openssl/x509v3.h>
51 #include "radsecproxy.h"
53 static struct options options;
54 struct list *clconfs, *srvconfs, *realms, *tlsconfs;
56 static int client_udp_count = 0;
57 static int client_tls_count = 0;
58 static int server_udp_count = 0;
59 static int server_tls_count = 0;
61 static struct replyq *udp_server_replyq = NULL;
62 static int udp_server_sock = -1;
63 static int udp_accserver_sock = -1;
64 static int udp_client4_sock = -1;
65 static int udp_client6_sock = -1;
66 static pthread_mutex_t *ssl_locks;
67 static long *ssl_lock_count;
71 /* callbacks for making OpenSSL thread safe */
72 unsigned long ssl_thread_id() {
73 return (unsigned long)pthread_self();
76 void ssl_locking_callback(int mode, int type, const char *file, int line) {
77 if (mode & CRYPTO_LOCK) {
78 pthread_mutex_lock(&ssl_locks[type]);
79 ssl_lock_count[type]++;
81 pthread_mutex_unlock(&ssl_locks[type]);
84 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
85 int pwdlen = strlen(userdata);
86 if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
88 memcpy(buf, userdata, pwdlen);
92 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
97 err_cert = X509_STORE_CTX_get_current_cert(ctx);
98 err = X509_STORE_CTX_get_error(ctx);
99 depth = X509_STORE_CTX_get_error_depth(ctx);
101 if (depth > MAX_CERT_DEPTH) {
103 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
104 X509_STORE_CTX_set_error(ctx, err);
108 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
109 debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
112 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
113 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
114 debug(DBG_WARN, "\tIssuer=%s", buf);
116 case X509_V_ERR_CERT_NOT_YET_VALID:
117 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
118 debug(DBG_WARN, "\tCertificate not yet valid");
120 case X509_V_ERR_CERT_HAS_EXPIRED:
121 debug(DBG_WARN, "Certificate has expired");
123 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
124 debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
129 printf("certificate verify returns %d\n", ok);
134 int resolvepeer(struct clsrvconf *conf, int ai_flags) {
135 struct addrinfo hints, *addrinfo;
139 slash = conf->host ? strchr(conf->host, '/') : NULL;
143 debug(DBG_WARN, "resolvepeer: prefix length must be specified after the / in %s", conf->host);
147 if (*s < '0' || *s > '9') {
148 debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
151 plen = atoi(slash + 1);
152 if (plen < 0 || plen > 128) {
153 debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
158 memset(&hints, 0, sizeof(hints));
159 hints.ai_socktype = (conf->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
160 hints.ai_family = AF_UNSPEC;
161 hints.ai_flags = ai_flags;
163 hints.ai_flags |= AI_NUMERICHOST;
164 if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) {
165 debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host, conf->port);
171 switch (addrinfo->ai_family) {
174 debug(DBG_WARN, "resolvepeer: prefix length must be <= 32 in %s", conf->host);
175 freeaddrinfo(addrinfo);
182 debug(DBG_WARN, "resolvepeer: prefix must be IPv4 or IPv6 in %s", conf->host);
183 freeaddrinfo(addrinfo);
186 conf->prefixlen = plen;
188 conf->prefixlen = 255;
191 freeaddrinfo(conf->addrinfo);
192 conf->addrinfo = addrinfo;
196 int connecttoserver(struct addrinfo *addrinfo) {
198 struct addrinfo *res;
201 for (res = addrinfo; res; res = res->ai_next) {
202 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
204 debug(DBG_WARN, "connecttoserver: socket failed");
207 if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
209 debug(DBG_WARN, "connecttoserver: connect failed");
216 int bindtoaddr(struct addrinfo *addrinfo) {
218 struct addrinfo *res;
220 for (res = addrinfo; res; res = res->ai_next) {
221 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
223 debug(DBG_WARN, "bindtoaddr: socket failed");
226 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
227 if (!bind(s, res->ai_addr, res->ai_addrlen))
229 debug(DBG_WARN, "bindtoaddr: bind failed");
235 /* returns 1 if the len first bits are equal, else 0 */
236 int prefixmatch(void *a1, void *a2, uint8_t len) {
237 static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
239 if (l && memcmp(a1, a2, l))
244 return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
247 /* returns the config with matching address, or NULL */
248 /* if conf argument is not NULL, we only check that one */
249 struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs, struct clsrvconf *conf) {
250 struct sockaddr_in6 *sa6 = NULL;
251 struct in_addr *a4 = NULL;
252 struct addrinfo *res;
253 struct list_node *entry;
255 if (addr->sa_family == AF_INET6) {
256 sa6 = (struct sockaddr_in6 *)addr;
257 if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
258 a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
262 a4 = &((struct sockaddr_in *)addr)->sin_addr;
265 if (conf->type == type) {
266 if (conf->prefixlen == 255) {
267 for (res = conf->addrinfo; res; res = res->ai_next)
268 if ((a4 && res->ai_family == AF_INET &&
269 !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
270 (sa6 && res->ai_family == AF_INET6 &&
271 !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
274 res = conf->addrinfo;
276 ((a4 && res->ai_family == AF_INET &&
277 prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
278 (sa6 && res->ai_family == AF_INET6 &&
279 prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
286 for (entry = list_first(confs); entry; entry = list_next(entry)) {
287 conf = (struct clsrvconf *)entry->data;
288 if (conf->type == type) {
289 if (conf->prefixlen == 255) {
290 for (res = conf->addrinfo; res; res = res->ai_next)
291 if ((a4 && res->ai_family == AF_INET &&
292 !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
293 (sa6 && res->ai_family == AF_INET6 &&
294 !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
297 res = conf->addrinfo;
299 ((a4 && res->ai_family == AF_INET &&
300 prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
301 (sa6 && res->ai_family == AF_INET6 &&
302 prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
310 struct replyq *newreplyq() {
311 struct replyq *replyq;
313 replyq = malloc(sizeof(struct replyq));
315 debugx(1, DBG_ERR, "malloc failed");
316 replyq->replies = list_create();
317 if (!replyq->replies)
318 debugx(1, DBG_ERR, "malloc failed");
319 pthread_mutex_init(&replyq->mutex, NULL);
320 pthread_cond_init(&replyq->cond, NULL);
324 struct client *addclient(struct clsrvconf *conf) {
325 struct client *new = malloc(sizeof(struct client));
328 debug(DBG_ERR, "malloc failed");
331 if (!conf->clients) {
332 conf->clients = list_create();
333 if (!conf->clients) {
334 debug(DBG_ERR, "malloc failed");
339 memset(new, 0, sizeof(struct client));
341 new->replyq = conf->type == 'T' ? newreplyq() : udp_server_replyq;
343 list_push(conf->clients, new);
347 void removeclient(struct client *client) {
348 if (!client || !client->conf->clients)
351 list_removedata(client->conf->clients, client);
355 void addserver(struct clsrvconf *conf) {
359 debugx(1, DBG_ERR, "addserver: currently works with just one server per conf");
361 conf->servers = malloc(sizeof(struct server));
363 debugx(1, DBG_ERR, "malloc failed");
364 memset(conf->servers, 0, sizeof(struct server));
365 conf->servers->conf = conf;
367 if (conf->type == 'U') {
368 switch (conf->addrinfo->ai_family) {
370 if (udp_client4_sock < 0) {
371 struct sockaddr_in sa;
372 memset(&sa, 0, sizeof(sa));
373 sa.sin_family = AF_INET;
374 udp_client4_sock = socket(PF_INET, conf->addrinfo->ai_socktype, conf->addrinfo->ai_protocol);
375 if (udp_client4_sock < 0)
376 debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
377 if (bind(udp_client4_sock, (struct sockaddr *)&sa, sizeof(sa)))
378 debugx(1, DBG_ERR, "addserver: failed to bind client socket for server %s", conf->host);
380 conf->servers->sock = udp_client4_sock;
383 if (udp_client6_sock < 0) {
384 struct sockaddr_in6 sa;
385 memset(&sa, 0, sizeof(sa));
386 sa.sin6_family = AF_INET6;
387 udp_client6_sock = socket(PF_INET6, conf->addrinfo->ai_socktype, conf->addrinfo->ai_protocol);
388 if (udp_client6_sock < 0)
389 debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
391 setsockopt(udp_client6_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on));
393 if (bind(udp_client6_sock, (struct sockaddr *)&sa, sizeof(sa)))
394 debugx(1, DBG_ERR, "addserver: failed to bind client socket for server %s", conf->host);
396 conf->servers->sock = udp_client6_sock;
399 debugx(1, DBG_ERR, "addserver: unsupported address family");
403 conf->servers->sock = -1;
405 pthread_mutex_init(&conf->servers->lock, NULL);
406 conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request));
407 if (!conf->servers->requests)
408 debugx(1, DBG_ERR, "malloc failed");
409 conf->servers->newrq = 0;
410 pthread_mutex_init(&conf->servers->newrq_mutex, NULL);
411 pthread_cond_init(&conf->servers->newrq_cond, NULL);
414 /* exactly one of client and server must be non-NULL */
415 /* should probably take peer list (client(s) or server(s)) as argument instead */
416 /* if *peer == NULL we return who we received from, else require it to be from peer */
417 /* return from in sa if not NULL */
418 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
420 unsigned char buf[65536], *rad;
421 struct sockaddr_storage from;
422 socklen_t fromlen = sizeof(from);
424 struct list_node *node;
427 cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
429 debug(DBG_WARN, "radudpget: recv failed");
432 debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
435 debug(DBG_WARN, "radudpget: packet too small");
441 debug(DBG_WARN, "radudpget: length too small");
446 debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
450 debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
454 p = find_conf('U', (struct sockaddr *)&from, NULL, (*client)->conf);
456 p = find_conf('U', (struct sockaddr *)&from, clconfs, NULL);
459 p = find_conf('U', (struct sockaddr *)&from, NULL, (*server)->conf);
461 p = find_conf('U', (struct sockaddr *)&from, srvconfs, NULL);
464 debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
470 debug(DBG_ERR, "radudpget: malloc failed");
474 if (client && !*client) {
475 node = list_first(p->clients);
476 *client = node ? (struct client *)node->data : addclient(p);
481 } else if (server && !*server)
482 *server = p->servers;
486 memcpy(rad, buf, len);
492 int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
493 int loc, i, l, n, r = 0;
496 STACK_OF(GENERAL_NAME) *alt;
499 debug(DBG_DBG, "subjectaltnameaddr");
501 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
505 ex = X509_get_ext(cert, loc);
506 alt = X509V3_EXT_d2i(ex);
510 n = sk_GENERAL_NAME_num(alt);
511 for (i = 0; i < n; i++) {
512 gn = sk_GENERAL_NAME_value(alt, i);
513 if (gn->type != GEN_IPADD)
516 v = (char *)ASN1_STRING_data(gn->d.ia5);
517 l = ASN1_STRING_length(gn->d.ia5);
518 if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
519 && !memcmp(v, &addr, l)) {
524 GENERAL_NAMES_free(alt);
528 int subjectaltnameregexp(X509 *cert, int type, char *exact, regex_t *regex) {
529 int loc, i, l, n, r = 0;
532 STACK_OF(GENERAL_NAME) *alt;
535 debug(DBG_DBG, "subjectaltnameregexp");
537 loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
541 ex = X509_get_ext(cert, loc);
542 alt = X509V3_EXT_d2i(ex);
546 n = sk_GENERAL_NAME_num(alt);
547 for (i = 0; i < n; i++) {
548 gn = sk_GENERAL_NAME_value(alt, i);
549 if (gn->type != type)
552 v = (char *)ASN1_STRING_data(gn->d.ia5);
553 l = ASN1_STRING_length(gn->d.ia5);
557 printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
560 if (memcmp(v, exact, l))
563 s = stringcopy((char *)v, l);
565 debug(DBG_ERR, "malloc failed");
568 if (regexec(regex, s, 0, NULL, 0)) {
577 GENERAL_NAMES_free(alt);
581 int tlsverifycert(SSL *ssl, struct clsrvconf *conf) {
588 uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
590 struct in6_addr addr;
592 if (SSL_get_verify_result(ssl) != X509_V_OK) {
593 debug(DBG_ERR, "tlsverifycert: basic validation failed");
594 while ((error = ERR_get_error()))
595 debug(DBG_ERR, "tlsverifycert: TLS: %s", ERR_error_string(error, NULL));
599 cert = SSL_get_peer_certificate(ssl);
601 debug(DBG_ERR, "tlsverifycert: failed to obtain certificate");
605 if (conf->prefixlen == 255) {
606 if (inet_pton(AF_INET, conf->host, &addr))
608 else if (inet_pton(AF_INET6, conf->host, &addr))
611 r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, conf->host, NULL);
615 debug(DBG_DBG, "tlsverifycert: No subjectaltname matching %s %s", type ? "address" : "host", conf->host);
618 debug(DBG_DBG, "tlsverifycert: Found subjectaltname matching %s %s", type ? "address" : "host", conf->host);
620 nm = X509_get_subject_name(cert);
623 loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
626 e = X509_NAME_get_entry(nm, loc);
627 s = X509_NAME_ENTRY_get_data(e);
628 v = (char *) ASN1_STRING_data(s);
629 l = ASN1_STRING_length(s);
633 printfchars(NULL, "cn", NULL, v, l);
635 if (l == strlen(conf->host) && !strncasecmp(conf->host, v, l)) {
637 debug(DBG_DBG, "tlsverifycert: Found cn matching host %s", conf->host);
643 debug(DBG_ERR, "tlsverifycert: cn not matching host %s", conf->host);
648 if (conf->certuriregex) {
649 r = subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex);
651 debug(DBG_DBG, "tlsverifycert: subjectaltname URI not matching regex");
655 debug(DBG_DBG, "tlsverifycert: subjectaltname URI matching regex");
661 void tlsconnect(struct server *server, struct timeval *when, char *text) {
665 debug(DBG_DBG, "tlsconnect called from %s", text);
666 pthread_mutex_lock(&server->lock);
667 if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
668 /* already reconnected, nothing to do */
669 debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
670 pthread_mutex_unlock(&server->lock);
674 debug(DBG_DBG, "tlsconnect %s", text);
677 gettimeofday(&now, NULL);
678 elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
679 if (server->connectionok) {
680 server->connectionok = 0;
682 } else if (elapsed < 5)
684 else if (elapsed < 300) {
685 debug(DBG_INFO, "tlsconnect: sleeping %lds", elapsed);
687 } else if (elapsed < 100000) {
688 debug(DBG_INFO, "tlsconnect: sleeping %ds", 600);
691 server->lastconnecttry.tv_sec = now.tv_sec; /* no sleep at startup */
692 debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->conf->host, server->conf->port);
693 if (server->sock >= 0)
695 if ((server->sock = connecttoserver(server->conf->addrinfo)) < 0) {
696 debug(DBG_ERR, "tlsconnect: connecttoserver failed");
700 SSL_free(server->ssl);
701 server->ssl = SSL_new(server->conf->ssl_ctx);
702 SSL_set_fd(server->ssl, server->sock);
703 if (SSL_connect(server->ssl) > 0 && tlsverifycert(server->ssl, server->conf))
706 debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
707 gettimeofday(&server->lastconnecttry, NULL);
708 pthread_mutex_unlock(&server->lock);
711 unsigned char *radtlsget(SSL *ssl) {
713 unsigned char buf[4], *rad;
716 for (total = 0; total < 4; total += cnt) {
717 cnt = SSL_read(ssl, buf + total, 4 - total);
719 debug(DBG_ERR, "radtlsget: connection lost");
720 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
721 /* remote end sent close_notify, send one back */
731 debug(DBG_ERR, "radtlsget: malloc failed");
736 for (; total < len; total += cnt) {
737 cnt = SSL_read(ssl, rad + total, len - total);
739 debug(DBG_ERR, "radtlsget: connection lost");
740 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
741 /* remote end sent close_notify, send one back */
753 debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
756 debug(DBG_DBG, "radtlsget: got %d bytes", total);
760 int clientradput(struct server *server, unsigned char *rad) {
764 struct timeval lastconnecttry;
765 struct clsrvconf *conf = server->conf;
768 if (conf->type == 'U') {
769 if (sendto(server->sock, rad, len, 0, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen) >= 0) {
770 debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, conf->host, conf->port);
773 debug(DBG_WARN, "clientradput: send failed");
777 lastconnecttry = server->lastconnecttry;
778 while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
779 while ((error = ERR_get_error()))
780 debug(DBG_ERR, "clientradput: TLS: %s", ERR_error_string(error, NULL));
781 tlsconnect(server, &lastconnecttry, "clientradput");
782 lastconnecttry = server->lastconnecttry;
785 server->connectionok = 1;
786 debug(DBG_DBG, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s", cnt, len, conf->host);
790 int radsign(unsigned char *rad, unsigned char *sec) {
791 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
792 static unsigned char first = 1;
793 static EVP_MD_CTX mdctx;
797 pthread_mutex_lock(&lock);
799 EVP_MD_CTX_init(&mdctx);
803 result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
804 EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
805 EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
806 EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
808 pthread_mutex_unlock(&lock);
812 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
813 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
814 static unsigned char first = 1;
815 static EVP_MD_CTX mdctx;
816 unsigned char hash[EVP_MAX_MD_SIZE];
820 pthread_mutex_lock(&lock);
822 EVP_MD_CTX_init(&mdctx);
828 result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
829 EVP_DigestUpdate(&mdctx, rad, 4) &&
830 EVP_DigestUpdate(&mdctx, reqauth, 16) &&
831 (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
832 EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
833 EVP_DigestFinal_ex(&mdctx, hash, &len) &&
835 !memcmp(hash, rad + 4, 16));
836 pthread_mutex_unlock(&lock);
840 int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
841 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
842 static unsigned char first = 1;
843 static HMAC_CTX hmacctx;
845 uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
847 pthread_mutex_lock(&lock);
849 HMAC_CTX_init(&hmacctx);
853 memcpy(auth, authattr, 16);
854 memset(authattr, 0, 16);
856 HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
857 HMAC_Update(&hmacctx, rad, RADLEN(rad));
858 HMAC_Final(&hmacctx, hash, &md_len);
859 memcpy(authattr, auth, 16);
861 debug(DBG_WARN, "message auth computation failed");
862 pthread_mutex_unlock(&lock);
866 if (memcmp(auth, hash, 16)) {
867 debug(DBG_WARN, "message authenticator, wrong value");
868 pthread_mutex_unlock(&lock);
872 pthread_mutex_unlock(&lock);
876 int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secret) {
877 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
878 static unsigned char first = 1;
879 static HMAC_CTX hmacctx;
885 pthread_mutex_lock(&lock);
887 HMAC_CTX_init(&hmacctx);
891 memset(authattrval, 0, 16);
893 HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
894 HMAC_Update(&hmacctx, rad, RADLEN(rad));
895 HMAC_Final(&hmacctx, authattrval, &md_len);
897 debug(DBG_WARN, "message auth computation failed");
898 pthread_mutex_unlock(&lock);
902 pthread_mutex_unlock(&lock);
906 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
908 if (ATTRTYPE(attrs) == type)
910 length -= ATTRLEN(attrs);
911 attrs += ATTRLEN(attrs);
916 void freerqdata(struct request *rq) {
917 if (rq->origusername)
918 free(rq->origusername);
923 void sendrq(struct server *to, struct request *rq) {
927 pthread_mutex_lock(&to->newrq_mutex);
928 /* might simplify if only try nextid, might be ok */
929 for (i = to->nextid; i < MAX_REQUESTS; i++)
930 if (!to->requests[i].buf)
932 if (i == MAX_REQUESTS) {
933 for (i = 0; i < to->nextid; i++)
934 if (!to->requests[i].buf)
936 if (i == to->nextid) {
937 debug(DBG_WARN, "No room in queue, dropping request");
939 pthread_mutex_unlock(&to->newrq_mutex);
944 rq->buf[1] = (char)i;
946 attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
947 if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->conf->secret)) {
949 pthread_mutex_unlock(&to->newrq_mutex);
953 debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host);
954 to->requests[i] = *rq;
959 debug(DBG_DBG, "signalling client writer");
960 pthread_cond_signal(&to->newrq_cond);
962 pthread_mutex_unlock(&to->newrq_mutex);
965 void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
969 if (!radsign(buf, (unsigned char *)to->conf->secret)) {
971 debug(DBG_WARN, "sendreply: failed to sign message");
975 reply = malloc(sizeof(struct reply));
978 debug(DBG_ERR, "sendreply: malloc failed");
981 memset(reply, 0, sizeof(struct reply));
986 pthread_mutex_lock(&to->replyq->mutex);
988 first = list_first(to->replyq->replies) == NULL;
990 if (!list_push(to->replyq->replies, reply)) {
991 pthread_mutex_unlock(&to->replyq->mutex);
994 debug(DBG_ERR, "sendreply: malloc failed");
999 debug(DBG_DBG, "signalling server writer");
1000 pthread_cond_signal(&to->replyq->cond);
1002 pthread_mutex_unlock(&to->replyq->mutex);
1005 int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1006 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1007 static unsigned char first = 1;
1008 static EVP_MD_CTX mdctx;
1009 unsigned char hash[EVP_MAX_MD_SIZE], *input;
1010 unsigned int md_len;
1011 uint8_t i, offset = 0, out[128];
1013 pthread_mutex_lock(&lock);
1015 EVP_MD_CTX_init(&mdctx);
1021 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1022 !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1023 !EVP_DigestUpdate(&mdctx, input, 16) ||
1024 !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1026 pthread_mutex_unlock(&lock);
1029 for (i = 0; i < 16; i++)
1030 out[offset + i] = hash[i] ^ in[offset + i];
1031 input = out + offset - 16;
1036 memcpy(in, out, len);
1037 pthread_mutex_unlock(&lock);
1041 int pwddecrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1042 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1043 static unsigned char first = 1;
1044 static EVP_MD_CTX mdctx;
1045 unsigned char hash[EVP_MAX_MD_SIZE], *input;
1046 unsigned int md_len;
1047 uint8_t i, offset = 0, out[128];
1049 pthread_mutex_lock(&lock);
1051 EVP_MD_CTX_init(&mdctx);
1057 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1058 !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1059 !EVP_DigestUpdate(&mdctx, input, 16) ||
1060 !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1062 pthread_mutex_unlock(&lock);
1065 for (i = 0; i < 16; i++)
1066 out[offset + i] = hash[i] ^ in[offset + i];
1067 input = in + offset;
1072 memcpy(in, out, len);
1073 pthread_mutex_unlock(&lock);
1077 int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1078 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1079 static unsigned char first = 1;
1080 static EVP_MD_CTX mdctx;
1081 unsigned char hash[EVP_MAX_MD_SIZE];
1082 unsigned int md_len;
1085 pthread_mutex_lock(&lock);
1087 EVP_MD_CTX_init(&mdctx);
1092 printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16);
1093 printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2);
1094 printfchars(NULL, "msppencrypt in", "%02x ", text, len);
1097 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1098 !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1099 !EVP_DigestUpdate(&mdctx, auth, 16) ||
1100 !EVP_DigestUpdate(&mdctx, salt, 2) ||
1101 !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1102 pthread_mutex_unlock(&lock);
1107 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1110 for (i = 0; i < 16; i++)
1113 for (offset = 16; offset < len; offset += 16) {
1115 printf("text + offset - 16 c(%d): ", offset / 16);
1116 printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1118 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1119 !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1120 !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1121 !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1123 pthread_mutex_unlock(&lock);
1127 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1130 for (i = 0; i < 16; i++)
1131 text[offset + i] ^= hash[i];
1135 printfchars(NULL, "msppencrypt out", "%02x ", text, len);
1138 pthread_mutex_unlock(&lock);
1142 int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1143 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1144 static unsigned char first = 1;
1145 static EVP_MD_CTX mdctx;
1146 unsigned char hash[EVP_MAX_MD_SIZE];
1147 unsigned int md_len;
1151 pthread_mutex_lock(&lock);
1153 EVP_MD_CTX_init(&mdctx);
1158 printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16);
1159 printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2);
1160 printfchars(NULL, "msppdecrypt in", "%02x ", text, len);
1163 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1164 !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1165 !EVP_DigestUpdate(&mdctx, auth, 16) ||
1166 !EVP_DigestUpdate(&mdctx, salt, 2) ||
1167 !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1168 pthread_mutex_unlock(&lock);
1173 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1176 for (i = 0; i < 16; i++)
1177 plain[i] = text[i] ^ hash[i];
1179 for (offset = 16; offset < len; offset += 16) {
1181 printf("text + offset - 16 c(%d): ", offset / 16);
1182 printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1184 if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1185 !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1186 !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1187 !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1189 pthread_mutex_unlock(&lock);
1193 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1196 for (i = 0; i < 16; i++)
1197 plain[offset + i] = text[offset + i] ^ hash[i];
1200 memcpy(text, plain, len);
1202 printfchars(NULL, "msppdecrypt out", "%02x ", text, len);
1205 pthread_mutex_unlock(&lock);
1209 struct realm *id2realm(char *id, uint8_t len) {
1210 struct list_node *entry;
1211 struct realm *realm;
1213 for (entry = list_first(realms); entry; entry = list_next(entry)) {
1214 realm = (struct realm *)entry->data;
1215 if (!regexec(&realm->regex, id, 0, NULL, 0)) {
1216 debug(DBG_DBG, "found matching realm: %s", realm->name);
1223 int rqinqueue(struct server *to, struct client *from, uint8_t id) {
1226 pthread_mutex_lock(&to->newrq_mutex);
1227 for (i = 0; i < MAX_REQUESTS; i++)
1228 if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from)
1230 pthread_mutex_unlock(&to->newrq_mutex);
1232 return i < MAX_REQUESTS;
1235 int attrvalidate(unsigned char *attrs, int length) {
1236 while (length > 1) {
1237 if (ATTRLEN(attrs) < 2) {
1238 debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1241 length -= ATTRLEN(attrs);
1243 debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1246 attrs += ATTRLEN(attrs);
1249 debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1253 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1254 if (len < 16 || len > 128 || len % 16) {
1255 debug(DBG_WARN, "pwdrecrypt: invalid password length");
1259 if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1260 debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1264 printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len);
1266 if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1267 debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1273 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1276 if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1277 debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1280 if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1281 debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1287 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1288 char *oldsecret, char *newsecret) {
1289 unsigned char *attr;
1291 for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1292 debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1293 if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1299 /* returns a pointer to the resized attribute value */
1300 uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) {
1301 uint8_t *attrs, *attr, vallen;
1305 len = RADLEN(*buf) - 20;
1308 attr = attrget(attrs, len, type);
1312 vallen = ATTRVALLEN(attr);
1313 if (vallen == newvallen)
1316 len += newvallen - vallen;
1317 if (newvallen > vallen) {
1318 new = realloc(*buf, len);
1320 debug(DBG_ERR, "resizeattr: malloc failed");
1329 memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen));
1330 attr[1] = newvallen + 2;
1331 ((uint16_t *)*buf)[1] = htons(len + 20);
1335 int rewriteusername(struct request *rq, char *in) {
1336 size_t nmatch = 10, reslen = 0, start = 0;
1337 regmatch_t pmatch[10], *pfield;
1339 unsigned char *result;
1340 char *out = rq->from->conf->rewriteattrreplacement;
1342 if (regexec(rq->from->conf->rewriteattrregex, in, nmatch, pmatch, 0)) {
1343 debug(DBG_DBG, "rewriteattr: username not matching, no rewrite");
1347 rq->origusername = stringcopy(in, 0);
1348 if (!rq->origusername)
1351 for (i = start; out[i]; i++) {
1352 if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1353 pfield = &pmatch[out[i + 1] - '0'];
1354 if (pfield->rm_so >= 0) {
1355 reslen += i - start + pfield->rm_eo - pfield->rm_so;
1361 reslen += i - start;
1363 result = resizeattr(&rq->buf, reslen, RAD_Attr_User_Name);
1369 for (i = start; out[i]; i++) {
1370 if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1371 pfield = &pmatch[out[i + 1] - '0'];
1372 if (pfield->rm_so >= 0) {
1373 memcpy(result + reslen, out + start, i - start);
1374 reslen += i - start;
1375 memcpy(result + reslen, in + pfield->rm_so, pfield->rm_eo - pfield->rm_so);
1376 reslen += pfield->rm_eo - pfield->rm_so;
1383 memcpy(result + reslen, out + start, i - start);
1384 reslen += i - start;
1385 memcpy(in, result, reslen);
1390 char *parsehostport(char *s, struct clsrvconf *conf) {
1395 /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
1399 for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1401 debugx(1, DBG_ERR, "no ] matching initial [");
1405 for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1408 debugx(1, DBG_ERR, "missing host/address");
1410 conf->host = stringcopy(field, p - field);
1413 if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
1414 debugx(1, DBG_ERR, "unexpected character after ]");
1417 /* port number or service name is specified */;
1419 for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1421 debugx(1, DBG_ERR, "syntax error, : but no following port");
1422 conf->port = stringcopy(field, p - field);
1424 conf->port = stringcopy(conf->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
1428 struct clsrvconf *resolve_hostport(char type, char *lconf) {
1429 struct clsrvconf *conf;
1431 conf = malloc(sizeof(struct clsrvconf));
1433 debugx(1, DBG_ERR, "malloc failed");
1434 memset(conf, 0, sizeof(struct clsrvconf));
1437 parsehostport(lconf, conf);
1438 if (!strcmp(conf->host, "*")) {
1443 conf->port = stringcopy(type == 'T' ? DEFAULT_TLS_PORT : DEFAULT_UDP_PORT, 0);
1444 if (!resolvepeer(conf, AI_PASSIVE))
1445 debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
1449 void acclog(unsigned char *attrs, int length, char *host) {
1450 unsigned char *attr;
1453 attr = attrget(attrs, length, RAD_Attr_User_Name);
1455 debug(DBG_INFO, "acclog: accounting-request from %s without username attribute", host);
1458 memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1459 username[ATTRVALLEN(attr)] = '\0';
1460 debug(DBG_INFO, "acclog: accounting-request from %s with username: %s", host, username);
1463 void respondaccounting(struct request *rq) {
1464 unsigned char *resp;
1468 debug(DBG_ERR, "respondstatusserver: malloc failed");
1471 memcpy(resp, rq->buf, 20);
1472 resp[0] = RAD_Accounting_Response;
1475 debug(DBG_DBG, "respondaccounting: responding to %s", rq->from->conf->host);
1476 sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1479 void respondstatusserver(struct request *rq) {
1480 unsigned char *resp;
1484 debug(DBG_ERR, "respondstatusserver: malloc failed");
1487 memcpy(resp, rq->buf, 20);
1488 resp[0] = RAD_Access_Accept;
1491 debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
1492 sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1495 void respondreject(struct request *rq, char *message) {
1496 unsigned char *resp;
1499 if (message && *message)
1500 len += 2 + strlen(message);
1504 debug(DBG_ERR, "respondreject: malloc failed");
1507 memcpy(resp, rq->buf, 20);
1508 resp[0] = RAD_Access_Reject;
1509 *(uint16_t *)(resp + 2) = htons(len);
1510 if (message && *message) {
1511 resp[20] = RAD_Attr_Reply_Message;
1512 resp[21] = len - 20;
1513 memcpy(resp + 22, message, len - 22);
1515 sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1518 struct server *realm2server(struct realm *realm) {
1519 struct list_node *entry;
1520 struct server *server, *best = NULL;
1522 for (entry = list_first(realm->srvconfs); entry; entry = list_next(entry)) {
1523 server = ((struct clsrvconf *)entry->data)->servers;
1524 if (!server->connectionok)
1526 if (!server->loststatsrv)
1532 if (server->loststatsrv < best->loststatsrv)
1538 void radsrv(struct request *rq) {
1539 uint8_t code, id, *auth, *attrs, *attr;
1541 struct server *to = NULL;
1543 unsigned char newauth[16];
1544 struct realm *realm = NULL;
1546 code = *(uint8_t *)rq->buf;
1547 id = *(uint8_t *)(rq->buf + 1);
1548 len = RADLEN(rq->buf);
1549 auth = (uint8_t *)(rq->buf + 4);
1551 debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
1553 if (code != RAD_Access_Request && code != RAD_Status_Server && code != RAD_Accounting_Request) {
1554 debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring");
1560 attrs = rq->buf + 20;
1562 if (!attrvalidate(attrs, len)) {
1563 debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
1568 attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1569 if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(rq->buf, ATTRVAL(attr), rq->from->conf->secret))) {
1570 debug(DBG_WARN, "radsrv: message authentication failed");
1575 if (code != RAD_Access_Request) {
1577 case RAD_Accounting_Request:
1578 acclog(attrs, len, rq->from->conf->host);
1579 respondaccounting(rq);
1581 case RAD_Status_Server:
1582 respondstatusserver(rq);
1589 /* code == RAD_Access_Request */
1590 attr = attrget(attrs, len, RAD_Attr_User_Name);
1592 debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
1596 memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1597 username[ATTRVALLEN(attr)] = '\0';
1599 if (rq->from->conf->rewriteattrregex) {
1600 if (!rewriteusername(rq, username)) {
1601 debug(DBG_WARN, "radsrv: username malloc failed, ignoring request");
1605 len = RADLEN(rq->buf) - 20;
1606 auth = (uint8_t *)(rq->buf + 4);
1607 attrs = rq->buf + 20;
1610 if (rq->origusername)
1611 debug(DBG_DBG, "Access Request with username: %s (originally %s)", username, rq->origusername);
1613 debug(DBG_DBG, "Access Request with username: %s", username);
1615 realm = id2realm(username, strlen(username));
1617 debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1622 to = realm2server(realm);
1623 if (to && rqinqueue(to, rq->from, id)) {
1624 debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->conf->host, id);
1630 if (realm->message) {
1631 debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->conf->host, username);
1632 respondreject(rq, realm->message);
1638 if (!RAND_bytes(newauth, 16)) {
1639 debug(DBG_WARN, "radsrv: failed to generate random auth");
1645 printfchars(NULL, "auth", "%02x ", auth, 16);
1648 attr = attrget(attrs, len, RAD_Attr_User_Password);
1650 debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1651 if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1657 attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1659 debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1660 if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1667 memcpy(rq->origauth, auth, 16);
1668 memcpy(auth, newauth, 16);
1672 int replyh(struct server *server, unsigned char *buf) {
1673 struct client *from;
1676 unsigned char *messageauth, *subattrs, *attrs, *attr, *username;
1677 struct sockaddr_storage fromsa;
1680 server->connectionok = 1;
1681 server->loststatsrv = 0;
1683 i = buf[1]; /* i is the id */
1686 case RAD_Access_Accept:
1687 debug(DBG_DBG, "got Access Accept with id %d", i);
1689 case RAD_Access_Reject:
1690 debug(DBG_DBG, "got Access Reject with id %d", i);
1692 case RAD_Access_Challenge:
1693 debug(DBG_DBG, "got Access Challenge with id %d", i);
1696 debug(DBG_INFO, "replyh: discarding, only accept access accept, access reject and access challenge messages");
1700 rq = server->requests + i;
1702 pthread_mutex_lock(&server->newrq_mutex);
1703 if (!rq->buf || !rq->tries) {
1704 pthread_mutex_unlock(&server->newrq_mutex);
1705 debug(DBG_INFO, "replyh: no matching request sent with this id, ignoring reply");
1710 pthread_mutex_unlock(&server->newrq_mutex);
1711 debug(DBG_INFO, "replyh: already received, ignoring reply");
1715 if (!validauth(buf, rq->buf + 4, (unsigned char *)server->conf->secret)) {
1716 pthread_mutex_unlock(&server->newrq_mutex);
1717 debug(DBG_WARN, "replyh: invalid auth, ignoring reply");
1722 len = RADLEN(buf) - 20;
1725 if (!attrvalidate(attrs, len)) {
1726 pthread_mutex_unlock(&server->newrq_mutex);
1727 debug(DBG_WARN, "replyh: attribute validation failed, ignoring reply");
1731 /* Message Authenticator */
1732 messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1734 if (ATTRVALLEN(messageauth) != 16) {
1735 pthread_mutex_unlock(&server->newrq_mutex);
1736 debug(DBG_WARN, "replyh: illegal message auth attribute length, ignoring reply");
1739 memcpy(tmp, buf + 4, 16);
1740 memcpy(buf + 4, rq->buf + 4, 16);
1741 if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
1742 pthread_mutex_unlock(&server->newrq_mutex);
1743 debug(DBG_WARN, "replyh: message authentication failed, ignoring reply");
1746 memcpy(buf + 4, tmp, 16);
1747 debug(DBG_DBG, "replyh: message auth ok");
1750 if (*rq->buf == RAD_Status_Server) {
1752 pthread_mutex_unlock(&server->newrq_mutex);
1753 debug(DBG_INFO, "replyh: got status server response from %s", server->conf->host);
1758 for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
1759 if (ATTRVALLEN(attr) <= 4)
1762 if (attr[2] != 0 || attr[3] != 0 || attr[4] != 1 || attr[5] != 55) /* 311 == MS */
1765 sublen = ATTRVALLEN(attr) - 4;
1766 subattrs = ATTRVAL(attr) + 4;
1767 if (!attrvalidate(subattrs, sublen) ||
1768 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1769 rq, server->conf->secret, from->conf->secret) ||
1770 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1771 rq, server->conf->secret, from->conf->secret))
1775 pthread_mutex_unlock(&server->newrq_mutex);
1776 debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
1780 if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject) {
1781 attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_User_Name);
1782 /* we know the attribute exists */
1783 memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
1784 tmp[ATTRVALLEN(attr)] = '\0';
1786 case RAD_Access_Accept:
1787 if (rq->origusername)
1788 debug(DBG_INFO, "Access Accept for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1790 debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->conf->host);
1792 case RAD_Access_Reject:
1793 if (rq->origusername)
1794 debug(DBG_INFO, "Access Reject for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1796 debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->conf->host);
1801 buf[1] = (char)rq->origid;
1802 memcpy(buf + 4, rq->origauth, 16);
1804 printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
1807 if (rq->origusername) {
1808 username = resizeattr(&buf, strlen(rq->origusername), RAD_Attr_User_Name);
1810 pthread_mutex_unlock(&server->newrq_mutex);
1811 debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
1814 memcpy(username, rq->origusername, strlen(rq->origusername));
1815 len = RADLEN(buf) - 20;
1818 messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1822 if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
1823 pthread_mutex_unlock(&server->newrq_mutex);
1824 debug(DBG_WARN, "replyh: failed to create authenticator, malloc failed?, ignoring reply");
1827 debug(DBG_DBG, "replyh: computed messageauthattr");
1830 if (from->conf->type == 'U')
1831 fromsa = rq->fromsa;
1832 /* once we set received = 1, rq may be reused */
1834 pthread_mutex_unlock(&server->newrq_mutex);
1836 debug(DBG_DBG, "replyh: giving packet back to where it came from");
1837 sendreply(from, buf, from->conf->type == 'U' ? &fromsa : NULL);
1841 void *udpclientrd(void *arg) {
1842 struct server *server;
1844 int *s = (int *)arg;
1848 buf = radudpget(*s, NULL, &server, NULL);
1849 if (!replyh(server, buf))
1854 void *tlsclientrd(void *arg) {
1855 struct server *server = (struct server *)arg;
1857 struct timeval lastconnecttry;
1860 /* yes, lastconnecttry is really necessary */
1861 lastconnecttry = server->lastconnecttry;
1862 buf = radtlsget(server->ssl);
1864 tlsconnect(server, &lastconnecttry, "clientrd");
1868 if (!replyh(server, buf))
1873 void *clientwr(void *arg) {
1874 struct server *server = (struct server *)arg;
1876 pthread_t tlsclientrdth;
1879 struct timeval now, lastsend;
1880 struct timespec timeout;
1881 struct request statsrvrq;
1882 unsigned char statsrvbuf[38];
1884 memset(&timeout, 0, sizeof(struct timespec));
1886 if (server->conf->statusserver) {
1887 memset(&statsrvrq, 0, sizeof(struct request));
1888 memset(statsrvbuf, 0, sizeof(statsrvbuf));
1889 statsrvbuf[0] = RAD_Status_Server;
1891 statsrvbuf[20] = RAD_Attr_Message_Authenticator;
1892 statsrvbuf[21] = 18;
1893 gettimeofday(&lastsend, NULL);
1896 if (server->conf->type == 'U') {
1897 server->connectionok = 1;
1899 tlsconnect(server, NULL, "new client");
1900 server->connectionok = 1;
1901 if (pthread_create(&tlsclientrdth, NULL, tlsclientrd, (void *)server))
1902 debugx(1, DBG_ERR, "clientwr: pthread_create failed");
1906 pthread_mutex_lock(&server->newrq_mutex);
1907 if (!server->newrq) {
1908 gettimeofday(&now, NULL);
1909 if (server->conf->statusserver) {
1910 /* random 0-7 seconds */
1911 RAND_bytes(&rnd, 1);
1913 if (!timeout.tv_sec || timeout.tv_sec - now.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
1914 timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
1916 if (timeout.tv_sec) {
1917 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1918 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1921 debug(DBG_DBG, "clientwr: waiting for new request");
1922 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
1925 if (server->newrq) {
1926 debug(DBG_DBG, "clientwr: got new request");
1929 debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1930 pthread_mutex_unlock(&server->newrq_mutex);
1932 for (i = 0; i < MAX_REQUESTS; i++) {
1933 pthread_mutex_lock(&server->newrq_mutex);
1934 while (i < MAX_REQUESTS && !server->requests[i].buf)
1936 if (i == MAX_REQUESTS) {
1937 pthread_mutex_unlock(&server->newrq_mutex);
1940 rq = server->requests + i;
1943 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
1945 debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
1947 /* setting this to NULL means that it can be reused */
1950 pthread_mutex_unlock(&server->newrq_mutex);
1954 gettimeofday(&now, NULL);
1955 if (now.tv_sec < rq->expiry.tv_sec) {
1956 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1957 timeout.tv_sec = rq->expiry.tv_sec;
1958 pthread_mutex_unlock(&server->newrq_mutex);
1962 if (rq->tries == (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1963 ? 1 : REQUEST_RETRIES)) {
1964 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1965 if (*rq->buf == RAD_Status_Server) {
1966 debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->conf->host);
1967 if (server->loststatsrv < 255)
1968 server->loststatsrv++;
1971 /* setting this to NULL means that it can be reused */
1973 pthread_mutex_unlock(&server->newrq_mutex);
1976 pthread_mutex_unlock(&server->newrq_mutex);
1978 rq->expiry.tv_sec = now.tv_sec +
1979 (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1980 ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
1981 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1982 timeout.tv_sec = rq->expiry.tv_sec;
1984 clientradput(server, server->requests[i].buf);
1985 gettimeofday(&lastsend, NULL);
1987 if (server->conf->statusserver) {
1988 gettimeofday(&now, NULL);
1989 if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
1990 if (!RAND_bytes(statsrvbuf + 4, 16)) {
1991 debug(DBG_WARN, "clientwr: failed to generate random auth");
1994 statsrvrq.buf = malloc(sizeof(statsrvbuf));
1995 if (!statsrvrq.buf) {
1996 debug(DBG_ERR, "clientwr: malloc failed");
1999 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
2000 debug(DBG_DBG, "clientwr: sending status server to %s", server->conf->host);
2001 lastsend.tv_sec = now.tv_sec;
2002 sendrq(server, &statsrvrq);
2008 void *udpserverwr(void *arg) {
2009 struct replyq *replyq = udp_server_replyq;
2010 struct reply *reply;
2013 pthread_mutex_lock(&replyq->mutex);
2014 while (!(reply = (struct reply *)list_shift(replyq->replies))) {
2015 debug(DBG_DBG, "udp server writer, waiting for signal");
2016 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2017 debug(DBG_DBG, "udp server writer, got signal");
2019 pthread_mutex_unlock(&replyq->mutex);
2021 if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
2022 (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
2023 debug(DBG_WARN, "sendudp: send failed");
2029 void *udpserverrd(void *arg) {
2031 pthread_t udpserverwrth;
2032 struct clsrvconf *listenres;
2034 listenres = resolve_hostport('U', options.listenudp);
2035 if ((udp_server_sock = bindtoaddr(listenres->addrinfo)) < 0)
2036 debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2038 debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
2039 listenres->host ? listenres->host : "*", listenres->port);
2042 if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
2043 debugx(1, DBG_ERR, "pthread_create failed");
2046 memset(&rq, 0, sizeof(struct request));
2047 rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
2052 void *udpaccserverrd(void *arg) {
2054 struct clsrvconf *listenres;
2056 listenres = resolve_hostport('U', options.listenaccudp);
2057 if ((udp_accserver_sock = bindtoaddr(listenres->addrinfo)) < 0)
2058 debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2060 debug(DBG_WARN, "udpaccserverrd: listening for UDP on %s:%s",
2061 listenres->host ? listenres->host : "*", listenres->port);
2065 memset(&rq, 0, sizeof(struct request));
2066 rq.buf = radudpget(udp_accserver_sock, &rq.from, NULL, &rq.fromsa);
2067 if (*(uint8_t *)rq.buf == RAD_Accounting_Request) {
2071 debug(DBG_INFO, "udpaccserverrd: got something other than accounting-request, ignoring");
2076 void *tlsserverwr(void *arg) {
2078 unsigned long error;
2079 struct client *client = (struct client *)arg;
2080 struct replyq *replyq;
2081 struct reply *reply;
2083 debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
2084 replyq = client->replyq;
2086 pthread_mutex_lock(&replyq->mutex);
2087 while (!list_first(replyq->replies)) {
2089 debug(DBG_DBG, "tls server writer, waiting for signal");
2090 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2091 debug(DBG_DBG, "tls server writer, got signal");
2094 /* ssl might have changed while waiting */
2095 pthread_mutex_unlock(&replyq->mutex);
2096 debug(DBG_DBG, "tlsserverwr: exiting as requested");
2100 reply = (struct reply *)list_shift(replyq->replies);
2101 pthread_mutex_unlock(&replyq->mutex);
2102 cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
2104 debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
2105 cnt, RADLEN(reply->buf));
2107 while ((error = ERR_get_error()))
2108 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
2114 void *tlsserverrd(void *arg) {
2116 unsigned long error;
2118 struct client *client = (struct client *)arg;
2119 pthread_t tlsserverwrth;
2122 debug(DBG_DBG, "tlsserverrd starting for %s", client->conf->host);
2125 if (SSL_accept(ssl) <= 0) {
2126 while ((error = ERR_get_error()))
2127 debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
2128 debug(DBG_ERR, "SSL_accept failed");
2131 if (tlsverifycert(client->ssl, client->conf)) {
2132 if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
2133 debug(DBG_ERR, "tlsserverrd: pthread_create failed");
2137 memset(&rq, 0, sizeof(struct request));
2138 rq.buf = radtlsget(client->ssl);
2141 debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
2145 debug(DBG_ERR, "tlsserverrd: connection lost");
2146 /* stop writer by setting ssl to NULL and give signal in case waiting for data */
2148 pthread_mutex_lock(&client->replyq->mutex);
2149 pthread_cond_signal(&client->replyq->cond);
2150 pthread_mutex_unlock(&client->replyq->mutex);
2151 debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
2152 pthread_join(tlsserverwrth, NULL);
2156 s = SSL_get_fd(ssl);
2158 shutdown(s, SHUT_RDWR);
2160 debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->conf->host);
2161 removeclient(client);
2166 pthread_t tlsserverth;
2168 struct sockaddr_storage from;
2169 size_t fromlen = sizeof(from);
2170 struct clsrvconf *conf;
2171 struct client *client;
2172 struct clsrvconf *listenres;
2174 listenres = resolve_hostport('T', options.listentcp);
2175 if ((s = bindtoaddr(listenres->addrinfo)) < 0)
2176 debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
2179 debug(DBG_WARN, "listening for incoming TCP on %s:%s", listenres->host ? listenres->host : "*", listenres->port);
2183 snew = accept(s, (struct sockaddr *)&from, &fromlen);
2185 debug(DBG_WARN, "accept failed");
2188 debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
2190 conf = find_conf('T', (struct sockaddr *)&from, clconfs, NULL);
2192 debug(DBG_WARN, "ignoring request, not a known TLS client");
2193 shutdown(snew, SHUT_RDWR);
2198 client = addclient(conf);
2201 debug(DBG_WARN, "Failed to create new client instance");
2202 shutdown(snew, SHUT_RDWR);
2206 client->ssl = SSL_new(client->conf->ssl_ctx);
2207 SSL_set_fd(client->ssl, snew);
2208 if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
2209 debug(DBG_ERR, "tlslistener: pthread_create failed");
2210 SSL_free(client->ssl);
2211 removeclient(client);
2212 shutdown(snew, SHUT_RDWR);
2216 pthread_detach(tlsserverth);
2221 void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, char *certkeyfile, char *certkeypwd) {
2225 unsigned long error;
2227 if (!certfile || !certkeyfile)
2228 debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified in TLS context %s", value);
2230 if (!cacertfile && !cacertpath)
2231 debugx(1, DBG_ERR, "CA Certificate file or path need to be specified in TLS context %s", value);
2234 ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
2235 ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
2236 for (i = 0; i < CRYPTO_num_locks(); i++) {
2237 ssl_lock_count[i] = 0;
2238 pthread_mutex_init(&ssl_locks[i], NULL);
2240 CRYPTO_set_id_callback(ssl_thread_id);
2241 CRYPTO_set_locking_callback(ssl_locking_callback);
2243 SSL_load_error_strings();
2246 while (!RAND_status()) {
2247 time_t t = time(NULL);
2248 pid_t pid = getpid();
2249 RAND_seed((unsigned char *)&t, sizeof(time_t));
2250 RAND_seed((unsigned char *)&pid, sizeof(pid));
2253 ctx = SSL_CTX_new(TLSv1_method());
2255 SSL_CTX_set_default_passwd_cb_userdata(ctx, certkeypwd);
2256 SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
2258 if (!SSL_CTX_use_certificate_chain_file(ctx, certfile) ||
2259 !SSL_CTX_use_PrivateKey_file(ctx, certkeyfile, SSL_FILETYPE_PEM) ||
2260 !SSL_CTX_check_private_key(ctx) ||
2261 !SSL_CTX_load_verify_locations(ctx, cacertfile, cacertpath)) {
2262 while ((error = ERR_get_error()))
2263 debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2264 debugx(1, DBG_ERR, "Error initialising SSL/TLS in TLS context %s", value);
2267 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
2268 SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
2270 new = malloc(sizeof(struct tls));
2271 if (!new || !list_push(tlsconfs, new))
2272 debugx(1, DBG_ERR, "malloc failed");
2274 memset(new, 0, sizeof(struct tls));
2275 new->name = stringcopy(value, 0);
2277 debugx(1, DBG_ERR, "malloc failed");
2280 debug(DBG_DBG, "tlsadd: added TLS context %s", value);
2284 struct list_node *entry;
2287 for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2288 t = (struct tls *)entry->data;
2292 SSL_CTX_free(t->ctx);
2294 list_destroy(tlsconfs);
2298 SSL_CTX *tlsgetctx(char *alt1, char *alt2) {
2299 struct list_node *entry;
2300 struct tls *t, *t1 = NULL, *t2 = NULL;
2302 for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2303 t = (struct tls *)entry->data;
2304 if (!strcasecmp(t->name, alt1)) {
2308 if (!t2 && alt2 && !strcasecmp(t->name, alt2))
2319 void addrealm(char *value, char **servers, char *message) {
2321 struct realm *realm;
2322 char *s, *regex = NULL;
2323 struct list_node *entry;
2324 struct clsrvconf *conf;
2326 if (*value == '/') {
2327 /* regexp, remove optional trailing / if present */
2328 if (value[strlen(value) - 1] == '/')
2329 value[strlen(value) - 1] = '\0';
2331 /* not a regexp, let us make it one */
2332 if (*value == '*' && !value[1])
2333 regex = stringcopy(".*", 0);
2335 for (n = 0, s = value; *s;)
2338 regex = malloc(strlen(value) + n + 3);
2341 for (n = 1, s = value; *s; s++) {
2351 debugx(1, DBG_ERR, "malloc failed");
2352 debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
2355 realm = malloc(sizeof(struct realm));
2357 debugx(1, DBG_ERR, "malloc failed");
2359 memset(realm, 0, sizeof(struct realm));
2360 realm->name = stringcopy(value, 0);
2362 debugx(1, DBG_ERR, "malloc failed");
2363 if (message && strlen(message) > 253)
2364 debugx(1, DBG_ERR, "ReplyMessage can be at most 253 bytes");
2365 realm->message = message;
2367 if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
2368 debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
2372 if (servers && *servers) {
2373 realm->srvconfs = list_create();
2374 if (!realm->srvconfs)
2375 debugx(1, DBG_ERR, "malloc failed");
2376 for (n = 0; servers[n]; n++) {
2377 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2378 conf = (struct clsrvconf *)entry->data;
2379 if (!strcasecmp(servers[n], conf->name))
2383 debugx(1, DBG_ERR, "addrealm failed, no server %s", servers[n]);
2384 if (!list_push(realm->srvconfs, conf))
2385 debugx(1, DBG_ERR, "malloc failed");
2386 debug(DBG_DBG, "addrealm: added server %s for realm %s", conf->name, value);
2389 realm->srvconfs = NULL;
2391 if (!list_push(realms, realm))
2392 debugx(1, DBG_ERR, "malloc failed");
2393 debug(DBG_DBG, "addrealm: added realm %s", value);
2396 FILE *openconfigfile(const char *filename) {
2398 char pathname[100], *base = NULL;
2400 f = fopen(filename, "r");
2402 debug(DBG_DBG, "reading config file %s", filename);
2406 if (strlen(filename) + 1 <= sizeof(pathname)) {
2407 /* basename() might modify the string */
2408 strcpy(pathname, filename);
2409 base = basename(pathname);
2410 f = fopen(base, "r");
2414 debugx(1, DBG_ERR, "could not read config file %s nor %s\n%s", filename, base, strerror(errno));
2416 debug(DBG_DBG, "reading config file %s", base);
2420 /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */
2421 char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) {
2422 char *t = s, *q, *r;
2424 if (!t || !token || !del)
2426 while (*t && strchr(del, *t))
2428 if (!*t || (comment && strchr(comment, *t))) {
2430 return t + 1; /* needs to be non-NULL, but value doesn't matter */
2432 if (quote && (q = strchr(quote, *t))) {
2435 while (*t && *t != *q)
2437 if (!*t || (t[1] && !strchr(del, t[1])))
2445 while (*t && !strchr(del, *t))
2451 /* Parses config with following syntax:
2454 * option-name = value
2456 * option-name value {
2457 * option-name [=] value
2461 void getgeneralconfig(FILE *f, char *block, ...) {
2464 /* initialise lots of stuff to avoid stupid compiler warnings */
2465 char *tokens[3], *s, *opt = NULL, *val = NULL, *word, *optval, **str = NULL, ***mstr = NULL;
2466 int type = 0, tcount, conftype = 0, n;
2467 void (*cbk)(FILE *, char *, char *, char *) = NULL;
2469 while (fgets(line, 1024, f)) {
2471 for (tcount = 0; tcount < 3; tcount++) {
2472 s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#");
2474 debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line);
2475 if (!tokens[tcount])
2478 if (!tcount || **tokens == '#')
2481 if (**tokens == '}') {
2484 debugx(1, DBG_ERR, "configuration error, found } with no matching {");
2491 conftype = CONF_STR;
2494 if (tokens[1][0] == '=' && tokens[1][1] == '\0') {
2497 conftype = CONF_STR;
2500 if (tokens[2][0] == '{' && tokens[2][1] == '\0') {
2503 conftype = CONF_CBK;
2509 debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]);
2510 debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]);
2514 debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt);
2516 va_start(ap, block);
2517 while ((word = va_arg(ap, char *))) {
2518 type = va_arg(ap, int);
2521 str = va_arg(ap, char **);
2523 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2526 mstr = va_arg(ap, char ***);
2528 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2531 cbk = va_arg(ap, void (*)(FILE *, char *, char *, char *));
2534 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2536 if (!strcasecmp(opt, word))
2543 debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt);
2544 debugx(1, DBG_ERR, "configuration error, unknown option %s", opt);
2547 if (((type == CONF_STR || type == CONF_MSTR) && conftype != CONF_STR) ||
2548 (type == CONF_CBK && conftype != CONF_CBK)) {
2550 debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt);
2551 debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt);
2557 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
2559 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
2561 debugx(1, DBG_ERR, "configuration error, option %s already set to %s", opt, *str);
2562 *str = stringcopy(val, 0);
2564 debugx(1, DBG_ERR, "malloc failed");
2568 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
2570 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
2572 for (n = 0; (*mstr)[n]; n++);
2575 *mstr = realloc(*mstr, sizeof(char *) * (n + 2));
2577 debugx(1, DBG_ERR, "malloc failed");
2578 (*mstr)[n] = stringcopy(val, 0);
2579 (*mstr)[n + 1] = NULL;
2582 optval = malloc(strlen(opt) + strlen(val) + 2);
2584 debugx(1, DBG_ERR, "malloc failed");
2585 sprintf(optval, "%s %s", opt, val);
2586 cbk(f, optval, opt, val);
2590 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2595 int addmatchcertattr(struct clsrvconf *conf, char *matchcertattr) {
2598 v = matchcertattr + 20;
2599 if (strncasecmp(matchcertattr, "SubjectAltName:URI:/", 20) || !*v)
2601 /* regexp, remove optional trailing / if present */
2602 if (v[strlen(v) - 1] == '/')
2603 v[strlen(v) - 1] = '\0';
2607 conf->certuriregex = malloc(sizeof(regex_t));
2608 if (!conf->certuriregex) {
2609 debug(DBG_ERR, "malloc failed");
2612 if (regcomp(conf->certuriregex, v, REG_ICASE | REG_NOSUB)) {
2613 free(conf->certuriregex);
2614 conf->certuriregex = NULL;
2615 debug(DBG_ERR, "failed to compile regular expression %s", v);
2621 int addrewriteattr(struct clsrvconf *conf, char *rewriteattr) {
2624 v = rewriteattr + 11;
2625 if (strncasecmp(rewriteattr, "User-Name:/", 11) || !*v)
2627 /* regexp, remove optional trailing / if present */
2628 if (v[strlen(v) - 1] == '/')
2629 v[strlen(v) - 1] = '\0';
2637 conf->rewriteattrregex = malloc(sizeof(regex_t));
2638 if (!conf->rewriteattrregex) {
2639 debug(DBG_ERR, "malloc failed");
2643 conf->rewriteattrreplacement = stringcopy(w, 0);
2644 if (!conf->rewriteattrreplacement) {
2645 free(conf->rewriteattrregex);
2646 conf->rewriteattrregex = NULL;
2650 if (regcomp(conf->rewriteattrregex, v, REG_ICASE | REG_EXTENDED)) {
2651 free(conf->rewriteattrregex);
2652 conf->rewriteattrregex = NULL;
2653 free(conf->rewriteattrreplacement);
2654 conf->rewriteattrreplacement = NULL;
2655 debug(DBG_ERR, "failed to compile regular expression %s", v);
2662 void confclient_cb(FILE *f, char *block, char *opt, char *val) {
2663 char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewriteattr = NULL;
2664 struct clsrvconf *conf;
2666 debug(DBG_DBG, "confclient_cb called for %s", block);
2668 conf = malloc(sizeof(struct clsrvconf));
2669 if (!conf || !list_push(clconfs, conf))
2670 debugx(1, DBG_ERR, "malloc failed");
2671 memset(conf, 0, sizeof(struct clsrvconf));
2673 getgeneralconfig(f, block,
2674 "type", CONF_STR, &type,
2675 "host", CONF_STR, &conf->host,
2676 "secret", CONF_STR, &conf->secret,
2677 "tls", CONF_STR, &tls,
2678 "matchcertificateattribute", CONF_STR, &matchcertattr,
2679 "rewriteattribute", CONF_STR, &rewriteattr,
2683 /* leave conf->name to be NULL for clients */
2685 conf->host = stringcopy(val, 0);
2687 if (type && !strcasecmp(type, "udp")) {
2690 } else if (type && !strcasecmp(type, "tls")) {
2691 conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultclient", "default");
2693 debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2694 if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2695 debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2699 debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2704 free(matchcertattr);
2707 if (!addrewriteattr(conf, rewriteattr))
2708 debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
2712 if (!resolvepeer(conf, 0))
2713 debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2715 if (!conf->secret) {
2716 if (conf->type == 'U')
2717 debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2718 conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2722 void confserver_cb(FILE *f, char *block, char *opt, char *val) {
2723 char *type = NULL, *tls = NULL, *matchcertattr = NULL, *statusserver = NULL;
2724 struct clsrvconf *conf;
2726 debug(DBG_DBG, "confserver_cb called for %s", block);
2728 conf = malloc(sizeof(struct clsrvconf));
2729 if (!conf || !list_push(srvconfs, conf))
2730 debugx(1, DBG_ERR, "malloc failed");
2731 memset(conf, 0, sizeof(struct clsrvconf));
2733 getgeneralconfig(f, block,
2734 "type", CONF_STR, &type,
2735 "host", CONF_STR, &conf->host,
2736 "port", CONF_STR, &conf->port,
2737 "secret", CONF_STR, &conf->secret,
2738 "tls", CONF_STR, &tls,
2739 "matchcertificateattribute", CONF_STR, &matchcertattr,
2740 "StatusServer", CONF_STR, &statusserver,
2744 conf->name = stringcopy(val, 0);
2746 conf->host = stringcopy(val, 0);
2748 if (type && !strcasecmp(type, "udp")) {
2752 conf->port = stringcopy(DEFAULT_UDP_PORT, 0);
2753 } else if (type && !strcasecmp(type, "tls")) {
2754 conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultserver", "default");
2756 debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2757 if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2758 debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2760 conf->port = stringcopy(DEFAULT_TLS_PORT, 0);
2764 debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2769 free(matchcertattr);
2771 if (!resolvepeer(conf, 0))
2772 debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2774 if (!conf->secret) {
2775 if (conf->type == 'U')
2776 debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2777 conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2781 if (!strcasecmp(statusserver, "on"))
2782 conf->statusserver = 1;
2783 else if (strcasecmp(statusserver, "off"))
2784 debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
2789 void confrealm_cb(FILE *f, char *block, char *opt, char *val) {
2790 char **servers = NULL, *msg = NULL;
2792 debug(DBG_DBG, "confrealm_cb called for %s", block);
2794 getgeneralconfig(f, block,
2795 "server", CONF_MSTR, &servers,
2796 "ReplyMessage", CONF_STR, &msg,
2800 addrealm(val, servers, msg);
2804 void conftls_cb(FILE *f, char *block, char *opt, char *val) {
2805 char *cacertfile = NULL, *cacertpath = NULL, *certfile = NULL, *certkeyfile = NULL, *certkeypwd = NULL;
2807 debug(DBG_DBG, "conftls_cb called for %s", block);
2809 getgeneralconfig(f, block,
2810 "CACertificateFile", CONF_STR, &cacertfile,
2811 "CACertificatePath", CONF_STR, &cacertpath,
2812 "CertificateFile", CONF_STR, &certfile,
2813 "CertificateKeyFile", CONF_STR, &certkeyfile,
2814 "CertificateKeyPassword", CONF_STR, &certkeypwd,
2818 tlsadd(val, cacertfile, cacertpath, certfile, certkeyfile, certkeypwd);
2826 void getmainconfig(const char *configfile) {
2828 char *loglevel = NULL;
2830 f = openconfigfile(configfile);
2831 memset(&options, 0, sizeof(options));
2833 clconfs = list_create();
2835 debugx(1, DBG_ERR, "malloc failed");
2837 srvconfs = list_create();
2839 debugx(1, DBG_ERR, "malloc failed");
2841 realms = list_create();
2843 debugx(1, DBG_ERR, "malloc failed");
2845 tlsconfs = list_create();
2847 debugx(1, DBG_ERR, "malloc failed");
2849 getgeneralconfig(f, NULL,
2850 "ListenUDP", CONF_STR, &options.listenudp,
2851 "ListenTCP", CONF_STR, &options.listentcp,
2852 "ListenAccountingUDP", CONF_STR, &options.listenaccudp,
2853 "LogLevel", CONF_STR, &loglevel,
2854 "LogDestination", CONF_STR, &options.logdestination,
2855 "Client", CONF_CBK, confclient_cb,
2856 "Server", CONF_CBK, confserver_cb,
2857 "Realm", CONF_CBK, confrealm_cb,
2858 "TLS", CONF_CBK, conftls_cb,
2865 if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
2866 debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
2867 options.loglevel = *loglevel - '0';
2872 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *loglevel, char **configfile) {
2875 while ((c = getopt(argc, argv, "c:d:fv")) != -1) {
2878 *configfile = optarg;
2881 if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
2882 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
2883 *loglevel = *optarg - '0';
2889 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
2894 if (!(argc - optind))
2898 debug(DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -v ]", argv[0]);
2902 int main(int argc, char **argv) {
2903 pthread_t udpserverth, udpaccserverth, udpclient4rdth, udpclient6rdth;
2904 struct list_node *entry;
2905 uint8_t foreground = 0, loglevel = 0;
2906 char *configfile = NULL;
2908 debug_init("radsecproxy");
2909 debug_set_level(DEBUG_LEVEL);
2910 getargs(argc, argv, &foreground, &loglevel, &configfile);
2912 debug_set_level(loglevel);
2913 getmainconfig(configfile ? configfile : CONFIG_MAIN);
2915 options.loglevel = loglevel;
2916 else if (options.loglevel)
2917 debug_set_level(options.loglevel);
2919 options.logdestination = NULL;
2921 if (!options.logdestination)
2922 options.logdestination = "x-syslog:///";
2923 debug_set_destination(options.logdestination);
2926 if (!list_first(clconfs))
2927 debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
2928 if (!list_first(srvconfs))
2929 debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
2930 if (!list_first(realms))
2931 debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
2933 if (!foreground && (daemon(0, 0) < 0))
2934 debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
2936 debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
2938 if (client_udp_count) {
2939 udp_server_replyq = newreplyq();
2940 if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
2941 debugx(1, DBG_ERR, "pthread_create failed");
2942 if (options.listenaccudp)
2943 if (pthread_create(&udpaccserverth, NULL, udpaccserverrd, NULL))
2944 debugx(1, DBG_ERR, "pthread_create failed");
2947 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2948 addserver((struct clsrvconf *)entry->data);
2949 if (pthread_create(&((struct clsrvconf *)entry->data)->servers->clientth, NULL, clientwr,
2950 (void *)((struct clsrvconf *)entry->data)->servers))
2951 debugx(1, DBG_ERR, "pthread_create failed");
2954 if (udp_client4_sock >= 0)
2955 if (pthread_create(&udpclient4rdth, NULL, udpclientrd, (void *)&udp_client4_sock))
2956 debugx(1, DBG_ERR, "clientwr: pthread_create failed");
2957 if (udp_client6_sock >= 0)
2958 if (pthread_create(&udpclient6rdth, NULL, udpclientrd, (void *)&udp_client6_sock))
2959 debugx(1, DBG_ERR, "clientwr: pthread_create failed");
2961 if (client_tls_count)
2962 return tlslistener();
2964 /* just hang around doing nothing, anything to do here? */