1002ec3f686f5a8750d11c8f3655c66468172605
[radsecproxy.git] / radsecproxy.c
1 /*
2  * Copyright (C) 2006, 2007 Stig Venaas <venaas@uninett.no>
3  *
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.
7  */
8
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
15  *
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
22  *
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
30 */
31
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <arpa/inet.h>
40 #include <regex.h>
41 #include <libgen.h>
42 #include <pthread.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>
49 #include "debug.h"
50 #include "list.h"
51 #include "radsecproxy.h"
52
53 static struct options options;
54 struct list *clconfs, *srvconfs, *realms, *tlsconfs;
55
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;
60
61 static struct clsrvconf *srcudpres = NULL;
62 static struct clsrvconf *srctcpres = NULL;
63
64 static struct replyq *udp_server_replyq = NULL;
65 static int udp_server_sock = -1;
66 static int udp_accserver_sock = -1;
67 static int udp_client4_sock = -1;
68 static int udp_client6_sock = -1;
69 static pthread_mutex_t *ssl_locks;
70 static long *ssl_lock_count;
71 extern int optind;
72 extern char *optarg;
73
74 /* callbacks for making OpenSSL thread safe */
75 unsigned long ssl_thread_id() {
76         return (unsigned long)pthread_self();
77 }
78
79 void ssl_locking_callback(int mode, int type, const char *file, int line) {
80     if (mode & CRYPTO_LOCK) {
81         pthread_mutex_lock(&ssl_locks[type]);
82         ssl_lock_count[type]++;
83     } else
84         pthread_mutex_unlock(&ssl_locks[type]);
85 }
86
87 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
88     int pwdlen = strlen(userdata);
89     if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
90         return 0;
91     memcpy(buf, userdata, pwdlen);
92     return pwdlen;
93 }
94
95 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
96   char buf[256];
97   X509 *err_cert;
98   int err, depth;
99
100   err_cert = X509_STORE_CTX_get_current_cert(ctx);
101   err = X509_STORE_CTX_get_error(ctx);
102   depth = X509_STORE_CTX_get_error_depth(ctx);
103
104   if (depth > MAX_CERT_DEPTH) {
105       ok = 0;
106       err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
107       X509_STORE_CTX_set_error(ctx, err);
108   }
109
110   if (!ok) {
111       X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
112       debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
113
114       switch (err) {
115       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
116           X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
117           debug(DBG_WARN, "\tIssuer=%s", buf);
118           break;
119       case X509_V_ERR_CERT_NOT_YET_VALID:
120       case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
121           debug(DBG_WARN, "\tCertificate not yet valid");
122           break;
123       case X509_V_ERR_CERT_HAS_EXPIRED:
124           debug(DBG_WARN, "Certificate has expired");
125           break;
126       case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
127           debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
128           break;
129       }
130   }
131 #ifdef DEBUG  
132   printf("certificate verify returns %d\n", ok);
133 #endif  
134   return ok;
135 }
136
137 int resolvepeer(struct clsrvconf *conf, int ai_flags) {
138     struct addrinfo hints, *addrinfo, *res;
139     char *slash, *s;
140     int plen;
141
142     slash = conf->host ? strchr(conf->host, '/') : NULL;
143     if (slash) {
144         s = slash + 1;
145         if (!*s) {
146             debug(DBG_WARN, "resolvepeer: prefix length must be specified after the / in %s", conf->host);
147             return 0;
148         }
149         for (; *s; s++)
150             if (*s < '0' || *s > '9') {
151                 debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
152                 return 0;
153             }
154         plen = atoi(slash + 1);
155         if (plen < 0 || plen > 128) {
156             debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
157             return 0;
158         }
159         *slash = '\0';
160     }
161     memset(&hints, 0, sizeof(hints));
162     hints.ai_socktype = (conf->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
163     hints.ai_family = AF_UNSPEC;
164     hints.ai_flags = ai_flags;
165     if (!conf->host && !conf->port) {
166         /* getaddrinfo() doesn't like host and port to be NULL */
167         if (getaddrinfo(conf->host, DEFAULT_UDP_PORT, &hints, &addrinfo)) {
168             debug(DBG_WARN, "resolvepeer: can't resolve (null) port (null)");
169             return 0;
170         }
171         for (res = addrinfo; res; res = res->ai_next) {
172             switch (res->ai_family) {
173             case AF_INET:
174                 ((struct sockaddr_in *)res->ai_addr)->sin_port = 0;
175                 break;
176             case AF_INET6:
177                 ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = 0;
178                 break;
179             }
180         }
181     } else {
182         if (slash)
183             hints.ai_flags |= AI_NUMERICHOST;
184         if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) {
185             debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host, conf->port);
186             return 0;
187         }
188         if (slash) {
189             *slash = '/';
190             switch (addrinfo->ai_family) {
191             case AF_INET:
192                 if (plen > 32) {
193                     debug(DBG_WARN, "resolvepeer: prefix length must be <= 32 in %s", conf->host);
194                     freeaddrinfo(addrinfo);
195                     return 0;
196                 }
197                 break;
198             case AF_INET6:
199                 break;
200             default:
201                 debug(DBG_WARN, "resolvepeer: prefix must be IPv4 or IPv6 in %s", conf->host);
202                 freeaddrinfo(addrinfo);
203                 return 0;
204             }
205             conf->prefixlen = plen;
206         } else
207             conf->prefixlen = 255;
208     }
209     if (conf->addrinfo)
210         freeaddrinfo(conf->addrinfo);
211     conf->addrinfo = addrinfo;
212     return 1;
213 }         
214
215 int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) {
216     int s, on = 1;
217     struct addrinfo *res;
218     
219     for (res = addrinfo; res; res = res->ai_next) {
220         if (family != AF_UNSPEC && family != res->ai_family)
221             continue;
222         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
223         if (s < 0) {
224             debug(DBG_WARN, "bindtoaddr: socket failed");
225             continue;
226         }
227         if (reuse)
228             setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
229 #ifdef IPV6_V6ONLY
230         if (v6only)
231             setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
232 #endif          
233
234         if (!bind(s, res->ai_addr, res->ai_addrlen))
235             return s;
236         debug(DBG_WARN, "bindtoaddr: bind failed");
237         close(s);
238     }
239     return -1;
240 }         
241
242 char *parsehostport(char *s, struct clsrvconf *conf, char *default_port) {
243     char *p, *field;
244     int ipv6 = 0;
245
246     p = s;
247     /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
248     if (*p == '[') {
249         p++;
250         field = p;
251         for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
252         if (*p != ']')
253             debugx(1, DBG_ERR, "no ] matching initial [");
254         ipv6 = 1;
255     } else {
256         field = p;
257         for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
258     }
259     if (field == p)
260         debugx(1, DBG_ERR, "missing host/address");
261
262     conf->host = stringcopy(field, p - field);
263     if (ipv6) {
264         p++;
265         if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
266             debugx(1, DBG_ERR, "unexpected character after ]");
267     }
268     if (*p == ':') {
269             /* port number or service name is specified */;
270             field = ++p;
271             for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
272             if (field == p)
273                 debugx(1, DBG_ERR, "syntax error, : but no following port");
274             conf->port = stringcopy(field, p - field);
275     } else
276         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
277     return p;
278 }
279
280 struct clsrvconf *resolve_hostport(char type, char *lconf, char *default_port) {
281     struct clsrvconf *conf;
282
283     conf = malloc(sizeof(struct clsrvconf));
284     if (!conf)
285         debugx(1, DBG_ERR, "malloc failed");
286     memset(conf, 0, sizeof(struct clsrvconf));
287     conf->type = type;
288     if (lconf) {
289         parsehostport(lconf, conf, default_port);
290         if (!strcmp(conf->host, "*")) {
291             free(conf->host);
292             conf->host = NULL;
293         }
294     } else
295         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
296     if (!resolvepeer(conf, AI_PASSIVE))
297         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
298     return conf;
299 }
300
301 int connecttcp(struct addrinfo *addrinfo) {
302     int s;
303     struct addrinfo *res;
304
305     s = -1;
306     for (res = addrinfo; res; res = res->ai_next) {
307         s = bindtoaddr(srctcpres->addrinfo, res->ai_family, 1, 1);
308         if (s < 0) {
309             debug(DBG_WARN, "connecttoserver: socket failed");
310             continue;
311         }
312         if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
313             break;
314         debug(DBG_WARN, "connecttoserver: connect failed");
315         close(s);
316         s = -1;
317     }
318     return s;
319 }         
320
321 /* returns 1 if the len first bits are equal, else 0 */
322 int prefixmatch(void *a1, void *a2, uint8_t len) {
323     static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
324     int r, l = len / 8;
325     if (l && memcmp(a1, a2, l))
326         return 0;
327     r = len % 8;
328     if (!r)
329         return 1;
330     return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
331 }
332
333 /* returns the config with matching address, or NULL */
334 /* if conf argument is not NULL, we only check that one */
335 struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs, struct clsrvconf *conf) {
336     struct sockaddr_in6 *sa6 = NULL;
337     struct in_addr *a4 = NULL;
338     struct addrinfo *res;
339     struct list_node *entry;
340     
341     if (addr->sa_family == AF_INET6) {
342         sa6 = (struct sockaddr_in6 *)addr;
343         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
344             a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
345             sa6 = NULL;
346         }
347     } else
348         a4 = &((struct sockaddr_in *)addr)->sin_addr;
349
350     if (conf) {
351         if (conf->type == type) {
352             if (conf->prefixlen == 255) {
353                 for (res = conf->addrinfo; res; res = res->ai_next)
354                     if ((a4 && res->ai_family == AF_INET &&
355                          !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
356                         (sa6 && res->ai_family == AF_INET6 &&
357                          !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
358                         return conf;
359             } else {
360                 res = conf->addrinfo;
361                 if (res &&
362                     ((a4 && res->ai_family == AF_INET &&
363                       prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
364                      (sa6 && res->ai_family == AF_INET6 &&
365                       prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
366                     return conf;
367             }
368         }
369         return NULL;
370     }
371
372     for (entry = list_first(confs); entry; entry = list_next(entry)) {  
373         conf = (struct clsrvconf *)entry->data;
374         if (conf->type == type) {
375             if (conf->prefixlen == 255) {
376                 for (res = conf->addrinfo; res; res = res->ai_next)
377                     if ((a4 && res->ai_family == AF_INET &&
378                          !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
379                         (sa6 && res->ai_family == AF_INET6 &&
380                          !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
381                         return conf;
382             } else {
383                 res = conf->addrinfo;
384                 if (res &&
385                     ((a4 && res->ai_family == AF_INET &&
386                       prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
387                      (sa6 && res->ai_family == AF_INET6 &&
388                       prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
389                     return conf;
390             }
391         }
392     }    
393     return NULL;
394 }
395
396 struct replyq *newreplyq() {
397     struct replyq *replyq;
398     
399     replyq = malloc(sizeof(struct replyq));
400     if (!replyq)
401         debugx(1, DBG_ERR, "malloc failed");
402     replyq->replies = list_create();
403     if (!replyq->replies)
404         debugx(1, DBG_ERR, "malloc failed");
405     pthread_mutex_init(&replyq->mutex, NULL);
406     pthread_cond_init(&replyq->cond, NULL);
407     return replyq;
408 }
409
410 struct client *addclient(struct clsrvconf *conf) {
411     struct client *new = malloc(sizeof(struct client));
412     
413     if (!new) {
414         debug(DBG_ERR, "malloc failed");
415         return NULL;
416     }
417     if (!conf->clients) {
418         conf->clients = list_create();
419         if (!conf->clients) {
420             debug(DBG_ERR, "malloc failed");
421             return NULL;
422         }
423     }
424     
425     memset(new, 0, sizeof(struct client));
426     new->conf = conf;
427     new->replyq = conf->type == 'T' ? newreplyq() : udp_server_replyq;
428
429     list_push(conf->clients, new);
430     return new;
431 }
432
433 void removeclient(struct client *client) {
434     if (!client || !client->conf->clients)
435         return;
436
437     list_removedata(client->conf->clients, client);
438     free(client);
439 }
440
441 void addserver(struct clsrvconf *conf) {
442     if (conf->servers)
443         debugx(1, DBG_ERR, "addserver: currently works with just one server per conf");
444     
445     conf->servers = malloc(sizeof(struct server));
446     if (!conf->servers)
447         debugx(1, DBG_ERR, "malloc failed");
448     memset(conf->servers, 0, sizeof(struct server));
449     conf->servers->conf = conf;
450
451     if (conf->type == 'U') {
452         if (!srcudpres)
453             srcudpres = resolve_hostport('U', options.sourceudp, NULL);
454         switch (conf->addrinfo->ai_family) {
455         case AF_INET:
456             if (udp_client4_sock < 0) {
457                 udp_client4_sock = bindtoaddr(srcudpres->addrinfo, AF_INET, 0, 1);
458                 if (udp_client4_sock < 0)
459                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
460             }
461             conf->servers->sock = udp_client4_sock;
462             break;
463         case AF_INET6:
464             if (udp_client6_sock < 0) {
465                 udp_client6_sock = bindtoaddr(srcudpres->addrinfo, AF_INET6, 0, 1);
466                 if (udp_client6_sock < 0)
467                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
468             }
469             conf->servers->sock = udp_client6_sock;
470             break;
471         default:
472             debugx(1, DBG_ERR, "addserver: unsupported address family");
473         }
474         
475     } else {
476         if (!srctcpres)
477             srctcpres = resolve_hostport('T', options.sourcetcp, NULL);
478         conf->servers->sock = -1;
479     }
480     
481     pthread_mutex_init(&conf->servers->lock, NULL);
482     conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request));
483     if (!conf->servers->requests)
484         debugx(1, DBG_ERR, "malloc failed");
485     conf->servers->newrq = 0;
486     pthread_mutex_init(&conf->servers->newrq_mutex, NULL);
487     pthread_cond_init(&conf->servers->newrq_cond, NULL);
488 }
489
490 /* exactly one of client and server must be non-NULL */
491 /* should probably take peer list (client(s) or server(s)) as argument instead */
492 /* if *peer == NULL we return who we received from, else require it to be from peer */
493 /* return from in sa if not NULL */
494 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
495     int cnt, len;
496     unsigned char buf[65536], *rad;
497     struct sockaddr_storage from;
498     socklen_t fromlen = sizeof(from);
499     struct clsrvconf *p;
500     struct list_node *node;
501     
502     for (;;) {
503         cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
504         if (cnt == -1) {
505             debug(DBG_WARN, "radudpget: recv failed");
506             continue;
507         }
508         debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
509
510         if (cnt < 20) {
511             debug(DBG_WARN, "radudpget: packet too small");
512             continue;
513         }
514     
515         len = RADLEN(buf);
516         if (len < 20) {
517             debug(DBG_WARN, "radudpget: length too small");
518             continue;
519         }
520
521         if (cnt < len) {
522             debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
523             continue;
524         }
525         if (cnt > len)
526             debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
527
528         if (client)
529             if (*client)
530                 p = find_conf('U', (struct sockaddr *)&from, NULL, (*client)->conf);
531             else
532                 p = find_conf('U', (struct sockaddr *)&from, clconfs, NULL);
533         else
534             if (*server)
535                 p = find_conf('U', (struct sockaddr *)&from, NULL, (*server)->conf);
536             else
537                 p = find_conf('U', (struct sockaddr *)&from, srvconfs, NULL);
538
539         if (!p) {
540             debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
541             continue;
542         }
543         
544         rad = malloc(len);
545         if (!rad) {
546             debug(DBG_ERR, "radudpget: malloc failed");
547             continue;
548         }
549         
550         if (client && !*client) {
551             node = list_first(p->clients);
552             *client = node ? (struct client *)node->data : addclient(p);
553             if (!*client) {
554                 free(rad);
555                 continue;
556             }
557         } else if (server && !*server)
558             *server = p->servers;
559         
560         break;
561     }
562     memcpy(rad, buf, len);
563     if (sa)
564         *sa = from;
565     return rad;
566 }
567
568 int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
569     int loc, i, l, n, r = 0;
570     char *v;
571     X509_EXTENSION *ex;
572     STACK_OF(GENERAL_NAME) *alt;
573     GENERAL_NAME *gn;
574     
575     debug(DBG_DBG, "subjectaltnameaddr");
576     
577     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
578     if (loc < 0)
579         return r;
580     
581     ex = X509_get_ext(cert, loc);
582     alt = X509V3_EXT_d2i(ex);
583     if (!alt)
584         return r;
585     
586     n = sk_GENERAL_NAME_num(alt);
587     for (i = 0; i < n; i++) {
588         gn = sk_GENERAL_NAME_value(alt, i);
589         if (gn->type != GEN_IPADD)
590             continue;
591         r = -1;
592         v = (char *)ASN1_STRING_data(gn->d.ia5);
593         l = ASN1_STRING_length(gn->d.ia5);
594         if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
595             && !memcmp(v, &addr, l)) {
596             r = 1;
597             break;
598         }
599     }
600     GENERAL_NAMES_free(alt);
601     return r;
602 }
603
604 int subjectaltnameregexp(X509 *cert, int type, char *exact,  regex_t *regex) {
605     int loc, i, l, n, r = 0;
606     char *s, *v;
607     X509_EXTENSION *ex;
608     STACK_OF(GENERAL_NAME) *alt;
609     GENERAL_NAME *gn;
610     
611     debug(DBG_DBG, "subjectaltnameregexp");
612     
613     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
614     if (loc < 0)
615         return r;
616     
617     ex = X509_get_ext(cert, loc);
618     alt = X509V3_EXT_d2i(ex);
619     if (!alt)
620         return r;
621     
622     n = sk_GENERAL_NAME_num(alt);
623     for (i = 0; i < n; i++) {
624         gn = sk_GENERAL_NAME_value(alt, i);
625         if (gn->type != type)
626             continue;
627         r = -1;
628         v = (char *)ASN1_STRING_data(gn->d.ia5);
629         l = ASN1_STRING_length(gn->d.ia5);
630         if (l <= 0)
631             continue;
632 #ifdef DEBUG
633         printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
634 #endif  
635         if (exact) {
636             if (memcmp(v, exact, l))
637                 continue;
638         } else {
639             s = stringcopy((char *)v, l);
640             if (!s) {
641                 debug(DBG_ERR, "malloc failed");
642                 continue;
643             }
644             if (regexec(regex, s, 0, NULL, 0)) {
645                 free(s);
646                 continue;
647             }
648             free(s);
649         }
650         r = 1;
651         break;
652     }
653     GENERAL_NAMES_free(alt);
654     return r;
655 }
656
657 int tlsverifycert(SSL *ssl, struct clsrvconf *conf) {
658     int l, loc, r;
659     X509 *cert;
660     X509_NAME *nm;
661     X509_NAME_ENTRY *e;
662     ASN1_STRING *s;
663     char *v;
664     uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
665     unsigned long error;
666     struct in6_addr addr;
667     
668     if (SSL_get_verify_result(ssl) != X509_V_OK) {
669         debug(DBG_ERR, "tlsverifycert: basic validation failed");
670         while ((error = ERR_get_error()))
671             debug(DBG_ERR, "tlsverifycert: TLS: %s", ERR_error_string(error, NULL));
672         return 0;
673     }
674
675     cert = SSL_get_peer_certificate(ssl);
676     if (!cert) {
677         debug(DBG_ERR, "tlsverifycert: failed to obtain certificate");
678         return 0;
679     }
680
681     if (conf->prefixlen == 255) {
682         if (inet_pton(AF_INET, conf->host, &addr))
683             type = AF_INET;
684         else if (inet_pton(AF_INET6, conf->host, &addr))
685             type = AF_INET6;
686
687         r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, conf->host, NULL);
688         if (r) {
689             if (r < 0) {
690                 X509_free(cert);
691                 debug(DBG_DBG, "tlsverifycert: No subjectaltname matching %s %s", type ? "address" : "host", conf->host);
692                 return 0;
693             }
694             debug(DBG_DBG, "tlsverifycert: Found subjectaltname matching %s %s", type ? "address" : "host", conf->host);
695         } else {
696             nm = X509_get_subject_name(cert);
697             loc = -1;
698             for (;;) {
699                 loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
700                 if (loc == -1)
701                     break;
702                 e = X509_NAME_get_entry(nm, loc);
703                 s = X509_NAME_ENTRY_get_data(e);
704                 v = (char *) ASN1_STRING_data(s);
705                 l = ASN1_STRING_length(s);
706                 if (l < 0)
707                     continue;
708 #ifdef DEBUG
709                 printfchars(NULL, "cn", NULL, v, l);
710 #endif      
711                 if (l == strlen(conf->host) && !strncasecmp(conf->host, v, l)) {
712                     r = 1;
713                     debug(DBG_DBG, "tlsverifycert: Found cn matching host %s", conf->host);
714                     break;
715                 }
716             }
717             if (!r) {
718                 X509_free(cert);
719                 debug(DBG_ERR, "tlsverifycert: cn not matching host %s", conf->host);
720                 return 0;
721             }
722         }
723     }
724     if (conf->certuriregex) {
725         r = subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex);
726         if (r < 1) {
727             debug(DBG_DBG, "tlsverifycert: subjectaltname URI not matching regex");
728             X509_free(cert);
729             return 0;
730         }
731         debug(DBG_DBG, "tlsverifycert: subjectaltname URI matching regex");
732     }
733     X509_free(cert);
734     return 1;
735 }
736
737 void tlsconnect(struct server *server, struct timeval *when, char *text) {
738     struct timeval now;
739     time_t elapsed;
740
741     debug(DBG_DBG, "tlsconnect called from %s", text);
742     pthread_mutex_lock(&server->lock);
743     if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
744         /* already reconnected, nothing to do */
745         debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
746         pthread_mutex_unlock(&server->lock);
747         return;
748     }
749
750     debug(DBG_DBG, "tlsconnect %s", text);
751
752     for (;;) {
753         gettimeofday(&now, NULL);
754         elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
755         if (server->connectionok) {
756             server->connectionok = 0;
757             sleep(10);
758         } else if (elapsed < 5)
759             sleep(10);
760         else if (elapsed < 300) {
761             debug(DBG_INFO, "tlsconnect: sleeping %lds", elapsed);
762             sleep(elapsed);
763         } else if (elapsed < 100000) {
764             debug(DBG_INFO, "tlsconnect: sleeping %ds", 600);
765             sleep(600);
766         } else
767             server->lastconnecttry.tv_sec = now.tv_sec;  /* no sleep at startup */
768         debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->conf->host, server->conf->port);
769         if (server->sock >= 0)
770             close(server->sock);
771         if ((server->sock = connecttcp(server->conf->addrinfo)) < 0) {
772             debug(DBG_ERR, "tlsconnect: connecttcp failed");
773             continue;
774         }
775         
776         SSL_free(server->ssl);
777         server->ssl = SSL_new(server->conf->ssl_ctx);
778         SSL_set_fd(server->ssl, server->sock);
779         if (SSL_connect(server->ssl) > 0 && tlsverifycert(server->ssl, server->conf))
780             break;
781     }
782     debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
783     gettimeofday(&server->lastconnecttry, NULL);
784     pthread_mutex_unlock(&server->lock);
785 }
786
787 unsigned char *radtlsget(SSL *ssl) {
788     int cnt, total, len;
789     unsigned char buf[4], *rad;
790
791     for (;;) {
792         for (total = 0; total < 4; total += cnt) {
793             cnt = SSL_read(ssl, buf + total, 4 - total);
794             if (cnt <= 0) {
795                 debug(DBG_ERR, "radtlsget: connection lost");
796                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
797                     /* remote end sent close_notify, send one back */
798                     SSL_shutdown(ssl);
799                 }
800                 return NULL;
801             }
802         }
803
804         len = RADLEN(buf);
805         rad = malloc(len);
806         if (!rad) {
807             debug(DBG_ERR, "radtlsget: malloc failed");
808             continue;
809         }
810         memcpy(rad, buf, 4);
811
812         for (; total < len; total += cnt) {
813             cnt = SSL_read(ssl, rad + total, len - total);
814             if (cnt <= 0) {
815                 debug(DBG_ERR, "radtlsget: connection lost");
816                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
817                     /* remote end sent close_notify, send one back */
818                     SSL_shutdown(ssl);
819                 }
820                 free(rad);
821                 return NULL;
822             }
823         }
824     
825         if (total >= 20)
826             break;
827         
828         free(rad);
829         debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
830     }
831     
832     debug(DBG_DBG, "radtlsget: got %d bytes", total);
833     return rad;
834 }
835
836 int clientradput(struct server *server, unsigned char *rad) {
837     int cnt;
838     size_t len;
839     unsigned long error;
840     struct timeval lastconnecttry;
841     struct clsrvconf *conf = server->conf;
842     
843     len = RADLEN(rad);
844     if (conf->type == 'U') {
845         if (sendto(server->sock, rad, len, 0, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen) >= 0) {
846             debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, conf->host, conf->port);
847             return 1;
848         }
849         debug(DBG_WARN, "clientradput: send failed");
850         return 0;
851     }
852
853     lastconnecttry = server->lastconnecttry;
854     while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
855         while ((error = ERR_get_error()))
856             debug(DBG_ERR, "clientradput: TLS: %s", ERR_error_string(error, NULL));
857         tlsconnect(server, &lastconnecttry, "clientradput");
858         lastconnecttry = server->lastconnecttry;
859     }
860
861     server->connectionok = 1;
862     debug(DBG_DBG, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s", cnt, len, conf->host);
863     return 1;
864 }
865
866 int radsign(unsigned char *rad, unsigned char *sec) {
867     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
868     static unsigned char first = 1;
869     static EVP_MD_CTX mdctx;
870     unsigned int md_len;
871     int result;
872     
873     pthread_mutex_lock(&lock);
874     if (first) {
875         EVP_MD_CTX_init(&mdctx);
876         first = 0;
877     }
878
879     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
880         EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
881         EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
882         EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
883         md_len == 16);
884     pthread_mutex_unlock(&lock);
885     return result;
886 }
887
888 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
889     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
890     static unsigned char first = 1;
891     static EVP_MD_CTX mdctx;
892     unsigned char hash[EVP_MAX_MD_SIZE];
893     unsigned int len;
894     int result;
895     
896     pthread_mutex_lock(&lock);
897     if (first) {
898         EVP_MD_CTX_init(&mdctx);
899         first = 0;
900     }
901
902     len = RADLEN(rad);
903     
904     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
905               EVP_DigestUpdate(&mdctx, rad, 4) &&
906               EVP_DigestUpdate(&mdctx, reqauth, 16) &&
907               (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
908               EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
909               EVP_DigestFinal_ex(&mdctx, hash, &len) &&
910               len == 16 &&
911               !memcmp(hash, rad + 4, 16));
912     pthread_mutex_unlock(&lock);
913     return result;
914 }
915               
916 int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
917     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
918     static unsigned char first = 1;
919     static HMAC_CTX hmacctx;
920     unsigned int md_len;
921     uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
922     
923     pthread_mutex_lock(&lock);
924     if (first) {
925         HMAC_CTX_init(&hmacctx);
926         first = 0;
927     }
928
929     memcpy(auth, authattr, 16);
930     memset(authattr, 0, 16);
931     md_len = 0;
932     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
933     HMAC_Update(&hmacctx, rad, RADLEN(rad));
934     HMAC_Final(&hmacctx, hash, &md_len);
935     memcpy(authattr, auth, 16);
936     if (md_len != 16) {
937         debug(DBG_WARN, "message auth computation failed");
938         pthread_mutex_unlock(&lock);
939         return 0;
940     }
941
942     if (memcmp(auth, hash, 16)) {
943         debug(DBG_WARN, "message authenticator, wrong value");
944         pthread_mutex_unlock(&lock);
945         return 0;
946     }   
947         
948     pthread_mutex_unlock(&lock);
949     return 1;
950 }
951
952 int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secret) {
953     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
954     static unsigned char first = 1;
955     static HMAC_CTX hmacctx;
956     unsigned int md_len;
957
958     if (!authattrval)
959         return 1;
960     
961     pthread_mutex_lock(&lock);
962     if (first) {
963         HMAC_CTX_init(&hmacctx);
964         first = 0;
965     }
966
967     memset(authattrval, 0, 16);
968     md_len = 0;
969     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
970     HMAC_Update(&hmacctx, rad, RADLEN(rad));
971     HMAC_Final(&hmacctx, authattrval, &md_len);
972     if (md_len != 16) {
973         debug(DBG_WARN, "message auth computation failed");
974         pthread_mutex_unlock(&lock);
975         return 0;
976     }
977
978     pthread_mutex_unlock(&lock);
979     return 1;
980 }
981
982 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
983     while (length > 1) {
984         if (ATTRTYPE(attrs) == type)
985             return attrs;
986         length -= ATTRLEN(attrs);
987         attrs += ATTRLEN(attrs);
988     }
989     return NULL;
990 }
991
992 void freerqdata(struct request *rq) {
993     if (rq->origusername)
994         free(rq->origusername);
995     if (rq->buf)
996         free(rq->buf);
997 }
998
999 void sendrq(struct server *to, struct request *rq) {
1000     int i;
1001     uint8_t *attr;
1002
1003     pthread_mutex_lock(&to->newrq_mutex);
1004     /* might simplify if only try nextid, might be ok */
1005     for (i = to->nextid; i < MAX_REQUESTS; i++)
1006         if (!to->requests[i].buf)
1007             break;
1008     if (i == MAX_REQUESTS) {
1009         for (i = 0; i < to->nextid; i++)
1010             if (!to->requests[i].buf)
1011                 break;
1012         if (i == to->nextid) {
1013             debug(DBG_WARN, "No room in queue, dropping request");
1014             freerqdata(rq);
1015             pthread_mutex_unlock(&to->newrq_mutex);
1016             return;
1017         }
1018     }
1019     
1020     rq->buf[1] = (char)i;
1021
1022     attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
1023     if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->conf->secret)) {
1024         freerqdata(rq);
1025         pthread_mutex_unlock(&to->newrq_mutex);
1026         return;
1027     }
1028
1029     debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host);
1030     to->requests[i] = *rq;
1031     to->nextid = i + 1;
1032
1033     if (!to->newrq) {
1034         to->newrq = 1;
1035         debug(DBG_DBG, "signalling client writer");
1036         pthread_cond_signal(&to->newrq_cond);
1037     }
1038     pthread_mutex_unlock(&to->newrq_mutex);
1039 }
1040
1041 void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
1042     struct reply *reply;
1043     uint8_t first;
1044     
1045     if (!radsign(buf, (unsigned char *)to->conf->secret)) {
1046         free(buf);
1047         debug(DBG_WARN, "sendreply: failed to sign message");
1048         return;
1049     }
1050
1051     reply = malloc(sizeof(struct reply));
1052     if (!reply) {
1053         free(buf);
1054         debug(DBG_ERR, "sendreply: malloc failed");
1055         return;
1056     }
1057     memset(reply, 0, sizeof(struct reply));
1058     reply->buf = buf;
1059     if (tosa)
1060         reply->tosa = *tosa;
1061     
1062     pthread_mutex_lock(&to->replyq->mutex);
1063
1064     first = list_first(to->replyq->replies) == NULL;
1065     
1066     if (!list_push(to->replyq->replies, reply)) {
1067         pthread_mutex_unlock(&to->replyq->mutex);
1068         free(reply);
1069         free(buf);
1070         debug(DBG_ERR, "sendreply: malloc failed");
1071         return;
1072     }
1073     
1074     if (first) {
1075         debug(DBG_DBG, "signalling server writer");
1076         pthread_cond_signal(&to->replyq->cond);
1077     }
1078     pthread_mutex_unlock(&to->replyq->mutex);
1079 }
1080
1081 int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1082     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1083     static unsigned char first = 1;
1084     static EVP_MD_CTX mdctx;
1085     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1086     unsigned int md_len;
1087     uint8_t i, offset = 0, out[128];
1088     
1089     pthread_mutex_lock(&lock);
1090     if (first) {
1091         EVP_MD_CTX_init(&mdctx);
1092         first = 0;
1093     }
1094
1095     input = auth;
1096     for (;;) {
1097         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1098             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1099             !EVP_DigestUpdate(&mdctx, input, 16) ||
1100             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1101             md_len != 16) {
1102             pthread_mutex_unlock(&lock);
1103             return 0;
1104         }
1105         for (i = 0; i < 16; i++)
1106             out[offset + i] = hash[i] ^ in[offset + i];
1107         input = out + offset - 16;
1108         offset += 16;
1109         if (offset == len)
1110             break;
1111     }
1112     memcpy(in, out, len);
1113     pthread_mutex_unlock(&lock);
1114     return 1;
1115 }
1116
1117 int pwddecrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1118     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1119     static unsigned char first = 1;
1120     static EVP_MD_CTX mdctx;
1121     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1122     unsigned int md_len;
1123     uint8_t i, offset = 0, out[128];
1124     
1125     pthread_mutex_lock(&lock);
1126     if (first) {
1127         EVP_MD_CTX_init(&mdctx);
1128         first = 0;
1129     }
1130
1131     input = auth;
1132     for (;;) {
1133         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1134             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1135             !EVP_DigestUpdate(&mdctx, input, 16) ||
1136             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1137             md_len != 16) {
1138             pthread_mutex_unlock(&lock);
1139             return 0;
1140         }
1141         for (i = 0; i < 16; i++)
1142             out[offset + i] = hash[i] ^ in[offset + i];
1143         input = in + offset;
1144         offset += 16;
1145         if (offset == len)
1146             break;
1147     }
1148     memcpy(in, out, len);
1149     pthread_mutex_unlock(&lock);
1150     return 1;
1151 }
1152
1153 int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1154     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1155     static unsigned char first = 1;
1156     static EVP_MD_CTX mdctx;
1157     unsigned char hash[EVP_MAX_MD_SIZE];
1158     unsigned int md_len;
1159     uint8_t i, offset;
1160     
1161     pthread_mutex_lock(&lock);
1162     if (first) {
1163         EVP_MD_CTX_init(&mdctx);
1164         first = 0;
1165     }
1166
1167 #if 0
1168     printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16);
1169     printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2);
1170     printfchars(NULL, "msppencrypt in", "%02x ", text, len);
1171 #endif
1172     
1173     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1174         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1175         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1176         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1177         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1178         pthread_mutex_unlock(&lock);
1179         return 0;
1180     }
1181
1182 #if 0    
1183     printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1184 #endif
1185     
1186     for (i = 0; i < 16; i++)
1187         text[i] ^= hash[i];
1188     
1189     for (offset = 16; offset < len; offset += 16) {
1190 #if 0   
1191         printf("text + offset - 16 c(%d): ", offset / 16);
1192         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1193 #endif
1194         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1195             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1196             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1197             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1198             md_len != 16) {
1199             pthread_mutex_unlock(&lock);
1200             return 0;
1201         }
1202 #if 0
1203         printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1204 #endif    
1205         
1206         for (i = 0; i < 16; i++)
1207             text[offset + i] ^= hash[i];
1208     }
1209     
1210 #if 0
1211     printfchars(NULL, "msppencrypt out", "%02x ", text, len);
1212 #endif
1213
1214     pthread_mutex_unlock(&lock);
1215     return 1;
1216 }
1217
1218 int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1219     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1220     static unsigned char first = 1;
1221     static EVP_MD_CTX mdctx;
1222     unsigned char hash[EVP_MAX_MD_SIZE];
1223     unsigned int md_len;
1224     uint8_t i, offset;
1225     char plain[255];
1226     
1227     pthread_mutex_lock(&lock);
1228     if (first) {
1229         EVP_MD_CTX_init(&mdctx);
1230         first = 0;
1231     }
1232
1233 #if 0
1234     printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16);
1235     printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2);
1236     printfchars(NULL, "msppdecrypt in", "%02x ", text, len);
1237 #endif
1238     
1239     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1240         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1241         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1242         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1243         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1244         pthread_mutex_unlock(&lock);
1245         return 0;
1246     }
1247
1248 #if 0    
1249     printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1250 #endif
1251     
1252     for (i = 0; i < 16; i++)
1253         plain[i] = text[i] ^ hash[i];
1254     
1255     for (offset = 16; offset < len; offset += 16) {
1256 #if 0   
1257         printf("text + offset - 16 c(%d): ", offset / 16);
1258         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1259 #endif
1260         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1261             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1262             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1263             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1264             md_len != 16) {
1265             pthread_mutex_unlock(&lock);
1266             return 0;
1267         }
1268 #if 0
1269         printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1270 #endif    
1271
1272         for (i = 0; i < 16; i++)
1273             plain[offset + i] = text[offset + i] ^ hash[i];
1274     }
1275
1276     memcpy(text, plain, len);
1277 #if 0
1278     printfchars(NULL, "msppdecrypt out", "%02x ", text, len);
1279 #endif
1280
1281     pthread_mutex_unlock(&lock);
1282     return 1;
1283 }
1284
1285 struct realm *id2realm(char *id, uint8_t len) {
1286     struct list_node *entry;
1287     struct realm *realm;
1288     
1289     for (entry = list_first(realms); entry; entry = list_next(entry)) {
1290         realm = (struct realm *)entry->data;
1291         if (!regexec(&realm->regex, id, 0, NULL, 0)) {
1292             debug(DBG_DBG, "found matching realm: %s", realm->name);
1293             return realm;
1294         }
1295     }
1296     return NULL;
1297 }
1298
1299 int rqinqueue(struct server *to, struct client *from, uint8_t id) {
1300     int i;
1301     
1302     pthread_mutex_lock(&to->newrq_mutex);
1303     for (i = 0; i < MAX_REQUESTS; i++)
1304         if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from)
1305             break;
1306     pthread_mutex_unlock(&to->newrq_mutex);
1307     
1308     return i < MAX_REQUESTS;
1309 }
1310
1311 int attrvalidate(unsigned char *attrs, int length) {
1312     while (length > 1) {
1313         if (ATTRLEN(attrs) < 2) {
1314             debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1315             return 0;
1316         }
1317         length -= ATTRLEN(attrs);
1318         if (length < 0) {
1319             debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1320             return 0;
1321         }
1322         attrs += ATTRLEN(attrs);
1323     }
1324     if (length)
1325         debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1326     return 1;
1327 }
1328
1329 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1330     if (len < 16 || len > 128 || len % 16) {
1331         debug(DBG_WARN, "pwdrecrypt: invalid password length");
1332         return 0;
1333     }
1334         
1335     if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1336         debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1337         return 0;
1338     }
1339 #ifdef DEBUG
1340     printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len);
1341 #endif  
1342     if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1343         debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1344         return 0;
1345     }
1346     return 1;
1347 }
1348
1349 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1350     if (len < 18)
1351         return 0;
1352     if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1353         debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1354         return 0;
1355     }
1356     if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1357         debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1358         return 0;
1359     }
1360     return 1;
1361 }
1362
1363 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1364            char *oldsecret, char *newsecret) {
1365     unsigned char *attr;
1366     
1367     for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1368         debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1369         if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1370             return 0;
1371     }
1372     return 1;
1373 }
1374
1375 /* returns a pointer to the resized attribute value */
1376 uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) {
1377     uint8_t *attrs, *attr, vallen;
1378     uint16_t len;
1379     unsigned char *new;
1380     
1381     len = RADLEN(*buf) - 20;
1382     attrs = *buf + 20;
1383
1384     attr = attrget(attrs, len, type);
1385     if (!attr)
1386         return NULL;
1387     
1388     vallen = ATTRVALLEN(attr);
1389     if (vallen == newvallen)
1390         return attr + 2;
1391
1392     len += newvallen - vallen;
1393     if (newvallen > vallen) {
1394         new = realloc(*buf, len);
1395         if (!new) {
1396             debug(DBG_ERR, "resizeattr: malloc failed");
1397             return NULL;
1398         }
1399         if (new != *buf) {
1400             attr += new - *buf;
1401             attrs = new + 20;
1402             *buf = new;
1403         }
1404     }
1405     memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen));
1406     attr[1] = newvallen + 2;
1407     ((uint16_t *)*buf)[1] = htons(len + 20);
1408     return attr + 2;
1409 }
1410                 
1411 int rewriteusername(struct request *rq, char *in) {
1412     size_t nmatch = 10, reslen = 0, start = 0;
1413     regmatch_t pmatch[10], *pfield;
1414     int i;
1415     unsigned char *result;
1416     char *out = rq->from->conf->rewriteattrreplacement;
1417     
1418     if (regexec(rq->from->conf->rewriteattrregex, in, nmatch, pmatch, 0)) {
1419         debug(DBG_DBG, "rewriteattr: username not matching, no rewrite");
1420         return 1;
1421     }
1422     
1423     rq->origusername = stringcopy(in, 0);
1424     if (!rq->origusername)
1425         return 0;
1426     
1427     for (i = start; out[i]; i++) {
1428         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1429             pfield = &pmatch[out[i + 1] - '0'];
1430             if (pfield->rm_so >= 0) {
1431                 reslen += i - start + pfield->rm_eo - pfield->rm_so;
1432                 start = i + 2;
1433             }
1434             i++;
1435         }
1436     }
1437     reslen += i - start;
1438
1439     result = resizeattr(&rq->buf, reslen, RAD_Attr_User_Name);
1440     if (!result)
1441         return 0;
1442     
1443     start = 0;
1444     reslen = 0;
1445     for (i = start; out[i]; i++) {
1446         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1447             pfield = &pmatch[out[i + 1] - '0'];
1448             if (pfield->rm_so >= 0) {
1449                 memcpy(result + reslen, out + start, i - start);
1450                 reslen += i - start;
1451                 memcpy(result + reslen, in + pfield->rm_so, pfield->rm_eo - pfield->rm_so);
1452                 reslen += pfield->rm_eo - pfield->rm_so;
1453                 start = i + 2;
1454             }
1455             i++;
1456         }
1457     }
1458
1459     memcpy(result + reslen, out + start, i - start);
1460     reslen += i - start;
1461     memcpy(in, result, reslen);
1462     in[reslen] = '\0';
1463     return 1;
1464 }
1465
1466 void acclog(unsigned char *attrs, int length, char *host) {
1467     unsigned char *attr;
1468     char username[256];
1469     
1470     attr = attrget(attrs, length, RAD_Attr_User_Name);
1471     if (!attr) {
1472         debug(DBG_INFO, "acclog: accounting-request from %s without username attribute", host);
1473         return;
1474     }
1475     memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1476     username[ATTRVALLEN(attr)] = '\0';
1477     debug(DBG_INFO, "acclog: accounting-request from %s with username: %s", host, username);
1478 }
1479         
1480 void respondaccounting(struct request *rq) {
1481     unsigned char *resp;
1482
1483     resp = malloc(20);
1484     if (!resp) {
1485         debug(DBG_ERR, "respondstatusserver: malloc failed");
1486         return;
1487     }
1488     memcpy(resp, rq->buf, 20);
1489     resp[0] = RAD_Accounting_Response;
1490     resp[2] = 0;
1491     resp[3] = 20;
1492     debug(DBG_DBG, "respondaccounting: responding to %s", rq->from->conf->host);
1493     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1494 }
1495
1496 void respondstatusserver(struct request *rq) {
1497     unsigned char *resp;
1498
1499     resp = malloc(20);
1500     if (!resp) {
1501         debug(DBG_ERR, "respondstatusserver: malloc failed");
1502         return;
1503     }
1504     memcpy(resp, rq->buf, 20);
1505     resp[0] = RAD_Access_Accept;
1506     resp[2] = 0;
1507     resp[3] = 20;
1508     debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
1509     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1510 }
1511
1512 void respondreject(struct request *rq, char *message) {
1513     unsigned char *resp;
1514     int len = 20;
1515
1516     if (message && *message)
1517         len += 2 + strlen(message);
1518     
1519     resp = malloc(len);
1520     if (!resp) {
1521         debug(DBG_ERR, "respondreject: malloc failed");
1522         return;
1523     }
1524     memcpy(resp, rq->buf, 20);
1525     resp[0] = RAD_Access_Reject;
1526     *(uint16_t *)(resp + 2) = htons(len);
1527     if (message && *message) {
1528         resp[20] = RAD_Attr_Reply_Message;
1529         resp[21] = len - 20;
1530         memcpy(resp + 22, message, len - 22);
1531     }
1532     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1533 }
1534
1535 struct server *realm2server(struct realm *realm) {
1536     struct list_node *entry;
1537     struct server *server, *best = NULL;
1538     
1539     for (entry = list_first(realm->srvconfs); entry; entry = list_next(entry)) {
1540         server = ((struct clsrvconf *)entry->data)->servers;
1541         if (!server->connectionok)
1542             continue;
1543         if (!server->loststatsrv)
1544             return server;
1545         if (!best) {
1546             best = server;
1547             continue;
1548         }
1549         if (server->loststatsrv < best->loststatsrv)
1550             best = server;
1551     }
1552     return best;
1553 }
1554
1555 void radsrv(struct request *rq) {
1556     uint8_t code, id, *auth, *attrs, *attr;
1557     uint16_t len;
1558     struct server *to = NULL;
1559     char username[256];
1560     unsigned char newauth[16];
1561     struct realm *realm = NULL;
1562     
1563     code = *(uint8_t *)rq->buf;
1564     id = *(uint8_t *)(rq->buf + 1);
1565     len = RADLEN(rq->buf);
1566     auth = (uint8_t *)(rq->buf + 4);
1567
1568     debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
1569     
1570     if (code != RAD_Access_Request && code != RAD_Status_Server && code != RAD_Accounting_Request) {
1571         debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring");
1572         freerqdata(rq);
1573         return;
1574     }
1575
1576     len -= 20;
1577     attrs = rq->buf + 20;
1578
1579     if (!attrvalidate(attrs, len)) {
1580         debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
1581         freerqdata(rq);
1582         return;
1583     }
1584
1585     attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1586     if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(rq->buf, ATTRVAL(attr), rq->from->conf->secret))) {
1587         debug(DBG_WARN, "radsrv: message authentication failed");
1588         freerqdata(rq);
1589         return;
1590     }
1591
1592     if (code != RAD_Access_Request) {
1593         switch (code) {
1594         case RAD_Accounting_Request:
1595             acclog(attrs, len, rq->from->conf->host);
1596             respondaccounting(rq);
1597             break;
1598         case RAD_Status_Server:
1599             respondstatusserver(rq);
1600             break;
1601         }
1602         freerqdata(rq);
1603         return;
1604     }
1605
1606     /* code == RAD_Access_Request */
1607     attr = attrget(attrs, len, RAD_Attr_User_Name);
1608     if (!attr) {
1609         debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
1610         freerqdata(rq);
1611         return;
1612     }
1613     memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1614     username[ATTRVALLEN(attr)] = '\0';
1615
1616     if (rq->from->conf->rewriteattrregex) {
1617         if (!rewriteusername(rq, username)) {
1618             debug(DBG_WARN, "radsrv: username malloc failed, ignoring request");
1619             freerqdata(rq);
1620             return;
1621         }
1622         len = RADLEN(rq->buf) - 20;
1623         auth = (uint8_t *)(rq->buf + 4);
1624         attrs = rq->buf + 20;
1625     }
1626
1627     if (rq->origusername)
1628         debug(DBG_DBG, "Access Request with username: %s (originally %s)", username, rq->origusername);
1629     else
1630         debug(DBG_DBG, "Access Request with username: %s", username);
1631         
1632     realm = id2realm(username, strlen(username));
1633     if (!realm) {
1634         debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1635         freerqdata(rq);
1636         return;
1637     }
1638         
1639     to = realm2server(realm);
1640     if (to && rqinqueue(to, rq->from, id)) {
1641         debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->conf->host, id);
1642         freerqdata(rq);
1643         return;
1644     }
1645
1646     if (!to) {
1647         if (realm->message) {
1648             debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->conf->host, username);
1649             respondreject(rq, realm->message);
1650         }
1651         freerqdata(rq);
1652         return;
1653     }
1654     
1655     if (!RAND_bytes(newauth, 16)) {
1656         debug(DBG_WARN, "radsrv: failed to generate random auth");
1657         freerqdata(rq);
1658         return;
1659     }
1660
1661 #ifdef DEBUG
1662     printfchars(NULL, "auth", "%02x ", auth, 16);
1663 #endif
1664
1665     attr = attrget(attrs, len, RAD_Attr_User_Password);
1666     if (attr) {
1667         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1668         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1669             freerqdata(rq);
1670             return;
1671         }
1672     }
1673     
1674     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1675     if (attr) {
1676         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1677         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1678             freerqdata(rq);
1679             return;
1680         }
1681     }
1682
1683     rq->origid = id;
1684     memcpy(rq->origauth, auth, 16);
1685     memcpy(auth, newauth, 16);
1686     sendrq(to, rq);
1687 }
1688
1689 int replyh(struct server *server, unsigned char *buf) {
1690     struct client *from;
1691     struct request *rq;
1692     int i, len, sublen;
1693     unsigned char *messageauth, *subattrs, *attrs, *attr, *username;
1694     struct sockaddr_storage fromsa;
1695     char tmp[256];
1696     
1697     server->connectionok = 1;
1698     server->loststatsrv = 0;
1699         
1700     i = buf[1]; /* i is the id */
1701
1702     switch (*buf) {
1703     case RAD_Access_Accept:
1704         debug(DBG_DBG, "got Access Accept with id %d", i);
1705         break;
1706     case RAD_Access_Reject:
1707         debug(DBG_DBG, "got Access Reject with id %d", i);
1708         break;
1709     case RAD_Access_Challenge:
1710         debug(DBG_DBG, "got Access Challenge with id %d", i);
1711         break;
1712     default:
1713         debug(DBG_INFO, "replyh: discarding, only accept access accept, access reject and access challenge messages");
1714         return 0;
1715     }
1716
1717     rq = server->requests + i;
1718         
1719     pthread_mutex_lock(&server->newrq_mutex);
1720     if (!rq->buf || !rq->tries) {
1721         pthread_mutex_unlock(&server->newrq_mutex);
1722         debug(DBG_INFO, "replyh: no matching request sent with this id, ignoring reply");
1723         return 0;
1724     }
1725
1726     if (rq->received) {
1727         pthread_mutex_unlock(&server->newrq_mutex);
1728         debug(DBG_INFO, "replyh: already received, ignoring reply");
1729         return 0;
1730     }
1731         
1732     if (!validauth(buf, rq->buf + 4, (unsigned char *)server->conf->secret)) {
1733         pthread_mutex_unlock(&server->newrq_mutex);
1734         debug(DBG_WARN, "replyh: invalid auth, ignoring reply");
1735         return 0;
1736     }
1737         
1738     from = rq->from;
1739     len = RADLEN(buf) - 20;
1740     attrs = buf + 20;
1741
1742     if (!attrvalidate(attrs, len)) {
1743         pthread_mutex_unlock(&server->newrq_mutex);
1744         debug(DBG_WARN, "replyh: attribute validation failed, ignoring reply");
1745         return 0;
1746     }
1747         
1748     /* Message Authenticator */
1749     messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1750     if (messageauth) {
1751         if (ATTRVALLEN(messageauth) != 16) {
1752             pthread_mutex_unlock(&server->newrq_mutex);
1753             debug(DBG_WARN, "replyh: illegal message auth attribute length, ignoring reply");
1754             return 0;
1755         }
1756         memcpy(tmp, buf + 4, 16);
1757         memcpy(buf + 4, rq->buf + 4, 16);
1758         if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
1759             pthread_mutex_unlock(&server->newrq_mutex);
1760             debug(DBG_WARN, "replyh: message authentication failed, ignoring reply");
1761             return 0;
1762         }
1763         memcpy(buf + 4, tmp, 16);
1764         debug(DBG_DBG, "replyh: message auth ok");
1765     }
1766         
1767     if (*rq->buf == RAD_Status_Server) {
1768         rq->received = 1;
1769         pthread_mutex_unlock(&server->newrq_mutex);
1770         debug(DBG_INFO, "replyh: got status server response from %s", server->conf->host);
1771         return 0;
1772     }
1773
1774     /* MS MPPE */
1775     for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
1776         if (ATTRVALLEN(attr) <= 4)
1777             break;
1778             
1779         if (attr[2] != 0 || attr[3] != 0 || attr[4] != 1 || attr[5] != 55)  /* 311 == MS */
1780             continue;
1781             
1782         sublen = ATTRVALLEN(attr) - 4;
1783         subattrs = ATTRVAL(attr) + 4;  
1784         if (!attrvalidate(subattrs, sublen) ||
1785             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1786                     rq, server->conf->secret, from->conf->secret) ||
1787             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1788                     rq, server->conf->secret, from->conf->secret))
1789             break;
1790     }
1791     if (attr) {
1792         pthread_mutex_unlock(&server->newrq_mutex);
1793         debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
1794         return 0;
1795     }
1796         
1797     if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject) {
1798         attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_User_Name);
1799         /* we know the attribute exists */
1800         memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
1801         tmp[ATTRVALLEN(attr)] = '\0';
1802         switch (*buf) {
1803         case RAD_Access_Accept:
1804             if (rq->origusername)
1805                 debug(DBG_INFO, "Access Accept for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1806             else
1807                 debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->conf->host);
1808             break;
1809         case RAD_Access_Reject:
1810             if (rq->origusername)
1811                 debug(DBG_INFO, "Access Reject for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1812             else
1813                 debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->conf->host);
1814             break;
1815         }
1816     }
1817         
1818     buf[1] = (char)rq->origid;
1819     memcpy(buf + 4, rq->origauth, 16);
1820 #ifdef DEBUG    
1821     printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
1822 #endif
1823
1824     if (rq->origusername) {
1825         username = resizeattr(&buf, strlen(rq->origusername), RAD_Attr_User_Name);
1826         if (!username) {
1827             pthread_mutex_unlock(&server->newrq_mutex);
1828             debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
1829             return 0;
1830         }
1831         memcpy(username, rq->origusername, strlen(rq->origusername));
1832         len = RADLEN(buf) - 20;
1833         attrs = buf + 20;
1834         if (messageauth)
1835             messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1836     }
1837         
1838     if (messageauth) {
1839         if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
1840             pthread_mutex_unlock(&server->newrq_mutex);
1841             debug(DBG_WARN, "replyh: failed to create authenticator, malloc failed?, ignoring reply");
1842             return 0;
1843         }
1844         debug(DBG_DBG, "replyh: computed messageauthattr");
1845     }
1846
1847     if (from->conf->type == 'U')
1848         fromsa = rq->fromsa;
1849     /* once we set received = 1, rq may be reused */
1850     rq->received = 1;
1851     pthread_mutex_unlock(&server->newrq_mutex);
1852
1853     debug(DBG_DBG, "replyh: giving packet back to where it came from");
1854     sendreply(from, buf, from->conf->type == 'U' ? &fromsa : NULL);
1855     return 1;
1856 }
1857
1858 void *udpclientrd(void *arg) {
1859     struct server *server;
1860     unsigned char *buf;
1861     int *s = (int *)arg;
1862     
1863     for (;;) {
1864         server = NULL;
1865         buf = radudpget(*s, NULL, &server, NULL);
1866         if (!replyh(server, buf))
1867             free(buf);
1868     }
1869 }
1870
1871 void *tlsclientrd(void *arg) {
1872     struct server *server = (struct server *)arg;
1873     unsigned char *buf;
1874     struct timeval lastconnecttry;
1875     
1876     for (;;) {
1877         /* yes, lastconnecttry is really necessary */
1878         lastconnecttry = server->lastconnecttry;
1879         buf = radtlsget(server->ssl);
1880         if (!buf) {
1881             tlsconnect(server, &lastconnecttry, "clientrd");
1882             continue;
1883         }
1884
1885         if (!replyh(server, buf))
1886             free(buf);
1887     }
1888 }
1889
1890 void *clientwr(void *arg) {
1891     struct server *server = (struct server *)arg;
1892     struct request *rq;
1893     pthread_t tlsclientrdth;
1894     int i;
1895     uint8_t rnd;
1896     struct timeval now, lastsend;
1897     struct timespec timeout;
1898     struct request statsrvrq;
1899     unsigned char statsrvbuf[38];
1900
1901     memset(&timeout, 0, sizeof(struct timespec));
1902     
1903     if (server->conf->statusserver) {
1904         memset(&statsrvrq, 0, sizeof(struct request));
1905         memset(statsrvbuf, 0, sizeof(statsrvbuf));
1906         statsrvbuf[0] = RAD_Status_Server;
1907         statsrvbuf[3] = 38;
1908         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
1909         statsrvbuf[21] = 18;
1910         gettimeofday(&lastsend, NULL);
1911     }
1912     
1913     if (server->conf->type == 'U') {
1914         server->connectionok = 1;
1915     } else {
1916         tlsconnect(server, NULL, "new client");
1917         server->connectionok = 1;
1918         if (pthread_create(&tlsclientrdth, NULL, tlsclientrd, (void *)server))
1919             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
1920     }
1921     
1922     for (;;) {
1923         pthread_mutex_lock(&server->newrq_mutex);
1924         if (!server->newrq) {
1925             gettimeofday(&now, NULL);
1926             if (server->conf->statusserver) {
1927                 /* random 0-7 seconds */
1928                 RAND_bytes(&rnd, 1);
1929                 rnd /= 32;
1930                 if (!timeout.tv_sec || timeout.tv_sec - now.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
1931                     timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
1932             }   
1933             if (timeout.tv_sec) {
1934                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1935                 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1936                 timeout.tv_sec = 0;
1937             } else {
1938                 debug(DBG_DBG, "clientwr: waiting for new request");
1939                 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
1940             }
1941         }
1942         if (server->newrq) {
1943             debug(DBG_DBG, "clientwr: got new request");
1944             server->newrq = 0;
1945         } else
1946             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1947         pthread_mutex_unlock(&server->newrq_mutex);
1948
1949         for (i = 0; i < MAX_REQUESTS; i++) {
1950             pthread_mutex_lock(&server->newrq_mutex);
1951             while (i < MAX_REQUESTS && !server->requests[i].buf)
1952                 i++;
1953             if (i == MAX_REQUESTS) {
1954                 pthread_mutex_unlock(&server->newrq_mutex);
1955                 break;
1956             }
1957             rq = server->requests + i;
1958
1959             if (rq->received) {
1960                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
1961                 if (rq->buf) {
1962                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
1963                     freerqdata(rq);
1964                     /* setting this to NULL means that it can be reused */
1965                     rq->buf = NULL;
1966                 }
1967                 pthread_mutex_unlock(&server->newrq_mutex);
1968                 continue;
1969             }
1970             
1971             gettimeofday(&now, NULL);
1972             if (now.tv_sec < rq->expiry.tv_sec) {
1973                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1974                     timeout.tv_sec = rq->expiry.tv_sec;
1975                 pthread_mutex_unlock(&server->newrq_mutex);
1976                 continue;
1977             }
1978
1979             if (rq->tries == (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1980                               ? 1 : REQUEST_RETRIES)) {
1981                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1982                 if (*rq->buf == RAD_Status_Server) {
1983                     debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->conf->host);
1984                     if (server->loststatsrv < 255)
1985                         server->loststatsrv++;
1986                 }
1987                 freerqdata(rq);
1988                 /* setting this to NULL means that it can be reused */
1989                 rq->buf = NULL;
1990                 pthread_mutex_unlock(&server->newrq_mutex);
1991                 continue;
1992             }
1993             pthread_mutex_unlock(&server->newrq_mutex);
1994
1995             rq->expiry.tv_sec = now.tv_sec +
1996                 (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1997                  ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
1998             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1999                 timeout.tv_sec = rq->expiry.tv_sec;
2000             rq->tries++;
2001             clientradput(server, server->requests[i].buf);
2002             gettimeofday(&lastsend, NULL);
2003         }
2004         if (server->conf->statusserver) {
2005             gettimeofday(&now, NULL);
2006             if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
2007                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
2008                     debug(DBG_WARN, "clientwr: failed to generate random auth");
2009                     continue;
2010                 }
2011                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
2012                 if (!statsrvrq.buf) {
2013                     debug(DBG_ERR, "clientwr: malloc failed");
2014                     continue;
2015                 }
2016                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
2017                 debug(DBG_DBG, "clientwr: sending status server to %s", server->conf->host);
2018                 lastsend.tv_sec = now.tv_sec;
2019                 sendrq(server, &statsrvrq);
2020             }
2021         }
2022     }
2023 }
2024
2025 void *udpserverwr(void *arg) {
2026     struct replyq *replyq = udp_server_replyq;
2027     struct reply *reply;
2028     
2029     for (;;) {
2030         pthread_mutex_lock(&replyq->mutex);
2031         while (!(reply = (struct reply *)list_shift(replyq->replies))) {
2032             debug(DBG_DBG, "udp server writer, waiting for signal");
2033             pthread_cond_wait(&replyq->cond, &replyq->mutex);
2034             debug(DBG_DBG, "udp server writer, got signal");
2035         }
2036         pthread_mutex_unlock(&replyq->mutex);
2037
2038         if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
2039                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
2040             debug(DBG_WARN, "sendudp: send failed");
2041         free(reply->buf);
2042         free(reply);
2043     }
2044 }
2045
2046 void *udpserverrd(void *arg) {
2047     struct request rq;
2048     pthread_t udpserverwrth;
2049     struct clsrvconf *listenres;
2050
2051     listenres = resolve_hostport('U', options.listenudp, DEFAULT_UDP_PORT);
2052     if ((udp_server_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2053         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2054
2055     debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
2056           listenres->host ? listenres->host : "*", listenres->port);
2057     free(listenres);
2058     
2059     if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
2060         debugx(1, DBG_ERR, "pthread_create failed");
2061     
2062     for (;;) {
2063         memset(&rq, 0, sizeof(struct request));
2064         rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
2065         radsrv(&rq);
2066     }
2067 }
2068
2069 void *udpaccserverrd(void *arg) {
2070     struct request rq;
2071     struct clsrvconf *listenres;
2072     
2073     listenres = resolve_hostport('U', options.listenaccudp, DEFAULT_UDP_PORT);
2074     if ((udp_accserver_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2075         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2076
2077     debug(DBG_WARN, "udpaccserverrd: listening for UDP on %s:%s",
2078           listenres->host ? listenres->host : "*", listenres->port);
2079     free(listenres);
2080     
2081     for (;;) {
2082         memset(&rq, 0, sizeof(struct request));
2083         rq.buf = radudpget(udp_accserver_sock, &rq.from, NULL, &rq.fromsa);
2084         if (*(uint8_t *)rq.buf == RAD_Accounting_Request) {
2085             radsrv(&rq);
2086             continue;
2087         }
2088         debug(DBG_INFO, "udpaccserverrd: got something other than accounting-request, ignoring");
2089         freerqdata(&rq);
2090     }
2091 }
2092
2093 void *tlsserverwr(void *arg) {
2094     int cnt;
2095     unsigned long error;
2096     struct client *client = (struct client *)arg;
2097     struct replyq *replyq;
2098     struct reply *reply;
2099     
2100     debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
2101     replyq = client->replyq;
2102     for (;;) {
2103         pthread_mutex_lock(&replyq->mutex);
2104         while (!list_first(replyq->replies)) {
2105             if (client->ssl) {      
2106                 debug(DBG_DBG, "tls server writer, waiting for signal");
2107                 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2108                 debug(DBG_DBG, "tls server writer, got signal");
2109             }
2110             if (!client->ssl) {
2111                 /* ssl might have changed while waiting */
2112                 pthread_mutex_unlock(&replyq->mutex);
2113                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
2114                 pthread_exit(NULL);
2115             }
2116         }
2117         reply = (struct reply *)list_shift(replyq->replies);
2118         pthread_mutex_unlock(&replyq->mutex);
2119         cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
2120         if (cnt > 0)
2121             debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
2122                   cnt, RADLEN(reply->buf));
2123         else
2124             while ((error = ERR_get_error()))
2125                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
2126         free(reply->buf);
2127         free(reply);
2128     }
2129 }
2130
2131 void *tlsserverrd(void *arg) {
2132     struct request rq;
2133     unsigned long error;
2134     int s;
2135     struct client *client = (struct client *)arg;
2136     pthread_t tlsserverwrth;
2137     SSL *ssl;
2138     
2139     debug(DBG_DBG, "tlsserverrd starting for %s", client->conf->host);
2140     ssl = client->ssl;
2141
2142     if (SSL_accept(ssl) <= 0) {
2143         while ((error = ERR_get_error()))
2144             debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
2145         debug(DBG_ERR, "SSL_accept failed");
2146         goto errexit;
2147     }
2148     if (tlsverifycert(client->ssl, client->conf)) {
2149         if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
2150             debug(DBG_ERR, "tlsserverrd: pthread_create failed");
2151             goto errexit;
2152         }
2153         for (;;) {
2154             memset(&rq, 0, sizeof(struct request));
2155             rq.buf = radtlsget(client->ssl);
2156             if (!rq.buf)
2157                 break;
2158             debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
2159             rq.from = client;
2160             radsrv(&rq);
2161         }
2162         debug(DBG_ERR, "tlsserverrd: connection lost");
2163         /* stop writer by setting ssl to NULL and give signal in case waiting for data */
2164         client->ssl = NULL;
2165         pthread_mutex_lock(&client->replyq->mutex);
2166         pthread_cond_signal(&client->replyq->cond);
2167         pthread_mutex_unlock(&client->replyq->mutex);
2168         debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
2169         pthread_join(tlsserverwrth, NULL);
2170     }
2171     
2172  errexit:
2173     s = SSL_get_fd(ssl);
2174     SSL_free(ssl);
2175     shutdown(s, SHUT_RDWR);
2176     close(s);
2177     debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->conf->host);
2178     removeclient(client);
2179     pthread_exit(NULL);
2180 }
2181
2182 int tlslistener() {
2183     pthread_t tlsserverth;
2184     int s, snew;
2185     struct sockaddr_storage from;
2186     size_t fromlen = sizeof(from);
2187     struct clsrvconf *conf;
2188     struct client *client;
2189     struct clsrvconf *listenres;
2190     
2191     listenres = resolve_hostport('T', options.listentcp, DEFAULT_TLS_PORT);
2192     if ((s = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2193         debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
2194     
2195     listen(s, 0);
2196     debug(DBG_WARN, "listening for incoming TCP on %s:%s", listenres->host ? listenres->host : "*", listenres->port);
2197     free(listenres);
2198     
2199     for (;;) {
2200         snew = accept(s, (struct sockaddr *)&from, &fromlen);
2201         if (snew < 0) {
2202             debug(DBG_WARN, "accept failed");
2203             continue;
2204         }
2205         debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
2206
2207         conf = find_conf('T', (struct sockaddr *)&from, clconfs, NULL);
2208         if (!conf) {
2209             debug(DBG_WARN, "ignoring request, not a known TLS client");
2210             shutdown(snew, SHUT_RDWR);
2211             close(snew);
2212             continue;
2213         }
2214
2215         client = addclient(conf);
2216
2217         if (!client) {
2218             debug(DBG_WARN, "Failed to create new client instance");
2219             shutdown(snew, SHUT_RDWR);
2220             close(snew);
2221             continue;
2222         }
2223         client->ssl = SSL_new(client->conf->ssl_ctx);
2224         SSL_set_fd(client->ssl, snew);
2225         if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
2226             debug(DBG_ERR, "tlslistener: pthread_create failed");
2227             SSL_free(client->ssl);
2228             removeclient(client);
2229             shutdown(snew, SHUT_RDWR);
2230             close(snew);
2231             continue;
2232         }
2233         pthread_detach(tlsserverth);
2234     }
2235     return 0;
2236 }
2237
2238 void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, char *certkeyfile, char *certkeypwd) {
2239     struct tls *new;
2240     SSL_CTX *ctx;
2241     STACK_OF(X509_NAME) *calist;
2242     int i;
2243     unsigned long error;
2244     
2245     if (!certfile || !certkeyfile)
2246         debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified in TLS context %s", value);
2247
2248     if (!cacertfile && !cacertpath)
2249         debugx(1, DBG_ERR, "CA Certificate file or path need to be specified in TLS context %s", value);
2250
2251     if (!ssl_locks) {
2252         ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
2253         ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
2254         for (i = 0; i < CRYPTO_num_locks(); i++) {
2255             ssl_lock_count[i] = 0;
2256             pthread_mutex_init(&ssl_locks[i], NULL);
2257         }
2258         CRYPTO_set_id_callback(ssl_thread_id);
2259         CRYPTO_set_locking_callback(ssl_locking_callback);
2260
2261         SSL_load_error_strings();
2262         SSL_library_init();
2263
2264         while (!RAND_status()) {
2265             time_t t = time(NULL);
2266             pid_t pid = getpid();
2267             RAND_seed((unsigned char *)&t, sizeof(time_t));
2268             RAND_seed((unsigned char *)&pid, sizeof(pid));
2269         }
2270     }
2271     ctx = SSL_CTX_new(TLSv1_method());
2272     if (certkeypwd) {
2273         SSL_CTX_set_default_passwd_cb_userdata(ctx, certkeypwd);
2274         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
2275     }
2276     if (!SSL_CTX_use_certificate_chain_file(ctx, certfile) ||
2277         !SSL_CTX_use_PrivateKey_file(ctx, certkeyfile, SSL_FILETYPE_PEM) ||
2278         !SSL_CTX_check_private_key(ctx) ||
2279         !SSL_CTX_load_verify_locations(ctx, cacertfile, cacertpath)) {
2280         while ((error = ERR_get_error()))
2281             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2282         debugx(1, DBG_ERR, "Error initialising SSL/TLS in TLS context %s", value);
2283     }
2284
2285     calist = cacertfile ? SSL_load_client_CA_file(cacertfile) : NULL;
2286     if (!cacertfile || calist) {
2287         if (cacertpath) {
2288             if (!calist)
2289                 calist = sk_X509_NAME_new_null();
2290             if (!SSL_add_dir_cert_subjects_to_stack(calist, cacertpath)) {
2291                 sk_X509_NAME_free(calist);
2292                 calist = NULL;
2293             }
2294         }
2295     }
2296     if (!calist) {
2297         while ((error = ERR_get_error()))
2298             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2299         debugx(1, DBG_ERR, "Error adding CA subjects in TLS context %s", value);
2300     }
2301     SSL_CTX_set_client_CA_list(ctx, calist);
2302     
2303     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
2304     SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
2305
2306     new = malloc(sizeof(struct tls));
2307     if (!new || !list_push(tlsconfs, new))
2308         debugx(1, DBG_ERR, "malloc failed");
2309
2310     memset(new, 0, sizeof(struct tls));
2311     new->name = stringcopy(value, 0);
2312     if (!new->name)
2313         debugx(1, DBG_ERR, "malloc failed");
2314     new->ctx = ctx;
2315     new->count = 0;
2316     debug(DBG_DBG, "tlsadd: added TLS context %s", value);
2317 }
2318
2319 void tlsfree() {
2320     struct list_node *entry;
2321     struct tls *t;
2322     
2323     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2324         t = (struct tls *)entry->data;
2325         if (t->name)
2326             free(t->name);
2327         if (!t->count)
2328             SSL_CTX_free(t->ctx);
2329     }
2330     list_destroy(tlsconfs);
2331     tlsconfs = NULL;
2332 }
2333
2334 SSL_CTX *tlsgetctx(char *alt1, char *alt2) {
2335     struct list_node *entry;
2336     struct tls *t, *t1 = NULL, *t2 = NULL;
2337     
2338     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2339         t = (struct tls *)entry->data;
2340         if (!strcasecmp(t->name, alt1)) {
2341             t1 = t;
2342             break;
2343         }
2344         if (!t2 && alt2 && !strcasecmp(t->name, alt2))
2345             t2 = t;
2346     }
2347
2348     t = (t1 ? t1 : t2);
2349     if (!t)
2350         return NULL;
2351     t->count++;
2352     return t->ctx;
2353 }
2354
2355 void addrealm(char *value, char **servers, char *message) {
2356     int n;
2357     struct realm *realm;
2358     char *s, *regex = NULL;
2359     struct list_node *entry;
2360     struct clsrvconf *conf;
2361     
2362     if (*value == '/') {
2363         /* regexp, remove optional trailing / if present */
2364         if (value[strlen(value) - 1] == '/')
2365             value[strlen(value) - 1] = '\0';
2366     } else {
2367         /* not a regexp, let us make it one */
2368         if (*value == '*' && !value[1])
2369             regex = stringcopy(".*", 0);
2370         else {
2371             for (n = 0, s = value; *s;)
2372                 if (*s++ == '.')
2373                     n++;
2374             regex = malloc(strlen(value) + n + 3);
2375             if (regex) {
2376                 regex[0] = '@';
2377                 for (n = 1, s = value; *s; s++) {
2378                     if (*s == '.')
2379                         regex[n++] = '\\';
2380                     regex[n++] = *s;
2381                 }
2382                 regex[n++] = '$';
2383                 regex[n] = '\0';
2384             }
2385         }
2386         if (!regex)
2387             debugx(1, DBG_ERR, "malloc failed");
2388         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
2389     }
2390
2391     realm = malloc(sizeof(struct realm));
2392     if (!realm)
2393         debugx(1, DBG_ERR, "malloc failed");
2394     
2395     memset(realm, 0, sizeof(struct realm));
2396     realm->name = stringcopy(value, 0);
2397     if (!realm->name)
2398         debugx(1, DBG_ERR, "malloc failed");
2399     if (message && strlen(message) > 253)
2400         debugx(1, DBG_ERR, "ReplyMessage can be at most 253 bytes");
2401     realm->message = message;
2402     
2403     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
2404         debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
2405     if (regex)
2406         free(regex);
2407     
2408     if (servers && *servers) {
2409         realm->srvconfs = list_create();
2410         if (!realm->srvconfs)
2411             debugx(1, DBG_ERR, "malloc failed");
2412         for (n = 0; servers[n]; n++) {
2413             for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2414                 conf = (struct clsrvconf *)entry->data;
2415                 if (!strcasecmp(servers[n], conf->name))
2416                     break;
2417             }
2418             if (!entry)
2419                 debugx(1, DBG_ERR, "addrealm failed, no server %s", servers[n]);
2420             if (!list_push(realm->srvconfs, conf))
2421                 debugx(1, DBG_ERR, "malloc failed");
2422             debug(DBG_DBG, "addrealm: added server %s for realm %s", conf->name, value);
2423         }
2424     } else
2425         realm->srvconfs = NULL;
2426     
2427     if (!list_push(realms, realm))
2428         debugx(1, DBG_ERR, "malloc failed");
2429     debug(DBG_DBG, "addrealm: added realm %s", value);
2430 }
2431
2432 FILE *openconfigfile(const char *filename) {
2433     FILE *f;
2434     char pathname[100], *base = NULL;
2435     
2436     f = fopen(filename, "r");
2437     if (f) {
2438         debug(DBG_DBG, "reading config file %s", filename);
2439         return f;
2440     }
2441
2442     if (strlen(filename) + 1 <= sizeof(pathname)) {
2443         /* basename() might modify the string */
2444         strcpy(pathname, filename);
2445         base = basename(pathname);
2446         f = fopen(base, "r");
2447     }
2448
2449     if (!f)
2450         debugx(1, DBG_ERR, "could not read config file %s nor %s\n%s", filename, base, strerror(errno));
2451     
2452     debug(DBG_DBG, "reading config file %s", base);
2453     return f;
2454 }
2455
2456 /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */
2457 char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) {
2458     char *t = s, *q, *r;
2459
2460     if (!t || !token || !del)
2461         return NULL;
2462     while (*t && strchr(del, *t))
2463         t++;
2464     if (!*t || (comment && strchr(comment, *t))) {
2465         *token = NULL;
2466         return t + 1; /* needs to be non-NULL, but value doesn't matter */
2467     }
2468     if (quote && (q = strchr(quote, *t))) {
2469         t++;
2470         r = t;
2471         while (*t && *t != *q)
2472             t++;
2473         if (!*t || (t[1] && !strchr(del, t[1])))
2474             return NULL;
2475         *t = '\0';
2476         *token = r;
2477         return t + 1;
2478     }
2479     *token = t;
2480     t++;
2481     while (*t && !strchr(del, *t))
2482         t++;
2483     *t = '\0';
2484     return t + 1;
2485 }
2486
2487 /* Parses config with following syntax:
2488  * One of these:
2489  * option-name value
2490  * option-name = value
2491  * Or:
2492  * option-name value {
2493  *     option-name [=] value
2494  *     ...
2495  * }
2496  */
2497 void getgeneralconfig(FILE *f, char *block, ...) {
2498     va_list ap;
2499     char line[1024];
2500     /* initialise lots of stuff to avoid stupid compiler warnings */
2501     char *tokens[3], *s, *opt = NULL, *val = NULL, *word, *optval, **str = NULL, ***mstr = NULL;
2502     int type = 0, tcount, conftype = 0, n;
2503     void (*cbk)(FILE *, char *, char *, char *) = NULL;
2504         
2505     while (fgets(line, 1024, f)) {
2506         s = line;
2507         for (tcount = 0; tcount < 3; tcount++) {
2508             s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#");
2509             if (!s)
2510                 debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line);
2511             if (!tokens[tcount])
2512                 break;
2513         }
2514         if (!tcount || **tokens == '#')
2515             continue;
2516
2517         if (**tokens == '}') {
2518             if (block)
2519                 return;
2520             debugx(1, DBG_ERR, "configuration error, found } with no matching {");
2521         }
2522             
2523         switch (tcount) {
2524         case 2:
2525             opt = tokens[0];
2526             val = tokens[1];
2527             conftype = CONF_STR;
2528             break;
2529         case 3:
2530             if (tokens[1][0] == '=' && tokens[1][1] == '\0') {
2531                 opt = tokens[0];
2532                 val = tokens[2];
2533                 conftype = CONF_STR;
2534                 break;
2535             }
2536             if (tokens[2][0] == '{' && tokens[2][1] == '\0') {
2537                 opt = tokens[0];
2538                 val = tokens[1];
2539                 conftype = CONF_CBK;
2540                 break;
2541             }
2542             /* fall through */
2543         default:
2544             if (block)
2545                 debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]);
2546             debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]);
2547         }
2548
2549         if (!*val)
2550             debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt);
2551         
2552         va_start(ap, block);
2553         while ((word = va_arg(ap, char *))) {
2554             type = va_arg(ap, int);
2555             switch (type) {
2556             case CONF_STR:
2557                 str = va_arg(ap, char **);
2558                 if (!str)
2559                     debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2560                 break;
2561             case CONF_MSTR:
2562                 mstr = va_arg(ap, char ***);
2563                 if (!mstr)
2564                     debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2565                 break;
2566             case CONF_CBK:
2567                 cbk = va_arg(ap, void (*)(FILE *, char *, char *, char *));
2568                 break;
2569             default:
2570                 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2571             }
2572             if (!strcasecmp(opt, word))
2573                 break;
2574         }
2575         va_end(ap);
2576         
2577         if (!word) {
2578             if (block)
2579                 debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt);
2580             debugx(1, DBG_ERR, "configuration error, unknown option %s", opt);
2581         }
2582
2583         if (((type == CONF_STR || type == CONF_MSTR) && conftype != CONF_STR) ||
2584             (type == CONF_CBK && conftype != CONF_CBK)) {
2585             if (block)
2586                 debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt);
2587             debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt);
2588         }
2589         
2590         switch (type) {
2591         case CONF_STR:
2592             if (block)
2593                 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
2594             else 
2595                 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
2596             if (*str)
2597                 debugx(1, DBG_ERR, "configuration error, option %s already set to %s", opt, *str);
2598             *str = stringcopy(val, 0);
2599             if (!*str)
2600                 debugx(1, DBG_ERR, "malloc failed");
2601             break;
2602         case CONF_MSTR:
2603             if (block)
2604                 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
2605             else 
2606                 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
2607             if (*mstr)
2608                 for (n = 0; (*mstr)[n]; n++);
2609             else
2610                 n = 0;
2611             *mstr = realloc(*mstr, sizeof(char *) * (n + 2));
2612             if (!*mstr)
2613                 debugx(1, DBG_ERR, "malloc failed");
2614             (*mstr)[n] = stringcopy(val, 0);
2615             (*mstr)[n + 1] = NULL;
2616             break;
2617         case CONF_CBK:
2618             optval = malloc(strlen(opt) + strlen(val) + 2);
2619             if (!optval)
2620                 debugx(1, DBG_ERR, "malloc failed");
2621             sprintf(optval, "%s %s", opt, val);
2622             cbk(f, optval, opt, val);
2623             free(optval);
2624             break;
2625         default:
2626             debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2627         }
2628     }
2629 }
2630
2631 int addmatchcertattr(struct clsrvconf *conf, char *matchcertattr) {
2632     char *v;
2633     
2634     v = matchcertattr + 20;
2635     if (strncasecmp(matchcertattr, "SubjectAltName:URI:/", 20) || !*v)
2636         return 0;
2637     /* regexp, remove optional trailing / if present */
2638     if (v[strlen(v) - 1] == '/')
2639         v[strlen(v) - 1] = '\0';
2640     if (!*v)
2641         return 0;
2642
2643     conf->certuriregex = malloc(sizeof(regex_t));
2644     if (!conf->certuriregex) {
2645         debug(DBG_ERR, "malloc failed");
2646         return 0;
2647     }
2648     if (regcomp(conf->certuriregex, v, REG_ICASE | REG_NOSUB)) {
2649         free(conf->certuriregex);
2650         conf->certuriregex = NULL;
2651         debug(DBG_ERR, "failed to compile regular expression %s", v);
2652         return 0;
2653     }
2654     return 1;
2655 }
2656
2657 int addrewriteattr(struct clsrvconf *conf, char *rewriteattr) {
2658     char *v, *w;
2659     
2660     v = rewriteattr + 11;
2661     if (strncasecmp(rewriteattr, "User-Name:/", 11) || !*v)
2662         return 0;
2663     /* regexp, remove optional trailing / if present */
2664     if (v[strlen(v) - 1] == '/')
2665         v[strlen(v) - 1] = '\0';
2666
2667     w = strchr(v, '/');
2668     if (!*w)
2669         return 0;
2670     *w = '\0';
2671     w++;
2672     
2673     conf->rewriteattrregex = malloc(sizeof(regex_t));
2674     if (!conf->rewriteattrregex) {
2675         debug(DBG_ERR, "malloc failed");
2676         return 0;
2677     }
2678
2679     conf->rewriteattrreplacement = stringcopy(w, 0);
2680     if (!conf->rewriteattrreplacement) {
2681         free(conf->rewriteattrregex);
2682         conf->rewriteattrregex = NULL;
2683         return 0;
2684     }
2685     
2686     if (regcomp(conf->rewriteattrregex, v, REG_ICASE | REG_EXTENDED)) {
2687         free(conf->rewriteattrregex);
2688         conf->rewriteattrregex = NULL;
2689         free(conf->rewriteattrreplacement);
2690         conf->rewriteattrreplacement = NULL;
2691         debug(DBG_ERR, "failed to compile regular expression %s", v);
2692         return 0;
2693     }
2694
2695     return 1;
2696 }
2697
2698 void confclient_cb(FILE *f, char *block, char *opt, char *val) {
2699     char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewriteattr = NULL;
2700     struct clsrvconf *conf;
2701     
2702     debug(DBG_DBG, "confclient_cb called for %s", block);
2703
2704     conf = malloc(sizeof(struct clsrvconf));
2705     if (!conf || !list_push(clconfs, conf))
2706         debugx(1, DBG_ERR, "malloc failed");
2707     memset(conf, 0, sizeof(struct clsrvconf));
2708     
2709     getgeneralconfig(f, block,
2710                      "type", CONF_STR, &type,
2711                      "host", CONF_STR, &conf->host,
2712                      "secret", CONF_STR, &conf->secret,
2713                      "tls", CONF_STR, &tls,
2714                      "matchcertificateattribute", CONF_STR, &matchcertattr,
2715                      "rewriteattribute", CONF_STR, &rewriteattr,
2716                      NULL
2717                      );
2718
2719     /* leave conf->name to be NULL for clients */
2720     if (!conf->host)
2721         conf->host = stringcopy(val, 0);
2722     
2723     if (type && !strcasecmp(type, "udp")) {
2724         conf->type = 'U';
2725         client_udp_count++;
2726     } else if (type && !strcasecmp(type, "tls")) {
2727         conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultclient", "default");
2728         if (!conf->ssl_ctx)
2729             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2730         if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2731             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2732         conf->type = 'T';
2733         client_tls_count++;
2734     } else
2735         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2736     free(type);
2737     if (tls)
2738         free(tls);
2739     if (matchcertattr)
2740         free(matchcertattr);
2741     
2742     if (rewriteattr) {
2743         if (!addrewriteattr(conf, rewriteattr))
2744             debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
2745         free(rewriteattr);
2746     }
2747     
2748     if (!resolvepeer(conf, 0))
2749         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2750     
2751     if (!conf->secret) {
2752         if (conf->type == 'U')
2753             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2754         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2755     }
2756 }
2757
2758 void confserver_cb(FILE *f, char *block, char *opt, char *val) {
2759     char *type = NULL, *tls = NULL, *matchcertattr = NULL, *statusserver = NULL;
2760     struct clsrvconf *conf;
2761     
2762     debug(DBG_DBG, "confserver_cb called for %s", block);
2763
2764     conf = malloc(sizeof(struct clsrvconf));
2765     if (!conf || !list_push(srvconfs, conf))
2766         debugx(1, DBG_ERR, "malloc failed");
2767     memset(conf, 0, sizeof(struct clsrvconf));
2768     
2769     getgeneralconfig(f, block,
2770                      "type", CONF_STR, &type,
2771                      "host", CONF_STR, &conf->host,
2772                      "port", CONF_STR, &conf->port,
2773                      "secret", CONF_STR, &conf->secret,
2774                      "tls", CONF_STR, &tls,
2775                      "matchcertificateattribute", CONF_STR, &matchcertattr,
2776                      "StatusServer", CONF_STR, &statusserver,
2777                      NULL
2778                      );
2779
2780     conf->name = stringcopy(val, 0);
2781     if (!conf->host)
2782         conf->host = stringcopy(val, 0);
2783     
2784     if (type && !strcasecmp(type, "udp")) {
2785         conf->type = 'U';
2786         server_udp_count++;
2787         if (!conf->port)
2788             conf->port = stringcopy(DEFAULT_UDP_PORT, 0);
2789     } else if (type && !strcasecmp(type, "tls")) {
2790         conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultserver", "default");
2791         if (!conf->ssl_ctx)
2792             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2793         if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2794             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2795         if (!conf->port)
2796             conf->port = stringcopy(DEFAULT_TLS_PORT, 0);
2797         conf->type = 'T';
2798         server_tls_count++;
2799     } else
2800         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2801     free(type);
2802     if (tls)
2803         free(tls);
2804     if (matchcertattr)
2805         free(matchcertattr);
2806     
2807     if (!resolvepeer(conf, 0))
2808         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2809     
2810     if (!conf->secret) {
2811         if (conf->type == 'U')
2812             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2813         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2814     }
2815     
2816     if (statusserver) {
2817         if (!strcasecmp(statusserver, "on"))
2818             conf->statusserver = 1;
2819         else if (strcasecmp(statusserver, "off"))
2820             debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
2821         free(statusserver);
2822     }
2823 }
2824
2825 void confrealm_cb(FILE *f, char *block, char *opt, char *val) {
2826     char **servers = NULL, *msg = NULL;
2827     
2828     debug(DBG_DBG, "confrealm_cb called for %s", block);
2829     
2830     getgeneralconfig(f, block,
2831                      "server", CONF_MSTR, &servers,
2832                      "ReplyMessage", CONF_STR, &msg,
2833                      NULL
2834                      );
2835
2836     addrealm(val, servers, msg);
2837     free(servers);
2838 }
2839
2840 void conftls_cb(FILE *f, char *block, char *opt, char *val) {
2841     char *cacertfile = NULL, *cacertpath = NULL, *certfile = NULL, *certkeyfile = NULL, *certkeypwd = NULL;
2842     
2843     debug(DBG_DBG, "conftls_cb called for %s", block);
2844     
2845     getgeneralconfig(f, block,
2846                      "CACertificateFile", CONF_STR, &cacertfile,
2847                      "CACertificatePath", CONF_STR, &cacertpath,
2848                      "CertificateFile", CONF_STR, &certfile,
2849                      "CertificateKeyFile", CONF_STR, &certkeyfile,
2850                      "CertificateKeyPassword", CONF_STR, &certkeypwd,
2851                      NULL
2852                      );
2853     
2854     tlsadd(val, cacertfile, cacertpath, certfile, certkeyfile, certkeypwd);
2855     free(cacertfile);
2856     free(cacertpath);
2857     free(certfile);
2858     free(certkeyfile);
2859     free(certkeypwd);
2860 }
2861
2862 void getmainconfig(const char *configfile) {
2863     FILE *f;
2864     char *loglevel = NULL;
2865
2866     f = openconfigfile(configfile);
2867     memset(&options, 0, sizeof(options));
2868     
2869     clconfs = list_create();
2870     if (!clconfs)
2871         debugx(1, DBG_ERR, "malloc failed");
2872     
2873     srvconfs = list_create();
2874     if (!srvconfs)
2875         debugx(1, DBG_ERR, "malloc failed");
2876     
2877     realms = list_create();
2878     if (!realms)
2879         debugx(1, DBG_ERR, "malloc failed");    
2880  
2881     tlsconfs = list_create();
2882     if (!tlsconfs)
2883         debugx(1, DBG_ERR, "malloc failed");    
2884  
2885     getgeneralconfig(f, NULL,
2886                      "ListenUDP", CONF_STR, &options.listenudp,
2887                      "ListenTCP", CONF_STR, &options.listentcp,
2888                      "ListenAccountingUDP", CONF_STR, &options.listenaccudp,
2889                      "SourceUDP", CONF_STR, &options.sourceudp,
2890                      "SourceTCP", CONF_STR, &options.sourcetcp,
2891                      "LogLevel", CONF_STR, &loglevel,
2892                      "LogDestination", CONF_STR, &options.logdestination,
2893                      "Client", CONF_CBK, confclient_cb,
2894                      "Server", CONF_CBK, confserver_cb,
2895                      "Realm", CONF_CBK, confrealm_cb,
2896                      "TLS", CONF_CBK, conftls_cb,
2897                      NULL
2898                      );
2899     fclose(f);
2900     tlsfree();
2901     
2902     if (loglevel) {
2903         if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
2904             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
2905         options.loglevel = *loglevel - '0';
2906         free(loglevel);
2907     }
2908 }
2909
2910 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile) {
2911     int c;
2912
2913     while ((c = getopt(argc, argv, "c:d:fpv")) != -1) {
2914         switch (c) {
2915         case 'c':
2916             *configfile = optarg;
2917             break;
2918         case 'd':
2919             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
2920                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
2921             *loglevel = *optarg - '0';
2922             break;
2923         case 'f':
2924             *foreground = 1;
2925             break;
2926         case 'p':
2927             *pretend = 1;
2928             break;
2929         case 'v':
2930                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
2931         default:
2932             goto usage;
2933         }
2934     }
2935     if (!(argc - optind))
2936         return;
2937
2938  usage:
2939     debug(DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -p ] [ -v ]", argv[0]);
2940     exit(1);
2941 }
2942
2943 int main(int argc, char **argv) {
2944     pthread_t udpserverth, udpaccserverth, udpclient4rdth, udpclient6rdth;
2945     struct list_node *entry;
2946     uint8_t foreground = 0, pretend = 0, loglevel = 0;
2947     char *configfile = NULL;
2948     
2949     debug_init("radsecproxy");
2950     debug_set_level(DEBUG_LEVEL);
2951     getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile);
2952     if (loglevel)
2953         debug_set_level(loglevel);
2954     getmainconfig(configfile ? configfile : CONFIG_MAIN);
2955     if (loglevel)
2956         options.loglevel = loglevel;
2957     else if (options.loglevel)
2958         debug_set_level(options.loglevel);
2959     if (foreground)
2960         options.logdestination = NULL;
2961     else {
2962         if (!options.logdestination)
2963             options.logdestination = "x-syslog:///";
2964         debug_set_destination(options.logdestination);
2965     }
2966
2967     if (pretend)
2968         debugx(0, DBG_ERR, "All OK so far; exiting since only pretending");
2969     
2970     if (!list_first(clconfs))
2971         debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
2972     if (!list_first(srvconfs))
2973         debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
2974     if (!list_first(realms))
2975         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
2976
2977     if (!foreground && (daemon(0, 0) < 0))
2978         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
2979     
2980     debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
2981
2982     if (client_udp_count) {
2983         udp_server_replyq = newreplyq();
2984         if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
2985             debugx(1, DBG_ERR, "pthread_create failed");
2986         if (options.listenaccudp)
2987             if (pthread_create(&udpaccserverth, NULL, udpaccserverrd, NULL))
2988                 debugx(1, DBG_ERR, "pthread_create failed");
2989     }
2990     
2991     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2992         addserver((struct clsrvconf *)entry->data);
2993         if (pthread_create(&((struct clsrvconf *)entry->data)->servers->clientth, NULL, clientwr,
2994                            (void *)((struct clsrvconf *)entry->data)->servers))
2995             debugx(1, DBG_ERR, "pthread_create failed");
2996     }
2997     /* srcudpres no longer needed, while srctcpres is needed later */
2998     if (srcudpres) {
2999         free(srcudpres);
3000         srcudpres = NULL;
3001     }
3002     if (udp_client4_sock >= 0)
3003         if (pthread_create(&udpclient4rdth, NULL, udpclientrd, (void *)&udp_client4_sock))
3004             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
3005     if (udp_client6_sock >= 0)
3006         if (pthread_create(&udpclient6rdth, NULL, udpclientrd, (void *)&udp_client6_sock))
3007             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
3008     
3009     if (client_tls_count)
3010         return tlslistener();
3011     
3012     /* just hang around doing nothing, anything to do here? */
3013     for (;;)
3014         sleep(1000);
3015 }