support quoting of values, realm matching literal or regexp with / prefixing a regexp
[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 struct server *id2server(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             return realms[i].server;
1004         }
1005     return NULL;
1006 }
1007
1008 int rqinqueue(struct server *to, struct client *from, uint8_t id) {
1009     int i;
1010     
1011     pthread_mutex_lock(&to->newrq_mutex);
1012     for (i = 0; i < MAX_REQUESTS; i++)
1013         if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from)
1014             break;
1015     pthread_mutex_unlock(&to->newrq_mutex);
1016     
1017     return i < MAX_REQUESTS;
1018 }
1019
1020 int attrvalidate(unsigned char *attrs, int length) {
1021     while (length > 1) {
1022         if (ATTRLEN(attrs) < 2) {
1023             debug(DBG_WARN, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
1024             return 0;
1025         }
1026         length -= ATTRLEN(attrs);
1027         if (length < 0) {
1028             debug(DBG_WARN, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
1029             return 0;
1030         }
1031         attrs += ATTRLEN(attrs);
1032     }
1033     if (length)
1034         debug(DBG_WARN, "attrvalidate: malformed packet? remaining byte after last attribute");
1035     return 1;
1036 }
1037
1038 int pwdrecrypt(uint8_t *pwd, uint8_t len, char *oldsecret, char *newsecret, uint8_t *oldauth, uint8_t *newauth) {
1039 #ifdef DEBUG    
1040     int i;
1041 #endif    
1042     if (len < 16 || len > 128 || len % 16) {
1043         debug(DBG_WARN, "pwdrecrypt: invalid password length");
1044         return 0;
1045     }
1046         
1047     if (!pwddecrypt(pwd, len, oldsecret, strlen(oldsecret), oldauth)) {
1048         debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
1049         return 0;
1050     }
1051 #ifdef DEBUG
1052     printf("pwdrecrypt: password: ");
1053     for (i = 0; i < len; i++)
1054         printf("%02x ", pwd[i]);
1055     printf("\n");
1056 #endif  
1057     if (!pwdencrypt(pwd, len, newsecret, strlen(newsecret), newauth)) {
1058         debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
1059         return 0;
1060     }
1061     return 1;
1062 }
1063
1064 int msmpprecrypt(uint8_t *msmpp, uint8_t len, char *oldsecret, char *newsecret, unsigned char *oldauth, char *newauth) {
1065     if (len < 18)
1066         return 0;
1067     if (!msmppdecrypt(msmpp + 2, len - 2, (unsigned char *)oldsecret, strlen(oldsecret), oldauth, msmpp)) {
1068         debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
1069         return 0;
1070     }
1071     if (!msmppencrypt(msmpp + 2, len - 2, (unsigned char *)newsecret, strlen(newsecret), (unsigned char *)newauth, msmpp)) {
1072         debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
1073         return 0;
1074     }
1075     return 1;
1076 }
1077
1078 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
1079            char *oldsecret, char *newsecret) {
1080     unsigned char *attr;
1081     
1082     for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
1083         debug(DBG_DBG, "msmppe: Got %s", attrtxt);
1084         if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, newsecret, rq->buf + 4, rq->origauth))
1085             return 0;
1086     }
1087     return 1;
1088 }
1089
1090 void respondstatusserver(struct request *rq) {
1091     unsigned char *resp;
1092
1093     resp = malloc(20);
1094     if (!resp) {
1095         debug(DBG_ERR, "respondstatusserver: malloc failed");
1096         return;
1097     }
1098     memcpy(resp, rq->buf, 20);
1099     resp[0] = RAD_Access_Accept;
1100     resp[2] = 0;
1101     resp[3] = 20;
1102     debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->peer.host);
1103     sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL);
1104 }
1105
1106 void radsrv(struct request *rq) {
1107     uint8_t code, id, *auth, *attrs, *attr;
1108     uint16_t len;
1109     struct server *to = NULL;
1110     char username[256];
1111     unsigned char *buf, newauth[16];
1112
1113     buf = rq->buf;
1114     code = *(uint8_t *)buf;
1115     id = *(uint8_t *)(buf + 1);
1116     len = RADLEN(buf);
1117     auth = (uint8_t *)(buf + 4);
1118
1119     debug(DBG_DBG, "radsrv: code %d, id %d, length %d", code, id, len);
1120     
1121     if (code != RAD_Access_Request && code != RAD_Status_Server) {
1122         debug(DBG_INFO, "radsrv: server currently accepts only access-requests and status-server, ignoring");
1123         free(buf);
1124         return;
1125     }
1126
1127     len -= 20;
1128     attrs = buf + 20;
1129
1130     if (!attrvalidate(attrs, len)) {
1131         debug(DBG_WARN, "radsrv: attribute validation failed, ignoring packet");
1132         free(buf);
1133         return;
1134     }
1135
1136     if (code == RAD_Access_Request) {
1137         attr = attrget(attrs, len, RAD_Attr_User_Name);
1138         if (!attr) {
1139             debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
1140             free(buf);
1141             return;
1142         }
1143         memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
1144         username[ATTRVALLEN(attr)] = '\0';
1145         debug(DBG_DBG, "Access Request with username: %s", username);
1146     
1147         to = id2server(username, strlen(username));
1148         if (!to) {
1149             debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1150             free(buf);
1151             return;
1152         }
1153     
1154         if (rqinqueue(to, rq->from, id)) {
1155             debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->peer.host, id);
1156             free(buf);
1157             return;
1158         }
1159     }
1160     
1161     attr = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1162     if (attr && (ATTRVALLEN(attr) != 16 || !checkmessageauth(buf, ATTRVAL(attr), rq->from->peer.secret))) {
1163         debug(DBG_WARN, "radsrv: message authentication failed");
1164         free(buf);
1165         return;
1166     }
1167     
1168     if (code == RAD_Status_Server) {
1169         respondstatusserver(rq);
1170         return;
1171     }
1172     
1173     if (!RAND_bytes(newauth, 16)) {
1174         debug(DBG_WARN, "radsrv: failed to generate random auth");
1175         free(buf);
1176         return;
1177     }
1178
1179 #ifdef DEBUG    
1180     printauth("auth", auth);
1181 #endif
1182
1183     attr = attrget(attrs, len, RAD_Attr_User_Password);
1184     if (attr) {
1185         debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", ATTRVALLEN(attr));
1186         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer.secret, to->peer.secret, auth, newauth)) {
1187             free(buf);
1188             return;
1189         }
1190     }
1191     
1192     attr = attrget(attrs, len, RAD_Attr_Tunnel_Password);
1193     if (attr) {
1194         debug(DBG_DBG, "radsrv: found tunnelpwdattr with value length %d", ATTRVALLEN(attr));
1195         if (!pwdrecrypt(ATTRVAL(attr), ATTRVALLEN(attr), rq->from->peer.secret, to->peer.secret, auth, newauth)) {
1196             free(buf);
1197             return;
1198         }
1199     }
1200
1201     rq->origid = id;
1202     memcpy(rq->origauth, auth, 16);
1203     memcpy(auth, newauth, 16);
1204     sendrq(to, rq);
1205 }
1206
1207 void *clientrd(void *arg) {
1208     struct server *server = (struct server *)arg;
1209     struct client *from;
1210     int i, len, sublen;
1211     unsigned char *buf, *messageauth, *subattrs, *attrs, *attr;
1212     struct sockaddr_storage fromsa;
1213     struct timeval lastconnecttry;
1214     char tmp[256];
1215     
1216     for (;;) {
1217         lastconnecttry = server->lastconnecttry;
1218         buf = (server->peer.type == 'U' ? radudpget(server->sock, NULL, &server, NULL) : radtlsget(server->peer.ssl));
1219         if (!buf && server->peer.type == 'T') {
1220             tlsconnect(server, &lastconnecttry, "clientrd");
1221             continue;
1222         }
1223     
1224         server->connectionok = 1;
1225
1226         i = buf[1]; /* i is the id */
1227
1228         switch (*buf) {
1229         case RAD_Access_Accept:
1230             debug(DBG_DBG, "got Access Accept with id %d", i);
1231             break;
1232         case RAD_Access_Reject:
1233             debug(DBG_DBG, "got Access Reject with id %d", i);
1234             break;
1235         case RAD_Access_Challenge:
1236             debug(DBG_DBG, "got Access Challenge with id %d", i);
1237             break;
1238         default:
1239             free(buf);
1240             debug(DBG_INFO, "clientrd: discarding, only accept access accept, access reject and access challenge messages");
1241             continue;
1242         }
1243         
1244         pthread_mutex_lock(&server->newrq_mutex);
1245         if (!server->requests[i].buf || !server->requests[i].tries) {
1246             pthread_mutex_unlock(&server->newrq_mutex);
1247             free(buf);
1248             debug(DBG_INFO, "clientrd: no matching request sent with this id, ignoring");
1249             continue;
1250         }
1251
1252         if (server->requests[i].received) {
1253             pthread_mutex_unlock(&server->newrq_mutex);
1254             free(buf);
1255             debug(DBG_INFO, "clientrd: already received, ignoring");
1256             continue;
1257         }
1258         
1259         if (!validauth(buf, server->requests[i].buf + 4, (unsigned char *)server->peer.secret)) {
1260             pthread_mutex_unlock(&server->newrq_mutex);
1261             free(buf);
1262             debug(DBG_WARN, "clientrd: invalid auth, ignoring");
1263             continue;
1264         }
1265         
1266         from = server->requests[i].from;
1267         len = RADLEN(buf) - 20;
1268         attrs = buf + 20;
1269
1270         if (!attrvalidate(attrs, len)) {
1271             pthread_mutex_unlock(&server->newrq_mutex);
1272             free(buf);
1273             debug(DBG_WARN, "clientrd: attribute validation failed, ignoring packet");
1274             continue;
1275         }
1276         
1277         /* Message Authenticator */
1278         messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator);
1279         if (messageauth) {
1280             if (ATTRVALLEN(messageauth) != 16) {
1281                 pthread_mutex_unlock(&server->newrq_mutex);
1282                 free(buf);
1283                 debug(DBG_WARN, "clientrd: illegal message auth attribute length, ignoring packet");
1284                 continue;
1285             }
1286             memcpy(tmp, buf + 4, 16);
1287             memcpy(buf + 4, server->requests[i].buf + 4, 16);
1288             if (!checkmessageauth(buf, ATTRVAL(messageauth), server->peer.secret)) {
1289                 pthread_mutex_unlock(&server->newrq_mutex);
1290                 free(buf);
1291                 debug(DBG_WARN, "clientrd: message authentication failed");
1292                 continue;
1293             }
1294             memcpy(buf + 4, tmp, 16);
1295             debug(DBG_DBG, "clientrd: message auth ok");
1296         }
1297         
1298         if (*server->requests[i].buf == RAD_Status_Server) {
1299             server->requests[i].received = 1;
1300             pthread_mutex_unlock(&server->newrq_mutex);
1301             free(buf);
1302             debug(DBG_INFO, "clientrd: got status server response from %s", server->peer.host);
1303             continue;
1304         }
1305
1306         /* MS MPPE */
1307         for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
1308             if (ATTRVALLEN(attr) <= 4)
1309                 break;
1310             
1311             if (((uint16_t *)attr)[1] != 0 || ntohs(((uint16_t *)attr)[2]) != 311) /* 311 == MS */
1312                 continue;
1313             
1314             sublen = ATTRVALLEN(attr) - 4;
1315             subattrs = ATTRVAL(attr) + 4;  
1316             if (!attrvalidate(subattrs, sublen) ||
1317                 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1318                         server->requests + i, server->peer.secret, from->peer.secret) ||
1319                 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1320                         server->requests + i, server->peer.secret, from->peer.secret))
1321                 break;
1322         }
1323         if (attr) {
1324             pthread_mutex_unlock(&server->newrq_mutex);
1325             free(buf);
1326             debug(DBG_WARN, "clientrd: MS attribute handling failed, ignoring packet");
1327             continue;
1328         }
1329         
1330         if (*buf == RAD_Access_Accept || *buf == RAD_Access_Reject) {
1331             attr = attrget(server->requests[i].buf + 20, RADLEN(server->requests[i].buf) - 20, RAD_Attr_User_Name);
1332             /* we know the attribute exists */
1333             memcpy(tmp, ATTRVAL(attr), ATTRVALLEN(attr));
1334             tmp[ATTRVALLEN(attr)] = '\0';
1335             switch (*buf) {
1336             case RAD_Access_Accept:
1337                 debug(DBG_INFO, "Access Accept for %s from %s", tmp, server->peer.host);
1338                 break;
1339             case RAD_Access_Reject:
1340                 debug(DBG_INFO, "Access Reject for %s from %s", tmp, server->peer.host);
1341                 break;
1342             }
1343         }
1344         
1345         /* once we set received = 1, requests[i] may be reused */
1346         buf[1] = (char)server->requests[i].origid;
1347         memcpy(buf + 4, server->requests[i].origauth, 16);
1348 #ifdef DEBUG    
1349         printauth("origauth/buf+4", buf + 4);
1350 #endif
1351         
1352         if (messageauth) {
1353             if (!createmessageauth(buf, ATTRVAL(messageauth), from->peer.secret)) {
1354                 pthread_mutex_unlock(&server->newrq_mutex);
1355                 free(buf);
1356                 continue;
1357             }
1358             debug(DBG_DBG, "clientrd: computed messageauthattr");
1359         }
1360
1361         if (from->peer.type == 'U')
1362             fromsa = server->requests[i].fromsa;
1363         server->requests[i].received = 1;
1364         pthread_mutex_unlock(&server->newrq_mutex);
1365
1366         debug(DBG_DBG, "clientrd: giving packet back to where it came from");
1367         sendreply(from, buf, from->peer.type == 'U' ? &fromsa : NULL);
1368     }
1369 }
1370
1371 void *clientwr(void *arg) {
1372     struct server *server = (struct server *)arg;
1373     struct request *rq;
1374     pthread_t clientrdth;
1375     int i;
1376     uint8_t rnd;
1377     struct timeval now, lastsend;
1378     struct timespec timeout;
1379     struct request statsrvrq;
1380     unsigned char statsrvbuf[38];
1381
1382     memset(&timeout, 0, sizeof(struct timespec));
1383     
1384     if (server->statusserver) {
1385         memset(&statsrvrq, 0, sizeof(struct request));
1386         memset(statsrvbuf, 0, sizeof(statsrvbuf));
1387         statsrvbuf[0] = RAD_Status_Server;
1388         statsrvbuf[3] = 38;
1389         statsrvbuf[20] = RAD_Attr_Message_Authenticator;
1390         statsrvbuf[21] = 18;
1391         gettimeofday(&lastsend, NULL);
1392     }
1393     
1394     if (server->peer.type == 'U') {
1395         if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0)
1396             debugx(1, DBG_ERR, "clientwr: connecttoserver failed");
1397     } else
1398         tlsconnect(server, NULL, "new client");
1399     
1400     if (pthread_create(&clientrdth, NULL, clientrd, (void *)server))
1401         debugx(1, DBG_ERR, "clientwr: pthread_create failed");
1402
1403     for (;;) {
1404         pthread_mutex_lock(&server->newrq_mutex);
1405         if (!server->newrq) {
1406             gettimeofday(&now, NULL);
1407             if (server->statusserver) {
1408                 /* random 0-7 seconds */
1409                 RAND_bytes(&rnd, 1);
1410                 rnd /= 32;
1411                 if (!timeout.tv_sec || timeout.tv_sec - now.tv_sec > lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd)
1412                     timeout.tv_sec = lastsend.tv_sec + STATUS_SERVER_PERIOD + rnd;
1413             }   
1414             if (timeout.tv_sec) {
1415                 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1416                 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1417                 timeout.tv_sec = 0;
1418             } else {
1419                 debug(DBG_DBG, "clientwr: waiting for new request");
1420                 pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex);
1421             }
1422         }
1423         if (server->newrq) {
1424             debug(DBG_DBG, "clientwr: got new request");
1425             server->newrq = 0;
1426         } else
1427             debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1428         pthread_mutex_unlock(&server->newrq_mutex);
1429
1430         for (i = 0; i < MAX_REQUESTS; i++) {
1431             pthread_mutex_lock(&server->newrq_mutex);
1432             while (!server->requests[i].buf && i < MAX_REQUESTS)
1433                 i++;
1434             if (i == MAX_REQUESTS) {
1435                 pthread_mutex_unlock(&server->newrq_mutex);
1436                 break;
1437             }
1438             rq = server->requests + i;
1439
1440             if (rq->received) {
1441                 debug(DBG_DBG, "clientwr: packet %d in queue is marked as received", i);
1442                 if (rq->buf) {
1443                     debug(DBG_DBG, "clientwr: freeing received packet %d from queue", i);
1444                     free(rq->buf);
1445                     /* setting this to NULL means that it can be reused */
1446                     rq->buf = NULL;
1447                 }
1448                 pthread_mutex_unlock(&server->newrq_mutex);
1449                 continue;
1450             }
1451             
1452             gettimeofday(&now, NULL);
1453             if (now.tv_sec < rq->expiry.tv_sec) {
1454                 if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1455                     timeout.tv_sec = rq->expiry.tv_sec;
1456                 pthread_mutex_unlock(&server->newrq_mutex);
1457                 continue;
1458             }
1459
1460             if (rq->tries == (*rq->buf == RAD_Status_Server || server->peer.type == 'T'
1461                               ? 1 : REQUEST_RETRIES)) {
1462                 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1463                 if (*rq->buf == RAD_Status_Server)
1464                     debug(DBG_WARN, "clientwr: no status server response, %s dead?", server->peer.host);
1465                 free(rq->buf);
1466                 /* setting this to NULL means that it can be reused */
1467                 rq->buf = NULL;
1468                 pthread_mutex_unlock(&server->newrq_mutex);
1469                 continue;
1470             }
1471             pthread_mutex_unlock(&server->newrq_mutex);
1472
1473             rq->expiry.tv_sec = now.tv_sec +
1474                 (*rq->buf == RAD_Status_Server || server->peer.type == 'T'
1475                  ? REQUEST_EXPIRY : REQUEST_EXPIRY / REQUEST_RETRIES);
1476             if (!timeout.tv_sec || rq->expiry.tv_sec < timeout.tv_sec)
1477                 timeout.tv_sec = rq->expiry.tv_sec;
1478             rq->tries++;
1479             clientradput(server, server->requests[i].buf);
1480             gettimeofday(&lastsend, NULL);
1481         }
1482         if (server->statusserver) {
1483             gettimeofday(&now, NULL);
1484             if (now.tv_sec - lastsend.tv_sec >= STATUS_SERVER_PERIOD) {
1485                 if (!RAND_bytes(statsrvbuf + 4, 16)) {
1486                     debug(DBG_WARN, "clientwr: failed to generate random auth");
1487                     continue;
1488                 }
1489                 statsrvrq.buf = malloc(sizeof(statsrvbuf));
1490                 if (!statsrvrq.buf) {
1491                     debug(DBG_ERR, "clientwr: malloc failed");
1492                     continue;
1493                 }
1494                 memcpy(statsrvrq.buf, statsrvbuf, sizeof(statsrvbuf));
1495                 debug(DBG_DBG, "clientwr: sending status server to %s", server->peer.host);
1496                 lastsend.tv_sec = now.tv_sec;
1497                 sendrq(server, &statsrvrq);
1498             }
1499         }
1500     }
1501 }
1502
1503 void *udpserverwr(void *arg) {
1504     struct replyq *replyq = &udp_server_replyq;
1505     struct reply *reply = replyq->replies;
1506     
1507     pthread_mutex_lock(&replyq->count_mutex);
1508     for (;;) {
1509         while (!replyq->count) {
1510             debug(DBG_DBG, "udp server writer, waiting for signal");
1511             pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
1512             debug(DBG_DBG, "udp server writer, got signal");
1513         }
1514         pthread_mutex_unlock(&replyq->count_mutex);
1515         
1516         if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
1517                    (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
1518             debug(DBG_WARN, "sendudp: send failed");
1519         free(reply->buf);
1520         
1521         pthread_mutex_lock(&replyq->count_mutex);
1522         replyq->count--;
1523         memmove(replyq->replies, replyq->replies + 1,
1524                 replyq->count * sizeof(struct reply));
1525     }
1526 }
1527
1528 void *udpserverrd(void *arg) {
1529     struct request rq;
1530     pthread_t udpserverwrth;
1531
1532     if ((udp_server_sock = bindtoaddr(udp_server_listen->addrinfo)) < 0)
1533         debugx(1, DBG_ERR, "udpserverrd: socket/bind failed");
1534
1535     debug(DBG_WARN, "udpserverrd: listening for UDP on %s:%s",
1536           udp_server_listen->host ? udp_server_listen->host : "*", udp_server_listen->port);
1537
1538     if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
1539         debugx(1, DBG_ERR, "pthread_create failed");
1540     
1541     for (;;) {
1542         memset(&rq, 0, sizeof(struct request));
1543         rq.buf = radudpget(udp_server_sock, &rq.from, NULL, &rq.fromsa);
1544         radsrv(&rq);
1545     }
1546 }
1547
1548 void *tlsserverwr(void *arg) {
1549     int cnt;
1550     unsigned long error;
1551     struct client *client = (struct client *)arg;
1552     struct replyq *replyq;
1553     
1554     debug(DBG_DBG, "tlsserverwr starting for %s", client->peer.host);
1555     replyq = client->replyq;
1556     pthread_mutex_lock(&replyq->count_mutex);
1557     for (;;) {
1558         while (!replyq->count) {
1559             if (client->peer.ssl) {         
1560                 debug(DBG_DBG, "tls server writer, waiting for signal");
1561                 pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
1562                 debug(DBG_DBG, "tls server writer, got signal");
1563             }
1564             if (!client->peer.ssl) {
1565                 /* ssl might have changed while waiting */
1566                 pthread_mutex_unlock(&replyq->count_mutex);
1567                 debug(DBG_DBG, "tlsserverwr: exiting as requested");
1568                 pthread_exit(NULL);
1569             }
1570         }
1571         pthread_mutex_unlock(&replyq->count_mutex);
1572         cnt = SSL_write(client->peer.ssl, replyq->replies->buf, RADLEN(replyq->replies->buf));
1573         if (cnt > 0)
1574             debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
1575                   cnt, RADLEN(replyq->replies->buf));
1576         else
1577             while ((error = ERR_get_error()))
1578                 debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
1579         free(replyq->replies->buf);
1580
1581         pthread_mutex_lock(&replyq->count_mutex);
1582         replyq->count--;
1583         memmove(replyq->replies, replyq->replies + 1, replyq->count * sizeof(struct reply));
1584     }
1585 }
1586
1587 void *tlsserverrd(void *arg) {
1588     struct request rq;
1589     unsigned long error;
1590     int s;
1591     struct client *client = (struct client *)arg;
1592     pthread_t tlsserverwrth;
1593     SSL *ssl;
1594     
1595     debug(DBG_DBG, "tlsserverrd starting for %s", client->peer.host);
1596     ssl = client->peer.ssl;
1597
1598     if (SSL_accept(ssl) <= 0) {
1599         while ((error = ERR_get_error()))
1600             debug(DBG_ERR, "tlsserverrd: SSL: %s", ERR_error_string(error, NULL));
1601         debug(DBG_ERR, "SSL_accept failed");
1602         goto errexit;
1603     }
1604     if (tlsverifycert(&client->peer)) {
1605         if (pthread_create(&tlsserverwrth, NULL, tlsserverwr, (void *)client)) {
1606             debug(DBG_ERR, "tlsserverrd: pthread_create failed");
1607             goto errexit;
1608         }
1609         for (;;) {
1610             memset(&rq, 0, sizeof(struct request));
1611             rq.buf = radtlsget(client->peer.ssl);
1612             if (!rq.buf)
1613                 break;
1614             debug(DBG_DBG, "tlsserverrd: got Radius message from %s", client->peer.host);
1615             rq.from = client;
1616             radsrv(&rq);
1617         }
1618         debug(DBG_ERR, "tlsserverrd: connection lost");
1619         /* stop writer by setting peer.ssl to NULL and give signal in case waiting for data */
1620         client->peer.ssl = NULL;
1621         pthread_mutex_lock(&client->replyq->count_mutex);
1622         pthread_cond_signal(&client->replyq->count_cond);
1623         pthread_mutex_unlock(&client->replyq->count_mutex);
1624         debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
1625         pthread_join(tlsserverwrth, NULL);
1626     }
1627     
1628  errexit:
1629     s = SSL_get_fd(ssl);
1630     SSL_free(ssl);
1631     shutdown(s, SHUT_RDWR);
1632     close(s);
1633     debug(DBG_DBG, "tlsserverrd thread for %s exiting", client->peer.host);
1634     client->peer.ssl = NULL;
1635     pthread_exit(NULL);
1636 }
1637
1638 int tlslistener() {
1639     pthread_t tlsserverth;
1640     int s, snew;
1641     struct sockaddr_storage from;
1642     size_t fromlen = sizeof(from);
1643     struct client *client;
1644
1645     if ((s = bindtoaddr(tcp_server_listen->addrinfo)) < 0)
1646         debugx(1, DBG_ERR, "tlslistener: socket/bind failed");
1647     
1648     listen(s, 0);
1649     debug(DBG_WARN, "listening for incoming TCP on %s:%s",
1650           tcp_server_listen->host ? tcp_server_listen->host : "*", tcp_server_listen->port);
1651
1652     for (;;) {
1653         snew = accept(s, (struct sockaddr *)&from, &fromlen);
1654         if (snew < 0) {
1655             debug(DBG_WARN, "accept failed");
1656             continue;
1657         }
1658         debug(DBG_WARN, "incoming TLS connection from %s", addr2string((struct sockaddr *)&from, fromlen));
1659
1660         client = find_client('T', (struct sockaddr *)&from, NULL);
1661         if (!client) {
1662             debug(DBG_WARN, "ignoring request, not a known TLS client");
1663             shutdown(snew, SHUT_RDWR);
1664             close(snew);
1665             continue;
1666         }
1667
1668         if (client->peer.ssl) {
1669             debug(DBG_WARN, "Ignoring incoming TLS connection, already have one from this client");
1670             shutdown(snew, SHUT_RDWR);
1671             close(snew);
1672             continue;
1673         }
1674         client->peer.ssl = SSL_new(ssl_ctx);
1675         SSL_set_fd(client->peer.ssl, snew);
1676         if (pthread_create(&tlsserverth, NULL, tlsserverrd, (void *)client)) {
1677             debug(DBG_ERR, "tlslistener: pthread_create failed");
1678             SSL_free(client->peer.ssl);
1679             shutdown(snew, SHUT_RDWR);
1680             close(snew);
1681             client->peer.ssl = NULL;
1682             continue;
1683         }
1684         pthread_detach(tlsserverth);
1685     }
1686     return 0;
1687 }
1688
1689 void addrealm(char *value, char *server) {
1690     int i, n;
1691     struct realm *realm;
1692     char *s, *regex = NULL;
1693     
1694     for (i = 0; i < server_count; i++)
1695         if (!strcasecmp(server, servers[i].peer.host))
1696             break;
1697     if (i == server_count)
1698         debugx(1, DBG_ERR, "addrealm failed, no server %s", server);
1699
1700     if (*value != '/') {
1701         /* not a regexp, let us make it one */
1702         if (*value == '*' && !value[1])
1703             regex = stringcopy(".*", 0);
1704         else {
1705             for (n = 0, s = value; *s;)
1706                 if (*s++ == '.')
1707                     n++;
1708             regex = malloc(strlen(value) + n + 3);
1709             if (regex) {
1710                 regex[0] = '@';
1711                 for (n = 1, s = value; *s; s++) {
1712                     if (*s == '.')
1713                         regex[n++] = '\\';
1714                     regex[n++] = *s;
1715                 }
1716                 regex[n++] = '$';
1717                 regex[n] = '\0';
1718             }
1719         }
1720         if (!regex)
1721             debugx(1, DBG_ERR, "malloc failed");
1722         debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
1723     }
1724
1725     realm_count++;
1726     realms = realloc(realms, realm_count * sizeof(struct realm));
1727     if (!realms)
1728         debugx(1, DBG_ERR, "malloc failed");
1729     realm = realms + realm_count - 1;
1730     memset(realm, 0, sizeof(struct realm));
1731     realm->name = stringcopy(value, 0);
1732     if (!realm->name)
1733         debugx(1, DBG_ERR, "malloc failed");
1734     realm->server = servers + i;
1735     if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
1736         debugx(1, DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
1737     if (regex)
1738         free(regex);
1739     debug(DBG_DBG, "addrealm: added realm %s for server %s", value, server);
1740 }
1741
1742 char *parsehostport(char *s, struct peer *peer) {
1743     char *p, *field;
1744     int ipv6 = 0;
1745
1746     p = s;
1747     /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */
1748     if (*p == '[') {
1749         p++;
1750         field = p;
1751         for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1752         if (*p != ']')
1753             debugx(1, DBG_ERR, "no ] matching initial [");
1754         ipv6 = 1;
1755     } else {
1756         field = p;
1757         for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1758     }
1759     if (field == p)
1760         debugx(1, DBG_ERR, "missing host/address");
1761
1762     peer->host = stringcopy(field, p - field);
1763     if (ipv6) {
1764         p++;
1765         if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n')
1766             debugx(1, DBG_ERR, "unexpected character after ]");
1767     }
1768     if (*p == ':') {
1769             /* port number or service name is specified */;
1770             field = ++p;
1771             for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1772             if (field == p)
1773                 debugx(1, DBG_ERR, "syntax error, : but no following port");
1774             peer->port = stringcopy(field, p - field);
1775     } else
1776         peer->port = stringcopy(peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
1777     return p;
1778 }
1779
1780 /* TODO remove this */
1781 /* * is default, else longest match ... ";" used for separator */
1782 char *parserealmlist(char *s, struct server *server) {
1783 #if 0    
1784     char *p;
1785     int i, n, l;
1786     char *realmdata;
1787     char **realms;
1788
1789     for (p = s, n = 1; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++)
1790         if (*p == ';')
1791             n++;
1792     l = p - s;
1793     if (!l)
1794         debugx(1, DBG_ERR, "realm list must be specified");
1795
1796     realmdata = stringcopy(s, l);
1797     realms = malloc((1+n) * sizeof(char *));
1798     if (!realms)
1799         debugx(1, DBG_ERR, "malloc failed");
1800     realms[0] = realmdata;
1801     for (n = 1, i = 0; i < l; i++)
1802         if (realmdata[i] == ';') {
1803             realmdata[i] = '\0';
1804             realms[n++] = realmdata + i + 1;
1805         }       
1806     for (i = 0; i < n; i++)
1807         addrealm(realms[i], server->peer.host);
1808     free(realms);
1809     free(realmdata);
1810     return p;
1811 #else
1812     char *start;
1813     char *realm;
1814
1815     for (start = s;; s++)
1816         if (!*s || *s == ';' || *s == ' ' || *s == '\t' || *s == '\n') {
1817             if (s - start > 0) {
1818                 realm = stringcopy(start, s - start);
1819                 addrealm(realm, server->peer.host);
1820                 free(realm);
1821             }
1822             if (*s != ';')
1823                 return s;
1824             start = s + 1;
1825         }
1826 #endif    
1827 }
1828
1829 FILE *openconfigfile(const char *filename) {
1830     FILE *f;
1831     char pathname[100], *base = NULL;
1832     
1833     f = fopen(filename, "r");
1834     if (f) {
1835         debug(DBG_DBG, "reading config file %s", filename);
1836         return f;
1837     }
1838
1839     if (strlen(filename) + 1 <= sizeof(pathname)) {
1840         /* basename() might modify the string */
1841         strcpy(pathname, filename);
1842         base = basename(pathname);
1843         f = fopen(base, "r");
1844     }
1845
1846     if (!f)
1847         debugx(1, DBG_ERR, "could not read config file %s nor %s\n%s", filename, base, strerror(errno));
1848     
1849     debug(DBG_DBG, "reading config file %s", base);
1850     return f;
1851 }
1852
1853 /* exactly one argument must be non-NULL */
1854 void getconfig(const char *serverfile, const char *clientfile) {
1855     FILE *f;
1856     char line[1024];
1857     char *p, *field;
1858     struct client *client;
1859     struct server *server;
1860     struct peer *peer;
1861     int i, count, *ucount, *tcount;
1862  
1863     f = openconfigfile(serverfile ? serverfile : clientfile);
1864     if (serverfile) {
1865         ucount = &server_udp_count;
1866         tcount = &server_tls_count;
1867     } else {
1868         ucount = &client_udp_count;
1869         tcount = &client_tls_count;
1870     }
1871     while (fgets(line, 1024, f)) {
1872         for (p = line; *p == ' ' || *p == '\t'; p++);
1873         switch (*p) {
1874         case '#':
1875         case '\n':
1876             break;
1877         case 'T':
1878             (*tcount)++;
1879             break;
1880         case 'U':
1881             (*ucount)++;
1882             break;
1883         default:
1884             debugx(1, DBG_ERR, "type must be U or T, got %c", *p);
1885         }
1886     }
1887
1888     if (serverfile) {
1889         count = server_count = server_udp_count + server_tls_count;
1890         servers = calloc(count, sizeof(struct server));
1891         if (!servers)
1892             debugx(1, DBG_ERR, "malloc failed");
1893     } else {
1894         if (client_udp_count) {
1895             udp_server_replyq.replies = malloc(client_udp_count * MAX_REQUESTS * sizeof(struct reply));
1896             if (!udp_server_replyq.replies)
1897                 debugx(1, DBG_ERR, "malloc failed");
1898             udp_server_replyq.size = client_udp_count * MAX_REQUESTS;
1899             udp_server_replyq.count = 0;
1900             pthread_mutex_init(&udp_server_replyq.count_mutex, NULL);
1901             pthread_cond_init(&udp_server_replyq.count_cond, NULL);
1902         }    
1903
1904         count = client_count = client_udp_count + client_tls_count;
1905         clients = calloc(count, sizeof(struct client));
1906         if (!clients)
1907             debugx(1, DBG_ERR, "malloc failed");
1908     }
1909     
1910     rewind(f);
1911     for (i = 0; i < count && fgets(line, 1024, f);) {
1912         if (serverfile) {
1913             server = &servers[i];
1914             peer = &server->peer;
1915         } else {
1916             client = &clients[i];
1917             peer = &client->peer;
1918         }
1919         for (p = line; *p == ' ' || *p == '\t'; p++);
1920         if (*p == '#' || *p == '\n')
1921             continue;
1922         peer->type = *p;        /* we already know it must be U or T */
1923         for (p++; *p == ' ' || *p == '\t'; p++);
1924         p = parsehostport(p, peer);
1925         for (; *p == ' ' || *p == '\t'; p++);
1926         if (serverfile) {
1927             p = parserealmlist(p, server);
1928             for (; *p == ' ' || *p == '\t'; p++);
1929         }
1930         field = p;
1931         for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
1932         if (field == p) {
1933             /* no secret set and end of line, line is complete if TLS */
1934             if (peer->type == 'U')
1935                 debugx(1, DBG_ERR, "secret must be specified for UDP");
1936             peer->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
1937         } else {
1938             peer->secret = stringcopy(field, p - field);
1939             /* check that rest of line only white space */
1940             for (; *p == ' ' || *p == '\t'; p++);
1941             if (*p && *p != '\n')
1942                 debugx(1, DBG_ERR, "max 4 fields per line, found a 5th");
1943         }
1944
1945         if ((serverfile && !resolvepeer(&server->peer, 0)) ||
1946             (clientfile && !resolvepeer(&client->peer, 0)))
1947             debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", peer->host, peer->port);
1948
1949         if (serverfile) {
1950             pthread_mutex_init(&server->lock, NULL);
1951             server->sock = -1;
1952             server->requests = calloc(MAX_REQUESTS, sizeof(struct request));
1953             if (!server->requests)
1954                 debugx(1, DBG_ERR, "malloc failed");
1955             server->newrq = 0;
1956             pthread_mutex_init(&server->newrq_mutex, NULL);
1957             pthread_cond_init(&server->newrq_cond, NULL);
1958         } else {
1959             if (peer->type == 'U')
1960                 client->replyq = &udp_server_replyq;
1961             else {
1962                 client->replyq = malloc(sizeof(struct replyq));
1963                 if (!client->replyq)
1964                     debugx(1, DBG_ERR, "malloc failed");
1965                 client->replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
1966                 if (!client->replyq->replies)
1967                     debugx(1, DBG_ERR, "malloc failed");
1968                 client->replyq->size = MAX_REQUESTS;
1969                 client->replyq->count = 0;
1970                 pthread_mutex_init(&client->replyq->count_mutex, NULL);
1971                 pthread_cond_init(&client->replyq->count_cond, NULL);
1972             }
1973         }
1974         debug(DBG_DBG, "got type %c, host %s, port %s, secret %s", peer->type, peer->host, peer->port, peer->secret);
1975         i++;
1976     }
1977     fclose(f);
1978 }
1979
1980 struct peer *server_create(char type) {
1981     struct peer *server;
1982     char *conf;
1983
1984     server = malloc(sizeof(struct peer));
1985     if (!server)
1986         debugx(1, DBG_ERR, "malloc failed");
1987     memset(server, 0, sizeof(struct peer));
1988     server->type = type;
1989     conf = (type == 'T' ? options.listentcp : options.listenudp);
1990     if (conf) {
1991         parsehostport(conf, server);
1992         if (!strcmp(server->host, "*")) {
1993             free(server->host);
1994             server->host = NULL;
1995         }
1996     } else
1997         server->port = stringcopy(type == 'T' ? DEFAULT_TLS_PORT : DEFAULT_UDP_PORT, 0);
1998     if (!resolvepeer(server, AI_PASSIVE))
1999         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", server->host, server->port);
2000     return server;
2001 }
2002
2003 /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */
2004 char *strtokenquote(char *s, char **token, char *del, char *quote) {
2005     char *t = s, *q, *r;
2006
2007     if (!t || !token || !del)
2008         return NULL;
2009     while (*t && strchr(del, *t))
2010         t++;
2011     if (!*t) {
2012         *token = NULL;
2013         return t + 1; /* needs to be non-NULL, but value doesn't matter */
2014     }
2015     if (quote && (q = strchr(quote, *t))) {
2016         t++;
2017         r = t;
2018         while (*t && *t != *q)
2019             t++;
2020         if (!*t || (t[1] && !strchr(del, t[1])))
2021             return NULL;
2022         *t = '\0';
2023         *token = r;
2024         return t + 1;
2025     }
2026     *token = t;
2027     t++;
2028     while (*t && !strchr(del, *t))
2029         t++;
2030     *t = '\0';
2031     return t + 1;
2032 }
2033
2034 /* Parses config with following syntax:
2035  * One of these:
2036  * option-name value
2037  * option-name = value
2038  * Or:
2039  * option-name value {
2040  *     option-name [=] value
2041  *     ...
2042  * }
2043  */
2044 void getgeneralconfig(FILE *f, char *block, ...) {
2045     va_list ap;
2046     char line[1024];
2047     /* initialise lots of stuff to avoid stupid compiler warnings */
2048     char *tokens[3], *s, *opt = NULL, *val = NULL, *word, **str = NULL;
2049     int type = 0, tcount, conftype = 0;
2050     void (*cbk)(FILE *, char *, char *) = NULL;
2051         
2052     while (fgets(line, 1024, f)) {
2053         s = line;
2054         for (tcount = 0; tcount < 3; tcount++) {
2055             s = strtokenquote(s, &tokens[tcount], " \t\n", "\"'");
2056             if (!s)
2057                 debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line);
2058             if (!tokens[tcount])
2059                 break;
2060         }
2061         if (!tcount || **tokens == '#')
2062             continue;
2063
2064         if (**tokens == '}') {
2065             if (block)
2066                 return;
2067             debugx(1, DBG_ERR, "configuration error, found } with no matching {");
2068         }
2069             
2070         switch (tcount) {
2071         case 2:
2072             opt = tokens[0];
2073             val = tokens[1];
2074             conftype = CONF_STR;
2075             break;
2076         case 3:
2077             if (tokens[1][0] == '=' && tokens[1][1] == '\0') {
2078                 opt = tokens[0];
2079                 val = tokens[2];
2080                 conftype = CONF_STR;
2081                 break;
2082             }
2083             if (tokens[2][0] == '{' && tokens[2][1] == '\0') {
2084                 opt = tokens[0];
2085                 val = tokens[1];
2086                 conftype = CONF_CBK;
2087                 break;
2088             }
2089             /* fall through */
2090         default:
2091             if (block)
2092                 debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]);
2093             debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]);
2094         }
2095
2096         if (!*val)
2097             debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", opt);
2098         
2099         va_start(ap, block);
2100         while ((word = va_arg(ap, char *))) {
2101             type = va_arg(ap, int);
2102             switch (type) {
2103             case CONF_STR:
2104                 str = va_arg(ap, char **);
2105                 if (!str)
2106                     debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2107                 break;
2108             case CONF_CBK:
2109                 cbk = va_arg(ap, void (*)(FILE *, char *, char *));
2110                 break;
2111             default:
2112                 debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2113             }
2114             if (!strcasecmp(opt, word))
2115                 break;
2116         }
2117         va_end(ap);
2118         
2119         if (!word) {
2120             if (block)
2121                 debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt);
2122             debugx(1, DBG_ERR, "configuration error, unknown option %s", opt);
2123         }
2124
2125         if (type != conftype) {
2126             if (block)
2127                 debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt);
2128             debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt);
2129         }
2130         
2131         switch (type) {
2132         case CONF_STR:
2133             if (block)
2134                 debug(DBG_DBG, "getgeneralconfig: block %s: %s = %s", block, opt, val);
2135             else 
2136                 debug(DBG_DBG, "getgeneralconfig: %s = %s", opt, val);
2137             *str = stringcopy(val, 0);
2138             break;
2139         case CONF_CBK:
2140             cbk(f, opt, val);
2141             break;
2142         default:
2143             debugx(1, DBG_ERR, "getgeneralconfig: internal parameter error");
2144         }
2145     }
2146 }
2147
2148 void confclsrv_cb(FILE *f, char *opt, char *val) {
2149     char *type = NULL, *secret = NULL, *port = NULL, *statusserver = NULL;
2150     char *block;
2151     struct client *client = NULL;
2152     struct server *server = NULL;
2153     struct peer *peer;
2154
2155     block = malloc(strlen(opt) + strlen(val) + 2);
2156     if (!block)
2157         debugx(1, DBG_ERR, "malloc failed");
2158     sprintf(block, "%s %s", opt, val);
2159     debug(DBG_DBG, "confclsrv_cb called for %s", block);
2160     
2161     if (!strcasecmp(opt, "client")) {
2162         getgeneralconfig(f, block,
2163                          "type", CONF_STR, &type,
2164                          "secret", CONF_STR, &secret,
2165                          NULL
2166                          );
2167         client_count++;
2168         clients = realloc(clients, client_count * sizeof(struct client));
2169         if (!clients)
2170             debugx(1, DBG_ERR, "malloc failed");
2171         client = clients + client_count - 1;
2172         memset(client, 0, sizeof(struct client));
2173         peer = &client->peer;
2174     } else {
2175         getgeneralconfig(f, block,
2176                          "type", CONF_STR, &type,
2177                          "secret", CONF_STR, &secret,
2178                          "port", CONF_STR, &port,
2179                          "StatusServer", CONF_STR, &statusserver,
2180                          NULL
2181                          );
2182         server_count++;
2183         servers = realloc(servers, server_count * sizeof(struct server));
2184         if (!servers)
2185             debugx(1, DBG_ERR, "malloc failed");
2186         server = servers + server_count - 1;
2187         memset(server, 0, sizeof(struct server));
2188         peer = &server->peer;
2189         peer->port = port;
2190         if (statusserver) {
2191             if (!strcasecmp(statusserver, "on"))
2192                 server->statusserver = 1;
2193             else if (strcasecmp(statusserver, "off"))
2194                 debugx(1, DBG_ERR, "error in block %s, StatusServer is %s, must be on or off", block, statusserver);
2195             free(statusserver);
2196         }
2197     }
2198     
2199     peer->host = stringcopy(val, 0);
2200     
2201     if (type && !strcasecmp(type, "udp")) {
2202         peer->type = 'U';
2203         if (client)
2204             client_udp_count++;
2205         else {
2206             server_udp_count++;
2207             if (!port)
2208                 peer->port = stringcopy(DEFAULT_UDP_PORT, 0);
2209         }
2210     } else if (type && !strcasecmp(type, "tls")) {
2211         peer->type = 'T';
2212         if (client)
2213             client_tls_count++;
2214         else {
2215             server_tls_count++;
2216             if (!port)
2217                 peer->port = stringcopy(DEFAULT_TLS_PORT, 0);
2218         }
2219     } else
2220         debugx(1, DBG_ERR, "error in block %s, type must be set to UDP or TLS", block);
2221     free(type);
2222     
2223     if (!resolvepeer(peer, 0))
2224         debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", peer->host, peer->port);
2225     
2226     if (!secret) {
2227         if (peer->type == 'U')
2228             debugx(1, DBG_ERR, "error in block %s, secret must be specified for UDP", block);
2229         peer->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
2230     } else {
2231         peer->secret = secret;
2232     }
2233
2234     if (client) {
2235         if (peer->type == 'U')
2236             client->replyq = &udp_server_replyq;
2237         else {
2238             client->replyq = malloc(sizeof(struct replyq));
2239             if (!client->replyq)
2240                 debugx(1, DBG_ERR, "malloc failed");
2241             client->replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
2242             if (!client->replyq->replies)
2243                 debugx(1, DBG_ERR, "malloc failed");
2244             client->replyq->size = MAX_REQUESTS;
2245             client->replyq->count = 0;
2246             pthread_mutex_init(&client->replyq->count_mutex, NULL);
2247             pthread_cond_init(&client->replyq->count_cond, NULL);
2248         }
2249     } else {
2250         pthread_mutex_init(&server->lock, NULL);
2251         server->sock = -1;
2252         server->requests = calloc(MAX_REQUESTS, sizeof(struct request));
2253         if (!server->requests)
2254             debugx(1, DBG_ERR, "malloc failed");
2255         server->newrq = 0;
2256         pthread_mutex_init(&server->newrq_mutex, NULL);
2257         pthread_cond_init(&server->newrq_cond, NULL);
2258     }
2259     
2260     free(block);
2261 }
2262
2263 void confrealm_cb(FILE *f, char *opt, char *val) {
2264     char *server = NULL;
2265     char *block;
2266     
2267     block = malloc(strlen(opt) + strlen(val) + 2);
2268     if (!block)
2269         debugx(1, DBG_ERR, "malloc failed");
2270     sprintf(block, "%s %s", opt, val);
2271     debug(DBG_DBG, "confrealm_cb called for %s", block);
2272     
2273     getgeneralconfig(f, block,
2274                      "server", CONF_STR, &server,
2275                      NULL
2276                      );
2277     if (!server)
2278         debugx(1, DBG_ERR, "error in block %s, server must be specified", block);
2279
2280     addrealm(val, server);
2281     free(server);
2282     free(block);
2283 }
2284
2285 void getmainconfig(const char *configfile) {
2286     FILE *f;
2287     char *loglevel = NULL;
2288
2289     f = openconfigfile(configfile);
2290     memset(&options, 0, sizeof(options));
2291
2292     getgeneralconfig(f, NULL,
2293                      "TLSCACertificateFile", CONF_STR, &options.tlscacertificatefile,
2294                      "TLSCACertificatePath", CONF_STR, &options.tlscacertificatepath,
2295                      "TLSCertificateFile", CONF_STR, &options.tlscertificatefile,
2296                      "TLSCertificateKeyFile", CONF_STR, &options.tlscertificatekeyfile,
2297                      "TLSCertificateKeyPassword", CONF_STR, &options.tlscertificatekeypassword,
2298                      "ListenUDP", CONF_STR, &options.listenudp,
2299                      "ListenTCP", CONF_STR, &options.listentcp,
2300                      "LogLevel", CONF_STR, &loglevel,
2301                      "LogDestination", CONF_STR, &options.logdestination,
2302                      "Client", CONF_CBK, confclsrv_cb,
2303                      "Server", CONF_CBK, confclsrv_cb,
2304                      "Realm", CONF_CBK, confrealm_cb,
2305                      NULL
2306                      );
2307     fclose(f);
2308
2309     if (loglevel) {
2310         if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
2311             debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
2312         options.loglevel = *loglevel - '0';
2313         free(loglevel);
2314     }
2315
2316     if (client_udp_count) {
2317         udp_server_replyq.replies = malloc(client_udp_count * MAX_REQUESTS * sizeof(struct reply));
2318         if (!udp_server_replyq.replies)
2319             debugx(1, DBG_ERR, "malloc failed");
2320         udp_server_replyq.size = client_udp_count * MAX_REQUESTS;
2321         udp_server_replyq.count = 0;
2322         pthread_mutex_init(&udp_server_replyq.count_mutex, NULL);
2323         pthread_cond_init(&udp_server_replyq.count_cond, NULL);
2324     }    
2325 }
2326
2327 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *loglevel, char **configfile) {
2328     int c;
2329
2330     while ((c = getopt(argc, argv, "c:d:fv")) != -1) {
2331         switch (c) {
2332         case 'c':
2333             *configfile = optarg;
2334             break;
2335         case 'd':
2336             if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '4')
2337                 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3 or 4, not %s", optarg);
2338             *loglevel = *optarg - '0';
2339             break;
2340         case 'f':
2341             *foreground = 1;
2342             break;
2343         case 'v':
2344                 debugx(0, DBG_ERR, "radsecproxy revision $Rev$");
2345         default:
2346             goto usage;
2347         }
2348     }
2349     if (!(argc - optind))
2350         return;
2351
2352  usage:
2353     debug(DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -v ]", argv[0]);
2354     exit(1);
2355 }
2356
2357 int main(int argc, char **argv) {
2358     pthread_t udpserverth;
2359     int i;
2360     uint8_t foreground = 0, loglevel = 0;
2361     char *configfile = NULL;
2362     
2363     debug_init("radsecproxy");
2364     debug_set_level(DEBUG_LEVEL);
2365     getargs(argc, argv, &foreground, &loglevel, &configfile);
2366     if (loglevel)
2367         debug_set_level(loglevel);
2368     getmainconfig(configfile ? configfile : CONFIG_MAIN);
2369     if (loglevel)
2370         options.loglevel = loglevel;
2371     else if (options.loglevel)
2372         debug_set_level(options.loglevel);
2373     if (foreground)
2374         options.logdestination = NULL;
2375     else {
2376         if (!options.logdestination)
2377             options.logdestination = "x-syslog://";
2378         debug_set_destination(options.logdestination);
2379     }
2380
2381     /* TODO remove getconfig completely when all use new config method */
2382     if (!server_count)
2383         getconfig(CONFIG_SERVERS, NULL);
2384     if (!client_count)
2385         getconfig(NULL, CONFIG_CLIENTS);
2386
2387     /* TODO exit if not at least one client and one server configured */
2388     if (!realm_count)
2389         debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
2390
2391     if (!foreground && (daemon(0, 0) < 0))
2392         debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
2393         
2394     if (client_udp_count) {
2395         udp_server_listen = server_create('U');
2396         if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
2397             debugx(1, DBG_ERR, "pthread_create failed");
2398     }
2399     
2400     if (client_tls_count || server_tls_count)
2401         ssl_ctx = ssl_init();
2402     
2403     for (i = 0; i < server_count; i++)
2404         if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
2405             debugx(1, DBG_ERR, "pthread_create failed");
2406
2407     if (client_tls_count) {
2408         tcp_server_listen = server_create('T');
2409         return tlslistener();
2410     }
2411     
2412     /* just hang around doing nothing, anything to do here? */
2413     for (;;)
2414         sleep(1000);
2415 }