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