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