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