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