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