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