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