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