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