find_client: min prefix of 0 needs to work
[freeradius.git] / src / main / client.c
1 /*
2  * client.c     Read clients into memory.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  */
24
25 RCSID("$Id$")
26
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/rad_assert.h>
29
30 #include <sys/stat.h>
31
32 #include <ctype.h>
33 #include <fcntl.h>
34
35 #ifdef WITH_DYNAMIC_CLIENTS
36 #ifdef HAVE_DIRENT_H
37 #include <dirent.h>
38 #endif
39 #endif
40
41 struct radclient_list {
42         /*
43          *      FIXME: One set of trees for IPv4, and another for IPv6?
44          */
45         rbtree_t        *trees[129]; /* for 0..128, inclusive. */
46         uint32_t        min_prefix;
47 };
48
49
50 #ifdef WITH_STATS
51 static rbtree_t         *tree_num = NULL;     /* client numbers 0..N */
52 static int              tree_num_max = 0;
53 #endif
54 static RADCLIENT_LIST   *root_clients = NULL;
55
56 #ifdef WITH_DYNAMIC_CLIENTS
57 static fr_fifo_t        *deleted_clients = NULL;
58 #endif
59
60 /*
61  *      Callback for freeing a client.
62  */
63 void client_free(RADCLIENT *client)
64 {
65         if (!client) return;
66
67 #ifdef WITH_DYNAMIC_CLIENTS
68         if (client->dynamic == 2) {
69                 time_t now;
70
71                 if (!deleted_clients) {
72                         deleted_clients = fr_fifo_create(1024,
73                                                          (void *) client_free);
74                         if (!deleted_clients) return; /* MEMLEAK */
75                 }
76
77                 /*
78                  *      Mark it as in the fifo, and remember when we
79                  *      pushed it.
80                  */
81                 client->dynamic = 3;
82                 client->created = now = time(NULL); /* re-set it */
83                 fr_fifo_push(deleted_clients, client);
84
85                 /*
86                  *      Peek at the head of the fifo.  If it might
87                  *      still be in use, return.  Otherwise, pop it
88                  *      from the queue and delete it.
89                  */
90                 client = fr_fifo_peek(deleted_clients);
91                 if ((client->created + 120) >= now) return;
92
93                 client = fr_fifo_pop(deleted_clients);
94                 rad_assert(client != NULL);
95         }
96 #endif
97
98         talloc_free(client);
99 }
100
101 /*
102  *      Callback for comparing two clients.
103  */
104 static int client_ipaddr_cmp(void const *one, void const *two)
105 {
106         RADCLIENT const *a = one;
107         RADCLIENT const *b = two;
108 #ifndef WITH_TCP
109
110         return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
111 #else
112         int rcode;
113
114         rcode = fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
115         if (rcode != 0) return rcode;
116
117         /*
118          *      Wildcard match
119          */
120         if ((a->proto == IPPROTO_IP) ||
121             (b->proto == IPPROTO_IP)) return 0;
122
123         return (a->proto - b->proto);
124 #endif
125 }
126
127 #ifdef WITH_STATS
128 static int client_num_cmp(void const *one, void const *two)
129 {
130         RADCLIENT const *a = one;
131         RADCLIENT const *b = two;
132
133         return (a->number - b->number);
134 }
135 #endif
136
137 /*
138  *      Free a RADCLIENT list.
139  */
140 void clients_free(RADCLIENT_LIST *clients)
141 {
142         int i;
143
144         if (!clients) clients = root_clients;
145         if (!clients) return;   /* Clients may not have been initialised yet */
146
147         for (i = 0; i <= 128; i++) {
148                 if (clients->trees[i]) rbtree_free(clients->trees[i]);
149                 clients->trees[i] = NULL;
150         }
151
152         if (clients == root_clients) {
153 #ifdef WITH_STATS
154                 if (tree_num) rbtree_free(tree_num);
155                 tree_num = NULL;
156                 tree_num_max = 0;
157 #endif
158                 root_clients = NULL;
159         }
160
161 #ifdef WITH_DYNAMIC_CLIENTS
162         /*
163          *      FIXME: No fr_fifo_delete()
164          */
165 #endif
166
167         talloc_free(clients);
168 }
169
170 /*
171  *      Return a new, initialized, set of clients.
172  */
173 RADCLIENT_LIST *clients_init(CONF_SECTION *cs)
174 {
175         RADCLIENT_LIST *clients = talloc_zero(cs, RADCLIENT_LIST);
176
177         if (!clients) return NULL;
178
179         clients->min_prefix = 128;
180
181         return clients;
182 }
183
184 /*
185  *      Add a client to the tree.
186  */
187 int client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
188 {
189         RADCLIENT *old;
190         char buffer[INET6_ADDRSTRLEN + 3];
191
192         if (!client) {
193                 return 0;
194         }
195
196         /*
197          *      Hack to fixup wildcard clients
198          */
199         if (is_wildcard(&client->ipaddr)) client->ipaddr.prefix = 0;
200
201         fr_ntop(buffer, sizeof(buffer), &client->ipaddr);
202         DEBUG3("Adding client %s (%s) to prefix tree %i", buffer, client->longname, client->ipaddr.prefix);
203
204         /*
205          *      If "clients" is NULL, it means add to the global list.
206          */
207         if (!clients) {
208                 /*
209                  *      Initialize it, if not done already.
210                  */
211                 if (!root_clients) {
212                         root_clients = clients_init(NULL);
213                         if (!root_clients) return 0;
214                 }
215                 clients = root_clients;
216         }
217
218         /*
219          *      Create a tree for it.
220          */
221         if (!clients->trees[client->ipaddr.prefix]) {
222                 clients->trees[client->ipaddr.prefix] = rbtree_create(clients, client_ipaddr_cmp, NULL, 0);
223                 if (!clients->trees[client->ipaddr.prefix]) {
224                         return 0;
225                 }
226         }
227
228 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
229
230         /*
231          *      Cannot insert the same client twice.
232          */
233         old = rbtree_finddata(clients->trees[client->ipaddr.prefix], client);
234         if (old) {
235                 /*
236                  *      If it's a complete duplicate, then free the new
237                  *      one, and return "OK".
238                  */
239                 if ((fr_ipaddr_cmp(&old->ipaddr, &client->ipaddr) == 0) &&
240                     (old->ipaddr.prefix == client->ipaddr.prefix) &&
241                     namecmp(longname) && namecmp(secret) &&
242                     namecmp(shortname) && namecmp(nas_type) &&
243                     namecmp(login) && namecmp(password) && namecmp(server) &&
244 #ifdef WITH_DYNAMIC_CLIENTS
245                     (old->lifetime == client->lifetime) &&
246                     namecmp(client_server) &&
247 #endif
248 #ifdef WITH_COA
249                     namecmp(coa_name) &&
250                     (old->coa_server == client->coa_server) &&
251                     (old->coa_pool == client->coa_pool) &&
252 #endif
253                     (old->message_authenticator == client->message_authenticator)) {
254                         WARN("Ignoring duplicate client %s", client->longname);
255                         client_free(client);
256                         return 1;
257                 }
258
259                 ERROR("Failed to add duplicate client %s",
260                        client->shortname);
261                 return 0;
262         }
263 #undef namecmp
264
265         /*
266          *      Other error adding client: likely is fatal.
267          */
268         if (!rbtree_insert(clients->trees[client->ipaddr.prefix], client)) {
269                 return 0;
270         }
271
272 #ifdef WITH_STATS
273         if (!tree_num) {
274                 tree_num = rbtree_create(clients, client_num_cmp, NULL, 0);
275         }
276
277 #ifdef WITH_DYNAMIC_CLIENTS
278         /*
279          *      More catching of clients added by rlm_sql.
280          *
281          *      The sql modules sets the dynamic flag BEFORE calling
282          *      us.  The client_from_request() function sets it AFTER
283          *      calling us.
284          */
285         if (client->dynamic && (client->lifetime == 0)) {
286                 RADCLIENT *network;
287
288                 /*
289                  *      If there IS an enclosing network,
290                  *      inherit the lifetime from it.
291                  */
292                 network = client_find(clients, &client->ipaddr, client->proto);
293                 if (network) {
294                         client->lifetime = network->lifetime;
295                 }
296         }
297 #endif
298
299         client->number = tree_num_max;
300         tree_num_max++;
301         if (tree_num) rbtree_insert(tree_num, client);
302 #endif
303
304         if (client->ipaddr.prefix < clients->min_prefix) {
305                 clients->min_prefix = client->ipaddr.prefix;
306         }
307
308         (void) talloc_steal(clients, client); /* reparent it */
309
310         return 1;
311 }
312
313
314 #ifdef WITH_DYNAMIC_CLIENTS
315 void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client)
316 {
317         if (!client) return;
318
319         if (!clients) clients = root_clients;
320
321         if (!client->dynamic) return;
322
323         rad_assert(client->ipaddr.prefix <= 128);
324
325         client->dynamic = 2;    /* signal to client_free */
326
327 #ifdef WITH_STATS
328         rbtree_deletebydata(tree_num, client);
329 #endif
330         rbtree_deletebydata(clients->trees[client->ipaddr.prefix], client);
331 }
332 #endif
333
334 #ifdef WITH_STATS
335 /*
336  *      Find a client in the RADCLIENTS list by number.
337  *      This is a support function for the statistics code.
338  */
339 RADCLIENT *client_findbynumber(RADCLIENT_LIST const *clients, int number)
340 {
341         if (!clients) clients = root_clients;
342
343         if (!clients) return NULL;
344
345         if (number >= tree_num_max) return NULL;
346
347         if (tree_num) {
348                 RADCLIENT myclient;
349
350                 myclient.number = number;
351
352                 return rbtree_finddata(tree_num, &myclient);
353         }
354
355         return NULL;
356 }
357 #else
358 RADCLIENT *client_findbynumber(UNUSED const RADCLIENT_LIST *clients, UNUSED int number)
359 {
360         return NULL;
361 }
362 #endif
363
364
365 /*
366  *      Find a client in the RADCLIENTS list.
367  */
368 RADCLIENT *client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto)
369 {
370   int32_t i, max_prefix;
371         RADCLIENT myclient;
372
373         if (!clients) clients = root_clients;
374
375         if (!clients || !ipaddr) return NULL;
376
377         switch (ipaddr->af) {
378         case AF_INET:
379                 max_prefix = 32;
380                 break;
381
382         case AF_INET6:
383                 max_prefix = 128;
384                 break;
385
386         default :
387                 return NULL;
388         }
389
390         for (i = max_prefix; i >= (int32_t) clients->min_prefix; i--) {
391                 void *data;
392
393                 myclient.ipaddr = *ipaddr;
394                 myclient.proto = proto;
395                 fr_ipaddr_mask(&myclient.ipaddr, i);
396
397                 if (!clients->trees[i]) continue;
398
399                 data = rbtree_finddata(clients->trees[i], &myclient);
400                 if (data) return data;
401         }
402
403         return NULL;
404 }
405
406 /*
407  *      Old wrapper for client_find
408  */
409 RADCLIENT *client_find_old(fr_ipaddr_t const *ipaddr)
410 {
411         return client_find(root_clients, ipaddr, IPPROTO_UDP);
412 }
413
414 static fr_ipaddr_t cl_ipaddr;
415 static char const *cl_srcipaddr = NULL;
416 static uint32_t cl_prefix;
417 #ifdef WITH_TCP
418 static char const *hs_proto = NULL;
419 #endif
420
421 #ifdef WITH_TCP
422 static CONF_PARSER limit_config[] = {
423         { "max_connections", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.max_connections),   "16" },
424
425         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.lifetime),   "0" },
426
427         { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.idle_timeout), "30" },
428
429         { NULL, -1, 0, NULL, NULL }             /* end the list */
430 };
431 #endif
432
433 static const CONF_PARSER client_config[] = {
434         { "ipaddr", FR_CONF_POINTER(PW_TYPE_IP_PREFIX, &cl_ipaddr), NULL },
435         { "ipv4addr", FR_CONF_POINTER(PW_TYPE_IPV4_PREFIX, &cl_ipaddr), NULL },
436         { "ipv6addr", FR_CONF_POINTER(PW_TYPE_IPV6_PREFIX, &cl_ipaddr), NULL },
437         { "netmask", FR_CONF_POINTER(PW_TYPE_INTEGER, &cl_prefix), NULL },
438
439         { "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
440
441         { "require_message_authenticator",  FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
442
443         { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
444         { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
445         { "nastype", FR_CONF_OFFSET(PW_TYPE_DEPRECATED | PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
446         { "nas_type", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
447         { "login", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, login), NULL },
448         { "password", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, password), NULL },
449         { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
450         { "response_window", FR_CONF_OFFSET(PW_TYPE_TIMEVAL, RADCLIENT, response_window), NULL },
451
452 #ifdef WITH_TCP
453         { "proto", FR_CONF_POINTER(PW_TYPE_STRING, &hs_proto), NULL },
454         { "limit", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) limit_config },
455 #endif
456
457 #ifdef WITH_DYNAMIC_CLIENTS
458         { "dynamic_clients", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, client_server), NULL },
459         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, lifetime), NULL },
460         { "rate_limit", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, rate_limit), NULL },
461 #endif
462
463 #ifdef WITH_COA
464         { "coa_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, coa_name), NULL },
465 #endif
466
467         { NULL, -1, 0, NULL, NULL }
468 };
469
470
471 static RADCLIENT *client_parse(CONF_SECTION *cs, int in_server)
472 {
473         RADCLIENT       *c;
474         char const      *name2;
475
476         name2 = cf_section_name2(cs);
477         if (!name2) {
478                 cf_log_err_cs(cs, "Missing client name");
479                 return NULL;
480         }
481
482         /*
483          *      The size is fine.. Let's create the buffer
484          */
485         c = talloc_zero(cs, RADCLIENT);
486         c->cs = cs;
487
488         memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
489         cl_prefix = 256;
490         if (cf_section_parse(cs, c, client_config) < 0) {
491                 cf_log_err_cs(cs, "Error parsing client section");
492         error:
493                 client_free(c);
494 #ifdef WITH_TCP
495                 hs_proto = NULL;
496                 cl_srcipaddr = NULL;
497 #endif
498
499                 return NULL;
500         }
501
502         /*
503          *      Global clients can set servers to use, per-server clients cannot.
504          */
505         if (in_server && c->server) {
506                 cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server");
507                 goto error;
508         }
509
510         /*
511          *      Newer style client definitions with either ipaddr or ipaddr6
512          *      config items.
513          */
514         if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
515                 char buffer[128];
516
517                 /*
518                  *      Sets ipv4/ipv6 address and prefix.
519                  */
520                 c->ipaddr = cl_ipaddr;
521
522                 /*
523                  *      Set the long name to be the result of a reverse lookup on the IP address.
524                  */
525                 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
526                 c->longname = talloc_typed_strdup(c, buffer);
527
528                 /*
529                  *      Set the short name to the name2.
530                  */
531                 if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2);
532         /*
533          *      No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax.
534          */
535         } else {
536                 WARN("No 'ipaddr' or 'ipv4addr' or 'ipv6addr' field found in client %s.  Please fix your configuration",
537                      name2);
538                 WARN("Support for old-style clients will be removed in a future release");
539
540 #ifdef WITH_TCP
541                 if (cf_pair_find(cs, "proto") != NULL) {
542                         cf_log_err_cs(cs, "Cannot use 'proto' inside of old-style client definition");
543                         goto error;
544                 }
545 #endif
546                 if (fr_pton(&c->ipaddr, name2, 0, true) < 0) {
547                         cf_log_err_cs(cs, "Failed parsing client name \"%s\" as ip address or hostname: %s", name2,
548                                       fr_strerror());
549                         goto error;
550                 }
551
552                 c->longname = talloc_typed_strdup(c, name2);
553                 if (!c->shortname) c->shortname = talloc_typed_strdup(c, c->longname);
554         }
555
556         /*
557          *      Prefix override (this needs to die)
558          */
559         if (cl_prefix != 256) {
560                 WARN("'netmask' field found in client %s is deprecated, use CIDR notation instead.  "
561                      "Please fix your configuration", name2);
562                 WARN("Support for 'netmask' will be removed in a future release");
563
564                 switch (c->ipaddr.af) {
565                 case AF_INET:
566                         if (cl_prefix > 32) {
567                                 cf_log_err_cs(cs, "Invalid IPv4 mask length \"%i\".  Should be between 0-32",
568                                               cl_prefix);
569                                 goto error;
570                         }
571                         break;
572
573                 case AF_INET6:
574                         if (cl_prefix > 128) {
575                                 cf_log_err_cs(cs, "Invalid IPv6 mask length \"%i\".  Should be between 0-128",
576                                               cl_prefix);
577                                 goto error;
578                         }
579                         break;
580
581                 default:
582                         rad_assert(0);
583                 }
584                 fr_ipaddr_mask(&c->ipaddr, cl_prefix);
585         }
586
587         c->proto = IPPROTO_UDP;
588         if (hs_proto) {
589                 if (strcmp(hs_proto, "udp") == 0) {
590                         hs_proto = NULL;
591
592 #ifdef WITH_TCP
593                 } else if (strcmp(hs_proto, "tcp") == 0) {
594                         hs_proto = NULL;
595                         c->proto = IPPROTO_TCP;
596 #  ifdef WITH_TLS
597                 } else if (strcmp(hs_proto, "tls") == 0) {
598                         hs_proto = NULL;
599                         c->proto = IPPROTO_TCP;
600                         c->tls_required = true;
601
602                 } else if (strcmp(hs_proto, "radsec") == 0) {
603                         hs_proto = NULL;
604                         c->proto = IPPROTO_TCP;
605                         c->tls_required = true;
606 #  endif
607                 } else if (strcmp(hs_proto, "*") == 0) {
608                         hs_proto = NULL;
609                         c->proto = IPPROTO_IP; /* fake for dual */
610 #endif
611                 } else {
612                         cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto);
613                         goto error;
614                 }
615         }
616
617         /*
618          *      If a src_ipaddr is specified, when we send the return packet
619          *      we will use this address instead of the src from the
620          *      request.
621          */
622         if (cl_srcipaddr) {
623 #ifdef WITH_UDPFROMTO
624                 switch (c->ipaddr.af) {
625                 case AF_INET:
626                         if (fr_pton4(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 0) {
627                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
628                                 goto error;
629                         }
630                         break;
631
632                 case AF_INET6:
633                         if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 0) {
634                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
635                                 goto error;
636                         }
637                         break;
638                 default:
639                         rad_assert(0);
640                 }
641 #else
642                 WARN("Server not built with udpfromto, ignoring client src_ipaddr");
643 #endif
644                 cl_srcipaddr = NULL;
645         }
646
647         /*
648          *      A response_window of zero is OK, and means that it's
649          *      ignored by the rest of the server timers.
650          */
651         if (timerisset(&c->response_window)) {
652                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000);
653                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0);
654                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0);
655         }
656
657 #ifdef WITH_DYNAMIC_CLIENTS
658         if (c->client_server) {
659                 c->secret = talloc_typed_strdup(c, "testing123");
660
661                 if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) ||
662                     ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) {
663                         cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address");
664                         goto error;
665                 }
666
667                 return c;
668         }
669 #endif
670
671         if (!c->secret || (c->secret[0] == '\0')) {
672 #ifdef WITH_DHCP
673                 char const *value = NULL;
674                 CONF_PAIR *cp = cf_pair_find(cs, "dhcp");
675
676                 if (cp) value = cf_pair_value(cp);
677
678                 /*
679                  *      Secrets aren't needed for DHCP.
680                  */
681                 if (value && (strcmp(value, "yes") == 0)) return c;
682 #endif
683
684 #ifdef WITH_TLS
685                 /*
686                  *      If the client is TLS only, the secret can be
687                  *      omitted.  When omitted, it's hard-coded to
688                  *      "radsec".  See RFC 6614.
689                  */
690                 if (c->tls_required) {
691                         c->secret = talloc_typed_strdup(cs, "radsec");
692                 } else
693 #endif
694
695                 {
696                         cf_log_err_cs(cs,
697                                       "secret must be at least 1 character long");
698                         goto error;
699                 }
700         }
701
702 #ifdef WITH_COA
703         /*
704          *      Point the client to the home server pool, OR to the
705          *      home server.  This gets around the problem of figuring
706          *      out which port to use.
707          */
708         if (c->coa_name) {
709                 c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA);
710                 if (!c->coa_pool) {
711                         c->coa_server = home_server_byname(c->coa_name,
712                                                            HOME_TYPE_COA);
713                 }
714                 if (!c->coa_pool && !c->coa_server) {
715                         cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name);
716                         goto error;
717                 }
718         }
719 #endif
720
721 #ifdef WITH_TCP
722         if ((c->proto == IPPROTO_TCP) || (c->proto == IPPROTO_IP)) {
723                 if ((c->limit.idle_timeout > 0) && (c->limit.idle_timeout < 5))
724                         c->limit.idle_timeout = 5;
725                 if ((c->limit.lifetime > 0) && (c->limit.lifetime < 5))
726                         c->limit.lifetime = 5;
727                 if ((c->limit.lifetime > 0) && (c->limit.idle_timeout > c->limit.lifetime))
728                         c->limit.idle_timeout = 0;
729         }
730 #endif
731
732         return c;
733 }
734
735
736 /*
737  *      Create the linked list of clients from the new configuration
738  *      type.  This way we don't have to change too much in the other
739  *      source-files.
740  */
741 #ifdef WITH_TLS
742 RADCLIENT_LIST *clients_parse_section(CONF_SECTION *section, bool tls_required)
743 #else
744 RADCLIENT_LIST *clients_parse_section(CONF_SECTION *section, UNUSED bool tls_required)
745 #endif
746 {
747         bool            global = false, in_server = false;
748         CONF_SECTION    *cs;
749         RADCLIENT       *c;
750         RADCLIENT_LIST  *clients;
751
752         /*
753          *      Be forgiving.  If there's already a clients, return
754          *      it.  Otherwise create a new one.
755          */
756         clients = cf_data_find(section, "clients");
757         if (clients) return clients;
758
759         clients = clients_init(section);
760         if (!clients) return NULL;
761
762         if (cf_top_section(section) == section) global = true;
763
764         if (strcmp("server", cf_section_name1(section)) == 0) in_server = true;
765
766         /*
767          *      Associate the clients structure with the section.
768          */
769         if (cf_data_add(section, "clients", clients, NULL) < 0) {
770                 cf_log_err_cs(section,
771                            "Failed to associate clients with section %s",
772                        cf_section_name1(section));
773                 clients_free(clients);
774                 return NULL;
775         }
776
777         for (cs = cf_subsection_find_next(section, NULL, "client");
778              cs != NULL;
779              cs = cf_subsection_find_next(section, cs, "client")) {
780                 c = client_parse(cs, in_server);
781                 if (!c) {
782                         return NULL;
783                 }
784
785 #ifdef WITH_TLS
786                 /*
787                  *      TLS clients CANNOT use non-TLS listeners.
788                  *      non-TLS clients CANNOT use TLS listeners.
789                  */
790                 if (tls_required != c->tls_required) {
791                         cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener");
792                         client_free(c);
793                         clients_free(clients);
794                         return NULL;
795                 }
796 #endif
797
798                 /*
799                  *      FIXME: Add the client as data via cf_data_add,
800                  *      for migration issues.
801                  */
802
803 #ifdef WITH_DYNAMIC_CLIENTS
804 #ifdef HAVE_DIRENT_H
805                 if (c->client_server) {
806                         char const *value;
807                         CONF_PAIR *cp;
808                         DIR             *dir;
809                         struct dirent   *dp;
810                         struct stat stat_buf;
811                         char buf2[2048];
812
813                         /*
814                          *      Find the directory where individual
815                          *      client definitions are stored.
816                          */
817                         cp = cf_pair_find(cs, "directory");
818                         if (!cp) goto add_client;
819
820                         value = cf_pair_value(cp);
821                         if (!value) {
822                                 cf_log_err_cs(cs,
823                                            "The \"directory\" entry must not be empty");
824                                 client_free(c);
825                                 return NULL;
826                         }
827
828                         DEBUG("including dynamic clients in %s", value);
829
830                         dir = opendir(value);
831                         if (!dir) {
832                                 cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno));
833                                 client_free(c);
834                                 return NULL;
835                         }
836
837                         /*
838                          *      Read the directory, ignoring "." files.
839                          */
840                         while ((dp = readdir(dir)) != NULL) {
841                                 char const *p;
842                                 RADCLIENT *dc;
843
844                                 if (dp->d_name[0] == '.') continue;
845
846                                 /*
847                                  *      Check for valid characters
848                                  */
849                                 for (p = dp->d_name; *p != '\0'; p++) {
850                                         if (isalpha((int)*p) ||
851                                             isdigit((int)*p) ||
852                                             (*p == ':') ||
853                                             (*p == '.')) continue;
854                                                 break;
855                                 }
856                                 if (*p != '\0') continue;
857
858                                 snprintf(buf2, sizeof(buf2), "%s/%s",
859                                          value, dp->d_name);
860
861                                 if ((stat(buf2, &stat_buf) != 0) ||
862                                     S_ISDIR(stat_buf.st_mode)) continue;
863
864                                 dc = client_read(buf2, in_server, true);
865                                 if (!dc) {
866                                         cf_log_err_cs(cs,
867                                                    "Failed reading client file \"%s\"", buf2);
868                                         client_free(c);
869                                         closedir(dir);
870                                         return NULL;
871                                 }
872
873                                 /*
874                                  *      Validate, and add to the list.
875                                  */
876                                 if (!client_validate(clients, c, dc)) {
877
878                                         client_free(c);
879                                         closedir(dir);
880                                         return NULL;
881                                 }
882                         } /* loop over the directory */
883                         closedir(dir);
884                 }
885 #endif /* HAVE_DIRENT_H */
886
887         add_client:
888 #endif /* WITH_DYNAMIC_CLIENTS */
889                 if (!client_add(clients, c)) {
890                         cf_log_err_cs(cs,
891                                    "Failed to add client %s",
892                                    cf_section_name2(cs));
893                         client_free(c);
894                         return NULL;
895                 }
896
897         }
898
899         /*
900          *      Replace the global list of clients with the new one.
901          *      The old one is still referenced from the original
902          *      configuration, and will be freed when that is freed.
903          */
904         if (global) {
905                 root_clients = clients;
906         }
907
908         return clients;
909 }
910
911 #ifdef WITH_DYNAMIC_CLIENTS
912 /*
913  *      We overload this structure a lot.
914  */
915 static const CONF_PARSER dynamic_config[] = {
916         { "FreeRADIUS-Client-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, ipaddr), NULL },
917         { "FreeRADIUS-Client-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, ipaddr), NULL },
918         { "FreeRADIUS-Client-IP-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV4_PREFIX, RADCLIENT, ipaddr), NULL },
919         { "FreeRADIUS-Client-IPv6-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV6_PREFIX, RADCLIENT, ipaddr), NULL },
920         { "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
921         { "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
922
923         { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
924
925         { "FreeRADIUS-Client-Secret",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
926         { "FreeRADIUS-Client-Shortname",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
927         { "FreeRADIUS-Client-NAS-Type",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
928         { "FreeRADIUS-Client-Virtual-Server",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
929
930         { NULL, -1, 0, NULL, NULL }
931 };
932
933
934 bool client_validate(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
935 {
936         char buffer[128];
937
938         /*
939          *      No virtual server defined.  Inherit the parent's
940          *      definition.
941          */
942         if (master->server && !c->server) {
943                 c->server = talloc_typed_strdup(c, master->server);
944         }
945
946         /*
947          *      If the client network isn't global (not tied to a
948          *      virtual server), then ensure that this clients server
949          *      is the same as the enclosing networks virtual server.
950          */
951         if (master->server &&
952              (strcmp(master->server, c->server) != 0)) {
953                 DEBUG("- Cannot add client %s: Virtual server %s is not the same as the virtual server for the network",
954                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->server);
955
956                 goto error;
957         }
958
959         if (!client_add(clients, c)) {
960                 DEBUG("- Cannot add client %s: Internal error", ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)));
961
962                 goto error;
963         }
964
965         /*
966          *      Initialize the remaining fields.
967          */
968         c->dynamic = true;
969         c->lifetime = master->lifetime;
970         c->created = time(NULL);
971         c->longname = talloc_typed_strdup(c, c->shortname);
972
973         DEBUG("- Added client %s with shared secret %s",
974               ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)),
975               c->secret);
976
977         return true;
978
979 error:
980         client_free(c);
981         return false;
982 }
983
984 /** Add a client from a result set (LDAP, SQL, et al)
985  *
986  * @param ctx Talloc context.
987  * @param identifier Client IP Address / IPv4 subnet / IPv6 subnet / FQDN.
988  * @param secret Client secret.
989  * @param shortname Client friendly name.
990  * @param type NAS-Type.
991  * @param server Virtual-Server to associate clients with.
992  * @param require_ma If true all packets from client must include a message-authenticator.
993  * @return The new client, or NULL on error.
994  */
995 RADCLIENT *client_from_query(TALLOC_CTX *ctx, char const *identifier, char const *secret, char const *shortname,
996                              char const *type, char const *server, bool require_ma)
997 {
998         RADCLIENT *c;
999         char buffer[128];
1000
1001         rad_assert(identifier);
1002         rad_assert(secret);
1003
1004         c = talloc_zero(ctx, RADCLIENT);
1005
1006         if (fr_pton(&c->ipaddr, identifier, 0, true) < 0) {
1007                 ERROR("%s", fr_strerror());
1008                 talloc_free(c);
1009
1010                 return NULL;
1011         }
1012
1013 #ifdef WITH_DYNAMIC_CLIENTS
1014         c->dynamic = true;
1015 #endif
1016         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1017         c->longname = talloc_typed_strdup(c, buffer);
1018
1019         /*
1020          *      Other values (secret, shortname, nas_type, virtual_server)
1021          */
1022         c->secret = talloc_typed_strdup(c, secret);
1023         if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
1024         if (type) c->nas_type = talloc_typed_strdup(c, type);
1025         if (server) c->server = talloc_typed_strdup(c, server);
1026         c->message_authenticator = require_ma;
1027
1028         return c;
1029 }
1030
1031 RADCLIENT *client_from_request(RADCLIENT_LIST *clients, REQUEST *request)
1032 {
1033         int i, *pi;
1034         char **p;
1035         RADCLIENT *c;
1036         char buffer[128];
1037
1038         if (!clients || !request) return NULL;
1039
1040         c = talloc_zero(clients, RADCLIENT);
1041         c->cs = request->client->cs;
1042         c->ipaddr.af = AF_UNSPEC;
1043         c->src_ipaddr.af = AF_UNSPEC;
1044
1045         for (i = 0; dynamic_config[i].name != NULL; i++) {
1046                 DICT_ATTR const *da;
1047                 VALUE_PAIR *vp;
1048
1049                 da = dict_attrbyname(dynamic_config[i].name);
1050                 if (!da) {
1051                         DEBUG("- Cannot add client %s: attribute \"%s\"is not in the dictionary",
1052                               ip_ntoh(&request->packet->src_ipaddr,
1053                                       buffer, sizeof(buffer)),
1054                               dynamic_config[i].name);
1055                 error:
1056                         client_free(c);
1057                         return NULL;
1058                 }
1059
1060                 vp = pairfind(request->config_items, da->attr, da->vendor, TAG_ANY);
1061                 if (!vp) {
1062                         /*
1063                          *      Not required.  Skip it.
1064                          */
1065                         if (!dynamic_config[i].dflt) continue;
1066
1067                         DEBUG("- Cannot add client %s: Required attribute \"%s\" is missing.",
1068                               ip_ntoh(&request->packet->src_ipaddr,
1069                                       buffer, sizeof(buffer)),
1070                               dynamic_config[i].name);
1071                         goto error;
1072                 }
1073
1074                 switch (dynamic_config[i].type) {
1075                 case PW_TYPE_IPV4_ADDR:
1076                         if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) {
1077                                 c->ipaddr.af = AF_INET;
1078                                 c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1079                                 c->ipaddr.prefix = 32;
1080                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) {
1081 #ifdef WITH_UDPFROMTO
1082                                 c->src_ipaddr.af = AF_INET;
1083                                 c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1084 #else
1085                                 WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address");
1086 #endif
1087                         }
1088
1089                         break;
1090
1091                 case PW_TYPE_IPV6_ADDR:
1092                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) {
1093                                 c->ipaddr.af = AF_INET6;
1094                                 c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1095                                 c->ipaddr.prefix = 128;
1096                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) {
1097 #ifdef WITH_UDPFROMTO
1098                                 c->src_ipaddr.af = AF_INET6;
1099                                 c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1100 #else
1101                                 WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address");
1102 #endif
1103                         }
1104
1105                         break;
1106
1107                 case PW_TYPE_IPV4_PREFIX:
1108                         if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) {
1109                                 c->ipaddr.af = AF_INET;
1110                                 memcpy(&c->ipaddr.ipaddr.ip4addr.s_addr, &(vp->vp_ipv4prefix[2]), sizeof(c->ipaddr.ipaddr.ip4addr.s_addr));
1111                                 fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f));
1112                         }
1113
1114                         break;
1115
1116                 case PW_TYPE_IPV6_PREFIX:
1117                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) {
1118                                 c->ipaddr.af = AF_INET6;
1119                                 memcpy(&c->ipaddr.ipaddr.ip6addr, &(vp->vp_ipv6prefix[2]), sizeof(c->ipaddr.ipaddr.ip6addr));
1120                                 fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]);
1121                         }
1122
1123                         break;
1124
1125                 case PW_TYPE_STRING:
1126                         p = (char **) ((char *) c + dynamic_config[i].offset);
1127                         if (*p) talloc_free(*p);
1128                         if (vp->vp_strvalue[0]) {
1129                                 *p = talloc_typed_strdup(c->cs, vp->vp_strvalue);
1130                         } else {
1131                                 *p = NULL;
1132                         }
1133                         break;
1134
1135                 case PW_TYPE_BOOLEAN:
1136                         pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset));
1137                         *pi = vp->vp_integer;
1138                         break;
1139
1140                 default:
1141                         goto error;
1142                 }
1143         }
1144
1145         if (c->ipaddr.af == AF_UNSPEC) {
1146                 DEBUG("- Cannot add client %s: No IP address was specified.",
1147                       ip_ntoh(&request->packet->src_ipaddr,
1148                               buffer, sizeof(buffer)));
1149
1150                 goto error;
1151         }
1152
1153         {
1154                 fr_ipaddr_t addr;
1155
1156                 /*
1157                  *      Need to apply the same mask as we set for the client
1158                  *      else clients created with FreeRADIUS-Client-IPv6-Prefix
1159                  *      or FreeRADIUS-Client-IPv4-Prefix will fail this check.
1160                  */
1161                 addr = request->packet->src_ipaddr;
1162                 fr_ipaddr_mask(&addr, c->ipaddr.prefix);
1163                 if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) {
1164                         char buf2[128];
1165
1166                         DEBUG("- Cannot add client %s: IP address %s do not match",
1167                               ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1168                               ip_ntoh(&c->ipaddr, buf2, sizeof(buf2)));
1169                         goto error;
1170                 }
1171         }
1172
1173         if (!c->secret || !*c->secret) {
1174                 DEBUG("- Cannot add client %s: No secret was specified.",
1175                       ip_ntoh(&request->packet->src_ipaddr,
1176                               buffer, sizeof(buffer)));
1177                 goto error;
1178         }
1179
1180         if (!client_validate(clients, request->client, c)) {
1181                 return NULL;
1182         }
1183
1184         if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) {
1185                 DEBUG("- Cannot add client %s: Client IP and src address are different IP version.",
1186                       ip_ntoh(&request->packet->src_ipaddr,
1187                               buffer, sizeof(buffer)));
1188
1189                 goto error;
1190         }
1191
1192         return c;
1193 }
1194
1195 /*
1196  *      Read a client definition from the given filename.
1197  */
1198 RADCLIENT *client_read(char const *filename, int in_server, int flag)
1199 {
1200         char const *p;
1201         RADCLIENT *c;
1202         CONF_SECTION *cs;
1203         char buffer[256];
1204
1205         if (!filename) return NULL;
1206
1207         cs = cf_file_read(filename);
1208         if (!cs) return NULL;
1209
1210         cs = cf_section_sub_find(cs, "client");
1211         if (!cs) {
1212                 ERROR("No \"client\" section found in client file");
1213                 return NULL;
1214         }
1215
1216         c = client_parse(cs, in_server);
1217         if (!c) return NULL;
1218
1219         p = strrchr(filename, FR_DIR_SEP);
1220         if (p) {
1221                 p++;
1222         } else {
1223                 p = filename;
1224         }
1225
1226         if (!flag) return c;
1227
1228         /*
1229          *      Additional validations
1230          */
1231         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1232         if (strcmp(p, buffer) != 0) {
1233                 DEBUG("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p);
1234                 client_free(c);
1235                 return NULL;
1236         }
1237
1238         return c;
1239 }
1240 #endif
1241