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