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