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