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