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