37a4ff64772387e1d790e4d30d9fdb7b1a346489
[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 <ctype.h>
44 #include <sys/wait.h>
45 #include <arpa/inet.h>
46 #include <regex.h>
47 #include <libgen.h>
48 #include <pthread.h>
49 #include <openssl/ssl.h>
50 #include <openssl/rand.h>
51 #include <openssl/err.h>
52 #include <openssl/md5.h>
53 #include <openssl/hmac.h>
54 #include <openssl/x509v3.h>
55 #include "debug.h"
56 #include "list.h"
57 #include "util.h"
58 #include "gconfig.h"
59 #include "radsecproxy.h"
60
61 static struct options options;
62 struct list *clconfs, *srvconfs, *realms, *tlsconfs, *rewriteconfs;
63
64 static int client_udp_count = 0;
65 static int client_tls_count = 0;
66 static int server_udp_count = 0;
67 static int server_tls_count = 0;
68
69 static struct addrinfo *srcudpres = NULL;
70 static struct addrinfo *srctcpres = NULL;
71
72 static struct replyq *udp_server_replyq = NULL;
73 static int udp_server_sock = -1;
74 static int udp_accserver_sock = -1;
75 static int udp_client4_sock = -1;
76 static int udp_client6_sock = -1;
77 static pthread_mutex_t *ssl_locks;
78 static long *ssl_lock_count;
79 extern int optind;
80 extern char *optarg;
81
82 /* minimum required declarations to avoid reordering code */
83 void adddynamicrealmserver(struct realm *realm, struct clsrvconf *conf, char *id);
84 void dynamicconfig(struct server *server);
85 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val);
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 (options.rpf && !strcmp(rq->from->conf->name, to->conf->name)) {
1935         debug(DBG_INFO, "radsrv: RPF failed, not forwarding request from client %s to server %s, discarding",
1936               rq->from->conf->name, to->conf->name);
1937         goto exit;
1938     }
1939
1940     if (rqinqueue(to, rq->from, id, code)) {
1941         debug(DBG_INFO, "radsrv: already got %s from host %s with id %d, ignoring",
1942               radmsgtype2string(code), rq->from->conf->host, id);
1943         goto exit;
1944     }
1945
1946     if (!RAND_bytes(newauth, 16)) {
1947         debug(DBG_WARN, "radsrv: failed to generate random auth");
1948         goto exit;
1949     }
1950
1951 #ifdef DEBUG
1952     printfchars(NULL, "auth", "%02x ", auth, 16);
1953 #endif
1954
1955     attr = attrget(attrs, len, RAD_Attr_User_Password);
1956     if (attr) {
1957         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1958         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth))
1959             goto exit;
1960     }
1961     
1962     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1963     if (attr) {
1964         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1965         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth))
1966             goto exit;
1967     }
1968
1969     rq->origid = id;
1970     memcpy(rq->origauth, auth, 16);
1971     memcpy(auth, newauth, 16);
1972     sendrq(to, rq);
1973     return;
1974     
1975  exit:
1976     freerqdata(rq);
1977 }
1978
1979 int replyh(struct server *server, unsigned char *buf) {
1980     struct client *from;
1981     struct request *rq;
1982     int i, len, sublen;
1983     unsigned char *messageauth, *subattrs, *attrs, *attr, *username;
1984     struct sockaddr_storage fromsa;
1985     char tmp[256];
1986     
1987     server->connectionok = 1;
1988     server->loststatsrv = 0;
1989         
1990     i = buf[1]; /* i is the id */
1991
1992     if (*buf != RAD_Access_Accept && *buf != RAD_Access_Reject && *buf != RAD_Access_Challenge
1993         && *buf != RAD_Accounting_Response) {
1994         debug(DBG_INFO, "replyh: discarding message type %s, accepting only access accept, access reject, access challenge and accounting response messages", radmsgtype2string(*buf));
1995         return 0;
1996     }
1997     debug(DBG_DBG, "got %s message with id %d", radmsgtype2string(*buf), i);
1998
1999     rq = server->requests + i;
2000
2001     pthread_mutex_lock(&server->newrq_mutex);
2002     if (!rq->buf || !rq->tries) {
2003         pthread_mutex_unlock(&server->newrq_mutex);
2004         debug(DBG_INFO, "replyh: no matching request sent with this id, ignoring reply");
2005         return 0;
2006     }
2007
2008     if (rq->received) {
2009         pthread_mutex_unlock(&server->newrq_mutex);
2010         debug(DBG_INFO, "replyh: already received, ignoring reply");
2011         return 0;
2012     }
2013         
2014     if (!validauth(buf, rq->buf + 4, (unsigned char *)server->conf->secret)) {
2015         pthread_mutex_unlock(&server->newrq_mutex);
2016         debug(DBG_WARN, "replyh: invalid auth, ignoring reply");
2017         return 0;
2018     }
2019         
2020     len = RADLEN(buf) - 20;
2021     attrs = buf + 20;
2022
2023     if (!attrvalidate(attrs, len)) {
2024         pthread_mutex_unlock(&server->newrq_mutex);
2025         debug(DBG_WARN, "replyh: attribute validation failed, ignoring reply");
2026         return 0;
2027     }
2028         
2029     /* Message Authenticator */
2030     messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
2031     if (messageauth) {
2032         if (ATTRVALLEN(messageauth) != 16) {
2033             pthread_mutex_unlock(&server->newrq_mutex);
2034             debug(DBG_WARN, "replyh: illegal message auth attribute length, ignoring reply");
2035             return 0;
2036         }
2037         memcpy(tmp, buf + 4, 16);
2038         memcpy(buf + 4, rq->buf + 4, 16);
2039         if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
2040             pthread_mutex_unlock(&server->newrq_mutex);
2041             debug(DBG_WARN, "replyh: message authentication failed, ignoring reply");
2042             return 0;
2043         }
2044         memcpy(buf + 4, tmp, 16);
2045         debug(DBG_DBG, "replyh: message auth ok");
2046     }
2047         
2048     if (*rq->buf == RAD_Status_Server) {
2049         rq->received = 1;
2050         pthread_mutex_unlock(&server->newrq_mutex);
2051         debug(DBG_DBG, "replyh: got status server response from %s", server->conf->host);
2052         return 0;
2053     }
2054
2055     from = rq->from;
2056     if (!from) {
2057         pthread_mutex_unlock(&server->newrq_mutex);
2058         debug(DBG_INFO, "replyh: client gone, ignoring reply");
2059         return 0;
2060     }
2061         
2062     if (server->conf->rewrite) {
2063         dorewrite(buf, server->conf->rewrite);
2064         len = RADLEN(buf) - 20;
2065     }
2066     
2067     /* MS MPPE */
2068     for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
2069         if (ATTRVALLEN(attr) <= 4)
2070             break;
2071             
2072         if (attr[2] != 0 || attr[3] != 0 || attr[4] != 1 || attr[5] != 55)  /* 311 == MS */
2073             continue;
2074             
2075         sublen = ATTRVALLEN(attr) - 4;
2076         subattrs = ATTRVAL(attr) + 4;  
2077         if (!attrvalidate(subattrs, sublen) ||
2078             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
2079                     rq, server->conf->secret, from->conf->secret) ||
2080             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
2081                     rq, server->conf->secret, from->conf->secret))
2082             break;
2083     }
2084     if (attr) {
2085         pthread_mutex_unlock(&server->newrq_mutex);
2086         debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
2087         return 0;
2088     }
2089         
2090     if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject || *buf == RAD_Accounting_Response) {
2091         attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_User_Name);
2092         if (attr) {
2093             memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
2094             tmp[ATTRVALLEN(attr)] = '\0';
2095             if (rq->origusername)
2096                 debug(DBG_INFO, "%s for %s (originally %s) from %s", radmsgtype2string(*buf), tmp,
2097                       rq->origusername, server->conf->host);
2098             else
2099                 debug(DBG_INFO, "%s for %s from %s", radmsgtype2string(*buf), tmp, server->conf->host);
2100         }
2101     }
2102         
2103     buf[1] = (char)rq->origid;
2104     memcpy(buf + 4, rq->origauth, 16);
2105 #ifdef DEBUG    
2106     printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
2107 #endif
2108
2109     if (rq->origusername) {
2110         username = resizeattr(&buf, strlen(rq->origusername), RAD_Attr_User_Name);
2111         if (!username) {
2112             pthread_mutex_unlock(&server->newrq_mutex);
2113             debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
2114             return 0;
2115         }
2116         memcpy(username, rq->origusername, strlen(rq->origusername));
2117         len = RADLEN(buf) - 20;
2118         attrs = buf + 20;
2119         if (messageauth)
2120             messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
2121     }
2122         
2123     if (messageauth) {
2124         if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
2125             pthread_mutex_unlock(&server->newrq_mutex);
2126             debug(DBG_WARN, "replyh: failed to create authenticator, malloc failed?, ignoring reply");
2127             return 0;
2128         }
2129         debug(DBG_DBG, "replyh: computed messageauthattr");
2130     }
2131
2132     if (from->conf->type == 'U')
2133         fromsa = rq->fromsa;
2134     /* once we set received = 1, rq may be reused */
2135     rq->received = 1;
2136
2137     debug(DBG_INFO, "replyh: passing reply to client %s", from->conf->name);
2138     sendreply(from, buf, from->conf->type == 'U' ? &fromsa : NULL);
2139     pthread_mutex_unlock(&server->newrq_mutex);
2140     return 1;
2141 }
2142
2143 void *udpclientrd(void *arg) {
2144     struct server *server;
2145     unsigned char *buf;
2146     int *s = (int *)arg;
2147     
2148     for (;;) {
2149         server = NULL;
2150         buf = radudpget(*s, NULL, &server, NULL);
2151         if (!replyh(server, buf))
2152             free(buf);
2153     }
2154 }
2155
2156 void *tlsclientrd(void *arg) {
2157     struct server *server = (struct server *)arg;
2158     unsigned char *buf;
2159     struct timeval lastconnecttry;
2160     
2161     for (;;) {
2162         /* yes, lastconnecttry is really necessary */
2163         lastconnecttry = server->lastconnecttry;
2164         buf = radtlsget(server->ssl);
2165         if (!buf) {
2166             tlsconnect(server, &lastconnecttry, "clientrd");
2167             continue;
2168         }
2169
2170         if (!replyh(server, buf))
2171             free(buf);
2172     }
2173 }
2174
2175 /* code for removing state not finished */
2176 void *clientwr(void *arg) {
2177     struct server *server = (struct server *)arg;
2178     struct request *rq;
2179     pthread_t tlsclientrdth;
2180     int i;
2181     uint8_t rnd;
2182     struct timeval now, lastsend;
2183     struct timespec timeout;
2184     struct request statsrvrq;
2185     unsigned char statsrvbuf[38];
2186     struct clsrvconf *conf;
2187
2188     conf = server->conf;
2189     
2190     if (server->dynamiclookuparg) {
2191         dynamicconfig(server);
2192         conf = server->conf;
2193         if (!conf)
2194             goto errexit;
2195     }
2196
2197     if (!conf->addrinfo && !resolvepeer(conf, 0)) {
2198         debug(DBG_WARN, "failed to resolve host %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
2199         goto errexit;
2200     }
2201
2202     memset(&timeout, 0, sizeof(struct timespec));
2203     
2204     if (conf->statusserver) {
2205         memset(&statsrvrq, 0, sizeof(struct request));
2206         memset(statsrvbuf, 0, sizeof(statsrvbuf));
2207         statsrvbuf[0] = RAD_Status_Server;
2208         statsrvbuf[3] = 38;
2209         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
2210         statsrvbuf[21] = 18;
2211         gettimeofday(&lastsend, NULL);
2212     }
2213     
2214     if (conf->type == 'U') {
2215         server->connectionok = 1;
2216     } else {
2217         tlsconnect(server, NULL, "new client");
2218         server->connectionok = 1;
2219         if (pthread_create(&tlsclientrdth, NULL, tlsclientrd, (void *)server)) {
2220             debug(DBG_ERR, "clientwr: pthread_create failed");
2221             goto errexit;
2222         }
2223     }
2224     
2225     for (;;) {
2226         pthread_mutex_lock(&server->newrq_mutex);
2227         if (!server->newrq) {
2228             gettimeofday(&now, NULL);
2229             if (conf->statusserver) {
2230                 /* random 0-7 seconds */
2231                 RAND_bytes(&rnd, 1);
2232                 rnd /= 32;
2233                 if (!timeout.tv_sec || timeout.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
2234                     timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
2235             }   
2236             if (timeout.tv_sec) {
2237                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
2238                 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
2239                 timeout.tv_sec = 0;
2240             } else {
2241                 debug(DBG_DBG, "clientwr: waiting for new request");
2242                 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
2243             }
2244         }
2245         if (server->newrq) {
2246             debug(DBG_DBG, "clientwr: got new request");
2247             server->newrq = 0;
2248         } else
2249             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
2250         pthread_mutex_unlock(&server->newrq_mutex);
2251
2252         for (i = 0; i < MAX_REQUESTS; i++) {
2253             pthread_mutex_lock(&server->newrq_mutex);
2254             while (i < MAX_REQUESTS && !server->requests[i].buf)
2255                 i++;
2256             if (i == MAX_REQUESTS) {
2257                 pthread_mutex_unlock(&server->newrq_mutex);
2258                 break;
2259             }
2260             rq = server->requests + i;
2261
2262             if (rq->received) {
2263                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
2264                 if (rq->buf) {
2265                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
2266                     freerqdata(rq);
2267                     /* setting this to NULL means that it can be reused */
2268                     rq->buf = NULL;
2269                 }
2270                 pthread_mutex_unlock(&server->newrq_mutex);
2271                 continue;
2272             }
2273             
2274             gettimeofday(&now, NULL);
2275             if (now.tv_sec < rq->expiry.tv_sec) {
2276                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
2277                     timeout.tv_sec = rq->expiry.tv_sec;
2278                 pthread_mutex_unlock(&server->newrq_mutex);
2279                 continue;
2280             }
2281
2282             if (rq->tries == (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
2283                               ? 1 : REQUEST_RETRIES)) {
2284                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
2285                 if (*rq->buf == RAD_Status_Server) {
2286                     debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->host);
2287                     if (server->loststatsrv < 255)
2288                         server->loststatsrv++;
2289                 }
2290                 freerqdata(rq);
2291                 /* setting this to NULL means that it can be reused */
2292                 rq->buf = NULL;
2293                 pthread_mutex_unlock(&server->newrq_mutex);
2294                 continue;
2295             }
2296             pthread_mutex_unlock(&server->newrq_mutex);
2297
2298             rq->expiry.tv_sec = now.tv_sec +
2299                 (*rq->buf == RAD_Status_Server || conf->type == 'T'
2300                  ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
2301             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
2302                 timeout.tv_sec = rq->expiry.tv_sec;
2303             rq->tries++;
2304             clientradput(server, server->requests[i].buf);
2305             gettimeofday(&lastsend, NULL);
2306         }
2307         if (conf->statusserver) {
2308             gettimeofday(&now, NULL);
2309             if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
2310                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
2311                     debug(DBG_WARN, "clientwr: failed to generate random auth");
2312                     continue;
2313                 }
2314                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
2315                 if (!statsrvrq.buf) {
2316                     debug(DBG_ERR, "clientwr: malloc failed");
2317                     continue;
2318                 }
2319                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
2320                 debug(DBG_DBG, "clientwr: sending status server to %s", conf->host);
2321                 lastsend.tv_sec = now.tv_sec;
2322                 sendrq(server, &statsrvrq);
2323             }
2324         }
2325     }
2326  errexit:
2327     /* this code needs more work */
2328     if (server->dynamiclookuparg) {
2329         /* remove subrealms using this server */
2330         /* need to free server->conf etc */
2331         if (conf) {
2332             free(conf->host);
2333             free(conf->name);
2334             if (conf->addrinfo) {
2335                 freeaddrinfo(conf->addrinfo);
2336                 conf->addrinfo = NULL;
2337             }
2338             /* add this once realm removal in place
2339             free(conf);
2340             server->conf = NULL;
2341             */
2342         }
2343     }
2344     freeserver(server, 1);
2345     return NULL;
2346 }
2347
2348 void *udpserverwr(void *arg) {
2349     struct replyq *replyq = udp_server_replyq;
2350     struct reply *reply;
2351     
2352     for (;;) {
2353         pthread_mutex_lock(&replyq->mutex);
2354         while (!(reply = (struct reply *)list_shift(replyq->replies))) {
2355             debug(DBG_DBG, "udp server writer, waiting for signal");
2356             pthread_cond_wait(&replyq->cond, &replyq->mutex);
2357             debug(DBG_DBG, "udp server writer, got signal");
2358         }
2359         pthread_mutex_unlock(&replyq->mutex);
2360
2361         if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
2362                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
2363             debug(DBG_WARN, "sendudp: send failed");
2364         free(reply->buf);
2365         free(reply);
2366     }
2367 }
2368
2369 void *udpserverrd(void *arg) {
2370     struct request rq;
2371     pthread_t udpserverwrth;
2372     struct clsrvconf *listenres;
2373
2374     listenres = resolve_hostport('U', options.listenudp, DEFAULT_UDP_PORT);
2375     if ((udp_server_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2376         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2377
2378     debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
2379           listenres->host ? listenres->host : "*", listenres->port);
2380     freeclsrvres(listenres);
2381     
2382     if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
2383         debugx(1, DBG_ERR, "pthread_create failed");
2384     
2385     for (;;) {
2386         memset(&rq, 0, sizeof(struct request));
2387         rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
2388         radsrv(&rq);
2389     }
2390 }
2391
2392 void *udpaccserverrd(void *arg) {
2393     struct request rq;
2394     struct clsrvconf *listenres;
2395     
2396     listenres = resolve_hostport('U', options.listenaccudp, DEFAULT_UDP_PORT);
2397     if ((udp_accserver_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2398         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2399
2400     debug(DBG_WARN, "udpaccserverrd: listening for UDP on %s:%s",
2401           listenres->host ? listenres->host : "*", listenres->port);
2402     freeclsrvres(listenres);
2403     
2404     for (;;) {
2405         memset(&rq, 0, sizeof(struct request));
2406         rq.buf = radudpget(udp_accserver_sock, &rq.from, NULL, &rq.fromsa);
2407         if (*(uint8_t *)rq.buf == RAD_Accounting_Request) {
2408             radsrv(&rq);
2409             continue;
2410         }
2411         debug(DBG_INFO, "udpaccserverrd: got something other than accounting-request, ignoring");
2412         freerqdata(&rq);
2413     }
2414 }
2415
2416 void *tlsserverwr(void *arg) {
2417     int cnt;
2418     unsigned long error;
2419     struct client *client = (struct client *)arg;
2420     struct replyq *replyq;
2421     struct reply *reply;
2422     
2423     debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
2424     replyq = client->replyq;
2425     for (;;) {
2426         pthread_mutex_lock(&replyq->mutex);
2427         while (!list_first(replyq->replies)) {
2428             if (client->ssl) {      
2429                 debug(DBG_DBG, "tls server writer, waiting for signal");
2430                 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2431                 debug(DBG_DBG, "tls server writer, got signal");
2432             }
2433             if (!client->ssl) {
2434                 /* ssl might have changed while waiting */
2435                 pthread_mutex_unlock(&replyq->mutex);
2436                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
2437                 pthread_exit(NULL);
2438             }
2439         }
2440         reply = (struct reply *)list_shift(replyq->replies);
2441         pthread_mutex_unlock(&replyq->mutex);
2442         cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
2443         if (cnt > 0)
2444             debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
2445                   cnt, RADLEN(reply->buf));
2446         else
2447             while ((error = ERR_get_error()))
2448                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
2449         free(reply->buf);
2450         free(reply);
2451     }
2452 }
2453
2454 void tlsserverrd(struct client *client) {
2455     struct request rq;
2456     pthread_t tlsserverwrth;
2457     
2458     debug(DBG_DBG, "tlsserverrd starting for %s", client->conf->host);
2459     
2460     if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
2461         debug(DBG_ERR, "tlsserverrd: pthread_create failed");
2462         return;
2463     }
2464
2465     for (;;) {
2466         memset(&rq, 0, sizeof(struct request));
2467         rq.buf = radtlsget(client->ssl);
2468         if (!rq.buf)
2469             break;
2470         debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
2471         rq.from = client;
2472         radsrv(&rq);
2473     }
2474     
2475     debug(DBG_ERR, "tlsserverrd: connection lost");
2476     /* stop writer by setting ssl to NULL and give signal in case waiting for data */
2477     client->ssl = NULL;
2478     pthread_mutex_lock(&client->replyq->mutex);
2479     pthread_cond_signal(&client->replyq->cond);
2480     pthread_mutex_unlock(&client->replyq->mutex);
2481     debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
2482     pthread_join(tlsserverwrth, NULL);
2483     removeclientrqs(client);
2484     debug(DBG_DBG, "tlsserverrd for %s exiting", client->conf->host);
2485 }
2486
2487 void *tlsservernew(void *arg) {
2488     int s;
2489     struct sockaddr_storage from;
2490     size_t fromlen = sizeof(from);
2491     struct clsrvconf *conf;
2492     struct list_node *cur = NULL;
2493     SSL *ssl = NULL;
2494     X509 *cert = NULL;
2495     unsigned long error;
2496     struct client *client;
2497
2498     s = *(int *)arg;
2499     if (getpeername(s, (struct sockaddr *)&from, &fromlen)) {
2500         debug(DBG_DBG, "tlsserverrd: getpeername failed, exiting");
2501         goto exit;
2502     }
2503     debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
2504
2505     conf = find_conf('T', (struct sockaddr *)&from, clconfs, &cur);
2506     if (conf) {
2507         ssl = SSL_new(conf->ssl_ctx);
2508         SSL_set_fd(ssl, s);
2509
2510         if (SSL_accept(ssl) <= 0) {
2511             while ((error = ERR_get_error()))
2512                 debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
2513             debug(DBG_ERR, "SSL_accept failed");
2514             goto exit;
2515         }
2516         cert = verifytlscert(ssl);
2517         if (!cert)
2518             goto exit;
2519     }
2520     
2521     while (conf) {
2522         if (verifyconfcert(cert, conf)) {
2523             X509_free(cert);
2524             client = addclient(conf);
2525             if (client) {
2526                 client->ssl = ssl;
2527                 tlsserverrd(client);
2528                 removeclient(client);
2529             } else
2530                 debug(DBG_WARN, "Failed to create new client instance");
2531             goto exit;
2532         }
2533         conf = find_conf('T', (struct sockaddr *)&from, clconfs, &cur);
2534     }
2535     debug(DBG_WARN, "ignoring request, no matching TLS client");
2536     if (cert)
2537         X509_free(cert);
2538
2539  exit:
2540     SSL_free(ssl);
2541     shutdown(s, SHUT_RDWR);
2542     close(s);
2543     pthread_exit(NULL);
2544 }
2545
2546 int tlslistener() {
2547     pthread_t tlsserverth;
2548     int s, snew;
2549     struct sockaddr_storage from;
2550     size_t fromlen = sizeof(from);
2551     struct clsrvconf *listenres;
2552
2553     listenres = resolve_hostport('T', options.listentcp, DEFAULT_TLS_PORT);
2554     if ((s = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2555         debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
2556
2557     debug(DBG_WARN, "listening for incoming TCP on %s:%s", listenres->host ? listenres->host : "*", listenres->port);
2558     freeclsrvres(listenres);
2559     listen(s, 0);
2560
2561     for (;;) {
2562         snew = accept(s, (struct sockaddr *)&from, &fromlen);
2563         if (snew < 0) {
2564             debug(DBG_WARN, "accept failed");
2565             continue;
2566         }
2567         if (pthread_create(&tlsserverth, NULL, tlsservernew, (void *)&snew)) {
2568             debug(DBG_ERR, "tlslistener: pthread_create failed");
2569             shutdown(snew, SHUT_RDWR);
2570             close(snew);
2571             continue;
2572         }
2573         pthread_detach(tlsserverth);
2574     }
2575     return 0;
2576 }
2577
2578 void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, char *certkeyfile, char *certkeypwd) {
2579     struct tls *new;
2580     SSL_CTX *ctx;
2581     STACK_OF(X509_NAME) *calist;
2582     int i;
2583     unsigned long error;
2584     
2585     if (!certfile || !certkeyfile)
2586         debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified in TLS context %s", value);
2587
2588     if (!cacertfile && !cacertpath)
2589         debugx(1, DBG_ERR, "CA Certificate file or path need to be specified in TLS context %s", value);
2590
2591     if (!ssl_locks) {
2592         ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
2593         ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
2594         for (i = 0; i < CRYPTO_num_locks(); i++) {
2595             ssl_lock_count[i] = 0;
2596             pthread_mutex_init(&ssl_locks[i], NULL);
2597         }
2598         CRYPTO_set_id_callback(ssl_thread_id);
2599         CRYPTO_set_locking_callback(ssl_locking_callback);
2600
2601         SSL_load_error_strings();
2602         SSL_library_init();
2603
2604         while (!RAND_status()) {
2605             time_t t = time(NULL);
2606             pid_t pid = getpid();
2607             RAND_seed((unsigned char *)&t, sizeof(time_t));
2608             RAND_seed((unsigned char *)&pid, sizeof(pid));
2609         }
2610     }
2611     ctx = SSL_CTX_new(TLSv1_method());
2612     if (certkeypwd) {
2613         SSL_CTX_set_default_passwd_cb_userdata(ctx, certkeypwd);
2614         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
2615     }
2616     if (!SSL_CTX_use_certificate_chain_file(ctx, certfile) ||
2617         !SSL_CTX_use_PrivateKey_file(ctx, certkeyfile, SSL_FILETYPE_PEM) ||
2618         !SSL_CTX_check_private_key(ctx) ||
2619         !SSL_CTX_load_verify_locations(ctx, cacertfile, cacertpath)) {
2620         while ((error = ERR_get_error()))
2621             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2622         debugx(1, DBG_ERR, "Error initialising SSL/TLS in TLS context %s", value);
2623     }
2624
2625     calist = cacertfile ? SSL_load_client_CA_file(cacertfile) : NULL;
2626     if (!cacertfile || calist) {
2627         if (cacertpath) {
2628             if (!calist)
2629                 calist = sk_X509_NAME_new_null();
2630             if (!SSL_add_dir_cert_subjects_to_stack(calist, cacertpath)) {
2631                 sk_X509_NAME_free(calist);
2632                 calist = NULL;
2633             }
2634         }
2635     }
2636     if (!calist) {
2637         while ((error = ERR_get_error()))
2638             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2639         debugx(1, DBG_ERR, "Error adding CA subjects in TLS context %s", value);
2640     }
2641     SSL_CTX_set_client_CA_list(ctx, calist);
2642     
2643     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
2644     SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
2645
2646     new = malloc(sizeof(struct tls));
2647     if (!new || !list_push(tlsconfs, new))
2648         debugx(1, DBG_ERR, "malloc failed");
2649
2650     memset(new, 0, sizeof(struct tls));
2651     new->name = stringcopy(value, 0);
2652     if (!new->name)
2653         debugx(1, DBG_ERR, "malloc failed");
2654     new->ctx = ctx;
2655     debug(DBG_DBG, "tlsadd: added TLS context %s", value);
2656 }
2657
2658 SSL_CTX *tlsgetctx(char *alt1, char *alt2) {
2659     struct list_node *entry;
2660     struct tls *t, *t1 = NULL, *t2 = NULL;
2661     
2662     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2663         t = (struct tls *)entry->data;
2664         if (!strcasecmp(t->name, alt1)) {
2665             t1 = t;
2666             break;
2667         }
2668         if (!t2 && alt2 && !strcasecmp(t->name, alt2))
2669             t2 = t;
2670     }
2671
2672     t = (t1 ? t1 : t2);
2673     if (!t)
2674         return NULL;
2675     return t->ctx;
2676 }
2677
2678 struct list *addsrvconfs(char *value, char **names) {
2679     struct list *conflist;
2680     int n;
2681     struct list_node *entry;
2682     struct clsrvconf *conf;
2683     
2684     if (!names || !*names)
2685         return NULL;
2686     
2687     conflist = list_create();
2688     if (!conflist) {
2689         debug(DBG_ERR, "malloc failed");
2690         return NULL;
2691     }
2692
2693     for (n = 0; names[n]; n++) {
2694         for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2695             conf = (struct clsrvconf *)entry->data;
2696             if (!strcasecmp(names[n], conf->name))
2697                 break;
2698         }
2699         if (!entry) {
2700             debug(DBG_ERR, "addsrvconfs failed for realm %s, no server named %s", value, names[n]);
2701             list_destroy(conflist);
2702             return NULL;
2703         }
2704         if (!list_push(conflist, conf)) {
2705             debug(DBG_ERR, "malloc failed");
2706             list_destroy(conflist);
2707             return NULL;
2708         }
2709         debug(DBG_DBG, "addsrvconfs: added server %s for realm %s", conf->name, value);
2710     }
2711     return conflist;
2712 }
2713
2714 void freerealm(struct realm *realm) {
2715     if (!realm)
2716         return;
2717     free(realm->name);
2718     if (realm->srvconfs) {
2719         /* emptying list without freeing data */
2720         while (list_shift(realm->srvconfs));
2721         list_destroy(realm->srvconfs);
2722     }
2723     if (realm->accsrvconfs) {
2724         /* emptying list without freeing data */
2725         while (list_shift(realm->accsrvconfs));
2726         list_destroy(realm->accsrvconfs);
2727     }
2728     free(realm);
2729 }
2730
2731 struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message) {
2732     int n;
2733     struct realm *realm;
2734     char *s, *regex = NULL;
2735     
2736     if (*value == '/') {
2737         /* regexp, remove optional trailing / if present */
2738         if (value[strlen(value) - 1] == '/')
2739             value[strlen(value) - 1] = '\0';
2740     } else {
2741         /* not a regexp, let us make it one */
2742         if (*value == '*' && !value[1])
2743             regex = stringcopy(".*", 0);
2744         else {
2745             for (n = 0, s = value; *s;)
2746                 if (*s++ == '.')
2747                     n++;
2748             regex = malloc(strlen(value) + n + 3);
2749             if (regex) {
2750                 regex[0] = '@';
2751                 for (n = 1, s = value; *s; s++) {
2752                     if (*s == '.')
2753                         regex[n++] = '\\';
2754                     regex[n++] = *s;
2755                 }
2756                 regex[n++] = '$';
2757                 regex[n] = '\0';
2758             }
2759         }
2760         if (!regex) {
2761             debug(DBG_ERR, "malloc failed");
2762             goto exit;
2763         }
2764         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
2765     }
2766
2767     realm = malloc(sizeof(struct realm));
2768     if (!realm) {
2769         debug(DBG_ERR, "malloc failed");
2770         goto exit;
2771     }
2772     memset(realm, 0, sizeof(struct realm));
2773     realm->name = stringcopy(value, 0);
2774     if (!realm->name) {
2775         debug(DBG_ERR, "malloc failed");
2776         goto errexit;
2777     }
2778     if (message && strlen(message) > 253) {
2779         debug(DBG_ERR, "ReplyMessage can be at most 253 bytes");
2780         goto errexit;
2781     }
2782     realm->message = message;
2783     
2784     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB)) {
2785         debug(DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
2786         goto errexit;
2787     }
2788     
2789     if (servers && *servers) {
2790         realm->srvconfs = addsrvconfs(value, servers);
2791         if (!realm->srvconfs)
2792             goto errexit;
2793     }
2794     
2795     if (accservers && *accservers) {
2796         realm->accsrvconfs = addsrvconfs(value, accservers);
2797         if (!realm->accsrvconfs)
2798             goto errexit;
2799     }
2800
2801     if (pthread_mutex_init(&realm->subrealms_mutex, NULL)) {
2802         debug(DBG_ERR, "mutex init failed");
2803         goto errexit;
2804     }
2805
2806     if (!list_push(realmlist, realm)) {
2807         debug(DBG_ERR, "malloc failed");
2808         pthread_mutex_destroy(&realm->subrealms_mutex);
2809         goto errexit;
2810     }
2811     
2812     debug(DBG_DBG, "addrealm: added realm %s", value);
2813     goto exit;
2814
2815  errexit:
2816     freerealm(realm);
2817     realm = NULL;
2818     
2819  exit:
2820     free(regex);
2821     if (servers) {
2822         for (n = 0; servers[n]; n++)
2823             free(servers[n]);
2824         free(servers);
2825     }
2826     if (accservers) {
2827         for (n = 0; accservers[n]; n++)
2828             free(accservers[n]);
2829         free(accservers);
2830     }
2831     return realm;
2832 }
2833
2834 void adddynamicrealmserver(struct realm *realm, struct clsrvconf *conf, char *id) {
2835     struct clsrvconf *srvconf;
2836     struct realm *newrealm = NULL;
2837     char *realmname, *s;
2838
2839     
2840     if (!conf->dynamiclookupcommand)
2841         return;
2842
2843     /* create dynamic for the realm (string after last @, exit if nothing after @ */
2844     realmname = strrchr(id, '@');
2845     if (!realmname)
2846         return;
2847     realmname++;
2848     if (!*realmname)
2849         return;
2850     for (s = realmname; *s; s++)
2851         if (*s != '.' && *s != '-' && !isalnum(*s))
2852             return;
2853     
2854     pthread_mutex_lock(&realm->subrealms_mutex);
2855     /* exit if we now already got a matching subrealm */
2856     if (id2realm(realm->subrealms, id))
2857         goto exit;
2858     srvconf = malloc(sizeof(struct clsrvconf));
2859     if (!srvconf) {
2860         debug(DBG_ERR, "malloc failed");
2861         goto exit;
2862     }
2863     *srvconf = *conf;
2864     if (!addserver(srvconf))
2865         goto errexit;
2866
2867     if (!realm->subrealms)
2868         realm->subrealms = list_create();
2869     if (!realm->subrealms)
2870         goto errexit;
2871     newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, NULL);
2872     if (!newrealm)
2873         goto errexit;
2874
2875     /* add server and accserver to newrealm */
2876     newrealm->srvconfs = list_create();
2877     if (!newrealm->srvconfs || !list_push(newrealm->srvconfs, srvconf)) {
2878         debug(DBG_ERR, "malloc failed");
2879         goto errexit;
2880     }
2881     newrealm->accsrvconfs = list_create();
2882     if (!newrealm->accsrvconfs || !list_push(newrealm->accsrvconfs, srvconf)) {
2883         debug(DBG_ERR, "malloc failed");
2884         goto errexit;
2885     }
2886
2887     srvconf->servers->dynamiclookuparg = stringcopy(realmname, 0);
2888
2889     if (pthread_create(&srvconf->servers->clientth, NULL, clientwr, (void *)(srvconf->servers))) {
2890         debug(DBG_ERR, "pthread_create failed");
2891         goto errexit;
2892     }
2893
2894     goto exit;
2895     
2896  errexit:
2897     if (newrealm) {
2898         list_removedata(realm->subrealms, newrealm);
2899         freerealm(newrealm);
2900     }
2901     freeserver(srvconf->servers, 1);
2902     free(srvconf);
2903     debug(DBG_ERR, "failed to create dynamic server");
2904
2905  exit:
2906     pthread_mutex_unlock(&realm->subrealms_mutex);
2907 }
2908
2909 void dynamicconfig(struct server *server) {
2910     int ok, fd[2], status;
2911     pid_t pid;
2912     struct clsrvconf *conf = server->conf;
2913     struct gconffile *cf = NULL;
2914     
2915     /* for now we only learn hostname/address */
2916     debug(DBG_DBG, "dynamicconfig: need dynamic server config for %s", server->dynamiclookuparg);
2917
2918     if (pipe(fd) > 0) {
2919         debug(DBG_ERR, "dynamicconfig: pipe error");
2920         goto errexit;
2921     }
2922     pid = fork();
2923     if (pid < 0) {
2924         debug(DBG_ERR, "dynamicconfig: fork error");
2925         goto errexit;
2926     } else if (pid == 0) {
2927         /* child */
2928         close(fd[0]);
2929         if (fd[1] != STDOUT_FILENO) {
2930             if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
2931                 debugx(1, DBG_ERR, "dynamicconfig: dup2 error for command %s", conf->dynamiclookupcommand);
2932             close(fd[1]);
2933         }
2934         if (execlp(conf->dynamiclookupcommand, conf->dynamiclookupcommand, server->dynamiclookuparg, NULL) < 0)
2935             debugx(1, DBG_ERR, "dynamicconfig: exec error for command %s", conf->dynamiclookupcommand);
2936     }
2937
2938     close(fd[1]);
2939     pushgconffile(&cf, fdopen(fd[0], "r"), conf->dynamiclookupcommand);
2940     ok = getgenericconfig(&cf, NULL,
2941                           "Server", CONF_CBK, confserver_cb, (void *)conf,
2942                           NULL
2943                           );
2944     freegconf(&cf);
2945         
2946     if (waitpid(pid, &status, 0) < 0) {
2947         debug(DBG_ERR, "dynamicconfig: wait error");
2948         goto errexit;
2949     }
2950     
2951     if (status) {
2952         debug(DBG_INFO, "dynamicconfig: command exited with status %d", WEXITSTATUS(status));
2953         goto errexit;
2954     }
2955
2956     if (ok)
2957         return;
2958
2959  errexit:    
2960     server->conf = NULL;
2961     debug(DBG_WARN, "dynamicconfig: failed to obtain dynamic server config");
2962 }
2963
2964 int addmatchcertattr(struct clsrvconf *conf) {
2965     char *v;
2966     regex_t **r;
2967     
2968     if (!strncasecmp(conf->matchcertattr, "CN:/", 4)) {
2969         r = &conf->certcnregex;
2970         v = conf->matchcertattr + 4;
2971     } else if (!strncasecmp(conf->matchcertattr, "SubjectAltName:URI:/", 20)) {
2972         r = &conf->certuriregex;
2973         v = conf->matchcertattr + 20;
2974     } else
2975         return 0;
2976     if (!*v)
2977         return 0;
2978     /* regexp, remove optional trailing / if present */
2979     if (v[strlen(v) - 1] == '/')
2980         v[strlen(v) - 1] = '\0';
2981     if (!*v)
2982         return 0;
2983
2984     *r = malloc(sizeof(regex_t));
2985     if (!*r) {
2986         debug(DBG_ERR, "malloc failed");
2987         return 0;
2988     }
2989     if (regcomp(*r, v, REG_ICASE | REG_NOSUB)) {
2990         free(*r);
2991         *r = NULL;
2992         debug(DBG_ERR, "failed to compile regular expression %s", v);
2993         return 0;
2994     }
2995     return 1;
2996 }
2997
2998 int addrewriteattr(struct clsrvconf *conf) {
2999     char *v, *w;
3000     
3001     v = conf->rewriteattr + 11;
3002     if (strncasecmp(conf->rewriteattr, "User-Name:/", 11) || !*v)
3003         return 0;
3004     /* regexp, remove optional trailing / if present */
3005     if (v[strlen(v) - 1] == '/')
3006         v[strlen(v) - 1] = '\0';
3007
3008     w = strchr(v, '/');
3009     if (!*w)
3010         return 0;
3011     *w = '\0';
3012     w++;
3013     
3014     conf->rewriteattrregex = malloc(sizeof(regex_t));
3015     if (!conf->rewriteattrregex) {
3016         debug(DBG_ERR, "malloc failed");
3017         return 0;
3018     }
3019
3020     conf->rewriteattrreplacement = stringcopy(w, 0);
3021     if (!conf->rewriteattrreplacement) {
3022         free(conf->rewriteattrregex);
3023         conf->rewriteattrregex = NULL;
3024         return 0;
3025     }
3026     
3027     if (regcomp(conf->rewriteattrregex, v, REG_ICASE | REG_EXTENDED)) {
3028         free(conf->rewriteattrregex);
3029         conf->rewriteattrregex = NULL;
3030         free(conf->rewriteattrreplacement);
3031         conf->rewriteattrreplacement = NULL;
3032         debug(DBG_ERR, "failed to compile regular expression %s", v);
3033         return 0;
3034     }
3035
3036     return 1;
3037 }
3038
3039 /* should accept both names and numeric values, only numeric right now */
3040 uint8_t attrname2val(char *attrname) {
3041     int val = 0;
3042     
3043     val = atoi(attrname);
3044     return val > 0 && val < 256 ? val : 0;
3045 }
3046
3047 /* should accept both names and numeric values, only numeric right now */
3048 int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) {
3049     char *s;
3050     
3051     *vendor = atoi(attrname);
3052     s = strchr(attrname, ':');
3053     if (!s) {
3054         *type = -1;
3055         return 1;
3056     }
3057     *type = atoi(s + 1);
3058     return *type >= 0 && *type < 256;
3059 }
3060
3061 struct rewrite *getrewrite(char *alt1, char *alt2) {
3062     struct list_node *entry;
3063     struct rewriteconf *r, *r1 = NULL, *r2 = NULL;
3064     
3065     for (entry = list_first(rewriteconfs); entry; entry = list_next(entry)) {
3066         r = (struct rewriteconf *)entry->data;
3067         if (!strcasecmp(r->name, alt1)) {
3068             r1 = r;
3069             break;
3070         }
3071         if (!r2 && alt2 && !strcasecmp(r->name, alt2))
3072             r2 = r;
3073     }
3074
3075     r = (r1 ? r1 : r2);
3076     if (!r)
3077         return NULL;
3078     return r->rewrite;
3079 }
3080
3081 void addrewrite(char *value, char **attrs, char **vattrs) {
3082     struct rewriteconf *new;
3083     struct rewrite *rewrite = NULL;
3084     int i, n;
3085     uint8_t *a = NULL;
3086     uint32_t *p, *va = NULL;
3087
3088     if (attrs) {
3089         n = 0;
3090         for (; attrs[n]; n++);
3091         a = malloc((n + 1) * sizeof(uint8_t));
3092         if (!a)
3093             debugx(1, DBG_ERR, "malloc failed");
3094     
3095         for (i = 0; i < n; i++) {
3096             if (!(a[i] = attrname2val(attrs[i])))
3097                 debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", attrs[i]);
3098             free(attrs[i]);
3099         }
3100         free(attrs);
3101         a[i] = 0;
3102     }
3103     
3104     if (vattrs) {
3105         n = 0;
3106         for (; vattrs[n]; n++);
3107         va = malloc((2 * n + 1) * sizeof(uint32_t));
3108         if (!va)
3109             debugx(1, DBG_ERR, "malloc failed");
3110     
3111         for (p = va, i = 0; i < n; i++, p += 2) {
3112             if (!vattrname2val(vattrs[i], p, p + 1))
3113                 debugx(1, DBG_ERR, "addrewrite: invalid vendor attribute %s", vattrs[i]);
3114             free(vattrs[i]);
3115         }
3116         free(vattrs);
3117         *p = 0;
3118     }
3119     
3120     if (a || va) {
3121         rewrite = malloc(sizeof(struct rewrite));
3122         if (!rewrite)
3123             debugx(1, DBG_ERR, "malloc failed");
3124         rewrite->removeattrs = a;
3125         rewrite->removevendorattrs = va;
3126     }
3127     
3128     new = malloc(sizeof(struct rewriteconf));
3129     if (!new || !list_push(rewriteconfs, new))
3130         debugx(1, DBG_ERR, "malloc failed");
3131
3132     memset(new, 0, sizeof(struct rewriteconf));
3133     new->name = stringcopy(value, 0);
3134     if (!new->name)
3135         debugx(1, DBG_ERR, "malloc failed");
3136         
3137     new->rewrite = rewrite;
3138     debug(DBG_DBG, "addrewrite: added rewrite block %s", value);
3139 }
3140
3141 void freeclsrvconf(struct clsrvconf *conf) {
3142     free(conf->name);
3143     free(conf->conftype);
3144     free(conf->host);
3145     free(conf->port);
3146     free(conf->secret);
3147     free(conf->tls);
3148     free(conf->matchcertattr);
3149     if (conf->certcnregex)
3150         regfree(conf->certcnregex);
3151     if (conf->certuriregex)
3152         regfree(conf->certuriregex);
3153     free(conf->confrewrite);
3154     free(conf->rewriteattr);
3155     if (conf->rewriteattrregex)
3156         regfree(conf->rewriteattrregex);
3157     free(conf->rewriteattrreplacement);
3158     free(conf->dynamiclookupcommand);
3159     if (conf->ssl_ctx)
3160         SSL_CTX_free(conf->ssl_ctx);
3161     free(conf->rewrite);
3162     if (conf->addrinfo)
3163         freeaddrinfo(conf->addrinfo);
3164     list_destroy(conf->clients);
3165     free(conf->servers);
3166     free(conf);
3167 }
3168
3169 int mergeconfstring(char **dst, char **src) {
3170     char *t;
3171     
3172     if (*src) {
3173         *dst = *src;
3174         *src = NULL;
3175         return 1;
3176     }
3177     if (*dst) {
3178         t = stringcopy(*dst, 0);
3179         if (!t) {
3180             debug(DBG_ERR, "malloc failed");
3181             return 0;
3182         }
3183         *dst = t;
3184     }
3185     return 1;
3186 }
3187
3188 /* assumes dst is a shallow copy */
3189 int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
3190     if (!mergeconfstring(&dst->name, &src->name) ||
3191         !mergeconfstring(&dst->conftype, &src->conftype) ||
3192         !mergeconfstring(&dst->host, &src->host) ||
3193         !mergeconfstring(&dst->port, &src->port) ||
3194         !mergeconfstring(&dst->secret, &src->secret) ||
3195         !mergeconfstring(&dst->tls, &src->tls) ||
3196         !mergeconfstring(&dst->matchcertattr, &src->matchcertattr) ||
3197         !mergeconfstring(&dst->confrewrite, &src->confrewrite))
3198         return 0;
3199     dst->statusserver = src->statusserver;
3200     dst->certnamecheck = src->certnamecheck;
3201     return 1;
3202 }
3203                    
3204 int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3205     struct clsrvconf *conf;
3206     
3207     debug(DBG_DBG, "confclient_cb called for %s", block);
3208
3209     conf = malloc(sizeof(struct clsrvconf));
3210     if (!conf || !list_push(clconfs, conf))
3211         debugx(1, DBG_ERR, "malloc failed");
3212     memset(conf, 0, sizeof(struct clsrvconf));
3213     conf->certnamecheck = 1;
3214     
3215     if (!getgenericconfig(cf, block,
3216                      "type", CONF_STR, &conf->conftype,
3217                      "host", CONF_STR, &conf->host,
3218                      "secret", CONF_STR, &conf->secret,
3219                      "tls", CONF_STR, &conf->tls,
3220                      "matchcertificateattribute", CONF_STR, &conf->matchcertattr,
3221                      "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
3222                      "rewrite", CONF_STR, &conf->confrewrite,
3223                      "rewriteattribute", CONF_STR, &conf->rewriteattr,
3224                      NULL
3225                           ))
3226         debugx(1, DBG_ERR, "configuration error");
3227     
3228     conf->name = stringcopy(val, 0);
3229     if (!conf->host)
3230         conf->host = stringcopy(val, 0);
3231     
3232     if (conf->conftype && !strcasecmp(conf->conftype, "udp")) {
3233         conf->type = 'U';
3234         client_udp_count++;
3235     } else if (conf->conftype && !strcasecmp(conf->conftype, "tls")) {
3236         conf->ssl_ctx = conf->tls ? tlsgetctx(conf->tls, NULL) : tlsgetctx("defaultclient", "default");
3237         if (!conf->ssl_ctx)
3238             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
3239         if (conf->matchcertattr && !addmatchcertattr(conf))
3240             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
3241         conf->type = 'T';
3242         client_tls_count++;
3243     } else
3244         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
3245     
3246     conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultclient", "default");
3247     
3248     if (conf->rewriteattr) {
3249         if (!addrewriteattr(conf))
3250             debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
3251     }
3252     
3253     if (!resolvepeer(conf, 0))
3254         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
3255     
3256     if (!conf->secret) {
3257         if (conf->type == 'U')
3258             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
3259         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
3260     }
3261     return 1;
3262 }
3263
3264 int compileserverconfig(struct clsrvconf *conf, const char *block) {
3265     switch (conf->type) {
3266     case 'U':
3267         if (!conf->port)
3268             conf->port = stringcopy(DEFAULT_UDP_PORT, 0);
3269         break;
3270     case 'T':
3271         conf->ssl_ctx = conf->tls ? tlsgetctx(conf->tls, NULL) : tlsgetctx("defaultserver", "default");
3272         if (!conf->ssl_ctx) {
3273             debug(DBG_ERR, "error in block %s, no tls context defined", block);
3274             return 0;
3275         }
3276         if (conf->matchcertattr && !addmatchcertattr(conf)) {
3277             debug(DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
3278             return 0;
3279         }
3280         if (!conf->port)
3281             conf->port = stringcopy(DEFAULT_TLS_PORT, 0);
3282         break;
3283     }
3284     
3285     conf->rewrite = conf->confrewrite ? getrewrite(conf->confrewrite, NULL) : getrewrite("defaultserver", "default");
3286     
3287     if (!conf->secret) {
3288         if (conf->type == 'U')
3289             debug(DBG_ERR, "error in block %s, secret must be specified for UDP", block);
3290         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
3291         if (!conf->secret) {
3292             debug(DBG_ERR, "malloc failed");
3293             return 0;
3294         }
3295     }
3296     
3297     if (!conf->dynamiclookupcommand && !resolvepeer(conf, 0)) {
3298         debug(DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
3299         return 0;
3300     }
3301     return 1;
3302 }
3303                         
3304 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3305     struct clsrvconf *conf, *resconf;
3306     
3307     debug(DBG_DBG, "confserver_cb called for %s", block);
3308
3309     conf = malloc(sizeof(struct clsrvconf));
3310     if (!conf) {
3311         debug(DBG_ERR, "malloc failed");
3312         return 0;
3313     }
3314     memset(conf, 0, sizeof(struct clsrvconf));
3315     resconf = (struct clsrvconf *)arg;
3316     if (resconf) {
3317         conf->statusserver = resconf->statusserver;
3318         conf->certnamecheck = resconf->certnamecheck;
3319     } else
3320         conf->certnamecheck = 1;
3321     
3322     if (!getgenericconfig(cf, block,
3323                      "type", CONF_STR, &conf->conftype,
3324                      "host", CONF_STR, &conf->host,
3325                      "port", CONF_STR, &conf->port,
3326                      "secret", CONF_STR, &conf->secret,
3327                      "tls", CONF_STR, &conf->tls,
3328                      "MatchCertificateAttribute", CONF_STR, &conf->matchcertattr,
3329                      "rewrite", CONF_STR, &conf->confrewrite,
3330                      "StatusServer", CONF_BLN, &conf->statusserver,
3331                      "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
3332                      "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand,
3333                      NULL
3334                           )) {
3335         debug(DBG_ERR, "configuration error");
3336         goto errexit;
3337     }
3338     
3339     conf->name = stringcopy(val, 0);
3340     if (!conf->name) {
3341         debug(DBG_ERR, "malloc failed");
3342         goto errexit;
3343     }
3344     if (!conf->host) {
3345         conf->host = stringcopy(val, 0);
3346         if (!conf->host) {
3347             debug(DBG_ERR, "malloc failed");
3348             goto errexit;
3349         }
3350     }
3351
3352     if (resconf) {
3353         if (!mergesrvconf(resconf, conf))
3354             goto errexit;
3355         free(conf);
3356         conf = resconf;
3357     }
3358
3359     if (conf->conftype && !strcasecmp(conf->conftype, "udp"))
3360         conf->type = 'U';
3361     else if (conf->conftype && !strcasecmp(conf->conftype, "tls"))
3362         conf->type = 'T';
3363     else {
3364         debug(DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
3365         goto errexit;
3366     }
3367     
3368     if (resconf || !conf->dynamiclookupcommand) {
3369         if (!compileserverconfig(conf, block))
3370             goto errexit;
3371     }
3372     
3373     if (resconf)
3374         return 1;
3375         
3376     switch (conf->type) {
3377     case 'U':
3378         server_udp_count++;
3379         break;
3380     case 'T':
3381         server_tls_count++;
3382         break;
3383     default:
3384         goto errexit;
3385     }
3386     
3387     if (!list_push(srvconfs, conf)) {
3388         debug(DBG_ERR, "malloc failed");
3389         goto errexit;
3390     }
3391     return 1;
3392
3393  errexit:    
3394     freeclsrvconf(conf);
3395     return 0;
3396 }
3397
3398 int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3399     char **servers = NULL, **accservers = NULL, *msg = NULL;
3400     
3401     debug(DBG_DBG, "confrealm_cb called for %s", block);
3402     
3403     if (!getgenericconfig(cf, block,
3404                      "server", CONF_MSTR, &servers,
3405                      "accountingServer", CONF_MSTR, &accservers,
3406                      "ReplyMessage", CONF_STR, &msg,
3407                      NULL
3408                           ))
3409         debugx(1, DBG_ERR, "configuration error");
3410
3411     addrealm(realms, val, servers, accservers, msg);
3412     return 1;
3413 }
3414
3415 int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3416     char *cacertfile = NULL, *cacertpath = NULL, *certfile = NULL, *certkeyfile = NULL, *certkeypwd = NULL;
3417     
3418     debug(DBG_DBG, "conftls_cb called for %s", block);
3419     
3420     if (!getgenericconfig(cf, block,
3421                      "CACertificateFile", CONF_STR, &cacertfile,
3422                      "CACertificatePath", CONF_STR, &cacertpath,
3423                      "CertificateFile", CONF_STR, &certfile,
3424                      "CertificateKeyFile", CONF_STR, &certkeyfile,
3425                      "CertificateKeyPassword", CONF_STR, &certkeypwd,
3426                      NULL
3427                           ))
3428         debugx(1, DBG_ERR, "configuration error");
3429     
3430     tlsadd(val, cacertfile, cacertpath, certfile, certkeyfile, certkeypwd);
3431     free(cacertfile);
3432     free(cacertpath);
3433     free(certfile);
3434     free(certkeyfile);
3435     free(certkeypwd);
3436     return 1;
3437 }
3438
3439 int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
3440     char **attrs = NULL, **vattrs = NULL;
3441     
3442     debug(DBG_DBG, "confrewrite_cb called for %s", block);
3443     
3444     if (!getgenericconfig(cf, block,
3445                      "removeAttribute", CONF_MSTR, &attrs,
3446                      "removeVendorAttribute", CONF_MSTR, &vattrs,
3447                      NULL
3448                           ))
3449         debugx(1, DBG_ERR, "configuration error");
3450     addrewrite(val, attrs, vattrs);
3451     return 1;
3452 }
3453
3454 void getmainconfig(const char *configfile) {
3455     char *loglevel = NULL;
3456     struct gconffile *cfs;
3457
3458     cfs = openconfigfile(configfile);
3459     memset(&options, 0, sizeof(options));
3460     
3461     clconfs = list_create();
3462     if (!clconfs)
3463         debugx(1, DBG_ERR, "malloc failed");
3464     
3465     srvconfs = list_create();
3466     if (!srvconfs)
3467         debugx(1, DBG_ERR, "malloc failed");
3468     
3469     realms = list_create();
3470     if (!realms)
3471         debugx(1, DBG_ERR, "malloc failed");    
3472  
3473     tlsconfs = list_create();
3474     if (!tlsconfs)
3475         debugx(1, DBG_ERR, "malloc failed");
3476     
3477     rewriteconfs = list_create();
3478     if (!rewriteconfs)
3479         debugx(1, DBG_ERR, "malloc failed");    
3480  
3481     if (!getgenericconfig(&cfs, NULL,
3482                           "ListenUDP", CONF_STR, &options.listenudp,
3483                           "ListenTCP", CONF_STR, &options.listentcp,
3484                           "ListenAccountingUDP", CONF_STR, &options.listenaccudp,
3485                           "SourceUDP", CONF_STR, &options.sourceudp,
3486                           "SourceTCP", CONF_STR, &options.sourcetcp,
3487                           "LogLevel", CONF_STR, &loglevel,
3488                           "LogDestination", CONF_STR, &options.logdestination,
3489                           "RPFCheck", CONF_BLN, &options.rpf,
3490                           "Client", CONF_CBK, confclient_cb, NULL,
3491                           "Server", CONF_CBK, confserver_cb, NULL,
3492                           "Realm", CONF_CBK, confrealm_cb, NULL,
3493                           "TLS", CONF_CBK, conftls_cb, NULL,
3494                           "Rewrite", CONF_CBK, confrewrite_cb, NULL,
3495                           NULL
3496                           ))
3497         debugx(1, DBG_ERR, "configuration error");
3498     
3499     if (loglevel) {
3500         if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
3501             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
3502         options.loglevel = *loglevel - '0';
3503         free(loglevel);
3504     }
3505 }
3506
3507 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile) {
3508     int c;
3509
3510     while ((c = getopt(argc, argv, "c:d:fpv")) != -1) {
3511         switch (c) {
3512         case 'c':
3513             *configfile = optarg;
3514             break;
3515         case 'd':
3516             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
3517                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
3518             *loglevel = *optarg - '0';
3519             break;
3520         case 'f':
3521             *foreground = 1;
3522             break;
3523         case 'p':
3524             *pretend = 1;
3525             break;
3526         case 'v':
3527                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
3528         default:
3529             goto usage;
3530         }
3531     }
3532     if (!(argc - optind))
3533         return;
3534
3535  usage:
3536     debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -p ] [ -v ]", argv[0]);
3537 }
3538
3539 #ifdef SYS_SOLARIS9
3540 int daemon(int a, int b) {
3541     int i;
3542
3543     if (fork())
3544         exit(0);
3545
3546     setsid();
3547
3548     for (i = 0; i < 3; i++) {
3549         close(i);
3550         open("/dev/null", O_RDWR);
3551     }
3552     return 1;
3553 }
3554 #endif
3555
3556 void *sighandler(void *arg) {
3557     sigset_t sigset;
3558     int sig;
3559
3560     for(;;) {
3561         sigemptyset(&sigset);
3562         sigaddset(&sigset, SIGPIPE);
3563         sigwait(&sigset, &sig);
3564         /* only get SIGPIPE right now, so could simplify below code */
3565         switch (sig) {
3566         case 0:
3567             /* completely ignoring this */
3568             break;
3569         case SIGPIPE:
3570             debug(DBG_WARN, "sighandler: got SIGPIPE, TLS write error?");
3571             break;
3572         default:
3573             debug(DBG_WARN, "sighandler: ignoring signal %d", sig);
3574         }
3575     }
3576 }
3577
3578 int main(int argc, char **argv) {
3579     pthread_t sigth, udpserverth, udpaccserverth, udpclient4rdth, udpclient6rdth;
3580     sigset_t sigset;
3581     struct list_node *entry;
3582     uint8_t foreground = 0, pretend = 0, loglevel = 0;
3583     char *configfile = NULL;
3584     struct clsrvconf *srvconf;
3585     
3586     debug_init("radsecproxy");
3587     debug_set_level(DEBUG_LEVEL);
3588     getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile);
3589     if (loglevel)
3590         debug_set_level(loglevel);
3591     getmainconfig(configfile ? configfile : CONFIG_MAIN);
3592     if (loglevel)
3593         options.loglevel = loglevel;
3594     else if (options.loglevel)
3595         debug_set_level(options.loglevel);
3596     if (foreground) {
3597         free(options.logdestination);
3598         options.logdestination = NULL;
3599    } else {
3600         if (!options.logdestination)
3601             options.logdestination = "x-syslog:///";
3602         debug_set_destination(options.logdestination);
3603         free(options.logdestination);
3604     }
3605
3606     if (!list_first(clconfs))
3607         debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
3608     if (!list_first(srvconfs))
3609         debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
3610     if (!list_first(realms))
3611         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
3612
3613     if (pretend)
3614         debugx(0, DBG_ERR, "All OK so far; exiting since only pretending");
3615
3616     if (!foreground && (daemon(0, 0) < 0))
3617         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
3618     
3619     debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
3620
3621     sigemptyset(&sigset);
3622     /* exit on all but SIGPIPE, ignore more? */
3623     sigaddset(&sigset, SIGPIPE);
3624     pthread_sigmask(SIG_BLOCK, &sigset, NULL);
3625     pthread_create(&sigth, NULL, sighandler, NULL);
3626     
3627     if (client_udp_count) {
3628         udp_server_replyq = newreplyq();
3629         if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
3630             debugx(1, DBG_ERR, "pthread_create failed");
3631         if (options.listenaccudp)
3632             if (pthread_create(&udpaccserverth, NULL, udpaccserverrd, NULL))
3633                 debugx(1, DBG_ERR, "pthread_create failed");
3634     }
3635     
3636     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
3637         srvconf = (struct clsrvconf *)entry->data;
3638         if (srvconf->dynamiclookupcommand)
3639             continue;
3640         if (!addserver(srvconf))
3641             debugx(1, DBG_ERR, "failed to add server");
3642         if (pthread_create(&srvconf->servers->clientth, NULL, clientwr,
3643                            (void *)(srvconf->servers)))
3644             debugx(1, DBG_ERR, "pthread_create failed");
3645     }
3646     /* srcudpres no longer needed, while srctcpres is needed later */
3647     if (srcudpres) {
3648         freeaddrinfo(srcudpres);
3649         srcudpres = NULL;
3650     }
3651     if (udp_client4_sock >= 0)
3652         if (pthread_create(&udpclient4rdth, NULL, udpclientrd, (void *)&udp_client4_sock))
3653             debugx(1, DBG_ERR, "pthread_create failed");
3654     if (udp_client6_sock >= 0)
3655         if (pthread_create(&udpclient6rdth, NULL, udpclientrd, (void *)&udp_client6_sock))
3656             debugx(1, DBG_ERR, "pthread_create failed");
3657     
3658     if (client_tls_count)
3659         return tlslistener();
3660     
3661     /* just hang around doing nothing, anything to do here? */
3662     for (;;)
3663         sleep(1000);
3664 }