Merge tag 'release_3_0_12' into branch moonshot-fr-3.0.12-upgrade.
[freeradius.git] / src / main / client.c
1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or (at
5  *   your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16
17 /**
18  * $Id$
19  * @file main/client.c
20  * @brief Manage clients allowed to communicate with the server.
21  *
22  * @copyright 2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23  * @copyright 2000,2006 The FreeRADIUS server project
24  * @copyright 2000 Alan DeKok <aland@ox.org>
25  * @copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
26  */
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/rad_assert.h>
31
32 #include <sys/stat.h>
33
34 #include <ctype.h>
35 #include <fcntl.h>
36
37 #ifdef WITH_DYNAMIC_CLIENTS
38 #ifdef HAVE_DIRENT_H
39 #include <dirent.h>
40 #endif
41 #endif
42
43 struct radclient_list {
44         /*
45          *      FIXME: One set of trees for IPv4, and another for IPv6?
46          */
47         rbtree_t        *trees[129]; /* for 0..128, inclusive. */
48         uint32_t        min_prefix;
49 };
50
51
52 #ifdef WITH_STATS
53 static rbtree_t         *tree_num = NULL;     /* client numbers 0..N */
54 static int              tree_num_max = 0;
55 #endif
56 static RADCLIENT_LIST   *root_clients = NULL;
57
58 #ifdef WITH_DYNAMIC_CLIENTS
59 static fr_fifo_t        *deleted_clients = NULL;
60 #endif
61
62 /*
63  *      Callback for freeing a client.
64  */
65 void client_free(RADCLIENT *client)
66 {
67         if (!client) return;
68
69 #ifdef WITH_DYNAMIC_CLIENTS
70         if (client->dynamic == 2) {
71                 time_t now;
72
73                 if (!deleted_clients) {
74                         deleted_clients = fr_fifo_create(NULL, 1024, (void (*)(void *))client_free);
75                         if (!deleted_clients) return; /* MEMLEAK */
76                 }
77
78                 /*
79                  *      Mark it as in the fifo, and remember when we
80                  *      pushed it.
81                  */
82                 client->dynamic = 3;
83                 client->created = now = time(NULL); /* re-set it */
84                 fr_fifo_push(deleted_clients, client);
85
86                 /*
87                  *      Peek at the head of the fifo.  If it might
88                  *      still be in use, return.  Otherwise, pop it
89                  *      from the queue and delete it.
90                  */
91                 client = fr_fifo_peek(deleted_clients);
92                 rad_assert(client != NULL);
93
94                 if ((client->created + 120) >= now) return;
95
96                 client = fr_fifo_pop(deleted_clients);
97                 rad_assert(client != NULL);
98         }
99 #endif
100
101         talloc_free(client);
102 }
103
104 /*
105  *      Callback for comparing two clients.
106  */
107 static int client_ipaddr_cmp(void const *one, void const *two)
108 {
109         RADCLIENT const *a = one;
110         RADCLIENT const *b = two;
111 #ifndef WITH_TCP
112
113         return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
114 #else
115         int rcode;
116
117         rcode = fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
118         if (rcode != 0) return rcode;
119
120         /*
121          *      Wildcard match
122          */
123         if ((a->proto == IPPROTO_IP) ||
124             (b->proto == IPPROTO_IP)) return 0;
125
126         return (a->proto - b->proto);
127 #endif
128 }
129
130 #ifdef WITH_STATS
131 static int client_num_cmp(void const *one, void const *two)
132 {
133         RADCLIENT const *a = one;
134         RADCLIENT const *b = two;
135
136         return (a->number - b->number);
137 }
138 #endif
139
140 /*
141  *      Free a RADCLIENT list.
142  */
143 void client_list_free(RADCLIENT_LIST *clients)
144 {
145         int i;
146
147         if (!clients) clients = root_clients;
148         if (!clients) return;   /* Clients may not have been initialised yet */
149
150         for (i = 0; i <= 128; i++) {
151                 if (clients->trees[i]) rbtree_free(clients->trees[i]);
152                 clients->trees[i] = NULL;
153         }
154
155         if (clients == root_clients) {
156 #ifdef WITH_STATS
157                 if (tree_num) rbtree_free(tree_num);
158                 tree_num = NULL;
159                 tree_num_max = 0;
160 #endif
161                 root_clients = NULL;
162         }
163
164 #ifdef WITH_DYNAMIC_CLIENTS
165         /*
166          *      FIXME: No fr_fifo_delete()
167          */
168 #endif
169
170         talloc_free(clients);
171 }
172
173 /*
174  *      Return a new, initialized, set of clients.
175  */
176 RADCLIENT_LIST *client_list_init(CONF_SECTION *cs)
177 {
178         RADCLIENT_LIST *clients = talloc_zero(cs, RADCLIENT_LIST);
179
180         if (!clients) return NULL;
181
182         clients->min_prefix = 128;
183
184         return clients;
185 }
186
187 /** Add a client to a RADCLIENT_LIST
188  *
189  * @param clients list to add client to, may be NULL if global client list is being used.
190  * @param client to add.
191  * @return true on success, false on failure.
192  */
193 bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
194 {
195         RADCLIENT *old;
196         char buffer[INET6_ADDRSTRLEN + 3];
197
198         if (!client) return false;
199
200         /*
201          *      Hack to fixup wildcard clients
202          *
203          *      If the IP is all zeros, with a 32 or 128 bit netmask
204          *      assume the user meant to configure 0.0.0.0/0 instead
205          *      of 0.0.0.0/32 - which would require the src IP of
206          *      the client to be all zeros.
207          */
208         if (fr_inaddr_any(&client->ipaddr) == 1) switch (client->ipaddr.af) {
209         case AF_INET:
210                 if (client->ipaddr.prefix == 32) client->ipaddr.prefix = 0;
211                 break;
212
213         case AF_INET6:
214                 if (client->ipaddr.prefix == 128) client->ipaddr.prefix = 0;
215                 break;
216
217         default:
218                 rad_assert(0);
219         }
220
221         fr_ntop(buffer, sizeof(buffer), &client->ipaddr);
222         DEBUG3("Adding client %s (%s) to prefix tree %i", buffer, client->longname, client->ipaddr.prefix);
223
224         /*
225          *      If the client also defines a server, do that now.
226          */
227         if (client->defines_coa_server) if (!realm_home_server_add(client->coa_server)) return false;
228
229         /*
230          *      If "clients" is NULL, it means add to the global list,
231          *      unless we're trying to add it to a virtual server...
232          */
233         if (!clients) {
234                 if (client->server != NULL) {
235                         CONF_SECTION *cs;
236                         CONF_SECTION *subcs;
237
238                         cs = cf_section_sub_find_name2(main_config.config, "server", client->server);
239                         if (!cs) {
240                                 ERROR("Failed to find virtual server %s", client->server);
241                                 return false;
242                         }
243
244                         /*
245                          *      If this server has no "listen" section, add the clients
246                          *      to the global client list.
247                          */
248                         subcs = cf_section_sub_find(cs, "listen");
249                         if (!subcs) goto global_clients;
250
251                         /*
252                          *      If the client list already exists, use that.
253                          *      Otherwise, create a new client list.
254                          */
255                         clients = cf_data_find(cs, "clients");
256                         if (!clients) {
257                                 clients = client_list_init(cs);
258                                 if (!clients) {
259                                         ERROR("Out of memory");
260                                         return false;
261                                 }
262
263                                 if (cf_data_add(cs, "clients", clients, (void (*)(void *)) client_list_free) < 0) {
264                                         ERROR("Failed to associate clients with virtual server %s", client->server);
265                                         client_list_free(clients);
266                                         return false;
267                                 }
268                         }
269
270                 } else {
271                 global_clients:
272                         /*
273                          *      Initialize the global list, if not done already.
274                          */
275                         if (!root_clients) {
276                                 root_clients = client_list_init(NULL);
277                                 if (!root_clients) return false;
278                         }
279                         clients = root_clients;
280                 }
281         }
282
283         /*
284          *      Create a tree for it.
285          */
286         if (!clients->trees[client->ipaddr.prefix]) {
287                 clients->trees[client->ipaddr.prefix] = rbtree_create(clients, client_ipaddr_cmp, NULL, 0);
288                 if (!clients->trees[client->ipaddr.prefix]) {
289                         return false;
290                 }
291         }
292
293 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
294
295         /*
296          *      Cannot insert the same client twice.
297          */
298         old = rbtree_finddata(clients->trees[client->ipaddr.prefix], client);
299         if (old) {
300                 /*
301                  *      If it's a complete duplicate, then free the new
302                  *      one, and return "OK".
303                  */
304                 if ((fr_ipaddr_cmp(&old->ipaddr, &client->ipaddr) == 0) &&
305                     (old->ipaddr.prefix == client->ipaddr.prefix) &&
306                     namecmp(longname) && namecmp(secret) &&
307                     namecmp(shortname) && namecmp(nas_type) &&
308                     namecmp(login) && namecmp(password) && namecmp(server) &&
309 #ifdef WITH_DYNAMIC_CLIENTS
310                     (old->lifetime == client->lifetime) &&
311                     namecmp(client_server) &&
312 #endif
313 #ifdef WITH_COA
314                     namecmp(coa_name) &&
315                     (old->coa_server == client->coa_server) &&
316                     (old->coa_pool == client->coa_pool) &&
317 #endif
318                     (old->message_authenticator == client->message_authenticator)) {
319                         WARN("Ignoring duplicate client %s", client->longname);
320                         client_free(client);
321                         return true;
322                 }
323
324                 ERROR("Failed to add duplicate client %s", client->shortname);
325                 return false;
326         }
327 #undef namecmp
328
329         /*
330          *      Other error adding client: likely is fatal.
331          */
332         if (!rbtree_insert(clients->trees[client->ipaddr.prefix], client)) {
333                 return false;
334         }
335
336 #ifdef WITH_STATS
337         if (!tree_num) {
338                 tree_num = rbtree_create(clients, client_num_cmp, NULL, 0);
339         }
340
341 #ifdef WITH_DYNAMIC_CLIENTS
342         /*
343          *      More catching of clients added by rlm_sql.
344          *
345          *      The sql modules sets the dynamic flag BEFORE calling
346          *      us.  The client_afrom_request() function sets it AFTER
347          *      calling us.
348          */
349         if (client->dynamic && (client->lifetime == 0)) {
350                 RADCLIENT *network;
351
352                 /*
353                  *      If there IS an enclosing network,
354                  *      inherit the lifetime from it.
355                  */
356                 network = client_find(clients, &client->ipaddr, client->proto);
357                 if (network) {
358                         client->lifetime = network->lifetime;
359                 }
360         }
361 #endif
362
363         client->number = tree_num_max;
364         tree_num_max++;
365         if (tree_num) rbtree_insert(tree_num, client);
366 #endif
367
368         if (client->ipaddr.prefix < clients->min_prefix) {
369                 clients->min_prefix = client->ipaddr.prefix;
370         }
371
372         (void) talloc_steal(clients, client); /* reparent it */
373
374         return true;
375 }
376
377
378 #ifdef WITH_DYNAMIC_CLIENTS
379 void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client)
380 {
381         if (!client) return;
382
383         if (!clients) clients = root_clients;
384
385         if (!client->dynamic) return;
386
387         rad_assert(client->ipaddr.prefix <= 128);
388
389         client->dynamic = 2;    /* signal to client_free */
390
391 #ifdef WITH_STATS
392         rbtree_deletebydata(tree_num, client);
393 #endif
394         rbtree_deletebydata(clients->trees[client->ipaddr.prefix], client);
395 }
396 #endif
397
398 #ifdef WITH_STATS
399 /*
400  *      Find a client in the RADCLIENTS list by number.
401  *      This is a support function for the statistics code.
402  */
403 RADCLIENT *client_findbynumber(RADCLIENT_LIST const *clients, int number)
404 {
405         if (!clients) clients = root_clients;
406
407         if (!clients) return NULL;
408
409         if (number >= tree_num_max) return NULL;
410
411         if (tree_num) {
412                 RADCLIENT myclient;
413
414                 myclient.number = number;
415
416                 return rbtree_finddata(tree_num, &myclient);
417         }
418
419         return NULL;
420 }
421 #else
422 RADCLIENT *client_findbynumber(UNUSED const RADCLIENT_LIST *clients, UNUSED int number)
423 {
424         return NULL;
425 }
426 #endif
427
428
429 /*
430  *      Find a client in the RADCLIENTS list.
431  */
432 RADCLIENT *client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto)
433 {
434   int32_t i, max_prefix;
435         RADCLIENT myclient;
436
437         if (!clients) clients = root_clients;
438
439         if (!clients || !ipaddr) return NULL;
440
441         switch (ipaddr->af) {
442         case AF_INET:
443                 max_prefix = 32;
444                 break;
445
446         case AF_INET6:
447                 max_prefix = 128;
448                 break;
449
450         default :
451                 return NULL;
452         }
453
454         for (i = max_prefix; i >= (int32_t) clients->min_prefix; i--) {
455                 void *data;
456
457                 myclient.ipaddr = *ipaddr;
458                 myclient.proto = proto;
459                 fr_ipaddr_mask(&myclient.ipaddr, i);
460
461                 if (!clients->trees[i]) continue;
462
463                 data = rbtree_finddata(clients->trees[i], &myclient);
464                 if (data) return data;
465         }
466
467         return NULL;
468 }
469
470 /*
471  *      Old wrapper for client_find
472  */
473 RADCLIENT *client_find_old(fr_ipaddr_t const *ipaddr)
474 {
475         return client_find(root_clients, ipaddr, IPPROTO_UDP);
476 }
477
478 static fr_ipaddr_t cl_ipaddr;
479 static uint32_t cl_netmask;
480 static char const *cl_srcipaddr = NULL;
481 static char const *hs_proto = NULL;
482
483 #ifdef WITH_TCP
484 static CONF_PARSER limit_config[] = {
485         { "max_connections", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.max_connections),   "16" },
486
487         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.lifetime),   "0" },
488
489         { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.idle_timeout), "30" },
490
491         CONF_PARSER_TERMINATOR
492 };
493 #endif
494
495 static const CONF_PARSER client_config[] = {
496         { "ipaddr", FR_CONF_POINTER(PW_TYPE_COMBO_IP_PREFIX, &cl_ipaddr), NULL },
497         { "ipv4addr", FR_CONF_POINTER(PW_TYPE_IPV4_PREFIX, &cl_ipaddr), NULL },
498         { "ipv6addr", FR_CONF_POINTER(PW_TYPE_IPV6_PREFIX, &cl_ipaddr), NULL },
499
500         { "netmask", FR_CONF_POINTER(PW_TYPE_INTEGER, &cl_netmask), NULL },
501
502         { "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
503
504         { "require_message_authenticator",  FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
505
506         { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
507         { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
508
509         { "nas_type", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
510
511         { "login", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, login), NULL },
512         { "password", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, password), NULL },
513         { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
514         { "response_window", FR_CONF_OFFSET(PW_TYPE_TIMEVAL, RADCLIENT, response_window), NULL },
515
516 #ifdef WITH_TCP
517         { "proto", FR_CONF_POINTER(PW_TYPE_STRING, &hs_proto), NULL },
518         { "limit", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) limit_config },
519 #endif
520
521 #ifdef WITH_DYNAMIC_CLIENTS
522         { "dynamic_clients", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, client_server), NULL },
523         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, lifetime), NULL },
524         { "rate_limit", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, rate_limit), NULL },
525 #endif
526
527         CONF_PARSER_TERMINATOR
528 };
529
530 /** Create the linked list of clients from the new configuration type
531  *
532  */
533 #ifdef WITH_TLS
534 RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, bool tls_required)
535 #else
536 RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls_required)
537 #endif
538 {
539         bool            global = false, in_server = false;
540         CONF_SECTION    *cs;
541         RADCLIENT       *c = NULL;
542         RADCLIENT_LIST  *clients = NULL;
543
544         /*
545          *      Be forgiving.  If there's already a clients, return
546          *      it.  Otherwise create a new one.
547          */
548         clients = cf_data_find(section, "clients");
549         if (clients) return clients;
550
551         clients = client_list_init(section);
552         if (!clients) return NULL;
553
554         if (cf_top_section(section) == section) global = true;
555
556         if (strcmp("server", cf_section_name1(section)) == 0) in_server = true;
557
558         for (cs = cf_subsection_find_next(section, NULL, "client");
559              cs;
560              cs = cf_subsection_find_next(section, cs, "client")) {
561                 c = client_afrom_cs(cs, cs, in_server, false);
562                 if (!c) {
563                 error:
564                         client_free(c);
565                         client_list_free(clients);
566                         return NULL;
567                 }
568
569 #ifdef WITH_TLS
570                 /*
571                  *      TLS clients CANNOT use non-TLS listeners.
572                  *      non-TLS clients CANNOT use TLS listeners.
573                  */
574                 if (tls_required != c->tls_required) {
575                         cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener");
576                         goto error;
577                 }
578 #endif
579
580                 /*
581                  *      FIXME: Add the client as data via cf_data_add,
582                  *      for migration issues.
583                  */
584
585 #ifdef WITH_DYNAMIC_CLIENTS
586 #ifdef HAVE_DIRENT_H
587                 if (c->client_server) {
588                         char const      *value;
589                         CONF_PAIR       *cp;
590                         DIR             *dir;
591                         struct dirent   *dp;
592                         struct stat     stat_buf;
593                         char            buf2[2048];
594
595                         /*
596                          *      Find the directory where individual
597                          *      client definitions are stored.
598                          */
599                         cp = cf_pair_find(cs, "directory");
600                         if (!cp) goto add_client;
601
602                         value = cf_pair_value(cp);
603                         if (!value) {
604                                 cf_log_err_cs(cs, "The \"directory\" entry must not be empty");
605                                 goto error;
606                         }
607
608                         DEBUG("including dynamic clients in %s", value);
609
610                         dir = opendir(value);
611                         if (!dir) {
612                                 cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno));
613                                 goto error;
614                         }
615
616                         /*
617                          *      Read the directory, ignoring "." files.
618                          */
619                         while ((dp = readdir(dir)) != NULL) {
620                                 char const *p;
621                                 RADCLIENT *dc;
622
623                                 if (dp->d_name[0] == '.') continue;
624
625                                 /*
626                                  *      Check for valid characters
627                                  */
628                                 for (p = dp->d_name; *p != '\0'; p++) {
629                                         if (isalpha((int)*p) ||
630                                             isdigit((int)*p) ||
631                                             (*p == ':') ||
632                                             (*p == '.')) continue;
633                                         break;
634                                 }
635                                 if (*p != '\0') continue;
636
637                                 snprintf(buf2, sizeof(buf2), "%s/%s", value, dp->d_name);
638
639                                 if ((stat(buf2, &stat_buf) != 0) || S_ISDIR(stat_buf.st_mode)) continue;
640
641                                 dc = client_read(buf2, in_server, true);
642                                 if (!dc) {
643                                         cf_log_err_cs(cs, "Failed reading client file \"%s\"", buf2);
644                                         closedir(dir);
645                                         goto error;
646                                 }
647
648                                 /*
649                                  *      Validate, and add to the list.
650                                  */
651                                 if (!client_add_dynamic(clients, c, dc)) {
652                                         closedir(dir);
653                                         goto error;
654                                 }
655                         } /* loop over the directory */
656                         closedir(dir);
657                 }
658 #endif /* HAVE_DIRENT_H */
659
660         add_client:
661 #endif /* WITH_DYNAMIC_CLIENTS */
662                 if (!client_add(clients, c)) {
663                         cf_log_err_cs(cs, "Failed to add client %s", cf_section_name2(cs));
664                         goto error;
665                 }
666
667         }
668
669         /*
670          *      Associate the clients structure with the section.
671          */
672         if (cf_data_add(section, "clients", clients, NULL) < 0) {
673                 cf_log_err_cs(section, "Failed to associate clients with section %s", cf_section_name1(section));
674                 client_list_free(clients);
675                 return NULL;
676         }
677
678         /*
679          *      Replace the global list of clients with the new one.
680          *      The old one is still referenced from the original
681          *      configuration, and will be freed when that is freed.
682          */
683         if (global) root_clients = clients;
684
685         return clients;
686 }
687
688 #ifdef WITH_DYNAMIC_CLIENTS
689 /*
690  *      We overload this structure a lot.
691  */
692 static const CONF_PARSER dynamic_config[] = {
693         { "FreeRADIUS-Client-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, ipaddr), NULL },
694         { "FreeRADIUS-Client-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, ipaddr), NULL },
695         { "FreeRADIUS-Client-IP-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV4_PREFIX, RADCLIENT, ipaddr), NULL },
696         { "FreeRADIUS-Client-IPv6-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV6_PREFIX, RADCLIENT, ipaddr), NULL },
697         { "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
698         { "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
699
700         { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
701
702         { "FreeRADIUS-Client-Secret",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
703         { "FreeRADIUS-Client-Shortname",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
704         { "FreeRADIUS-Client-NAS-Type",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
705         { "FreeRADIUS-Client-Virtual-Server",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
706
707         CONF_PARSER_TERMINATOR
708 };
709
710 /** Add a dynamic client
711  *
712  */
713 bool client_add_dynamic(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
714 {
715         char buffer[128];
716
717         /*
718          *      No virtual server defined.  Inherit the parent's
719          *      definition.
720          */
721         if (master->server && !c->server) {
722                 c->server = talloc_typed_strdup(c, master->server);
723         }
724
725         /*
726          *      If the client network isn't global (not tied to a
727          *      virtual server), then ensure that this clients server
728          *      is the same as the enclosing networks virtual server.
729          */
730         if (master->server && (strcmp(master->server, c->server) != 0)) {
731                 ERROR("Cannot add client %s/%i: Virtual server %s is not the same as the virtual server for the network",
732                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->server);
733
734                 goto error;
735         }
736
737         if (!client_add(clients, c)) {
738                 ERROR("Cannot add client %s/%i: Internal error",
739                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix);
740
741                 goto error;
742         }
743
744         /*
745          *      Initialize the remaining fields.
746          */
747         c->dynamic = true;
748         c->lifetime = master->lifetime;
749         c->created = time(NULL);
750         c->longname = talloc_typed_strdup(c, c->shortname);
751
752         INFO("Adding client %s/%i with shared secret \"%s\"",
753              ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->secret);
754
755         return true;
756
757 error:
758         client_free(c);
759         return false;
760 }
761
762 /** Create a client CONF_SECTION using a mapping section to map values from a result set to client attributes
763  *
764  * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too.
765  *
766  * @note Caller should free CONF_SECTION passed in as out, on error.
767  *       Contents of that section will be in an undefined state.
768  *
769  * @param[in,out] out Section to perform mapping on. Either the root of the client config, or a parent section
770  *      (when this function is called recursively).
771  *      Should be alloced with cf_section_alloc, or if there's a separate template section, the
772  *      result of calling cf_section_dup on that section.
773  * @param[in] map section.
774  * @param[in] func to call to retrieve CONF_PAIR values. Must return a talloced buffer containing the value.
775  * @param[in] data to pass to func, usually a result pointer.
776  * @return 0 on success else -1 on error.
777  */
778 int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_cb_t func, void *data)
779 {
780         CONF_ITEM const *ci;
781
782         for (ci = cf_item_find_next(map, NULL);
783              ci != NULL;
784              ci = cf_item_find_next(map, ci)) {
785                 CONF_PAIR const *cp;
786                 CONF_PAIR *old;
787                 char *value;
788                 char const *attr;
789
790                 /*
791                  *      Recursively process map subsection
792                  */
793                 if (cf_item_is_section(ci)) {
794                         CONF_SECTION *cs, *cc;
795
796                         cs = cf_item_to_section(ci);
797                         /*
798                          *      Use pre-existing section or alloc a new one
799                          */
800                         cc = cf_section_sub_find_name2(out, cf_section_name1(cs), cf_section_name2(cs));
801                         if (!cc) {
802                                 cc = cf_section_alloc(out, cf_section_name1(cs), cf_section_name2(cs));
803                                 cf_section_add(out, cc);
804                                 if (!cc) return -1;
805                         }
806
807                         if (client_map_section(cc, cs, func, data) < 0) return -1;
808                         continue;
809                 }
810
811                 cp = cf_item_to_pair(ci);
812                 attr = cf_pair_attr(cp);
813
814                 /*
815                  *      The callback can return 0 (success) and not provide a value
816                  *      in which case we skip the mapping pair.
817                  *
818                  *      Or return -1 in which case we error out.
819                  */
820                 if (func(&value, cp, data) < 0) {
821                         cf_log_err_cs(out, "Failed performing mapping \"%s\" = \"%s\"", attr, cf_pair_value(cp));
822                         return -1;
823                 }
824                 if (!value) continue;
825
826                 /*
827                  *      Replace an existing CONF_PAIR
828                  */
829                 old = cf_pair_find(out, attr);
830                 if (old) {
831                         cf_pair_replace(out, old, value);
832                         talloc_free(value);
833                         continue;
834                 }
835
836                 /*
837                  *      ...or add a new CONF_PAIR
838                  */
839                 cp = cf_pair_alloc(out, attr, value, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
840                 if (!cp) {
841                         cf_log_err_cs(out, "Failed allocing pair \"%s\" = \"%s\"", attr, value);
842                         talloc_free(value);
843                         return -1;
844                 }
845                 talloc_free(value);
846                 cf_item_add(out, cf_pair_to_item(cp));
847         }
848
849         return 0;
850 }
851
852 /** Allocate a new client from a config section
853  *
854  * @param ctx to allocate new clients in.
855  * @param cs to process as a client.
856  * @param in_server Whether the client should belong to a specific virtual server.
857  * @param with_coa If true and coa_server or coa_pool aren't specified automatically,
858  *      create a coa home_server section and add it to the client CONF_SECTION.
859  * @return new RADCLIENT struct.
860  */
861 RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bool with_coa)
862 {
863         RADCLIENT       *c;
864         char const      *name2;
865
866         name2 = cf_section_name2(cs);
867         if (!name2) {
868                 cf_log_err_cs(cs, "Missing client name");
869                 return NULL;
870         }
871
872         /*
873          *      The size is fine.. Let's create the buffer
874          */
875         c = talloc_zero(ctx, RADCLIENT);
876         c->cs = cs;
877
878         memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
879         cl_netmask = 255;
880
881         if (cf_section_parse(cs, c, client_config) < 0) {
882                 cf_log_err_cs(cs, "Error parsing client section");
883         error:
884                 client_free(c);
885 #ifdef WITH_TCP
886                 hs_proto = NULL;
887                 cl_srcipaddr = NULL;
888 #endif
889
890                 return NULL;
891         }
892
893         /*
894          *      Global clients can set servers to use, per-server clients cannot.
895          */
896         if (in_server && c->server) {
897                 cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server");
898                 goto error;
899         }
900
901         /*
902          *      Allow the old method to specify "netmask".  Just using "1.2.3.4" means it's a /32.
903          */
904         if (cl_netmask != 255) {
905                 if ((cl_ipaddr.prefix != cl_netmask) &&
906                     (((cl_ipaddr.af == AF_INET) && cl_ipaddr.prefix != 32) ||
907                      ((cl_ipaddr.af == AF_INET6) && cl_ipaddr.prefix != 128))) {
908                         cf_log_err_cs(cs, "Clients cannot use 'ipaddr/mask' and 'netmask' at the same time.");
909                         goto error;
910                 }
911
912                 cl_ipaddr.prefix = cl_netmask;
913         }
914
915         /*
916          *      Newer style client definitions with either ipaddr or ipaddr6
917          *      config items.
918          */
919         if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
920                 char buffer[128];
921
922                 /*
923                  *      Sets ipv4/ipv6 address and prefix.
924                  */
925                 c->ipaddr = cl_ipaddr;
926
927                 /*
928                  *      Set the long name to be the result of a reverse lookup on the IP address.
929                  */
930                 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
931                 c->longname = talloc_typed_strdup(c, buffer);
932
933                 /*
934                  *      Set the short name to the name2.
935                  */
936                 if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2);
937         /*
938          *      No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax.
939          */
940         } else {
941                 WARN("No 'ipaddr' or 'ipv4addr' or 'ipv6addr' field found in client %s. "
942                      "Please fix your configuration", name2);
943                 WARN("Support for old-style clients will be removed in a future release");
944
945 #ifdef WITH_TCP
946                 if (cf_pair_find(cs, "proto") != NULL) {
947                         cf_log_err_cs(cs, "Cannot use 'proto' inside of old-style client definition");
948                         goto error;
949                 }
950 #endif
951                 if (fr_pton(&c->ipaddr, name2, -1, AF_UNSPEC, true) < 0) {
952                         cf_log_err_cs(cs, "Failed parsing client name \"%s\" as ip address or hostname: %s", name2,
953                                       fr_strerror());
954                         goto error;
955                 }
956
957                 c->longname = talloc_typed_strdup(c, name2);
958                 if (!c->shortname) c->shortname = talloc_typed_strdup(c, c->longname);
959         }
960
961         c->proto = IPPROTO_UDP;
962         if (hs_proto) {
963                 if (strcmp(hs_proto, "udp") == 0) {
964                         hs_proto = NULL;
965
966 #ifdef WITH_TCP
967                 } else if (strcmp(hs_proto, "tcp") == 0) {
968                         hs_proto = NULL;
969                         c->proto = IPPROTO_TCP;
970 #  ifdef WITH_TLS
971                 } else if (strcmp(hs_proto, "tls") == 0) {
972                         hs_proto = NULL;
973                         c->proto = IPPROTO_TCP;
974                         c->tls_required = true;
975
976                 } else if (strcmp(hs_proto, "radsec") == 0) {
977                         hs_proto = NULL;
978                         c->proto = IPPROTO_TCP;
979                         c->tls_required = true;
980 #  endif
981                 } else if (strcmp(hs_proto, "*") == 0) {
982                         hs_proto = NULL;
983                         c->proto = IPPROTO_IP; /* fake for dual */
984 #endif
985                 } else {
986                         cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto);
987                         goto error;
988                 }
989         }
990
991         /*
992          *      If a src_ipaddr is specified, when we send the return packet
993          *      we will use this address instead of the src from the
994          *      request.
995          */
996         if (cl_srcipaddr) {
997 #ifdef WITH_UDPFROMTO
998                 switch (c->ipaddr.af) {
999                 case AF_INET:
1000                         if (fr_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) {
1001                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
1002                                 goto error;
1003                         }
1004                         break;
1005
1006                 case AF_INET6:
1007                         if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) {
1008                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
1009                                 goto error;
1010                         }
1011                         break;
1012                 default:
1013                         rad_assert(0);
1014                 }
1015 #else
1016                 WARN("Server not built with udpfromto, ignoring client src_ipaddr");
1017 #endif
1018                 cl_srcipaddr = NULL;
1019         }
1020
1021         /*
1022          *      A response_window of zero is OK, and means that it's
1023          *      ignored by the rest of the server timers.
1024          */
1025         if (timerisset(&c->response_window)) {
1026                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000);
1027                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0);
1028                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0);
1029         }
1030
1031 #ifdef WITH_DYNAMIC_CLIENTS
1032         if (c->client_server) {
1033                 c->secret = talloc_typed_strdup(c, "testing123");
1034
1035                 if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) ||
1036                     ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) {
1037                         cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address");
1038                         goto error;
1039                 }
1040
1041                 return c;
1042         }
1043 #endif
1044
1045         if (!c->secret || (c->secret[0] == '\0')) {
1046 #ifdef WITH_DHCP
1047                 char const *value = NULL;
1048                 CONF_PAIR *cp = cf_pair_find(cs, "dhcp");
1049
1050                 if (cp) value = cf_pair_value(cp);
1051
1052                 /*
1053                  *      Secrets aren't needed for DHCP.
1054                  */
1055                 if (value && (strcmp(value, "yes") == 0)) return c;
1056 #endif
1057
1058 #ifdef WITH_TLS
1059                 /*
1060                  *      If the client is TLS only, the secret can be
1061                  *      omitted.  When omitted, it's hard-coded to
1062                  *      "radsec".  See RFC 6614.
1063                  */
1064                 if (c->tls_required) {
1065                         c->secret = talloc_typed_strdup(cs, "radsec");
1066                 } else
1067 #endif
1068
1069                 {
1070                         cf_log_err_cs(cs, "secret must be at least 1 character long");
1071                         goto error;
1072                 }
1073         }
1074
1075 #ifdef WITH_COA
1076         {
1077                 CONF_PAIR *cp;
1078
1079                 /*
1080                  *      Point the client to the home server pool, OR to the
1081                  *      home server.  This gets around the problem of figuring
1082                  *      out which port to use.
1083                  */
1084                 cp = cf_pair_find(cs, "coa_server");
1085                 if (cp) {
1086                         c->coa_name = cf_pair_value(cp);
1087                         c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA);
1088                         if (!c->coa_pool) {
1089                                 c->coa_server = home_server_byname(c->coa_name, HOME_TYPE_COA);
1090                         }
1091                         if (!c->coa_pool && !c->coa_server) {
1092                                 cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name);
1093                                 goto error;
1094                         }
1095                 /*
1096                  *      If we're implicitly adding a CoA home server for
1097                  *      every client, or there's a server subsection,
1098                  *      create a home server CONF_SECTION and then parse
1099                  *      it into a home_server_t.
1100                  */
1101                 } else if (with_coa || cf_section_sub_find(cs, "coa_server")) {
1102                         CONF_SECTION *server;
1103                         home_server_t *home;
1104
1105                         if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix != 32)) ||
1106                             ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix != 128))) {
1107                                 WARN("Subnets not supported for home servers.  "
1108                                      "Not adding client %s as home_server", name2);
1109                                 goto done_coa;
1110                         }
1111
1112                         server = home_server_cs_afrom_client(cs);
1113                         if (!server) goto error;
1114
1115                         /*
1116                          *      Must be allocated in the context of the client,
1117                          *      as allocating using the context of the
1118                          *      realm_config_t without a mutex, by one of the
1119                          *      workers, would be bad.
1120                          */
1121                         home = home_server_afrom_cs(NULL, NULL, server);
1122                         if (!home) {
1123                                 talloc_free(server);
1124                                 goto error;
1125                         }
1126
1127                         rad_assert(home->type == HOME_TYPE_COA);
1128
1129                         c->coa_server = home;
1130                         c->defines_coa_server = true;
1131                 }
1132         }
1133 done_coa:
1134 #endif
1135
1136 #ifdef WITH_TCP
1137         if ((c->proto == IPPROTO_TCP) || (c->proto == IPPROTO_IP)) {
1138                 if ((c->limit.idle_timeout > 0) && (c->limit.idle_timeout < 5))
1139                         c->limit.idle_timeout = 5;
1140                 if ((c->limit.lifetime > 0) && (c->limit.lifetime < 5))
1141                         c->limit.lifetime = 5;
1142                 if ((c->limit.lifetime > 0) && (c->limit.idle_timeout > c->limit.lifetime))
1143                         c->limit.idle_timeout = 0;
1144         }
1145 #endif
1146
1147         return c;
1148 }
1149
1150 /** Add a client from a result set (SQL)
1151  *
1152  * @todo This function should die. SQL should use client_afrom_cs.
1153  *
1154  * @param ctx Talloc context.
1155  * @param identifier Client IP Address / IPv4 subnet / IPv6 subnet / FQDN.
1156  * @param secret Client secret.
1157  * @param shortname Client friendly name.
1158  * @param type NAS-Type.
1159  * @param server Virtual-Server to associate clients with.
1160  * @param require_ma If true all packets from client must include a message-authenticator.
1161  * @return The new client, or NULL on error.
1162  */
1163 RADCLIENT *client_afrom_query(TALLOC_CTX *ctx, char const *identifier, char const *secret,
1164                               char const *shortname, char const *type, char const *server, bool require_ma)
1165 {
1166         RADCLIENT *c;
1167         char buffer[128];
1168
1169         rad_assert(identifier);
1170         rad_assert(secret);
1171
1172         c = talloc_zero(ctx, RADCLIENT);
1173
1174         if (fr_pton(&c->ipaddr, identifier, -1, AF_UNSPEC, true) < 0) {
1175                 ERROR("%s", fr_strerror());
1176                 talloc_free(c);
1177
1178                 return NULL;
1179         }
1180
1181 #ifdef WITH_DYNAMIC_CLIENTS
1182         c->dynamic = true;
1183 #endif
1184         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1185         c->longname = talloc_typed_strdup(c, buffer);
1186
1187         /*
1188          *      Other values (secret, shortname, nas_type, virtual_server)
1189          */
1190         c->secret = talloc_typed_strdup(c, secret);
1191         if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
1192         if (type) c->nas_type = talloc_typed_strdup(c, type);
1193         if (server) c->server = talloc_typed_strdup(c, server);
1194         c->message_authenticator = require_ma;
1195
1196         return c;
1197 }
1198
1199 /** Create a new client, consuming all attributes in the control list of the request
1200  *
1201  * @param clients list to add new client to.
1202  * @param request Fake request.
1203  * @return a new client on success, else NULL on error.
1204  */
1205 RADCLIENT *client_afrom_request(RADCLIENT_LIST *clients, REQUEST *request)
1206 {
1207         static int      cnt;
1208         int             i, *pi;
1209         char            **p;
1210         RADCLIENT       *c;
1211         CONF_PAIR       *cp = NULL;
1212         char            buffer[128];
1213
1214         vp_cursor_t     cursor;
1215         VALUE_PAIR      *vp = NULL;
1216
1217         if (!clients || !request) return NULL;
1218
1219         snprintf(buffer, sizeof(buffer), "dynamic%i", cnt++);
1220
1221         c = talloc_zero(clients, RADCLIENT);
1222         c->cs = cf_section_alloc(NULL, "client", buffer);
1223         talloc_steal(c, c->cs);
1224         c->ipaddr.af = AF_UNSPEC;
1225         c->src_ipaddr.af = AF_UNSPEC;
1226
1227         fr_cursor_init(&cursor, &request->config);
1228
1229         RDEBUG2("Converting control list to client fields");
1230         RINDENT();
1231         for (i = 0; dynamic_config[i].name != NULL; i++) {
1232                 DICT_ATTR const *da;
1233                 char *strvalue = NULL;
1234
1235                 da = dict_attrbyname(dynamic_config[i].name);
1236                 if (!da) {
1237                         RERROR("Cannot add client %s: attribute \"%s\" is not in the dictionary",
1238                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1239                                dynamic_config[i].name);
1240                 error:
1241                         REXDENT();
1242                         talloc_free(vp);
1243                         client_free(c);
1244                         return NULL;
1245                 }
1246
1247                 fr_cursor_first(&cursor);
1248                 if (!fr_cursor_next_by_da(&cursor, da, TAG_ANY)) {
1249                         /*
1250                          *      Not required.  Skip it.
1251                          */
1252                         if (!dynamic_config[i].dflt) continue;
1253
1254                         RERROR("Cannot add client %s: Required attribute \"%s\" is missing",
1255                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1256                                dynamic_config[i].name);
1257                         goto error;
1258                 }
1259                 vp = fr_cursor_remove(&cursor);
1260
1261                 /*
1262                  *      Freed at the same time as the vp.
1263                  */
1264                 strvalue = vp_aprints_value(vp, vp, '\'');
1265
1266                 switch (dynamic_config[i].type) {
1267                 case PW_TYPE_IPV4_ADDR:
1268                         if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) {
1269                                 c->ipaddr.af = AF_INET;
1270                                 c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1271                                 c->ipaddr.prefix = 32;
1272                                 cp = cf_pair_alloc(c->cs, "ipv4addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1273                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) {
1274 #ifdef WITH_UDPFROMTO
1275                                 RDEBUG2("src_ipaddr = %s", strvalue);
1276                                 c->src_ipaddr.af = AF_INET;
1277                                 c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1278                                 c->src_ipaddr.prefix = 32;
1279                                 cp = cf_pair_alloc(c->cs, "src_ipaddr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1280 #else
1281                                 RWARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address");
1282 #endif
1283                         }
1284
1285                         break;
1286
1287                 case PW_TYPE_IPV6_ADDR:
1288                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) {
1289                                 c->ipaddr.af = AF_INET6;
1290                                 c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1291                                 c->ipaddr.prefix = 128;
1292                                 cp = cf_pair_alloc(c->cs, "ipv6addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1293                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) {
1294 #ifdef WITH_UDPFROMTO
1295                                 c->src_ipaddr.af = AF_INET6;
1296                                 c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1297                                 c->src_ipaddr.prefix = 128;
1298                                 cp = cf_pair_alloc(c->cs, "src_addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1299 #else
1300                                 RWARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address");
1301 #endif
1302                         }
1303
1304                         break;
1305
1306                 case PW_TYPE_IPV4_PREFIX:
1307                         if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) {
1308                                 c->ipaddr.af = AF_INET;
1309                                 memcpy(&c->ipaddr.ipaddr.ip4addr, &vp->vp_ipv4prefix[2],
1310                                        sizeof(c->ipaddr.ipaddr.ip4addr.s_addr));
1311                                 fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f));
1312                                 cp = cf_pair_alloc(c->cs, "ipv4addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1313                         }
1314
1315                         break;
1316
1317                 case PW_TYPE_IPV6_PREFIX:
1318                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) {
1319                                 c->ipaddr.af = AF_INET6;
1320                                 memcpy(&c->ipaddr.ipaddr.ip6addr, &vp->vp_ipv6prefix[2],
1321                                        sizeof(c->ipaddr.ipaddr.ip6addr));
1322                                 fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]);
1323                                 cp = cf_pair_alloc(c->cs, "ipv6addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1324                         }
1325
1326                         break;
1327
1328                 case PW_TYPE_STRING:
1329                 {
1330                         CONF_PARSER const *parse;
1331
1332                         /*
1333                          *      Cache pointer to CONF_PAIR buffer in RADCLIENT struct
1334                          */
1335                         p = (char **) ((char *) c + dynamic_config[i].offset);
1336                         if (*p) TALLOC_FREE(*p);
1337                         if (!vp->vp_strvalue[0]) break;
1338
1339                         /*
1340                          *      We could reuse the CONF_PAIR buff, this just keeps things
1341                          *      consistent between client_afrom_cs, and client_afrom_query.
1342                          */
1343                         *p = talloc_strdup(c, strvalue);
1344
1345                         /*
1346                          *      This is fairly nasty... In order to figure out the CONF_PAIR
1347                          *      name associated with a field, find offsets that match between
1348                          *      the dynamic_config CONF_PARSER table, and the client_config
1349                          *      CONF_PARSER table.
1350                          *
1351                          *      This is so that things that expect to find CONF_PAIRs in the
1352                          *      client CONF_SECTION for fields like 'nas_type' can.
1353                          */
1354                         for (parse = client_config; parse->name; parse++) {
1355                                 if (parse->offset == dynamic_config[i].offset) break;
1356                         }
1357                         rad_assert(parse);
1358
1359                         cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
1360                 }
1361                         break;
1362
1363                 case PW_TYPE_BOOLEAN:
1364                 {
1365                         CONF_PARSER const *parse;
1366
1367                         pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset));
1368                         *pi = vp->vp_integer;
1369
1370                         /*
1371                          *      Same nastiness as above.
1372                          */
1373                         for (parse = client_config; parse->name; parse++) {
1374                                 if (parse->offset == dynamic_config[i].offset) break;
1375                         }
1376                         rad_assert(parse);
1377
1378                         cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1379                 }
1380                         break;
1381
1382                 default:
1383                         goto error;
1384                 }
1385
1386                 if (!cp) {
1387                         RERROR("Error creating equivalent conf pair for %s", vp->da->name);
1388                         goto error;
1389                 }
1390
1391                 if (cf_pair_attr_type(cp) == T_SINGLE_QUOTED_STRING) {
1392                         RDEBUG2("%s = '%s'", cf_pair_attr(cp), cf_pair_value(cp));
1393                 } else {
1394                         RDEBUG2("%s = %s", cf_pair_attr(cp), cf_pair_value(cp));
1395                 }
1396                 cf_pair_add(c->cs, cp);
1397
1398                 talloc_free(vp);
1399         }
1400
1401         fr_cursor_first(&cursor);
1402         vp = fr_cursor_remove(&cursor);
1403         if (vp) {
1404                 do {
1405                         char *value;
1406
1407                         value = vp_aprints_value(vp, vp, '\'');
1408                         if (!value) {
1409                                 ERROR("Failed stringifying value of &control:%s", vp->da->name);
1410                                 goto error;
1411                         }
1412
1413                         if (vp->da->type == PW_TYPE_STRING) {
1414                                 RDEBUG2("%s = '%s'", vp->da->name, value);
1415                                 cp = cf_pair_alloc(c->cs, vp->da->name, value, T_OP_SET,
1416                                                    T_BARE_WORD, T_SINGLE_QUOTED_STRING);
1417                         } else {
1418                                 RDEBUG2("%s = %s", vp->da->name, value);
1419                                 cp = cf_pair_alloc(c->cs, vp->da->name, value, T_OP_SET,
1420                                                    T_BARE_WORD, T_BARE_WORD);
1421                         }
1422                         cf_pair_add(c->cs, cp);
1423
1424                         talloc_free(vp);
1425                 } while ((vp = fr_cursor_remove(&cursor)));
1426         }
1427         REXDENT();
1428
1429         if (c->ipaddr.af == AF_UNSPEC) {
1430                 RERROR("Cannot add client %s: No IP address was specified.",
1431                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1432
1433                 goto error;
1434         }
1435
1436         {
1437                 fr_ipaddr_t addr;
1438
1439                 /*
1440                  *      Need to apply the same mask as we set for the client
1441                  *      else clients created with FreeRADIUS-Client-IPv6-Prefix
1442                  *      or FreeRADIUS-Client-IPv4-Prefix will fail this check.
1443                  */
1444                 addr = request->packet->src_ipaddr;
1445                 fr_ipaddr_mask(&addr, c->ipaddr.prefix);
1446                 if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) {
1447                         char buf2[128];
1448
1449                         RERROR("Cannot add client %s: Not in specified subnet %s/%i",
1450                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1451                                ip_ntoh(&c->ipaddr, buf2, sizeof(buf2)), c->ipaddr.prefix);
1452                         goto error;
1453                 }
1454         }
1455
1456         if (!c->secret || !*c->secret) {
1457                 RERROR("Cannot add client %s: No secret was specified",
1458                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1459                 goto error;
1460         }
1461
1462         if (!client_add_dynamic(clients, request->client, c)) {
1463                 return NULL;
1464         }
1465
1466         if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) {
1467                 RERROR("Cannot add client %s: Client IP and src address are different IP version",
1468                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1469
1470                 goto error;
1471         }
1472
1473         return c;
1474 }
1475
1476 /*
1477  *      Read a client definition from the given filename.
1478  */
1479 RADCLIENT *client_read(char const *filename, int in_server, int flag)
1480 {
1481         char const *p;
1482         RADCLIENT *c;
1483         CONF_SECTION *cs;
1484         char buffer[256];
1485
1486         if (!filename) return NULL;
1487
1488         cs = cf_section_alloc(NULL, "main", NULL);
1489         if (!cs) return NULL;
1490
1491         if (cf_file_read(cs, filename) < 0) {
1492                 talloc_free(cs);
1493                 return NULL;
1494         }
1495
1496         cs = cf_section_sub_find(cs, "client");
1497         if (!cs) {
1498                 ERROR("No \"client\" section found in client file");
1499                 return NULL;
1500         }
1501
1502         c = client_afrom_cs(cs, cs, in_server, false);
1503         if (!c) return NULL;
1504
1505         p = strrchr(filename, FR_DIR_SEP);
1506         if (p) {
1507                 p++;
1508         } else {
1509                 p = filename;
1510         }
1511
1512         if (!flag) return c;
1513
1514         /*
1515          *      Additional validations
1516          */
1517         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1518         if (strcmp(p, buffer) != 0) {
1519                 ERROR("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p);
1520                 client_free(c);
1521                 return NULL;
1522         }
1523
1524         return c;
1525 }
1526 #endif
1527