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