implemented config file stack; to be used for include support
[radsecproxy.git] / radsecproxy.c
1 /*
2  * Copyright (C) 2006, 2007 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 <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <arpa/inet.h>
40 #include <regex.h>
41 #include <libgen.h>
42 #include <pthread.h>
43 #include <openssl/ssl.h>
44 #include <openssl/rand.h>
45 #include <openssl/err.h>
46 #include <openssl/md5.h>
47 #include <openssl/hmac.h>
48 #include <openssl/x509v3.h>
49 #include "debug.h"
50 #include "list.h"
51 #include "util.h"
52 #include "gconfig.h"
53 #include "radsecproxy.h"
54
55 static struct options options;
56 struct list *clconfs, *srvconfs, *realms, *tlsconfs;
57
58 static int client_udp_count = 0;
59 static int client_tls_count = 0;
60 static int server_udp_count = 0;
61 static int server_tls_count = 0;
62
63 static struct clsrvconf *srcudpres = NULL;
64 static struct clsrvconf *srctcpres = NULL;
65
66 static struct replyq *udp_server_replyq = NULL;
67 static int udp_server_sock = -1;
68 static int udp_accserver_sock = -1;
69 static int udp_client4_sock = -1;
70 static int udp_client6_sock = -1;
71 static pthread_mutex_t *ssl_locks;
72 static long *ssl_lock_count;
73 extern int optind;
74 extern char *optarg;
75
76 /* callbacks for making OpenSSL thread safe */
77 unsigned long ssl_thread_id() {
78         return (unsigned long)pthread_self();
79 }
80
81 void ssl_locking_callback(int mode, int type, const char *file, int line) {
82     if (mode & CRYPTO_LOCK) {
83         pthread_mutex_lock(&ssl_locks[type]);
84         ssl_lock_count[type]++;
85     } else
86         pthread_mutex_unlock(&ssl_locks[type]);
87 }
88
89 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
90     int pwdlen = strlen(userdata);
91     if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
92         return 0;
93     memcpy(buf, userdata, pwdlen);
94     return pwdlen;
95 }
96
97 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
98   char buf[256];
99   X509 *err_cert;
100   int err, depth;
101
102   err_cert = X509_STORE_CTX_get_current_cert(ctx);
103   err = X509_STORE_CTX_get_error(ctx);
104   depth = X509_STORE_CTX_get_error_depth(ctx);
105
106   if (depth > MAX_CERT_DEPTH) {
107       ok = 0;
108       err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
109       X509_STORE_CTX_set_error(ctx, err);
110   }
111
112   if (!ok) {
113       X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
114       debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
115
116       switch (err) {
117       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
118           X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
119           debug(DBG_WARN, "\tIssuer=%s", buf);
120           break;
121       case X509_V_ERR_CERT_NOT_YET_VALID:
122       case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
123           debug(DBG_WARN, "\tCertificate not yet valid");
124           break;
125       case X509_V_ERR_CERT_HAS_EXPIRED:
126           debug(DBG_WARN, "Certificate has expired");
127           break;
128       case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
129           debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
130           break;
131       }
132   }
133 #ifdef DEBUG  
134   printf("certificate verify returns %d\n", ok);
135 #endif  
136   return ok;
137 }
138
139 int resolvepeer(struct clsrvconf *conf, int ai_flags) {
140     struct addrinfo hints, *addrinfo, *res;
141     char *slash, *s;
142     int plen;
143
144     slash = conf->host ? strchr(conf->host, '/') : NULL;
145     if (slash) {
146         s = slash + 1;
147         if (!*s) {
148             debug(DBG_WARN, "resolvepeer: prefix length must be specified after the / in %s", conf->host);
149             return 0;
150         }
151         for (; *s; s++)
152             if (*s < '0' || *s > '9') {
153                 debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
154                 return 0;
155             }
156         plen = atoi(slash + 1);
157         if (plen < 0 || plen > 128) {
158             debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host);
159             return 0;
160         }
161         *slash = '\0';
162     }
163     memset(&hints, 0, sizeof(hints));
164     hints.ai_socktype = (conf->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
165     hints.ai_family = AF_UNSPEC;
166     hints.ai_flags = ai_flags;
167     if (!conf->host && !conf->port) {
168         /* getaddrinfo() doesn't like host and port to be NULL */
169         if (getaddrinfo(conf->host, DEFAULT_UDP_PORT, &hints, &addrinfo)) {
170             debug(DBG_WARN, "resolvepeer: can't resolve (null) port (null)");
171             return 0;
172         }
173         for (res = addrinfo; res; res = res->ai_next) {
174             switch (res->ai_family) {
175             case AF_INET:
176                 ((struct sockaddr_in *)res->ai_addr)->sin_port = 0;
177                 break;
178             case AF_INET6:
179                 ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = 0;
180                 break;
181             }
182         }
183     } else {
184         if (slash)
185             hints.ai_flags |= AI_NUMERICHOST;
186         if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) {
187             debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host, conf->port);
188             return 0;
189         }
190         if (slash) {
191             *slash = '/';
192             switch (addrinfo->ai_family) {
193             case AF_INET:
194                 if (plen > 32) {
195                     debug(DBG_WARN, "resolvepeer: prefix length must be <= 32 in %s", conf->host);
196                     freeaddrinfo(addrinfo);
197                     return 0;
198                 }
199                 break;
200             case AF_INET6:
201                 break;
202             default:
203                 debug(DBG_WARN, "resolvepeer: prefix must be IPv4 or IPv6 in %s", conf->host);
204                 freeaddrinfo(addrinfo);
205                 return 0;
206             }
207             conf->prefixlen = plen;
208         } else
209             conf->prefixlen = 255;
210     }
211     if (conf->addrinfo)
212         freeaddrinfo(conf->addrinfo);
213     conf->addrinfo = addrinfo;
214     return 1;
215 }         
216
217 int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) {
218     int s, on = 1;
219     struct addrinfo *res;
220     
221     for (res = addrinfo; res; res = res->ai_next) {
222         if (family != AF_UNSPEC && family != res->ai_family)
223             continue;
224         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
225         if (s < 0) {
226             debug(DBG_WARN, "bindtoaddr: socket failed");
227             continue;
228         }
229         if (reuse)
230             setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
231 #ifdef IPV6_V6ONLY
232         if (v6only)
233             setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
234 #endif          
235
236         if (!bind(s, res->ai_addr, res->ai_addrlen))
237             return s;
238         debug(DBG_WARN, "bindtoaddr: bind failed");
239         close(s);
240     }
241     return -1;
242 }         
243
244 char *parsehostport(char *s, struct clsrvconf *conf, char *default_port) {
245     char *p, *field;
246     int ipv6 = 0;
247
248     p = s;
249     /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
250     if (*p == '[') {
251         p++;
252         field = p;
253         for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
254         if (*p != ']')
255             debugx(1, DBG_ERR, "no ] matching initial [");
256         ipv6 = 1;
257     } else {
258         field = p;
259         for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
260     }
261     if (field == p)
262         debugx(1, DBG_ERR, "missing host/address");
263
264     conf->host = stringcopy(field, p - field);
265     if (ipv6) {
266         p++;
267         if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
268             debugx(1, DBG_ERR, "unexpected character after ]");
269     }
270     if (*p == ':') {
271             /* port number or service name is specified */;
272             field = ++p;
273             for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
274             if (field == p)
275                 debugx(1, DBG_ERR, "syntax error, : but no following port");
276             conf->port = stringcopy(field, p - field);
277     } else
278         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
279     return p;
280 }
281
282 struct clsrvconf *resolve_hostport(char type, char *lconf, char *default_port) {
283     struct clsrvconf *conf;
284
285     conf = malloc(sizeof(struct clsrvconf));
286     if (!conf)
287         debugx(1, DBG_ERR, "malloc failed");
288     memset(conf, 0, sizeof(struct clsrvconf));
289     conf->type = type;
290     if (lconf) {
291         parsehostport(lconf, conf, default_port);
292         if (!strcmp(conf->host, "*")) {
293             free(conf->host);
294             conf->host = NULL;
295         }
296     } else
297         conf->port = default_port ? stringcopy(default_port, 0) : NULL;
298     if (!resolvepeer(conf, AI_PASSIVE))
299         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
300     return conf;
301 }
302
303 int connecttcp(struct addrinfo *addrinfo) {
304     int s;
305     struct addrinfo *res;
306
307     s = -1;
308     for (res = addrinfo; res; res = res->ai_next) {
309         s = bindtoaddr(srctcpres->addrinfo, res->ai_family, 1, 1);
310         if (s < 0) {
311             debug(DBG_WARN, "connecttoserver: socket failed");
312             continue;
313         }
314         if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
315             break;
316         debug(DBG_WARN, "connecttoserver: connect failed");
317         close(s);
318         s = -1;
319     }
320     return s;
321 }         
322
323 /* returns 1 if the len first bits are equal, else 0 */
324 int prefixmatch(void *a1, void *a2, uint8_t len) {
325     static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
326     int r, l = len / 8;
327     if (l && memcmp(a1, a2, l))
328         return 0;
329     r = len % 8;
330     if (!r)
331         return 1;
332     return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
333 }
334
335 /* returns the config with matching address, or NULL */
336 /* if conf argument is not NULL, we only check that one */
337 struct clsrvconf *find_conf(char type, struct sockaddr *addr, struct list *confs, struct clsrvconf *conf) {
338     struct sockaddr_in6 *sa6 = NULL;
339     struct in_addr *a4 = NULL;
340     struct addrinfo *res;
341     struct list_node *entry;
342     
343     if (addr->sa_family == AF_INET6) {
344         sa6 = (struct sockaddr_in6 *)addr;
345         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
346             a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
347             sa6 = NULL;
348         }
349     } else
350         a4 = &((struct sockaddr_in *)addr)->sin_addr;
351
352     if (conf) {
353         if (conf->type == type) {
354             if (conf->prefixlen == 255) {
355                 for (res = conf->addrinfo; res; res = res->ai_next)
356                     if ((a4 && res->ai_family == AF_INET &&
357                          !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
358                         (sa6 && res->ai_family == AF_INET6 &&
359                          !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
360                         return conf;
361             } else {
362                 res = conf->addrinfo;
363                 if (res &&
364                     ((a4 && res->ai_family == AF_INET &&
365                       prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
366                      (sa6 && res->ai_family == AF_INET6 &&
367                       prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
368                     return conf;
369             }
370         }
371         return NULL;
372     }
373
374     for (entry = list_first(confs); entry; entry = list_next(entry)) {  
375         conf = (struct clsrvconf *)entry->data;
376         if (conf->type == type) {
377             if (conf->prefixlen == 255) {
378                 for (res = conf->addrinfo; res; res = res->ai_next)
379                     if ((a4 && res->ai_family == AF_INET &&
380                          !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
381                         (sa6 && res->ai_family == AF_INET6 &&
382                          !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
383                         return conf;
384             } else {
385                 res = conf->addrinfo;
386                 if (res &&
387                     ((a4 && res->ai_family == AF_INET &&
388                       prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) ||
389                      (sa6 && res->ai_family == AF_INET6 &&
390                       prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen))))
391                     return conf;
392             }
393         }
394     }    
395     return NULL;
396 }
397
398 struct replyq *newreplyq() {
399     struct replyq *replyq;
400     
401     replyq = malloc(sizeof(struct replyq));
402     if (!replyq)
403         debugx(1, DBG_ERR, "malloc failed");
404     replyq->replies = list_create();
405     if (!replyq->replies)
406         debugx(1, DBG_ERR, "malloc failed");
407     pthread_mutex_init(&replyq->mutex, NULL);
408     pthread_cond_init(&replyq->cond, NULL);
409     return replyq;
410 }
411
412 struct client *addclient(struct clsrvconf *conf) {
413     struct client *new = malloc(sizeof(struct client));
414     
415     if (!new) {
416         debug(DBG_ERR, "malloc failed");
417         return NULL;
418     }
419     if (!conf->clients) {
420         conf->clients = list_create();
421         if (!conf->clients) {
422             debug(DBG_ERR, "malloc failed");
423             return NULL;
424         }
425     }
426     
427     memset(new, 0, sizeof(struct client));
428     new->conf = conf;
429     new->replyq = conf->type == 'T' ? newreplyq() : udp_server_replyq;
430
431     list_push(conf->clients, new);
432     return new;
433 }
434
435 void removeclient(struct client *client) {
436     if (!client || !client->conf->clients)
437         return;
438
439     list_removedata(client->conf->clients, client);
440     free(client);
441 }
442
443 void addserver(struct clsrvconf *conf) {
444     if (conf->servers)
445         debugx(1, DBG_ERR, "addserver: currently works with just one server per conf");
446     
447     conf->servers = malloc(sizeof(struct server));
448     if (!conf->servers)
449         debugx(1, DBG_ERR, "malloc failed");
450     memset(conf->servers, 0, sizeof(struct server));
451     conf->servers->conf = conf;
452
453     if (conf->type == 'U') {
454         if (!srcudpres)
455             srcudpres = resolve_hostport('U', options.sourceudp, NULL);
456         switch (conf->addrinfo->ai_family) {
457         case AF_INET:
458             if (udp_client4_sock < 0) {
459                 udp_client4_sock = bindtoaddr(srcudpres->addrinfo, AF_INET, 0, 1);
460                 if (udp_client4_sock < 0)
461                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
462             }
463             conf->servers->sock = udp_client4_sock;
464             break;
465         case AF_INET6:
466             if (udp_client6_sock < 0) {
467                 udp_client6_sock = bindtoaddr(srcudpres->addrinfo, AF_INET6, 0, 1);
468                 if (udp_client6_sock < 0)
469                     debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host);
470             }
471             conf->servers->sock = udp_client6_sock;
472             break;
473         default:
474             debugx(1, DBG_ERR, "addserver: unsupported address family");
475         }
476         
477     } else {
478         if (!srctcpres)
479             srctcpres = resolve_hostport('T', options.sourcetcp, NULL);
480         conf->servers->sock = -1;
481     }
482     
483     pthread_mutex_init(&conf->servers->lock, NULL);
484     conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request));
485     if (!conf->servers->requests)
486         debugx(1, DBG_ERR, "malloc failed");
487     conf->servers->newrq = 0;
488     pthread_mutex_init(&conf->servers->newrq_mutex, NULL);
489     pthread_cond_init(&conf->servers->newrq_cond, NULL);
490 }
491
492 /* exactly one of client and server must be non-NULL */
493 /* should probably take peer list (client(s) or server(s)) as argument instead */
494 /* if *peer == NULL we return who we received from, else require it to be from peer */
495 /* return from in sa if not NULL */
496 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
497     int cnt, len;
498     unsigned char buf[65536], *rad;
499     struct sockaddr_storage from;
500     socklen_t fromlen = sizeof(from);
501     struct clsrvconf *p;
502     struct list_node *node;
503     
504     for (;;) {
505         cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
506         if (cnt == -1) {
507             debug(DBG_WARN, "radudpget: recv failed");
508             continue;
509         }
510         debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
511
512         if (cnt < 20) {
513             debug(DBG_WARN, "radudpget: packet too small");
514             continue;
515         }
516     
517         len = RADLEN(buf);
518         if (len < 20) {
519             debug(DBG_WARN, "radudpget: length too small");
520             continue;
521         }
522
523         if (cnt < len) {
524             debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
525             continue;
526         }
527         if (cnt > len)
528             debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
529
530         if (client)
531             if (*client)
532                 p = find_conf('U', (struct sockaddr *)&from, NULL, (*client)->conf);
533             else
534                 p = find_conf('U', (struct sockaddr *)&from, clconfs, NULL);
535         else
536             if (*server)
537                 p = find_conf('U', (struct sockaddr *)&from, NULL, (*server)->conf);
538             else
539                 p = find_conf('U', (struct sockaddr *)&from, srvconfs, NULL);
540
541         if (!p) {
542             debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
543             continue;
544         }
545         
546         rad = malloc(len);
547         if (!rad) {
548             debug(DBG_ERR, "radudpget: malloc failed");
549             continue;
550         }
551         
552         if (client && !*client) {
553             node = list_first(p->clients);
554             *client = node ? (struct client *)node->data : addclient(p);
555             if (!*client) {
556                 free(rad);
557                 continue;
558             }
559         } else if (server && !*server)
560             *server = p->servers;
561         
562         break;
563     }
564     memcpy(rad, buf, len);
565     if (sa)
566         *sa = from;
567     return rad;
568 }
569
570 int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {
571     int loc, i, l, n, r = 0;
572     char *v;
573     X509_EXTENSION *ex;
574     STACK_OF(GENERAL_NAME) *alt;
575     GENERAL_NAME *gn;
576     
577     debug(DBG_DBG, "subjectaltnameaddr");
578     
579     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
580     if (loc < 0)
581         return r;
582     
583     ex = X509_get_ext(cert, loc);
584     alt = X509V3_EXT_d2i(ex);
585     if (!alt)
586         return r;
587     
588     n = sk_GENERAL_NAME_num(alt);
589     for (i = 0; i < n; i++) {
590         gn = sk_GENERAL_NAME_value(alt, i);
591         if (gn->type != GEN_IPADD)
592             continue;
593         r = -1;
594         v = (char *)ASN1_STRING_data(gn->d.ia5);
595         l = ASN1_STRING_length(gn->d.ia5);
596         if (((family == AF_INET && l == sizeof(struct in_addr)) || (family == AF_INET6 && l == sizeof(struct in6_addr)))
597             && !memcmp(v, &addr, l)) {
598             r = 1;
599             break;
600         }
601     }
602     GENERAL_NAMES_free(alt);
603     return r;
604 }
605
606 int subjectaltnameregexp(X509 *cert, int type, char *exact,  regex_t *regex) {
607     int loc, i, l, n, r = 0;
608     char *s, *v;
609     X509_EXTENSION *ex;
610     STACK_OF(GENERAL_NAME) *alt;
611     GENERAL_NAME *gn;
612     
613     debug(DBG_DBG, "subjectaltnameregexp");
614     
615     loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
616     if (loc < 0)
617         return r;
618     
619     ex = X509_get_ext(cert, loc);
620     alt = X509V3_EXT_d2i(ex);
621     if (!alt)
622         return r;
623     
624     n = sk_GENERAL_NAME_num(alt);
625     for (i = 0; i < n; i++) {
626         gn = sk_GENERAL_NAME_value(alt, i);
627         if (gn->type != type)
628             continue;
629         r = -1;
630         v = (char *)ASN1_STRING_data(gn->d.ia5);
631         l = ASN1_STRING_length(gn->d.ia5);
632         if (l <= 0)
633             continue;
634 #ifdef DEBUG
635         printfchars(NULL, gn->type == GEN_DNS ? "dns" : "uri", NULL, v, l);
636 #endif  
637         if (exact) {
638             if (memcmp(v, exact, l))
639                 continue;
640         } else {
641             s = stringcopy((char *)v, l);
642             if (!s) {
643                 debug(DBG_ERR, "malloc failed");
644                 continue;
645             }
646             if (regexec(regex, s, 0, NULL, 0)) {
647                 free(s);
648                 continue;
649             }
650             free(s);
651         }
652         r = 1;
653         break;
654     }
655     GENERAL_NAMES_free(alt);
656     return r;
657 }
658
659 int tlsverifycert(SSL *ssl, struct clsrvconf *conf) {
660     int l, loc, r;
661     X509 *cert;
662     X509_NAME *nm;
663     X509_NAME_ENTRY *e;
664     ASN1_STRING *s;
665     char *v;
666     uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
667     unsigned long error;
668     struct in6_addr addr;
669     
670     if (SSL_get_verify_result(ssl) != X509_V_OK) {
671         debug(DBG_ERR, "tlsverifycert: basic validation failed");
672         while ((error = ERR_get_error()))
673             debug(DBG_ERR, "tlsverifycert: TLS: %s", ERR_error_string(error, NULL));
674         return 0;
675     }
676
677     cert = SSL_get_peer_certificate(ssl);
678     if (!cert) {
679         debug(DBG_ERR, "tlsverifycert: failed to obtain certificate");
680         return 0;
681     }
682
683     if (conf->prefixlen == 255) {
684         if (inet_pton(AF_INET, conf->host, &addr))
685             type = AF_INET;
686         else if (inet_pton(AF_INET6, conf->host, &addr))
687             type = AF_INET6;
688
689         r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, conf->host, NULL);
690         if (r) {
691             if (r < 0) {
692                 X509_free(cert);
693                 debug(DBG_DBG, "tlsverifycert: No subjectaltname matching %s %s", type ? "address" : "host", conf->host);
694                 return 0;
695             }
696             debug(DBG_DBG, "tlsverifycert: Found subjectaltname matching %s %s", type ? "address" : "host", conf->host);
697         } else {
698             nm = X509_get_subject_name(cert);
699             loc = -1;
700             for (;;) {
701                 loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
702                 if (loc == -1)
703                     break;
704                 e = X509_NAME_get_entry(nm, loc);
705                 s = X509_NAME_ENTRY_get_data(e);
706                 v = (char *) ASN1_STRING_data(s);
707                 l = ASN1_STRING_length(s);
708                 if (l < 0)
709                     continue;
710 #ifdef DEBUG
711                 printfchars(NULL, "cn", NULL, v, l);
712 #endif      
713                 if (l == strlen(conf->host) && !strncasecmp(conf->host, v, l)) {
714                     r = 1;
715                     debug(DBG_DBG, "tlsverifycert: Found cn matching host %s", conf->host);
716                     break;
717                 }
718             }
719             if (!r) {
720                 X509_free(cert);
721                 debug(DBG_ERR, "tlsverifycert: cn not matching host %s", conf->host);
722                 return 0;
723             }
724         }
725     }
726     if (conf->certuriregex) {
727         r = subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex);
728         if (r < 1) {
729             debug(DBG_DBG, "tlsverifycert: subjectaltname URI not matching regex");
730             X509_free(cert);
731             return 0;
732         }
733         debug(DBG_DBG, "tlsverifycert: subjectaltname URI matching regex");
734     }
735     X509_free(cert);
736     return 1;
737 }
738
739 void tlsconnect(struct server *server, struct timeval *when, char *text) {
740     struct timeval now;
741     time_t elapsed;
742
743     debug(DBG_DBG, "tlsconnect called from %s", text);
744     pthread_mutex_lock(&server->lock);
745     if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
746         /* already reconnected, nothing to do */
747         debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
748         pthread_mutex_unlock(&server->lock);
749         return;
750     }
751
752     debug(DBG_DBG, "tlsconnect %s", text);
753
754     for (;;) {
755         gettimeofday(&now, NULL);
756         elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
757         if (server->connectionok) {
758             server->connectionok = 0;
759             sleep(10);
760         } else if (elapsed < 5)
761             sleep(10);
762         else if (elapsed < 300) {
763             debug(DBG_INFO, "tlsconnect: sleeping %lds", elapsed);
764             sleep(elapsed);
765         } else if (elapsed < 100000) {
766             debug(DBG_INFO, "tlsconnect: sleeping %ds", 600);
767             sleep(600);
768         } else
769             server->lastconnecttry.tv_sec = now.tv_sec;  /* no sleep at startup */
770         debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->conf->host, server->conf->port);
771         if (server->sock >= 0)
772             close(server->sock);
773         if ((server->sock = connecttcp(server->conf->addrinfo)) < 0) {
774             debug(DBG_ERR, "tlsconnect: connecttcp failed");
775             continue;
776         }
777         
778         SSL_free(server->ssl);
779         server->ssl = SSL_new(server->conf->ssl_ctx);
780         SSL_set_fd(server->ssl, server->sock);
781         if (SSL_connect(server->ssl) > 0 && tlsverifycert(server->ssl, server->conf))
782             break;
783     }
784     debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
785     gettimeofday(&server->lastconnecttry, NULL);
786     pthread_mutex_unlock(&server->lock);
787 }
788
789 unsigned char *radtlsget(SSL *ssl) {
790     int cnt, total, len;
791     unsigned char buf[4], *rad;
792
793     for (;;) {
794         for (total = 0; total < 4; total += cnt) {
795             cnt = SSL_read(ssl, buf + total, 4 - total);
796             if (cnt <= 0) {
797                 debug(DBG_ERR, "radtlsget: connection lost");
798                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
799                     /* remote end sent close_notify, send one back */
800                     SSL_shutdown(ssl);
801                 }
802                 return NULL;
803             }
804         }
805
806         len = RADLEN(buf);
807         rad = malloc(len);
808         if (!rad) {
809             debug(DBG_ERR, "radtlsget: malloc failed");
810             continue;
811         }
812         memcpy(rad, buf, 4);
813
814         for (; total < len; total += cnt) {
815             cnt = SSL_read(ssl, rad + total, len - total);
816             if (cnt <= 0) {
817                 debug(DBG_ERR, "radtlsget: connection lost");
818                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
819                     /* remote end sent close_notify, send one back */
820                     SSL_shutdown(ssl);
821                 }
822                 free(rad);
823                 return NULL;
824             }
825         }
826     
827         if (total >= 20)
828             break;
829         
830         free(rad);
831         debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
832     }
833     
834     debug(DBG_DBG, "radtlsget: got %d bytes", total);
835     return rad;
836 }
837
838 int clientradput(struct server *server, unsigned char *rad) {
839     int cnt;
840     size_t len;
841     unsigned long error;
842     struct timeval lastconnecttry;
843     struct clsrvconf *conf = server->conf;
844     
845     len = RADLEN(rad);
846     if (conf->type == 'U') {
847         if (sendto(server->sock, rad, len, 0, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen) >= 0) {
848             debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, conf->host, conf->port);
849             return 1;
850         }
851         debug(DBG_WARN, "clientradput: send failed");
852         return 0;
853     }
854
855     lastconnecttry = server->lastconnecttry;
856     while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
857         while ((error = ERR_get_error()))
858             debug(DBG_ERR, "clientradput: TLS: %s", ERR_error_string(error, NULL));
859         tlsconnect(server, &lastconnecttry, "clientradput");
860         lastconnecttry = server->lastconnecttry;
861     }
862
863     server->connectionok = 1;
864     debug(DBG_DBG, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s", cnt, len, conf->host);
865     return 1;
866 }
867
868 int radsign(unsigned char *rad, unsigned char *sec) {
869     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
870     static unsigned char first = 1;
871     static EVP_MD_CTX mdctx;
872     unsigned int md_len;
873     int result;
874     
875     pthread_mutex_lock(&lock);
876     if (first) {
877         EVP_MD_CTX_init(&mdctx);
878         first = 0;
879     }
880
881     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
882         EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
883         EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
884         EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
885         md_len == 16);
886     pthread_mutex_unlock(&lock);
887     return result;
888 }
889
890 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
891     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
892     static unsigned char first = 1;
893     static EVP_MD_CTX mdctx;
894     unsigned char hash[EVP_MAX_MD_SIZE];
895     unsigned int len;
896     int result;
897     
898     pthread_mutex_lock(&lock);
899     if (first) {
900         EVP_MD_CTX_init(&mdctx);
901         first = 0;
902     }
903
904     len = RADLEN(rad);
905     
906     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
907               EVP_DigestUpdate(&mdctx, rad, 4) &&
908               EVP_DigestUpdate(&mdctx, reqauth, 16) &&
909               (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
910               EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
911               EVP_DigestFinal_ex(&mdctx, hash, &len) &&
912               len == 16 &&
913               !memcmp(hash, rad + 4, 16));
914     pthread_mutex_unlock(&lock);
915     return result;
916 }
917               
918 int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
919     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
920     static unsigned char first = 1;
921     static HMAC_CTX hmacctx;
922     unsigned int md_len;
923     uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
924     
925     pthread_mutex_lock(&lock);
926     if (first) {
927         HMAC_CTX_init(&hmacctx);
928         first = 0;
929     }
930
931     memcpy(auth, authattr, 16);
932     memset(authattr, 0, 16);
933     md_len = 0;
934     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
935     HMAC_Update(&hmacctx, rad, RADLEN(rad));
936     HMAC_Final(&hmacctx, hash, &md_len);
937     memcpy(authattr, auth, 16);
938     if (md_len != 16) {
939         debug(DBG_WARN, "message auth computation failed");
940         pthread_mutex_unlock(&lock);
941         return 0;
942     }
943
944     if (memcmp(auth, hash, 16)) {
945         debug(DBG_WARN, "message authenticator, wrong value");
946         pthread_mutex_unlock(&lock);
947         return 0;
948     }   
949         
950     pthread_mutex_unlock(&lock);
951     return 1;
952 }
953
954 int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secret) {
955     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
956     static unsigned char first = 1;
957     static HMAC_CTX hmacctx;
958     unsigned int md_len;
959
960     if (!authattrval)
961         return 1;
962     
963     pthread_mutex_lock(&lock);
964     if (first) {
965         HMAC_CTX_init(&hmacctx);
966         first = 0;
967     }
968
969     memset(authattrval, 0, 16);
970     md_len = 0;
971     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
972     HMAC_Update(&hmacctx, rad, RADLEN(rad));
973     HMAC_Final(&hmacctx, authattrval, &md_len);
974     if (md_len != 16) {
975         debug(DBG_WARN, "message auth computation failed");
976         pthread_mutex_unlock(&lock);
977         return 0;
978     }
979
980     pthread_mutex_unlock(&lock);
981     return 1;
982 }
983
984 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
985     while (length > 1) {
986         if (ATTRTYPE(attrs) == type)
987             return attrs;
988         length -= ATTRLEN(attrs);
989         attrs += ATTRLEN(attrs);
990     }
991     return NULL;
992 }
993
994 void freerqdata(struct request *rq) {
995     if (rq->origusername)
996         free(rq->origusername);
997     if (rq->buf)
998         free(rq->buf);
999 }
1000
1001 void sendrq(struct server *to, struct request *rq) {
1002     int i;
1003     uint8_t *attr;
1004
1005     pthread_mutex_lock(&to->newrq_mutex);
1006     /* might simplify if only try nextid, might be ok */
1007     for (i = to->nextid; i < MAX_REQUESTS; i++)
1008         if (!to->requests[i].buf)
1009             break;
1010     if (i == MAX_REQUESTS) {
1011         for (i = 0; i < to->nextid; i++)
1012             if (!to->requests[i].buf)
1013                 break;
1014         if (i == to->nextid) {
1015             debug(DBG_WARN, "No room in queue, dropping request");
1016             freerqdata(rq);
1017             pthread_mutex_unlock(&to->newrq_mutex);
1018             return;
1019         }
1020     }
1021     
1022     rq->buf[1] = (char)i;
1023
1024     attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
1025     if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->conf->secret)) {
1026         freerqdata(rq);
1027         pthread_mutex_unlock(&to->newrq_mutex);
1028         return;
1029     }
1030
1031     debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host);
1032     to->requests[i] = *rq;
1033     to->nextid = i + 1;
1034
1035     if (!to->newrq) {
1036         to->newrq = 1;
1037         debug(DBG_DBG, "signalling client writer");
1038         pthread_cond_signal(&to->newrq_cond);
1039     }
1040     pthread_mutex_unlock(&to->newrq_mutex);
1041 }
1042
1043 void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
1044     struct reply *reply;
1045     uint8_t first;
1046     
1047     if (!radsign(buf, (unsigned char *)to->conf->secret)) {
1048         free(buf);
1049         debug(DBG_WARN, "sendreply: failed to sign message");
1050         return;
1051     }
1052
1053     reply = malloc(sizeof(struct reply));
1054     if (!reply) {
1055         free(buf);
1056         debug(DBG_ERR, "sendreply: malloc failed");
1057         return;
1058     }
1059     memset(reply, 0, sizeof(struct reply));
1060     reply->buf = buf;
1061     if (tosa)
1062         reply->tosa = *tosa;
1063     
1064     pthread_mutex_lock(&to->replyq->mutex);
1065
1066     first = list_first(to->replyq->replies) == NULL;
1067     
1068     if (!list_push(to->replyq->replies, reply)) {
1069         pthread_mutex_unlock(&to->replyq->mutex);
1070         free(reply);
1071         free(buf);
1072         debug(DBG_ERR, "sendreply: malloc failed");
1073         return;
1074     }
1075     
1076     if (first) {
1077         debug(DBG_DBG, "signalling server writer");
1078         pthread_cond_signal(&to->replyq->cond);
1079     }
1080     pthread_mutex_unlock(&to->replyq->mutex);
1081 }
1082
1083 int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1084     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1085     static unsigned char first = 1;
1086     static EVP_MD_CTX mdctx;
1087     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1088     unsigned int md_len;
1089     uint8_t i, offset = 0, out[128];
1090     
1091     pthread_mutex_lock(&lock);
1092     if (first) {
1093         EVP_MD_CTX_init(&mdctx);
1094         first = 0;
1095     }
1096
1097     input = auth;
1098     for (;;) {
1099         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1100             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1101             !EVP_DigestUpdate(&mdctx, input, 16) ||
1102             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1103             md_len != 16) {
1104             pthread_mutex_unlock(&lock);
1105             return 0;
1106         }
1107         for (i = 0; i < 16; i++)
1108             out[offset + i] = hash[i] ^ in[offset + i];
1109         input = out + offset - 16;
1110         offset += 16;
1111         if (offset == len)
1112             break;
1113     }
1114     memcpy(in, out, len);
1115     pthread_mutex_unlock(&lock);
1116     return 1;
1117 }
1118
1119 int pwddecrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
1120     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1121     static unsigned char first = 1;
1122     static EVP_MD_CTX mdctx;
1123     unsigned char hash[EVP_MAX_MD_SIZE], *input;
1124     unsigned int md_len;
1125     uint8_t i, offset = 0, out[128];
1126     
1127     pthread_mutex_lock(&lock);
1128     if (first) {
1129         EVP_MD_CTX_init(&mdctx);
1130         first = 0;
1131     }
1132
1133     input = auth;
1134     for (;;) {
1135         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1136             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
1137             !EVP_DigestUpdate(&mdctx, input, 16) ||
1138             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1139             md_len != 16) {
1140             pthread_mutex_unlock(&lock);
1141             return 0;
1142         }
1143         for (i = 0; i < 16; i++)
1144             out[offset + i] = hash[i] ^ in[offset + i];
1145         input = in + offset;
1146         offset += 16;
1147         if (offset == len)
1148             break;
1149     }
1150     memcpy(in, out, len);
1151     pthread_mutex_unlock(&lock);
1152     return 1;
1153 }
1154
1155 int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1156     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1157     static unsigned char first = 1;
1158     static EVP_MD_CTX mdctx;
1159     unsigned char hash[EVP_MAX_MD_SIZE];
1160     unsigned int md_len;
1161     uint8_t i, offset;
1162     
1163     pthread_mutex_lock(&lock);
1164     if (first) {
1165         EVP_MD_CTX_init(&mdctx);
1166         first = 0;
1167     }
1168
1169 #if 0
1170     printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16);
1171     printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2);
1172     printfchars(NULL, "msppencrypt in", "%02x ", text, len);
1173 #endif
1174     
1175     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1176         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1177         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1178         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1179         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1180         pthread_mutex_unlock(&lock);
1181         return 0;
1182     }
1183
1184 #if 0    
1185     printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1186 #endif
1187     
1188     for (i = 0; i < 16; i++)
1189         text[i] ^= hash[i];
1190     
1191     for (offset = 16; offset < len; offset += 16) {
1192 #if 0   
1193         printf("text + offset - 16 c(%d): ", offset / 16);
1194         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1195 #endif
1196         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1197             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1198             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1199             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1200             md_len != 16) {
1201             pthread_mutex_unlock(&lock);
1202             return 0;
1203         }
1204 #if 0
1205         printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
1206 #endif    
1207         
1208         for (i = 0; i < 16; i++)
1209             text[offset + i] ^= hash[i];
1210     }
1211     
1212 #if 0
1213     printfchars(NULL, "msppencrypt out", "%02x ", text, len);
1214 #endif
1215
1216     pthread_mutex_unlock(&lock);
1217     return 1;
1218 }
1219
1220 int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
1221     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
1222     static unsigned char first = 1;
1223     static EVP_MD_CTX mdctx;
1224     unsigned char hash[EVP_MAX_MD_SIZE];
1225     unsigned int md_len;
1226     uint8_t i, offset;
1227     char plain[255];
1228     
1229     pthread_mutex_lock(&lock);
1230     if (first) {
1231         EVP_MD_CTX_init(&mdctx);
1232         first = 0;
1233     }
1234
1235 #if 0
1236     printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16);
1237     printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2);
1238     printfchars(NULL, "msppdecrypt in", "%02x ", text, len);
1239 #endif
1240     
1241     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1242         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1243         !EVP_DigestUpdate(&mdctx, auth, 16) ||
1244         !EVP_DigestUpdate(&mdctx, salt, 2) ||
1245         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
1246         pthread_mutex_unlock(&lock);
1247         return 0;
1248     }
1249
1250 #if 0    
1251     printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1252 #endif
1253     
1254     for (i = 0; i < 16; i++)
1255         plain[i] = text[i] ^ hash[i];
1256     
1257     for (offset = 16; offset < len; offset += 16) {
1258 #if 0   
1259         printf("text + offset - 16 c(%d): ", offset / 16);
1260         printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
1261 #endif
1262         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
1263             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
1264             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
1265             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
1266             md_len != 16) {
1267             pthread_mutex_unlock(&lock);
1268             return 0;
1269         }
1270 #if 0
1271         printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
1272 #endif    
1273
1274         for (i = 0; i < 16; i++)
1275             plain[offset + i] = text[offset + i] ^ hash[i];
1276     }
1277
1278     memcpy(text, plain, len);
1279 #if 0
1280     printfchars(NULL, "msppdecrypt out", "%02x ", text, len);
1281 #endif
1282
1283     pthread_mutex_unlock(&lock);
1284     return 1;
1285 }
1286
1287 struct realm *id2realm(char *id, uint8_t len) {
1288     struct list_node *entry;
1289     struct realm *realm;
1290     
1291     for (entry = list_first(realms); entry; entry = list_next(entry)) {
1292         realm = (struct realm *)entry->data;
1293         if (!regexec(&realm->regex, id, 0, NULL, 0)) {
1294             debug(DBG_DBG, "found matching realm: %s", realm->name);
1295             return realm;
1296         }
1297     }
1298     return NULL;
1299 }
1300
1301 int rqinqueue(struct server *to, struct client *from, uint8_t id) {
1302     int i;
1303     
1304     pthread_mutex_lock(&to->newrq_mutex);
1305     for (i = 0; i < MAX_REQUESTS; i++)
1306         if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from)
1307             break;
1308     pthread_mutex_unlock(&to->newrq_mutex);
1309     
1310     return i < MAX_REQUESTS;
1311 }
1312
1313 int attrvalidate(unsigned char *attrs, int length) {
1314     while (length > 1) {
1315         if (ATTRLEN(attrs) < 2) {
1316             debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1317             return 0;
1318         }
1319         length -= ATTRLEN(attrs);
1320         if (length < 0) {
1321             debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1322             return 0;
1323         }
1324         attrs += ATTRLEN(attrs);
1325     }
1326     if (length)
1327         debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1328     return 1;
1329 }
1330
1331 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1332     if (len < 16 || len > 128 || len % 16) {
1333         debug(DBG_WARN, "pwdrecrypt: invalid password length");
1334         return 0;
1335     }
1336         
1337     if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1338         debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1339         return 0;
1340     }
1341 #ifdef DEBUG
1342     printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len);
1343 #endif  
1344     if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1345         debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1346         return 0;
1347     }
1348     return 1;
1349 }
1350
1351 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1352     if (len < 18)
1353         return 0;
1354     if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1355         debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1356         return 0;
1357     }
1358     if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1359         debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1360         return 0;
1361     }
1362     return 1;
1363 }
1364
1365 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1366            char *oldsecret, char *newsecret) {
1367     unsigned char *attr;
1368     
1369     for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1370         debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1371         if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1372             return 0;
1373     }
1374     return 1;
1375 }
1376
1377 /* returns a pointer to the resized attribute value */
1378 uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) {
1379     uint8_t *attrs, *attr, vallen;
1380     uint16_t len;
1381     unsigned char *new;
1382     
1383     len = RADLEN(*buf) - 20;
1384     attrs = *buf + 20;
1385
1386     attr = attrget(attrs, len, type);
1387     if (!attr)
1388         return NULL;
1389     
1390     vallen = ATTRVALLEN(attr);
1391     if (vallen == newvallen)
1392         return attr + 2;
1393
1394     len += newvallen - vallen;
1395     if (newvallen > vallen) {
1396         new = realloc(*buf, len);
1397         if (!new) {
1398             debug(DBG_ERR, "resizeattr: malloc failed");
1399             return NULL;
1400         }
1401         if (new != *buf) {
1402             attr += new - *buf;
1403             attrs = new + 20;
1404             *buf = new;
1405         }
1406     }
1407     memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen));
1408     attr[1] = newvallen + 2;
1409     ((uint16_t *)*buf)[1] = htons(len + 20);
1410     return attr + 2;
1411 }
1412                 
1413 int rewriteusername(struct request *rq, char *in) {
1414     size_t nmatch = 10, reslen = 0, start = 0;
1415     regmatch_t pmatch[10], *pfield;
1416     int i;
1417     unsigned char *result;
1418     char *out = rq->from->conf->rewriteattrreplacement;
1419     
1420     if (regexec(rq->from->conf->rewriteattrregex, in, nmatch, pmatch, 0)) {
1421         debug(DBG_DBG, "rewriteattr: username not matching, no rewrite");
1422         return 1;
1423     }
1424     
1425     rq->origusername = stringcopy(in, 0);
1426     if (!rq->origusername)
1427         return 0;
1428     
1429     for (i = start; out[i]; i++) {
1430         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1431             pfield = &pmatch[out[i + 1] - '0'];
1432             if (pfield->rm_so >= 0) {
1433                 reslen += i - start + pfield->rm_eo - pfield->rm_so;
1434                 start = i + 2;
1435             }
1436             i++;
1437         }
1438     }
1439     reslen += i - start;
1440
1441     result = resizeattr(&rq->buf, reslen, RAD_Attr_User_Name);
1442     if (!result)
1443         return 0;
1444     
1445     start = 0;
1446     reslen = 0;
1447     for (i = start; out[i]; i++) {
1448         if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') {
1449             pfield = &pmatch[out[i + 1] - '0'];
1450             if (pfield->rm_so >= 0) {
1451                 memcpy(result + reslen, out + start, i - start);
1452                 reslen += i - start;
1453                 memcpy(result + reslen, in + pfield->rm_so, pfield->rm_eo - pfield->rm_so);
1454                 reslen += pfield->rm_eo - pfield->rm_so;
1455                 start = i + 2;
1456             }
1457             i++;
1458         }
1459     }
1460
1461     memcpy(result + reslen, out + start, i - start);
1462     reslen += i - start;
1463     memcpy(in, result, reslen);
1464     in[reslen] = '\0';
1465     return 1;
1466 }
1467
1468 void acclog(unsigned char *attrs, int length, char *host) {
1469     unsigned char *attr;
1470     char username[256];
1471     
1472     attr = attrget(attrs, length, RAD_Attr_User_Name);
1473     if (!attr) {
1474         debug(DBG_INFO, "acclog: accounting-request from %s without username attribute", host);
1475         return;
1476     }
1477     memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1478     username[ATTRVALLEN(attr)] = '\0';
1479     debug(DBG_INFO, "acclog: accounting-request from %s with username: %s", host, username);
1480 }
1481         
1482 void respondaccounting(struct request *rq) {
1483     unsigned char *resp;
1484
1485     resp = malloc(20);
1486     if (!resp) {
1487         debug(DBG_ERR, "respondstatusserver: malloc failed");
1488         return;
1489     }
1490     memcpy(resp, rq->buf, 20);
1491     resp[0] = RAD_Accounting_Response;
1492     resp[2] = 0;
1493     resp[3] = 20;
1494     debug(DBG_DBG, "respondaccounting: responding to %s", rq->from->conf->host);
1495     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1496 }
1497
1498 void respondstatusserver(struct request *rq) {
1499     unsigned char *resp;
1500
1501     resp = malloc(20);
1502     if (!resp) {
1503         debug(DBG_ERR, "respondstatusserver: malloc failed");
1504         return;
1505     }
1506     memcpy(resp, rq->buf, 20);
1507     resp[0] = RAD_Access_Accept;
1508     resp[2] = 0;
1509     resp[3] = 20;
1510     debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
1511     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1512 }
1513
1514 void respondreject(struct request *rq, char *message) {
1515     unsigned char *resp;
1516     int len = 20;
1517
1518     if (message && *message)
1519         len += 2 + strlen(message);
1520     
1521     resp = malloc(len);
1522     if (!resp) {
1523         debug(DBG_ERR, "respondreject: malloc failed");
1524         return;
1525     }
1526     memcpy(resp, rq->buf, 20);
1527     resp[0] = RAD_Access_Reject;
1528     *(uint16_t *)(resp + 2) = htons(len);
1529     if (message && *message) {
1530         resp[20] = RAD_Attr_Reply_Message;
1531         resp[21] = len - 20;
1532         memcpy(resp + 22, message, len - 22);
1533     }
1534     sendreply(rq->from, resp, rq->from->conf->type == 'U' ? &rq->fromsa : NULL);
1535 }
1536
1537 struct server *realm2server(struct realm *realm) {
1538     struct list_node *entry;
1539     struct server *server, *best = NULL;
1540     
1541     for (entry = list_first(realm->srvconfs); entry; entry = list_next(entry)) {
1542         server = ((struct clsrvconf *)entry->data)->servers;
1543         if (!server->connectionok)
1544             continue;
1545         if (!server->loststatsrv)
1546             return server;
1547         if (!best) {
1548             best = server;
1549             continue;
1550         }
1551         if (server->loststatsrv < best->loststatsrv)
1552             best = server;
1553     }
1554     return best;
1555 }
1556
1557 void radsrv(struct request *rq) {
1558     uint8_t code, id, *auth, *attrs, *attr;
1559     uint16_t len;
1560     struct server *to = NULL;
1561     char username[256];
1562     unsigned char newauth[16];
1563     struct realm *realm = NULL;
1564     
1565     code = *(uint8_t *)rq->buf;
1566     id = *(uint8_t *)(rq->buf + 1);
1567     len = RADLEN(rq->buf);
1568     auth = (uint8_t *)(rq->buf + 4);
1569
1570     debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
1571     
1572     if (code != RAD_Access_Request && code != RAD_Status_Server && code != RAD_Accounting_Request) {
1573         debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring");
1574         freerqdata(rq);
1575         return;
1576     }
1577
1578     len -= 20;
1579     attrs = rq->buf + 20;
1580
1581     if (!attrvalidate(attrs, len)) {
1582         debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
1583         freerqdata(rq);
1584         return;
1585     }
1586
1587     attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1588     if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(rq->buf, ATTRVAL(attr), rq->from->conf->secret))) {
1589         debug(DBG_WARN, "radsrv: message authentication failed");
1590         freerqdata(rq);
1591         return;
1592     }
1593
1594     if (code != RAD_Access_Request) {
1595         switch (code) {
1596         case RAD_Accounting_Request:
1597             acclog(attrs, len, rq->from->conf->host);
1598             respondaccounting(rq);
1599             break;
1600         case RAD_Status_Server:
1601             respondstatusserver(rq);
1602             break;
1603         }
1604         freerqdata(rq);
1605         return;
1606     }
1607
1608     /* code == RAD_Access_Request */
1609     attr = attrget(attrs, len, RAD_Attr_User_Name);
1610     if (!attr) {
1611         debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
1612         freerqdata(rq);
1613         return;
1614     }
1615     memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1616     username[ATTRVALLEN(attr)] = '\0';
1617
1618     if (rq->from->conf->rewriteattrregex) {
1619         if (!rewriteusername(rq, username)) {
1620             debug(DBG_WARN, "radsrv: username malloc failed, ignoring request");
1621             freerqdata(rq);
1622             return;
1623         }
1624         len = RADLEN(rq->buf) - 20;
1625         auth = (uint8_t *)(rq->buf + 4);
1626         attrs = rq->buf + 20;
1627     }
1628
1629     if (rq->origusername)
1630         debug(DBG_DBG, "Access Request with username: %s (originally %s)", username, rq->origusername);
1631     else
1632         debug(DBG_DBG, "Access Request with username: %s", username);
1633         
1634     realm = id2realm(username, strlen(username));
1635     if (!realm) {
1636         debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1637         freerqdata(rq);
1638         return;
1639     }
1640         
1641     to = realm2server(realm);
1642     if (to && rqinqueue(to, rq->from, id)) {
1643         debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->conf->host, id);
1644         freerqdata(rq);
1645         return;
1646     }
1647
1648     if (!to) {
1649         if (realm->message) {
1650             debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->conf->host, username);
1651             respondreject(rq, realm->message);
1652         }
1653         freerqdata(rq);
1654         return;
1655     }
1656     
1657     if (!RAND_bytes(newauth, 16)) {
1658         debug(DBG_WARN, "radsrv: failed to generate random auth");
1659         freerqdata(rq);
1660         return;
1661     }
1662
1663 #ifdef DEBUG
1664     printfchars(NULL, "auth", "%02x ", auth, 16);
1665 #endif
1666
1667     attr = attrget(attrs, len, RAD_Attr_User_Password);
1668     if (attr) {
1669         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1670         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1671             freerqdata(rq);
1672             return;
1673         }
1674     }
1675     
1676     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1677     if (attr) {
1678         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1679         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->conf->secret, to->conf->secret, auth, newauth)) {
1680             freerqdata(rq);
1681             return;
1682         }
1683     }
1684
1685     rq->origid = id;
1686     memcpy(rq->origauth, auth, 16);
1687     memcpy(auth, newauth, 16);
1688     sendrq(to, rq);
1689 }
1690
1691 int replyh(struct server *server, unsigned char *buf) {
1692     struct client *from;
1693     struct request *rq;
1694     int i, len, sublen;
1695     unsigned char *messageauth, *subattrs, *attrs, *attr, *username;
1696     struct sockaddr_storage fromsa;
1697     char tmp[256];
1698     
1699     server->connectionok = 1;
1700     server->loststatsrv = 0;
1701         
1702     i = buf[1]; /* i is the id */
1703
1704     switch (*buf) {
1705     case RAD_Access_Accept:
1706         debug(DBG_DBG, "got Access Accept with id %d", i);
1707         break;
1708     case RAD_Access_Reject:
1709         debug(DBG_DBG, "got Access Reject with id %d", i);
1710         break;
1711     case RAD_Access_Challenge:
1712         debug(DBG_DBG, "got Access Challenge with id %d", i);
1713         break;
1714     default:
1715         debug(DBG_INFO, "replyh: discarding, only accept access accept, access reject and access challenge messages");
1716         return 0;
1717     }
1718
1719     rq = server->requests + i;
1720         
1721     pthread_mutex_lock(&server->newrq_mutex);
1722     if (!rq->buf || !rq->tries) {
1723         pthread_mutex_unlock(&server->newrq_mutex);
1724         debug(DBG_INFO, "replyh: no matching request sent with this id, ignoring reply");
1725         return 0;
1726     }
1727
1728     if (rq->received) {
1729         pthread_mutex_unlock(&server->newrq_mutex);
1730         debug(DBG_INFO, "replyh: already received, ignoring reply");
1731         return 0;
1732     }
1733         
1734     if (!validauth(buf, rq->buf + 4, (unsigned char *)server->conf->secret)) {
1735         pthread_mutex_unlock(&server->newrq_mutex);
1736         debug(DBG_WARN, "replyh: invalid auth, ignoring reply");
1737         return 0;
1738     }
1739         
1740     from = rq->from;
1741     len = RADLEN(buf) - 20;
1742     attrs = buf + 20;
1743
1744     if (!attrvalidate(attrs, len)) {
1745         pthread_mutex_unlock(&server->newrq_mutex);
1746         debug(DBG_WARN, "replyh: attribute validation failed, ignoring reply");
1747         return 0;
1748     }
1749         
1750     /* Message Authenticator */
1751     messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1752     if (messageauth) {
1753         if (ATTRVALLEN(messageauth) != 16) {
1754             pthread_mutex_unlock(&server->newrq_mutex);
1755             debug(DBG_WARN, "replyh: illegal message auth attribute length, ignoring reply");
1756             return 0;
1757         }
1758         memcpy(tmp, buf + 4, 16);
1759         memcpy(buf + 4, rq->buf + 4, 16);
1760         if (!checkmessageauth(buf, ATTRVAL(messageauth), server->conf->secret)) {
1761             pthread_mutex_unlock(&server->newrq_mutex);
1762             debug(DBG_WARN, "replyh: message authentication failed, ignoring reply");
1763             return 0;
1764         }
1765         memcpy(buf + 4, tmp, 16);
1766         debug(DBG_DBG, "replyh: message auth ok");
1767     }
1768         
1769     if (*rq->buf == RAD_Status_Server) {
1770         rq->received = 1;
1771         pthread_mutex_unlock(&server->newrq_mutex);
1772         debug(DBG_INFO, "replyh: got status server response from %s", server->conf->host);
1773         return 0;
1774     }
1775
1776     /* MS MPPE */
1777     for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
1778         if (ATTRVALLEN(attr) <= 4)
1779             break;
1780             
1781         if (attr[2] != 0 || attr[3] != 0 || attr[4] != 1 || attr[5] != 55)  /* 311 == MS */
1782             continue;
1783             
1784         sublen = ATTRVALLEN(attr) - 4;
1785         subattrs = ATTRVAL(attr) + 4;  
1786         if (!attrvalidate(subattrs, sublen) ||
1787             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1788                     rq, server->conf->secret, from->conf->secret) ||
1789             !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1790                     rq, server->conf->secret, from->conf->secret))
1791             break;
1792     }
1793     if (attr) {
1794         pthread_mutex_unlock(&server->newrq_mutex);
1795         debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
1796         return 0;
1797     }
1798         
1799     if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject) {
1800         attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_User_Name);
1801         /* we know the attribute exists */
1802         memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
1803         tmp[ATTRVALLEN(attr)] = '\0';
1804         switch (*buf) {
1805         case RAD_Access_Accept:
1806             if (rq->origusername)
1807                 debug(DBG_INFO, "Access Accept for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1808             else
1809                 debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->conf->host);
1810             break;
1811         case RAD_Access_Reject:
1812             if (rq->origusername)
1813                 debug(DBG_INFO, "Access Reject for %s (originally %s) from %s", tmp, rq->origusername, server->conf->host);
1814             else
1815                 debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->conf->host);
1816             break;
1817         }
1818     }
1819         
1820     buf[1] = (char)rq->origid;
1821     memcpy(buf + 4, rq->origauth, 16);
1822 #ifdef DEBUG    
1823     printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
1824 #endif
1825
1826     if (rq->origusername) {
1827         username = resizeattr(&buf, strlen(rq->origusername), RAD_Attr_User_Name);
1828         if (!username) {
1829             pthread_mutex_unlock(&server->newrq_mutex);
1830             debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
1831             return 0;
1832         }
1833         memcpy(username, rq->origusername, strlen(rq->origusername));
1834         len = RADLEN(buf) - 20;
1835         attrs = buf + 20;
1836         if (messageauth)
1837             messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1838     }
1839         
1840     if (messageauth) {
1841         if (!createmessageauth(buf, ATTRVAL(messageauth), from->conf->secret)) {
1842             pthread_mutex_unlock(&server->newrq_mutex);
1843             debug(DBG_WARN, "replyh: failed to create authenticator, malloc failed?, ignoring reply");
1844             return 0;
1845         }
1846         debug(DBG_DBG, "replyh: computed messageauthattr");
1847     }
1848
1849     if (from->conf->type == 'U')
1850         fromsa = rq->fromsa;
1851     /* once we set received = 1, rq may be reused */
1852     rq->received = 1;
1853     pthread_mutex_unlock(&server->newrq_mutex);
1854
1855     debug(DBG_DBG, "replyh: giving packet back to where it came from");
1856     sendreply(from, buf, from->conf->type == 'U' ? &fromsa : NULL);
1857     return 1;
1858 }
1859
1860 void *udpclientrd(void *arg) {
1861     struct server *server;
1862     unsigned char *buf;
1863     int *s = (int *)arg;
1864     
1865     for (;;) {
1866         server = NULL;
1867         buf = radudpget(*s, NULL, &server, NULL);
1868         if (!replyh(server, buf))
1869             free(buf);
1870     }
1871 }
1872
1873 void *tlsclientrd(void *arg) {
1874     struct server *server = (struct server *)arg;
1875     unsigned char *buf;
1876     struct timeval lastconnecttry;
1877     
1878     for (;;) {
1879         /* yes, lastconnecttry is really necessary */
1880         lastconnecttry = server->lastconnecttry;
1881         buf = radtlsget(server->ssl);
1882         if (!buf) {
1883             tlsconnect(server, &lastconnecttry, "clientrd");
1884             continue;
1885         }
1886
1887         if (!replyh(server, buf))
1888             free(buf);
1889     }
1890 }
1891
1892 void *clientwr(void *arg) {
1893     struct server *server = (struct server *)arg;
1894     struct request *rq;
1895     pthread_t tlsclientrdth;
1896     int i;
1897     uint8_t rnd;
1898     struct timeval now, lastsend;
1899     struct timespec timeout;
1900     struct request statsrvrq;
1901     unsigned char statsrvbuf[38];
1902
1903     memset(&timeout, 0, sizeof(struct timespec));
1904     
1905     if (server->conf->statusserver) {
1906         memset(&statsrvrq, 0, sizeof(struct request));
1907         memset(statsrvbuf, 0, sizeof(statsrvbuf));
1908         statsrvbuf[0] = RAD_Status_Server;
1909         statsrvbuf[3] = 38;
1910         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
1911         statsrvbuf[21] = 18;
1912         gettimeofday(&lastsend, NULL);
1913     }
1914     
1915     if (server->conf->type == 'U') {
1916         server->connectionok = 1;
1917     } else {
1918         tlsconnect(server, NULL, "new client");
1919         server->connectionok = 1;
1920         if (pthread_create(&tlsclientrdth, NULL, tlsclientrd, (void *)server))
1921             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
1922     }
1923     
1924     for (;;) {
1925         pthread_mutex_lock(&server->newrq_mutex);
1926         if (!server->newrq) {
1927             gettimeofday(&now, NULL);
1928             if (server->conf->statusserver) {
1929                 /* random 0-7 seconds */
1930                 RAND_bytes(&rnd, 1);
1931                 rnd /= 32;
1932                 if (!timeout.tv_sec || timeout.tv_sec - now.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
1933                     timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
1934             }   
1935             if (timeout.tv_sec) {
1936                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1937                 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1938                 timeout.tv_sec = 0;
1939             } else {
1940                 debug(DBG_DBG, "clientwr: waiting for new request");
1941                 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
1942             }
1943         }
1944         if (server->newrq) {
1945             debug(DBG_DBG, "clientwr: got new request");
1946             server->newrq = 0;
1947         } else
1948             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1949         pthread_mutex_unlock(&server->newrq_mutex);
1950
1951         for (i = 0; i < MAX_REQUESTS; i++) {
1952             pthread_mutex_lock(&server->newrq_mutex);
1953             while (i < MAX_REQUESTS && !server->requests[i].buf)
1954                 i++;
1955             if (i == MAX_REQUESTS) {
1956                 pthread_mutex_unlock(&server->newrq_mutex);
1957                 break;
1958             }
1959             rq = server->requests + i;
1960
1961             if (rq->received) {
1962                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
1963                 if (rq->buf) {
1964                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
1965                     freerqdata(rq);
1966                     /* setting this to NULL means that it can be reused */
1967                     rq->buf = NULL;
1968                 }
1969                 pthread_mutex_unlock(&server->newrq_mutex);
1970                 continue;
1971             }
1972             
1973             gettimeofday(&now, NULL);
1974             if (now.tv_sec < rq->expiry.tv_sec) {
1975                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1976                     timeout.tv_sec = rq->expiry.tv_sec;
1977                 pthread_mutex_unlock(&server->newrq_mutex);
1978                 continue;
1979             }
1980
1981             if (rq->tries == (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1982                               ? 1 : REQUEST_RETRIES)) {
1983                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1984                 if (*rq->buf == RAD_Status_Server) {
1985                     debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->conf->host);
1986                     if (server->loststatsrv < 255)
1987                         server->loststatsrv++;
1988                 }
1989                 freerqdata(rq);
1990                 /* setting this to NULL means that it can be reused */
1991                 rq->buf = NULL;
1992                 pthread_mutex_unlock(&server->newrq_mutex);
1993                 continue;
1994             }
1995             pthread_mutex_unlock(&server->newrq_mutex);
1996
1997             rq->expiry.tv_sec = now.tv_sec +
1998                 (*rq->buf == RAD_Status_Server || server->conf->type == 'T'
1999                  ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
2000             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
2001                 timeout.tv_sec = rq->expiry.tv_sec;
2002             rq->tries++;
2003             clientradput(server, server->requests[i].buf);
2004             gettimeofday(&lastsend, NULL);
2005         }
2006         if (server->conf->statusserver) {
2007             gettimeofday(&now, NULL);
2008             if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
2009                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
2010                     debug(DBG_WARN, "clientwr: failed to generate random auth");
2011                     continue;
2012                 }
2013                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
2014                 if (!statsrvrq.buf) {
2015                     debug(DBG_ERR, "clientwr: malloc failed");
2016                     continue;
2017                 }
2018                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
2019                 debug(DBG_DBG, "clientwr: sending status server to %s", server->conf->host);
2020                 lastsend.tv_sec = now.tv_sec;
2021                 sendrq(server, &statsrvrq);
2022             }
2023         }
2024     }
2025 }
2026
2027 void *udpserverwr(void *arg) {
2028     struct replyq *replyq = udp_server_replyq;
2029     struct reply *reply;
2030     
2031     for (;;) {
2032         pthread_mutex_lock(&replyq->mutex);
2033         while (!(reply = (struct reply *)list_shift(replyq->replies))) {
2034             debug(DBG_DBG, "udp server writer, waiting for signal");
2035             pthread_cond_wait(&replyq->cond, &replyq->mutex);
2036             debug(DBG_DBG, "udp server writer, got signal");
2037         }
2038         pthread_mutex_unlock(&replyq->mutex);
2039
2040         if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
2041                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
2042             debug(DBG_WARN, "sendudp: send failed");
2043         free(reply->buf);
2044         free(reply);
2045     }
2046 }
2047
2048 void *udpserverrd(void *arg) {
2049     struct request rq;
2050     pthread_t udpserverwrth;
2051     struct clsrvconf *listenres;
2052
2053     listenres = resolve_hostport('U', options.listenudp, DEFAULT_UDP_PORT);
2054     if ((udp_server_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2055         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2056
2057     debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
2058           listenres->host ? listenres->host : "*", listenres->port);
2059     free(listenres);
2060     
2061     if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
2062         debugx(1, DBG_ERR, "pthread_create failed");
2063     
2064     for (;;) {
2065         memset(&rq, 0, sizeof(struct request));
2066         rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
2067         radsrv(&rq);
2068     }
2069 }
2070
2071 void *udpaccserverrd(void *arg) {
2072     struct request rq;
2073     struct clsrvconf *listenres;
2074     
2075     listenres = resolve_hostport('U', options.listenaccudp, DEFAULT_UDP_PORT);
2076     if ((udp_accserver_sock = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2077         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
2078
2079     debug(DBG_WARN, "udpaccserverrd: listening for UDP on %s:%s",
2080           listenres->host ? listenres->host : "*", listenres->port);
2081     free(listenres);
2082     
2083     for (;;) {
2084         memset(&rq, 0, sizeof(struct request));
2085         rq.buf = radudpget(udp_accserver_sock, &rq.from, NULL, &rq.fromsa);
2086         if (*(uint8_t *)rq.buf == RAD_Accounting_Request) {
2087             radsrv(&rq);
2088             continue;
2089         }
2090         debug(DBG_INFO, "udpaccserverrd: got something other than accounting-request, ignoring");
2091         freerqdata(&rq);
2092     }
2093 }
2094
2095 void *tlsserverwr(void *arg) {
2096     int cnt;
2097     unsigned long error;
2098     struct client *client = (struct client *)arg;
2099     struct replyq *replyq;
2100     struct reply *reply;
2101     
2102     debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
2103     replyq = client->replyq;
2104     for (;;) {
2105         pthread_mutex_lock(&replyq->mutex);
2106         while (!list_first(replyq->replies)) {
2107             if (client->ssl) {      
2108                 debug(DBG_DBG, "tls server writer, waiting for signal");
2109                 pthread_cond_wait(&replyq->cond, &replyq->mutex);
2110                 debug(DBG_DBG, "tls server writer, got signal");
2111             }
2112             if (!client->ssl) {
2113                 /* ssl might have changed while waiting */
2114                 pthread_mutex_unlock(&replyq->mutex);
2115                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
2116                 pthread_exit(NULL);
2117             }
2118         }
2119         reply = (struct reply *)list_shift(replyq->replies);
2120         pthread_mutex_unlock(&replyq->mutex);
2121         cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
2122         if (cnt > 0)
2123             debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
2124                   cnt, RADLEN(reply->buf));
2125         else
2126             while ((error = ERR_get_error()))
2127                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
2128         free(reply->buf);
2129         free(reply);
2130     }
2131 }
2132
2133 void *tlsserverrd(void *arg) {
2134     struct request rq;
2135     unsigned long error;
2136     int s;
2137     struct client *client = (struct client *)arg;
2138     pthread_t tlsserverwrth;
2139     SSL *ssl;
2140     
2141     debug(DBG_DBG, "tlsserverrd starting for %s", client->conf->host);
2142     ssl = client->ssl;
2143
2144     if (SSL_accept(ssl) <= 0) {
2145         while ((error = ERR_get_error()))
2146             debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
2147         debug(DBG_ERR, "SSL_accept failed");
2148         goto errexit;
2149     }
2150     if (tlsverifycert(client->ssl, client->conf)) {
2151         if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
2152             debug(DBG_ERR, "tlsserverrd: pthread_create failed");
2153             goto errexit;
2154         }
2155         for (;;) {
2156             memset(&rq, 0, sizeof(struct request));
2157             rq.buf = radtlsget(client->ssl);
2158             if (!rq.buf)
2159                 break;
2160             debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->conf->host);
2161             rq.from = client;
2162             radsrv(&rq);
2163         }
2164         debug(DBG_ERR, "tlsserverrd: connection lost");
2165         /* stop writer by setting ssl to NULL and give signal in case waiting for data */
2166         client->ssl = NULL;
2167         pthread_mutex_lock(&client->replyq->mutex);
2168         pthread_cond_signal(&client->replyq->cond);
2169         pthread_mutex_unlock(&client->replyq->mutex);
2170         debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
2171         pthread_join(tlsserverwrth, NULL);
2172     }
2173     
2174  errexit:
2175     s = SSL_get_fd(ssl);
2176     SSL_free(ssl);
2177     shutdown(s, SHUT_RDWR);
2178     close(s);
2179     debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->conf->host);
2180     removeclient(client);
2181     pthread_exit(NULL);
2182 }
2183
2184 int tlslistener() {
2185     pthread_t tlsserverth;
2186     int s, snew;
2187     struct sockaddr_storage from;
2188     size_t fromlen = sizeof(from);
2189     struct clsrvconf *conf;
2190     struct client *client;
2191     struct clsrvconf *listenres;
2192     
2193     listenres = resolve_hostport('T', options.listentcp, DEFAULT_TLS_PORT);
2194     if ((s = bindtoaddr(listenres->addrinfo, AF_UNSPEC, 1, 0)) < 0)
2195         debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
2196     
2197     listen(s, 0);
2198     debug(DBG_WARN, "listening for incoming TCP on %s:%s", listenres->host ? listenres->host : "*", listenres->port);
2199     free(listenres);
2200     
2201     for (;;) {
2202         snew = accept(s, (struct sockaddr *)&from, &fromlen);
2203         if (snew < 0) {
2204             debug(DBG_WARN, "accept failed");
2205             continue;
2206         }
2207         debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
2208
2209         conf = find_conf('T', (struct sockaddr *)&from, clconfs, NULL);
2210         if (!conf) {
2211             debug(DBG_WARN, "ignoring request, not a known TLS client");
2212             shutdown(snew, SHUT_RDWR);
2213             close(snew);
2214             continue;
2215         }
2216
2217         client = addclient(conf);
2218
2219         if (!client) {
2220             debug(DBG_WARN, "Failed to create new client instance");
2221             shutdown(snew, SHUT_RDWR);
2222             close(snew);
2223             continue;
2224         }
2225         client->ssl = SSL_new(client->conf->ssl_ctx);
2226         SSL_set_fd(client->ssl, snew);
2227         if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
2228             debug(DBG_ERR, "tlslistener: pthread_create failed");
2229             SSL_free(client->ssl);
2230             removeclient(client);
2231             shutdown(snew, SHUT_RDWR);
2232             close(snew);
2233             continue;
2234         }
2235         pthread_detach(tlsserverth);
2236     }
2237     return 0;
2238 }
2239
2240 void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, char *certkeyfile, char *certkeypwd) {
2241     struct tls *new;
2242     SSL_CTX *ctx;
2243     STACK_OF(X509_NAME) *calist;
2244     int i;
2245     unsigned long error;
2246     
2247     if (!certfile || !certkeyfile)
2248         debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified in TLS context %s", value);
2249
2250     if (!cacertfile && !cacertpath)
2251         debugx(1, DBG_ERR, "CA Certificate file or path need to be specified in TLS context %s", value);
2252
2253     if (!ssl_locks) {
2254         ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
2255         ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
2256         for (i = 0; i < CRYPTO_num_locks(); i++) {
2257             ssl_lock_count[i] = 0;
2258             pthread_mutex_init(&ssl_locks[i], NULL);
2259         }
2260         CRYPTO_set_id_callback(ssl_thread_id);
2261         CRYPTO_set_locking_callback(ssl_locking_callback);
2262
2263         SSL_load_error_strings();
2264         SSL_library_init();
2265
2266         while (!RAND_status()) {
2267             time_t t = time(NULL);
2268             pid_t pid = getpid();
2269             RAND_seed((unsigned char *)&t, sizeof(time_t));
2270             RAND_seed((unsigned char *)&pid, sizeof(pid));
2271         }
2272     }
2273     ctx = SSL_CTX_new(TLSv1_method());
2274     if (certkeypwd) {
2275         SSL_CTX_set_default_passwd_cb_userdata(ctx, certkeypwd);
2276         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
2277     }
2278     if (!SSL_CTX_use_certificate_chain_file(ctx, certfile) ||
2279         !SSL_CTX_use_PrivateKey_file(ctx, certkeyfile, SSL_FILETYPE_PEM) ||
2280         !SSL_CTX_check_private_key(ctx) ||
2281         !SSL_CTX_load_verify_locations(ctx, cacertfile, cacertpath)) {
2282         while ((error = ERR_get_error()))
2283             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2284         debugx(1, DBG_ERR, "Error initialising SSL/TLS in TLS context %s", value);
2285     }
2286
2287     calist = cacertfile ? SSL_load_client_CA_file(cacertfile) : NULL;
2288     if (!cacertfile || calist) {
2289         if (cacertpath) {
2290             if (!calist)
2291                 calist = sk_X509_NAME_new_null();
2292             if (!SSL_add_dir_cert_subjects_to_stack(calist, cacertpath)) {
2293                 sk_X509_NAME_free(calist);
2294                 calist = NULL;
2295             }
2296         }
2297     }
2298     if (!calist) {
2299         while ((error = ERR_get_error()))
2300             debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
2301         debugx(1, DBG_ERR, "Error adding CA subjects in TLS context %s", value);
2302     }
2303     SSL_CTX_set_client_CA_list(ctx, calist);
2304     
2305     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
2306     SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
2307
2308     new = malloc(sizeof(struct tls));
2309     if (!new || !list_push(tlsconfs, new))
2310         debugx(1, DBG_ERR, "malloc failed");
2311
2312     memset(new, 0, sizeof(struct tls));
2313     new->name = stringcopy(value, 0);
2314     if (!new->name)
2315         debugx(1, DBG_ERR, "malloc failed");
2316     new->ctx = ctx;
2317     new->count = 0;
2318     debug(DBG_DBG, "tlsadd: added TLS context %s", value);
2319 }
2320
2321 void tlsfree() {
2322     struct list_node *entry;
2323     struct tls *t;
2324     
2325     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2326         t = (struct tls *)entry->data;
2327         if (t->name)
2328             free(t->name);
2329         if (!t->count)
2330             SSL_CTX_free(t->ctx);
2331     }
2332     list_destroy(tlsconfs);
2333     tlsconfs = NULL;
2334 }
2335
2336 SSL_CTX *tlsgetctx(char *alt1, char *alt2) {
2337     struct list_node *entry;
2338     struct tls *t, *t1 = NULL, *t2 = NULL;
2339     
2340     for (entry = list_first(tlsconfs); entry; entry = list_next(entry)) {
2341         t = (struct tls *)entry->data;
2342         if (!strcasecmp(t->name, alt1)) {
2343             t1 = t;
2344             break;
2345         }
2346         if (!t2 && alt2 && !strcasecmp(t->name, alt2))
2347             t2 = t;
2348     }
2349
2350     t = (t1 ? t1 : t2);
2351     if (!t)
2352         return NULL;
2353     t->count++;
2354     return t->ctx;
2355 }
2356
2357 void addrealm(char *value, char **servers, char *message) {
2358     int n;
2359     struct realm *realm;
2360     char *s, *regex = NULL;
2361     struct list_node *entry;
2362     struct clsrvconf *conf;
2363     
2364     if (*value == '/') {
2365         /* regexp, remove optional trailing / if present */
2366         if (value[strlen(value) - 1] == '/')
2367             value[strlen(value) - 1] = '\0';
2368     } else {
2369         /* not a regexp, let us make it one */
2370         if (*value == '*' && !value[1])
2371             regex = stringcopy(".*", 0);
2372         else {
2373             for (n = 0, s = value; *s;)
2374                 if (*s++ == '.')
2375                     n++;
2376             regex = malloc(strlen(value) + n + 3);
2377             if (regex) {
2378                 regex[0] = '@';
2379                 for (n = 1, s = value; *s; s++) {
2380                     if (*s == '.')
2381                         regex[n++] = '\\';
2382                     regex[n++] = *s;
2383                 }
2384                 regex[n++] = '$';
2385                 regex[n] = '\0';
2386             }
2387         }
2388         if (!regex)
2389             debugx(1, DBG_ERR, "malloc failed");
2390         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
2391     }
2392
2393     realm = malloc(sizeof(struct realm));
2394     if (!realm)
2395         debugx(1, DBG_ERR, "malloc failed");
2396     
2397     memset(realm, 0, sizeof(struct realm));
2398     realm->name = stringcopy(value, 0);
2399     if (!realm->name)
2400         debugx(1, DBG_ERR, "malloc failed");
2401     if (message && strlen(message) > 253)
2402         debugx(1, DBG_ERR, "ReplyMessage can be at most 253 bytes");
2403     realm->message = message;
2404     
2405     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
2406         debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
2407     if (regex)
2408         free(regex);
2409     
2410     if (servers && *servers) {
2411         realm->srvconfs = list_create();
2412         if (!realm->srvconfs)
2413             debugx(1, DBG_ERR, "malloc failed");
2414         for (n = 0; servers[n]; n++) {
2415             for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2416                 conf = (struct clsrvconf *)entry->data;
2417                 if (!strcasecmp(servers[n], conf->name))
2418                     break;
2419             }
2420             if (!entry)
2421                 debugx(1, DBG_ERR, "addrealm failed, no server %s", servers[n]);
2422             if (!list_push(realm->srvconfs, conf))
2423                 debugx(1, DBG_ERR, "malloc failed");
2424             debug(DBG_DBG, "addrealm: added server %s for realm %s", conf->name, value);
2425         }
2426     } else
2427         realm->srvconfs = NULL;
2428     
2429     if (!list_push(realms, realm))
2430         debugx(1, DBG_ERR, "malloc failed");
2431     debug(DBG_DBG, "addrealm: added realm %s", value);
2432 }
2433
2434 struct gconffile *openconfigfile(const char *filename) {
2435     FILE *f;
2436     char pathname[100], *base = NULL;
2437     struct gconffile *cf = NULL;
2438     
2439     f = pushgconffile(&cf, filename);
2440     if (f) {
2441         debug(DBG_DBG, "reading config file %s", filename);
2442         return cf;
2443     }
2444
2445     if (strlen(filename) + 1 <= sizeof(pathname)) {
2446         /* basename() might modify the string */
2447         strcpy(pathname, filename);
2448         base = basename(pathname);
2449         f = pushgconffile(&cf, base);
2450     }
2451
2452     if (!f)
2453         debugx(1, DBG_ERR, "could not read config file %s nor %s\n%s", filename, base, strerror(errno));
2454     
2455     debug(DBG_DBG, "reading config file %s", base);
2456     return cf;
2457 }
2458
2459 int addmatchcertattr(struct clsrvconf *conf, char *matchcertattr) {
2460     char *v;
2461     
2462     v = matchcertattr + 20;
2463     if (strncasecmp(matchcertattr, "SubjectAltName:URI:/", 20) || !*v)
2464         return 0;
2465     /* regexp, remove optional trailing / if present */
2466     if (v[strlen(v) - 1] == '/')
2467         v[strlen(v) - 1] = '\0';
2468     if (!*v)
2469         return 0;
2470
2471     conf->certuriregex = malloc(sizeof(regex_t));
2472     if (!conf->certuriregex) {
2473         debug(DBG_ERR, "malloc failed");
2474         return 0;
2475     }
2476     if (regcomp(conf->certuriregex, v, REG_ICASE | REG_NOSUB)) {
2477         free(conf->certuriregex);
2478         conf->certuriregex = NULL;
2479         debug(DBG_ERR, "failed to compile regular expression %s", v);
2480         return 0;
2481     }
2482     return 1;
2483 }
2484
2485 int addrewriteattr(struct clsrvconf *conf, char *rewriteattr) {
2486     char *v, *w;
2487     
2488     v = rewriteattr + 11;
2489     if (strncasecmp(rewriteattr, "User-Name:/", 11) || !*v)
2490         return 0;
2491     /* regexp, remove optional trailing / if present */
2492     if (v[strlen(v) - 1] == '/')
2493         v[strlen(v) - 1] = '\0';
2494
2495     w = strchr(v, '/');
2496     if (!*w)
2497         return 0;
2498     *w = '\0';
2499     w++;
2500     
2501     conf->rewriteattrregex = malloc(sizeof(regex_t));
2502     if (!conf->rewriteattrregex) {
2503         debug(DBG_ERR, "malloc failed");
2504         return 0;
2505     }
2506
2507     conf->rewriteattrreplacement = stringcopy(w, 0);
2508     if (!conf->rewriteattrreplacement) {
2509         free(conf->rewriteattrregex);
2510         conf->rewriteattrregex = NULL;
2511         return 0;
2512     }
2513     
2514     if (regcomp(conf->rewriteattrregex, v, REG_ICASE | REG_EXTENDED)) {
2515         free(conf->rewriteattrregex);
2516         conf->rewriteattrregex = NULL;
2517         free(conf->rewriteattrreplacement);
2518         conf->rewriteattrreplacement = NULL;
2519         debug(DBG_ERR, "failed to compile regular expression %s", v);
2520         return 0;
2521     }
2522
2523     return 1;
2524 }
2525
2526 void confclient_cb(FILE *f, char *block, char *opt, char *val) {
2527     char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewriteattr = NULL;
2528     struct clsrvconf *conf;
2529     
2530     debug(DBG_DBG, "confclient_cb called for %s", block);
2531
2532     conf = malloc(sizeof(struct clsrvconf));
2533     if (!conf || !list_push(clconfs, conf))
2534         debugx(1, DBG_ERR, "malloc failed");
2535     memset(conf, 0, sizeof(struct clsrvconf));
2536     
2537     getgenericconfig(f, block,
2538                      "type", CONF_STR, &type,
2539                      "host", CONF_STR, &conf->host,
2540                      "secret", CONF_STR, &conf->secret,
2541                      "tls", CONF_STR, &tls,
2542                      "matchcertificateattribute", CONF_STR, &matchcertattr,
2543                      "rewriteattribute", CONF_STR, &rewriteattr,
2544                      NULL
2545                      );
2546
2547     /* leave conf->name to be NULL for clients */
2548     if (!conf->host)
2549         conf->host = stringcopy(val, 0);
2550     
2551     if (type && !strcasecmp(type, "udp")) {
2552         conf->type = 'U';
2553         client_udp_count++;
2554     } else if (type && !strcasecmp(type, "tls")) {
2555         conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultclient", "default");
2556         if (!conf->ssl_ctx)
2557             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2558         if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2559             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2560         conf->type = 'T';
2561         client_tls_count++;
2562     } else
2563         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2564     free(type);
2565     if (tls)
2566         free(tls);
2567     if (matchcertattr)
2568         free(matchcertattr);
2569     
2570     if (rewriteattr) {
2571         if (!addrewriteattr(conf, rewriteattr))
2572             debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
2573         free(rewriteattr);
2574     }
2575     
2576     if (!resolvepeer(conf, 0))
2577         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2578     
2579     if (!conf->secret) {
2580         if (conf->type == 'U')
2581             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2582         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2583     }
2584 }
2585
2586 void confserver_cb(FILE *f, char *block, char *opt, char *val) {
2587     char *type = NULL, *tls = NULL, *matchcertattr = NULL, *statusserver = NULL;
2588     struct clsrvconf *conf;
2589     
2590     debug(DBG_DBG, "confserver_cb called for %s", block);
2591
2592     conf = malloc(sizeof(struct clsrvconf));
2593     if (!conf || !list_push(srvconfs, conf))
2594         debugx(1, DBG_ERR, "malloc failed");
2595     memset(conf, 0, sizeof(struct clsrvconf));
2596     
2597     getgenericconfig(f, block,
2598                      "type", CONF_STR, &type,
2599                      "host", CONF_STR, &conf->host,
2600                      "port", CONF_STR, &conf->port,
2601                      "secret", CONF_STR, &conf->secret,
2602                      "tls", CONF_STR, &tls,
2603                      "matchcertificateattribute", CONF_STR, &matchcertattr,
2604                      "StatusServer", CONF_STR, &statusserver,
2605                      NULL
2606                      );
2607
2608     conf->name = stringcopy(val, 0);
2609     if (!conf->host)
2610         conf->host = stringcopy(val, 0);
2611     
2612     if (type && !strcasecmp(type, "udp")) {
2613         conf->type = 'U';
2614         server_udp_count++;
2615         if (!conf->port)
2616             conf->port = stringcopy(DEFAULT_UDP_PORT, 0);
2617     } else if (type && !strcasecmp(type, "tls")) {
2618         conf->ssl_ctx = tls ? tlsgetctx(tls, NULL) : tlsgetctx("defaultserver", "default");
2619         if (!conf->ssl_ctx)
2620             debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2621         if (matchcertattr && !addmatchcertattr(conf, matchcertattr))
2622             debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2623         if (!conf->port)
2624             conf->port = stringcopy(DEFAULT_TLS_PORT, 0);
2625         conf->type = 'T';
2626         server_tls_count++;
2627     } else
2628         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2629     free(type);
2630     if (tls)
2631         free(tls);
2632     if (matchcertattr)
2633         free(matchcertattr);
2634     
2635     if (!resolvepeer(conf, 0))
2636         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host, conf->port);
2637     
2638     if (!conf->secret) {
2639         if (conf->type == 'U')
2640             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2641         conf->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2642     }
2643     
2644     if (statusserver) {
2645         if (!strcasecmp(statusserver, "on"))
2646             conf->statusserver = 1;
2647         else if (strcasecmp(statusserver, "off"))
2648             debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
2649         free(statusserver);
2650     }
2651 }
2652
2653 void confrealm_cb(FILE *f, char *block, char *opt, char *val) {
2654     char **servers = NULL, *msg = NULL;
2655     
2656     debug(DBG_DBG, "confrealm_cb called for %s", block);
2657     
2658     getgenericconfig(f, block,
2659                      "server", CONF_MSTR, &servers,
2660                      "ReplyMessage", CONF_STR, &msg,
2661                      NULL
2662                      );
2663
2664     addrealm(val, servers, msg);
2665     free(servers);
2666 }
2667
2668 void conftls_cb(FILE *f, char *block, char *opt, char *val) {
2669     char *cacertfile = NULL, *cacertpath = NULL, *certfile = NULL, *certkeyfile = NULL, *certkeypwd = NULL;
2670     
2671     debug(DBG_DBG, "conftls_cb called for %s", block);
2672     
2673     getgenericconfig(f, block,
2674                      "CACertificateFile", CONF_STR, &cacertfile,
2675                      "CACertificatePath", CONF_STR, &cacertpath,
2676                      "CertificateFile", CONF_STR, &certfile,
2677                      "CertificateKeyFile", CONF_STR, &certkeyfile,
2678                      "CertificateKeyPassword", CONF_STR, &certkeypwd,
2679                      NULL
2680                      );
2681     
2682     tlsadd(val, cacertfile, cacertpath, certfile, certkeyfile, certkeypwd);
2683     free(cacertfile);
2684     free(cacertpath);
2685     free(certfile);
2686     free(certkeyfile);
2687     free(certkeypwd);
2688 }
2689
2690 void getmainconfig(const char *configfile) {
2691     FILE *f;
2692     char *loglevel = NULL;
2693     struct gconffile *cfs;
2694
2695     cfs = openconfigfile(configfile);
2696     f = cfs->file;
2697     memset(&options, 0, sizeof(options));
2698     
2699     clconfs = list_create();
2700     if (!clconfs)
2701         debugx(1, DBG_ERR, "malloc failed");
2702     
2703     srvconfs = list_create();
2704     if (!srvconfs)
2705         debugx(1, DBG_ERR, "malloc failed");
2706     
2707     realms = list_create();
2708     if (!realms)
2709         debugx(1, DBG_ERR, "malloc failed");    
2710  
2711     tlsconfs = list_create();
2712     if (!tlsconfs)
2713         debugx(1, DBG_ERR, "malloc failed");    
2714  
2715     getgenericconfig(f, NULL,
2716                      "ListenUDP", CONF_STR, &options.listenudp,
2717                      "ListenTCP", CONF_STR, &options.listentcp,
2718                      "ListenAccountingUDP", CONF_STR, &options.listenaccudp,
2719                      "SourceUDP", CONF_STR, &options.sourceudp,
2720                      "SourceTCP", CONF_STR, &options.sourcetcp,
2721                      "LogLevel", CONF_STR, &loglevel,
2722                      "LogDestination", CONF_STR, &options.logdestination,
2723                      "Client", CONF_CBK, confclient_cb,
2724                      "Server", CONF_CBK, confserver_cb,
2725                      "Realm", CONF_CBK, confrealm_cb,
2726                      "TLS", CONF_CBK, conftls_cb,
2727                      NULL
2728                      );
2729     popgconffile(&cfs);
2730     tlsfree();
2731     
2732     if (loglevel) {
2733         if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
2734             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
2735         options.loglevel = *loglevel - '0';
2736         free(loglevel);
2737     }
2738 }
2739
2740 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile) {
2741     int c;
2742
2743     while ((c = getopt(argc, argv, "c:d:fpv")) != -1) {
2744         switch (c) {
2745         case 'c':
2746             *configfile = optarg;
2747             break;
2748         case 'd':
2749             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
2750                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
2751             *loglevel = *optarg - '0';
2752             break;
2753         case 'f':
2754             *foreground = 1;
2755             break;
2756         case 'p':
2757             *pretend = 1;
2758             break;
2759         case 'v':
2760                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
2761         default:
2762             goto usage;
2763         }
2764     }
2765     if (!(argc - optind))
2766         return;
2767
2768  usage:
2769     debug(DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -p ] [ -v ]", argv[0]);
2770     exit(1);
2771 }
2772
2773 int main(int argc, char **argv) {
2774     pthread_t udpserverth, udpaccserverth, udpclient4rdth, udpclient6rdth;
2775     struct list_node *entry;
2776     uint8_t foreground = 0, pretend = 0, loglevel = 0;
2777     char *configfile = NULL;
2778     
2779     debug_init("radsecproxy");
2780     debug_set_level(DEBUG_LEVEL);
2781     getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile);
2782     if (loglevel)
2783         debug_set_level(loglevel);
2784     getmainconfig(configfile ? configfile : CONFIG_MAIN);
2785     if (loglevel)
2786         options.loglevel = loglevel;
2787     else if (options.loglevel)
2788         debug_set_level(options.loglevel);
2789     if (foreground)
2790         options.logdestination = NULL;
2791     else {
2792         if (!options.logdestination)
2793             options.logdestination = "x-syslog:///";
2794         debug_set_destination(options.logdestination);
2795     }
2796
2797     if (pretend)
2798         debugx(0, DBG_ERR, "All OK so far; exiting since only pretending");
2799     
2800     if (!list_first(clconfs))
2801         debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
2802     if (!list_first(srvconfs))
2803         debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
2804     if (!list_first(realms))
2805         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
2806
2807     if (!foreground && (daemon(0, 0) < 0))
2808         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
2809     
2810     debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
2811
2812     if (client_udp_count) {
2813         udp_server_replyq = newreplyq();
2814         if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
2815             debugx(1, DBG_ERR, "pthread_create failed");
2816         if (options.listenaccudp)
2817             if (pthread_create(&udpaccserverth, NULL, udpaccserverrd, NULL))
2818                 debugx(1, DBG_ERR, "pthread_create failed");
2819     }
2820     
2821     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2822         addserver((struct clsrvconf *)entry->data);
2823         if (pthread_create(&((struct clsrvconf *)entry->data)->servers->clientth, NULL, clientwr,
2824                            (void *)((struct clsrvconf *)entry->data)->servers))
2825             debugx(1, DBG_ERR, "pthread_create failed");
2826     }
2827     /* srcudpres no longer needed, while srctcpres is needed later */
2828     if (srcudpres) {
2829         free(srcudpres);
2830         srcudpres = NULL;
2831     }
2832     if (udp_client4_sock >= 0)
2833         if (pthread_create(&udpclient4rdth, NULL, udpclientrd, (void *)&udp_client4_sock))
2834             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
2835     if (udp_client6_sock >= 0)
2836         if (pthread_create(&udpclient6rdth, NULL, udpclientrd, (void *)&udp_client6_sock))
2837             debugx(1, DBG_ERR, "clientwr: pthread_create failed");
2838     
2839     if (client_tls_count)
2840         return tlslistener();
2841     
2842     /* just hang around doing nothing, anything to do here? */
2843     for (;;)
2844         sleep(1000);
2845 }