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