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