simplified radudpget, minor dtls changes
[radsecproxy.git] / radsecproxy.c
1 /*
2  * Copyright (C) 2006-2008 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 /* Bugs:
33  * TCP accounting not yet supported
34  * We are not removing client requests from dynamic servers, see removeclientrqs()
35  */
36
37 #include <signal.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <netdb.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <limits.h>
44 #ifdef SYS_SOLARIS9
45 #include <fcntl.h>
46 #endif
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/select.h>
50 #include <ctype.h>
51 #include <sys/wait.h>
52 #include <arpa/inet.h>
53 #include <regex.h>
54 #include <libgen.h>
55 #include <pthread.h>
56 #include <openssl/ssl.h>
57 #include <openssl/rand.h>
58 #include <openssl/err.h>
59 #include <openssl/md5.h>
60 #include <openssl/hmac.h>
61 #include <openssl/x509v3.h>
62 #include "debug.h"
63 #include "list.h"
64 #include "util.h"
65 #include "gconfig.h"
66 #include "radsecproxy.h"
67
68 static struct options options;
69 struct list *clconfs, *srvconfs, *realms, *tlsconfs, *rewriteconfs;
70
71 static struct addrinfo *srcprotores[3] = { NULL, NULL, NULL };
72
73 static struct replyq *udp_server_replyq = NULL;
74 static int udp_client4_sock = -1;
75 static int udp_client6_sock = -1;
76 static pthread_mutex_t tlsconfs_lock;
77 static pthread_mutex_t *ssl_locks = NULL;
78 static long *ssl_lock_count;
79 extern int optind;
80 extern char *optarg;
81
82 /* minimum required declarations to avoid reordering code */
83 void adddynamicrealmserver(struct realm *realm, struct clsrvconf *conf, char *id);
84 int dynamicconfig(struct server *server);
85 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val);
86 void freerealm(struct realm *realm);
87 void freeclsrvconf(struct clsrvconf *conf);
88 void freerqdata(struct request *rq);
89 void *udpserverrd(void *arg);
90 void *tlslistener(void *arg);
91 void *tcplistener(void *arg);
92 int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text);
93 int dtlsinit(struct server *server, struct timeval *when, int timeout, char *text);
94 int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text);
95 void *udpclientrd(void *arg);
96 void *tlsclientrd(void *arg);
97 void *dtlsclientrd(void *arg);
98 void *tcpclientrd(void *arg);
99 int clientradputudp(struct server *server, unsigned char *rad);
100 int clientradputtls(struct server *server, unsigned char *rad);
101 int clientradputdtls(struct server *server, unsigned char *rad);
102 int clientradputtcp(struct server *server, unsigned char *rad);
103     
104 static const struct protodefs protodefs[] = {
105     {   "udp", /* UDP, assuming RAD_UDP defined as 0 */
106         NULL, /* secretdefault */
107         SOCK_DGRAM, /* socktype */
108         "1812", /* portdefault */
109         REQUEST_RETRY_COUNT, /* retrycountdefault */
110         10, /* retrycountmax */
111         REQUEST_RETRY_INTERVAL, /* retryintervaldefault */
112         60, /* retryintervalmax */
113         udpserverrd, /* listener */
114         &options.sourceudp, /* srcaddrport */
115         NULL, /* connecter */
116         udpclientrd, /* clientreader */
117         clientradputudp /* clientradput */
118     },
119     {   "tls", /* TLS, assuming RAD_TLS defined as 1 */
120         "mysecret", /* secretdefault */
121         SOCK_STREAM, /* socktype */
122         "2083", /* portdefault */
123         0, /* retrycountdefault */
124         0, /* retrycountmax */
125         REQUEST_RETRY_INTERVAL * REQUEST_RETRY_COUNT, /* retryintervaldefault */
126         60, /* retryintervalmax */
127         tlslistener, /* listener */
128         &options.sourcetls, /* srcaddrport */
129         tlsconnect, /* connecter */
130         tlsclientrd, /* clientreader */
131         clientradputtls /* clientradput */
132     },
133     {   "tcp", /* TCP, assuming RAD_TCP defined as 2 */
134         NULL, /* secretdefault */
135         SOCK_STREAM, /* socktype */
136         "1812", /* portdefault */
137         0, /* retrycountdefault */
138         0, /* retrycountmax */
139         REQUEST_RETRY_INTERVAL * REQUEST_RETRY_COUNT, /* retryintervaldefault */
140         60, /* retryintervalmax */
141         tcplistener, /* listener */
142         &options.sourcetcp, /* srcaddrport */
143         tcpconnect, /* connecter */
144         tcpclientrd, /* clientreader */
145         clientradputtcp /* clientradput */
146     },
147     {   "dtls", /* DTLS, assuming RAD_DTLS defined as 3 */
148         NULL, /* secretdefault */
149         SOCK_DGRAM, /* socktype */
150         "1812", /* portdefault */
151         REQUEST_RETRY_COUNT, /* retrycountdefault */
152         10, /* retrycountmax */
153         REQUEST_RETRY_INTERVAL, /* retryintervaldefault */
154         60, /* retryintervalmax */
155         NULL, /* listener */
156         &options.sourceudp, /* srcaddrport */
157         dtlsinit, /* connecter */
158         dtlsclientrd, /* clientreader */
159         clientradputdtls /* clientradput */
160     },
161     {   NULL
162     }
163 };
164
165 uint8_t protoname2int(const char *name) {
166     int i;
167
168     for (i = 0; protodefs[i].name && strcasecmp(protodefs[i].name, name); i++);
169     return i;
170 }
171     
172 /* callbacks for making OpenSSL thread safe */
173 unsigned long ssl_thread_id() {
174         return (unsigned long)pthread_self();
175 }
176
177 void ssl_locking_callback(int mode, int type, const char *file, int line) {
178     if (mode & CRYPTO_LOCK) {
179         pthread_mutex_lock(&ssl_locks[type]);
180         ssl_lock_count[type]++;
181     } else
182         pthread_mutex_unlock(&ssl_locks[type]);
183 }
184
185 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
186     int pwdlen = strlen(userdata);
187     if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
188         return 0;
189     memcpy(buf, userdata, pwdlen);
190     return pwdlen;
191 }
192
193 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
194   char buf[256];
195   X509 *err_cert;
196   int err, depth;
197
198   err_cert = X509_STORE_CTX_get_current_cert(ctx);
199   err = X509_STORE_CTX_get_error(ctx);
200   depth = X509_STORE_CTX_get_error_depth(ctx);
201
202   if (depth > MAX_CERT_DEPTH) {
203       ok = 0;
204       err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
205       X509_STORE_CTX_set_error(ctx, err);
206   }
207
208   if (!ok) {
209       X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
210       debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
211
212       switch (err) {
213       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
214           X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
215           debug(DBG_WARN, "\tIssuer=%s", buf);
216           break;
217       case X509_V_ERR_CERT_NOT_YET_VALID:
218       case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
219           debug(DBG_WARN, "\tCertificate not yet valid");
220           break;
221       case X509_V_ERR_CERT_HAS_EXPIRED:
222           debug(DBG_WARN, "Certificate has expired");
223           break;
224       case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
225           debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
226           break;
227       }
228   }
229 #ifdef DEBUG  
230   printf("certificate verify returns %d\n", ok);
231 #endif  
232   return ok;
233 }
234
235 int resolvepeer(struct clsrvconf *conf, int ai_flags) {
236     struct addrinfo hints, *addrinfo, *res;
237     char *slash, *s;
238     int plen = 0;
239
240     slash = conf->host ? strchr(conf->host, '/') : NULL;
241     if (slash) {
242         s = slash + 1;
243         if (!*s) {
244             debug(DBG_WARN, "resolvepeer: prefix length must be specified after the / in %s", conf->host);
245             return 0;
246         }
247         for (; *s; s++)
248             if (*s < '0' || *s > '9') {
249                 debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
250                 return 0;
251             }
252         plen = atoi(slash + 1);
253         if (plen < 0 || plen > 128) {
254             debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
255             return 0;
256         }
257         *slash = '\0';
258     }
259     memset(&hints, 0, sizeof(hints));
260     hints.ai_socktype = conf->pdef->socktype;
261     hints.ai_family = AF_UNSPEC;
262     hints.ai_flags = ai_flags;
263     if (!conf->host && !conf->port) {
264         /* getaddrinfo() doesn't like host and port to be NULL */
265         if (getaddrinfo(conf->host, conf->pdef->portdefault, &hints, &addrinfo)) {
266             debug(DBG_WARN, "resolvepeer: can't resolve (null) port (null)");
267             return 0;
268         }
269         for (res = addrinfo; res; res = res->ai_next) {
270             switch (res->ai_family) {
271             case AF_INET:
272                 ((struct sockaddr_in *)res->ai_addr)->sin_port = 0;
273                 break;
274             case AF_INET6:
275                 ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = 0;
276                 break;
277             }
278         }
279     } else {
280         if (slash)
281             hints.ai_flags |= AI_NUMERICHOST;
282         if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) {
283             debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
284             return 0;
285         }
286         if (slash) {
287             *slash = '/';
288             switch (addrinfo->ai_family) {
289             case AF_INET:
290                 if (plen > 32) {
291                     debug(DBG_WARN, "resolvepeer: prefix length must be <= 32 in %s", conf->host);
292                     freeaddrinfo(addrinfo);
293                     return 0;
294                 }
295                 break;
296             case AF_INET6:
297                 break;
298             default:
299                 debug(DBG_WARN, "resolvepeer: prefix must be IPv4 or IPv6 in %s", conf->host);
300                 freeaddrinfo(addrinfo);
301                 return 0;
302             }
303             conf->prefixlen = plen;
304         } else
305             conf->prefixlen = 255;
306     }
307     if (conf->addrinfo)
308         freeaddrinfo(conf->addrinfo);
309     conf->addrinfo = addrinfo;
310     return 1;
311 }         
312
313 int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) {
314     int s, on = 1;
315     struct addrinfo *res;
316     
317     for (res = addrinfo; res; res = res->ai_next) {
318         if (family != AF_UNSPEC && family != res->ai_family)
319             continue;
320         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
321         if (s < 0) {
322             debug(DBG_WARN, "bindtoaddr: socket failed");
323             continue;
324         }
325         if (reuse)
326             setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
327 #ifdef IPV6_V6ONLY
328         if (v6only)
329             setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
330 #endif          
331
332         if (!bind(s, res->ai_addr, res->ai_addrlen))
333             return s;
334         debug(DBG_WARN, "bindtoaddr: bind failed");
335         close(s);
336     }
337     return -1;
338 }         
339
340 char *parsehostport(char *s, struct clsrvconf *conf, char *default_port) {
341     char *p, *field;
342     int ipv6 = 0;
343
344     p = s;
345     /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
346     if (*p == '[') {
347         p++;
348         field = p;
349         for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
350         if (*p != ']')
351             debugx(1, DBG_ERR, "no ] matching initial [");
352         ipv6 = 1;
353     } else {
354         field = p;
355         for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
356     }
357     if (field == p)
358         debugx(1, DBG_ERR, "missing host/address");
359
360     conf->host = stringcopy(field, p - field);
361     if (ipv6) {
362         p++;
363         if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
364             debugx(1, DBG_ERR, "unexpected character after ]");
365     }
366     if (*p == ':') {
367             /* port number or service name is specified */;
368             field = ++p;
369             for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
370             if (field == p)
371                 debugx(1, DBG_ERR, "syntax error, : but no following port");
372             conf->port = stringcopy(field, p - field);
373     } else
374         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
375     return p;
376 }
377
378 struct clsrvconf *resolve_hostport(uint8_t type, char *lconf, char *default_port) {
379     struct clsrvconf *conf;
380
381     conf = malloc(sizeof(struct clsrvconf));
382     if (!conf)
383         debugx(1, DBG_ERR, "malloc failed");
384     memset(conf, 0, sizeof(struct clsrvconf));
385     conf->type = type;
386     conf->pdef = &protodefs[conf->type];
387     if (lconf) {
388         parsehostport(lconf, conf, default_port);
389         if (!strcmp(conf->host, "*")) {
390             free(conf->host);
391             conf->host = NULL;
392         }
393     } else
394         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
395     if (!resolvepeer(conf, AI_PASSIVE))
396         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
397     return conf;
398 }
399
400 void freeclsrvres(struct clsrvconf *res) {
401     free(res->host);
402     free(res->port);
403     if (res->addrinfo)
404         freeaddrinfo(res->addrinfo);
405     free(res);
406 }
407
408 int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src) {
409     int s;
410     struct addrinfo *res;
411
412     s = -1;
413     for (res = addrinfo; res; res = res->ai_next) {
414         s = bindtoaddr(src, res->ai_family, 1, 1);
415         if (s < 0) {
416             debug(DBG_WARN, "connecttoserver: socket failed");
417             continue;
418         }
419         if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
420             break;
421         debug(DBG_WARN, "connecttoserver: connect failed");
422         close(s);
423         s = -1;
424     }
425     return s;
426 }         
427
428 /* returns 1 if the len first bits are equal, else 0 */
429 int prefixmatch(void *a1, void *a2, uint8_t len) {
430     static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
431     int r, l = len / 8;
432     if (l && memcmp(a1, a2, l))
433         return 0;
434     r = len % 8;
435     if (!r)
436         return 1;
437     return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
438 }
439
440 /* returns next config with matching address, or NULL */
441 struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur) {
442     struct sockaddr_in6 *sa6 = NULL;
443     struct in_addr *a4 = NULL;
444     struct addrinfo *res;
445     struct list_node *entry;
446     struct clsrvconf *conf;
447     
448     if (addr->sa_family == AF_INET6) {
449         sa6 = (struct sockaddr_in6 *)addr;
450         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
451             a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
452             sa6 = NULL;
453         }
454     } else
455         a4 = &((struct sockaddr_in *)addr)->sin_addr;
456
457     for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) {
458         conf = (struct clsrvconf *)entry->data;
459         if (conf->type == type) {
460             if (conf->prefixlen == 255) {
461                 for (res = conf->addrinfo; res; res = res->ai_next)
462                     if ((a4 && res->ai_family == AF_INET &&
463                          !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
464                         (sa6 && res->ai_family == AF_INET6 &&
465                          !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16))) {
466                         if (cur)
467                             *cur = entry;
468                         return conf;
469                     }
470             } else {
471                 res = conf->addrinfo;
472                 if (res &&
473                     ((a4 && res->ai_family == AF_INET &&
474                       prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
475                      (sa6 && res->ai_family == AF_INET6 &&
476                       prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen)))) {
477                     if (cur)
478                         *cur = entry;
479                     return conf;
480                 }
481             }
482         }
483     }    
484     return NULL;
485 }
486
487 /* returns next config of given type, or NULL */
488 struct clsrvconf *find_conf_type(uint8_t type, struct list *confs, struct list_node **cur) {
489     struct list_node *entry;
490     struct clsrvconf *conf;
491     
492     for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) {
493         conf = (struct clsrvconf *)entry->data;
494         if (conf->type == type) {
495             if (cur)
496                 *cur = entry;
497             return conf;
498         }
499     }    
500     return NULL;
501 }
502
503 struct replyq *newreplyq() {
504     struct replyq *replyq;
505     
506     replyq = malloc(sizeof(struct replyq));
507     if (!replyq)
508         debugx(1, DBG_ERR, "malloc failed");
509     replyq->replies = list_create();
510     if (!replyq->replies)
511         debugx(1, DBG_ERR, "malloc failed");
512     pthread_mutex_init(&replyq->mutex, NULL);
513     pthread_cond_init(&replyq->cond, NULL);
514     return replyq;
515 }
516
517 struct client *addclient(struct clsrvconf *conf) {
518     struct client *new = malloc(sizeof(struct client));
519     
520     if (!new) {
521         debug(DBG_ERR, "malloc failed");
522         return NULL;
523     }
524     if (!conf->clients) {
525         conf->clients = list_create();
526         if (!conf->clients) {
527             debug(DBG_ERR, "malloc failed");
528             return NULL;
529         }
530     }
531     
532     memset(new, 0, sizeof(struct client));
533     new->conf = conf;
534     new->replyq = conf->type == RAD_UDP ? udp_server_replyq : newreplyq();
535
536     list_push(conf->clients, new);
537     return new;
538 }
539
540 void removeclient(struct client *client) {
541     struct list_node *entry;
542     
543     if (!client || !client->conf->clients)
544         return;
545
546     pthread_mutex_lock(&client->replyq->mutex);
547     for (entry = list_first(client->replyq->replies); entry; entry = list_next(entry))
548         free(((struct reply *)entry)->buf);
549     list_destroy(client->replyq->replies);
550     pthread_cond_destroy(&client->replyq->cond);
551     pthread_mutex_unlock(&client->replyq->mutex);
552     pthread_mutex_destroy(&client->replyq->mutex);
553     list_removedata(client->conf->clients, client);
554     free(client);
555 }
556
557 void removeclientrqs(struct client *client) {
558     struct list_node *entry;
559     struct server *server;
560     struct request *rq;
561     int i;
562     
563     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
564         server = ((struct clsrvconf *)entry->data)->servers;
565         if (!server)
566             continue;
567         pthread_mutex_lock(&server->newrq_mutex);
568         for (i = 0; i < MAX_REQUESTS; i++) {
569             rq = server->requests + i;
570             if (rq->from == client)
571                 rq->from = NULL;
572         }
573         pthread_mutex_unlock(&server->newrq_mutex);
574     }
575 }
576
577 void freeserver(struct server *server, uint8_t destroymutex) {
578     struct request *rq, *end;
579
580     if (!server)
581         return;
582
583     if(server->requests) {
584         rq = server->requests;
585         for (end = rq + MAX_REQUESTS; rq < end; rq++)
586             freerqdata(rq);
587         free(server->requests);
588     }
589     free(server->dynamiclookuparg);
590     if (destroymutex) {
591         pthread_mutex_destroy(&server->lock);
592         pthread_cond_destroy(&server->newrq_cond);
593         pthread_mutex_destroy(&server->newrq_mutex);
594     }
595     free(server);
596 }
597
598 int addserver(struct clsrvconf *conf) {
599     struct clsrvconf *res;
600     uint8_t type;
601     
602     if (conf->servers) {
603         debug(DBG_ERR, "addserver: currently works with just one server per conf");
604         return 0;
605     }
606     conf->servers = malloc(sizeof(struct server));
607     if (!conf->servers) {
608         debug(DBG_ERR, "malloc failed");
609         return 0;
610     }
611     memset(conf->servers, 0, sizeof(struct server));
612     conf->servers->conf = conf;
613
614     type = conf->type;
615     if (type == RAD_DTLS)
616         type = RAD_UDP;
617     
618     if (!srcprotores[type]) {
619         res = resolve_hostport(type, *conf->pdef->srcaddrport, NULL);
620         srcprotores[type] = res->addrinfo;
621         res->addrinfo = NULL;
622         freeclsrvres(res);
623     }
624
625     if (type == RAD_UDP) {
626         switch (conf->addrinfo->ai_family) {
627         case AF_INET:
628             if (udp_client4_sock < 0) {
629                 udp_client4_sock = bindtoaddr(srcprotores[RAD_UDP], AF_INET, 0, 1);
630                 if (udp_client4_sock < 0)
631                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
632             }
633             conf->servers->sock = udp_client4_sock;
634             break;
635         case AF_INET6:
636             if (udp_client6_sock < 0) {
637                 udp_client6_sock = bindtoaddr(srcprotores[RAD_UDP], AF_INET6, 0, 1);
638                 if (udp_client6_sock < 0)
639                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
640             }
641             conf->servers->sock = udp_client6_sock;
642             break;
643         default:
644             debugx(1, DBG_ERR, "addserver: unsupported address family");
645         }
646         
647     } else
648         conf->servers->sock = -1;
649     
650     conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request));
651     if (!conf->servers->requests) {
652         debug(DBG_ERR, "malloc failed");
653         goto errexit;
654     }
655     if (pthread_mutex_init(&conf->servers->lock, NULL)) {
656         debug(DBG_ERR, "mutex init failed");
657         goto errexit;
658     }
659     conf->servers->newrq = 0;
660     if (pthread_mutex_init(&conf->servers->newrq_mutex, NULL)) {
661         debug(DBG_ERR, "mutex init failed");
662         pthread_mutex_destroy(&conf->servers->lock);
663         goto errexit;
664     }
665     if (pthread_cond_init(&conf->servers->newrq_cond, NULL)) {
666         debug(DBG_ERR, "mutex init failed");
667         pthread_mutex_destroy(&conf->servers->newrq_mutex);
668         pthread_mutex_destroy(&conf->servers->lock);
669         goto errexit;
670     }
671
672     return 1;
673     
674  errexit:
675     freeserver(conf->servers, 0);
676     conf->servers = NULL;
677     return 0;
678 }
679
680 /* exactly one of client and server must be non-NULL */
681 /* return who we received from in *client or *server */
682 /* return from in sa if not NULL */
683 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
684     int cnt, len;
685     unsigned char buf[4], *rad;
686     struct sockaddr_storage from;
687     socklen_t fromlen = sizeof(from);
688     struct clsrvconf *p;
689     struct list_node *node;
690     fd_set readfds;
691     
692     for (;;) {
693         FD_ZERO(&readfds);
694         FD_SET(s, &readfds);
695         if (select(s + 1, &readfds, NULL, NULL, NULL) < 1)
696             continue;
697         cnt = recvfrom(s, buf, 4, MSG_PEEK, (struct sockaddr *)&from, &fromlen);
698         if (cnt == -1) {
699             debug(DBG_WARN, "radudpget: recv failed");
700             continue;
701         }
702
703         p = find_conf(RAD_UDP, (struct sockaddr *)&from, client ? clconfs : srvconfs, NULL);
704         if (!p) {
705             debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen));
706             recv(s, buf, 4, 0);
707             continue;
708         }
709         
710         len = RADLEN(buf);
711         if (len < 20) {
712             debug(DBG_WARN, "radudpget: length too small");
713             recv(s, buf, 4, 0);
714             continue;
715         }
716         
717         rad = malloc(len);
718         if (!rad) {
719             debug(DBG_ERR, "radudpget: malloc failed");
720             recv(s, buf, 4, 0);
721             continue;
722         }
723         
724         cnt = recv(s, rad, len, MSG_TRUNC);
725         debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
726
727         if (cnt < len) {
728             debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
729             free(rad);
730             continue;
731         }
732         
733         if (cnt > len)
734             debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
735
736         if (client) {
737             node = list_first(p->clients);
738             *client = node ? (struct client *)node->data : addclient(p);
739             if (!*client) {
740                 free(rad);
741                 continue;
742             }
743         } else if (server)
744             *server = p->servers;
745         break;
746     }
747     if (sa)
748         *sa = from;
749     return rad;
750 }
751
752 int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
753     int loc, i, l, n, r = 0;
754     char *v;
755     X509_EXTENSION *ex;
756     STACK_OF(GENERAL_NAME) *alt;
757     GENERAL_NAME *gn;
758     
759     debug(DBG_DBG, "subjectaltnameaddr");
760     
761     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
762     if (loc < 0)
763         return r;
764     
765     ex = X509_get_ext(cert, loc);
766     alt = X509V3_EXT_d2i(ex);
767     if (!alt)
768         return r;
769     
770     n = sk_GENERAL_NAME_num(alt);
771     for (i = 0; i < n; i++) {
772         gn = sk_GENERAL_NAME_value(alt, i);
773         if (gn->type != GEN_IPADD)
774             continue;
775         r = -1;
776         v = (char *)ASN1_STRING_data(gn->d.ia5);
777         l = ASN1_STRING_length(gn->d.ia5);
778         if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
779             && !memcmp(v, &addr, l)) {
780             r = 1;
781             break;
782         }
783     }
784     GENERAL_NAMES_free(alt);
785     return r;
786 }
787
788 int cnregexp(X509 *cert, char *exact, regex_t *regex) {
789     int loc, l;
790     char *v, *s;
791     X509_NAME *nm;
792     X509_NAME_ENTRY *e;
793     ASN1_STRING *t;
794
795     nm = X509_get_subject_name(cert);
796     loc = -1;
797     for (;;) {
798         loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
799         if (loc == -1)
800             break;
801         e = X509_NAME_get_entry(nm, loc);
802         t = X509_NAME_ENTRY_get_data(e);
803         v = (char *) ASN1_STRING_data(t);
804         l = ASN1_STRING_length(t);
805         if (l < 0)
806             continue;
807         if (exact) {
808             if (l == strlen(exact) && !strncasecmp(exact, v, l))
809                 return 1;
810         } else {
811             s = stringcopy((char *)v, l);
812             if (!s) {
813                 debug(DBG_ERR, "malloc failed");
814                 continue;
815             }
816             if (regexec(regex, s, 0, NULL, 0)) {
817                 free(s);
818                 continue;
819             }
820             free(s);
821             return 1;
822         }
823     }
824     return 0;
825 }
826
827 int subjectaltnameregexp(X509 *cert, int type, char *exact,  regex_t *regex) {
828     int loc, i, l, n, r = 0;
829     char *s, *v;
830     X509_EXTENSION *ex;
831     STACK_OF(GENERAL_NAME) *alt;
832     GENERAL_NAME *gn;
833     
834     debug(DBG_DBG, "subjectaltnameregexp");
835     
836     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
837     if (loc < 0)
838         return r;
839     
840     ex = X509_get_ext(cert, loc);
841     alt = X509V3_EXT_d2i(ex);
842     if (!alt)
843         return r;
844     
845     n = sk_GENERAL_NAME_num(alt);
846     for (i = 0; i < n; i++) {
847         gn = sk_GENERAL_NAME_value(alt, i);
848         if (gn->type != type)
849             continue;
850         r = -1;
851         v = (char *)ASN1_STRING_data(gn->d.ia5);
852         l = ASN1_STRING_length(gn->d.ia5);
853         if (l <= 0)
854             continue;
855 #ifdef DEBUG
856         printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
857 #endif  
858         if (exact) {
859             if (memcmp(v, exact, l))
860                 continue;
861         } else {
862             s = stringcopy((char *)v, l);
863             if (!s) {
864                 debug(DBG_ERR, "malloc failed");
865                 continue;
866             }
867             if (regexec(regex, s, 0, NULL, 0)) {
868                 free(s);
869                 continue;
870             }
871             free(s);
872         }
873         r = 1;
874         break;
875     }
876     GENERAL_NAMES_free(alt);
877     return r;
878 }
879
880 X509 *verifytlscert(SSL *ssl) {
881     X509 *cert;
882     unsigned long error;
883     
884     if (SSL_get_verify_result(ssl) != X509_V_OK) {
885         debug(DBG_ERR, "verifytlscert: basic validation failed");
886         while ((error = ERR_get_error()))
887             debug(DBG_ERR, "verifytlscert: TLS: %s", ERR_error_string(error, NULL));
888         return NULL;
889     }
890
891     cert = SSL_get_peer_certificate(ssl);
892     if (!cert)
893         debug(DBG_ERR, "verifytlscert: failed to obtain certificate");
894     return cert;
895 }
896     
897 int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
898     int r;
899     uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
900     struct in6_addr addr;
901     
902     if (conf->certnamecheck && conf->prefixlen == 255) {
903         if (inet_pton(AF_INET, conf->host, &addr))
904             type = AF_INET;
905         else if (inet_pton(AF_INET6, conf->host, &addr))
906             type = AF_INET6;
907
908         r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, conf->host, NULL);
909         if (r) {
910             if (r < 0) {
911                 debug(DBG_WARN, "verifyconfcert: No subjectaltname matching %s %s", type ? "address" : "host", conf->host);
912                 return 0;
913             }
914             debug(DBG_DBG, "verifyconfcert: Found subjectaltname matching %s %s", type ? "address" : "host", conf->host);
915         } else {
916             if (!cnregexp(cert, conf->host, NULL)) {
917                 debug(DBG_WARN, "verifyconfcert: cn not matching host %s", conf->host);
918                 return 0;
919             }           
920             debug(DBG_DBG, "verifyconfcert: Found cn matching host %s", conf->host);
921         }
922     }
923     if (conf->certcnregex) {
924         if (cnregexp(cert, NULL, conf->certcnregex) < 1) {
925             debug(DBG_WARN, "verifyconfcert: CN not matching regex");
926             return 0;
927         }
928         debug(DBG_DBG, "verifyconfcert: CN matching regex");
929     }
930     if (conf->certuriregex) {
931         if (subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex) < 1) {
932             debug(DBG_WARN, "verifyconfcert: subjectaltname URI not matching regex");
933             return 0;
934         }
935         debug(DBG_DBG, "verifyconfcert: subjectaltname URI matching regex");
936     }
937     return 1;
938 }
939
940 int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text) {
941     struct timeval now;
942     time_t elapsed;
943     X509 *cert;
944     unsigned long error;
945     
946     debug(DBG_DBG, "tlsconnect: called from %s", text);
947     pthread_mutex_lock(&server->lock);
948     if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
949         /* already reconnected, nothing to do */
950         debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
951         pthread_mutex_unlock(&server->lock);
952         return 1;
953     }
954
955     for (;;) {
956         gettimeofday(&now, NULL);
957         elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
958         if (timeout && server->lastconnecttry.tv_sec && elapsed > timeout) {
959             debug(DBG_DBG, "tlsconnect: timeout");
960             if (server->sock >= 0)
961                 close(server->sock);
962             SSL_free(server->ssl);
963             server->ssl = NULL;
964             pthread_mutex_unlock(&server->lock);
965             return 0;
966         }
967         if (server->connectionok) {
968             server->connectionok = 0;
969             sleep(2);
970         } else if (elapsed < 1)
971             sleep(2);
972         else if (elapsed < 60) {
973             debug(DBG_INFO, "tlsconnect: sleeping %lds", elapsed);
974             sleep(elapsed);
975         } else if (elapsed < 100000) {
976             debug(DBG_INFO, "tlsconnect: sleeping %ds", 60);
977             sleep(60);
978         } else
979             server->lastconnecttry.tv_sec = now.tv_sec;  /* no sleep at startup */
980         debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->conf->host, server->conf->port);
981         if (server->sock >= 0)
982             close(server->sock);
983         if ((server->sock = connecttcp(server->conf->addrinfo, srcprotores[RAD_TLS])) < 0) {
984             debug(DBG_ERR, "tlsconnect: connecttcp failed");
985             continue;
986         }
987         
988         SSL_free(server->ssl);
989         server->ssl = SSL_new(server->conf->ssl_ctx);
990         SSL_set_fd(server->ssl, server->sock);
991         if (SSL_connect(server->ssl) <= 0) {
992             while ((error = ERR_get_error()))
993                 debug(DBG_ERR, "tlsconnect: TLS: %s", ERR_error_string(error, NULL));
994             continue;
995         }
996         cert = verifytlscert(server->ssl);
997         if (!cert)
998             continue;
999         if (verifyconfcert(cert, server->conf)) {
1000             X509_free(cert);
1001             break;
1002         }
1003         X509_free(cert);
1004     }
1005     debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
1006     gettimeofday(&server->lastconnecttry, NULL);
1007     pthread_mutex_unlock(&server->lock);
1008     return 1;
1009 }
1010
1011 int dtlsinit(struct server *server, struct timeval *when, int timeout, char *text) {
1012     BIO *dummybio, *wbio;
1013     
1014     debug(DBG_DBG, "dtlsinit: called from %s", text);
1015     server->ssl = SSL_new(server->conf->ssl_ctx);
1016     SSL_set_connect_state(server->ssl);
1017     
1018     dummybio = BIO_new(BIO_s_mem());
1019     /* trying to read from this BIO always returns retry */
1020     BIO_set_mem_eof_return(dummybio, -1);
1021     
1022     wbio = BIO_new_dgram(server->sock, BIO_NOCLOSE);
1023     BIO_dgram_set_peer(wbio, server->conf->addrinfo->ai_addr);
1024     /* the real rbio will be set by radudpget */
1025     SSL_set_bio(server->ssl, dummybio, wbio);
1026     return 1;
1027 }
1028     
1029 int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text) {
1030     struct timeval now;
1031     time_t elapsed;
1032     
1033     debug(DBG_DBG, "tcpconnect: called from %s", text);
1034     pthread_mutex_lock(&server->lock);
1035     if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
1036         /* already reconnected, nothing to do */
1037         debug(DBG_DBG, "tcpconnect(%s): seems already reconnected", text);
1038         pthread_mutex_unlock(&server->lock);
1039         return 1;
1040     }
1041
1042     for (;;) {
1043         gettimeofday(&now, NULL);
1044         elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
1045         if (timeout && server->lastconnecttry.tv_sec && elapsed > timeout) {
1046             debug(DBG_DBG, "tcpconnect: timeout");
1047             if (server->sock >= 0)
1048                 close(server->sock);
1049             pthread_mutex_unlock(&server->lock);
1050             return 0;
1051         }
1052         if (server->connectionok) {
1053             server->connectionok = 0;
1054             sleep(2);
1055         } else if (elapsed < 1)
1056             sleep(2);
1057         else if (elapsed < 60) {
1058             debug(DBG_INFO, "tcpconnect: sleeping %lds", elapsed);
1059             sleep(elapsed);
1060         } else if (elapsed < 100000) {
1061             debug(DBG_INFO, "tcpconnect: sleeping %ds", 60);
1062             sleep(60);
1063         } else
1064             server->lastconnecttry.tv_sec = now.tv_sec;  /* no sleep at startup */
1065         debug(DBG_WARN, "tcpconnect: trying to open TCP connection to %s port %s", server->conf->host, server->conf->port);
1066         if (server->sock >= 0)
1067             close(server->sock);
1068         if ((server->sock = connecttcp(server->conf->addrinfo, srcprotores[RAD_TCP])) >= 0)
1069             break;
1070         debug(DBG_ERR, "tcpconnect: connecttcp failed");
1071     }
1072     debug(DBG_WARN, "tcpconnect: TCP connection to %s port %s up", server->conf->host, server->conf->port);
1073     gettimeofday(&server->lastconnecttry, NULL);
1074     pthread_mutex_unlock(&server->lock);
1075     return 1;
1076 }
1077
1078 /* timeout in seconds, 0 means no timeout (blocking), returns when num bytes have been read, or timeout */
1079 /* returns 0 on timeout, -1 on error and num if ok */
1080 int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout) {
1081     int s, ndesc, cnt, len;
1082     fd_set readfds, writefds;
1083     struct timeval timer;
1084     
1085     s = SSL_get_fd(ssl);
1086     if (s < 0)
1087         return -1;
1088     /* make socket non-blocking? */
1089     for (len = 0; len < num; len += cnt) {
1090         FD_ZERO(&readfds);
1091         FD_SET(s, &readfds);
1092         writefds = readfds;
1093         if (timeout) {
1094             timer.tv_sec = timeout;
1095             timer.tv_usec = 0;
1096         }
1097         ndesc = select(s + 1, &readfds, &writefds, NULL, timeout ? &timer : NULL);
1098         if (ndesc < 1)
1099             return ndesc;
1100
1101         cnt = SSL_read(ssl, buf + len, num - len);
1102         if (cnt <= 0)
1103             switch (SSL_get_error(ssl, cnt)) {
1104             case SSL_ERROR_WANT_READ:
1105             case SSL_ERROR_WANT_WRITE:
1106                 cnt = 0;
1107                 continue;
1108             case SSL_ERROR_ZERO_RETURN:
1109                 /* remote end sent close_notify, send one back */
1110                 SSL_shutdown(ssl);
1111                 /* fall through */
1112             default:
1113                 return -1;
1114             }
1115     }
1116     return num;
1117 }
1118
1119 /* timeout in seconds, 0 means no timeout (blocking) */
1120 unsigned char *radtlsget(SSL *ssl, int timeout) {
1121     int cnt, len;
1122     unsigned char buf[4], *rad;
1123
1124     for (;;) {
1125         cnt = sslreadtimeout(ssl, buf, 4, timeout);
1126         if (cnt < 1) {
1127             debug(DBG_DBG, cnt ? "radtlsget: connection lost" : "radtlsget: timeout");
1128             return NULL;
1129         }
1130
1131         len = RADLEN(buf);
1132         rad = malloc(len);
1133         if (!rad) {
1134             debug(DBG_ERR, "radtlsget: malloc failed");
1135             continue;
1136         }
1137         memcpy(rad, buf, 4);
1138         
1139         cnt = sslreadtimeout(ssl, rad + 4, len - 4, timeout);
1140         if (cnt < 1) {
1141             debug(DBG_DBG, cnt ? "radtlsget: connection lost" : "radtlsget: timeout");
1142             free(rad);
1143             return NULL;
1144         }
1145         
1146         if (len >= 20)
1147             break;
1148         
1149         free(rad);
1150         debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
1151     }
1152     
1153     debug(DBG_DBG, "radtlsget: got %d bytes", len);
1154     return rad;
1155 }
1156
1157 /* timeout in seconds, 0 means no timeout (blocking), returns when num bytes have been read, or timeout */
1158 /* returns 0 on timeout, -1 on error and num if ok */
1159 int tcpreadtimeout(int s, unsigned char *buf, int num, int timeout) {
1160     int ndesc, cnt, len;
1161     fd_set readfds, writefds;
1162     struct timeval timer;
1163     
1164     if (s < 0)
1165         return -1;
1166     /* make socket non-blocking? */
1167     for (len = 0; len < num; len += cnt) {
1168         FD_ZERO(&readfds);
1169         FD_SET(s, &readfds);
1170         writefds = readfds;
1171         if (timeout) {
1172             timer.tv_sec = timeout;
1173             timer.tv_usec = 0;
1174         }
1175         ndesc = select(s + 1, &readfds, &writefds, NULL, timeout ? &timer : NULL);
1176         if (ndesc < 1)
1177             return ndesc;
1178
1179         cnt = read(s, buf + len, num - len);
1180         if (cnt <= 0)
1181             return -1;
1182     }
1183     return num;
1184 }
1185
1186 /* timeout in seconds, 0 means no timeout (blocking) */
1187 unsigned char *radtcpget(int s, int timeout) {
1188     int cnt, len;
1189     unsigned char buf[4], *rad;
1190
1191     for (;;) {
1192         cnt = tcpreadtimeout(s, buf, 4, timeout);
1193         if (cnt < 1) {
1194             debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout");
1195             return NULL;
1196         }
1197
1198         len = RADLEN(buf);
1199         rad = malloc(len);
1200         if (!rad) {
1201             debug(DBG_ERR, "radtcpget: malloc failed");
1202             continue;
1203         }
1204         memcpy(rad, buf, 4);
1205         
1206         cnt = tcpreadtimeout(s, rad + 4, len - 4, timeout);
1207         if (cnt < 1) {
1208             debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout");
1209             free(rad);
1210             return NULL;
1211         }
1212         
1213         if (len >= 20)
1214             break;
1215         
1216         free(rad);
1217         debug(DBG_WARN, "radtcpget: packet smaller than minimum radius size");
1218     }
1219     
1220     debug(DBG_DBG, "radtcpget: got %d bytes", len);
1221     return rad;
1222 }
1223
1224 int clientradputudp(struct server *server, unsigned char *rad) {
1225     size_t len;
1226     struct sockaddr_storage sa;
1227     struct sockaddr *sap;
1228     struct clsrvconf *conf = server->conf;
1229     in_port_t *port = NULL;
1230     
1231     len = RADLEN(rad);
1232     
1233     if (*rad == RAD_Accounting_Request) {
1234         sap = (struct sockaddr *)&sa;
1235         memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen);
1236     } else
1237         sap = conf->addrinfo->ai_addr;
1238     
1239     switch (sap->sa_family) {
1240     case AF_INET:
1241         port = &((struct sockaddr_in *)sap)->sin_port;
1242         break;
1243     case AF_INET6:
1244         port = &((struct sockaddr_in6 *)sap)->sin6_port;
1245         break;
1246     default:
1247         return 0;
1248     }
1249
1250     if (*rad == RAD_Accounting_Request)
1251         *port = htons(ntohs(*port) + 1);
1252     
1253     if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) {
1254         debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port));
1255         return 1;
1256     }
1257
1258     debug(DBG_WARN, "clientradputudp: send failed");
1259     return 0;
1260 }
1261
1262 int clientradputtls(struct server *server, unsigned char *rad) {
1263     int cnt;
1264     size_t len;
1265     unsigned long error;
1266     struct timeval lastconnecttry;
1267     struct clsrvconf *conf = server->conf;
1268     
1269     len = RADLEN(rad);
1270     lastconnecttry = server->lastconnecttry;
1271     while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
1272         while ((error = ERR_get_error()))
1273             debug(DBG_ERR, "clientradputtls: TLS: %s", ERR_error_string(error, NULL));
1274         if (server->dynamiclookuparg)
1275             return 0;
1276         tlsconnect(server, &lastconnecttry, 0, "clientradputtls");
1277         lastconnecttry = server->lastconnecttry;
1278     }
1279
1280     server->connectionok = 1;
1281     debug(DBG_DBG, "clientradputtls: Sent %d bytes, Radius packet of length %d to TLS peer %s", cnt, len, conf->host);
1282     return 1;
1283 }
1284
1285 int clientradputdtls(struct server *server, unsigned char *rad) {
1286     int cnt;
1287     size_t len;
1288     unsigned long error;
1289     struct clsrvconf *conf = server->conf;
1290     
1291     len = RADLEN(rad);
1292     while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
1293         while ((error = ERR_get_error()))
1294             debug(DBG_ERR, "clientradputdtls: DTLS: %s", ERR_error_string(error, NULL));
1295     }
1296     debug(DBG_DBG, "clientradputdtls: Sent %d bytes, Radius packet of length %d to DTLS peer %s", cnt, len, conf->host);
1297     return 1;
1298 }
1299
1300 int clientradputtcp(struct server *server, unsigned char *rad) {
1301     int cnt;
1302     size_t len;
1303     struct timeval lastconnecttry;
1304     struct clsrvconf *conf = server->conf;
1305     
1306     len = RADLEN(rad);
1307     lastconnecttry = server->lastconnecttry;
1308     while ((cnt = write(server->sock, rad, len)) <= 0) {
1309         debug(DBG_ERR, "clientradputtcp: write error");
1310         tcpconnect(server, &lastconnecttry, 0, "clientradputtcp");
1311         lastconnecttry = server->lastconnecttry;
1312     }
1313
1314     server->connectionok = 1;
1315     debug(DBG_DBG, "clientradputtcp: Sent %d bytes, Radius packet of length %d to TCP peer %s", cnt, len, conf->host);
1316     return 1;
1317 }
1318
1319 int radsign(unsigned char *rad, unsigned char *sec) {
1320     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1321     static unsigned char first = 1;
1322     static EVP_MD_CTX mdctx;
1323     unsigned int md_len;
1324     int result;
1325     
1326     pthread_mutex_lock(&lock);
1327     if (first) {
1328         EVP_MD_CTX_init(&mdctx);
1329         first = 0;
1330     }
1331
1332     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
1333         EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
1334         EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
1335         EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
1336         md_len == 16);
1337     pthread_mutex_unlock(&lock);
1338     return result;
1339 }
1340
1341 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
1342     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1343     static unsigned char first = 1;
1344     static EVP_MD_CTX mdctx;
1345     unsigned char hash[EVP_MAX_MD_SIZE];
1346     unsigned int len;
1347     int result;
1348     
1349     pthread_mutex_lock(&lock);
1350     if (first) {
1351         EVP_MD_CTX_init(&mdctx);
1352         first = 0;
1353     }
1354
1355     len = RADLEN(rad);
1356     
1357     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
1358               EVP_DigestUpdate(&mdctx, rad, 4) &&
1359               EVP_DigestUpdate(&mdctx, reqauth, 16) &&
1360               (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
1361               EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
1362               EVP_DigestFinal_ex(&mdctx, hash, &len) &&
1363               len == 16 &&
1364               !memcmp(hash, rad + 4, 16));
1365     pthread_mutex_unlock(&lock);
1366     return result;
1367 }
1368               
1369 int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
1370     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1371     static unsigned char first = 1;
1372     static HMAC_CTX hmacctx;
1373     unsigned int md_len;
1374     uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
1375     
1376     pthread_mutex_lock(&lock);
1377     if (first) {
1378         HMAC_CTX_init(&hmacctx);
1379         first = 0;
1380     }
1381
1382     memcpy(auth, authattr, 16);
1383     memset(authattr, 0, 16);
1384     md_len = 0;
1385     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
1386     HMAC_Update(&hmacctx, rad, RADLEN(rad));
1387     HMAC_Final(&hmacctx, hash, &md_len);
1388     memcpy(authattr, auth, 16);
1389     if (md_len != 16) {
1390         debug(DBG_WARN, "message auth computation failed");
1391         pthread_mutex_unlock(&lock);
1392         return 0;
1393     }
1394
1395     if (memcmp(auth, hash, 16)) {
1396         debug(DBG_WARN, "message authenticator, wrong value");
1397         pthread_mutex_unlock(&lock);
1398         return 0;
1399     }   
1400         
1401     pthread_mutex_unlock(&lock);
1402     return 1;
1403 }
1404
1405 int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secret) {
1406     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1407     static unsigned char first = 1;
1408     static HMAC_CTX hmacctx;
1409     unsigned int md_len;
1410
1411     if (!authattrval)
1412         return 1;
1413     
1414     pthread_mutex_lock(&lock);
1415     if (first) {
1416         HMAC_CTX_init(&hmacctx);
1417         first = 0;
1418     }
1419
1420     memset(authattrval, 0, 16);
1421     md_len = 0;
1422     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
1423     HMAC_Update(&hmacctx, rad, RADLEN(rad));
1424     HMAC_Final(&hmacctx, authattrval, &md_len);
1425     if (md_len != 16) {
1426         debug(DBG_WARN, "message auth computation failed");
1427         pthread_mutex_unlock(&lock);
1428         return 0;
1429     }
1430
1431     pthread_mutex_unlock(&lock);
1432     return 1;
1433 }
1434
1435 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
1436     while (length > 1) {
1437         if (ATTRTYPE(attrs) == type)
1438             return attrs;
1439         length -= ATTRLEN(attrs);
1440         attrs += ATTRLEN(attrs);
1441     }
1442     return NULL;
1443 }
1444
1445 void freerqdata(struct request *rq) {
1446     if (rq->origusername)
1447         free(rq->origusername);
1448     if (rq->buf)
1449         free(rq->buf);
1450 }
1451
1452 void sendrq(struct server *to, struct request *rq) {
1453     int i;
1454     uint8_t *attr;
1455
1456     pthread_mutex_lock(&to->newrq_mutex);
1457     /* might simplify if only try nextid, might be ok */
1458     for (i = to->nextid; i < MAX_REQUESTS; i++)
1459         if (!to->requests[i].buf)
1460             break;
1461     if (i == MAX_REQUESTS) {
1462         for (i = 0; i < to->nextid; i++)
1463             if (!to->requests[i].buf)
1464                 break;
1465         if (i == to->nextid) {
1466             debug(DBG_WARN, "sendrq: no room in queue, dropping request");
1467             freerqdata(rq);
1468             goto exit;
1469         }
1470     }
1471     
1472     rq->buf[1] = (char)i;
1473
1474     attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
1475     if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->conf->secret)) {
1476         freerqdata(rq);
1477         goto exit;
1478     }
1479     
1480     if (*rq->buf == RAD_Accounting_Request) {
1481         if (!radsign(rq->buf, (unsigned char *)to->conf->secret)) {
1482             debug(DBG_WARN, "sendrq: failed to sign Accounting-Request message");
1483             freerqdata(rq);
1484             goto exit;
1485         }
1486     }
1487
1488     debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host);
1489     to->requests[i] = *rq;
1490     to->nextid = i + 1;
1491
1492     if (!to->newrq) {
1493         to->newrq = 1;
1494         debug(DBG_DBG, "sendrq: signalling client writer");
1495         pthread_cond_signal(&to->newrq_cond);
1496     }
1497  exit:
1498     pthread_mutex_unlock(&to->newrq_mutex);
1499 }
1500
1501 void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa, int toudpsock) {
1502     struct reply *reply;
1503     uint8_t first;
1504     
1505     if (!radsign(buf, (unsigned char *)to->conf->secret)) {
1506         free(buf);
1507         debug(DBG_WARN, "sendreply: failed to sign message");
1508         return;
1509     }
1510
1511     reply = malloc(sizeof(struct reply));
1512     if (!reply) {
1513         free(buf);
1514         debug(DBG_ERR, "sendreply: malloc failed");
1515         return;
1516     }
1517     memset(reply, 0, sizeof(struct reply));
1518     reply->buf = buf;
1519     if (tosa)
1520         reply->tosa = *tosa;
1521     reply->toudpsock = toudpsock;
1522     
1523     pthread_mutex_lock(&to->replyq->mutex);
1524
1525     first = list_first(to->replyq->replies) == NULL;
1526     
1527     if (!list_push(to->replyq->replies, reply)) {
1528         pthread_mutex_unlock(&to->replyq->mutex);
1529         free(reply);
1530         free(buf);
1531         debug(DBG_ERR, "sendreply: malloc failed");
1532         return;
1533     }
1534     
1535     if (first) {
1536         debug(DBG_DBG, "signalling server writer");
1537         pthread_cond_signal(&to->replyq->cond);
1538     }
1539     pthread_mutex_unlock(&to->replyq->mutex);
1540 }
1541
1542 int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1543     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1544     static unsigned char first = 1;
1545     static EVP_MD_CTX mdctx;
1546     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1547     unsigned int md_len;
1548     uint8_t i, offset = 0, out[128];
1549     
1550     pthread_mutex_lock(&lock);
1551     if (first) {
1552         EVP_MD_CTX_init(&mdctx);
1553         first = 0;
1554     }
1555
1556     input = auth;
1557     for (;;) {
1558         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1559             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1560             !EVP_DigestUpdate(&mdctx, input, 16) ||
1561             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1562             md_len != 16) {
1563             pthread_mutex_unlock(&lock);
1564             return 0;
1565         }
1566         for (i = 0; i < 16; i++)
1567             out[offset + i] = hash[i] ^ in[offset + i];
1568         input = out + offset - 16;
1569         offset += 16;
1570         if (offset == len)
1571             break;
1572     }
1573     memcpy(in, out, len);
1574     pthread_mutex_unlock(&lock);
1575     return 1;
1576 }
1577
1578 int pwddecrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1579     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1580     static unsigned char first = 1;
1581     static EVP_MD_CTX mdctx;
1582     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1583     unsigned int md_len;
1584     uint8_t i, offset = 0, out[128];
1585     
1586     pthread_mutex_lock(&lock);
1587     if (first) {
1588         EVP_MD_CTX_init(&mdctx);
1589         first = 0;
1590     }
1591
1592     input = auth;
1593     for (;;) {
1594         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1595             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1596             !EVP_DigestUpdate(&mdctx, input, 16) ||
1597             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1598             md_len != 16) {
1599             pthread_mutex_unlock(&lock);
1600             return 0;
1601         }
1602         for (i = 0; i < 16; i++)
1603             out[offset + i] = hash[i] ^ in[offset + i];
1604         input = in + offset;
1605         offset += 16;
1606         if (offset == len)
1607             break;
1608     }
1609     memcpy(in, out, len);
1610     pthread_mutex_unlock(&lock);
1611     return 1;
1612 }
1613
1614 int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1615     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1616     static unsigned char first = 1;
1617     static EVP_MD_CTX mdctx;
1618     unsigned char hash[EVP_MAX_MD_SIZE];
1619     unsigned int md_len;
1620     uint8_t i, offset;
1621     
1622     pthread_mutex_lock(&lock);
1623     if (first) {
1624         EVP_MD_CTX_init(&mdctx);
1625         first = 0;
1626     }
1627
1628 #if 0
1629     printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16);
1630     printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2);
1631     printfchars(NULL, "msppencrypt in", "%02x ", text, len);
1632 #endif
1633     
1634     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1635         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1636         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1637         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1638         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1639         pthread_mutex_unlock(&lock);
1640         return 0;
1641     }
1642
1643 #if 0    
1644     printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1645 #endif
1646     
1647     for (i = 0; i < 16; i++)
1648         text[i] ^= hash[i];
1649     
1650     for (offset = 16; offset < len; offset += 16) {
1651 #if 0   
1652         printf("text + offset - 16 c(%d): ", offset / 16);
1653         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1654 #endif
1655         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1656             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1657             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1658             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1659             md_len != 16) {
1660             pthread_mutex_unlock(&lock);
1661             return 0;
1662         }
1663 #if 0
1664         printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1665 #endif    
1666         
1667         for (i = 0; i < 16; i++)
1668             text[offset + i] ^= hash[i];
1669     }
1670     
1671 #if 0
1672     printfchars(NULL, "msppencrypt out", "%02x ", text, len);
1673 #endif
1674
1675     pthread_mutex_unlock(&lock);
1676     return 1;
1677 }
1678
1679 int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1680     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1681     static unsigned char first = 1;
1682     static EVP_MD_CTX mdctx;
1683     unsigned char hash[EVP_MAX_MD_SIZE];
1684     unsigned int md_len;
1685     uint8_t i, offset;
1686     char plain[255];
1687     
1688     pthread_mutex_lock(&lock);
1689     if (first) {
1690         EVP_MD_CTX_init(&mdctx);
1691         first = 0;
1692     }
1693
1694 #if 0
1695     printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16);
1696     printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2);
1697     printfchars(NULL, "msppdecrypt in", "%02x ", text, len);
1698 #endif
1699     
1700     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1701         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1702         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1703         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1704         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1705         pthread_mutex_unlock(&lock);
1706         return 0;
1707     }
1708
1709 #if 0    
1710     printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1711 #endif
1712     
1713     for (i = 0; i < 16; i++)
1714         plain[i] = text[i] ^ hash[i];
1715     
1716     for (offset = 16; offset < len; offset += 16) {
1717 #if 0   
1718         printf("text + offset - 16 c(%d): ", offset / 16);
1719         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1720 #endif
1721         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1722             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1723             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1724             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1725             md_len != 16) {
1726             pthread_mutex_unlock(&lock);
1727             return 0;
1728         }
1729 #if 0
1730         printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1731 #endif    
1732
1733         for (i = 0; i < 16; i++)
1734             plain[offset + i] = text[offset + i] ^ hash[i];
1735     }
1736
1737     memcpy(text, plain, len);
1738 #if 0
1739     printfchars(NULL, "msppdecrypt out", "%02x ", text, len);
1740 #endif
1741
1742     pthread_mutex_unlock(&lock);
1743     return 1;
1744 }
1745
1746 struct realm *id2realm(struct list *realmlist, char *id) {
1747     struct list_node *entry;
1748     struct realm *realm, *subrealm = NULL;
1749
1750     /* need to do locking for subrealms and check subrealm timers */
1751     for (entry = list_first(realmlist); entry; entry = list_next(entry)) {
1752         realm = (struct realm *)entry->data;
1753         if (!regexec(&realm->regex, id, 0, NULL, 0)) {
1754             pthread_mutex_lock(&realm->subrealms_mutex);
1755             if (realm->subrealms)
1756                 subrealm = id2realm(realm->subrealms, id);
1757             pthread_mutex_unlock(&realm->subrealms_mutex);
1758             return subrealm ? subrealm : realm;
1759         }
1760     }
1761     return NULL;
1762 }
1763
1764 /* helper function, only used by removeserversubrealms() */
1765 void _internal_removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) {
1766     struct list_node *entry;
1767     struct realm *realm;
1768     
1769     for (entry = list_first(realmlist); entry;) {
1770         realm = (struct realm *)entry->data;
1771         entry = list_next(entry);
1772         if (realm->srvconfs) {
1773             list_removedata(realm->srvconfs, srv);
1774             if (!list_first(realm->srvconfs)) {
1775                 list_destroy(realm->srvconfs);
1776                 realm->srvconfs = NULL;
1777             }
1778         }
1779         if (realm->accsrvconfs) {
1780             list_removedata(realm->accsrvconfs, srv);
1781             if (!list_first(realm->accsrvconfs)) {
1782                 list_destroy(realm->accsrvconfs);
1783                 realm->accsrvconfs = NULL;
1784             }
1785         }
1786
1787         /* remove subrealm if no servers */
1788         if (!realm->srvconfs && !realm->accsrvconfs) {
1789             list_removedata(realmlist, realm);
1790             freerealm(realm);
1791         }
1792     }
1793 }
1794
1795 void removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) {
1796     struct list_node *entry;
1797     struct realm *realm;
1798     
1799     for (entry = list_first(realmlist); entry; entry = list_next(entry)) {
1800         realm = (struct realm *)entry->data;
1801         pthread_mutex_lock(&realm->subrealms_mutex);
1802         if (realm->subrealms) {
1803             _internal_removeserversubrealms(realm->subrealms, srv);
1804             if (!list_first(realm->subrealms)) {
1805                 list_destroy(realm->subrealms);
1806                 realm->subrealms = NULL;
1807             }
1808         }
1809         pthread_mutex_unlock(&realm->subrealms_mutex);
1810     }
1811 }
1812                         
1813 int rqinqueue(struct server *to, struct client *from, uint8_t id, uint8_t code) {
1814     struct request *rq = to->requests, *end;
1815     
1816     pthread_mutex_lock(&to->newrq_mutex);
1817     for (end = rq + MAX_REQUESTS; rq < end; rq++)
1818         if (rq->buf && !rq->received && rq->origid == id && rq->from == from && *rq->buf == code)
1819             break;
1820     pthread_mutex_unlock(&to->newrq_mutex);
1821     
1822     return rq < end;
1823 }
1824
1825 int attrvalidate(unsigned char *attrs, int length) {
1826     while (length > 1) {
1827         if (ATTRLEN(attrs) < 2) {
1828             debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1829             return 0;
1830         }
1831         length -= ATTRLEN(attrs);
1832         if (length < 0) {
1833             debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1834             return 0;
1835         }
1836         attrs += ATTRLEN(attrs);
1837     }
1838     if (length)
1839         debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1840     return 1;
1841 }
1842
1843 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1844     if (len < 16 || len > 128 || len % 16) {
1845         debug(DBG_WARN, "pwdrecrypt: invalid password length");
1846         return 0;
1847     }
1848         
1849     if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1850         debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1851         return 0;
1852     }
1853 #ifdef DEBUG
1854     printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len);
1855 #endif  
1856     if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1857         debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1858         return 0;
1859     }
1860     return 1;
1861 }
1862
1863 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1864     if (len < 18)
1865         return 0;
1866     if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1867         debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1868         return 0;
1869     }
1870     if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1871         debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1872         return 0;
1873     }
1874     return 1;
1875 }
1876
1877 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1878            char *oldsecret, char *newsecret) {
1879     unsigned char *attr;
1880     
1881     for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1882         debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1883         if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1884             return 0;
1885     }
1886     return 1;
1887 }
1888
1889 int findvendorsubattr(uint32_t *attrs, uint32_t vendor, uint8_t subattr) {
1890     if (!attrs)
1891         return 0;
1892     
1893     for (; attrs[0]; attrs += 2)
1894         if (attrs[0] == vendor && attrs[1] == subattr)
1895             return 1;
1896     return 0;
1897 }
1898
1899 int dovendorrewrite(uint8_t *attrs, uint16_t length, uint32_t *removevendorattrs) {
1900     uint8_t alen, sublen, rmlen = 0;
1901     uint32_t vendor = *(uint32_t *)ATTRVAL(attrs);
1902     uint8_t *subattrs;
1903     
1904     if (!removevendorattrs)
1905         return 0;
1906
1907     while (*removevendorattrs && *removevendorattrs != vendor)
1908         removevendorattrs += 2;
1909     if (!*removevendorattrs)
1910         return 0;
1911     
1912     alen = ATTRLEN(attrs);
1913
1914     if (findvendorsubattr(removevendorattrs, vendor, -1)) {
1915         /* remove entire vendor attribute */
1916         memmove(attrs, attrs + alen, length - alen);
1917         return alen;
1918     }
1919
1920     sublen = alen - 4;
1921     subattrs = ATTRVAL(attrs) + 4;
1922     
1923     if (!attrvalidate(subattrs, sublen)) {
1924         debug(DBG_WARN, "dovendorrewrite: vendor attribute validation failed, no rewrite");
1925         return 0;
1926     }
1927
1928     length -= 6;
1929     while (sublen > 1) {
1930         alen = ATTRLEN(subattrs);
1931         sublen -= alen;
1932         length -= alen;
1933         if (findvendorsubattr(removevendorattrs, vendor, ATTRTYPE(subattrs))) {
1934             memmove(subattrs, subattrs + alen, length);
1935             rmlen += alen;
1936         } else
1937             subattrs += alen;
1938     }
1939
1940     ATTRLEN(attrs) -= rmlen;
1941     return rmlen;
1942 }
1943
1944 void dorewrite(uint8_t *buf, struct rewrite *rewrite) {
1945     uint8_t *attrs, alen;
1946     uint16_t len, rmlen = 0;
1947     
1948     if (!rewrite || (!rewrite->removeattrs && !rewrite->removevendorattrs))
1949         return;
1950
1951     len = RADLEN(buf) - 20;
1952     attrs = buf + 20;
1953     while (len > 1) {
1954         alen = ATTRLEN(attrs);
1955         len -= alen;
1956         if (rewrite->removeattrs && strchr((char *)rewrite->removeattrs, ATTRTYPE(attrs))) {
1957             memmove(attrs, attrs + alen, len);
1958             rmlen += alen;
1959         } else if (ATTRTYPE(attrs) == RAD_Attr_Vendor_Specific && rewrite->removevendorattrs)
1960             rmlen += dovendorrewrite(attrs, len, rewrite->removevendorattrs);
1961         else
1962             attrs += alen;
1963     }
1964     if (rmlen)
1965         ((uint16_t *)buf)[1] = htons(RADLEN(buf) - rmlen);
1966 }
1967
1968 /* returns a pointer to the resized attribute value */
1969 uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) {
1970     uint8_t *attrs, *attr, vallen;
1971     uint16_t len;
1972     unsigned char *new;
1973     
1974     len = RADLEN(*buf) - 20;
1975     attrs = *buf + 20;
1976
1977     attr = attrget(attrs, len, type);
1978     if (!attr)
1979         return NULL;
1980     
1981     vallen = ATTRVALLEN(attr);
1982     if (vallen == newvallen)
1983         return attr + 2;
1984
1985     len += newvallen - vallen;
1986     if (newvallen > vallen) {
1987         new = realloc(*buf, len + 20);
1988         if (!new) {
1989             debug(DBG_ERR, "resizeattr: malloc failed");
1990             return NULL;
1991         }
1992         if (new != *buf) {
1993             attr += new - *buf;
1994             attrs = new + 20;
1995             *buf = new;
1996         }
1997     }
1998     memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen));
1999     attr[1] = newvallen + 2;
2000     ((uint16_t *)*buf)[1] = htons(len + 20);
2001     return attr + 2;
2002 }
2003                 
2004 int rewriteusername(struct request *rq, char *in) {
2005     size_t nmatch = 10, reslen = 0, start = 0;
2006     regmatch_t pmatch[10], *pfield;
2007     int i;
2008     unsigned char *result;
2009     char *out = rq->from->conf->rewriteattrreplacement;
2010     
2011     if (regexec(rq->from->conf->rewriteattrregex, in, nmatch, pmatch, 0)) {
2012         debug(DBG_DBG, "rewriteattr: username not matching, no rewrite");
2013         return 1;
2014     }
2015     
2016     rq->origusername = stringcopy(in, 0);
2017     if (!rq->origusername)
2018         return 0;
2019     
2020     for (i = start; out[i]; i++) {
2021         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
2022             pfield = &pmatch[out[i + 1] - '0'];
2023             if (pfield->rm_so >= 0) {
2024                 reslen += i - start + pfield->rm_eo - pfield->rm_so;
2025                 start = i + 2;
2026             }
2027             i++;
2028         }
2029     }
2030     reslen += i - start;
2031
2032     result = resizeattr(&rq->buf, reslen, RAD_Attr_User_Name);
2033     if (!result)
2034         return 0;
2035     
2036     start = 0;
2037     reslen = 0;
2038     for (i = start; out[i]; i++) {
2039         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
2040             pfield = &pmatch[out[i + 1] - '0'];
2041             if (pfield->rm_so >= 0) {
2042                 memcpy(result + reslen, out + start, i - start);
2043                 reslen += i - start;
2044                 memcpy(result + reslen, in + pfield->rm_so, pfield->rm_eo - pfield->rm_so);
2045                 reslen += pfield->rm_eo - pfield->rm_so;
2046                 start = i + 2;
2047             }
2048             i++;
2049         }
2050     }
2051
2052     memcpy(result + reslen, out + start, i - start);
2053     reslen += i - start;
2054     memcpy(in, result, reslen);
2055     in[reslen] = '\0';
2056     return 1;
2057 }
2058
2059 const char *radmsgtype2string(uint8_t code) {
2060     static const char *rad_msg_names[] = {
2061         "", "Access-Request", "Access-Accept", "Access-Reject",
2062         "Accounting-Request", "Accounting-Response", "", "",
2063         "", "", "", "Access-Challenge",
2064         "Status-Server", "Status-Client"
2065     };
2066     return code < 14 && *rad_msg_names[code] ? rad_msg_names[code] : "Unknown";
2067 }
2068
2069 void char2hex(char *h, unsigned char c) {
2070     static const char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
2071                                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
2072     h[0] = hexdigits[c / 16];
2073     h[1] = hexdigits[c % 16];
2074     return;
2075 }
2076
2077 char *radattr2ascii(char *ascii, size_t len, unsigned char *attr) {
2078     int i, l;
2079     char *s, *d;
2080
2081     if (!attr || len == 1) {
2082         *ascii = '\0';
2083         return ascii;
2084     }
2085
2086     l = ATTRVALLEN(attr);
2087     s = (char *)ATTRVAL(attr);
2088     d = ascii;
2089
2090     for (i = 0; i < l; i++) {
2091         if (s[i] > 31 && s[i] < 127) {
2092             *d++ = s[i];
2093             if (d - ascii == len - 1)
2094                 break;
2095         } else {
2096             if (d - ascii > len - 4)
2097                 break;
2098             *d++ = '%';
2099             char2hex(d, s[i]);
2100             d += 2;
2101             if (d - ascii == len - 1)
2102                 break;
2103         }
2104     }
2105     *d = '\0';
2106     return ascii;
2107 }
2108
2109 void acclog(unsigned char *attrs, int length, char *host) {
2110     unsigned char *attr;
2111     char username[760];
2112     
2113     attr = attrget(attrs, length, RAD_Attr_User_Name);
2114     if (!attr) {
2115         debug(DBG_INFO, "acclog: accounting-request from %s without username attribute", host);
2116         return;
2117     }
2118     radattr2ascii(username, sizeof(username), attr);
2119     debug(DBG_INFO, "acclog: accounting-request from %s with username: %s", host, username);
2120 }
2121         
2122 void respondaccounting(struct request *rq) {
2123     unsigned char *resp;
2124
2125     resp = malloc(20);
2126     if (!resp) {
2127         debug(DBG_ERR, "respondaccounting: malloc failed");
2128         return;
2129     }
2130     memcpy(resp, rq->buf, 20);
2131     resp[0] = RAD_Accounting_Response;
2132     resp[2] = 0;
2133     resp[3] = 20;
2134     debug(DBG_DBG, "respondaccounting: responding to %s", rq->from->conf->host);
2135     sendreply(rq->from, resp, &rq->fromsa, rq->fromudpsock);
2136 }
2137
2138 void respondstatusserver(struct request *rq) {
2139     unsigned char *resp;
2140
2141     resp = malloc(20);
2142     if (!resp) {
2143         debug(DBG_ERR, "respondstatusserver: malloc failed");
2144         return;
2145     }
2146     memcpy(resp, rq->buf, 20);
2147     resp[0] = RAD_Access_Accept;
2148     resp[2] = 0;
2149     resp[3] = 20;
2150     debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
2151     sendreply(rq->from, resp, &rq->fromsa, rq->fromudpsock);
2152 }
2153
2154 void respondreject(struct request *rq, char *message) {
2155     unsigned char *resp;
2156     int len = 20;
2157
2158     if (message && *message)
2159         len += 2 + strlen(message);
2160     
2161     resp = malloc(len);
2162     if (!resp) {
2163         debug(DBG_ERR, "respondreject: malloc failed");
2164         return;
2165     }
2166     memcpy(resp, rq->buf, 20);
2167     resp[0] = RAD_Access_Reject;
2168     *(uint16_t *)(resp + 2) = htons(len);
2169     if (message && *message) {
2170         resp[20] = RAD_Attr_Reply_Message;
2171         resp[21] = len - 20;
2172         memcpy(resp + 22, message, len - 22);
2173     }
2174     sendreply(rq->from, resp, &rq->fromsa, rq->fromudpsock);
2175 }
2176
2177 struct clsrvconf *choosesrvconf(struct list *srvconfs) {
2178     struct list_node *entry;
2179     struct clsrvconf *server, *best = NULL, *first = NULL;
2180
2181     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2182         server = (struct clsrvconf *)entry->data;
2183         if (!server->servers)
2184             return server;
2185         if (!first)
2186             first = server;
2187         if (!server->servers->connectionok)
2188             continue;
2189         if (!server->servers->lostrqs)
2190             return server;
2191         if (!best) {
2192             best = server;
2193             continue;
2194         }
2195         if (server->servers->lostrqs < best->servers->lostrqs)
2196             best = server;
2197     }
2198     return best ? best : first;
2199 }
2200
2201 struct server *findserver(struct realm **realm, char *id, uint8_t acc) {
2202     struct clsrvconf *srvconf;
2203     
2204     *realm = id2realm(realms, id);
2205     if (!*realm)
2206         return NULL;
2207     debug(DBG_DBG, "found matching realm: %s", (*realm)->name);
2208     srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs);
2209     if (!srvconf)
2210         return NULL;
2211     if (!acc && !srvconf->servers)
2212         adddynamicrealmserver(*realm, srvconf, id);
2213     return srvconf->servers;
2214 }
2215
2216 /* returns 0 if validation/authentication fails, else 1 */
2217 int radsrv(struct request *rq) {
2218     uint8_t code, id, *auth, *attrs, *attr;
2219     uint16_t len;
2220     struct server *to = NULL;
2221     char username[254], userascii[760];
2222     unsigned char newauth[16];
2223     struct realm *realm = NULL;
2224     
2225     code = *(uint8_t *)rq->buf;
2226     id = *(uint8_t *)(rq->buf + 1);
2227     len = RADLEN(rq->buf);
2228     auth = (uint8_t *)(rq->buf + 4);
2229
2230     debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
2231     
2232     if (code != RAD_Access_Request && code != RAD_Status_Server && code != RAD_Accounting_Request) {
2233         debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring");
2234         goto exit;
2235     }
2236
2237     len -= 20;
2238     attrs = rq->buf + 20;
2239
2240     if (!attrvalidate(attrs, len)) {
2241         debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
2242         goto errvalauth;
2243     }
2244
2245     attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
2246     if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(rq->buf, ATTRVAL(attr), rq->from->conf->secret))) {
2247         debug(DBG_WARN, "radsrv: message authentication failed");
2248         goto errvalauth;
2249     }
2250
2251     if (code == RAD_Status_Server) {
2252         respondstatusserver(rq);
2253         goto exit;
2254     }
2255     
2256     /* below: code == RAD_Access_Request || code == RAD_Accounting_Request */
2257
2258     if (code == RAD_Accounting_Request) {
2259         memset(newauth, 0, 16);
2260         if (!validauth(rq->buf, newauth, (unsigned char *)rq->from->conf->secret)) {
2261             debug(DBG_WARN, "radsrv: Accounting-Request message authentication failed");
2262             goto errvalauth;
2263         }
2264     }
2265     
2266     if (rq->from->conf->rewrite) {
2267         dorewrite(rq->buf, rq->from->conf->rewrite);
2268         len = RADLEN(rq->buf) - 20;
2269     }
2270     
2271     attr = attrget(attrs, len, RAD_Attr_User_Name);
2272     if (!attr) {
2273         if (code == RAD_Accounting_Request) {
2274             acclog(attrs, len, rq->from->conf->host);
2275             respondaccounting(rq);
2276         } else
2277             debug(DBG_WARN, "radsrv: ignoring access request, no username attribute");
2278         goto exit;
2279     }
2280     memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
2281     username[ATTRVALLEN(attr)] = '\0';
2282     radattr2ascii(userascii, sizeof(userascii), attr);
2283
2284     if (rq->from->conf->rewriteattrregex) {
2285         if (!rewriteusername(rq, username)) {
2286             debug(DBG_WARN, "radsrv: username malloc failed, ignoring request");
2287             goto exit;
2288         }
2289         len = RADLEN(rq->buf) - 20;
2290         auth = (uint8_t *)(rq->buf + 4);
2291         attrs = rq->buf + 20;
2292     }
2293
2294     debug(DBG_DBG, "%s with username: %s", radmsgtype2string(code), userascii);
2295     
2296     to = findserver(&realm, username, code == RAD_Accounting_Request);
2297     if (!realm) {
2298         debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
2299         goto exit;
2300     }
2301     if (!to) {
2302         if (realm->message && code == RAD_Access_Request) {
2303             debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->conf->host, userascii);
2304             respondreject(rq, realm->message);
2305         } else if (realm->accresp && code == RAD_Accounting_Request) {
2306             acclog(attrs, len, rq->from->conf->host);
2307             respondaccounting(rq);
2308         }
2309         goto exit;
2310     }
2311     
2312     if (options.loopprevention && !strcmp(rq->from->conf->name, to->conf->name)) {
2313         debug(DBG_INFO, "radsrv: Loop prevented, not forwarding request from client %s to server %s, discarding",
2314               rq->from->conf->name, to->conf->name);
2315         goto exit;
2316     }
2317
2318     if (rqinqueue(to, rq->from, id, code)) {
2319         debug(DBG_INFO, "radsrv: already got %s from host %s with id %d, ignoring",
2320               radmsgtype2string(code), rq->from->conf->host, id);
2321         goto exit;
2322     }
2323     
2324     if (code != RAD_Accounting_Request) {
2325         if (!RAND_bytes(newauth, 16)) {
2326             debug(DBG_WARN, "radsrv: failed to generate random auth");
2327             goto exit;
2328         }
2329     }
2330
2331 #ifdef DEBUG
2332     printfchars(NULL, "auth", "%02x ", auth, 16);
2333 #endif
2334
2335     attr = attrget(attrs, len, RAD_Attr_User_Password);
2336     if (attr) {
2337         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
2338         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth))
2339             goto exit;
2340     }
2341     
2342     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
2343     if (attr) {
2344         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
2345         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth))
2346             goto exit;
2347     }
2348
2349     rq->origid = id;
2350     memcpy(rq->origauth, auth, 16);
2351     memcpy(auth, newauth, 16);
2352     sendrq(to, rq);
2353     return 1;
2354     
2355  exit:
2356     freerqdata(rq);
2357     return 1;
2358
2359  errvalauth:
2360     freerqdata(rq);
2361     return 0;
2362 }
2363
2364 int replyh(struct server *server, unsigned char *buf) {
2365     struct client *from;
2366     struct request *rq;
2367     int i, len, sublen;
2368     unsigned char *messageauth, *subattrs, *attrs, *attr, *username;
2369     struct sockaddr_storage fromsa;
2370     char tmp[760], stationid[760];
2371     
2372     server->connectionok = 1;
2373     server->lostrqs = 0;
2374         
2375     i = buf[1]; /* i is the id */
2376
2377     if (*buf != RAD_Access_Accept && *buf != RAD_Access_Reject && *buf != RAD_Access_Challenge
2378         && *buf != RAD_Accounting_Response) {
2379         debug(DBG_INFO, "replyh: discarding message type %s, accepting only access accept, access reject, access challenge and accounting response messages", radmsgtype2string(*buf));
2380         return 0;
2381     }
2382     debug(DBG_DBG, "got %s message with id %d", radmsgtype2string(*buf), i);
2383
2384     rq = server->requests + i;
2385
2386     pthread_mutex_lock(&server->newrq_mutex);
2387     if (!rq->buf || !rq->tries) {
2388         pthread_mutex_unlock(&server->newrq_mutex);
2389         debug(DBG_INFO, "replyh: no matching request sent with this id, ignoring reply");
2390         return 0;
2391     }
2392
2393     if (rq->received) {
2394         pthread_mutex_unlock(&server->newrq_mutex);
2395         debug(DBG_INFO, "replyh: already received, ignoring reply");
2396         return 0;
2397     }
2398         
2399     if (!validauth(buf, rq->buf + 4, (unsigned char *)server->conf->secret)) {
2400         pthread_mutex_unlock(&server->newrq_mutex);
2401         debug(DBG_WARN, "replyh: invalid auth, ignoring reply");
2402         return 0;
2403     }
2404         
2405     len = RADLEN(buf) - 20;
2406     attrs = buf + 20;
2407
2408     if (!attrvalidate(attrs, len)) {
2409         pthread_mutex_unlock(&server->newrq_mutex);
2410         debug(DBG_WARN, "replyh: attribute validation failed, ignoring reply");
2411         return 0;
2412     }
2413         
2414     /* Message Authenticator */
2415     messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
2416     if (messageauth) {
2417         if (ATTRVALLEN(messageauth) != 16) {
2418             pthread_mutex_unlock(&server->newrq_mutex);
2419             debug(DBG_WARN, "replyh: illegal message auth attribute length, ignoring reply");
2420             return 0;
2421         }
2422         memcpy(tmp, buf + 4, 16);
2423         memcpy(buf + 4, rq->buf + 4, 16);
2424         if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
2425             pthread_mutex_unlock(&server->newrq_mutex);
2426             debug(DBG_WARN, "replyh: message authentication failed, ignoring reply");
2427             return 0;
2428         }
2429         memcpy(buf + 4, tmp, 16);
2430         debug(DBG_DBG, "replyh: message auth ok");
2431     }
2432     
2433     gettimeofday(&server->lastrcv, NULL);
2434     
2435     if (*rq->buf == RAD_Status_Server) {
2436         rq->received = 1;
2437         pthread_mutex_unlock(&server->newrq_mutex);
2438         debug(DBG_DBG, "replyh: got status server response from %s", server->conf->host);
2439         return 0;
2440     }
2441
2442     gettimeofday(&server->lastreply, NULL);
2443     
2444     from = rq->from;
2445     if (!from) {
2446         pthread_mutex_unlock(&server->newrq_mutex);
2447         debug(DBG_INFO, "replyh: client gone, ignoring reply");
2448         return 0;
2449     }
2450         
2451     if (server->conf->rewrite) {
2452         dorewrite(buf, server->conf->rewrite);
2453         len = RADLEN(buf) - 20;
2454     }
2455     
2456     /* MS MPPE */
2457     for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
2458         if (ATTRVALLEN(attr) <= 4)
2459             break;
2460             
2461         if (attr[2] != 0 || attr[3] != 0 || attr[4] != 1 || attr[5] != 55)  /* 311 == MS */
2462             continue;
2463             
2464         sublen = ATTRVALLEN(attr) - 4;
2465         subattrs = ATTRVAL(attr) + 4;  
2466         if (!attrvalidate(subattrs, sublen) ||
2467             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
2468                     rq, server->conf->secret, from->conf->secret) ||
2469             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
2470                     rq, server->conf->secret, from->conf->secret))
2471             break;
2472     }
2473     if (attr) {
2474         pthread_mutex_unlock(&server->newrq_mutex);
2475         debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
2476         return 0;
2477     }
2478         
2479     if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject || *buf == RAD_Accounting_Response) {
2480         attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_User_Name);
2481         if (attr) {
2482             radattr2ascii(tmp, sizeof(tmp), attr);
2483             attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Calling_Station_Id);
2484             if (attr) {
2485                 radattr2ascii(stationid, sizeof(stationid), attr);
2486                 debug(DBG_INFO, "%s for user %s stationid %s from %s",
2487                       radmsgtype2string(*buf), tmp, stationid, server->conf->host);
2488             } else
2489                 debug(DBG_INFO, "%s for user %s from %s", radmsgtype2string(*buf), tmp, server->conf->host);
2490         }
2491     }
2492         
2493     buf[1] = (char)rq->origid;
2494     memcpy(buf + 4, rq->origauth, 16);
2495 #ifdef DEBUG    
2496     printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
2497 #endif
2498
2499     if (rq->origusername) {
2500         username = resizeattr(&buf, strlen(rq->origusername), RAD_Attr_User_Name);
2501         if (!username) {
2502             pthread_mutex_unlock(&server->newrq_mutex);
2503             debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
2504             return 0;
2505         }
2506         memcpy(username, rq->origusername, strlen(rq->origusername));
2507         len = RADLEN(buf) - 20;
2508         attrs = buf + 20;
2509         if (messageauth)
2510             messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
2511     }
2512         
2513     if (messageauth) {
2514         if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
2515             pthread_mutex_unlock(&server->newrq_mutex);
2516             debug(DBG_WARN, "replyh: failed to create authenticator, malloc failed?, ignoring reply");
2517             return 0;
2518         }
2519         debug(DBG_DBG, "replyh: computed messageauthattr");
2520     }
2521
2522     fromsa = rq->fromsa; /* only needed for UDP */
2523     /* once we set received = 1, rq may be reused */
2524     rq->received = 1;
2525
2526     debug(DBG_INFO, "replyh: passing reply to client %s", from->conf->name);
2527     sendreply(from, buf, &fromsa, rq->fromudpsock);
2528     pthread_mutex_unlock(&server->newrq_mutex);
2529     return 1;
2530 }
2531
2532 void *udpclientrd(void *arg) {
2533     struct server *server;
2534     unsigned char *buf;
2535     int *s = (int *)arg;
2536     
2537     for (;;) {
2538         server = NULL;
2539         buf = radudpget(*s, NULL, &server, NULL);
2540         if (!replyh(server, buf))
2541             free(buf);
2542     }
2543 }
2544
2545 void *tlsclientrd(void *arg) {
2546     struct server *server = (struct server *)arg;
2547     unsigned char *buf;
2548     struct timeval now, lastconnecttry;
2549     
2550     for (;;) {
2551         /* yes, lastconnecttry is really necessary */
2552         lastconnecttry = server->lastconnecttry;
2553         buf = radtlsget(server->ssl, server->dynamiclookuparg ? IDLE_TIMEOUT : 0);
2554         if (!buf) {
2555             if (server->dynamiclookuparg)
2556                 break;
2557             tlsconnect(server, &lastconnecttry, 0, "tlsclientrd");
2558             continue;
2559         }
2560
2561         if (!replyh(server, buf))
2562             free(buf);
2563         if (server->dynamiclookuparg) {
2564             gettimeofday(&now, NULL);
2565             if (now.tv_sec - server->lastreply.tv_sec > IDLE_TIMEOUT) {
2566                 debug(DBG_INFO, "tlsclientrd: idle timeout for %s", server->conf->name);
2567                 break;
2568             }
2569         }
2570     }
2571     ERR_remove_state(0);
2572     server->clientrdgone = 1;
2573     return NULL;
2574 }
2575
2576 void *dtlsclientrd(void *arg) {
2577     struct server *server = (struct server *)arg;
2578     
2579     for (;;) {
2580         sleep(1000);
2581     }
2582     ERR_remove_state(0);
2583     server->clientrdgone = 1;
2584     return NULL;
2585 }
2586
2587 void *tcpclientrd(void *arg) {
2588     struct server *server = (struct server *)arg;
2589     unsigned char *buf;
2590     struct timeval lastconnecttry;
2591     
2592     for (;;) {
2593         /* yes, lastconnecttry is really necessary */
2594         lastconnecttry = server->lastconnecttry;
2595         buf = radtcpget(server->sock, 0);
2596         if (!buf) {
2597             tcpconnect(server, &lastconnecttry, 0, "tcpclientrd");
2598             continue;
2599         }
2600
2601         if (!replyh(server, buf))
2602             free(buf);
2603     }
2604     server->clientrdgone = 1;
2605     return NULL;
2606 }
2607
2608 /* code for removing state not finished */
2609 void *clientwr(void *arg) {
2610     struct server *server = (struct server *)arg;
2611     struct request *rq;
2612     pthread_t clientrdth;
2613     int i, dynconffail = 0;
2614     uint8_t rnd;
2615     struct timeval now;
2616     struct timespec timeout;
2617     struct request statsrvrq;
2618     unsigned char statsrvbuf[38];
2619     struct clsrvconf *conf;
2620     
2621     conf = server->conf;
2622     
2623     if (server->dynamiclookuparg && !dynamicconfig(server)) {
2624         dynconffail = 1;
2625         goto errexit;
2626     }
2627     
2628     if (!conf->addrinfo && !resolvepeer(conf, 0)) {
2629         debug(DBG_WARN, "failed to resolve host %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
2630         goto errexit;
2631     }
2632
2633     memset(&timeout, 0, sizeof(struct timespec));
2634     
2635     if (conf->statusserver) {
2636         memset(&statsrvrq, 0, sizeof(struct request));
2637         memset(statsrvbuf, 0, sizeof(statsrvbuf));
2638         statsrvbuf[0] = RAD_Status_Server;
2639         statsrvbuf[3] = 38;
2640         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
2641         statsrvbuf[21] = 18;
2642         gettimeofday(&server->lastrcv, NULL);
2643     }
2644
2645     if (conf->pdef->connecter) {
2646         if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 6 : 0, "clientwr"))
2647             goto errexit;
2648         server->connectionok = 1;
2649         if (pthread_create(&clientrdth, NULL, conf->pdef->clientreader, (void *)server)) {
2650             debug(DBG_ERR, "clientwr: pthread_create failed");
2651             goto errexit;
2652         }
2653     } else
2654         server->connectionok = 1;
2655     
2656     for (;;) {
2657         pthread_mutex_lock(&server->newrq_mutex);
2658         if (!server->newrq) {
2659             gettimeofday(&now, NULL);
2660             /* random 0-7 seconds */
2661             RAND_bytes(&rnd, 1);
2662             rnd /= 32;
2663             if (conf->statusserver) {
2664                 if (!timeout.tv_sec || timeout.tv_sec > server->lastrcv.tv_sec + STATUS_SERVER_PERIOD + rnd)
2665                     timeout.tv_sec = server->lastrcv.tv_sec + STATUS_SERVER_PERIOD + rnd;
2666             } else {
2667                 if (!timeout.tv_sec || timeout.tv_sec > now.tv_sec + STATUS_SERVER_PERIOD + rnd)
2668                     timeout.tv_sec = now.tv_sec + STATUS_SERVER_PERIOD + rnd;
2669             }
2670 #if 0       
2671             if (timeout.tv_sec > now.tv_sec)
2672                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
2673 #endif      
2674             pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
2675             timeout.tv_sec = 0;
2676         }
2677         if (server->newrq) {
2678             debug(DBG_DBG, "clientwr: got new request");
2679             server->newrq = 0;
2680         }
2681 #if 0   
2682         else
2683             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
2684 #endif  
2685         pthread_mutex_unlock(&server->newrq_mutex);
2686
2687         for (i = 0; i < MAX_REQUESTS; i++) {
2688             if (server->clientrdgone) {
2689                 pthread_join(clientrdth, NULL);
2690                 goto errexit;
2691             }
2692             pthread_mutex_lock(&server->newrq_mutex);
2693             while (i < MAX_REQUESTS && !server->requests[i].buf)
2694                 i++;
2695             if (i == MAX_REQUESTS) {
2696                 pthread_mutex_unlock(&server->newrq_mutex);
2697                 break;
2698             }
2699             rq = server->requests + i;
2700
2701             if (rq->received) {
2702                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
2703                 if (rq->buf) {
2704                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
2705                     freerqdata(rq);
2706                     /* setting this to NULL means that it can be reused */
2707                     rq->buf = NULL;
2708                 }
2709                 pthread_mutex_unlock(&server->newrq_mutex);
2710                 continue;
2711             }
2712             
2713             gettimeofday(&now, NULL);
2714             if (now.tv_sec < rq->expiry.tv_sec) {
2715                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
2716                     timeout.tv_sec = rq->expiry.tv_sec;
2717                 pthread_mutex_unlock(&server->newrq_mutex);
2718                 continue;
2719             }
2720
2721             if (rq->tries == (*rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) {
2722                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
2723                 if (conf->statusserver) {
2724                     if (*rq->buf == RAD_Status_Server) {
2725                         debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->host);
2726                         if (server->lostrqs < 255)
2727                             server->lostrqs++;
2728                     }
2729                 } else {
2730                     debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->host);
2731                     if (server->lostrqs < 255)
2732                         server->lostrqs++;
2733                 }
2734                 freerqdata(rq);
2735                 /* setting this to NULL means that it can be reused */
2736                 rq->buf = NULL;
2737                 pthread_mutex_unlock(&server->newrq_mutex);
2738                 continue;
2739             }
2740             pthread_mutex_unlock(&server->newrq_mutex);
2741
2742             rq->expiry.tv_sec = now.tv_sec + conf->retryinterval;
2743             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
2744                 timeout.tv_sec = rq->expiry.tv_sec;
2745             rq->tries++;
2746             conf->pdef->clientradput(server, server->requests[i].buf);
2747         }
2748         if (conf->statusserver) {
2749             gettimeofday(&now, NULL);
2750             if (now.tv_sec - server->lastrcv.tv_sec >= STATUS_SERVER_PERIOD) {
2751                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
2752                     debug(DBG_WARN, "clientwr: failed to generate random auth");
2753                     continue;
2754                 }
2755                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
2756                 if (!statsrvrq.buf) {
2757                     debug(DBG_ERR, "clientwr: malloc failed");
2758                     continue;
2759                 }
2760                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
2761                 debug(DBG_DBG, "clientwr: sending status server to %s", conf->host);
2762                 sendrq(server, &statsrvrq);
2763             }
2764         }
2765     }
2766  errexit:
2767     conf->servers = NULL;
2768     if (server->dynamiclookuparg) {
2769         removeserversubrealms(realms, conf);
2770         if (dynconffail)
2771             free(conf);
2772         else
2773             freeclsrvconf(conf);
2774     }
2775     freeserver(server, 1);
2776     ERR_remove_state(0);
2777     return NULL;
2778 }
2779
2780 void *udpserverwr(void *arg) {
2781     struct replyq *replyq = udp_server_replyq;
2782     struct reply *reply;
2783     
2784     for (;;) {
2785         pthread_mutex_lock(&replyq->mutex);
2786         while (!(reply = (struct reply *)list_shift(replyq->replies))) {
2787             debug(DBG_DBG, "udp server writer, waiting for signal");
2788             pthread_cond_wait(&replyq->cond, &replyq->mutex);
2789             debug(DBG_DBG, "udp server writer, got signal");
2790         }
2791         pthread_mutex_unlock(&replyq->mutex);
2792
2793         if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0,
2794                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
2795             debug(DBG_WARN, "sendudp: send failed");
2796         free(reply->buf);
2797         free(reply);
2798     }
2799 }
2800
2801 void *udpserverrd(void *arg) {
2802     struct request rq;
2803     int *sp = (int *)arg;
2804     
2805     for (;;) {
2806         memset(&rq, 0, sizeof(struct request));
2807         rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa);
2808         rq.fromudpsock = *sp;
2809         radsrv(&rq);
2810     }
2811     free(sp);
2812 }
2813
2814 void *tlsserverwr(void *arg) {
2815     int cnt;
2816     unsigned long error;
2817     struct client *client = (struct client *)arg;
2818     struct replyq *replyq;
2819     struct reply *reply;
2820     
2821     debug(DBG_DBG, "tlsserverwr: starting for %s", client->conf->host);
2822     replyq = client->replyq;
2823     for (;;) {
2824         pthread_mutex_lock(&replyq->mutex);
2825         while (!list_first(replyq->replies)) {
2826             if (client->ssl) {      
2827                 debug(DBG_DBG, "tlsserverwr: waiting for signal");
2828                 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2829                 debug(DBG_DBG, "tlsserverwr: got signal");
2830             }
2831             if (!client->ssl) {
2832                 /* ssl might have changed while waiting */
2833                 pthread_mutex_unlock(&replyq->mutex);
2834                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
2835                 ERR_remove_state(0);
2836                 pthread_exit(NULL);
2837             }
2838         }
2839         reply = (struct reply *)list_shift(replyq->replies);
2840         pthread_mutex_unlock(&replyq->mutex);
2841         cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
2842         if (cnt > 0)
2843             debug(DBG_DBG, "tlsserverwr: sent %d bytes, Radius packet of length %d",
2844                   cnt, RADLEN(reply->buf));
2845         else
2846             while ((error = ERR_get_error()))
2847                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
2848         free(reply->buf);
2849         free(reply);
2850     }
2851 }
2852
2853 void tlsserverrd(struct client *client) {
2854     struct request rq;
2855     pthread_t tlsserverwrth;
2856     
2857     debug(DBG_DBG, "tlsserverrd: starting for %s", client->conf->host);
2858     
2859     if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
2860         debug(DBG_ERR, "tlsserverrd: pthread_create failed");
2861         return;
2862     }
2863
2864     for (;;) {
2865         memset(&rq, 0, sizeof(struct request));
2866         rq.buf = radtlsget(client->ssl, 0);
2867         if (!rq.buf) {
2868             debug(DBG_ERR, "tlsserverrd: connection from %s lost", client->conf->host);
2869             break;
2870         }
2871         debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
2872         rq.from = client;
2873         if (!radsrv(&rq)) {
2874             debug(DBG_ERR, "tlsserverrd: message authentication/validation failed, closing connection from %s", client->conf->host);
2875             break;
2876         }
2877     }
2878     
2879     /* stop writer by setting ssl to NULL and give signal in case waiting for data */
2880     client->ssl = NULL;
2881     pthread_mutex_lock(&client->replyq->mutex);
2882     pthread_cond_signal(&client->replyq->cond);
2883     pthread_mutex_unlock(&client->replyq->mutex);
2884     debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
2885     pthread_join(tlsserverwrth, NULL);
2886     removeclientrqs(client);
2887     debug(DBG_DBG, "tlsserverrd: reader for %s exiting", client->conf->host);
2888 }
2889
2890 void *tlsservernew(void *arg) {
2891     int s;
2892     struct sockaddr_storage from;
2893     size_t fromlen = sizeof(from);
2894     struct clsrvconf *conf;
2895     struct list_node *cur = NULL;
2896     SSL *ssl = NULL;
2897     X509 *cert = NULL;
2898     unsigned long error;
2899     struct client *client;
2900
2901     s = *(int *)arg;
2902     if (getpeername(s, (struct sockaddr *)&from, &fromlen)) {
2903         debug(DBG_DBG, "tlsservernew: getpeername failed, exiting");
2904         goto exit;
2905     }
2906     debug(DBG_WARN, "tlsservernew: incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
2907
2908     conf = find_conf(RAD_TLS, (struct sockaddr *)&from, clconfs, &cur);
2909     if (conf) {
2910         ssl = SSL_new(conf->ssl_ctx);
2911         SSL_set_fd(ssl, s);
2912
2913         if (SSL_accept(ssl) <= 0) {
2914             while ((error = ERR_get_error()))
2915                 debug(DBG_ERR, "tlsservernew: SSL: %s", ERR_error_string(error, NULL));
2916             debug(DBG_ERR, "tlsservernew: SSL_accept failed");
2917             goto exit;
2918         }
2919         cert = verifytlscert(ssl);
2920         if (!cert)
2921             goto exit;
2922     }
2923     
2924     while (conf) {
2925         if (verifyconfcert(cert, conf)) {
2926             X509_free(cert);
2927             client = addclient(conf);
2928             if (client) {
2929                 client->ssl = ssl;
2930                 tlsserverrd(client);
2931                 removeclient(client);
2932             } else
2933                 debug(DBG_WARN, "tlsservernew: failed to create new client instance");
2934             goto exit;
2935         }
2936         conf = find_conf(RAD_TLS, (struct sockaddr *)&from, clconfs, &cur);
2937     }
2938     debug(DBG_WARN, "tlsservernew: ignoring request, no matching TLS client");
2939     if (cert)
2940         X509_free(cert);
2941
2942  exit:
2943     SSL_free(ssl);
2944     ERR_remove_state(0);
2945     shutdown(s, SHUT_RDWR);
2946     close(s);
2947     pthread_exit(NULL);
2948 }
2949
2950 void *tlslistener(void *arg) {
2951     pthread_t tlsserverth;
2952     int s, *sp = (int *)arg;
2953     struct sockaddr_storage from;
2954     size_t fromlen = sizeof(from);
2955
2956     listen(*sp, 0);
2957
2958     for (;;) {
2959         s = accept(*sp, (struct sockaddr *)&from, &fromlen);
2960         if (s < 0) {
2961             debug(DBG_WARN, "accept failed");
2962             continue;
2963         }
2964         if (pthread_create(&tlsserverth, NULL, tlsservernew, (void *)&s)) {
2965             debug(DBG_ERR, "tlslistener: pthread_create failed");
2966             shutdown(s, SHUT_RDWR);
2967             close(s);
2968             continue;
2969         }
2970         pthread_detach(tlsserverth);
2971     }
2972     free(sp);
2973     return NULL;
2974 }
2975
2976 void *tcpserverwr(void *arg) {
2977     int cnt;
2978     struct client *client = (struct client *)arg;
2979     struct replyq *replyq;
2980     struct reply *reply;
2981     
2982     debug(DBG_DBG, "tcpserverwr: starting for %s", client->conf->host);
2983     replyq = client->replyq;
2984     for (;;) {
2985         pthread_mutex_lock(&replyq->mutex);
2986         while (!list_first(replyq->replies)) {
2987             if (client->s >= 0) {           
2988                 debug(DBG_DBG, "tcpserverwr: waiting for signal");
2989                 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2990                 debug(DBG_DBG, "tcpserverwr: got signal");
2991             }
2992             if (client->s < 0) {
2993                 /* s might have changed while waiting */
2994                 pthread_mutex_unlock(&replyq->mutex);
2995                 debug(DBG_DBG, "tcpserverwr: exiting as requested");
2996                 pthread_exit(NULL);
2997             }
2998         }
2999         reply = (struct reply *)list_shift(replyq->replies);
3000         pthread_mutex_unlock(&replyq->mutex);
3001         cnt = write(client->s, reply->buf, RADLEN(reply->buf));
3002         if (cnt > 0)
3003             debug(DBG_DBG, "tcpserverwr: sent %d bytes, Radius packet of length %d",
3004                   cnt, RADLEN(reply->buf));
3005         else
3006             debug(DBG_ERR, "tcpserverwr: write error for %s", client->conf->host);
3007         free(reply->buf);
3008         free(reply);
3009     }
3010 }
3011
3012 void tcpserverrd(struct client *client) {
3013     struct request rq;
3014     pthread_t tcpserverwrth;
3015     
3016     debug(DBG_DBG, "tcpserverrd: starting for %s", client->conf->host);
3017     
3018     if (pthread_create(&tcpserverwrth, NULL, tcpserverwr, (void *)client)) {
3019         debug(DBG_ERR, "tcpserverrd: pthread_create failed");
3020         return;
3021     }
3022
3023     for (;;) {
3024         memset(&rq, 0, sizeof(struct request));
3025         rq.buf = radtcpget(client->s, 0);
3026         if (!rq.buf) {
3027             debug(DBG_ERR, "tcpserverrd: connection from %s lost", client->conf->host);
3028             break;
3029         }
3030         debug(DBG_DBG, "tcpserverrd: got Radius message from %s", client->conf->host);
3031         rq.from = client;
3032         if (!radsrv(&rq)) {
3033             debug(DBG_ERR, "tcpserverrd: message authentication/validation failed, closing connection from %s", client->conf->host);
3034             break;
3035         }
3036     }
3037
3038     /* stop writer by setting s to -1 and give signal in case waiting for data */
3039     client->s = -1;
3040     pthread_mutex_lock(&client->replyq->mutex);
3041     pthread_cond_signal(&client->replyq->cond);
3042     pthread_mutex_unlock(&client->replyq->mutex);
3043     debug(DBG_DBG, "tcpserverrd: waiting for writer to end");
3044     pthread_join(tcpserverwrth, NULL);
3045     removeclientrqs(client);
3046     debug(DBG_DBG, "tcpserverrd: reader for %s exiting", client->conf->host);
3047 }
3048
3049 void *tcpservernew(void *arg) {
3050     int s;
3051     struct sockaddr_storage from;
3052     size_t fromlen = sizeof(from);
3053     struct clsrvconf *conf;
3054     struct client *client;
3055
3056     s = *(int *)arg;
3057     if (getpeername(s, (struct sockaddr *)&from, &fromlen)) {
3058         debug(DBG_DBG, "tcpservernew: getpeername failed, exiting");
3059         goto exit;
3060     }
3061     debug(DBG_WARN, "tcpservernew: incoming TCP connection from %s", addr2string((struct sockaddr *)&from, fromlen));
3062
3063     conf = find_conf(RAD_TCP, (struct sockaddr *)&from, clconfs, NULL);
3064     if (conf) {
3065         client = addclient(conf);
3066         if (client) {
3067             client->s = s;
3068             tcpserverrd(client);
3069             removeclient(client);
3070         } else
3071             debug(DBG_WARN, "tcpservernew: failed to create new client instance");
3072     } else
3073         debug(DBG_WARN, "tcpservernew: ignoring request, no matching TCP client");
3074
3075  exit:
3076     shutdown(s, SHUT_RDWR);
3077     close(s);
3078     pthread_exit(NULL);
3079 }
3080
3081 void *tcplistener(void *arg) {
3082     pthread_t tcpserverth;
3083     int s, *sp = (int *)arg;
3084     struct sockaddr_storage from;
3085     size_t fromlen = sizeof(from);
3086
3087     listen(*sp, 0);
3088
3089     for (;;) {
3090         s = accept(*sp, (struct sockaddr *)&from, &fromlen);
3091         if (s < 0) {
3092             debug(DBG_WARN, "accept failed");
3093             continue;
3094         }
3095         if (pthread_create(&tcpserverth, NULL, tcpservernew, (void *)&s)) {
3096             debug(DBG_ERR, "tcplistener: pthread_create failed");
3097             shutdown(s, SHUT_RDWR);
3098             close(s);
3099             continue;
3100         }
3101         pthread_detach(tcpserverth);
3102     }
3103     free(sp);
3104     return NULL;
3105 }
3106
3107 void createlistener(uint8_t type, char *arg) {
3108     pthread_t th;
3109     struct clsrvconf *listenres;
3110     struct addrinfo *res;
3111     int s = -1, on = 1, *sp = NULL;
3112     
3113     listenres = resolve_hostport(type, arg, protodefs[type].portdefault);
3114     if (!listenres)
3115         debugx(1, DBG_ERR, "createlistener: failed to resolve %s", arg);
3116     
3117     for (res = listenres->addrinfo; res; res = res->ai_next) {
3118         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3119         if (s < 0) {
3120             debug(DBG_WARN, "createlistener: socket failed");
3121             continue;
3122         }
3123         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
3124 #ifdef IPV6_V6ONLY
3125         if (res->ai_family == AF_INET6)
3126             setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
3127 #endif          
3128         if (bind(s, res->ai_addr, res->ai_addrlen)) {
3129             debug(DBG_WARN, "createlistener: bind failed");
3130             close(s);
3131             s = -1;
3132             continue;
3133         }
3134
3135         sp = malloc(sizeof(int));
3136         if (!sp)
3137             debugx(1, DBG_ERR, "malloc failed");
3138         *sp = s;
3139         if (pthread_create(&th, NULL, protodefs[type].listener, (void *)sp))
3140             debugx(1, DBG_ERR, "pthread_create failed");
3141         pthread_detach(th);
3142     }
3143     if (!sp)
3144         debugx(1, DBG_ERR, "createlistener: socket/bind failed");
3145     
3146     debug(DBG_WARN, "createlistener: listening for %s on %s:%s", protodefs[type].name,
3147           listenres->host ? listenres->host : "*", listenres->port);
3148     freeclsrvres(listenres);
3149 }
3150
3151 void createlisteners(uint8_t type, char **args) {
3152     int i;
3153
3154     if (args)
3155         for (i = 0; args[i]; i++)
3156             createlistener(type, args[i]);
3157     else
3158         createlistener(type, NULL);
3159 }
3160
3161 SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
3162     SSL_CTX *ctx = NULL;
3163     STACK_OF(X509_NAME) *calist;
3164     X509_STORE *x509_s;
3165     int i;
3166     unsigned long error;
3167
3168     if (!ssl_locks) {
3169         ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
3170         ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
3171         for (i = 0; i < CRYPTO_num_locks(); i++) {
3172             ssl_lock_count[i] = 0;
3173             pthread_mutex_init(&ssl_locks[i], NULL);
3174         }
3175         CRYPTO_set_id_callback(ssl_thread_id);
3176         CRYPTO_set_locking_callback(ssl_locking_callback);
3177
3178         SSL_load_error_strings();
3179         SSL_library_init();
3180
3181         while (!RAND_status()) {
3182             time_t t = time(NULL);
3183             pid_t pid = getpid();
3184             RAND_seed((unsigned char *)&t, sizeof(time_t));
3185             RAND_seed((unsigned char *)&pid, sizeof(pid));
3186         }
3187     }
3188
3189     switch (type) {
3190     case RAD_TLS:
3191         ctx = SSL_CTX_new(TLSv1_method());
3192         break;
3193     case RAD_DTLS:
3194         ctx = SSL_CTX_new(DTLSv1_method());
3195         SSL_CTX_set_read_ahead(ctx, 1);
3196         break;
3197     }
3198     if (!ctx) {
3199         debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
3200         return NULL;
3201     }
3202     
3203     if (conf->certkeypwd) {
3204         SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd);
3205         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
3206     }
3207     if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
3208         !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
3209         !SSL_CTX_check_private_key(ctx) ||
3210         !SSL_CTX_load_verify_locations(ctx, conf->cacertfile, conf->cacertpath)) {
3211         while ((error = ERR_get_error()))
3212             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
3213         debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
3214         SSL_CTX_free(ctx);
3215         return NULL;
3216     }
3217
3218     calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
3219     if (!conf->cacertfile || calist) {
3220         if (conf->cacertpath) {
3221             if (!calist)
3222                 calist = sk_X509_NAME_new_null();
3223             if (!SSL_add_dir_cert_subjects_to_stack(calist, conf->cacertpath)) {
3224                 sk_X509_NAME_free(calist);
3225                 calist = NULL;
3226             }
3227         }
3228     }
3229     if (!calist) {
3230         while ((error = ERR_get_error()))
3231             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
3232         debug(DBG_ERR, "tlscreatectx: Error adding CA subjects in TLS context %s", conf->name);
3233         SSL_CTX_free(ctx);
3234         return NULL;
3235     }
3236     ERR_clear_error(); /* add_dir_cert_subj returns errors on success */
3237     SSL_CTX_set_client_CA_list(ctx, calist);
3238     
3239     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
3240     SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
3241
3242     if (conf->crlcheck) {
3243         x509_s = SSL_CTX_get_cert_store(ctx);
3244         X509_STORE_set_flags(x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
3245     }
3246
3247     debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
3248     return ctx;
3249 }
3250
3251 SSL_CTX *tlsgetctx(uint8_t type, char *alt1, char *alt2) {
3252     struct list_node *entry;
3253     struct tls *t, *t1 = NULL, *t2 = NULL;
3254     SSL_CTX *ctx = NULL;
3255     
3256     pthread_mutex_lock(&tlsconfs_lock);
3257     
3258     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
3259         t = (struct tls *)entry->data;
3260         if (!strcasecmp(t->name, alt1)) {
3261             t1 = t;
3262             break;
3263         }
3264         if (!t2 && alt2 && !strcasecmp(t->name, alt2))
3265             t2 = t;
3266     }
3267
3268     t = (t1 ? t1 : t2);
3269     if (!t)
3270         goto exit;
3271
3272     switch (type) {
3273     case RAD_TLS:
3274         if (!t->tlsctx)
3275             t->tlsctx = tlscreatectx(RAD_TLS, t);
3276         ctx = t->tlsctx;
3277         break;
3278     case RAD_DTLS:
3279         if (!t->dtlsctx)
3280             t->dtlsctx = tlscreatectx(RAD_DTLS, t);
3281         ctx = t->dtlsctx;
3282         break;
3283     }
3284     
3285  exit:
3286     pthread_mutex_unlock(&tlsconfs_lock);
3287     return ctx;
3288 }
3289
3290 struct list *addsrvconfs(char *value, char **names) {
3291     struct list *conflist;
3292     int n;
3293     struct list_node *entry;
3294     struct clsrvconf *conf = NULL;
3295     
3296     if (!names || !*names)
3297         return NULL;
3298     
3299     conflist = list_create();
3300     if (!conflist) {
3301         debug(DBG_ERR, "malloc failed");
3302         return NULL;
3303     }
3304
3305     for (n = 0; names[n]; n++) {
3306         for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
3307             conf = (struct clsrvconf *)entry->data;
3308             if (!strcasecmp(names[n], conf->name))
3309                 break;
3310         }
3311         if (!entry) {
3312             debug(DBG_ERR, "addsrvconfs failed for realm %s, no server named %s", value, names[n]);
3313             list_destroy(conflist);
3314             return NULL;
3315         }
3316         if (!list_push(conflist, conf)) {
3317             debug(DBG_ERR, "malloc failed");
3318             list_destroy(conflist);
3319             return NULL;
3320         }
3321         debug(DBG_DBG, "addsrvconfs: added server %s for realm %s", conf->name, value);
3322     }
3323     return conflist;
3324 }
3325
3326 void freerealm(struct realm *realm) {
3327     if (!realm)
3328         return;
3329     free(realm->name);
3330     free(realm->message);
3331     regfree(&realm->regex);
3332     pthread_mutex_destroy(&realm->subrealms_mutex);
3333     if (realm->subrealms)
3334         list_destroy(realm->subrealms);
3335     if (realm->srvconfs) {
3336         /* emptying list without freeing data */
3337         while (list_shift(realm->srvconfs));
3338         list_destroy(realm->srvconfs);
3339     }
3340     if (realm->accsrvconfs) {
3341         /* emptying list without freeing data */
3342         while (list_shift(realm->accsrvconfs));
3343         list_destroy(realm->accsrvconfs);
3344     }
3345     free(realm);
3346 }
3347
3348 struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message, uint8_t accresp) {
3349     int n;
3350     struct realm *realm;
3351     char *s, *regex = NULL;
3352     
3353     if (*value == '/') {
3354         /* regexp, remove optional trailing / if present */
3355         if (value[strlen(value) - 1] == '/')
3356             value[strlen(value) - 1] = '\0';
3357     } else {
3358         /* not a regexp, let us make it one */
3359         if (*value == '*' && !value[1])
3360             regex = stringcopy(".*", 0);
3361         else {
3362             for (n = 0, s = value; *s;)
3363                 if (*s++ == '.')
3364                     n++;
3365             regex = malloc(strlen(value) + n + 3);
3366             if (regex) {
3367                 regex[0] = '@';
3368                 for (n = 1, s = value; *s; s++) {
3369                     if (*s == '.')
3370                         regex[n++] = '\\';
3371                     regex[n++] = *s;
3372                 }
3373                 regex[n++] = '$';
3374                 regex[n] = '\0';
3375             }
3376         }
3377         if (!regex) {
3378             debug(DBG_ERR, "malloc failed");
3379             realm = NULL;
3380             goto exit;
3381         }
3382         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
3383     }
3384
3385     realm = malloc(sizeof(struct realm));
3386     if (!realm) {
3387         debug(DBG_ERR, "malloc failed");
3388         goto exit;
3389     }
3390     memset(realm, 0, sizeof(struct realm));
3391     
3392     if (pthread_mutex_init(&realm->subrealms_mutex, NULL)) {
3393         debug(DBG_ERR, "mutex init failed");
3394         free(realm);
3395         realm = NULL;
3396         goto exit;
3397     }
3398
3399     realm->name = stringcopy(value, 0);
3400     if (!realm->name) {
3401         debug(DBG_ERR, "malloc failed");
3402         goto errexit;
3403     }
3404     if (message && strlen(message) > 253) {
3405         debug(DBG_ERR, "ReplyMessage can be at most 253 bytes");
3406         goto errexit;
3407     }
3408     realm->message = message;
3409     realm->accresp = accresp;
3410     
3411     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB)) {
3412         debug(DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
3413         goto errexit;
3414     }
3415     
3416     if (servers && *servers) {
3417         realm->srvconfs = addsrvconfs(value, servers);
3418         if (!realm->srvconfs)
3419             goto errexit;
3420     }
3421     
3422     if (accservers && *accservers) {
3423         realm->accsrvconfs = addsrvconfs(value, accservers);
3424         if (!realm->accsrvconfs)
3425             goto errexit;
3426     }
3427
3428     if (!list_push(realmlist, realm)) {
3429         debug(DBG_ERR, "malloc failed");
3430         pthread_mutex_destroy(&realm->subrealms_mutex);
3431         goto errexit;
3432     }
3433     
3434     debug(DBG_DBG, "addrealm: added realm %s", value);
3435     goto exit;
3436
3437  errexit:
3438     freerealm(realm);
3439     realm = NULL;
3440     
3441  exit:
3442     free(regex);
3443     if (servers) {
3444         for (n = 0; servers[n]; n++)
3445             free(servers[n]);
3446         free(servers);
3447     }
3448     if (accservers) {
3449         for (n = 0; accservers[n]; n++)
3450             free(accservers[n]);
3451         free(accservers);
3452     }
3453     return realm;
3454 }
3455
3456 void adddynamicrealmserver(struct realm *realm, struct clsrvconf *conf, char *id) {
3457     struct clsrvconf *srvconf;
3458     struct realm *newrealm = NULL;
3459     char *realmname, *s;
3460     pthread_t clientth;
3461     
3462     if (!conf->dynamiclookupcommand)
3463         return;
3464
3465     /* create dynamic for the realm (string after last @, exit if nothing after @ */
3466     realmname = strrchr(id, '@');
3467     if (!realmname)
3468         return;
3469     realmname++;
3470     if (!*realmname)
3471         return;
3472     for (s = realmname; *s; s++)
3473         if (*s != '.' && *s != '-' && !isalnum((int)*s))
3474             return;
3475     
3476     pthread_mutex_lock(&realm->subrealms_mutex);
3477     /* exit if we now already got a matching subrealm */
3478     if (id2realm(realm->subrealms, id))
3479         goto exit;
3480     srvconf = malloc(sizeof(struct clsrvconf));
3481     if (!srvconf) {
3482         debug(DBG_ERR, "malloc failed");
3483         goto exit;
3484     }
3485     *srvconf = *conf;
3486     if (!addserver(srvconf))
3487         goto errexit;
3488
3489     if (!realm->subrealms)
3490         realm->subrealms = list_create();
3491     if (!realm->subrealms)
3492         goto errexit;
3493     newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, NULL, 0);
3494     if (!newrealm)
3495         goto errexit;
3496
3497     /* add server and accserver to newrealm */
3498     newrealm->srvconfs = list_create();
3499     if (!newrealm->srvconfs || !list_push(newrealm->srvconfs, srvconf)) {
3500         debug(DBG_ERR, "malloc failed");
3501         goto errexit;
3502     }
3503     newrealm->accsrvconfs = list_create();
3504     if (!newrealm->accsrvconfs || !list_push(newrealm->accsrvconfs, srvconf)) {
3505         debug(DBG_ERR, "malloc failed");
3506         goto errexit;
3507     }
3508
3509     srvconf->servers->dynamiclookuparg = stringcopy(realmname, 0);
3510
3511     if (pthread_create(&clientth, NULL, clientwr, (void *)(srvconf->servers))) {
3512         debug(DBG_ERR, "pthread_create failed");
3513         goto errexit;
3514     }
3515     pthread_detach(clientth);
3516     goto exit;
3517     
3518  errexit:
3519     if (newrealm) {
3520         list_removedata(realm->subrealms, newrealm);
3521         freerealm(newrealm);
3522         if (!list_first(realm->subrealms)) {
3523             list_destroy(realm->subrealms);
3524             realm->subrealms = NULL;
3525         }
3526     }
3527     freeserver(srvconf->servers, 1);
3528     free(srvconf);
3529     debug(DBG_ERR, "failed to create dynamic server");
3530
3531  exit:
3532     pthread_mutex_unlock(&realm->subrealms_mutex);
3533 }
3534
3535 int dynamicconfig(struct server *server) {
3536     int ok, fd[2], status;
3537     pid_t pid;
3538     struct clsrvconf *conf = server->conf;
3539     struct gconffile *cf = NULL;
3540     
3541     /* for now we only learn hostname/address */
3542     debug(DBG_DBG, "dynamicconfig: need dynamic server config for %s", server->dynamiclookuparg);
3543
3544     if (pipe(fd) > 0) {
3545         debug(DBG_ERR, "dynamicconfig: pipe error");
3546         goto errexit;
3547     }
3548     pid = fork();
3549     if (pid < 0) {
3550         debug(DBG_ERR, "dynamicconfig: fork error");
3551         close(fd[0]);
3552         close(fd[1]);
3553         goto errexit;
3554     } else if (pid == 0) {
3555         /* child */
3556         close(fd[0]);
3557         if (fd[1] != STDOUT_FILENO) {
3558             if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
3559                 debugx(1, DBG_ERR, "dynamicconfig: dup2 error for command %s", conf->dynamiclookupcommand);
3560             close(fd[1]);
3561         }
3562         if (execlp(conf->dynamiclookupcommand, conf->dynamiclookupcommand, server->dynamiclookuparg, NULL) < 0)
3563             debugx(1, DBG_ERR, "dynamicconfig: exec error for command %s", conf->dynamiclookupcommand);
3564     }
3565
3566     close(fd[1]);
3567     pushgconffile(&cf, fdopen(fd[0], "r"), conf->dynamiclookupcommand);
3568     ok = getgenericconfig(&cf, NULL,
3569                           "Server", CONF_CBK, confserver_cb, (void *)conf,
3570                           NULL
3571                           );
3572     freegconf(&cf);
3573         
3574     if (waitpid(pid, &status, 0) < 0) {
3575         debug(DBG_ERR, "dynamicconfig: wait error");
3576         goto errexit;
3577     }
3578     
3579     if (status) {
3580         debug(DBG_INFO, "dynamicconfig: command exited with status %d", WEXITSTATUS(status));
3581         goto errexit;
3582     }
3583
3584     if (ok)
3585         return 1;
3586
3587  errexit:    
3588     debug(DBG_WARN, "dynamicconfig: failed to obtain dynamic server config");
3589     return 0;
3590 }
3591
3592 int addmatchcertattr(struct clsrvconf *conf) {
3593     char *v;
3594     regex_t **r;
3595     
3596     if (!strncasecmp(conf->matchcertattr, "CN:/", 4)) {
3597         r = &conf->certcnregex;
3598         v = conf->matchcertattr + 4;
3599     } else if (!strncasecmp(conf->matchcertattr, "SubjectAltName:URI:/", 20)) {
3600         r = &conf->certuriregex;
3601         v = conf->matchcertattr + 20;
3602     } else
3603         return 0;
3604     if (!*v)
3605         return 0;
3606     /* regexp, remove optional trailing / if present */
3607     if (v[strlen(v) - 1] == '/')
3608         v[strlen(v) - 1] = '\0';
3609     if (!*v)
3610         return 0;
3611
3612     *r = malloc(sizeof(regex_t));
3613     if (!*r) {
3614         debug(DBG_ERR, "malloc failed");
3615         return 0;
3616     }
3617     if (regcomp(*r, v, REG_ICASE | REG_NOSUB)) {
3618         free(*r);
3619         *r = NULL;
3620         debug(DBG_ERR, "failed to compile regular expression %s", v);
3621         return 0;
3622     }
3623     return 1;
3624 }
3625
3626 int addrewriteattr(struct clsrvconf *conf) {
3627     char *v, *w;
3628     
3629     v = conf->rewriteattr + 11;
3630     if (strncasecmp(conf->rewriteattr, "User-Name:/", 11) || !*v)
3631         return 0;
3632     /* regexp, remove optional trailing / if present */
3633     if (v[strlen(v) - 1] == '/')
3634         v[strlen(v) - 1] = '\0';
3635
3636     w = strchr(v, '/');
3637     if (!*w)
3638         return 0;
3639     *w = '\0';
3640     w++;
3641     
3642     conf->rewriteattrregex = malloc(sizeof(regex_t));
3643     if (!conf->rewriteattrregex) {
3644         debug(DBG_ERR, "malloc failed");
3645         return 0;
3646     }
3647
3648     conf->rewriteattrreplacement = stringcopy(w, 0);
3649     if (!conf->rewriteattrreplacement) {
3650         free(conf->rewriteattrregex);
3651         conf->rewriteattrregex = NULL;
3652         return 0;
3653     }
3654     
3655     if (regcomp(conf->rewriteattrregex, v, REG_ICASE | REG_EXTENDED)) {
3656         free(conf->rewriteattrregex);
3657         conf->rewriteattrregex = NULL;
3658         free(conf->rewriteattrreplacement);
3659         conf->rewriteattrreplacement = NULL;
3660         debug(DBG_ERR, "failed to compile regular expression %s", v);
3661         return 0;
3662     }
3663
3664     return 1;
3665 }
3666
3667 /* should accept both names and numeric values, only numeric right now */
3668 uint8_t attrname2val(char *attrname) {
3669     int val = 0;
3670     
3671     val = atoi(attrname);
3672     return val > 0 && val < 256 ? val : 0;
3673 }
3674
3675 /* should accept both names and numeric values, only numeric right now */
3676 int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) {
3677     char *s;
3678     
3679     *vendor = atoi(attrname);
3680     s = strchr(attrname, ':');
3681     if (!s) {
3682         *type = -1;
3683         return 1;
3684     }
3685     *type = atoi(s + 1);
3686     return *type >= 0 && *type < 256;
3687 }
3688
3689 struct rewrite *getrewrite(char *alt1, char *alt2) {
3690     struct list_node *entry;
3691     struct rewriteconf *r, *r1 = NULL, *r2 = NULL;
3692     
3693     for (entry = list_first(rewriteconfs); entry; entry = list_next(entry)) {
3694         r = (struct rewriteconf *)entry->data;
3695         if (!strcasecmp(r->name, alt1)) {
3696             r1 = r;
3697             break;
3698         }
3699         if (!r2 && alt2 && !strcasecmp(r->name, alt2))
3700             r2 = r;
3701     }
3702
3703     r = (r1 ? r1 : r2);
3704     if (!r)
3705         return NULL;
3706     return r->rewrite;
3707 }
3708
3709 void addrewrite(char *value, char **attrs, char **vattrs) {
3710     struct rewriteconf *new;
3711     struct rewrite *rewrite = NULL;
3712     int i, n;
3713     uint8_t *a = NULL;
3714     uint32_t *p, *va = NULL;
3715
3716     if (attrs) {
3717         n = 0;
3718         for (; attrs[n]; n++);
3719         a = malloc((n + 1) * sizeof(uint8_t));
3720         if (!a)
3721             debugx(1, DBG_ERR, "malloc failed");
3722     
3723         for (i = 0; i < n; i++) {
3724             if (!(a[i] = attrname2val(attrs[i])))
3725                 debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", attrs[i]);
3726             free(attrs[i]);
3727         }
3728         free(attrs);
3729         a[i] = 0;
3730     }
3731     
3732     if (vattrs) {
3733         n = 0;
3734         for (; vattrs[n]; n++);
3735         va = malloc((2 * n + 1) * sizeof(uint32_t));
3736         if (!va)
3737             debugx(1, DBG_ERR, "malloc failed");
3738     
3739         for (p = va, i = 0; i < n; i++, p += 2) {
3740             if (!vattrname2val(vattrs[i], p, p + 1))
3741                 debugx(1, DBG_ERR, "addrewrite: invalid vendor attribute %s", vattrs[i]);
3742             free(vattrs[i]);
3743         }
3744         free(vattrs);
3745         *p = 0;
3746     }
3747     
3748     if (a || va) {
3749         rewrite = malloc(sizeof(struct rewrite));
3750         if (!rewrite)
3751             debugx(1, DBG_ERR, "malloc failed");
3752         rewrite->removeattrs = a;
3753         rewrite->removevendorattrs = va;
3754     }
3755     
3756     new = malloc(sizeof(struct rewriteconf));
3757     if (!new || !list_push(rewriteconfs, new))
3758         debugx(1, DBG_ERR, "malloc failed");
3759
3760     memset(new, 0, sizeof(struct rewriteconf));
3761     new->name = stringcopy(value, 0);
3762     if (!new->name)
3763         debugx(1, DBG_ERR, "malloc failed");
3764         
3765     new->rewrite = rewrite;
3766     debug(DBG_DBG, "addrewrite: added rewrite block %s", value);
3767 }
3768
3769 void freeclsrvconf(struct clsrvconf *conf) {
3770     free(conf->name);
3771     free(conf->host);
3772     free(conf->port);
3773     free(conf->secret);
3774     free(conf->tls);
3775     free(conf->matchcertattr);
3776     if (conf->certcnregex)
3777         regfree(conf->certcnregex);
3778     if (conf->certuriregex)
3779         regfree(conf->certuriregex);
3780     free(conf->confrewrite);
3781     free(conf->rewriteattr);
3782     if (conf->rewriteattrregex)
3783         regfree(conf->rewriteattrregex);
3784     free(conf->rewriteattrreplacement);
3785     free(conf->dynamiclookupcommand);
3786     free(conf->rewrite);
3787     if (conf->addrinfo)
3788         freeaddrinfo(conf->addrinfo);
3789     /* not touching ssl_ctx, clients and servers */
3790     free(conf);
3791 }
3792
3793 int mergeconfstring(char **dst, char **src) {
3794     char *t;
3795     
3796     if (*src) {
3797         *dst = *src;
3798         *src = NULL;
3799         return 1;
3800     }
3801     if (*dst) {
3802         t = stringcopy(*dst, 0);
3803         if (!t) {
3804             debug(DBG_ERR, "malloc failed");
3805             return 0;
3806         }
3807         *dst = t;
3808     }
3809     return 1;
3810 }
3811
3812 /* assumes dst is a shallow copy */
3813 int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
3814     if (!mergeconfstring(&dst->name, &src->name) ||
3815         !mergeconfstring(&dst->host, &src->host) ||
3816         !mergeconfstring(&dst->port, &src->port) ||
3817         !mergeconfstring(&dst->secret, &src->secret) ||
3818         !mergeconfstring(&dst->tls, &src->tls) ||
3819         !mergeconfstring(&dst->matchcertattr, &src->matchcertattr) ||
3820         !mergeconfstring(&dst->confrewrite, &src->confrewrite) ||
3821         !mergeconfstring(&dst->dynamiclookupcommand, &src->dynamiclookupcommand))
3822         return 0;
3823     if (src->pdef)
3824         dst->pdef = src->pdef;
3825     dst->statusserver = src->statusserver;
3826     dst->certnamecheck = src->certnamecheck;
3827     if (src->retryinterval != 255)
3828         dst->retryinterval = src->retryinterval;
3829     if (src->retrycount != 255)
3830         dst->retrycount = src->retrycount;
3831     return 1;
3832 }
3833
3834 int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3835     struct clsrvconf *conf;
3836     char *conftype = NULL;
3837     
3838     debug(DBG_DBG, "confclient_cb called for %s", block);
3839
3840     conf = malloc(sizeof(struct clsrvconf));
3841     if (!conf || !list_push(clconfs, conf))
3842         debugx(1, DBG_ERR, "malloc failed");
3843     memset(conf, 0, sizeof(struct clsrvconf));
3844     conf->certnamecheck = 1;
3845     
3846     if (!getgenericconfig(cf, block,
3847                      "type", CONF_STR, &conftype,
3848                      "host", CONF_STR, &conf->host,
3849                      "secret", CONF_STR, &conf->secret,
3850                      "tls", CONF_STR, &conf->tls,
3851                      "matchcertificateattribute", CONF_STR, &conf->matchcertattr,
3852                      "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
3853                      "rewrite", CONF_STR, &conf->confrewrite,
3854                      "rewriteattribute", CONF_STR, &conf->rewriteattr,
3855                      NULL
3856                           ))
3857         debugx(1, DBG_ERR, "configuration error");
3858     
3859     conf->name = stringcopy(val, 0);
3860     if (!conf->host)
3861         conf->host = stringcopy(val, 0);
3862     if (!conf->name || !conf->host)
3863         debugx(1, DBG_ERR, "malloc failed");
3864         
3865     if (!conftype)
3866         debugx(1, DBG_ERR, "error in block %s, option type missing", block);
3867     conf->type = protoname2int(conftype);
3868     conf->pdef = &protodefs[conf->type];
3869     if (!conf->pdef->name)
3870         debugx(1, DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
3871     free(conftype);
3872     
3873     if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
3874         conf->ssl_ctx = conf->tls ? tlsgetctx(conf->type, conf->tls, NULL) : tlsgetctx(conf->type, "defaultclient", "default");
3875         if (!conf->ssl_ctx)
3876             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
3877         if (conf->matchcertattr && !addmatchcertattr(conf))
3878             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
3879     }
3880     
3881     conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultclient", "default");
3882     
3883     if (conf->rewriteattr) {
3884         if (!addrewriteattr(conf))
3885             debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
3886     }
3887     
3888     if (!resolvepeer(conf, 0))
3889         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
3890     
3891     if (!conf->secret) {
3892         if (!conf->pdef->secretdefault)
3893             debugx(1, DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name);
3894         conf->secret = stringcopy(conf->pdef->secretdefault, 0);
3895         if (!conf->secret)
3896             debugx(1, DBG_ERR, "malloc failed");
3897     }
3898     return 1;
3899 }
3900
3901 int compileserverconfig(struct clsrvconf *conf, const char *block) {
3902     if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
3903         conf->ssl_ctx = conf->tls ? tlsgetctx(conf->type, conf->tls, NULL) : tlsgetctx(conf->type, "defaultserver", "default");
3904         if (!conf->ssl_ctx) {
3905             debug(DBG_ERR, "error in block %s, no tls context defined", block);
3906             return 0;
3907         }
3908         if (conf->matchcertattr && !addmatchcertattr(conf)) {
3909             debug(DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
3910             return 0;
3911         }
3912     }
3913
3914     if (!conf->port) {
3915         conf->port = stringcopy(conf->pdef->portdefault, 0);
3916         if (!conf->port) {
3917             debug(DBG_ERR, "malloc failed");
3918             return 0;
3919         }
3920     }
3921     
3922     if (conf->retryinterval == 255)
3923         conf->retryinterval = protodefs[conf->type].retryintervaldefault;
3924     if (conf->retrycount == 255)
3925         conf->retrycount = protodefs[conf->type].retrycountdefault;
3926     
3927     conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultserver", "default");
3928
3929     if (!conf->secret) {
3930         if (!conf->pdef->secretdefault) {
3931             debug(DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name);
3932             return 0;
3933         }
3934         conf->secret = stringcopy(conf->pdef->secretdefault, 0);
3935         if (!conf->secret) {
3936             debug(DBG_ERR, "malloc failed");
3937             return 0;
3938         }
3939     }
3940     
3941     if (!conf->dynamiclookupcommand && !resolvepeer(conf, 0)) {
3942         debug(DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
3943         return 0;
3944     }
3945     return 1;
3946 }
3947                         
3948 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3949     struct clsrvconf *conf, *resconf;
3950     char *conftype = NULL;
3951     long int retryinterval = LONG_MIN, retrycount = LONG_MIN;
3952     
3953     debug(DBG_DBG, "confserver_cb called for %s", block);
3954
3955     conf = malloc(sizeof(struct clsrvconf));
3956     if (!conf) {
3957         debug(DBG_ERR, "malloc failed");
3958         return 0;
3959     }
3960     memset(conf, 0, sizeof(struct clsrvconf));
3961     resconf = (struct clsrvconf *)arg;
3962     if (resconf) {
3963         conf->statusserver = resconf->statusserver;
3964         conf->certnamecheck = resconf->certnamecheck;
3965     } else
3966         conf->certnamecheck = 1;
3967
3968     if (!getgenericconfig(cf, block,
3969                           "type", CONF_STR, &conftype,
3970                           "host", CONF_STR, &conf->host,
3971                           "port", CONF_STR, &conf->port,
3972                           "secret", CONF_STR, &conf->secret,
3973                           "tls", CONF_STR, &conf->tls,
3974                           "MatchCertificateAttribute", CONF_STR, &conf->matchcertattr,
3975                           "rewrite", CONF_STR, &conf->confrewrite,
3976                           "StatusServer", CONF_BLN, &conf->statusserver,
3977                           "RetryInterval", CONF_LINT, &retryinterval,
3978                           "RetryCount", CONF_LINT, &retrycount,
3979                           "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
3980                           "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand,
3981                           NULL
3982                           )) {
3983         debug(DBG_ERR, "configuration error");
3984         goto errexit;
3985     }
3986     
3987     conf->name = stringcopy(val, 0);
3988     if (!conf->name) {
3989         debug(DBG_ERR, "malloc failed");
3990         goto errexit;
3991     }
3992     if (!conf->host) {
3993         conf->host = stringcopy(val, 0);
3994         if (!conf->host) {
3995             debug(DBG_ERR, "malloc failed");
3996             goto errexit;
3997         }
3998     }
3999
4000     if (!conftype)
4001         debugx(1, DBG_ERR, "error in block %s, option type missing", block);
4002     conf->type = protoname2int(conftype);
4003     conf->pdef = &protodefs[conf->type];
4004     if (!conf->pdef->name) {
4005         debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
4006         free(conftype);
4007         goto errexit;
4008     }
4009     free(conftype);
4010             
4011     if (retryinterval != LONG_MIN) {
4012         if (retryinterval < 1 || retryinterval > conf->pdef->retryintervalmax) {
4013             debug(DBG_ERR, "error in block %s, value of option RetryInterval is %d, must be 1-%d", block, retryinterval, conf->pdef->retryintervalmax);
4014             goto errexit;
4015         }
4016         conf->retryinterval = (uint8_t)retryinterval;
4017     } else
4018         conf->retryinterval = 255;
4019     
4020     if (retrycount != LONG_MIN) {
4021         if (retrycount < 0 || retrycount > conf->pdef->retrycountmax) {
4022             debug(DBG_ERR, "error in block %s, value of option RetryCount is %d, must be 0-%d", block, retrycount, conf->pdef->retrycountmax);
4023             goto errexit;
4024         }
4025         conf->retrycount = (uint8_t)retrycount;
4026     } else
4027         conf->retrycount = 255;
4028     
4029     if (resconf) {
4030         if (!mergesrvconf(resconf, conf))
4031             goto errexit;
4032         free(conf);
4033         conf = resconf;
4034         if (conf->dynamiclookupcommand) {
4035             free(conf->dynamiclookupcommand);
4036             conf->dynamiclookupcommand = NULL;
4037         }
4038     }
4039
4040     if (resconf || !conf->dynamiclookupcommand) {
4041         if (!compileserverconfig(conf, block))
4042             goto errexit;
4043     }
4044     
4045     if (resconf)
4046         return 1;
4047         
4048     if (!list_push(srvconfs, conf)) {
4049         debug(DBG_ERR, "malloc failed");
4050         goto errexit;
4051     }
4052     return 1;
4053
4054  errexit:    
4055     freeclsrvconf(conf);
4056     return 0;
4057 }
4058
4059 int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
4060     char **servers = NULL, **accservers = NULL, *msg = NULL;
4061     uint8_t accresp = 0;
4062     
4063     debug(DBG_DBG, "confrealm_cb called for %s", block);
4064     
4065     if (!getgenericconfig(cf, block,
4066                      "server", CONF_MSTR, &servers,
4067                      "accountingServer", CONF_MSTR, &accservers,
4068                      "ReplyMessage", CONF_STR, &msg,
4069                      "AccountingResponse", CONF_BLN, &accresp,
4070                      NULL
4071                           ))
4072         debugx(1, DBG_ERR, "configuration error");
4073
4074     addrealm(realms, val, servers, accservers, msg, accresp);
4075     return 1;
4076 }
4077
4078 int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
4079     struct tls *conf;
4080     
4081     debug(DBG_DBG, "conftls_cb called for %s", block);
4082     
4083     conf = malloc(sizeof(struct tls));
4084     if (!conf) {
4085         debug(DBG_ERR, "conftls_cb: malloc failed");
4086         return 0;
4087     }
4088     memset(conf, 0, sizeof(struct tls));
4089     
4090     if (!getgenericconfig(cf, block,
4091                      "CACertificateFile", CONF_STR, &conf->cacertfile,
4092                      "CACertificatePath", CONF_STR, &conf->cacertpath,
4093                      "CertificateFile", CONF_STR, &conf->certfile,
4094                      "CertificateKeyFile", CONF_STR, &conf->certkeyfile,
4095                      "CertificateKeyPassword", CONF_STR, &conf->certkeypwd,
4096                      "CRLCheck", CONF_BLN, &conf->crlcheck,
4097                      NULL
4098                           )) {
4099         debug(DBG_ERR, "conftls_cb: configuration error in block %s", val);
4100         goto errexit;
4101     }
4102     if (!conf->certfile || !conf->certkeyfile) {
4103         debug(DBG_ERR, "conftls_cb: TLSCertificateFile and TLSCertificateKeyFile must be specified in block %s", val);
4104         goto errexit;
4105     }
4106     if (!conf->cacertfile && !conf->cacertpath) {
4107         debug(DBG_ERR, "conftls_cb: CA Certificate file or path need to be specified in block %s", val);
4108         goto errexit;
4109     }
4110
4111     conf->name = stringcopy(val, 0);
4112     if (!conf->name) {
4113         debug(DBG_ERR, "conftls_cb: malloc failed");
4114         goto errexit;
4115     }
4116     
4117     pthread_mutex_lock(&tlsconfs_lock);
4118     if (!list_push(tlsconfs, conf)) {
4119         debug(DBG_ERR, "conftls_cb: malloc failed");
4120         pthread_mutex_unlock(&tlsconfs_lock);
4121         goto errexit;
4122     }
4123     pthread_mutex_unlock(&tlsconfs_lock);
4124             
4125     debug(DBG_DBG, "conftls_cb: added TLS block %s", val);
4126     return 1;
4127
4128  errexit:
4129     free(conf->cacertfile);
4130     free(conf->cacertpath);
4131     free(conf->certfile);
4132     free(conf->certkeyfile);
4133     free(conf->certkeypwd);
4134     free(conf);
4135     return 0;
4136 }
4137
4138 int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
4139     char **attrs = NULL, **vattrs = NULL;
4140     
4141     debug(DBG_DBG, "confrewrite_cb called for %s", block);
4142     
4143     if (!getgenericconfig(cf, block,
4144                      "removeAttribute", CONF_MSTR, &attrs,
4145                      "removeVendorAttribute", CONF_MSTR, &vattrs,
4146                      NULL
4147                           ))
4148         debugx(1, DBG_ERR, "configuration error");
4149     addrewrite(val, attrs, vattrs);
4150     return 1;
4151 }
4152
4153 void getmainconfig(const char *configfile) {
4154     long int loglevel = LONG_MIN;
4155     struct gconffile *cfs;
4156
4157     cfs = openconfigfile(configfile);
4158     memset(&options, 0, sizeof(options));
4159     
4160     clconfs = list_create();
4161     if (!clconfs)
4162         debugx(1, DBG_ERR, "malloc failed");
4163     
4164     srvconfs = list_create();
4165     if (!srvconfs)
4166         debugx(1, DBG_ERR, "malloc failed");
4167     
4168     realms = list_create();
4169     if (!realms)
4170         debugx(1, DBG_ERR, "malloc failed");    
4171  
4172     tlsconfs = list_create();
4173     if (!tlsconfs)
4174         debugx(1, DBG_ERR, "malloc failed");
4175     
4176     rewriteconfs = list_create();
4177     if (!rewriteconfs)
4178         debugx(1, DBG_ERR, "malloc failed");    
4179  
4180     if (!getgenericconfig(&cfs, NULL,
4181                           "ListenUDP", CONF_MSTR, &options.listenudp,
4182                           "ListenTCP", CONF_MSTR, &options.listentcp,
4183                           "ListenTLS", CONF_MSTR, &options.listentls,
4184                           "ListenAccountingUDP", CONF_MSTR, &options.listenaccudp,
4185                           "SourceUDP", CONF_STR, &options.sourceudp,
4186                           "SourceTCP", CONF_STR, &options.sourcetcp,
4187                           "SourceTLS", CONF_STR, &options.sourcetls,
4188                           "LogLevel", CONF_LINT, &loglevel,
4189                           "LogDestination", CONF_STR, &options.logdestination,
4190                           "LoopPrevention", CONF_BLN, &options.loopprevention,
4191                           "Client", CONF_CBK, confclient_cb, NULL,
4192                           "Server", CONF_CBK, confserver_cb, NULL,
4193                           "Realm", CONF_CBK, confrealm_cb, NULL,
4194                           "TLS", CONF_CBK, conftls_cb, NULL,
4195                           "Rewrite", CONF_CBK, confrewrite_cb, NULL,
4196                           NULL
4197                           ))
4198         debugx(1, DBG_ERR, "configuration error");
4199     
4200     if (loglevel != LONG_MIN) {
4201         if (loglevel < 1 || loglevel > 4)
4202             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %d, must be 1, 2, 3 or 4", configfile, loglevel);
4203         options.loglevel = (uint8_t)loglevel;
4204     }
4205 }
4206
4207 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile) {
4208     int c;
4209
4210     while ((c = getopt(argc, argv, "c:d:fpv")) != -1) {
4211         switch (c) {
4212         case 'c':
4213             *configfile = optarg;
4214             break;
4215         case 'd':
4216             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
4217                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
4218             *loglevel = *optarg - '0';
4219             break;
4220         case 'f':
4221             *foreground = 1;
4222             break;
4223         case 'p':
4224             *pretend = 1;
4225             break;
4226         case 'v':
4227                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
4228         default:
4229             goto usage;
4230         }
4231     }
4232     if (!(argc - optind))
4233         return;
4234
4235  usage:
4236     debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -p ] [ -v ]", argv[0]);
4237 }
4238
4239 #ifdef SYS_SOLARIS9
4240 int daemon(int a, int b) {
4241     int i;
4242
4243     if (fork())
4244         exit(0);
4245
4246     setsid();
4247
4248     for (i = 0; i < 3; i++) {
4249         close(i);
4250         open("/dev/null", O_RDWR);
4251     }
4252     return 1;
4253 }
4254 #endif
4255
4256 void *sighandler(void *arg) {
4257     sigset_t sigset;
4258     int sig;
4259
4260     for(;;) {
4261         sigemptyset(&sigset);
4262         sigaddset(&sigset, SIGPIPE);
4263         sigwait(&sigset, &sig);
4264         /* only get SIGPIPE right now, so could simplify below code */
4265         switch (sig) {
4266         case 0:
4267             /* completely ignoring this */
4268             break;
4269         case SIGPIPE:
4270             debug(DBG_WARN, "sighandler: got SIGPIPE, TLS write error?");
4271             break;
4272         default:
4273             debug(DBG_WARN, "sighandler: ignoring signal %d", sig);
4274         }
4275     }
4276 }
4277
4278 int main(int argc, char **argv) {
4279     pthread_t sigth, udpclient4rdth, udpclient6rdth, udpserverwrth;
4280     sigset_t sigset;
4281     struct list_node *entry;
4282     uint8_t foreground = 0, pretend = 0, loglevel = 0;
4283     char *configfile = NULL;
4284     struct clsrvconf *srvconf;
4285     
4286     debug_init("radsecproxy");
4287     debug_set_level(DEBUG_LEVEL);
4288     pthread_mutex_init(&tlsconfs_lock, NULL);
4289     
4290     getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile);
4291     if (loglevel)
4292         debug_set_level(loglevel);
4293     getmainconfig(configfile ? configfile : CONFIG_MAIN);
4294     if (loglevel)
4295         options.loglevel = loglevel;
4296     else if (options.loglevel)
4297         debug_set_level(options.loglevel);
4298     if (!foreground)
4299         debug_set_destination(options.logdestination ? options.logdestination : "x-syslog:///");
4300     free(options.logdestination);
4301
4302     if (!list_first(clconfs))
4303         debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
4304     if (!list_first(srvconfs))
4305         debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
4306     if (!list_first(realms))
4307         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
4308
4309     if (pretend)
4310         debugx(0, DBG_ERR, "All OK so far; exiting since only pretending");
4311
4312     if (!foreground && (daemon(0, 0) < 0))
4313         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
4314     
4315     debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
4316
4317     sigemptyset(&sigset);
4318     /* exit on all but SIGPIPE, ignore more? */
4319     sigaddset(&sigset, SIGPIPE);
4320     pthread_sigmask(SIG_BLOCK, &sigset, NULL);
4321     pthread_create(&sigth, NULL, sighandler, NULL);
4322
4323     if (find_conf_type(RAD_UDP, clconfs, NULL) || find_conf_type(RAD_DTLS, clconfs, NULL)) {
4324         udp_server_replyq = newreplyq();
4325         if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
4326             debugx(1, DBG_ERR, "pthread_create failed");
4327         createlisteners(RAD_UDP, options.listenudp);
4328         if (options.listenaccudp)
4329             createlisteners(RAD_UDP, options.listenaccudp);
4330     }
4331     
4332     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
4333         srvconf = (struct clsrvconf *)entry->data;
4334         if (srvconf->dynamiclookupcommand)
4335             continue;
4336         if (!addserver(srvconf))
4337             debugx(1, DBG_ERR, "failed to add server");
4338         if (pthread_create(&srvconf->servers->clientth, NULL, clientwr,
4339                            (void *)(srvconf->servers)))
4340             debugx(1, DBG_ERR, "pthread_create failed");
4341     }
4342     /* srcprotores for UDP no longer needed */
4343     if (srcprotores[RAD_UDP]) {
4344         freeaddrinfo(srcprotores[RAD_UDP]);
4345         srcprotores[RAD_UDP] = NULL;
4346     }
4347     if (udp_client4_sock >= 0)
4348         if (pthread_create(&udpclient4rdth, NULL, protodefs[RAD_UDP].clientreader, (void *)&udp_client4_sock))
4349             debugx(1, DBG_ERR, "pthread_create failed");
4350     if (udp_client6_sock >= 0)
4351         if (pthread_create(&udpclient6rdth, NULL, protodefs[RAD_UDP].clientreader, (void *)&udp_client6_sock))
4352             debugx(1, DBG_ERR, "pthread_create failed");
4353     
4354     if (find_conf_type(RAD_TCP, clconfs, NULL))
4355         createlisteners(RAD_TCP, options.listentcp);
4356     
4357     if (find_conf_type(RAD_TLS, clconfs, NULL))
4358         createlisteners(RAD_TLS, options.listentls);
4359     
4360     /* just hang around doing nothing, anything to do here? */
4361     for (;;)
4362         sleep(1000);
4363 }