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