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