removed some old backwards compatible config stuff (clients.conf/servers.conf)
[radsecproxy.git] / radsecproxy.c
1 /*
2  * Copyright (C) 2006, 2007 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 <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/time.h>
38 #include <regex.h>
39 #include <libgen.h>
40 #include <pthread.h>
41 #include <openssl/ssl.h>
42 #include <openssl/rand.h>
43 #include <openssl/err.h>
44 #include <openssl/md5.h>
45 #include <openssl/hmac.h>
46 #include "debug.h"
47 #include "radsecproxy.h"
48
49 static struct options options;
50 static struct client *clients = NULL;
51 static struct server *servers = NULL;
52 static struct realm *realms = NULL;
53
54 static int client_udp_count = 0;
55 static int client_tls_count = 0;
56 static int client_count = 0;
57 static int server_udp_count = 0;
58 static int server_tls_count = 0;
59 static int server_count = 0;
60 static int realm_count = 0;
61
62 static struct peer *tcp_server_listen;
63 static struct peer *udp_server_listen;
64 static struct replyq udp_server_replyq;
65 static int udp_server_sock = -1;
66 static pthread_mutex_t *ssl_locks;
67 static long *ssl_lock_count;
68 static SSL_CTX *ssl_ctx = NULL;
69 extern int optind;
70 extern char *optarg;
71
72 /* callbacks for making OpenSSL thread safe */
73 unsigned long ssl_thread_id() {
74         return (unsigned long)pthread_self();
75 }
76
77 void ssl_locking_callback(int mode, int type, const char *file, int line) {
78     if (mode & CRYPTO_LOCK) {
79         pthread_mutex_lock(&ssl_locks[type]);
80         ssl_lock_count[type]++;
81     } else
82         pthread_mutex_unlock(&ssl_locks[type]);
83 }
84
85 static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
86     int pwdlen = strlen(userdata);
87     if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
88         return 0;
89     memcpy(buf, userdata, pwdlen);
90     return pwdlen;
91 }
92
93 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
94   char buf[256];
95   X509 *err_cert;
96   int err, depth;
97
98   err_cert = X509_STORE_CTX_get_current_cert(ctx);
99   err = X509_STORE_CTX_get_error(ctx);
100   depth = X509_STORE_CTX_get_error_depth(ctx);
101
102   if (depth > MAX_CERT_DEPTH) {
103       ok = 0;
104       err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
105       X509_STORE_CTX_set_error(ctx, err);
106   }
107
108   if (!ok) {
109       X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
110       debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
111
112       switch (err) {
113       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
114           X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
115           debug(DBG_WARN, "\tIssuer=%s", buf);
116           break;
117       case X509_V_ERR_CERT_NOT_YET_VALID:
118       case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
119           debug(DBG_WARN, "\tCertificate not yet valid");
120           break;
121       case X509_V_ERR_CERT_HAS_EXPIRED:
122           debug(DBG_WARN, "Certificate has expired");
123           break;
124       case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
125           debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
126           break;
127       }
128   }
129 #ifdef DEBUG  
130   printf("certificate verify returns %d\n", ok);
131 #endif  
132   return ok;
133 }
134
135 SSL_CTX *ssl_init() {
136     SSL_CTX *ctx;
137     int i;
138     unsigned long error;
139     
140     if (!options.tlscertificatefile || !options.tlscertificatekeyfile)
141         debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified for TLS");
142
143     if (!options.tlscacertificatefile && !options.tlscacertificatepath)
144         debugx(1, DBG_ERR, "CA Certificate file/path need to be configured");
145
146     ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
147     ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
148     for (i = 0; i < CRYPTO_num_locks(); i++) {
149         ssl_lock_count[i] = 0;
150         pthread_mutex_init(&ssl_locks[i], NULL);
151     }
152     CRYPTO_set_id_callback(ssl_thread_id);
153     CRYPTO_set_locking_callback(ssl_locking_callback);
154
155     SSL_load_error_strings();
156     SSL_library_init();
157
158     while (!RAND_status()) {
159         time_t t = time(NULL);
160         pid_t pid = getpid();
161         RAND_seed((unsigned char *)&t, sizeof(time_t));
162         RAND_seed((unsigned char *)&pid, sizeof(pid));
163     }
164
165     ctx = SSL_CTX_new(TLSv1_method());
166     if (options.tlscertificatekeypassword) {
167         SSL_CTX_set_default_passwd_cb_userdata(ctx, options.tlscertificatekeypassword);
168         SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
169     }
170     if (SSL_CTX_use_certificate_chain_file(ctx, options.tlscertificatefile) &&
171         SSL_CTX_use_PrivateKey_file(ctx, options.tlscertificatekeyfile, SSL_FILETYPE_PEM) &&
172         SSL_CTX_check_private_key(ctx) &&
173         SSL_CTX_load_verify_locations(ctx, options.tlscacertificatefile, options.tlscacertificatepath)) {
174         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb);
175         SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
176         return ctx;
177     }
178
179     while ((error = ERR_get_error()))
180         debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
181     debug(DBG_ERR, "Error initialising SSL/TLS");
182     exit(1);
183 }    
184
185 #ifdef DEBUG
186 void printauth(char *s, unsigned char *t) {
187     int i;
188     printf("%s:", s);
189     for (i = 0; i < 16; i++)
190             printf("%02x ", t[i]);
191     printf("\n");
192 }
193 #endif
194
195 int resolvepeer(struct peer *peer, int ai_flags) {
196     struct addrinfo hints, *addrinfo;
197     
198     memset(&hints, 0, sizeof(hints));
199     hints.ai_socktype = (peer->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
200     hints.ai_family = AF_UNSPEC;
201     hints.ai_flags = ai_flags;
202     if (getaddrinfo(peer->host, peer->port, &hints, &addrinfo)) {
203         debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", peer->host, peer->port);
204         return 0;
205     }
206
207     if (peer->addrinfo)
208         freeaddrinfo(peer->addrinfo);
209     peer->addrinfo = addrinfo;
210     return 1;
211 }         
212
213 int connecttoserver(struct addrinfo *addrinfo) {
214     int s;
215     struct addrinfo *res;
216
217     s = -1;
218     for (res = addrinfo; res; res = res->ai_next) {
219         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
220         if (s < 0) {
221             debug(DBG_WARN, "connecttoserver: socket failed");
222             continue;
223         }
224         if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
225             break;
226         debug(DBG_WARN, "connecttoserver: connect failed");
227         close(s);
228         s = -1;
229     }
230     return s;
231 }         
232
233 int bindtoaddr(struct addrinfo *addrinfo) {
234     int s, on = 1;
235     struct addrinfo *res;
236     
237     for (res = addrinfo; res; res = res->ai_next) {
238         s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
239         if (s < 0) {
240             debug(DBG_WARN, "bindtoaddr: socket failed");
241             continue;
242         }
243         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
244         if (!bind(s, res->ai_addr, res->ai_addrlen))
245             return s;
246         debug(DBG_WARN, "bindtoaddr: bind failed");
247         close(s);
248     }
249     return -1;
250 }         
251
252 /* returns the client with matching address, or NULL */
253 /* if client argument is not NULL, we only check that one client */
254 struct client *find_client(char type, struct sockaddr *addr, struct client *client) {
255     struct sockaddr_in6 *sa6 = NULL;
256     struct in_addr *a4 = NULL;
257     struct client *c;
258     int i;
259     struct addrinfo *res;
260
261     if (addr->sa_family == AF_INET6) {
262         sa6 = (struct sockaddr_in6 *)addr;
263         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
264             a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
265     } else
266         a4 = &((struct sockaddr_in *)addr)->sin_addr;
267
268     c = (client ? client : clients);
269     for (i = 0; i < client_count; i++) {
270         if (c->peer.type == type)
271             for (res = c->peer.addrinfo; res; res = res->ai_next)
272                 if ((a4 && res->ai_family == AF_INET &&
273                      !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
274                     (res->ai_family == AF_INET6 &&
275                      !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
276                     return c;
277         if (client)
278             break;
279         c++;
280     }
281     return NULL;
282 }
283
284 /* returns the server with matching address, or NULL */
285 /* if server argument is not NULL, we only check that one server */
286 struct server *find_server(char type, struct sockaddr *addr, struct server *server) {
287     struct sockaddr_in6 *sa6 = NULL;
288     struct in_addr *a4 = NULL;
289     struct server *s;
290     int i;
291     struct addrinfo *res;
292
293     if (addr->sa_family == AF_INET6) {
294         sa6 = (struct sockaddr_in6 *)addr;
295         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
296             a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12];
297     } else
298         a4 = &((struct sockaddr_in *)addr)->sin_addr;
299
300     s = (server ? server : servers);
301     for (i = 0; i < server_count; i++) {
302         if (s->peer.type == type)
303             for (res = s->peer.addrinfo; res; res = res->ai_next)
304                 if ((a4 && res->ai_family == AF_INET &&
305                      !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) ||
306                     (res->ai_family == AF_INET6 &&
307                      !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16)))
308                     return s;
309         if (server)
310             break;
311         s++;
312     }
313     return NULL;
314 }
315
316 /* exactly one of client and server must be non-NULL */
317 /* if *peer == NULL we return who we received from, else require it to be from peer */
318 /* return from in sa if not NULL */
319 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
320     int cnt, len;
321     void *f;
322     unsigned char buf[65536], *rad;
323     struct sockaddr_storage from;
324     socklen_t fromlen = sizeof(from);
325
326     for (;;) {
327         cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
328         if (cnt == -1) {
329             debug(DBG_WARN, "radudpget: recv failed");
330             continue;
331         }
332         debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
333
334         if (cnt < 20) {
335             debug(DBG_WARN, "radudpget: packet too small");
336             continue;
337         }
338     
339         len = RADLEN(buf);
340         if (len < 20) {
341             debug(DBG_WARN, "radudpget: length too small");
342             continue;
343         }
344
345         if (cnt < len) {
346             debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
347             continue;
348         }
349         if (cnt > len)
350             debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
351
352         f = (client
353              ? (void *)find_client('U', (struct sockaddr *)&from, *client)
354              : (void *)find_server('U', (struct sockaddr *)&from, *server));
355         if (!f) {
356             debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
357             continue;
358         }
359
360         rad = malloc(len);
361         if (rad)
362             break;
363         debug(DBG_ERR, "radudpget: malloc failed");
364     }
365     memcpy(rad, buf, len);
366     if (client)
367         *client = (struct client *)f; /* only need this if *client == NULL, but if not NULL *client == f here */
368     else
369         *server = (struct server *)f; /* only need this if *server == NULL, but if not NULL *server == f here */
370     if (sa)
371         *sa = from;
372     return rad;
373 }
374
375 int tlsverifycert(struct peer *peer) {
376     int l, loc;
377     X509 *cert;
378     X509_NAME *nm;
379     X509_NAME_ENTRY *e;
380     unsigned char *v;
381     unsigned long error;
382
383     if (SSL_get_verify_result(peer->ssl) != X509_V_OK) {
384         debug(DBG_ERR, "tlsverifycert: basic validation failed");
385         while ((error = ERR_get_error()))
386             debug(DBG_ERR, "tlsverifycert: TLS: %s", ERR_error_string(error, NULL));
387         return 0;
388     }
389
390     cert = SSL_get_peer_certificate(peer->ssl);
391     if (!cert) {
392         debug(DBG_ERR, "tlsverifycert: failed to obtain certificate");
393         return 0;
394     }
395     nm = X509_get_subject_name(cert);
396     loc = -1;
397     for (;;) {
398         loc = X509_NAME_get_index_by_NID(nm, NID_commonName, loc);
399         if (loc == -1)
400             break;
401         e = X509_NAME_get_entry(nm, loc);
402         l = ASN1_STRING_to_UTF8(&v, X509_NAME_ENTRY_get_data(e));
403         if (l < 0)
404             continue;
405 #ifdef DEBUG
406         {
407             int i;
408             printf("cn: ");
409             for (i = 0; i < l; i++)
410                 printf("%c", v[i]);
411             printf("\n");
412         }
413 #endif  
414         if (l == strlen(peer->host) && !strncasecmp(peer->host, (char *)v, l)) {
415             debug(DBG_DBG, "tlsverifycert: Found cn matching host %s, All OK", peer->host);
416             return 1;
417         }
418         debug(DBG_ERR, "tlsverifycert: cn not matching host %s", peer->host);
419     }
420     X509_free(cert);
421     return 0;
422 }
423
424 void tlsconnect(struct server *server, struct timeval *when, char *text) {
425     struct timeval now;
426     time_t elapsed;
427
428     debug(DBG_DBG, "tlsconnect called from %s", text);
429     pthread_mutex_lock(&server->lock);
430     if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
431         /* already reconnected, nothing to do */
432         debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
433         pthread_mutex_unlock(&server->lock);
434         return;
435     }
436
437     debug(DBG_DBG, "tlsconnect %s", text);
438
439     for (;;) {
440         gettimeofday(&now, NULL);
441         elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
442         if (server->connectionok) {
443             server->connectionok = 0;
444             sleep(10);
445         } else if (elapsed < 5)
446             sleep(10);
447         else if (elapsed < 300) {
448             debug(DBG_INFO, "tlsconnect: sleeping %lds", elapsed);
449             sleep(elapsed);
450         } else if (elapsed < 100000) {
451             debug(DBG_INFO, "tlsconnect: sleeping %ds", 600);
452             sleep(600);
453         } else
454             server->lastconnecttry.tv_sec = now.tv_sec;  /* no sleep at startup */
455         debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->peer.host, server->peer.port);
456         if (server->sock >= 0)
457             close(server->sock);
458         if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0) {
459             debug(DBG_ERR, "tlsconnect: connecttoserver failed");
460             continue;
461         }
462         
463         SSL_free(server->peer.ssl);
464         server->peer.ssl = SSL_new(ssl_ctx);
465         SSL_set_fd(server->peer.ssl, server->sock);
466         if (SSL_connect(server->peer.ssl) > 0 && tlsverifycert(&server->peer))
467             break;
468     }
469     debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->peer.host, server->peer.port);
470     gettimeofday(&server->lastconnecttry, NULL);
471     pthread_mutex_unlock(&server->lock);
472 }
473
474 unsigned char *radtlsget(SSL *ssl) {
475     int cnt, total, len;
476     unsigned char buf[4], *rad;
477
478     for (;;) {
479         for (total = 0; total < 4; total += cnt) {
480             cnt = SSL_read(ssl, buf + total, 4 - total);
481             if (cnt <= 0) {
482                 debug(DBG_ERR, "radtlsget: connection lost");
483                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
484                     /* remote end sent close_notify, send one back */
485                     SSL_shutdown(ssl);
486                 }
487                 return NULL;
488             }
489         }
490
491         len = RADLEN(buf);
492         rad = malloc(len);
493         if (!rad) {
494             debug(DBG_ERR, "radtlsget: malloc failed");
495             continue;
496         }
497         memcpy(rad, buf, 4);
498
499         for (; total < len; total += cnt) {
500             cnt = SSL_read(ssl, rad + total, len - total);
501             if (cnt <= 0) {
502                 debug(DBG_ERR, "radtlsget: connection lost");
503                 if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
504                     /* remote end sent close_notify, send one back */
505                     SSL_shutdown(ssl);
506                 }
507                 free(rad);
508                 return NULL;
509             }
510         }
511     
512         if (total >= 20)
513             break;
514         
515         free(rad);
516         debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
517     }
518     
519     debug(DBG_DBG, "radtlsget: got %d bytes", total);
520     return rad;
521 }
522
523 int clientradput(struct server *server, unsigned char *rad) {
524     int cnt;
525     size_t len;
526     unsigned long error;
527     struct timeval lastconnecttry;
528     
529     len = RADLEN(rad);
530     if (server->peer.type == 'U') {
531         if (send(server->sock, rad, len, 0) >= 0) {
532             debug(DBG_DBG, "clienradput: sent UDP of length %d to %s port %s", len, server->peer.host, server->peer.port);
533             return 1;
534         }
535         debug(DBG_WARN, "clientradput: send failed");
536         return 0;
537     }
538
539     lastconnecttry = server->lastconnecttry;
540     while ((cnt = SSL_write(server->peer.ssl, rad, len)) <= 0) {
541         while ((error = ERR_get_error()))
542             debug(DBG_ERR, "clientradput: TLS: %s", ERR_error_string(error, NULL));
543         tlsconnect(server, &lastconnecttry, "clientradput");
544         lastconnecttry = server->lastconnecttry;
545     }
546
547     server->connectionok = 1;
548     debug(DBG_DBG, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s",
549            cnt, len, server->peer.host);
550     return 1;
551 }
552
553 int radsign(unsigned char *rad, unsigned char *sec) {
554     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
555     static unsigned char first = 1;
556     static EVP_MD_CTX mdctx;
557     unsigned int md_len;
558     int result;
559     
560     pthread_mutex_lock(&lock);
561     if (first) {
562         EVP_MD_CTX_init(&mdctx);
563         first = 0;
564     }
565
566     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
567         EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) &&
568         EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
569         EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) &&
570         md_len == 16);
571     pthread_mutex_unlock(&lock);
572     return result;
573 }
574
575 int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
576     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
577     static unsigned char first = 1;
578     static EVP_MD_CTX mdctx;
579     unsigned char hash[EVP_MAX_MD_SIZE];
580     unsigned int len;
581     int result;
582     
583     pthread_mutex_lock(&lock);
584     if (first) {
585         EVP_MD_CTX_init(&mdctx);
586         first = 0;
587     }
588
589     len = RADLEN(rad);
590     
591     result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
592               EVP_DigestUpdate(&mdctx, rad, 4) &&
593               EVP_DigestUpdate(&mdctx, reqauth, 16) &&
594               (len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
595               EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
596               EVP_DigestFinal_ex(&mdctx, hash, &len) &&
597               len == 16 &&
598               !memcmp(hash, rad + 4, 16));
599     pthread_mutex_unlock(&lock);
600     return result;
601 }
602               
603 int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
604     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
605     static unsigned char first = 1;
606     static HMAC_CTX hmacctx;
607     unsigned int md_len;
608     uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
609     
610     pthread_mutex_lock(&lock);
611     if (first) {
612         HMAC_CTX_init(&hmacctx);
613         first = 0;
614     }
615
616     memcpy(auth, authattr, 16);
617     memset(authattr, 0, 16);
618     md_len = 0;
619     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
620     HMAC_Update(&hmacctx, rad, RADLEN(rad));
621     HMAC_Final(&hmacctx, hash, &md_len);
622     memcpy(authattr, auth, 16);
623     if (md_len != 16) {
624         debug(DBG_WARN, "message auth computation failed");
625         pthread_mutex_unlock(&lock);
626         return 0;
627     }
628
629     if (memcmp(auth, hash, 16)) {
630         debug(DBG_WARN, "message authenticator, wrong value");
631         pthread_mutex_unlock(&lock);
632         return 0;
633     }   
634         
635     pthread_mutex_unlock(&lock);
636     return 1;
637 }
638
639 int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secret) {
640     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
641     static unsigned char first = 1;
642     static HMAC_CTX hmacctx;
643     unsigned int md_len;
644
645     if (!authattrval)
646         return 1;
647     
648     pthread_mutex_lock(&lock);
649     if (first) {
650         HMAC_CTX_init(&hmacctx);
651         first = 0;
652     }
653
654     memset(authattrval, 0, 16);
655     md_len = 0;
656     HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
657     HMAC_Update(&hmacctx, rad, RADLEN(rad));
658     HMAC_Final(&hmacctx, authattrval, &md_len);
659     if (md_len != 16) {
660         debug(DBG_WARN, "message auth computation failed");
661         pthread_mutex_unlock(&lock);
662         return 0;
663     }
664
665     pthread_mutex_unlock(&lock);
666     return 1;
667 }
668
669 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
670     while (length > 1) {
671         if (ATTRTYPE(attrs) == type)
672             return attrs;
673         length -= ATTRLEN(attrs);
674         attrs += ATTRLEN(attrs);
675     }
676     return NULL;
677 }
678
679 void sendrq(struct server *to, struct request *rq) {
680     int i;
681     uint8_t *attr;
682
683     pthread_mutex_lock(&to->newrq_mutex);
684     /* might simplify if only try nextid, might be ok */
685     for (i = to->nextid; i < MAX_REQUESTS; i++)
686         if (!to->requests[i].buf)
687             break;
688     if (i == MAX_REQUESTS) {
689         for (i = 0; i < to->nextid; i++)
690             if (!to->requests[i].buf)
691                 break;
692         if (i == to->nextid) {
693             debug(DBG_WARN, "No room in queue, dropping request");
694             free(rq->buf);
695             pthread_mutex_unlock(&to->newrq_mutex);
696             return;
697         }
698     }
699     
700     rq->buf[1] = (char)i;
701
702     attr = attrget(rq->buf + 20, RADLEN(rq->buf) - 20, RAD_Attr_Message_Authenticator);
703     if (attr && !createmessageauth(rq->buf, ATTRVAL(attr), to->peer.secret)) {
704         free(rq->buf);
705         pthread_mutex_unlock(&to->newrq_mutex);
706         return;
707     }
708
709     debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->peer.host);
710     to->requests[i] = *rq;
711     to->nextid = i + 1;
712
713     if (!to->newrq) {
714         to->newrq = 1;
715         debug(DBG_DBG, "signalling client writer");
716         pthread_cond_signal(&to->newrq_cond);
717     }
718     pthread_mutex_unlock(&to->newrq_mutex);
719 }
720
721 void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
722     struct replyq *replyq = to->replyq;
723     
724     if (!radsign(buf, (unsigned char *)to->peer.secret)) {
725         free(buf);
726         debug(DBG_WARN, "sendreply: failed to sign message");
727         return;
728     }
729         
730     pthread_mutex_lock(&replyq->count_mutex);
731     if (replyq->count == replyq->size) {
732         debug(DBG_WARN, "No room in queue, dropping request");
733         pthread_mutex_unlock(&replyq->count_mutex);
734         free(buf);
735         return;
736     }
737
738     replyq->replies[replyq->count].buf = buf;
739     if (tosa)
740         replyq->replies[replyq->count].tosa = *tosa;
741     replyq->count++;
742
743     if (replyq->count == 1) {
744         debug(DBG_DBG, "signalling server writer");
745         pthread_cond_signal(&replyq->count_cond);
746     }
747     pthread_mutex_unlock(&replyq->count_mutex);
748 }
749
750 int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
751     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
752     static unsigned char first = 1;
753     static EVP_MD_CTX mdctx;
754     unsigned char hash[EVP_MAX_MD_SIZE], *input;
755     unsigned int md_len;
756     uint8_t i, offset = 0, out[128];
757     
758     pthread_mutex_lock(&lock);
759     if (first) {
760         EVP_MD_CTX_init(&mdctx);
761         first = 0;
762     }
763
764     input = auth;
765     for (;;) {
766         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
767             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
768             !EVP_DigestUpdate(&mdctx, input, 16) ||
769             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
770             md_len != 16) {
771             pthread_mutex_unlock(&lock);
772             return 0;
773         }
774         for (i = 0; i < 16; i++)
775             out[offset + i] = hash[i] ^ in[offset + i];
776         input = out + offset - 16;
777         offset += 16;
778         if (offset == len)
779             break;
780     }
781     memcpy(in, out, len);
782     pthread_mutex_unlock(&lock);
783     return 1;
784 }
785
786 int pwddecrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
787     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
788     static unsigned char first = 1;
789     static EVP_MD_CTX mdctx;
790     unsigned char hash[EVP_MAX_MD_SIZE], *input;
791     unsigned int md_len;
792     uint8_t i, offset = 0, out[128];
793     
794     pthread_mutex_lock(&lock);
795     if (first) {
796         EVP_MD_CTX_init(&mdctx);
797         first = 0;
798     }
799
800     input = auth;
801     for (;;) {
802         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
803             !EVP_DigestUpdate(&mdctx, (uint8_t *)shared, sharedlen) ||
804             !EVP_DigestUpdate(&mdctx, input, 16) ||
805             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
806             md_len != 16) {
807             pthread_mutex_unlock(&lock);
808             return 0;
809         }
810         for (i = 0; i < 16; i++)
811             out[offset + i] = hash[i] ^ in[offset + i];
812         input = in + offset;
813         offset += 16;
814         if (offset == len)
815             break;
816     }
817     memcpy(in, out, len);
818     pthread_mutex_unlock(&lock);
819     return 1;
820 }
821
822 int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
823     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
824     static unsigned char first = 1;
825     static EVP_MD_CTX mdctx;
826     unsigned char hash[EVP_MAX_MD_SIZE];
827     unsigned int md_len;
828     uint8_t i, offset;
829     
830     pthread_mutex_lock(&lock);
831     if (first) {
832         EVP_MD_CTX_init(&mdctx);
833         first = 0;
834     }
835
836 #if 0    
837     printf("msppencrypt auth in: ");
838     for (i = 0; i < 16; i++)
839         printf("%02x ", auth[i]);
840     printf("\n");
841     
842     printf("msppencrypt salt in: ");
843     for (i = 0; i < 2; i++)
844         printf("%02x ", salt[i]);
845     printf("\n");
846     
847     printf("msppencrypt in: ");
848     for (i = 0; i < len; i++)
849         printf("%02x ", text[i]);
850     printf("\n");
851 #endif
852     
853     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
854         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
855         !EVP_DigestUpdate(&mdctx, auth, 16) ||
856         !EVP_DigestUpdate(&mdctx, salt, 2) ||
857         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
858         pthread_mutex_unlock(&lock);
859         return 0;
860     }
861
862 #if 0    
863     printf("msppencrypt hash: ");
864     for (i = 0; i < 16; i++)
865         printf("%02x ", hash[i]);
866     printf("\n");
867 #endif
868     
869     for (i = 0; i < 16; i++)
870         text[i] ^= hash[i];
871     
872     for (offset = 16; offset < len; offset += 16) {
873 #if 0   
874         printf("text + offset - 16 c(%d): ", offset / 16);
875         for (i = 0; i < 16; i++)
876             printf("%02x ", (text + offset - 16)[i]);
877         printf("\n");
878 #endif
879         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
880             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
881             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
882             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
883             md_len != 16) {
884             pthread_mutex_unlock(&lock);
885             return 0;
886         }
887 #if 0   
888         printf("msppencrypt hash: ");
889         for (i = 0; i < 16; i++)
890             printf("%02x ", hash[i]);
891         printf("\n");
892 #endif    
893         
894         for (i = 0; i < 16; i++)
895             text[offset + i] ^= hash[i];
896     }
897     
898 #if 0
899     printf("msppencrypt out: ");
900     for (i = 0; i < len; i++)
901         printf("%02x ", text[i]);
902     printf("\n");
903 #endif
904
905     pthread_mutex_unlock(&lock);
906     return 1;
907 }
908
909 int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
910     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
911     static unsigned char first = 1;
912     static EVP_MD_CTX mdctx;
913     unsigned char hash[EVP_MAX_MD_SIZE];
914     unsigned int md_len;
915     uint8_t i, offset;
916     char plain[255];
917     
918     pthread_mutex_lock(&lock);
919     if (first) {
920         EVP_MD_CTX_init(&mdctx);
921         first = 0;
922     }
923
924 #if 0    
925     printf("msppdecrypt auth in: ");
926     for (i = 0; i < 16; i++)
927         printf("%02x ", auth[i]);
928     printf("\n");
929     
930     printf("msppedecrypt salt in: ");
931     for (i = 0; i < 2; i++)
932         printf("%02x ", salt[i]);
933     printf("\n");
934     
935     printf("msppedecrypt in: ");
936     for (i = 0; i < len; i++)
937         printf("%02x ", text[i]);
938     printf("\n");
939 #endif
940     
941     if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
942         !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
943         !EVP_DigestUpdate(&mdctx, auth, 16) ||
944         !EVP_DigestUpdate(&mdctx, salt, 2) ||
945         !EVP_DigestFinal_ex(&mdctx, hash, &md_len)) {
946         pthread_mutex_unlock(&lock);
947         return 0;
948     }
949
950 #if 0    
951     printf("msppedecrypt hash: ");
952     for (i = 0; i < 16; i++)
953         printf("%02x ", hash[i]);
954     printf("\n");
955 #endif
956     
957     for (i = 0; i < 16; i++)
958         plain[i] = text[i] ^ hash[i];
959     
960     for (offset = 16; offset < len; offset += 16) {
961 #if 0   
962         printf("text + offset - 16 c(%d): ", offset / 16);
963         for (i = 0; i < 16; i++)
964             printf("%02x ", (text + offset - 16)[i]);
965         printf("\n");
966 #endif
967         if (!EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) ||
968             !EVP_DigestUpdate(&mdctx, shared, sharedlen) ||
969             !EVP_DigestUpdate(&mdctx, text + offset - 16, 16) ||
970             !EVP_DigestFinal_ex(&mdctx, hash, &md_len) ||
971             md_len != 16) {
972             pthread_mutex_unlock(&lock);
973             return 0;
974         }
975 #if 0   
976     printf("msppedecrypt hash: ");
977     for (i = 0; i < 16; i++)
978         printf("%02x ", hash[i]);
979     printf("\n");
980 #endif    
981
982     for (i = 0; i < 16; i++)
983         plain[offset + i] = text[offset + i] ^ hash[i];
984     }
985
986     memcpy(text, plain, len);
987 #if 0
988     printf("msppedecrypt out: ");
989     for (i = 0; i < len; i++)
990         printf("%02x ", text[i]);
991     printf("\n");
992 #endif
993
994     pthread_mutex_unlock(&lock);
995     return 1;
996 }
997
998 int id2server(struct server **server, char *id, uint8_t len) {
999     int i;
1000     for (i = 0; i < realm_count; i++)
1001         if (!regexec(&realms[i].regex, id, 0, NULL, 0)) {
1002             debug(DBG_DBG, "found matching realm: %s, host %s", realms[i].name, realms[i].server->peer.host);
1003             *server = realms[i].server;
1004             return 1;
1005         }
1006     return 0;
1007 }
1008
1009 int rqinqueue(struct server *to, struct client *from, uint8_t id) {
1010     int i;
1011     
1012     pthread_mutex_lock(&to->newrq_mutex);
1013     for (i = 0; i < MAX_REQUESTS; i++)
1014         if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from)
1015             break;
1016     pthread_mutex_unlock(&to->newrq_mutex);
1017     
1018     return i < MAX_REQUESTS;
1019 }
1020
1021 int attrvalidate(unsigned char *attrs, int length) {
1022     while (length > 1) {
1023         if (ATTRLEN(attrs) < 2) {
1024             debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1025             return 0;
1026         }
1027         length -= ATTRLEN(attrs);
1028         if (length < 0) {
1029             debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1030             return 0;
1031         }
1032         attrs += ATTRLEN(attrs);
1033     }
1034     if (length)
1035         debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1036     return 1;
1037 }
1038
1039 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1040 #ifdef DEBUG    
1041     int i;
1042 #endif    
1043     if (len < 16 || len > 128 || len % 16) {
1044         debug(DBG_WARN, "pwdrecrypt: invalid password length");
1045         return 0;
1046     }
1047         
1048     if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1049         debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1050         return 0;
1051     }
1052 #ifdef DEBUG
1053     printf("pwdrecrypt: password: ");
1054     for (i = 0; i < len; i++)
1055         printf("%02x ", pwd[i]);
1056     printf("\n");
1057 #endif  
1058     if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1059         debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1060         return 0;
1061     }
1062     return 1;
1063 }
1064
1065 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1066     if (len < 18)
1067         return 0;
1068     if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1069         debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1070         return 0;
1071     }
1072     if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1073         debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1074         return 0;
1075     }
1076     return 1;
1077 }
1078
1079 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1080            char *oldsecret, char *newsecret) {
1081     unsigned char *attr;
1082     
1083     for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1084         debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1085         if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1086             return 0;
1087     }
1088     return 1;
1089 }
1090
1091 void respondstatusserver(struct request *rq) {
1092     unsigned char *resp;
1093
1094     resp = malloc(20);
1095     if (!resp) {
1096         debug(DBG_ERR, "respondstatusserver: malloc failed");
1097         return;
1098     }
1099     memcpy(resp, rq->buf, 20);
1100     resp[0] = RAD_Access_Accept;
1101     resp[2] = 0;
1102     resp[3] = 20;
1103     debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->peer.host);
1104     sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL);
1105 }
1106
1107 void respondreject(struct request *rq) {
1108     unsigned char *resp;
1109
1110     resp = malloc(20);
1111     if (!resp) {
1112         debug(DBG_ERR, "respondreject: malloc failed");
1113         return;
1114     }
1115     memcpy(resp, rq->buf, 20);
1116     resp[0] = RAD_Access_Reject;
1117     resp[2] = 0;
1118     resp[3] = 20;
1119     sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL);
1120 }
1121
1122 void radsrv(struct request *rq) {
1123     uint8_t code, id, *auth, *attrs, *attr;
1124     uint16_t len;
1125     struct server *to = NULL;
1126     char username[256];
1127     unsigned char *buf, newauth[16];
1128
1129     buf = rq->buf;
1130     code = *(uint8_t *)buf;
1131     id = *(uint8_t *)(buf + 1);
1132     len = RADLEN(buf);
1133     auth = (uint8_t *)(buf + 4);
1134
1135     debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
1136     
1137     if (code != RAD_Access_Request && code != RAD_Status_Server) {
1138         debug(DBG_INFO, "radsrv: server currently accepts only access-requests and status-server, ignoring");
1139         free(buf);
1140         return;
1141     }
1142
1143     len -= 20;
1144     attrs = buf + 20;
1145
1146     if (!attrvalidate(attrs, len)) {
1147         debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
1148         free(buf);
1149         return;
1150     }
1151
1152     if (code == RAD_Access_Request) {
1153         attr = attrget(attrs, len, RAD_Attr_User_Name);
1154         if (!attr) {
1155             debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
1156             free(buf);
1157             return;
1158         }
1159         memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1160         username[ATTRVALLEN(attr)] = '\0';
1161         debug(DBG_DBG, "Access Request with username: %s", username);
1162     
1163         if (!id2server(&to, username, strlen(username))) {
1164             debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1165             free(buf);
1166             return;
1167         }
1168
1169         if (to && rqinqueue(to, rq->from, id)) {
1170             debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->peer.host, id);
1171             free(buf);
1172             return;
1173         }
1174     }
1175     
1176     attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1177     if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(buf, ATTRVAL(attr), rq->from->peer.secret))) {
1178         debug(DBG_WARN, "radsrv: message authentication failed");
1179         free(buf);
1180         return;
1181     }
1182     
1183     if (code == RAD_Status_Server) {
1184         respondstatusserver(rq);
1185         return;
1186     }
1187
1188     if (!to) {
1189         debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->peer.host, username);
1190         respondreject(rq);
1191         return;
1192     }
1193     
1194     if (!RAND_bytes(newauth, 16)) {
1195         debug(DBG_WARN, "radsrv: failed to generate random auth");
1196         free(buf);
1197         return;
1198     }
1199
1200 #ifdef DEBUG    
1201     printauth("auth", auth);
1202 #endif
1203
1204     attr = attrget(attrs, len, RAD_Attr_User_Password);
1205     if (attr) {
1206         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1207         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer.secret, to->peer.secret, auth, newauth)) {
1208             free(buf);
1209             return;
1210         }
1211     }
1212     
1213     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1214     if (attr) {
1215         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1216         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer.secret, to->peer.secret, auth, newauth)) {
1217             free(buf);
1218             return;
1219         }
1220     }
1221
1222     rq->origid = id;
1223     memcpy(rq->origauth, auth, 16);
1224     memcpy(auth, newauth, 16);
1225     sendrq(to, rq);
1226 }
1227
1228 void *clientrd(void *arg) {
1229     struct server *server = (struct server *)arg;
1230     struct client *from;
1231     int i, len, sublen;
1232     unsigned char *buf, *messageauth, *subattrs, *attrs, *attr;
1233     struct sockaddr_storage fromsa;
1234     struct timeval lastconnecttry;
1235     char tmp[256];
1236     
1237     for (;;) {
1238         lastconnecttry = server->lastconnecttry;
1239         buf = (server->peer.type == 'U' ? radudpget(server->sock, NULL, &server, NULL) : radtlsget(server->peer.ssl));
1240         if (!buf && server->peer.type == 'T') {
1241             tlsconnect(server, &lastconnecttry, "clientrd");
1242             continue;
1243         }
1244     
1245         server->connectionok = 1;
1246
1247         i = buf[1]; /* i is the id */
1248
1249         switch (*buf) {
1250         case RAD_Access_Accept:
1251             debug(DBG_DBG, "got Access Accept with id %d", i);
1252             break;
1253         case RAD_Access_Reject:
1254             debug(DBG_DBG, "got Access Reject with id %d", i);
1255             break;
1256         case RAD_Access_Challenge:
1257             debug(DBG_DBG, "got Access Challenge with id %d", i);
1258             break;
1259         default:
1260             free(buf);
1261             debug(DBG_INFO, "clientrd: discarding, only accept access accept, access reject and access challenge messages");
1262             continue;
1263         }
1264         
1265         pthread_mutex_lock(&server->newrq_mutex);
1266         if (!server->requests[i].buf || !server->requests[i].tries) {
1267             pthread_mutex_unlock(&server->newrq_mutex);
1268             free(buf);
1269             debug(DBG_INFO, "clientrd: no matching request sent with this id, ignoring");
1270             continue;
1271         }
1272
1273         if (server->requests[i].received) {
1274             pthread_mutex_unlock(&server->newrq_mutex);
1275             free(buf);
1276             debug(DBG_INFO, "clientrd: already received, ignoring");
1277             continue;
1278         }
1279         
1280         if (!validauth(buf, server->requests[i].buf + 4, (unsigned char *)server->peer.secret)) {
1281             pthread_mutex_unlock(&server->newrq_mutex);
1282             free(buf);
1283             debug(DBG_WARN, "clientrd: invalid auth, ignoring");
1284             continue;
1285         }
1286         
1287         from = server->requests[i].from;
1288         len = RADLEN(buf) - 20;
1289         attrs = buf + 20;
1290
1291         if (!attrvalidate(attrs, len)) {
1292             pthread_mutex_unlock(&server->newrq_mutex);
1293             free(buf);
1294             debug(DBG_WARN, "clientrd: attribute validation failed, ignoring packet");
1295             continue;
1296         }
1297         
1298         /* Message Authenticator */
1299         messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1300         if (messageauth) {
1301             if (ATTRVALLEN(messageauth) != 16) {
1302                 pthread_mutex_unlock(&server->newrq_mutex);
1303                 free(buf);
1304                 debug(DBG_WARN, "clientrd: illegal message auth attribute length, ignoring packet");
1305                 continue;
1306             }
1307             memcpy(tmp, buf + 4, 16);
1308             memcpy(buf + 4, server->requests[i].buf + 4, 16);
1309             if (!checkmessageauth(buf, ATTRVAL(messageauth), server->peer.secret)) {
1310                 pthread_mutex_unlock(&server->newrq_mutex);
1311                 free(buf);
1312                 debug(DBG_WARN, "clientrd: message authentication failed");
1313                 continue;
1314             }
1315             memcpy(buf + 4, tmp, 16);
1316             debug(DBG_DBG, "clientrd: message auth ok");
1317         }
1318         
1319         if (*server->requests[i].buf == RAD_Status_Server) {
1320             server->requests[i].received = 1;
1321             pthread_mutex_unlock(&server->newrq_mutex);
1322             free(buf);
1323             debug(DBG_INFO, "clientrd: got status server response from %s", server->peer.host);
1324             continue;
1325         }
1326
1327         /* MS MPPE */
1328         for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
1329             if (ATTRVALLEN(attr) <= 4)
1330                 break;
1331             
1332             if (((uint16_t *)attr)[1] != 0 || ntohs(((uint16_t *)attr)[2]) != 311) /* 311 == MS */
1333                 continue;
1334             
1335             sublen = ATTRVALLEN(attr) - 4;
1336             subattrs = ATTRVAL(attr) + 4;  
1337             if (!attrvalidate(subattrs, sublen) ||
1338                 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1339                         server->requests + i, server->peer.secret, from->peer.secret) ||
1340                 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1341                         server->requests + i, server->peer.secret, from->peer.secret))
1342                 break;
1343         }
1344         if (attr) {
1345             pthread_mutex_unlock(&server->newrq_mutex);
1346             free(buf);
1347             debug(DBG_WARN, "clientrd: MS attribute handling failed, ignoring packet");
1348             continue;
1349         }
1350         
1351         if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject) {
1352             attr = attrget(server->requests[i].buf + 20, RADLEN(server->requests[i].buf) - 20, RAD_Attr_User_Name);
1353             /* we know the attribute exists */
1354             memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
1355             tmp[ATTRVALLEN(attr)] = '\0';
1356             switch (*buf) {
1357             case RAD_Access_Accept:
1358                 debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->peer.host);
1359                 break;
1360             case RAD_Access_Reject:
1361                 debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->peer.host);
1362                 break;
1363             }
1364         }
1365         
1366         /* once we set received = 1, requests[i] may be reused */
1367         buf[1] = (char)server->requests[i].origid;
1368         memcpy(buf + 4, server->requests[i].origauth, 16);
1369 #ifdef DEBUG    
1370         printauth("origauth/buf+4", buf + 4);
1371 #endif
1372         
1373         if (messageauth) {
1374             if (!createmessageauth(buf, ATTRVAL(messageauth), from->peer.secret)) {
1375                 pthread_mutex_unlock(&server->newrq_mutex);
1376                 free(buf);
1377                 continue;
1378             }
1379             debug(DBG_DBG, "clientrd: computed messageauthattr");
1380         }
1381
1382         if (from->peer.type == 'U')
1383             fromsa = server->requests[i].fromsa;
1384         server->requests[i].received = 1;
1385         pthread_mutex_unlock(&server->newrq_mutex);
1386
1387         debug(DBG_DBG, "clientrd: giving packet back to where it came from");
1388         sendreply(from, buf, from->peer.type == 'U' ? &fromsa : NULL);
1389     }
1390 }
1391
1392 void *clientwr(void *arg) {
1393     struct server *server = (struct server *)arg;
1394     struct request *rq;
1395     pthread_t clientrdth;
1396     int i;
1397     uint8_t rnd;
1398     struct timeval now, lastsend;
1399     struct timespec timeout;
1400     struct request statsrvrq;
1401     unsigned char statsrvbuf[38];
1402
1403     memset(&timeout, 0, sizeof(struct timespec));
1404     
1405     if (server->statusserver) {
1406         memset(&statsrvrq, 0, sizeof(struct request));
1407         memset(statsrvbuf, 0, sizeof(statsrvbuf));
1408         statsrvbuf[0] = RAD_Status_Server;
1409         statsrvbuf[3] = 38;
1410         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
1411         statsrvbuf[21] = 18;
1412         gettimeofday(&lastsend, NULL);
1413     }
1414     
1415     if (server->peer.type == 'U') {
1416         if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0)
1417             debugx(1, DBG_ERR, "clientwr: connecttoserver failed");
1418     } else
1419         tlsconnect(server, NULL, "new client");
1420     
1421     if (pthread_create(&clientrdth, NULL, clientrd, (void *)server))
1422         debugx(1, DBG_ERR, "clientwr: pthread_create failed");
1423
1424     for (;;) {
1425         pthread_mutex_lock(&server->newrq_mutex);
1426         if (!server->newrq) {
1427             gettimeofday(&now, NULL);
1428             if (server->statusserver) {
1429                 /* random 0-7 seconds */
1430                 RAND_bytes(&rnd, 1);
1431                 rnd /= 32;
1432                 if (!timeout.tv_sec || timeout.tv_sec - now.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
1433                     timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
1434             }   
1435             if (timeout.tv_sec) {
1436                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1437                 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1438                 timeout.tv_sec = 0;
1439             } else {
1440                 debug(DBG_DBG, "clientwr: waiting for new request");
1441                 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
1442             }
1443         }
1444         if (server->newrq) {
1445             debug(DBG_DBG, "clientwr: got new request");
1446             server->newrq = 0;
1447         } else
1448             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1449         pthread_mutex_unlock(&server->newrq_mutex);
1450
1451         for (i = 0; i < MAX_REQUESTS; i++) {
1452             pthread_mutex_lock(&server->newrq_mutex);
1453             while (!server->requests[i].buf && i < MAX_REQUESTS)
1454                 i++;
1455             if (i == MAX_REQUESTS) {
1456                 pthread_mutex_unlock(&server->newrq_mutex);
1457                 break;
1458             }
1459             rq = server->requests + i;
1460
1461             if (rq->received) {
1462                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
1463                 if (rq->buf) {
1464                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
1465                     free(rq->buf);
1466                     /* setting this to NULL means that it can be reused */
1467                     rq->buf = NULL;
1468                 }
1469                 pthread_mutex_unlock(&server->newrq_mutex);
1470                 continue;
1471             }
1472             
1473             gettimeofday(&now, NULL);
1474             if (now.tv_sec < rq->expiry.tv_sec) {
1475                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1476                     timeout.tv_sec = rq->expiry.tv_sec;
1477                 pthread_mutex_unlock(&server->newrq_mutex);
1478                 continue;
1479             }
1480
1481             if (rq->tries == (*rq->buf == RAD_Status_Server || server->peer.type == 'T'
1482                               ? 1 : REQUEST_RETRIES)) {
1483                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1484                 if (*rq->buf == RAD_Status_Server)
1485                     debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->peer.host);
1486                 free(rq->buf);
1487                 /* setting this to NULL means that it can be reused */
1488                 rq->buf = NULL;
1489                 pthread_mutex_unlock(&server->newrq_mutex);
1490                 continue;
1491             }
1492             pthread_mutex_unlock(&server->newrq_mutex);
1493
1494             rq->expiry.tv_sec = now.tv_sec +
1495                 (*rq->buf == RAD_Status_Server || server->peer.type == 'T'
1496                  ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
1497             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1498                 timeout.tv_sec = rq->expiry.tv_sec;
1499             rq->tries++;
1500             clientradput(server, server->requests[i].buf);
1501             gettimeofday(&lastsend, NULL);
1502         }
1503         if (server->statusserver) {
1504             gettimeofday(&now, NULL);
1505             if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
1506                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
1507                     debug(DBG_WARN, "clientwr: failed to generate random auth");
1508                     continue;
1509                 }
1510                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
1511                 if (!statsrvrq.buf) {
1512                     debug(DBG_ERR, "clientwr: malloc failed");
1513                     continue;
1514                 }
1515                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
1516                 debug(DBG_DBG, "clientwr: sending status server to %s", server->peer.host);
1517                 lastsend.tv_sec = now.tv_sec;
1518                 sendrq(server, &statsrvrq);
1519             }
1520         }
1521     }
1522 }
1523
1524 void *udpserverwr(void *arg) {
1525     struct replyq *replyq = &udp_server_replyq;
1526     struct reply *reply = replyq->replies;
1527     
1528     pthread_mutex_lock(&replyq->count_mutex);
1529     for (;;) {
1530         while (!replyq->count) {
1531             debug(DBG_DBG, "udp server writer, waiting for signal");
1532             pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
1533             debug(DBG_DBG, "udp server writer, got signal");
1534         }
1535         pthread_mutex_unlock(&replyq->count_mutex);
1536         
1537         if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
1538                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
1539             debug(DBG_WARN, "sendudp: send failed");
1540         free(reply->buf);
1541         
1542         pthread_mutex_lock(&replyq->count_mutex);
1543         replyq->count--;
1544         memmove(replyq->replies, replyq->replies + 1,
1545                 replyq->count * sizeof(struct reply));
1546     }
1547 }
1548
1549 void *udpserverrd(void *arg) {
1550     struct request rq;
1551     pthread_t udpserverwrth;
1552
1553     if ((udp_server_sock = bindtoaddr(udp_server_listen->addrinfo)) < 0)
1554         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
1555
1556     debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
1557           udp_server_listen->host ? udp_server_listen->host : "*", udp_server_listen->port);
1558
1559     if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
1560         debugx(1, DBG_ERR, "pthread_create failed");
1561     
1562     for (;;) {
1563         memset(&rq, 0, sizeof(struct request));
1564         rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
1565         radsrv(&rq);
1566     }
1567 }
1568
1569 void *tlsserverwr(void *arg) {
1570     int cnt;
1571     unsigned long error;
1572     struct client *client = (struct client *)arg;
1573     struct replyq *replyq;
1574     
1575     debug(DBG_DBG, "tlsserverwr starting for %s", client->peer.host);
1576     replyq = client->replyq;
1577     pthread_mutex_lock(&replyq->count_mutex);
1578     for (;;) {
1579         while (!replyq->count) {
1580             if (client->peer.ssl) {         
1581                 debug(DBG_DBG, "tls server writer, waiting for signal");
1582                 pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
1583                 debug(DBG_DBG, "tls server writer, got signal");
1584             }
1585             if (!client->peer.ssl) {
1586                 /* ssl might have changed while waiting */
1587                 pthread_mutex_unlock(&replyq->count_mutex);
1588                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
1589                 pthread_exit(NULL);
1590             }
1591         }
1592         pthread_mutex_unlock(&replyq->count_mutex);
1593         cnt = SSL_write(client->peer.ssl, replyq->replies->buf, RADLEN(replyq->replies->buf));
1594         if (cnt > 0)
1595             debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
1596                   cnt, RADLEN(replyq->replies->buf));
1597         else
1598             while ((error = ERR_get_error()))
1599                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
1600         free(replyq->replies->buf);
1601
1602         pthread_mutex_lock(&replyq->count_mutex);
1603         replyq->count--;
1604         memmove(replyq->replies, replyq->replies + 1, replyq->count * sizeof(struct reply));
1605     }
1606 }
1607
1608 void *tlsserverrd(void *arg) {
1609     struct request rq;
1610     unsigned long error;
1611     int s;
1612     struct client *client = (struct client *)arg;
1613     pthread_t tlsserverwrth;
1614     SSL *ssl;
1615     
1616     debug(DBG_DBG, "tlsserverrd starting for %s", client->peer.host);
1617     ssl = client->peer.ssl;
1618
1619     if (SSL_accept(ssl) <= 0) {
1620         while ((error = ERR_get_error()))
1621             debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
1622         debug(DBG_ERR, "SSL_accept failed");
1623         goto errexit;
1624     }
1625     if (tlsverifycert(&client->peer)) {
1626         if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
1627             debug(DBG_ERR, "tlsserverrd: pthread_create failed");
1628             goto errexit;
1629         }
1630         for (;;) {
1631             memset(&rq, 0, sizeof(struct request));
1632             rq.buf = radtlsget(client->peer.ssl);
1633             if (!rq.buf)
1634                 break;
1635             debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->peer.host);
1636             rq.from = client;
1637             radsrv(&rq);
1638         }
1639         debug(DBG_ERR, "tlsserverrd: connection lost");
1640         /* stop writer by setting peer.ssl to NULL and give signal in case waiting for data */
1641         client->peer.ssl = NULL;
1642         pthread_mutex_lock(&client->replyq->count_mutex);
1643         pthread_cond_signal(&client->replyq->count_cond);
1644         pthread_mutex_unlock(&client->replyq->count_mutex);
1645         debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
1646         pthread_join(tlsserverwrth, NULL);
1647     }
1648     
1649  errexit:
1650     s = SSL_get_fd(ssl);
1651     SSL_free(ssl);
1652     shutdown(s, SHUT_RDWR);
1653     close(s);
1654     debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->peer.host);
1655     client->peer.ssl = NULL;
1656     pthread_exit(NULL);
1657 }
1658
1659 int tlslistener() {
1660     pthread_t tlsserverth;
1661     int s, snew;
1662     struct sockaddr_storage from;
1663     size_t fromlen = sizeof(from);
1664     struct client *client;
1665
1666     if ((s = bindtoaddr(tcp_server_listen->addrinfo)) < 0)
1667         debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
1668     
1669     listen(s, 0);
1670     debug(DBG_WARN, "listening for incoming TCP on %s:%s",
1671           tcp_server_listen->host ? tcp_server_listen->host : "*", tcp_server_listen->port);
1672
1673     for (;;) {
1674         snew = accept(s, (struct sockaddr *)&from, &fromlen);
1675         if (snew < 0) {
1676             debug(DBG_WARN, "accept failed");
1677             continue;
1678         }
1679         debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
1680
1681         client = find_client('T', (struct sockaddr *)&from, NULL);
1682         if (!client) {
1683             debug(DBG_WARN, "ignoring request, not a known TLS client");
1684             shutdown(snew, SHUT_RDWR);
1685             close(snew);
1686             continue;
1687         }
1688
1689         if (client->peer.ssl) {
1690             debug(DBG_WARN, "Ignoring incoming TLS connection, already have one from this client");
1691             shutdown(snew, SHUT_RDWR);
1692             close(snew);
1693             continue;
1694         }
1695         client->peer.ssl = SSL_new(ssl_ctx);
1696         SSL_set_fd(client->peer.ssl, snew);
1697         if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
1698             debug(DBG_ERR, "tlslistener: pthread_create failed");
1699             SSL_free(client->peer.ssl);
1700             shutdown(snew, SHUT_RDWR);
1701             close(snew);
1702             client->peer.ssl = NULL;
1703             continue;
1704         }
1705         pthread_detach(tlsserverth);
1706     }
1707     return 0;
1708 }
1709
1710 void addrealm(char *value, char *server) {
1711     int i, n;
1712     struct realm *realm;
1713     char *s, *regex = NULL;
1714
1715     if (server) {
1716         for (i = 0; i < server_count; i++)
1717             if (!strcasecmp(server, servers[i].peer.host))
1718                 break;
1719         if (i == server_count)
1720             debugx(1, DBG_ERR, "addrealm failed, no server %s", server);
1721     }
1722     
1723     if (*value != '/') {
1724         /* not a regexp, let us make it one */
1725         if (*value == '*' && !value[1])
1726             regex = stringcopy(".*", 0);
1727         else {
1728             for (n = 0, s = value; *s;)
1729                 if (*s++ == '.')
1730                     n++;
1731             regex = malloc(strlen(value) + n + 3);
1732             if (regex) {
1733                 regex[0] = '@';
1734                 for (n = 1, s = value; *s; s++) {
1735                     if (*s == '.')
1736                         regex[n++] = '\\';
1737                     regex[n++] = *s;
1738                 }
1739                 regex[n++] = '$';
1740                 regex[n] = '\0';
1741             }
1742         }
1743         if (!regex)
1744             debugx(1, DBG_ERR, "malloc failed");
1745         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
1746     }
1747
1748     realm_count++;
1749     realms = realloc(realms, realm_count * sizeof(struct realm));
1750     if (!realms)
1751         debugx(1, DBG_ERR, "malloc failed");
1752     realm = realms + realm_count - 1;
1753     memset(realm, 0, sizeof(struct realm));
1754     realm->name = stringcopy(value, 0);
1755     if (!realm->name)
1756         debugx(1, DBG_ERR, "malloc failed");
1757     if (server)
1758         realm->server = servers + i;
1759     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
1760         debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
1761     if (regex)
1762         free(regex);
1763     debug(DBG_DBG, "addrealm: added realm %s for server %s", value, server);
1764 }
1765
1766 char *parsehostport(char *s, struct peer *peer) {
1767     char *p, *field;
1768     int ipv6 = 0;
1769
1770     p = s;
1771     /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
1772     if (*p == '[') {
1773         p++;
1774         field = p;
1775         for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1776         if (*p != ']')
1777             debugx(1, DBG_ERR, "no ] matching initial [");
1778         ipv6 = 1;
1779     } else {
1780         field = p;
1781         for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1782     }
1783     if (field == p)
1784         debugx(1, DBG_ERR, "missing host/address");
1785
1786     peer->host = stringcopy(field, p - field);
1787     if (ipv6) {
1788         p++;
1789         if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
1790             debugx(1, DBG_ERR, "unexpected character after ]");
1791     }
1792     if (*p == ':') {
1793             /* port number or service name is specified */;
1794             field = ++p;
1795             for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1796             if (field == p)
1797                 debugx(1, DBG_ERR, "syntax error, : but no following port");
1798             peer->port = stringcopy(field, p - field);
1799     } else
1800         peer->port = stringcopy(peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
1801     return p;
1802 }
1803
1804 FILE *openconfigfile(const char *filename) {
1805     FILE *f;
1806     char pathname[100], *base = NULL;
1807     
1808     f = fopen(filename, "r");
1809     if (f) {
1810         debug(DBG_DBG, "reading config file %s", filename);
1811         return f;
1812     }
1813
1814     if (strlen(filename) + 1 <= sizeof(pathname)) {
1815         /* basename() might modify the string */
1816         strcpy(pathname, filename);
1817         base = basename(pathname);
1818         f = fopen(base, "r");
1819     }
1820
1821     if (!f)
1822         debugx(1, DBG_ERR, "could not read config file %s nor %s\n%s", filename, base, strerror(errno));
1823     
1824     debug(DBG_DBG, "reading config file %s", base);
1825     return f;
1826 }
1827
1828 struct peer *server_create(char type) {
1829     struct peer *server;
1830     char *conf;
1831
1832     server = malloc(sizeof(struct peer));
1833     if (!server)
1834         debugx(1, DBG_ERR, "malloc failed");
1835     memset(server, 0, sizeof(struct peer));
1836     server->type = type;
1837     conf = (type == 'T' ? options.listentcp : options.listenudp);
1838     if (conf) {
1839         parsehostport(conf, server);
1840         if (!strcmp(server->host, "*")) {
1841             free(server->host);
1842             server->host = NULL;
1843         }
1844     } else
1845         server->port = stringcopy(type == 'T' ? DEFAULT_TLS_PORT : DEFAULT_UDP_PORT, 0);
1846     if (!resolvepeer(server, AI_PASSIVE))
1847         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", server->host, server->port);
1848     return server;
1849 }
1850
1851 /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */
1852 char *strtokenquote(char *s, char **token, char *del, char *quote) {
1853     char *t = s, *q, *r;
1854
1855     if (!t || !token || !del)
1856         return NULL;
1857     while (*t && strchr(del, *t))
1858         t++;
1859     if (!*t) {
1860         *token = NULL;
1861         return t + 1; /* needs to be non-NULL, but value doesn't matter */
1862     }
1863     if (quote && (q = strchr(quote, *t))) {
1864         t++;
1865         r = t;
1866         while (*t && *t != *q)
1867             t++;
1868         if (!*t || (t[1] && !strchr(del, t[1])))
1869             return NULL;
1870         *t = '\0';
1871         *token = r;
1872         return t + 1;
1873     }
1874     *token = t;
1875     t++;
1876     while (*t && !strchr(del, *t))
1877         t++;
1878     *t = '\0';
1879     return t + 1;
1880 }
1881
1882 /* Parses config with following syntax:
1883  * One of these:
1884  * option-name value
1885  * option-name = value
1886  * Or:
1887  * option-name value {
1888  *     option-name [=] value
1889  *     ...
1890  * }
1891  */
1892 void getgeneralconfig(FILE *f, char *block, ...) {
1893     va_list ap;
1894     char line[1024];
1895     /* initialise lots of stuff to avoid stupid compiler warnings */
1896     char *tokens[3], *s, *opt = NULL, *val = NULL, *word, **str = NULL;
1897     int type = 0, tcount, conftype = 0;
1898     void (*cbk)(FILE *, char *, char *) = NULL;
1899         
1900     while (fgets(line, 1024, f)) {
1901         s = line;
1902         for (tcount = 0; tcount < 3; tcount++) {
1903             s = strtokenquote(s, &tokens[tcount], " \t\n", "\"'");
1904             if (!s)
1905                 debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line);
1906             if (!tokens[tcount])
1907                 break;
1908         }
1909         if (!tcount || **tokens == '#')
1910             continue;
1911
1912         if (**tokens == '}') {
1913             if (block)
1914                 return;
1915             debugx(1, DBG_ERR, "configuration error, found } with no matching {");
1916         }
1917             
1918         switch (tcount) {
1919         case 2:
1920             opt = tokens[0];
1921             val = tokens[1];
1922             conftype = CONF_STR;
1923             break;
1924         case 3:
1925             if (tokens[1][0] == '=' && tokens[1][1] == '\0') {
1926                 opt = tokens[0];
1927                 val = tokens[2];
1928                 conftype = CONF_STR;
1929                 break;
1930             }
1931             if (tokens[2][0] == '{' && tokens[2][1] == '\0') {
1932                 opt = tokens[0];
1933                 val = tokens[1];
1934                 conftype = CONF_CBK;
1935                 break;
1936             }
1937             /* fall through */
1938         default:
1939             if (block)
1940                 debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]);
1941             debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]);
1942         }
1943
1944         if (!*val)
1945             debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt);
1946         
1947         va_start(ap, block);
1948         while ((word = va_arg(ap, char *))) {
1949             type = va_arg(ap, int);
1950             switch (type) {
1951             case CONF_STR:
1952                 str = va_arg(ap, char **);
1953                 if (!str)
1954                     debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
1955                 break;
1956             case CONF_CBK:
1957                 cbk = va_arg(ap, void (*)(FILE *, char *, char *));
1958                 break;
1959             default:
1960                 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
1961             }
1962             if (!strcasecmp(opt, word))
1963                 break;
1964         }
1965         va_end(ap);
1966         
1967         if (!word) {
1968             if (block)
1969                 debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt);
1970             debugx(1, DBG_ERR, "configuration error, unknown option %s", opt);
1971         }
1972
1973         if (type != conftype) {
1974             if (block)
1975                 debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt);
1976             debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt);
1977         }
1978         
1979         switch (type) {
1980         case CONF_STR:
1981             if (block)
1982                 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
1983             else 
1984                 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
1985             *str = stringcopy(val, 0);
1986             break;
1987         case CONF_CBK:
1988             cbk(f, opt, val);
1989             break;
1990         default:
1991             debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
1992         }
1993     }
1994 }
1995
1996 void confclsrv_cb(FILE *f, char *opt, char *val) {
1997     char *type = NULL, *secret = NULL, *port = NULL, *statusserver = NULL;
1998     char *block;
1999     struct client *client = NULL;
2000     struct server *server = NULL;
2001     struct peer *peer;
2002
2003     block = malloc(strlen(opt) + strlen(val) + 2);
2004     if (!block)
2005         debugx(1, DBG_ERR, "malloc failed");
2006     sprintf(block, "%s %s", opt, val);
2007     debug(DBG_DBG, "confclsrv_cb called for %s", block);
2008     
2009     if (!strcasecmp(opt, "client")) {
2010         getgeneralconfig(f, block,
2011                          "type", CONF_STR, &type,
2012                          "secret", CONF_STR, &secret,
2013                          NULL
2014                          );
2015         client_count++;
2016         clients = realloc(clients, client_count * sizeof(struct client));
2017         if (!clients)
2018             debugx(1, DBG_ERR, "malloc failed");
2019         client = clients + client_count - 1;
2020         memset(client, 0, sizeof(struct client));
2021         peer = &client->peer;
2022     } else {
2023         getgeneralconfig(f, block,
2024                          "type", CONF_STR, &type,
2025                          "secret", CONF_STR, &secret,
2026                          "port", CONF_STR, &port,
2027                          "StatusServer", CONF_STR, &statusserver,
2028                          NULL
2029                          );
2030         server_count++;
2031         servers = realloc(servers, server_count * sizeof(struct server));
2032         if (!servers)
2033             debugx(1, DBG_ERR, "malloc failed");
2034         server = servers + server_count - 1;
2035         memset(server, 0, sizeof(struct server));
2036         peer = &server->peer;
2037         peer->port = port;
2038         if (statusserver) {
2039             if (!strcasecmp(statusserver, "on"))
2040                 server->statusserver = 1;
2041             else if (strcasecmp(statusserver, "off"))
2042                 debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
2043             free(statusserver);
2044         }
2045     }
2046     
2047     peer->host = stringcopy(val, 0);
2048     
2049     if (type && !strcasecmp(type, "udp")) {
2050         peer->type = 'U';
2051         if (client)
2052             client_udp_count++;
2053         else {
2054             server_udp_count++;
2055             if (!port)
2056                 peer->port = stringcopy(DEFAULT_UDP_PORT, 0);
2057         }
2058     } else if (type && !strcasecmp(type, "tls")) {
2059         peer->type = 'T';
2060         if (client)
2061             client_tls_count++;
2062         else {
2063             server_tls_count++;
2064             if (!port)
2065                 peer->port = stringcopy(DEFAULT_TLS_PORT, 0);
2066         }
2067     } else
2068         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2069     free(type);
2070     
2071     if (!resolvepeer(peer, 0))
2072         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", peer->host, peer->port);
2073     
2074     if (!secret) {
2075         if (peer->type == 'U')
2076             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2077         peer->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2078     } else {
2079         peer->secret = secret;
2080     }
2081
2082     if (client) {
2083         if (peer->type == 'U')
2084             client->replyq = &udp_server_replyq;
2085         else {
2086             client->replyq = malloc(sizeof(struct replyq));
2087             if (!client->replyq)
2088                 debugx(1, DBG_ERR, "malloc failed");
2089             client->replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
2090             if (!client->replyq->replies)
2091                 debugx(1, DBG_ERR, "malloc failed");
2092             client->replyq->size = MAX_REQUESTS;
2093             client->replyq->count = 0;
2094             pthread_mutex_init(&client->replyq->count_mutex, NULL);
2095             pthread_cond_init(&client->replyq->count_cond, NULL);
2096         }
2097     } else {
2098         pthread_mutex_init(&server->lock, NULL);
2099         server->sock = -1;
2100         server->requests = calloc(MAX_REQUESTS, sizeof(struct request));
2101         if (!server->requests)
2102             debugx(1, DBG_ERR, "malloc failed");
2103         server->newrq = 0;
2104         pthread_mutex_init(&server->newrq_mutex, NULL);
2105         pthread_cond_init(&server->newrq_cond, NULL);
2106     }
2107     
2108     free(block);
2109 }
2110
2111 void confrealm_cb(FILE *f, char *opt, char *val) {
2112     char *server = NULL;
2113     char *block;
2114     
2115     block = malloc(strlen(opt) + strlen(val) + 2);
2116     if (!block)
2117         debugx(1, DBG_ERR, "malloc failed");
2118     sprintf(block, "%s %s", opt, val);
2119     debug(DBG_DBG, "confrealm_cb called for %s", block);
2120     
2121     getgeneralconfig(f, block,
2122                      "server", CONF_STR, &server,
2123                      NULL
2124                      );
2125 #if 0    
2126     if (!server)
2127         debugx(1, DBG_ERR, "error in block %s, server must be specified", block);
2128 #endif
2129     addrealm(val, server);
2130     free(server);
2131     free(block);
2132 }
2133
2134 void getmainconfig(const char *configfile) {
2135     FILE *f;
2136     char *loglevel = NULL;
2137
2138     f = openconfigfile(configfile);
2139     memset(&options, 0, sizeof(options));
2140
2141     getgeneralconfig(f, NULL,
2142                      "TLSCACertificateFile", CONF_STR, &options.tlscacertificatefile,
2143                      "TLSCACertificatePath", CONF_STR, &options.tlscacertificatepath,
2144                      "TLSCertificateFile", CONF_STR, &options.tlscertificatefile,
2145                      "TLSCertificateKeyFile", CONF_STR, &options.tlscertificatekeyfile,
2146                      "TLSCertificateKeyPassword", CONF_STR, &options.tlscertificatekeypassword,
2147                      "ListenUDP", CONF_STR, &options.listenudp,
2148                      "ListenTCP", CONF_STR, &options.listentcp,
2149                      "LogLevel", CONF_STR, &loglevel,
2150                      "LogDestination", CONF_STR, &options.logdestination,
2151                      "Client", CONF_CBK, confclsrv_cb,
2152                      "Server", CONF_CBK, confclsrv_cb,
2153                      "Realm", CONF_CBK, confrealm_cb,
2154                      NULL
2155                      );
2156     fclose(f);
2157
2158     if (loglevel) {
2159         if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
2160             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
2161         options.loglevel = *loglevel - '0';
2162         free(loglevel);
2163     }
2164
2165     if (client_udp_count) {
2166         udp_server_replyq.replies = malloc(client_udp_count * MAX_REQUESTS * sizeof(struct reply));
2167         if (!udp_server_replyq.replies)
2168             debugx(1, DBG_ERR, "malloc failed");
2169         udp_server_replyq.size = client_udp_count * MAX_REQUESTS;
2170         udp_server_replyq.count = 0;
2171         pthread_mutex_init(&udp_server_replyq.count_mutex, NULL);
2172         pthread_cond_init(&udp_server_replyq.count_cond, NULL);
2173     }    
2174 }
2175
2176 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *loglevel, char **configfile) {
2177     int c;
2178
2179     while ((c = getopt(argc, argv, "c:d:fv")) != -1) {
2180         switch (c) {
2181         case 'c':
2182             *configfile = optarg;
2183             break;
2184         case 'd':
2185             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
2186                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
2187             *loglevel = *optarg - '0';
2188             break;
2189         case 'f':
2190             *foreground = 1;
2191             break;
2192         case 'v':
2193                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
2194         default:
2195             goto usage;
2196         }
2197     }
2198     if (!(argc - optind))
2199         return;
2200
2201  usage:
2202     debug(DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -v ]", argv[0]);
2203     exit(1);
2204 }
2205
2206 int main(int argc, char **argv) {
2207     pthread_t udpserverth;
2208     int i;
2209     uint8_t foreground = 0, loglevel = 0;
2210     char *configfile = NULL;
2211     
2212     debug_init("radsecproxy");
2213     debug_set_level(DEBUG_LEVEL);
2214     getargs(argc, argv, &foreground, &loglevel, &configfile);
2215     if (loglevel)
2216         debug_set_level(loglevel);
2217     getmainconfig(configfile ? configfile : CONFIG_MAIN);
2218     if (loglevel)
2219         options.loglevel = loglevel;
2220     else if (options.loglevel)
2221         debug_set_level(options.loglevel);
2222     if (foreground)
2223         options.logdestination = NULL;
2224     else {
2225         if (!options.logdestination)
2226             options.logdestination = "x-syslog://";
2227         debug_set_destination(options.logdestination);
2228     }
2229
2230     if (!server_count)
2231         debugx(1, DBG_ERR, "No servers configured, nothing to do, exiting");
2232     if (!client_count)
2233         debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
2234     if (!realm_count)
2235         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
2236
2237     if (!foreground && (daemon(0, 0) < 0))
2238         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
2239         
2240     if (client_udp_count) {
2241         udp_server_listen = server_create('U');
2242         if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
2243             debugx(1, DBG_ERR, "pthread_create failed");
2244     }
2245     
2246     if (client_tls_count || server_tls_count)
2247         ssl_ctx = ssl_init();
2248     
2249     for (i = 0; i < server_count; i++)
2250         if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
2251             debugx(1, DBG_ERR, "pthread_create failed");
2252
2253     if (client_tls_count) {
2254         tcp_server_listen = server_create('T');
2255         return tlslistener();
2256     }
2257     
2258     /* just hang around doing nothing, anything to do here? */
2259     for (;;)
2260         sleep(1000);
2261 }