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