1 /* Copyright (c) 2007-2009, UNINETT AS
2 * Copyright (c) 2010-2013,2015-2016, NORDUnet A/S */
3 /* See LICENSE for licensing information. */
4
5 /* For UDP there is one server instance consisting of udpserverrd and udpserverth
6 * rd is responsible for init and launching wr
7 * For TLS there is a server instance that launches tlsserverrd for each TLS peer
8 * each tlsserverrd launches tlsserverwr
9 * For each UDP/TLS peer there is clientrd and clientwr, clientwr is responsible
10 * for init and launching rd
11 *
12 * serverrd will receive a request, processes it and puts it in the requestq of
13 * the appropriate clientwr
14 * clientwr monitors its requestq and sends requests
15 * clientrd looks for responses, processes them and puts them in the replyq of
16 * the peer the request came from
17 * serverwr monitors its reply and sends replies
18 *
19 * In addition to the main thread, we have:
20 * If UDP peers are configured, there will be 2 + 2 * #peers UDP threads
21 * If TLS peers are configured, there will initially be 2 * #peers TLS threads
22 * For each TLS peer connecting to us there will be 2 more TLS threads
23 * This is only for connected peers
24 * Example: With 3 UDP peers and 30 TLS peers, there will be a max of
25 * 1 + (2 + 2 * 3) + (2 * 30) + (2 * 30) = 129 threads
26 */
27
28 /* Bugs:
29 * May segfault when dtls connections go down? More testing needed
30 * Remove expired stuff from clients request list?
31 * Multiple outgoing connections if not enough IDs? (multiple servers per conf?)
32 * Useful for TCP accounting? Now we require separate server config for alt port
33 */
34
35 #define _GNU_SOURCE
36 #include <signal.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #if defined(HAVE_MALLOPT)
44 #include <malloc.h>
45 #endif
46 #ifdef SYS_SOLARIS9
47 #include <fcntl.h>
48 #endif
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <ctype.h>
52 #include <sys/wait.h>
53 #include <arpa/inet.h>
54 #include <regex.h>
55 #include <libgen.h>
56 #include <pthread.h>
57 #include <errno.h>
58 #include <assert.h>
59 #include <openssl/ssl.h>
60 #include <openssl/rand.h>
61 #include <openssl/err.h>
62 #include <nettle/md5.h>
63 #include "debug.h"
64 #include "hash.h"
65 #include "util.h"
66 #include "hostport.h"
67 #include "radsecproxy.h"
68 #include "udp.h"
69 #include "tcp.h"
70 #include "tls.h"
71 #include "dtls.h"
72 #include "fticks.h"
73 #include "fticks_hashmac.h"
74
75 static struct options options;
76 static struct list *clconfs, *srvconfs;
77 static struct list *realms;
78
79 #ifdef __CYGWIN__
80 extern int __declspec(dllimport) optind;
81 extern char __declspec(dllimport) *optarg;
82 #else
83 extern int optind;
84 extern char *optarg;
85 #endif
86 static const struct protodefs *protodefs[RAD_PROTOCOUNT];
87 pthread_attr_t pthread_attr;
88
89 /* minimum required declarations to avoid reordering code */
90 struct realm *adddynamicrealmserver(struct realm *realm, char *id);
91 int dynamicconfig(struct server *server);
92 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val);
93 void freerealm(struct realm *realm);
94 void freeclsrvconf(struct clsrvconf *conf);
95 void freerq(struct request *rq);
96 void freerqoutdata(struct rqout *rqout);
97 void rmclientrq(struct request *rq, uint8_t id);
98
99 static const struct protodefs *(*protoinits[])(uint8_t) = { udpinit, tlsinit, tcpinit, dtlsinit };
100
protoname2int(const char * name)101 uint8_t protoname2int(const char *name) {
102 uint8_t i;
103
104 for (i = 0; i < RAD_PROTOCOUNT; i++)
105 if (protodefs[i] && protodefs[i]->name && !strcasecmp(protodefs[i]->name, name))
106 return i;
107 return 255;
108 }
109
110 /* returns 1 if the len first bits are equal, else 0 */
prefixmatch(void * a1,void * a2,uint8_t len)111 int prefixmatch(void *a1, void *a2, uint8_t len) {
112 static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
113 uint8_t r, l = len / 8;
114 if (l && memcmp(a1, a2, l))
115 return 0;
116 r = len % 8;
117 if (!r)
118 return 1;
119 return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
120 }
121
122 /* returns next config with matching address, or NULL */
find_conf(uint8_t type,struct sockaddr * addr,struct list * confs,struct list_node ** cur,uint8_t server_p)123 struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur, uint8_t server_p) {
124 struct list_node *entry;
125 struct clsrvconf *conf;
126
127 for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) {
128 conf = (struct clsrvconf *)entry->data;
129 if (conf->type == type && addressmatches(conf->hostports, addr, server_p)) {
130 if (cur)
131 *cur = entry;
132 return conf;
133 }
134 }
135 return NULL;
136 }
137
find_clconf(uint8_t type,struct sockaddr * addr,struct list_node ** cur)138 struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur) {
139 return find_conf(type, addr, clconfs, cur, 0);
140 }
141
find_srvconf(uint8_t type,struct sockaddr * addr,struct list_node ** cur)142 struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur) {
143 return find_conf(type, addr, srvconfs, cur, 1);
144 }
145
146 /* returns next config of given type, or NULL */
find_clconf_type(uint8_t type,struct list_node ** cur)147 struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur) {
148 struct list_node *entry;
149 struct clsrvconf *conf;
150
151 for (entry = (cur && *cur ? list_next(*cur) : list_first(clconfs)); entry; entry = list_next(entry)) {
152 conf = (struct clsrvconf *)entry->data;
153 if (conf->type == type) {
154 if (cur)
155 *cur = entry;
156 return conf;
157 }
158 }
159 return NULL;
160 }
161
newqueue()162 struct gqueue *newqueue() {
163 struct gqueue *q;
164
165 q = malloc(sizeof(struct gqueue));
166 if (!q)
167 debugx(1, DBG_ERR, "malloc failed");
168 q->entries = list_create();
169 if (!q->entries)
170 debugx(1, DBG_ERR, "malloc failed");
171 pthread_mutex_init(&q->mutex, NULL);
172 pthread_cond_init(&q->cond, NULL);
173 return q;
174 }
175
removequeue(struct gqueue * q)176 void removequeue(struct gqueue *q) {
177 struct list_node *entry;
178
179 if (!q)
180 return;
181 pthread_mutex_lock(&q->mutex);
182 for (entry = list_first(q->entries); entry; entry = list_next(entry))
183 freerq((struct request *)entry->data);
184 list_free(q->entries);
185 pthread_cond_destroy(&q->cond);
186 pthread_mutex_unlock(&q->mutex);
187 pthread_mutex_destroy(&q->mutex);
188 free(q);
189 }
190
addclient(struct clsrvconf * conf,uint8_t lock)191 struct client *addclient(struct clsrvconf *conf, uint8_t lock) {
192 struct client *new = NULL;
193
194 if (lock)
195 pthread_mutex_lock(conf->lock);
196 if (!conf->clients) {
197 conf->clients = list_create();
198 if (!conf->clients) {
199 if (lock)
200 pthread_mutex_unlock(conf->lock);
201 debug(DBG_ERR, "malloc failed");
202 return NULL;
203 }
204 }
205
206 new = calloc(1, sizeof(struct client));
207 if (!new) {
208 debug(DBG_ERR, "malloc failed");
209 if (lock)
210 pthread_mutex_unlock(conf->lock);
211 return NULL;
212 }
213 if (!list_push(conf->clients, new)) {
214 free(new);
215 if (lock)
216 pthread_mutex_unlock(conf->lock);
217 return NULL;
218 }
219 new->conf = conf;
220 if (conf->pdef->addclient)
221 conf->pdef->addclient(new);
222 else
223 new->replyq = newqueue();
224 pthread_mutex_init(&new->lock, NULL);
225 if (lock)
226 pthread_mutex_unlock(conf->lock);
227 return new;
228 }
229
removeclientrqs_sendrq_freeserver_lock(uint8_t wantlock)230 void removeclientrqs_sendrq_freeserver_lock(uint8_t wantlock) {
231 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
232
233 if (wantlock)
234 pthread_mutex_lock(&lock);
235 else
236 pthread_mutex_unlock(&lock);
237 }
238
removeclientrq(struct client * client,int i)239 void removeclientrq(struct client *client, int i) {
240 struct request *rq;
241 struct rqout *rqout;
242
243 rq = client->rqs[i];
244 if (!rq)
245 return;
246
247 removeclientrqs_sendrq_freeserver_lock(1);
248 if (rq->to) {
249 rqout = rq->to->requests + rq->newid;
250 pthread_mutex_lock(rqout->lock);
251 if (rqout->rq == rq) /* still pointing to our request */
252 freerqoutdata(rqout);
253 pthread_mutex_unlock(rqout->lock);
254 }
255 client->rqs[i] = NULL;
256 freerq(rq);
257 removeclientrqs_sendrq_freeserver_lock(0);
258 }
259
removeclientrqs(struct client * client)260 void removeclientrqs(struct client *client) {
261 int i;
262
263 for (i = 0; i < MAX_REQUESTS; i++)
264 removeclientrq(client, i);
265 }
266
removelockedclient(struct client * client)267 void removelockedclient(struct client *client) {
268 struct clsrvconf *conf;
269
270 conf = client->conf;
271 if (conf->clients) {
272 removeclientrqs(client);
273 removequeue(client->replyq);
274 list_removedata(conf->clients, client);
275 pthread_mutex_destroy(&client->lock);
276 free(client->addr);
277 free(client);
278 }
279 }
280
removeclient(struct client * client)281 void removeclient(struct client *client) {
282 struct clsrvconf *conf;
283
284 if (!client)
285 return;
286
287 conf = client->conf;
288 pthread_mutex_lock(conf->lock);
289 removelockedclient(client);
290 pthread_mutex_unlock(conf->lock);
291 }
292
freeserver(struct server * server,uint8_t destroymutex)293 void freeserver(struct server *server, uint8_t destroymutex) {
294 struct rqout *rqout, *end;
295
296 if (!server)
297 return;
298
299 removeclientrqs_sendrq_freeserver_lock(1);
300 if (server->requests) {
301 rqout = server->requests;
302 for (end = rqout + MAX_REQUESTS; rqout < end; rqout++) {
303 freerqoutdata(rqout);
304 pthread_mutex_destroy(rqout->lock);
305 free(rqout->lock);
306 }
307 free(server->requests);
308 }
309 free(server->dynamiclookuparg);
310 if (server->ssl) {
311 SSL_free(server->ssl);
312 }
313 if (destroymutex) {
314 pthread_mutex_destroy(&server->lock);
315 pthread_cond_destroy(&server->newrq_cond);
316 pthread_mutex_destroy(&server->newrq_mutex);
317 }
318 removeclientrqs_sendrq_freeserver_lock(0);
319 free(server);
320 }
321
addserver(struct clsrvconf * conf)322 int addserver(struct clsrvconf *conf) {
323 int i;
324
325 if (conf->servers) {
326 debug(DBG_ERR, "addserver: currently works with just one server per conf");
327 return 0;
328 }
329 conf->servers = malloc(sizeof(struct server));
330 if (!conf->servers) {
331 debug(DBG_ERR, "malloc failed");
332 return 0;
333 }
334 memset(conf->servers, 0, sizeof(struct server));
335 conf->servers->conf = conf;
336
337 conf->pdef->setsrcres();
338
339 conf->servers->sock = -1;
340 if (conf->pdef->addserverextra)
341 conf->pdef->addserverextra(conf);
342
343 conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct rqout));
344 if (!conf->servers->requests) {
345 debug(DBG_ERR, "malloc failed");
346 goto errexit;
347 }
348 for (i = 0; i < MAX_REQUESTS; i++) {
349 conf->servers->requests[i].lock = malloc(sizeof(pthread_mutex_t));
350 if (!conf->servers->requests[i].lock) {
351 debug(DBG_ERR, "malloc failed");
352 goto errexit;
353 }
354 if (pthread_mutex_init(conf->servers->requests[i].lock, NULL)) {
355 debugerrno(errno, DBG_ERR, "mutex init failed");
356 free(conf->servers->requests[i].lock);
357 conf->servers->requests[i].lock = NULL;
358 goto errexit;
359 }
360 }
361 if (pthread_mutex_init(&conf->servers->lock, NULL)) {
362 debugerrno(errno, DBG_ERR, "mutex init failed");
363 goto errexit;
364 }
365 conf->servers->newrq = 0;
366 conf->servers->conreset = 0;
367 if (pthread_mutex_init(&conf->servers->newrq_mutex, NULL)) {
368 debugerrno(errno, DBG_ERR, "mutex init failed");
369 pthread_mutex_destroy(&conf->servers->lock);
370 goto errexit;
371 }
372 if (pthread_cond_init(&conf->servers->newrq_cond, NULL)) {
373 debugerrno(errno, DBG_ERR, "mutex init failed");
374 pthread_mutex_destroy(&conf->servers->newrq_mutex);
375 pthread_mutex_destroy(&conf->servers->lock);
376 goto errexit;
377 }
378
379 return 1;
380
381 errexit:
382 freeserver(conf->servers, 0);
383 conf->servers = NULL;
384 return 0;
385 }
386
attrget(unsigned char * attrs,int length,uint8_t type)387 unsigned char *attrget(unsigned char *attrs, int length, uint8_t type) {
388 while (length > 1) {
389 if (ATTRTYPE(attrs) == type)
390 return attrs;
391 length -= ATTRLEN(attrs);
392 attrs += ATTRLEN(attrs);
393 }
394 return NULL;
395 }
396
newrqref(struct request * rq)397 struct request *newrqref(struct request *rq) {
398 if (rq) {
399 pthread_mutex_lock(&rq->refmutex);
400 rq->refcount++;
401 pthread_mutex_unlock(&rq->refmutex);
402 }
403 return rq;
404 }
405
freerq(struct request * rq)406 void freerq(struct request *rq) {
407 if (!rq)
408 return;
409 pthread_mutex_lock(&rq->refmutex);
410 debug(DBG_DBG, "freerq: called with refcount %d", rq->refcount);
411 if (--rq->refcount) {
412 pthread_mutex_unlock(&rq->refmutex);
413 return;
414 }
415 pthread_mutex_unlock(&rq->refmutex);
416 if (rq->origusername)
417 free(rq->origusername);
418 if (rq->buf)
419 free(rq->buf);
420 if (rq->replybuf)
421 free(rq->replybuf);
422 if (rq->msg)
423 radmsg_free(rq->msg);
424 pthread_mutex_destroy(&rq->refmutex);
425 free(rq);
426 }
427
freerqoutdata(struct rqout * rqout)428 void freerqoutdata(struct rqout *rqout) {
429 if (!rqout)
430 return;
431 if (rqout->rq) {
432 if (rqout->rq->buf) {
433 free(rqout->rq->buf);
434 rqout->rq->buf = NULL;
435 }
436 rqout->rq->to = NULL;
437 freerq(rqout->rq);
438 rqout->rq = NULL;
439 }
440 rqout->tries = 0;
441 memset(&rqout->expiry, 0, sizeof(struct timeval));
442 }
443
_internal_sendrq(struct server * to,uint8_t id,struct request * rq)444 int _internal_sendrq(struct server *to, uint8_t id, struct request *rq) {
445 if (!to->requests[id].rq) {
446 pthread_mutex_lock(to->requests[id].lock);
447 if (!to->requests[id].rq) {
448 rq->newid = id;
449 rq->msg->id = id;
450 rq->buf = radmsg2buf(rq->msg, to->conf->secret, to->conf->secret_len);
451 if (!rq->buf) {
452 pthread_mutex_unlock(to->requests[id].lock);
453 debug(DBG_ERR, "sendrq: radmsg2buf failed");
454 return 0;
455 }
456 debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", id, to->conf->name);
457 to->requests[id].rq = rq;
458 pthread_mutex_unlock(to->requests[id].lock);
459 return 1;
460 }
461 }
462 pthread_mutex_unlock(to->requests[id].lock);
463 return 0;
464 }
465
sendrq(struct request * rq)466 void sendrq(struct request *rq) {
467 int i, start;
468 struct server *to;
469
470 removeclientrqs_sendrq_freeserver_lock(1);
471 to = rq->to;
472 if (!to)
473 goto errexit;
474
475 start = to->conf->statusserver == RSP_STATSRV_OFF ? 0 : 1;
476 pthread_mutex_lock(&to->newrq_mutex);
477 if (start && rq->msg->code == RAD_Status_Server) {
478 if (!_internal_sendrq(to, 0, rq)) {
479 debug(DBG_INFO, "sendrq: status server already in queue, dropping request");
480 goto errexit;
481 }
482 } else {
483 if (!to->nextid)
484 to->nextid = start;
485 /* might simplify if only try nextid, might be ok */
486 for (i = to->nextid; i < MAX_REQUESTS; i++) {
487 if (_internal_sendrq(to, i, rq))
488 break;
489 }
490 if (i == MAX_REQUESTS) {
491 for (i = start; i < to->nextid; i++) {
492 if (_internal_sendrq(to, i, rq))
493 break;
494 }
495 if (i == to->nextid) {
496 debug(DBG_WARN, "sendrq: no room in queue for server %s, dropping request", to->conf->name);
497 goto errexit;
498 }
499 }
500
501 if (i >= start) /* i is not reserved for statusserver */
502 to->nextid = i + 1;
503 }
504
505 if (!to->newrq) {
506 to->newrq = 1;
507 debug(DBG_DBG, "sendrq: signalling client writer");
508 pthread_cond_signal(&to->newrq_cond);
509 }
510
511 pthread_mutex_unlock(&to->newrq_mutex);
512 removeclientrqs_sendrq_freeserver_lock(0);
513 return;
514
515 errexit:
516 if (rq->from)
517 rmclientrq(rq, rq->rqid);
518 freerq(rq);
519 if (to)
520 pthread_mutex_unlock(&to->newrq_mutex);
521 removeclientrqs_sendrq_freeserver_lock(0);
522 }
523
sendreply(struct request * rq)524 void sendreply(struct request *rq) {
525 uint8_t first;
526 struct client *to = rq->from;
527
528 if (!rq->replybuf)
529 rq->replybuf = radmsg2buf(rq->msg, to->conf->secret, to->conf->secret_len);
530 radmsg_free(rq->msg);
531 rq->msg = NULL;
532 if (!rq->replybuf) {
533 freerq(rq);
534 debug(DBG_ERR, "sendreply: radmsg2buf failed");
535 return;
536 }
537
538 pthread_mutex_lock(&to->replyq->mutex);
539 first = list_first(to->replyq->entries) == NULL;
540
541 if (!list_push(to->replyq->entries, rq)) {
542 pthread_mutex_unlock(&to->replyq->mutex);
543 freerq(rq);
544 debug(DBG_ERR, "sendreply: malloc failed");
545 return;
546 }
547
548 if (first) {
549 debug(DBG_DBG, "signalling server writer");
550 pthread_cond_signal(&to->replyq->cond);
551 }
552 pthread_mutex_unlock(&to->replyq->mutex);
553 }
554
pwdcrypt(char encrypt_flag,uint8_t * in,uint8_t len,uint8_t * shared,uint8_t sharedlen,uint8_t * auth,uint8_t * salt,uint8_t saltlen)555 static int pwdcrypt(char encrypt_flag, uint8_t *in, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt, uint8_t saltlen) {
556 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
557 struct md5_ctx mdctx;
558 unsigned char hash[MD5_DIGEST_SIZE], *input;
559 uint8_t i, offset = 0, out[128];
560
561 pthread_mutex_lock(&lock);
562
563 md5_init(&mdctx);
564 input = auth;
565 for (;;) {
566 md5_update(&mdctx, sharedlen, shared);
567 md5_update(&mdctx, 16, input);
568 if (salt) {
569 md5_update(&mdctx, saltlen, salt);
570 salt = NULL;
571 }
572 md5_digest(&mdctx, sizeof(hash), hash);
573 for (i = 0; i < 16; i++)
574 out[offset + i] = hash[i] ^ in[offset + i];
575 if (encrypt_flag)
576 input = out + offset;
577 else
578 input = in + offset;
579 offset += 16;
580 if (offset == len)
581 break;
582 }
583 memcpy(in, out, len);
584
585 pthread_mutex_unlock(&lock);
586 return 1;
587 }
588
msmppencrypt(uint8_t * text,uint8_t len,uint8_t * shared,uint8_t sharedlen,uint8_t * auth,uint8_t * salt)589 static int msmppencrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
590 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
591 struct md5_ctx mdctx;
592 unsigned char hash[MD5_DIGEST_SIZE];
593 uint8_t i, offset;
594
595 pthread_mutex_lock(&lock);
596 md5_init(&mdctx);
597
598 #if 0
599 printfchars(NULL, "msppencrypt auth in", "%02x ", auth, 16);
600 printfchars(NULL, "msppencrypt salt in", "%02x ", salt, 2);
601 printfchars(NULL, "msppencrypt in", "%02x ", text, len);
602 #endif
603
604 md5_update(&mdctx, sharedlen, shared);
605 md5_update(&mdctx, 16, auth);
606 md5_update(&mdctx, 2, salt);
607 md5_digest(&mdctx, sizeof(hash), hash);
608
609 #if 0
610 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
611 #endif
612
613 for (i = 0; i < 16; i++)
614 text[i] ^= hash[i];
615
616 for (offset = 16; offset < len; offset += 16) {
617 #if 0
618 printf("text + offset - 16 c(%d): ", offset / 16);
619 printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
620 #endif
621 md5_update(&mdctx, sharedlen, shared);
622 md5_update(&mdctx, 16, text + offset - 16);
623 md5_digest(&mdctx, sizeof(hash), hash);
624 #if 0
625 printfchars(NULL, "msppencrypt hash", "%02x ", hash, 16);
626 #endif
627
628 for (i = 0; i < 16; i++)
629 text[offset + i] ^= hash[i];
630 }
631
632 #if 0
633 printfchars(NULL, "msppencrypt out", "%02x ", text, len);
634 #endif
635
636 pthread_mutex_unlock(&lock);
637 return 1;
638 }
639
msmppdecrypt(uint8_t * text,uint8_t len,uint8_t * shared,uint8_t sharedlen,uint8_t * auth,uint8_t * salt)640 static int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, uint8_t *auth, uint8_t *salt) {
641 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
642 struct md5_ctx mdctx;
643 unsigned char hash[MD5_DIGEST_SIZE];
644 uint8_t i, offset;
645 char plain[255];
646
647 pthread_mutex_lock(&lock);
648 md5_init(&mdctx);
649
650 #if 0
651 printfchars(NULL, "msppdecrypt auth in", "%02x ", auth, 16);
652 printfchars(NULL, "msppdecrypt salt in", "%02x ", salt, 2);
653 printfchars(NULL, "msppdecrypt in", "%02x ", text, len);
654 #endif
655
656 md5_update(&mdctx, sharedlen, shared);
657 md5_update(&mdctx, 16, auth);
658 md5_update(&mdctx, 2, salt);
659 md5_digest(&mdctx, sizeof(hash), hash);
660
661 #if 0
662 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
663 #endif
664
665 for (i = 0; i < 16; i++)
666 plain[i] = text[i] ^ hash[i];
667
668 for (offset = 16; offset < len; offset += 16) {
669 #if 0
670 printf("text + offset - 16 c(%d): ", offset / 16);
671 printfchars(NULL, NULL, "%02x ", text + offset - 16, 16);
672 #endif
673 md5_update(&mdctx, sharedlen, shared);
674 md5_update(&mdctx, 16, text + offset - 16);
675 md5_digest(&mdctx, sizeof(hash), hash);
676 #if 0
677 printfchars(NULL, "msppdecrypt hash", "%02x ", hash, 16);
678 #endif
679
680 for (i = 0; i < 16; i++)
681 plain[offset + i] = text[offset + i] ^ hash[i];
682 }
683
684 memcpy(text, plain, len);
685 #if 0
686 printfchars(NULL, "msppdecrypt out", "%02x ", text, len);
687 #endif
688
689 pthread_mutex_unlock(&lock);
690 return 1;
691 }
692
newrealmref(struct realm * r)693 struct realm *newrealmref(struct realm *r) {
694 if (r) {
695 pthread_mutex_lock(&r->refmutex);
696 r->refcount++;
697 pthread_mutex_unlock(&r->refmutex);
698 }
699 return r;
700 }
701
702 /* returns with lock on realm */
id2realm(struct list * realmlist,char * id)703 struct realm *id2realm(struct list *realmlist, char *id) {
704 struct list_node *entry;
705 struct realm *realm, *subrealm;
706
707 /* need to do locking for subrealms and check subrealm timers */
708 for (entry = list_first(realmlist); entry; entry = list_next(entry)) {
709 realm = (struct realm *)entry->data;
710 if (!regexec(&realm->regex, id, 0, NULL, 0)) {
711 pthread_mutex_lock(&realm->mutex);
712 if (realm->subrealms) {
713 subrealm = id2realm(realm->subrealms, id);
714 if (subrealm) {
715 pthread_mutex_unlock(&realm->mutex);
716 return subrealm;
717 }
718 }
719 return newrealmref(realm);
720 }
721 }
722 return NULL;
723 }
724
hasdynamicserver(struct list * srvconfs)725 int hasdynamicserver(struct list *srvconfs) {
726 struct list_node *entry;
727
728 for (entry = list_first(srvconfs); entry; entry = list_next(entry))
729 if (((struct clsrvconf *)entry->data)->servers->dynamiclookuparg)
730 return 1;
731 return 0;
732 }
733
734 /* helper function, only used by removeserversubrealms() */
_internal_removeserversubrealms(struct list * realmlist,struct clsrvconf * srv)735 void _internal_removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) {
736 struct list_node *entry, *entry2;
737 struct realm *realm;
738 struct list *srvconfs;
739
740 for (entry = list_first(realmlist); entry;) {
741 realm = newrealmref((struct realm *)entry->data);
742 entry = list_next(entry);
743 pthread_mutex_lock(&realm->mutex);
744
745 if (realm->srvconfs) {
746 srvconfs = realm->srvconfs;
747 for (entry2 = list_first(realm->srvconfs); entry2; entry2 = list_next(entry2))
748 if (entry2->data == srv)
749 freerealm(realm);
750 list_removedata(srvconfs, srv);
751 }
752 if (realm->accsrvconfs) {
753 srvconfs = realm->accsrvconfs;
754 for (entry2 = list_first(realm->accsrvconfs); entry2; entry2 = list_next(entry2))
755 if (entry2->data == srv)
756 freerealm(realm);
757 list_removedata(srvconfs, srv);
758 }
759
760 /* remove subrealm if no dynamic servers left */
761 if (!hasdynamicserver(realm->srvconfs) && !hasdynamicserver(realm->accsrvconfs)) {
762 while (list_shift(realm->srvconfs))
763 freerealm(realm);
764 list_destroy(realm->srvconfs);
765 realm->srvconfs = NULL;
766 while (list_shift(realm->accsrvconfs))
767 freerealm(realm);
768 list_destroy(realm->accsrvconfs);
769 realm->accsrvconfs = NULL;
770 list_removedata(realmlist, realm);
771 }
772 pthread_mutex_unlock(&realm->mutex);
773 freerealm(realm);
774 }
775 }
776
removeserversubrealms(struct list * realmlist,struct clsrvconf * srv)777 void removeserversubrealms(struct list *realmlist, struct clsrvconf *srv) {
778 struct list_node *entry;
779 struct realm *realm;
780
781 for (entry = list_first(realmlist); entry; entry = list_next(entry)) {
782 realm = (struct realm *)entry->data;
783 pthread_mutex_lock(&realm->mutex);
784 if (realm->subrealms) {
785 _internal_removeserversubrealms(realm->subrealms, srv);
786 if (!list_first(realm->subrealms)) {
787 list_destroy(realm->subrealms);
788 realm->subrealms = NULL;
789 }
790 }
791 pthread_mutex_unlock(&realm->mutex);
792 }
793 }
794
pwdrecrypt(uint8_t * pwd,uint8_t len,uint8_t * oldsecret,int oldsecret_len,uint8_t * newsecret,int newsecret_len,uint8_t * oldauth,uint8_t * newauth,uint8_t * oldsalt,uint8_t oldsaltlen,uint8_t * newsalt,uint8_t newsaltlen)795 int pwdrecrypt(uint8_t *pwd, uint8_t len, uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len, uint8_t *oldauth, uint8_t *newauth,
796 uint8_t *oldsalt, uint8_t oldsaltlen, uint8_t *newsalt, uint8_t newsaltlen) {
797 if (len < 16 || len > 128 || len % 16) {
798 debug(DBG_WARN, "pwdrecrypt: invalid password length");
799 return 0;
800 }
801
802 if (!pwdcrypt(0, pwd, len, oldsecret, oldsecret_len, oldauth, oldsalt, oldsaltlen)) {
803 debug(DBG_WARN, "pwdrecrypt: cannot decrypt password");
804 return 0;
805 }
806 #ifdef DEBUG
807 printfchars(NULL, "pwdrecrypt: password", "%02x ", pwd, len);
808 #endif
809 if (!pwdcrypt(1, pwd, len, newsecret, newsecret_len, newauth, newsalt, newsaltlen)) {
810 debug(DBG_WARN, "pwdrecrypt: cannot encrypt password");
811 return 0;
812 }
813 return 1;
814 }
815
msmpprecrypt(uint8_t * msmpp,uint8_t len,uint8_t * oldsecret,int oldsecret_len,uint8_t * newsecret,int newsecret_len,uint8_t * oldauth,uint8_t * newauth)816 int msmpprecrypt(uint8_t *msmpp, uint8_t len, uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len, uint8_t *oldauth, uint8_t *newauth) {
817 if (len < 18)
818 return 0;
819 if (!msmppdecrypt(msmpp + 2, len - 2, oldsecret, oldsecret_len, oldauth, msmpp)) {
820 debug(DBG_WARN, "msmpprecrypt: failed to decrypt msppe key");
821 return 0;
822 }
823 if (!msmppencrypt(msmpp + 2, len - 2, newsecret, newsecret_len, newauth, msmpp)) {
824 debug(DBG_WARN, "msmpprecrypt: failed to encrypt msppe key");
825 return 0;
826 }
827 return 1;
828 }
829
msmppe(unsigned char * attrs,int length,uint8_t type,char * attrtxt,struct request * rq,uint8_t * oldsecret,int oldsecret_len,uint8_t * newsecret,int newsecret_len)830 int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct request *rq,
831 uint8_t *oldsecret, int oldsecret_len, uint8_t *newsecret, int newsecret_len) {
832 unsigned char *attr;
833
834 for (attr = attrs; (attr = attrget(attr, length - (attr - attrs), type)); attr += ATTRLEN(attr)) {
835 debug(DBG_DBG, "msmppe: Got %s", attrtxt);
836 if (!msmpprecrypt(ATTRVAL(attr), ATTRVALLEN(attr), oldsecret, oldsecret_len, newsecret, newsecret_len, rq->buf + 4, rq->rqauth))
837 return 0;
838 }
839 return 1;
840 }
841
rewriteusername(struct request * rq,struct tlv * attr)842 int rewriteusername(struct request *rq, struct tlv *attr) {
843 char *orig = (char *)tlv2str(attr);
844 if (!dorewritemodattr(attr, rq->from->conf->rewriteusername)) {
845 free(orig);
846 return 0;
847 }
848 if (strlen(orig) != attr->l || memcmp(orig, attr->v, attr->l))
849 rq->origusername = (char *)orig;
850 else
851 free(orig);
852 return 1;
853 }
854
addttlattr(struct radmsg * msg,uint32_t * attrtype,uint8_t addttl)855 void addttlattr(struct radmsg *msg, uint32_t *attrtype, uint8_t addttl) {
856 uint8_t ttl[4];
857 struct tlv *attr;
858
859 memset(ttl, 0, 4);
860 ttl[3] = addttl;
861
862 if (attrtype[1] == 256) { /* not vendor */
863 attr = maketlv(attrtype[0], 4, ttl);
864 if (attr && !radmsg_add(msg, attr))
865 freetlv(attr);
866 } else {
867 attr = maketlv(attrtype[1], 4, ttl);
868 if (attr)
869 addvendorattr(msg, attrtype[0], attr);
870 }
871 }
872
decttl(uint8_t l,uint8_t * v)873 int decttl(uint8_t l, uint8_t *v) {
874 int i;
875
876 if (l == 0)
877 return 0;
878
879 i = l - 1;
880 if (v[i]) {
881 if (--v[i--])
882 return 1;
883 while (i >= 0 && !v[i])
884 i--;
885 return i >= 0;
886 }
887 for (i--; i >= 0 && !v[i]; i--);
888 if (i < 0)
889 return 0;
890 v[i]--;
891 while (++i < l)
892 v[i] = 255;
893 return 1;
894 }
895
896 /* returns -1 if no ttl, 0 if exceeded, 1 if ok */
checkttl(struct radmsg * msg,uint32_t * attrtype)897 int checkttl(struct radmsg *msg, uint32_t *attrtype) {
898 uint8_t alen, *subattrs;
899 struct tlv *attr;
900 struct list_node *node;
901 uint32_t vendor;
902 int sublen;
903
904 if (attrtype[1] == 256) { /* not vendor */
905 attr = radmsg_gettype(msg, attrtype[0]);
906 if (attr)
907 return decttl(attr->l, attr->v);
908 } else
909 for (node = list_first(msg->attrs); node; node = list_next(node)) {
910 attr = (struct tlv *)node->data;
911 if (attr->t != RAD_Attr_Vendor_Specific || attr->l <= 4)
912 continue;
913 memcpy(&vendor, attr->v, 4);
914 if (ntohl(vendor) != attrtype[0])
915 continue;
916 sublen = attr->l - 4;
917 subattrs = attr->v + 4;
918 if (!attrvalidate(subattrs, sublen))
919 continue;
920 while (sublen > 1) {
921 if (ATTRTYPE(subattrs) == attrtype[1])
922 return decttl(ATTRVALLEN(subattrs), ATTRVAL(subattrs));
923 alen = ATTRLEN(subattrs);
924 sublen -= alen;
925 subattrs += alen;
926 }
927 }
928 return -1;
929 }
930
radmsgtype2string(uint8_t code)931 const char *radmsgtype2string(uint8_t code) {
932 static const char *rad_msg_names[] = {
933 "", "Access-Request", "Access-Accept", "Access-Reject",
934 "Accounting-Request", "Accounting-Response", "", "",
935 "", "", "", "Access-Challenge",
936 "Status-Server", "Status-Client"
937 };
938 return code < 14 && *rad_msg_names[code] ? rad_msg_names[code] : "Unknown";
939 }
940
char2hex(char * h,unsigned char c)941 void char2hex(char *h, unsigned char c) {
942 static const char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
943 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
944 h[0] = hexdigits[c / 16];
945 h[1] = hexdigits[c % 16];
946 return;
947 }
948
radattr2ascii(struct tlv * attr)949 uint8_t *radattr2ascii(struct tlv *attr) {
950 int i, l;
951 uint8_t *a, *d;
952
953 if (!attr)
954 return NULL;
955
956 l = attr->l;
957 for (i = 0; i < attr->l; i++)
958 if (attr->v[i] < 32 || attr->v[i] > 126)
959 l += 2;
960 if (l == attr->l)
961 return (uint8_t *)stringcopy((char *)attr->v, attr->l);
962
963 a = malloc(l + 1);
964 if (!a)
965 return NULL;
966
967 d = a;
968 for (i = 0; i < attr->l; i++)
969 if (attr->v[i] < 32 || attr->v[i] > 126) {
970 *d++ = '%';
971 char2hex((char *)d, attr->v[i]);
972 d += 2;
973 } else
974 *d++ = attr->v[i];
975 *d = '\0';
976 return a;
977 }
978
replylog(struct radmsg * msg,struct server * server,struct request * rq)979 void replylog(struct radmsg *msg, struct server *server, struct request *rq) {
980 uint8_t *username, *logusername = NULL, *stationid, *replymsg, *tmpmsg;
981 char *servername, *logstationid = NULL;
982 uint8_t level = DBG_NOTICE;
983 char tmp[INET6_ADDRSTRLEN];
984
985 servername = server ? server->conf->name : "_self_";
986 username = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_User_Name));
987 if (username) {
988 logusername = options.logfullusername ? username : (uint8_t *)strchr((char *)username, '@');
989 }
990 stationid = radattr2ascii(radmsg_gettype(rq->msg, RAD_Attr_Calling_Station_Id));
991 if (stationid) {
992 logstationid = calloc(128, sizeof(char));
993 sprintf((char *)logstationid, " stationid ");
994 switch (options.log_mac) {
995 case RSP_MAC_VENDOR_HASHED:
996 case RSP_MAC_VENDOR_KEY_HASHED:
997 memcpy(logstationid + 11, stationid, 9);
998 fticks_hashmac((uint8_t *)stationid, options.log_mac == RSP_MAC_VENDOR_KEY_HASHED ?
999 options.log_key : NULL, 65, (uint8_t *)logstationid+20);
1000 break;
1001 case RSP_MAC_FULLY_HASHED:
1002 case RSP_MAC_FULLY_KEY_HASHED:
1003 fticks_hashmac((uint8_t *)stationid, options.log_mac == RSP_MAC_FULLY_KEY_HASHED ?
1004 options.log_key : NULL, 65, (uint8_t *)logstationid+11);
1005 break;
1006 case RSP_MAC_STATIC:
1007 sprintf(logstationid+11, "undisclosed");
1008 break;
1009 case RSP_MAC_ORIGINAL:
1010 default:
1011 strncpy(logstationid+11, (char *)stationid, 128-12);
1012 }
1013 free(stationid);
1014 }
1015 replymsg = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Reply_Message));
1016 if (replymsg) {
1017 if (asprintf((char **)&tmpmsg, " (%s)", replymsg) >= 0) {
1018 free(replymsg);
1019 replymsg = tmpmsg;
1020 }
1021 }
1022
1023 if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Accounting_Response) {
1024 if (msg->code == RAD_Accounting_Response)
1025 level = DBG_INFO;
1026 if (logusername) {
1027 debug(level, "%s for user %s%s from %s%s to %s (%s)",
1028 radmsgtype2string(msg->code), logusername, logstationid ? logstationid : "",
1029 servername, replymsg ? (char *)replymsg : "", rq->from->conf->name,
1030 addr2string(rq->from->addr, tmp, sizeof(tmp)));
1031 } else {
1032 debug(level, "%s (response to %s) from %s to %s (%s)", radmsgtype2string(msg->code),
1033 radmsgtype2string(rq->msg->code), servername,
1034 rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp)));
1035 }
1036 } else if(msg->code == RAD_Access_Request) {
1037 debug(level, "missing response to %s for user %s%s from %s (%s) to %s",
1038 radmsgtype2string(msg->code), logusername, logstationid ? logstationid : "",
1039 rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp)), servername);
1040 }
1041 free(username);
1042 free(logstationid);
1043 free(replymsg);
1044 }
1045
respond(struct request * rq,uint8_t code,char * message,int copy_proxystate_flag,int add_msg_auth)1046 void respond(struct request *rq, uint8_t code, char *message,
1047 int copy_proxystate_flag, int add_msg_auth)
1048 {
1049 struct radmsg *msg;
1050 struct tlv *attr;
1051 char tmp[INET6_ADDRSTRLEN];
1052
1053 msg = radmsg_init(code, rq->msg->id, rq->msg->auth);
1054 if (!msg) {
1055 debug(DBG_ERR, "respond: malloc failed");
1056 return;
1057 }
1058
1059 if (add_msg_auth) {
1060 attr = maketlv(RAD_Attr_Message_Authenticator, 16, NULL);
1061 if (!attr || !radmsg_add(msg, attr)) {
1062 freetlv(attr);
1063 radmsg_free(msg);
1064 debug(DBG_ERR, "respond: malloc failed");
1065 return;
1066 }
1067 }
1068 if (message && *message) {
1069 attr = maketlv(RAD_Attr_Reply_Message, strlen(message), message);
1070 if (!attr || !radmsg_add(msg, attr)) {
1071 freetlv(attr);
1072 radmsg_free(msg);
1073 debug(DBG_ERR, "respond: malloc failed");
1074 return;
1075 }
1076 }
1077 if (copy_proxystate_flag) {
1078 if (radmsg_copy_attrs(msg, rq->msg, RAD_Attr_Proxy_State) < 0) {
1079 debug(DBG_ERR, "%s: unable to copy all Proxy-State attributes",
1080 __func__);
1081 }
1082 }
1083
1084 replylog(msg, NULL, rq);
1085 debug(DBG_DBG, "respond: sending %s (id %d) to %s (%s)", radmsgtype2string(msg->code), msg->id, rq->from->conf->name, addr2string(rq->from->addr, tmp, sizeof(tmp)));
1086
1087 radmsg_free(rq->msg);
1088 rq->msg = msg;
1089 sendreply(newrqref(rq));
1090 }
1091
choosesrvconf(struct list * srvconfs)1092 struct clsrvconf *choosesrvconf(struct list *srvconfs) {
1093 struct list_node *entry;
1094 struct clsrvconf *server, *best = NULL, *first = NULL;
1095
1096 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
1097 server = (struct clsrvconf *)entry->data;
1098 if (!server->servers)
1099 return server;
1100 if (server->servers->state == RSP_SERVER_STATE_FAILING)
1101 continue;
1102 if (!first)
1103 first = server;
1104 if (server->servers->state == RSP_SERVER_STATE_STARTUP || server->servers->state == RSP_SERVER_STATE_RECONNECTING)
1105 continue;
1106 if (!server->servers->lostrqs)
1107 return server;
1108 if (!best) {
1109 best = server;
1110 continue;
1111 }
1112 if (server->servers->lostrqs < best->servers->lostrqs)
1113 best = server;
1114 }
1115 if (best && best->servers->lostrqs == MAX_LOSTRQS)
1116 for (entry = list_first(srvconfs); entry; entry = list_next(entry))
1117 if (((struct clsrvconf *)entry->data)->servers->lostrqs == MAX_LOSTRQS)
1118 ((struct clsrvconf *)entry->data)->servers->lostrqs--;
1119 return best ? best : first;
1120 }
1121
1122 /* returns with lock on realm, protects from server changes while in use by radsrv/sendrq */
findserver(struct realm ** realm,struct tlv * username,uint8_t acc)1123 struct server *findserver(struct realm **realm, struct tlv *username, uint8_t acc) {
1124 struct clsrvconf *srvconf;
1125 struct realm *subrealm;
1126 struct server *server = NULL;
1127 char *id = (char *)tlv2str(username);
1128
1129 if (!id)
1130 return NULL;
1131 /* returns with lock on realm */
1132 *realm = id2realm(realms, id);
1133 if (!*realm)
1134 goto exit;
1135 debug(DBG_DBG, "found matching realm: %s", (*realm)->name);
1136 srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs);
1137 if (srvconf && !(*realm)->parent && !srvconf->servers && srvconf->dynamiclookupcommand) {
1138 subrealm = adddynamicrealmserver(*realm, id);
1139 if (subrealm) {
1140 pthread_mutex_lock(&subrealm->mutex);
1141 pthread_mutex_unlock(&(*realm)->mutex);
1142 freerealm(*realm);
1143 *realm = subrealm;
1144 debug(DBG_DBG, "added realm: %s", (*realm)->name);
1145 srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs);
1146 debug(DBG_DBG, "found conf for new realm: %s", srvconf->name);
1147 }
1148 }
1149 if (srvconf) {
1150 debug(DBG_DBG, "found matching conf: %s", srvconf->name);
1151 server = srvconf->servers;
1152 }
1153
1154 exit:
1155 free(id);
1156 return server;
1157 }
1158
1159
newrequest()1160 struct request *newrequest() {
1161 struct request *rq;
1162
1163 rq = malloc(sizeof(struct request));
1164 if (!rq) {
1165 debug(DBG_ERR, "newrequest: malloc failed");
1166 return NULL;
1167 }
1168 memset(rq, 0, sizeof(struct request));
1169 rq->refcount = 1;
1170 pthread_mutex_init(&rq->refmutex, NULL);
1171 gettimeofday(&rq->created, NULL);
1172 return rq;
1173 }
1174
1175 static void
purgedupcache(struct client * client)1176 purgedupcache(struct client *client) {
1177 struct request *r;
1178 struct timeval now;
1179 int i;
1180
1181 gettimeofday(&now, NULL);
1182 for (i = 0; i < MAX_REQUESTS; i++) {
1183 r = client->rqs[i];
1184 if (r && now.tv_sec - r->created.tv_sec > r->from->conf->dupinterval) {
1185 removeclientrq(client, i);
1186 }
1187 }
1188 }
1189
addclientrq(struct request * rq)1190 int addclientrq(struct request *rq) {
1191 struct request *r;
1192 struct timeval now;
1193 char tmp[INET6_ADDRSTRLEN];
1194
1195 r = rq->from->rqs[rq->rqid];
1196 if (r) {
1197 if (!memcmp(rq->rqauth, r->rqauth, 16)) {
1198 gettimeofday(&now, NULL);
1199 if (now.tv_sec - r->created.tv_sec < r->from->conf->dupinterval) {
1200 if (r->replybuf) {
1201 debug(DBG_INFO, "addclientrq: already sent reply to request with id %d from %s, resending", rq->rqid, addr2string(r->from->addr, tmp, sizeof(tmp)));
1202 sendreply(newrqref(r));
1203 } else
1204 debug(DBG_INFO, "addclientrq: already got request with id %d from %s, ignoring", rq->rqid, addr2string(r->from->addr, tmp, sizeof(tmp)));
1205 return 0;
1206 }
1207 }
1208 removeclientrq(rq->from, rq->rqid);
1209 }
1210 rq->from->rqs[rq->rqid] = newrqref(rq);
1211 return 1;
1212 }
1213
rmclientrq(struct request * rq,uint8_t id)1214 void rmclientrq(struct request *rq, uint8_t id) {
1215 struct request *r;
1216
1217 r = rq->from->rqs[id];
1218 if (r) {
1219 freerq(r);
1220 rq->from->rqs[id] = NULL;
1221 }
1222 }
1223
1224 /* Called from server readers, handling incoming requests from
1225 * clients. */
1226 /* returns 0 if validation/authentication fails, else 1 */
radsrv(struct request * rq)1227 int radsrv(struct request *rq) {
1228 struct radmsg *msg = NULL;
1229 struct tlv *attr;
1230 uint8_t *userascii = NULL;
1231 struct realm *realm = NULL;
1232 struct server *to = NULL;
1233 struct client *from = rq->from;
1234 int ttlres;
1235 char tmp[INET6_ADDRSTRLEN];
1236
1237 msg = buf2radmsg(rq->buf, from->conf->secret, from->conf->secret_len, NULL);
1238 free(rq->buf);
1239 rq->buf = NULL;
1240
1241 if (!msg) {
1242 debug(DBG_NOTICE, "radsrv: ignoring request from %s (%s), validation failed.", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)));
1243 freerq(rq);
1244 return 0;
1245 }
1246
1247 rq->msg = msg;
1248 rq->rqid = msg->id;
1249 memcpy(rq->rqauth, msg->auth, 16);
1250
1251 debug(DBG_DBG, "radsrv: code %d, id %d", msg->code, msg->id);
1252 if (msg->code != RAD_Access_Request && msg->code != RAD_Status_Server && msg->code != RAD_Accounting_Request) {
1253 debug(DBG_INFO, "radsrv: server currently accepts only access-requests, accounting-requests and status-server, ignoring");
1254 goto exit;
1255 }
1256
1257 purgedupcache(from);
1258 if (!addclientrq(rq))
1259 goto exit;
1260
1261 if (msg->code == RAD_Status_Server) {
1262 respond(rq, RAD_Access_Accept, NULL, 1, 0);
1263 goto exit;
1264 }
1265
1266 /* below: code == RAD_Access_Request || code == RAD_Accounting_Request */
1267
1268 if (from->conf->rewritein && !dorewrite(msg, from->conf->rewritein))
1269 goto rmclrqexit;
1270
1271 ttlres = checkttl(msg, options.ttlattrtype);
1272 if (!ttlres) {
1273 debug(DBG_INFO, "radsrv: ignoring request from client %s (%s), ttl exceeded", from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)));
1274 goto exit;
1275 }
1276
1277 attr = radmsg_gettype(msg, RAD_Attr_User_Name);
1278 if (!attr) {
1279 if (msg->code == RAD_Accounting_Request) {
1280 respond(rq, RAD_Accounting_Response, NULL, 1, 0);
1281 } else
1282 debug(DBG_INFO, "radsrv: ignoring access request, no username attribute");
1283 goto exit;
1284 }
1285
1286 if (from->conf->rewriteusername && !rewriteusername(rq, attr)) {
1287 debug(DBG_WARN, "radsrv: username malloc failed, ignoring request");
1288 goto rmclrqexit;
1289 }
1290
1291 userascii = radattr2ascii(attr);
1292 if (!userascii)
1293 goto rmclrqexit;
1294 debug(DBG_INFO, "radsrv: got %s (id %d) with username: %s from client %s (%s)", radmsgtype2string(msg->code), msg->id, userascii, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)));
1295
1296 /* will return with lock on the realm */
1297 to = findserver(&realm, attr, msg->code == RAD_Accounting_Request);
1298 if (!realm) {
1299 debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
1300 goto exit;
1301 }
1302
1303 if (!to) {
1304 if (realm->message && msg->code == RAD_Access_Request) {
1305 debug(DBG_INFO, "radsrv: sending %s (id %d) to %s (%s) for %s", radmsgtype2string(RAD_Access_Reject), msg->id, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), userascii);
1306 respond(rq, RAD_Access_Reject, realm->message, 1, 1);
1307 } else if (realm->accresp && msg->code == RAD_Accounting_Request) {
1308 respond(rq, RAD_Accounting_Response, NULL, 1, 0);
1309 }
1310 goto exit;
1311 }
1312
1313 if ((to->conf->loopprevention == 1
1314 || (to->conf->loopprevention == UCHAR_MAX && options.loopprevention == 1))
1315 && !strcmp(from->conf->name, to->conf->name)) {
1316 debug(DBG_INFO, "radsrv: Loop prevented, not forwarding request from client %s (%s) to server %s, discarding",
1317 from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), to->conf->name);
1318 goto exit;
1319 }
1320
1321 /* If there is a CHAP-Password attribute but no CHAP-Challenge
1322 * one, create a CHAP-Challenge containing the Request
1323 * Authenticator because that's what the CHAP-Password is based
1324 * on. */
1325 attr = radmsg_gettype(msg, RAD_Attr_CHAP_Password);
1326 if (attr) {
1327 debug(DBG_DBG, "%s: found CHAP-Password with value length %d", __func__,
1328 attr->l);
1329 attr = radmsg_gettype(msg, RAD_Attr_CHAP_Challenge);
1330 if (attr == NULL) {
1331 debug(DBG_DBG, "%s: no CHAP-Challenge found, creating one", __func__);
1332 attr = maketlv(RAD_Attr_CHAP_Challenge, 16, msg->auth);
1333 if (attr == NULL || radmsg_add(msg, attr) != 1) {
1334 debug(DBG_ERR, "%s: adding CHAP-Challenge failed, "
1335 "CHAP-Password request dropped", __func__);
1336 freetlv(attr);
1337 goto rmclrqexit;
1338 }
1339 }
1340 }
1341
1342 /* Create new Request Authenticator. */
1343 if (msg->code == RAD_Accounting_Request)
1344 memset(msg->auth, 0, 16);
1345 else if (!RAND_bytes(msg->auth, 16)) {
1346 debug(DBG_WARN, "radsrv: failed to generate random auth");
1347 goto rmclrqexit;
1348 }
1349
1350 #ifdef DEBUG
1351 printfchars(NULL, "auth", "%02x ", msg->auth, 16);
1352 #endif
1353
1354 attr = radmsg_gettype(msg, RAD_Attr_User_Password);
1355 if (attr) {
1356 debug(DBG_DBG, "radsrv: found userpwdattr with value length %d", attr->l);
1357 if (!pwdrecrypt(attr->v, attr->l, from->conf->secret, from->conf->secret_len, to->conf->secret, to->conf->secret_len, rq->rqauth, msg->auth, NULL, 0, NULL, 0))
1358 goto rmclrqexit;
1359 }
1360
1361 if (to->conf->rewriteout && !dorewrite(msg, to->conf->rewriteout))
1362 goto rmclrqexit;
1363
1364 if (ttlres == -1 && (options.addttl || to->conf->addttl))
1365 addttlattr(msg, options.ttlattrtype, to->conf->addttl ? to->conf->addttl : options.addttl);
1366
1367 free(userascii);
1368 rq->to = to;
1369 sendrq(rq);
1370 pthread_mutex_unlock(&realm->mutex);
1371 freerealm(realm);
1372 return 1;
1373
1374 rmclrqexit:
1375 rmclientrq(rq, msg->id);
1376 exit:
1377 freerq(rq);
1378 free(userascii);
1379 if (realm) {
1380 pthread_mutex_unlock(&realm->mutex);
1381 freerealm(realm);
1382 }
1383 return 1;
1384 }
1385
1386 /* Called from client readers, handling replies from servers. */
replyh(struct server * server,unsigned char * buf)1387 void replyh(struct server *server, unsigned char *buf) {
1388 struct client *from;
1389 struct rqout *rqout;
1390 int sublen, ttlres;
1391 unsigned char *subattrs;
1392 struct radmsg *msg = NULL;
1393 struct tlv *attr;
1394 struct list_node *node;
1395 char tmp[INET6_ADDRSTRLEN];
1396
1397 server->lostrqs = 0;
1398
1399 rqout = server->requests + buf[1];
1400 pthread_mutex_lock(rqout->lock);
1401 if (!rqout->tries) {
1402 free(buf);
1403 buf = NULL;
1404 debug(DBG_INFO, "replyh: no outstanding request with this id, ignoring reply");
1405 goto errunlock;
1406 }
1407
1408 msg = buf2radmsg(buf, server->conf->secret, server->conf->secret_len, rqout->rq->msg->auth);
1409 #ifdef DEBUG
1410 printfchars(NULL, "origauth/buf+4", "%02x ", buf + 4, 16);
1411 #endif
1412 free(buf);
1413 buf = NULL;
1414 if (!msg) {
1415 debug(DBG_NOTICE, "replyh: ignoring message from server %s, validation failed", server->conf->name);
1416 goto errunlock;
1417 }
1418 if (msg->code != RAD_Access_Accept && msg->code != RAD_Access_Reject && msg->code != RAD_Access_Challenge
1419 && msg->code != RAD_Accounting_Response) {
1420 debug(DBG_INFO, "replyh: discarding message type %s, accepting only access accept, access reject, access challenge and accounting response messages", radmsgtype2string(msg->code));
1421 goto errunlock;
1422 }
1423 debug(DBG_DBG, "got %s message with id %d", radmsgtype2string(msg->code), msg->id);
1424
1425 gettimeofday(&server->lastrcv, NULL);
1426
1427 if (rqout->rq->msg->code == RAD_Status_Server) {
1428 freerqoutdata(rqout);
1429 debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name);
1430 if (server->conf->statusserver == RSP_STATSRV_AUTO)
1431 server->conf->statusserver = RSP_STATSRV_MINIMAL;
1432 goto errunlock;
1433 }
1434
1435 gettimeofday(&server->lastreply, NULL);
1436
1437 if (server->conf->rewritein && !dorewrite(msg, server->conf->rewritein)) {
1438 debug(DBG_INFO, "replyh: rewritein failed");
1439 goto errunlock;
1440 }
1441
1442 ttlres = checkttl(msg, options.ttlattrtype);
1443 if (!ttlres) {
1444 debug(DBG_INFO, "replyh: ignoring reply from server %s, ttl exceeded", server->conf->name);
1445 goto errunlock;
1446 }
1447
1448 from = rqout->rq->from;
1449
1450 /* MS MPPE */
1451 for (node = list_first(msg->attrs); node; node = list_next(node)) {
1452 attr = (struct tlv *)node->data;
1453 if (attr->t != RAD_Attr_Vendor_Specific)
1454 continue;
1455 if (attr->l <= 4)
1456 break;
1457 if (attr->v[0] != 0 || attr->v[1] != 0 || attr->v[2] != 1 || attr->v[3] != 55) /* 311 == MS */
1458 continue;
1459
1460 sublen = attr->l - 4;
1461 subattrs = attr->v + 4;
1462 if (!attrvalidate(subattrs, sublen) ||
1463 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Send_Key, "MS MPPE Send Key",
1464 rqout->rq, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len) ||
1465 !msmppe(subattrs, sublen, RAD_VS_ATTR_MS_MPPE_Recv_Key, "MS MPPE Recv Key",
1466 rqout->rq, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len))
1467 break;
1468 }
1469 if (node) {
1470 debug(DBG_WARN, "replyh: MS attribute handling failed, ignoring reply");
1471 goto errunlock;
1472 }
1473
1474 /* reencrypt tunnel-password RFC2868 */
1475 attr = radmsg_gettype(msg, RAD_Attr_Tunnel_Password);
1476 if (attr && msg->code == RAD_Access_Accept) {
1477 uint8_t newsalt[2];
1478 debug(DBG_DBG, "replyh: found tunnelpwdattr with value length %d", attr->l);
1479 if (!RAND_bytes(newsalt,2))
1480 goto errunlock;
1481 newsalt[0] |= 0x80;
1482 if (!pwdrecrypt(attr->v+3, attr->l-3, server->conf->secret, server->conf->secret_len, from->conf->secret, from->conf->secret_len,
1483 rqout->rq->msg->auth, rqout->rq->rqauth, attr->v+1, 2, newsalt, 2))
1484 goto errunlock;
1485 memcpy(attr->v+1, newsalt, 2);
1486 }
1487
1488 replylog(msg, server, rqout->rq);
1489
1490 if (msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject)
1491 if (options.fticks_reporting && from->conf->fticks_viscountry != NULL)
1492 fticks_log(&options, from, msg, rqout->rq);
1493
1494 msg->id = (char)rqout->rq->rqid;
1495 memcpy(msg->auth, rqout->rq->rqauth, 16);
1496
1497 if (rqout->rq->origusername && (attr = radmsg_gettype(msg, RAD_Attr_User_Name))) {
1498 if (!resizeattr(attr, strlen(rqout->rq->origusername))) {
1499 debug(DBG_WARN, "replyh: malloc failed, ignoring reply");
1500 goto errunlock;
1501 }
1502 memcpy(attr->v, rqout->rq->origusername, strlen(rqout->rq->origusername));
1503 }
1504
1505 if (from->conf->rewriteout && !dorewrite(msg, from->conf->rewriteout)) {
1506 debug(DBG_WARN, "replyh: rewriteout failed");
1507 goto errunlock;
1508 }
1509
1510 if (ttlres == -1 && (options.addttl || from->conf->addttl))
1511 addttlattr(msg, options.ttlattrtype, from->conf->addttl ? from->conf->addttl : options.addttl);
1512
1513 debug(DBG_DBG, "replyh: passing %s (id %d) to client %s (%s)", radmsgtype2string(msg->code), msg->id, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)));
1514
1515 radmsg_free(rqout->rq->msg);
1516 rqout->rq->msg = msg;
1517 sendreply(newrqref(rqout->rq));
1518 freerqoutdata(rqout);
1519 pthread_mutex_unlock(rqout->lock);
1520 return;
1521
1522 errunlock:
1523 radmsg_free(msg);
1524 pthread_mutex_unlock(rqout->lock);
1525 return;
1526 }
1527
createstatsrvrq()1528 struct request *createstatsrvrq() {
1529 struct request *rq;
1530 struct tlv *attr;
1531
1532 rq = newrequest();
1533 if (!rq)
1534 return NULL;
1535 rq->msg = radmsg_init(RAD_Status_Server, 0, NULL);
1536 if (!rq->msg)
1537 goto exit;
1538 attr = maketlv(RAD_Attr_Message_Authenticator, 16, NULL);
1539 if (!attr)
1540 goto exit;
1541 if (!radmsg_add(rq->msg, attr)) {
1542 freetlv(attr);
1543 goto exit;
1544 }
1545 return rq;
1546
1547 exit:
1548 freerq(rq);
1549 return NULL;
1550 }
1551
1552 /* code for removing state not finished */
clientwr(void * arg)1553 void *clientwr(void *arg) {
1554 struct server *server = (struct server *)arg;
1555 struct rqout *rqout = NULL;
1556 pthread_t clientrdth;
1557 int i, dynconffail = 0;
1558 time_t secs;
1559 uint8_t rnd, do_resend = 0, statusserver_requested = 0;
1560 struct timeval now, laststatsrv;
1561 struct timespec timeout;
1562 struct request *statsrvrq;
1563 struct clsrvconf *conf;
1564
1565 assert(server);
1566 conf = server->conf;
1567
1568 #define ZZZ 900
1569
1570 server->state = RSP_SERVER_STATE_STARTUP;
1571 if (server->dynamiclookuparg && !dynamicconfig(server)) {
1572 dynconffail = 1;
1573 server->state = RSP_SERVER_STATE_FAILING;
1574 debug(DBG_WARN, "%s: dynamicconfig(%s: %s) failed, sleeping %ds",
1575 __func__, server->conf->name, server->dynamiclookuparg, ZZZ);
1576 sleep(ZZZ);
1577 goto errexit;
1578 }
1579 /* FIXME: Is resolving not always done by compileserverconfig(),
1580 * either as part of static configuration setup or by
1581 * dynamicconfig() above? */
1582 if (!resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) {
1583 debug(DBG_WARN, "%s: resolve failed, sleeping %ds", __func__, ZZZ);
1584 server->state = RSP_SERVER_STATE_FAILING;
1585 sleep(ZZZ);
1586 goto errexit;
1587 }
1588
1589 memset(&timeout, 0, sizeof(struct timespec));
1590
1591 gettimeofday(&server->lastreply, NULL);
1592 server->lastrcv = server->lastreply;
1593 laststatsrv = server->lastreply;
1594
1595 if (conf->pdef->connecter) {
1596 if (!conf->pdef->connecter(server, server->dynamiclookuparg ? 5 : 0, "clientwr")) {
1597 server->state = RSP_SERVER_STATE_FAILING;
1598 if (server->dynamiclookuparg) {
1599 debug(DBG_WARN, "%s: connect failed, sleeping %ds",
1600 __func__, ZZZ);
1601 sleep(ZZZ);
1602 }
1603 goto errexit;
1604 }
1605 if (pthread_create(&clientrdth, &pthread_attr, conf->pdef->clientconnreader, (void *)server)) {
1606 debugerrno(errno, DBG_ERR, "clientwr: pthread_create failed");
1607 server->state = RSP_SERVER_STATE_FAILING;
1608 goto errexit;
1609 }
1610 }
1611 server->state = RSP_SERVER_STATE_CONNECTED;
1612
1613 for (;;) {
1614 pthread_mutex_lock(&server->newrq_mutex);
1615 if (!server->newrq) {
1616 gettimeofday(&now, NULL);
1617 /* random 0-7 seconds */
1618 RAND_bytes(&rnd, 1);
1619 rnd /= 32;
1620 if (conf->statusserver != RSP_STATSRV_OFF) {
1621 secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec;
1622 if (now.tv_sec - secs > STATUS_SERVER_PERIOD)
1623 secs = now.tv_sec;
1624 if (!timeout.tv_sec || timeout.tv_sec > secs + STATUS_SERVER_PERIOD + rnd)
1625 timeout.tv_sec = secs + STATUS_SERVER_PERIOD + rnd;
1626 } else {
1627 if (!timeout.tv_sec || timeout.tv_sec > now.tv_sec + STATUS_SERVER_PERIOD + rnd)
1628 timeout.tv_sec = now.tv_sec + STATUS_SERVER_PERIOD + rnd;
1629 }
1630 #if 0
1631 if (timeout.tv_sec > now.tv_sec)
1632 debug(DBG_DBG, "clientwr: waiting up to %ld secs for new request", timeout.tv_sec - now.tv_sec);
1633 #endif
1634 pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout);
1635 timeout.tv_sec = 0;
1636 }
1637 if (server->newrq) {
1638 debug(DBG_DBG, "clientwr: got new request");
1639 server->newrq = 0;
1640 }
1641 if (server->conreset) {
1642 debug(DBG_DBG, "clientwr: connection reset; resending all aoutstanding requests");
1643 do_resend = 1;
1644 server->conreset = 0;
1645 }
1646 #if 0
1647 else
1648 debug(DBG_DBG, "clientwr: request timer expired, processing request queue");
1649 #endif
1650 pthread_mutex_unlock(&server->newrq_mutex);
1651
1652 if (do_resend || server->lastrcv.tv_sec > laststatsrv.tv_sec)
1653 statusserver_requested = 0;
1654
1655 for (i = 0; i < MAX_REQUESTS; i++) {
1656 if (server->clientrdgone) {
1657 server->state = RSP_SERVER_STATE_FAILING;
1658 if (conf->pdef->connecter)
1659 pthread_join(clientrdth, NULL);
1660 goto errexit;
1661 }
1662
1663 for (; i < MAX_REQUESTS; i++) {
1664 rqout = server->requests + i;
1665 if (rqout->rq) {
1666 pthread_mutex_lock(rqout->lock);
1667 if (rqout->rq)
1668 break;
1669 pthread_mutex_unlock(rqout->lock);
1670 }
1671 }
1672
1673 if (i == MAX_REQUESTS)
1674 break;
1675
1676 gettimeofday(&now, NULL);
1677 if (do_resend) {
1678 if (rqout->tries > 0)
1679 rqout->tries--;
1680 } else if (now.tv_sec < rqout->expiry.tv_sec) {
1681 if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec)
1682 timeout.tv_sec = rqout->expiry.tv_sec;
1683 pthread_mutex_unlock(rqout->lock);
1684 continue;
1685 }
1686
1687 if (rqout->tries > 0 && now.tv_sec - server->lastrcv.tv_sec > conf->retryinterval && !do_resend)
1688 statusserver_requested = 1;
1689 if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) {
1690 debug(DBG_DBG, "clientwr: removing expired packet from queue");
1691 replylog(rqout->rq->msg, server, rqout->rq);
1692 if (conf->statusserver == RSP_STATSRV_ON || conf->statusserver == RSP_STATSRV_MINIMAL) {
1693 if (*rqout->rq->buf == RAD_Status_Server) {
1694 debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name);
1695 if (server->lostrqs < MAX_LOSTRQS)
1696 server->lostrqs++;
1697 }
1698 } else {
1699 if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) {
1700 if (server->lastreply.tv_sec >= laststatsrv.tv_sec) {
1701 debug(DBG_DBG, "clientwr: status server autodetect failed, disabling status server for %s", conf->name);
1702 conf->statusserver = RSP_STATSRV_OFF;
1703 }
1704 } else {
1705 debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name);
1706 if (server->lostrqs < MAX_LOSTRQS)
1707 server->lostrqs++;
1708 }
1709 }
1710 freerqoutdata(rqout);
1711 pthread_mutex_unlock(rqout->lock);
1712 continue;
1713 }
1714
1715 rqout->expiry.tv_sec = now.tv_sec + conf->retryinterval;
1716 if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec)
1717 timeout.tv_sec = rqout->expiry.tv_sec;
1718 rqout->tries++;
1719 if (!conf->pdef->clientradput(server, rqout->rq->buf)) {
1720 debug(DBG_WARN, "clientwr: could not send request to server %s", conf->name);
1721 if (server->lostrqs < MAX_LOSTRQS)
1722 server->lostrqs++;
1723 }
1724 pthread_mutex_unlock(rqout->lock);
1725 }
1726 do_resend = 0;
1727 if (server->state == RSP_SERVER_STATE_CONNECTED && !(conf->statusserver == RSP_STATSRV_OFF)) {
1728 gettimeofday(&now, NULL);
1729 if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - (server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec) > STATUS_SERVER_PERIOD) ||
1730 (conf->statusserver == RSP_STATSRV_MINIMAL && statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD) ||
1731 (conf->statusserver == RSP_STATSRV_AUTO && server->lastreply.tv_sec >= laststatsrv.tv_sec)) {
1732
1733 laststatsrv = now;
1734 statsrvrq = createstatsrvrq();
1735 if (statsrvrq) {
1736 statsrvrq->to = server;
1737 debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name);
1738 sendrq(statsrvrq);
1739 }
1740 statusserver_requested = 0;
1741 }
1742 }
1743 }
1744 errexit:
1745 if (server->dynamiclookuparg) {
1746 removeserversubrealms(realms, conf);
1747 if (dynconffail)
1748 free(conf);
1749 else
1750 freeclsrvconf(conf);
1751 }
1752 freeserver(server, 1);
1753 return NULL;
1754 }
1755
createlistener(uint8_t type,char * arg)1756 void createlistener(uint8_t type, char *arg) {
1757 pthread_t th;
1758 struct addrinfo *res;
1759 int s = -1, on = 1, *sp = NULL;
1760 struct hostportres *hp = newhostport(arg, protodefs[type]->portdefault, 0);
1761
1762 if (!hp || !resolvehostport(hp, AF_UNSPEC, protodefs[type]->socktype, 1))
1763 debugx(1, DBG_ERR, "createlistener: failed to resolve %s", arg);
1764
1765 for (res = hp->addrinfo; res; res = res->ai_next) {
1766 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1767 if (s < 0) {
1768 debugerrno(errno, DBG_WARN, "createlistener: socket failed");
1769 continue;
1770 }
1771 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
1772 debugerrno(errno, DBG_WARN, "createlistener: SO_REUSEADDR");
1773
1774 disable_DF_bit(s, res);
1775
1776 #ifdef IPV6_V6ONLY
1777 if (res->ai_family == AF_INET6)
1778 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
1779 debugerrno(errno, DBG_WARN, "createlistener: IPV6_V6ONLY");
1780 #endif
1781 if (res->ai_socktype == SOCK_DGRAM) {
1782 if (res->ai_family == AF_INET6) {
1783 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == -1)
1784 debugerrno(errno, DBG_WARN, "craetelistener: IPV6_RECVPKTINFO");
1785 } else if (res->ai_family == AF_INET) {
1786 #if defined(IP_PKTINFO)
1787 if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) == -1)
1788 debugerrno(errno, DBG_WARN, "createlistener: IP_PKTINFO");
1789 #elif defined(IP_RECVDSTADDR)
1790 if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) == -1)
1791 debugerrno(errno, DBG_WARN, "createlistener: IP_RECVDSTADDR");
1792 #endif
1793 }
1794 }
1795 if (bind(s, res->ai_addr, res->ai_addrlen)) {
1796 debugerrno(errno, DBG_WARN, "createlistener: bind failed");
1797 close(s);
1798 continue;
1799 }
1800
1801 sp = malloc(sizeof(int));
1802 if (!sp)
1803 debugx(1, DBG_ERR, "malloc failed");
1804 *sp = s;
1805 if (pthread_create(&th, &pthread_attr, protodefs[type]->listener, (void *)sp))
1806 debugerrnox(errno, DBG_ERR, "pthread_create failed");
1807 pthread_detach(th);
1808 }
1809 if (!sp)
1810 debugx(1, DBG_ERR, "createlistener: socket/bind failed");
1811
1812 debug(DBG_WARN, "createlistener: listening for %s on %s:%s", protodefs[type]->name, hp->host ? hp->host : "*", hp->port);
1813 freehostport(hp);
1814 }
1815
createlisteners(uint8_t type)1816 void createlisteners(uint8_t type) {
1817 int i;
1818 char **args;
1819
1820 args = protodefs[type]->getlistenerargs();
1821 if (args)
1822 for (i = 0; args[i]; i++)
1823 createlistener(type, args[i]);
1824 else
1825 createlistener(type, NULL);
1826 }
1827
randinit()1828 void randinit() {
1829 time_t t;
1830 pid_t pid;
1831
1832 while (!RAND_status()) {
1833 t = time(NULL);
1834 pid = getpid();
1835 RAND_seed((unsigned char *)&t, sizeof(time_t));
1836 RAND_seed((unsigned char *)&pid, sizeof(pid));
1837 }
1838 }
1839
addsrvconfs(char * value,char ** names)1840 struct list *addsrvconfs(char *value, char **names) {
1841 struct list *conflist;
1842 int n;
1843 struct list_node *entry;
1844 struct clsrvconf *conf = NULL;
1845
1846 if (!names || !*names)
1847 return NULL;
1848
1849 conflist = list_create();
1850 if (!conflist) {
1851 debug(DBG_ERR, "malloc failed");
1852 return NULL;
1853 }
1854
1855 for (n = 0; names[n]; n++) {
1856 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
1857 conf = (struct clsrvconf *)entry->data;
1858 if (!strcasecmp(names[n], conf->name))
1859 break;
1860 }
1861 if (!entry) {
1862 debug(DBG_ERR, "addsrvconfs failed for realm %s, no server named %s", value, names[n]);
1863 list_free(conflist);
1864 return NULL;
1865 }
1866 if (!list_push(conflist, conf)) {
1867 debug(DBG_ERR, "malloc failed");
1868 list_free(conflist);
1869 return NULL;
1870 }
1871 debug(DBG_DBG, "addsrvconfs: added server %s for realm %s", conf->name, value);
1872 }
1873 return conflist;
1874 }
1875
freerealm(struct realm * realm)1876 void freerealm(struct realm *realm) {
1877 if (!realm)
1878 return;
1879 debug(DBG_DBG, "freerealm: called with refcount %d", realm->refcount);
1880 pthread_mutex_lock(&realm->refmutex);
1881 if (--realm->refcount) {
1882 pthread_mutex_unlock(&realm->refmutex);
1883 return;
1884 }
1885 pthread_mutex_unlock(&realm->refmutex);
1886
1887 free(realm->name);
1888 free(realm->message);
1889 regfree(&realm->regex);
1890 pthread_mutex_destroy(&realm->refmutex);
1891 pthread_mutex_destroy(&realm->mutex);
1892 /* if refcount == 0, all subrealms gone */
1893 list_destroy(realm->subrealms);
1894 /* if refcount == 0, all srvconfs gone */
1895 list_destroy(realm->srvconfs);
1896 /* if refcount == 0, all accsrvconfs gone */
1897 list_destroy(realm->accsrvconfs);
1898 freerealm(realm->parent);
1899 free(realm);
1900 }
1901
addrealm(struct list * realmlist,char * value,char ** servers,char ** accservers,char * message,uint8_t accresp)1902 struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message, uint8_t accresp) {
1903 int n;
1904 struct realm *realm;
1905 char *s, *regex = NULL;
1906
1907 if (*value == '/') {
1908 /* regexp, remove optional trailing / if present */
1909 if (value[strlen(value) - 1] == '/')
1910 value[strlen(value) - 1] = '\0';
1911 } else {
1912 /* not a regexp, let us make it one */
1913 if (*value == '*' && !value[1])
1914 regex = stringcopy(".*", 0);
1915 else {
1916 for (n = 0, s = value; *s;)
1917 if (*s++ == '.')
1918 n++;
1919 regex = malloc(strlen(value) + n + 3);
1920 if (regex) {
1921 regex[0] = '@';
1922 for (n = 1, s = value; *s; s++) {
1923 if (*s == '.')
1924 regex[n++] = '\\';
1925 regex[n++] = *s;
1926 }
1927 regex[n++] = '$';
1928 regex[n] = '\0';
1929 }
1930 }
1931 if (!regex) {
1932 debug(DBG_ERR, "malloc failed");
1933 realm = NULL;
1934 goto exit;
1935 }
1936 debug(DBG_DBG, "addrealm: constructed regexp %s from %s", regex, value);
1937 }
1938
1939 realm = malloc(sizeof(struct realm));
1940 if (!realm) {
1941 debug(DBG_ERR, "malloc failed");
1942 goto exit;
1943 }
1944 memset(realm, 0, sizeof(struct realm));
1945
1946 if (pthread_mutex_init(&realm->mutex, NULL) ||
1947 pthread_mutex_init(&realm->refmutex, NULL)) {
1948 debugerrno(errno, DBG_ERR, "mutex init failed");
1949 free(realm);
1950 realm = NULL;
1951 goto exit;
1952 }
1953 newrealmref(realm);
1954
1955 realm->name = stringcopy(value, 0);
1956 if (!realm->name) {
1957 debug(DBG_ERR, "malloc failed");
1958 goto errexit;
1959 }
1960 if (message && strlen(message) > 253) {
1961 debug(DBG_ERR, "ReplyMessage can be at most 253 bytes");
1962 goto errexit;
1963 }
1964 realm->message = message;
1965 realm->accresp = accresp;
1966
1967 if (regcomp(&realm->regex, regex ? regex : value + 1, REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
1968 debug(DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
1969 goto errexit;
1970 }
1971
1972 if (servers && *servers) {
1973 realm->srvconfs = addsrvconfs(value, servers);
1974 if (!realm->srvconfs)
1975 goto errexit;
1976 }
1977
1978 if (accservers && *accservers) {
1979 realm->accsrvconfs = addsrvconfs(value, accservers);
1980 if (!realm->accsrvconfs)
1981 goto errexit;
1982 }
1983
1984 if (!list_push(realmlist, realm)) {
1985 debug(DBG_ERR, "malloc failed");
1986 pthread_mutex_destroy(&realm->mutex);
1987 goto errexit;
1988 }
1989
1990 debug(DBG_DBG, "addrealm: added realm %s", value);
1991 goto exit;
1992
1993 errexit:
1994 while (list_shift(realm->srvconfs));
1995 while (list_shift(realm->accsrvconfs));
1996 freerealm(realm);
1997 realm = NULL;
1998 exit:
1999 free(regex);
2000 if (servers) {
2001 if (realm)
2002 for (n = 0; servers[n]; n++)
2003 newrealmref(realm);
2004 freegconfmstr(servers);
2005 }
2006 if (accservers) {
2007 if (realm)
2008 for (n = 0; accservers[n]; n++)
2009 newrealmref(realm);
2010 freegconfmstr(accservers);
2011 }
2012 return realm;
2013 }
2014
createsubrealmservers(struct realm * realm,struct list * srvconfs)2015 struct list *createsubrealmservers(struct realm *realm, struct list *srvconfs) {
2016 struct list_node *entry;
2017 struct clsrvconf *conf, *srvconf;
2018 struct list *subrealmservers = NULL;
2019 pthread_t clientth;
2020
2021 if (list_first(srvconfs)) {
2022 subrealmservers = list_create();
2023 if (!subrealmservers)
2024 return NULL;
2025 }
2026
2027 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
2028 conf = (struct clsrvconf *)entry->data;
2029 if (!conf->servers && conf->dynamiclookupcommand) {
2030 srvconf = malloc(sizeof(struct clsrvconf));
2031 if (!srvconf) {
2032 debug(DBG_ERR, "malloc failed");
2033 continue;
2034 }
2035 debug(DBG_DBG, "%s: copying config %s", __func__, conf->name);
2036 *srvconf = *conf;
2037 /* Shallow copy -- sharing all the pointers. addserver()
2038 * will take care of servers (which btw has to be NUL) but
2039 * the rest of them are shared with the config found in
2040 * the srvconfs list. */
2041 if (addserver(srvconf)) {
2042 srvconf->servers->dynamiclookuparg = stringcopy(realm->name, 0);
2043 srvconf->servers->state = RSP_SERVER_STATE_STARTUP;
2044 debug(DBG_DBG, "%s: new client writer for %s",
2045 __func__, srvconf->servers->conf->name);
2046 if (pthread_create(&clientth, &pthread_attr, clientwr, (void *)(srvconf->servers))) {
2047 debugerrno(errno, DBG_ERR, "pthread_create failed");
2048 freeserver(srvconf->servers, 1);
2049 srvconf->servers = NULL;
2050 } else
2051 pthread_detach(clientth);
2052
2053 }
2054 conf = srvconf;
2055 }
2056 if (conf->servers) {
2057 if (list_push(subrealmservers, conf))
2058 newrealmref(realm);
2059 else
2060 debug(DBG_ERR, "malloc failed");
2061 }
2062 }
2063 return subrealmservers;
2064 }
2065
adddynamicrealmserver(struct realm * realm,char * id)2066 struct realm *adddynamicrealmserver(struct realm *realm, char *id) {
2067 struct realm *newrealm = NULL;
2068 char *realmname, *s;
2069
2070 /* create dynamic for the realm (string after last @, exit if nothing after @ */
2071 realmname = strrchr(id, '@');
2072 if (!realmname)
2073 return NULL;
2074 realmname++;
2075 if (!*realmname)
2076 return NULL;
2077 for (s = realmname; *s; s++)
2078 if (*s != '.' && *s != '-' && !isalnum((int)*s))
2079 return NULL;
2080
2081 if (!realm->subrealms)
2082 realm->subrealms = list_create();
2083 if (!realm->subrealms)
2084 return NULL;
2085
2086 newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, stringcopy(realm->message, 0), realm->accresp);
2087 if (!newrealm) {
2088 list_destroy(realm->subrealms);
2089 realm->subrealms = NULL;
2090 return NULL;
2091 }
2092
2093 newrealm->parent = newrealmref(realm);
2094 /* add server and accserver to newrealm */
2095 newrealm->srvconfs = createsubrealmservers(newrealm, realm->srvconfs);
2096 newrealm->accsrvconfs = createsubrealmservers(newrealm, realm->accsrvconfs);
2097 return newrealm;
2098 }
2099
dynamicconfig(struct server * server)2100 int dynamicconfig(struct server *server) {
2101 int ok, fd[2], status;
2102 pid_t pid;
2103 struct clsrvconf *conf = server->conf;
2104 struct gconffile *cf = NULL;
2105
2106 /* for now we only learn hostname/address */
2107 debug(DBG_DBG, "dynamicconfig: need dynamic server config for %s", server->dynamiclookuparg);
2108
2109 if (pipe(fd) > 0) {
2110 debugerrno(errno, DBG_ERR, "dynamicconfig: pipe error");
2111 goto errexit;
2112 }
2113 pid = fork();
2114 if (pid < 0) {
2115 debugerrno(errno, DBG_ERR, "dynamicconfig: fork error");
2116 close(fd[0]);
2117 close(fd[1]);
2118 goto errexit;
2119 } else if (pid == 0) {
2120 /* child */
2121 close(fd[0]);
2122 if (fd[1] != STDOUT_FILENO) {
2123 if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
2124 debugx(1, DBG_ERR, "dynamicconfig: dup2 error for command %s", conf->dynamiclookupcommand);
2125 close(fd[1]);
2126 }
2127 if (execlp(conf->dynamiclookupcommand, conf->dynamiclookupcommand, server->dynamiclookuparg, NULL) < 0)
2128 debugx(1, DBG_ERR, "dynamicconfig: exec error for command %s", conf->dynamiclookupcommand);
2129 }
2130
2131 close(fd[1]);
2132 pushgconffile(&cf, fdopen(fd[0], "r"), conf->dynamiclookupcommand);
2133 ok = getgenericconfig(&cf, NULL, "Server", CONF_CBK, confserver_cb,
2134 (void *) conf, NULL);
2135 freegconf(&cf);
2136
2137 if (waitpid(pid, &status, 0) < 0) {
2138 debugerrno(errno, DBG_ERR, "dynamicconfig: wait error");
2139 goto errexit;
2140 }
2141
2142 if (status) {
2143 debug(DBG_INFO, "dynamicconfig: command exited with status %d",
2144 WEXITSTATUS(status));
2145 goto errexit;
2146 }
2147
2148 if (ok)
2149 return 1;
2150
2151 errexit:
2152 debug(DBG_WARN, "dynamicconfig: failed to obtain dynamic server config");
2153 return 0;
2154 }
2155
setttlattr(struct options * opts,char * defaultattr)2156 int setttlattr(struct options *opts, char *defaultattr) {
2157 char *ttlattr = opts->ttlattr ? opts->ttlattr : defaultattr;
2158
2159 if (vattrname2val(ttlattr, opts->ttlattrtype, opts->ttlattrtype + 1) &&
2160 (opts->ttlattrtype[1] != 256 || opts->ttlattrtype[0] < 256))
2161 return 1;
2162 debug(DBG_ERR, "setttlattr: invalid TTLAttribute value %s", ttlattr);
2163 return 0;
2164 }
2165
freeclsrvconf(struct clsrvconf * conf)2166 void freeclsrvconf(struct clsrvconf *conf) {
2167 assert(conf);
2168 debug(DBG_DBG, "%s: freeing %p (%s)", __func__, conf, conf->name ? conf->name : "incomplete");
2169 free(conf->name);
2170 if (conf->hostsrc)
2171 freegconfmstr(conf->hostsrc);
2172 free(conf->portsrc);
2173 free(conf->confsecret);
2174 free(conf->secret);
2175 free(conf->tls);
2176 free(conf->matchcertattr);
2177 if (conf->certcnregex)
2178 regfree(conf->certcnregex);
2179 if (conf->certuriregex)
2180 regfree(conf->certuriregex);
2181 free(conf->confrewritein);
2182 free(conf->confrewriteout);
2183 if (conf->rewriteusername) {
2184 if (conf->rewriteusername->regex)
2185 regfree(conf->rewriteusername->regex);
2186 free(conf->rewriteusername->replacement);
2187 free(conf->rewriteusername);
2188 }
2189 free(conf->dynamiclookupcommand);
2190 conf->rewritein=NULL;
2191 conf->rewriteout=NULL;
2192 if (conf->hostports)
2193 freehostports(conf->hostports);
2194 if (conf->lock) {
2195 pthread_mutex_destroy(conf->lock);
2196 free(conf->lock);
2197 }
2198 /* not touching ssl_ctx, clients and servers */
2199 free(conf);
2200 }
2201
mergeconfstring(char ** dst,char ** src)2202 int mergeconfstring(char **dst, char **src) {
2203 char *t;
2204
2205 if (*src) {
2206 *dst = *src;
2207 *src = NULL;
2208 return 1;
2209 }
2210 if (*dst) {
2211 t = stringcopy(*dst, 0);
2212 if (!t) {
2213 debug(DBG_ERR, "malloc failed");
2214 return 0;
2215 }
2216 *dst = t;
2217 }
2218 return 1;
2219 }
2220
mstringcopy(char ** in)2221 char **mstringcopy(char **in) {
2222 char **out;
2223 int n;
2224
2225 if (!in)
2226 return NULL;
2227
2228 for (n = 0; in[n]; n++);
2229 out = malloc((n + 1) * sizeof(char *));
2230 if (!out)
2231 return NULL;
2232 for (n = 0; in[n]; n++) {
2233 out[n] = stringcopy(in[n], 0);
2234 if (!out[n]) {
2235 freegconfmstr(out);
2236 return NULL;
2237 }
2238 }
2239 out[n] = NULL;
2240 return out;
2241 }
2242
mergeconfmstring(char *** dst,char *** src)2243 int mergeconfmstring(char ***dst, char ***src) {
2244 char **t;
2245
2246 if (*src) {
2247 *dst = *src;
2248 *src = NULL;
2249 return 1;
2250 }
2251 if (*dst) {
2252 t = mstringcopy(*dst);
2253 if (!t) {
2254 debug(DBG_ERR, "malloc failed");
2255 return 0;
2256 }
2257 *dst = t;
2258 }
2259 return 1;
2260 }
2261
2262 /* assumes dst is a shallow copy */
mergesrvconf(struct clsrvconf * dst,struct clsrvconf * src)2263 int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
2264 if (!mergeconfstring(&dst->name, &src->name) ||
2265 !mergeconfmstring(&dst->hostsrc, &src->hostsrc) ||
2266 !mergeconfstring(&dst->portsrc, &src->portsrc) ||
2267 !mergeconfstring(&dst->confsecret, &src->confsecret) ||
2268 !mergeconfstring(&dst->tls, &src->tls) ||
2269 !mergeconfstring(&dst->matchcertattr, &src->matchcertattr) ||
2270 !mergeconfstring(&dst->confrewritein, &src->confrewritein) ||
2271 !mergeconfstring(&dst->confrewriteout, &src->confrewriteout) ||
2272 !mergeconfstring(&dst->confrewriteusername, &src->confrewriteusername) ||
2273 !mergeconfstring(&dst->dynamiclookupcommand, &src->dynamiclookupcommand) ||
2274 !mergeconfstring(&dst->fticks_viscountry, &src->fticks_viscountry) ||
2275 !mergeconfstring(&dst->fticks_visinst, &src->fticks_visinst))
2276 return 0;
2277 if (src->pdef)
2278 dst->pdef = src->pdef;
2279 dst->statusserver = src->statusserver;
2280 dst->certnamecheck = src->certnamecheck;
2281 if (src->retryinterval != 255)
2282 dst->retryinterval = src->retryinterval;
2283 if (src->retrycount != 255)
2284 dst->retrycount = src->retrycount;
2285 return 1;
2286 }
2287
2288 /** Set *AF according to IPV4ONLY and IPV6ONLY:
2289 - If both are set, the function fails.
2290 - If exactly one is set, *AF is set accordingly.
2291 - If none is set, *AF is not affected.
2292 Return 0 on success and !0 on failure.
2293 In the case of an error, *AF is not affected. */
config_hostaf(const char * desc,int ipv4only,int ipv6only,int * af)2294 int config_hostaf(const char *desc, int ipv4only, int ipv6only, int *af) {
2295 assert(af != NULL);
2296 if (ipv4only && ipv6only) {
2297 debug(DBG_ERR, "error in block %s, at most one of IPv4Only and "
2298 "IPv6Only can be enabled", desc);
2299 return -1;
2300 }
2301 if (ipv4only)
2302 *af = AF_INET;
2303 if (ipv6only)
2304 *af = AF_INET6;
2305 return 0;
2306 }
2307
confclient_cb(struct gconffile ** cf,void * arg,char * block,char * opt,char * val)2308 int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
2309 struct clsrvconf *conf, *existing;
2310 char *conftype = NULL, *rewriteinalias = NULL;
2311 long int dupinterval = LONG_MIN, addttl = LONG_MIN;
2312 uint8_t ipv4only = 0, ipv6only = 0;
2313 struct list_node *entry;
2314
2315 debug(DBG_DBG, "confclient_cb called for %s", block);
2316
2317 conf = malloc(sizeof(struct clsrvconf));
2318 if (!conf)
2319 debugx(1, DBG_ERR, "malloc failed");
2320 memset(conf, 0, sizeof(struct clsrvconf));
2321 conf->certnamecheck = 1;
2322
2323 if (!getgenericconfig(
2324 cf, block,
2325 "type", CONF_STR, &conftype,
2326 "host", CONF_MSTR, &conf->hostsrc,
2327 "IPv4Only", CONF_BLN, &ipv4only,
2328 "IPv6Only", CONF_BLN, &ipv6only,
2329 "secret", CONF_STR_NOESC, &conf->confsecret,
2330 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2331 "tls", CONF_STR, &conf->tls,
2332 "matchcertificateattribute", CONF_STR, &conf->matchcertattr,
2333 "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
2334 #endif
2335 "DuplicateInterval", CONF_LINT, &dupinterval,
2336 "addTTL", CONF_LINT, &addttl,
2337 "tcpKeepalive", CONF_BLN, &conf->keepalive,
2338 "rewrite", CONF_STR, &rewriteinalias,
2339 "rewriteIn", CONF_STR, &conf->confrewritein,
2340 "rewriteOut", CONF_STR, &conf->confrewriteout,
2341 "rewriteattribute", CONF_STR, &conf->confrewriteusername,
2342 "fticksVISCOUNTRY", CONF_STR, &conf->fticks_viscountry,
2343 "fticksVISINST", CONF_STR, &conf->fticks_visinst,
2344 NULL
2345 ))
2346 debugx(1, DBG_ERR, "configuration error");
2347
2348 conf->name = stringcopy(val, 0);
2349 if (conf->name && !conf->hostsrc) {
2350 conf->hostsrc = malloc(2 * sizeof(char *));
2351 if (conf->hostsrc) {
2352 conf->hostsrc[0] = stringcopy(val, 0);
2353 conf->hostsrc[1] = NULL;
2354 }
2355 }
2356 if (!conf->name || !conf->hostsrc || !conf->hostsrc[0])
2357 debugx(1, DBG_ERR, "malloc failed");
2358
2359 if (!conftype)
2360 debugx(1, DBG_ERR, "error in block %s, option type missing", block);
2361 conf->type = protoname2int(conftype);
2362 if (conf->type == 255)
2363 debugx(1, DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
2364 free(conftype);
2365 conf->pdef = protodefs[conf->type];
2366
2367 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2368 if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
2369 conf->tlsconf = conf->tls
2370 ? tlsgettls(conf->tls, NULL)
2371 : tlsgettls("defaultClient", "default");
2372 if (!conf->tlsconf)
2373 debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
2374 if (conf->matchcertattr && !addmatchcertattr(conf))
2375 debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2376 }
2377 #endif
2378
2379 conf->hostaf = AF_UNSPEC;
2380 if (config_hostaf("top level", options.ipv4only, options.ipv6only, &conf->hostaf))
2381 debugx(1, DBG_ERR, "config error: ^");
2382 if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf))
2383 debugx(1, DBG_ERR, "error in block %s: ^", block);
2384
2385 if (dupinterval != LONG_MIN) {
2386 if (dupinterval < 0 || dupinterval > 255)
2387 debugx(1, DBG_ERR, "error in block %s, value of option DuplicateInterval is %d, must be 0-255", block, dupinterval);
2388 conf->dupinterval = (uint8_t)dupinterval;
2389 } else
2390 conf->dupinterval = conf->pdef->duplicateintervaldefault;
2391
2392 if (addttl != LONG_MIN) {
2393 if (addttl < 1 || addttl > 255)
2394 debugx(1, DBG_ERR, "error in block %s, value of option addTTL is %d, must be 1-255", block, addttl);
2395 conf->addttl = (uint8_t)addttl;
2396 }
2397
2398 if (!conf->confrewritein)
2399 conf->confrewritein = rewriteinalias;
2400 else
2401 free(rewriteinalias);
2402 conf->rewritein = conf->confrewritein
2403 ? getrewrite(conf->confrewritein, NULL)
2404 : getrewrite("defaultClient", "default");
2405 if (conf->confrewriteout)
2406 conf->rewriteout = getrewrite(conf->confrewriteout, NULL);
2407
2408 if (conf->confrewriteusername) {
2409 conf->rewriteusername = extractmodattr(conf->confrewriteusername);
2410 if (!conf->rewriteusername)
2411 debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block);
2412 }
2413
2414 if (!addhostport(&conf->hostports, conf->hostsrc, conf->pdef->portdefault, 1) ||
2415 !resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype))
2416 debugx(1, DBG_ERR, "%s: resolve failed, exiting", __func__);
2417
2418 if (!conf->confsecret) {
2419 if (!conf->pdef->secretdefault)
2420 debugx(1, DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name);
2421 conf->confsecret = stringcopy(conf->pdef->secretdefault, 0);
2422 if (!conf->confsecret)
2423 debugx(1, DBG_ERR, "malloc failed");
2424 }
2425 conf->secret = (unsigned char *)stringcopy(conf->confsecret, 0);
2426 conf->secret_len = unhex((char *)conf->secret, 1);
2427
2428 if (conf->tlsconf) {
2429 for (entry = list_first(clconfs); entry; entry = list_next(entry)) {
2430 existing = (struct clsrvconf *)entry->data;
2431
2432 if (existing->type == conf->type &&
2433 existing->tlsconf != conf->tlsconf &&
2434 hostportmatches(existing->hostports, conf->hostports, 0)) {
2435
2436 debugx(1, DBG_ERR, "error in block %s, overlapping clients must reference the same tls block", block);
2437 }
2438 }
2439 }
2440
2441 conf->lock = malloc(sizeof(pthread_mutex_t));
2442 if (!conf->lock)
2443 debugx(1, DBG_ERR, "malloc failed");
2444
2445 pthread_mutex_init(conf->lock, NULL);
2446 if (!list_push(clconfs, conf))
2447 debugx(1, DBG_ERR, "malloc failed");
2448 return 1;
2449 }
2450
compileserverconfig(struct clsrvconf * conf,const char * block)2451 int compileserverconfig(struct clsrvconf *conf, const char *block) {
2452 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2453 if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
2454 conf->tlsconf = conf->tls
2455 ? tlsgettls(conf->tls, NULL)
2456 : tlsgettls("defaultServer", "default");
2457 if (!conf->tlsconf) {
2458 debug(DBG_ERR, "error in block %s, no tls context defined", block);
2459 return 0;
2460 }
2461 if (conf->matchcertattr && !addmatchcertattr(conf)) {
2462 debug(DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
2463 return 0;
2464 }
2465 }
2466 #endif
2467
2468 if (!conf->portsrc) {
2469 conf->portsrc = stringcopy(conf->pdef->portdefault, 0);
2470 if (!conf->portsrc) {
2471 debug(DBG_ERR, "malloc failed");
2472 return 0;
2473 }
2474 }
2475
2476 if (conf->retryinterval == 255)
2477 conf->retryinterval = conf->pdef->retryintervaldefault;
2478 if (conf->retrycount == 255)
2479 conf->retrycount = conf->pdef->retrycountdefault;
2480
2481 conf->rewritein = conf->confrewritein
2482 ? getrewrite(conf->confrewritein, NULL)
2483 : getrewrite("defaultServer", "default");
2484 if (conf->confrewriteout)
2485 conf->rewriteout = getrewrite(conf->confrewriteout, NULL);
2486
2487 if (!addhostport(&conf->hostports, conf->hostsrc, conf->portsrc, 0)) {
2488 debug(DBG_ERR, "error in block %s, failed to parse %s", block, *conf->hostsrc);
2489 return 0;
2490 }
2491
2492 if (!conf->dynamiclookupcommand &&
2493 !resolvehostports(conf->hostports, conf->hostaf,
2494 conf->pdef->socktype)) {
2495 debug(DBG_ERR, "%s: resolve failed", __func__);
2496 return 0;
2497 }
2498 return 1;
2499 }
2500
confserver_cb(struct gconffile ** cf,void * arg,char * block,char * opt,char * val)2501 int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
2502 struct clsrvconf *conf, *resconf;
2503 char *conftype = NULL, *rewriteinalias = NULL, *statusserver = NULL;
2504 long int retryinterval = LONG_MIN, retrycount = LONG_MIN, addttl = LONG_MIN;
2505 uint8_t ipv4only = 0, ipv6only = 0, confmerged = 0;
2506
2507 debug(DBG_DBG, "confserver_cb called for %s", block);
2508
2509 conf = malloc(sizeof(struct clsrvconf));
2510 if (!conf) {
2511 debug(DBG_ERR, "malloc failed");
2512 return 0;
2513 }
2514 memset(conf, 0, sizeof(struct clsrvconf));
2515 conf->loopprevention = UCHAR_MAX; /* Uninitialized. */
2516 resconf = (struct clsrvconf *)arg;
2517 if (resconf) {
2518 conf->statusserver = resconf->statusserver;
2519 conf->certnamecheck = resconf->certnamecheck;
2520 } else {
2521 conf->certnamecheck = 1;
2522 }
2523
2524 if (!getgenericconfig(cf, block,
2525 "type", CONF_STR, &conftype,
2526 "host", CONF_MSTR, &conf->hostsrc,
2527 "IPv4Only", CONF_BLN, &ipv4only,
2528 "IPv6Only", CONF_BLN, &ipv6only,
2529 "port", CONF_STR, &conf->portsrc,
2530 "secret", CONF_STR_NOESC, &conf->confsecret,
2531 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2532 "tls", CONF_STR, &conf->tls,
2533 "MatchCertificateAttribute", CONF_STR, &conf->matchcertattr,
2534 "CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
2535 #endif
2536 "addTTL", CONF_LINT, &addttl,
2537 "tcpKeepalive", CONF_BLN, &conf->keepalive,
2538 "rewrite", CONF_STR, &rewriteinalias,
2539 "rewriteIn", CONF_STR, &conf->confrewritein,
2540 "rewriteOut", CONF_STR, &conf->confrewriteout,
2541 "StatusServer", CONF_STR, &statusserver,
2542 "RetryInterval", CONF_LINT, &retryinterval,
2543 "RetryCount", CONF_LINT, &retrycount,
2544 "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand,
2545 "LoopPrevention", CONF_BLN, &conf->loopprevention,
2546 NULL
2547 )) {
2548 debug(DBG_ERR, "configuration error");
2549 goto errexit;
2550 }
2551
2552 conf->name = stringcopy(val, 0);
2553 if (conf->name && !conf->hostsrc) {
2554 conf->hostsrc = malloc(2 * sizeof(char *));
2555 if (conf->hostsrc) {
2556 conf->hostsrc[0] = stringcopy(val, 0);
2557 conf->hostsrc[1] = NULL;
2558 }
2559 }
2560 if (!conf->name || !conf->hostsrc || !conf->hostsrc[0]) {
2561 debug(DBG_ERR, "malloc failed");
2562 goto errexit;
2563 }
2564
2565 if (!conftype) {
2566 debug(DBG_ERR, "error in block %s, option type missing", block);
2567 goto errexit;
2568 }
2569 conf->type = protoname2int(conftype);
2570 if (conf->type == 255) {
2571 debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
2572 goto errexit;
2573 }
2574 free(conftype);
2575 conftype = NULL;
2576
2577 conf->hostaf = AF_UNSPEC;
2578 if (config_hostaf("top level", options.ipv4only, options.ipv6only, &conf->hostaf))
2579 debugx(1, DBG_ERR, "config error: ^");
2580 if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf))
2581 goto errexit;
2582
2583 conf->pdef = protodefs[conf->type];
2584
2585 if (!conf->confrewritein)
2586 conf->confrewritein = rewriteinalias;
2587 else
2588 free(rewriteinalias);
2589 rewriteinalias = NULL;
2590
2591 if (retryinterval != LONG_MIN) {
2592 if (retryinterval < 1 || retryinterval > conf->pdef->retryintervalmax) {
2593 debug(DBG_ERR, "error in block %s, value of option RetryInterval is %d, must be 1-%d", block, retryinterval, conf->pdef->retryintervalmax);
2594 goto errexit;
2595 }
2596 conf->retryinterval = (uint8_t)retryinterval;
2597 } else
2598 conf->retryinterval = 255;
2599
2600 if (retrycount != LONG_MIN) {
2601 if (retrycount < 0 || retrycount > conf->pdef->retrycountmax) {
2602 debug(DBG_ERR, "error in block %s, value of option RetryCount is %d, must be 0-%d", block, retrycount, conf->pdef->retrycountmax);
2603 goto errexit;
2604 }
2605 conf->retrycount = (uint8_t)retrycount;
2606 } else
2607 conf->retrycount = 255;
2608
2609 if (addttl != LONG_MIN) {
2610 if (addttl < 1 || addttl > 255) {
2611 debug(DBG_ERR, "error in block %s, value of option addTTL is %d, must be 1-255", block, addttl);
2612 goto errexit;
2613 }
2614 conf->addttl = (uint8_t)addttl;
2615 }
2616
2617 if (statusserver) {
2618 if (strcasecmp(statusserver, "Off") == 0)
2619 conf->statusserver = RSP_STATSRV_OFF;
2620 else if (strcasecmp(statusserver, "On") == 0)
2621 conf->statusserver = RSP_STATSRV_ON;
2622 else if (strcasecmp(statusserver, "Minimal") == 0)
2623 conf->statusserver = RSP_STATSRV_MINIMAL;
2624 else if (strcasecmp(statusserver, "Auto") == 0)
2625 conf->statusserver = RSP_STATSRV_AUTO;
2626 else
2627 debugx(1, DBG_ERR, "config error in blocck %s: invalid StatusServer value: %s", block, statusserver);
2628 }
2629
2630 if (resconf) {
2631 if (!mergesrvconf(resconf, conf))
2632 goto errexit;
2633 free(conf);
2634 conf = resconf;
2635 confmerged = 1;
2636 if (conf->dynamiclookupcommand) {
2637 free(conf->dynamiclookupcommand);
2638 conf->dynamiclookupcommand = NULL;
2639 }
2640 }
2641
2642 if (resconf || !conf->dynamiclookupcommand) {
2643 if (!compileserverconfig(conf, block))
2644 goto errexit;
2645 }
2646
2647 if (!conf->confsecret) {
2648 if (!conf->pdef->secretdefault) {
2649 debug(DBG_ERR, "error in block %s, secret must be specified for transport type %s", block, conf->pdef->name);
2650 goto errexit;
2651 }
2652 conf->confsecret = stringcopy(conf->pdef->secretdefault, 0);
2653 if (!conf->confsecret) {
2654 debug(DBG_ERR, "malloc failed");
2655 goto errexit;
2656 }
2657 }
2658 conf->secret = (unsigned char *)stringcopy(conf->confsecret,0);
2659 conf->secret_len = unhex((char *)conf->secret,1);
2660
2661 if (resconf)
2662 return 1;
2663
2664 if (!list_push(srvconfs, conf)) {
2665 debug(DBG_ERR, "malloc failed");
2666 goto errexit;
2667 }
2668 return 1;
2669
2670 errexit:
2671 free(conftype);
2672 free(rewriteinalias);
2673 /* if conf was merged into resconf, don't free it */
2674 if (!confmerged)
2675 freeclsrvconf(conf);
2676 return 0;
2677 }
2678
confrewrite_cb(struct gconffile ** cf,void * arg,char * block,char * opt,char * val)2679 int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
2680 uint8_t whitelist_mode = 0;
2681 char **rmattrs = NULL, **rmvattrs = NULL;
2682 char **wlattrs = NULL, **wlvattrs = NULL;
2683 char **addattrs = NULL, **addvattrs = NULL;
2684 char **modattrs = NULL, **modvattrs = NULL;
2685 char **supattrs = NULL, **supvattrs = NULL;
2686
2687 debug(DBG_DBG, "confrewrite_cb called for %s", block);
2688
2689 if (!getgenericconfig(cf, block,
2690 "whitelistMode", CONF_BLN, &whitelist_mode,
2691 "removeAttribute", CONF_MSTR, &rmattrs,
2692 "removeVendorAttribute", CONF_MSTR, &rmvattrs,
2693 "whitelistAttribute", CONF_MSTR, &wlattrs,
2694 "whitelistVendorAttribute", CONF_MSTR, &wlvattrs,
2695 "addAttribute", CONF_MSTR_NOESC, &addattrs,
2696 "addVendorAttribute", CONF_MSTR_NOESC, &addvattrs,
2697 "modifyAttribute", CONF_MSTR, &modattrs,
2698 "modifyVendorAttribute", CONF_MSTR, &modvattrs,
2699 "supplementAttribute", CONF_MSTR_NOESC, &supattrs,
2700 "supplementVendorAttribute", CONF_MSTR_NOESC, &supvattrs,
2701 NULL))
2702 debugx(1, DBG_ERR, "configuration error");
2703 addrewrite(val, whitelist_mode, whitelist_mode? wlattrs : rmattrs, whitelist_mode? wlvattrs : rmvattrs,
2704 addattrs, addvattrs, modattrs, modvattrs, supattrs, supvattrs);
2705
2706 freegconfmstr(whitelist_mode? rmattrs : wlattrs);
2707 freegconfmstr(whitelist_mode? rmvattrs : wlvattrs);
2708
2709 return 1;
2710 }
2711
confrealm_cb(struct gconffile ** cf,void * arg,char * block,char * opt,char * val)2712 int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
2713 char **servers = NULL, **accservers = NULL, *msg = NULL;
2714 uint8_t accresp = 0;
2715
2716 debug(DBG_DBG, "confrealm_cb called for %s", block);
2717
2718 if (!getgenericconfig(cf, block,
2719 "server", CONF_MSTR, &servers,
2720 "accountingServer", CONF_MSTR, &accservers,
2721 "ReplyMessage", CONF_STR, &msg,
2722 "AccountingResponse", CONF_BLN, &accresp,
2723 NULL
2724 ))
2725 debugx(1, DBG_ERR, "configuration error");
2726
2727 addrealm(realms, val, servers, accservers, msg, accresp);
2728 return 1;
2729 }
2730
setprotoopts(uint8_t type,char ** listenargs,char * sourcearg)2731 int setprotoopts(uint8_t type, char **listenargs, char *sourcearg) {
2732 struct commonprotoopts *protoopts;
2733
2734 protoopts = malloc(sizeof(struct commonprotoopts));
2735 if (!protoopts)
2736 return 0;
2737 memset(protoopts, 0, sizeof(struct commonprotoopts));
2738 protoopts->listenargs = listenargs;
2739 protoopts->sourcearg = sourcearg;
2740 protodefs[type]->setprotoopts(protoopts);
2741 return 1;
2742 }
2743
getmainconfig(const char * configfile)2744 void getmainconfig(const char *configfile) {
2745 long int addttl = LONG_MIN, loglevel = LONG_MIN;
2746 struct gconffile *cfs;
2747 char **listenargs[RAD_PROTOCOUNT];
2748 char *sourcearg[RAD_PROTOCOUNT];
2749 char *log_mac_str = NULL;
2750 char *log_key_str = NULL;
2751 uint8_t *fticks_reporting_str = NULL;
2752 uint8_t *fticks_mac_str = NULL;
2753 uint8_t *fticks_key_str = NULL;
2754 int i;
2755
2756 cfs = openconfigfile(configfile);
2757 memset(&options, 0, sizeof(options));
2758 memset(&listenargs, 0, sizeof(listenargs));
2759 memset(&sourcearg, 0, sizeof(sourcearg));
2760 options.logfullusername = 1;
2761
2762 clconfs = list_create();
2763 if (!clconfs)
2764 debugx(1, DBG_ERR, "malloc failed");
2765
2766 srvconfs = list_create();
2767 if (!srvconfs)
2768 debugx(1, DBG_ERR, "malloc failed");
2769
2770 realms = list_create();
2771 if (!realms)
2772 debugx(1, DBG_ERR, "malloc failed");
2773
2774 if (!getgenericconfig(
2775 &cfs, NULL,
2776 #ifdef RADPROT_UDP
2777 "ListenUDP", CONF_MSTR, &listenargs[RAD_UDP],
2778 "SourceUDP", CONF_STR, &sourcearg[RAD_UDP],
2779 #endif
2780 #ifdef RADPROT_TCP
2781 "ListenTCP", CONF_MSTR, &listenargs[RAD_TCP],
2782 "SourceTCP", CONF_STR, &sourcearg[RAD_TCP],
2783 #endif
2784 #ifdef RADPROT_TLS
2785 "ListenTLS", CONF_MSTR, &listenargs[RAD_TLS],
2786 "SourceTLS", CONF_STR, &sourcearg[RAD_TLS],
2787 #endif
2788 #ifdef RADPROT_DTLS
2789 "ListenDTLS", CONF_MSTR, &listenargs[RAD_DTLS],
2790 "SourceDTLS", CONF_STR, &sourcearg[RAD_DTLS],
2791 #endif
2792 "PidFile", CONF_STR, &options.pidfile,
2793 "TTLAttribute", CONF_STR, &options.ttlattr,
2794 "addTTL", CONF_LINT, &addttl,
2795 "LogLevel", CONF_LINT, &loglevel,
2796 "LogDestination", CONF_STR, &options.logdestination,
2797 "LogThreadId", CONF_BLN, &options.logtid,
2798 "LogMAC", CONF_STR, &log_mac_str,
2799 "LogKey", CONF_STR, &log_key_str,
2800 "LogFullUsername", CONF_BLN, &options.logfullusername,
2801 "LoopPrevention", CONF_BLN, &options.loopprevention,
2802 "Client", CONF_CBK, confclient_cb, NULL,
2803 "Server", CONF_CBK, confserver_cb, NULL,
2804 "Realm", CONF_CBK, confrealm_cb, NULL,
2805 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2806 "TLS", CONF_CBK, conftls_cb, NULL,
2807 #endif
2808 "Rewrite", CONF_CBK, confrewrite_cb, NULL,
2809 "FTicksReporting", CONF_STR, &fticks_reporting_str,
2810 "FTicksMAC", CONF_STR, &fticks_mac_str,
2811 "FTicksKey", CONF_STR, &fticks_key_str,
2812 "FTicksSyslogFacility", CONF_STR, &options.ftickssyslogfacility,
2813 "FTicksPrefix", CONF_STR, &options.fticksprefix,
2814 "IPv4Only", CONF_BLN, &options.ipv4only,
2815 "IPv6Only", CONF_BLN, &options.ipv6only,
2816 NULL
2817 ))
2818 debugx(1, DBG_ERR, "configuration error");
2819
2820 if (loglevel != LONG_MIN) {
2821 if (loglevel < 1 || loglevel > 5)
2822 debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %d, must be 1, 2, 3, 4 or 5", configfile, loglevel);
2823 options.loglevel = (uint8_t)loglevel;
2824 }
2825 if (log_mac_str != NULL) {
2826 if (strcasecmp(log_mac_str, "Static") == 0)
2827 options.log_mac = RSP_MAC_STATIC;
2828 else if (strcasecmp(log_mac_str, "Original") == 0)
2829 options.log_mac = RSP_MAC_ORIGINAL;
2830 else if (strcasecmp(log_mac_str, "VendorHashed") == 0)
2831 options.log_mac = RSP_MAC_VENDOR_HASHED;
2832 else if (strcasecmp(log_mac_str, "VendorKeyHashed") == 0)
2833 options.log_mac = RSP_MAC_VENDOR_KEY_HASHED;
2834 else if (strcasecmp(log_mac_str, "FullyHashed") == 0)
2835 options.log_mac = RSP_MAC_FULLY_HASHED;
2836 else if (strcasecmp(log_mac_str, "FullyKeyHashed") == 0)
2837 options.log_mac = RSP_MAC_FULLY_KEY_HASHED;
2838 else {
2839 debugx(1, DBG_ERR, "config error: invalid LogMAC value: %s", log_mac_str);
2840 }
2841 if (log_key_str != NULL) {
2842 options.log_key = (uint8_t *)log_key_str;
2843 } else if ((options.log_mac == RSP_MAC_VENDOR_KEY_HASHED
2844 || options.log_mac == RSP_MAC_FULLY_KEY_HASHED)) {
2845 debugx(1, DBG_ERR, "config error: LogMAC %s requires LogKey to be set.", log_mac_str);
2846 }
2847 free(log_mac_str);
2848 } else {
2849 options.log_mac = RSP_MAC_ORIGINAL;
2850 }
2851
2852 if (addttl != LONG_MIN) {
2853 if (addttl < 1 || addttl > 255)
2854 debugx(1, DBG_ERR, "error in %s, value of option addTTL is %d, must be 1-255", configfile, addttl);
2855 options.addttl = (uint8_t)addttl;
2856 }
2857 if (!setttlattr(&options, DEFAULT_TTL_ATTR))
2858 debugx(1, DBG_ERR, "Failed to set TTLAttribute, exiting");
2859
2860 if (!options.fticksprefix)
2861 options.fticksprefix = DEFAULT_FTICKS_PREFIX;
2862 fticks_configure(&options, &fticks_reporting_str, &fticks_mac_str,
2863 &fticks_key_str);
2864
2865 for (i = 0; i < RAD_PROTOCOUNT; i++)
2866 if (listenargs[i] || sourcearg[i])
2867 setprotoopts(i, listenargs[i], sourcearg[i]);
2868 }
2869
getargs(int argc,char ** argv,uint8_t * foreground,uint8_t * pretend,uint8_t * loglevel,char ** configfile,char ** pidfile)2870 void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile, char **pidfile) {
2871 int c;
2872
2873 while ((c = getopt(argc, argv, "c:d:i:fpv")) != -1) {
2874 switch (c) {
2875 case 'c':
2876 *configfile = optarg;
2877 break;
2878 case 'd':
2879 if (strlen(optarg) != 1 || *optarg < '1' || *optarg > '5')
2880 debugx(1, DBG_ERR, "Debug level must be 1, 2, 3, 4 or 5, not %s", optarg);
2881 *loglevel = *optarg - '0';
2882 break;
2883 case 'f':
2884 *foreground = 1;
2885 break;
2886 case 'i':
2887 *pidfile = optarg;
2888 break;
2889 case 'p':
2890 *pretend = 1;
2891 break;
2892 case 'v':
2893 debug(DBG_ERR, "radsecproxy revision %s", PACKAGE_VERSION);
2894 debug(DBG_ERR, "This binary was built with support for the following transports:");
2895 #ifdef RADPROT_UDP
2896 debug(DBG_ERR, " UDP");
2897 #endif
2898 #ifdef RADPROT_TCP
2899 debug(DBG_ERR, " TCP");
2900 #endif
2901 #ifdef RADPROT_TLS
2902 debug(DBG_ERR, " TLS");
2903 #endif
2904 #ifdef RADPROT_DTLS
2905 debug(DBG_ERR, " DTLS");
2906 #endif
2907 exit(0);
2908 default:
2909 goto usage;
2910 }
2911 }
2912 if (!(argc - optind))
2913 return;
2914
2915 usage:
2916 debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -i pidfile ] [ -p ] [ -v ]", argv[0]);
2917 }
2918
2919 #ifdef SYS_SOLARIS9
daemon(int a,int b)2920 int daemon(int a, int b) {
2921 int i;
2922
2923 if (fork())
2924 exit(0);
2925
2926 setsid();
2927
2928 for (i = 0; i < 3; i++) {
2929 close(i);
2930 open("/dev/null", O_RDWR);
2931 }
2932 return 1;
2933 }
2934 #endif
2935
sighandler(void * arg)2936 void *sighandler(void *arg) {
2937 sigset_t sigset;
2938 int sig;
2939
2940 for(;;) {
2941 sigemptyset(&sigset);
2942 sigaddset(&sigset, SIGHUP);
2943 sigaddset(&sigset, SIGPIPE);
2944 sigwait(&sigset, &sig);
2945 switch (sig) {
2946 case 0:
2947 /* completely ignoring this */
2948 break;
2949 case SIGHUP:
2950 debug(DBG_INFO, "sighandler: got SIGHUP");
2951 debug_reopen_log();
2952 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
2953 tlsreloadcrls();
2954 #endif
2955 break;
2956 case SIGPIPE:
2957 debug(DBG_WARN, "sighandler: got SIGPIPE, TLS write error?");
2958 break;
2959 default:
2960 debug(DBG_WARN, "sighandler: ignoring signal %d", sig);
2961 }
2962 }
2963 }
2964
createpidfile(const char * pidfile)2965 int createpidfile(const char *pidfile) {
2966 int r = 0;
2967 FILE *f = fopen(pidfile, "w");
2968 if (f)
2969 r = fprintf(f, "%ld\n", (long) getpid());
2970 return f && !fclose(f) && r >= 0;
2971 }
2972
radsecproxy_main(int argc,char ** argv)2973 int radsecproxy_main(int argc, char **argv) {
2974 pthread_t sigth;
2975 sigset_t sigset;
2976 struct list_node *entry;
2977 uint8_t foreground = 0, pretend = 0, loglevel = 0;
2978 char *configfile = NULL, *pidfile = NULL;
2979 struct clsrvconf *srvconf;
2980 int i;
2981
2982 debug_init("radsecproxy");
2983 debug_set_level(DEBUG_LEVEL);
2984
2985 if (pthread_attr_init(&pthread_attr))
2986 debugx(1, DBG_ERR, "pthread_attr_init failed");
2987 if (pthread_attr_setstacksize(&pthread_attr, PTHREAD_STACK_SIZE))
2988 debugx(1, DBG_ERR, "pthread_attr_setstacksize failed");
2989 #if defined(HAVE_MALLOPT)
2990 if (mallopt(M_TRIM_THRESHOLD, 4 * 1024) != 1)
2991 debugx(1, DBG_ERR, "mallopt failed");
2992 #endif
2993
2994 for (i = 0; i < RAD_PROTOCOUNT; i++)
2995 protodefs[i] = protoinits[i](i);
2996
2997 /* needed even if no TLS/DTLS transport */
2998 randinit();
2999
3000 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
3001 sslinit();
3002 #endif
3003
3004 getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile, &pidfile);
3005 if (loglevel)
3006 debug_set_level(loglevel);
3007 getmainconfig(configfile ? configfile : CONFIG_MAIN);
3008 if (loglevel)
3009 options.loglevel = loglevel;
3010 else if (options.loglevel)
3011 debug_set_level(options.loglevel);
3012 if (!foreground) {
3013 debug_set_destination(options.logdestination
3014 ? options.logdestination
3015 : "x-syslog:///", LOG_TYPE_DEBUG);
3016 if (options.ftickssyslogfacility) {
3017 debug_set_destination(options.ftickssyslogfacility,
3018 LOG_TYPE_FTICKS);
3019 free(options.ftickssyslogfacility);
3020 }
3021 }
3022 free(options.logdestination);
3023 if (options.logtid)
3024 debug_tid_on();
3025
3026 if (!list_first(clconfs))
3027 debugx(1, DBG_ERR, "No clients configured, nothing to do, exiting");
3028 if (!list_first(realms))
3029 debugx(1, DBG_ERR, "No realms configured, nothing to do, exiting");
3030
3031 if (pretend)
3032 debugx(0, DBG_ERR, "All OK so far; exiting since only pretending");
3033
3034 if (!foreground && (daemon(0, 0) < 0))
3035 debugx(1, DBG_ERR, "daemon() failed: %s", strerror(errno));
3036
3037 debug_timestamp_on();
3038 debug(DBG_INFO, "radsecproxy %s starting", PACKAGE_VERSION);
3039 if (!pidfile)
3040 pidfile = options.pidfile;
3041 if (pidfile && !createpidfile(pidfile))
3042 debugx(1, DBG_ERR, "failed to create pidfile %s: %s", pidfile, strerror(errno));
3043
3044 sigemptyset(&sigset);
3045 /* exit on all but SIGHUP|SIGPIPE, ignore more? */
3046 sigaddset(&sigset, SIGHUP);
3047 sigaddset(&sigset, SIGPIPE);
3048 pthread_sigmask(SIG_BLOCK, &sigset, NULL);
3049 if (pthread_create(&sigth, &pthread_attr, sighandler, NULL))
3050 debugx(1, DBG_ERR, "pthread_create failed: sighandler");
3051
3052 for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
3053 srvconf = (struct clsrvconf *)entry->data;
3054 if (srvconf->dynamiclookupcommand)
3055 continue;
3056 if (!addserver(srvconf))
3057 debugx(1, DBG_ERR, "failed to add server");
3058 if (pthread_create(&srvconf->servers->clientth, &pthread_attr, clientwr,
3059 (void *)(srvconf->servers)))
3060 debugx(1, DBG_ERR, "pthread_create failed");
3061 }
3062
3063 for (i = 0; i < RAD_PROTOCOUNT; i++) {
3064 if (!protodefs[i])
3065 continue;
3066 if (protodefs[i]->initextra)
3067 protodefs[i]->initextra();
3068 if (find_clconf_type(i, NULL))
3069 createlisteners(i);
3070 }
3071
3072 /* just hang around doing nothing, anything to do here? */
3073 for (;;)
3074 sleep(1000);
3075 }
3076
3077 /* Local Variables: */
3078 /* c-file-style: "stroustrup" */
3079 /* End: */
3080