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