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