2 * client.c Read clients into memory.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/rad_assert.h>
35 #ifdef WITH_DYNAMIC_CLIENTS
41 struct radclient_list {
43 * FIXME: One set of trees for IPv4, and another for IPv6?
45 rbtree_t *trees[129]; /* for 0..128, inclusive. */
51 static rbtree_t *tree_num = NULL; /* client numbers 0..N */
52 static int tree_num_max = 0;
54 static RADCLIENT_LIST *root_clients = NULL;
56 #ifdef WITH_DYNAMIC_CLIENTS
57 static fr_fifo_t *deleted_clients = NULL;
61 * Callback for freeing a client.
63 void client_free(RADCLIENT *client)
67 #ifdef WITH_DYNAMIC_CLIENTS
68 if (client->dynamic == 2) {
71 if (!deleted_clients) {
72 deleted_clients = fr_fifo_create(1024,
73 (void *) client_free);
74 if (!deleted_clients) return; /* MEMLEAK */
78 * Mark it as in the fifo, and remember when we
82 client->created = now = time(NULL); /* re-set it */
83 fr_fifo_push(deleted_clients, client);
86 * Peek at the head of the fifo. If it might
87 * still be in use, return. Otherwise, pop it
88 * from the queue and delete it.
90 client = fr_fifo_peek(deleted_clients);
91 if ((client->created + 120) >= now) return;
93 client = fr_fifo_pop(deleted_clients);
94 rad_assert(client != NULL);
102 * Callback for comparing two clients.
104 static int client_ipaddr_cmp(void const *one, void const *two)
106 RADCLIENT const *a = one;
107 RADCLIENT const *b = two;
110 return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
114 rcode = fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
115 if (rcode != 0) return rcode;
120 if ((a->proto == IPPROTO_IP) ||
121 (b->proto == IPPROTO_IP)) return 0;
123 return (a->proto - b->proto);
128 static int client_num_cmp(void const *one, void const *two)
130 RADCLIENT const *a = one;
131 RADCLIENT const *b = two;
133 return (a->number - b->number);
138 * Free a RADCLIENT list.
140 void clients_free(RADCLIENT_LIST *clients)
144 if (!clients) clients = root_clients;
145 if (!clients) return; /* Clients may not have been initialised yet */
147 for (i = 0; i <= 128; i++) {
148 if (clients->trees[i]) rbtree_free(clients->trees[i]);
149 clients->trees[i] = NULL;
152 if (clients == root_clients) {
154 if (tree_num) rbtree_free(tree_num);
161 #ifdef WITH_DYNAMIC_CLIENTS
163 * FIXME: No fr_fifo_delete()
167 talloc_free(clients);
171 * Return a new, initialized, set of clients.
173 RADCLIENT_LIST *clients_init(CONF_SECTION *cs)
175 RADCLIENT_LIST *clients = talloc_zero(cs, RADCLIENT_LIST);
177 if (!clients) return NULL;
179 clients->min_prefix = 128;
185 * Add a client to the tree.
187 int client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
190 char buffer[INET6_ADDRSTRLEN + 3];
197 * Hack to fixup wildcard clients
199 if (is_wildcard(&client->ipaddr)) client->ipaddr.prefix = 0;
201 fr_ntop(buffer, sizeof(buffer), &client->ipaddr);
202 DEBUG3("Adding client %s (%s) to prefix tree %i", buffer, client->longname, client->ipaddr.prefix);
205 * If "clients" is NULL, it means add to the global list.
209 * Initialize it, if not done already.
212 root_clients = clients_init(NULL);
213 if (!root_clients) return 0;
215 clients = root_clients;
219 * Create a tree for it.
221 if (!clients->trees[client->ipaddr.prefix]) {
222 clients->trees[client->ipaddr.prefix] = rbtree_create(clients, client_ipaddr_cmp, NULL, 0);
223 if (!clients->trees[client->ipaddr.prefix]) {
228 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
231 * Cannot insert the same client twice.
233 old = rbtree_finddata(clients->trees[client->ipaddr.prefix], client);
236 * If it's a complete duplicate, then free the new
237 * one, and return "OK".
239 if ((fr_ipaddr_cmp(&old->ipaddr, &client->ipaddr) == 0) &&
240 (old->ipaddr.prefix == client->ipaddr.prefix) &&
241 namecmp(longname) && namecmp(secret) &&
242 namecmp(shortname) && namecmp(nas_type) &&
243 namecmp(login) && namecmp(password) && namecmp(server) &&
244 #ifdef WITH_DYNAMIC_CLIENTS
245 (old->lifetime == client->lifetime) &&
246 namecmp(client_server) &&
250 (old->coa_server == client->coa_server) &&
251 (old->coa_pool == client->coa_pool) &&
253 (old->message_authenticator == client->message_authenticator)) {
254 WARN("Ignoring duplicate client %s", client->longname);
259 ERROR("Failed to add duplicate client %s",
266 * Other error adding client: likely is fatal.
268 if (!rbtree_insert(clients->trees[client->ipaddr.prefix], client)) {
274 tree_num = rbtree_create(clients, client_num_cmp, NULL, 0);
277 #ifdef WITH_DYNAMIC_CLIENTS
279 * More catching of clients added by rlm_sql.
281 * The sql modules sets the dynamic flag BEFORE calling
282 * us. The client_from_request() function sets it AFTER
285 if (client->dynamic && (client->lifetime == 0)) {
289 * If there IS an enclosing network,
290 * inherit the lifetime from it.
292 network = client_find(clients, &client->ipaddr, client->proto);
294 client->lifetime = network->lifetime;
299 client->number = tree_num_max;
301 if (tree_num) rbtree_insert(tree_num, client);
304 if (client->ipaddr.prefix < clients->min_prefix) {
305 clients->min_prefix = client->ipaddr.prefix;
308 (void) talloc_steal(clients, client); /* reparent it */
314 #ifdef WITH_DYNAMIC_CLIENTS
315 void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client)
319 if (!clients) clients = root_clients;
321 if (!client->dynamic) return;
323 rad_assert(client->ipaddr.prefix <= 128);
325 client->dynamic = 2; /* signal to client_free */
328 rbtree_deletebydata(tree_num, client);
330 rbtree_deletebydata(clients->trees[client->ipaddr.prefix], client);
336 * Find a client in the RADCLIENTS list by number.
337 * This is a support function for the statistics code.
339 RADCLIENT *client_findbynumber(RADCLIENT_LIST const *clients, int number)
341 if (!clients) clients = root_clients;
343 if (!clients) return NULL;
345 if (number >= tree_num_max) return NULL;
350 myclient.number = number;
352 return rbtree_finddata(tree_num, &myclient);
358 RADCLIENT *client_findbynumber(UNUSED const RADCLIENT_LIST *clients, UNUSED int number)
366 * Find a client in the RADCLIENTS list.
368 RADCLIENT *client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto)
370 int32_t i, max_prefix;
373 if (!clients) clients = root_clients;
375 if (!clients || !ipaddr) return NULL;
377 switch (ipaddr->af) {
390 for (i = max_prefix; i >= (int32_t) clients->min_prefix; i--) {
393 myclient.ipaddr = *ipaddr;
394 myclient.proto = proto;
395 fr_ipaddr_mask(&myclient.ipaddr, i);
397 if (!clients->trees[i]) continue;
399 data = rbtree_finddata(clients->trees[i], &myclient);
400 if (data) return data;
407 * Old wrapper for client_find
409 RADCLIENT *client_find_old(fr_ipaddr_t const *ipaddr)
411 return client_find(root_clients, ipaddr, IPPROTO_UDP);
414 static fr_ipaddr_t cl_ipaddr;
415 static char const *cl_srcipaddr = NULL;
416 static uint32_t cl_prefix;
418 static char const *hs_proto = NULL;
422 static CONF_PARSER limit_config[] = {
423 { "max_connections", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.max_connections), "16" },
425 { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.lifetime), "0" },
427 { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.idle_timeout), "30" },
429 { NULL, -1, 0, NULL, NULL } /* end the list */
433 static const CONF_PARSER client_config[] = {
434 { "ipaddr", FR_CONF_POINTER(PW_TYPE_IP_PREFIX, &cl_ipaddr), NULL },
435 { "ipv4addr", FR_CONF_POINTER(PW_TYPE_IPV4_PREFIX, &cl_ipaddr), NULL },
436 { "ipv6addr", FR_CONF_POINTER(PW_TYPE_IPV6_PREFIX, &cl_ipaddr), NULL },
437 { "netmask", FR_CONF_POINTER(PW_TYPE_INTEGER, &cl_prefix), NULL },
439 { "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
441 { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
443 { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
444 { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
445 { "nastype", FR_CONF_OFFSET(PW_TYPE_DEPRECATED | PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
446 { "nas_type", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
447 { "login", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, login), NULL },
448 { "password", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, password), NULL },
449 { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
450 { "response_window", FR_CONF_OFFSET(PW_TYPE_TIMEVAL, RADCLIENT, response_window), NULL },
453 { "proto", FR_CONF_POINTER(PW_TYPE_STRING, &hs_proto), NULL },
454 { "limit", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) limit_config },
457 #ifdef WITH_DYNAMIC_CLIENTS
458 { "dynamic_clients", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, client_server), NULL },
459 { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, lifetime), NULL },
460 { "rate_limit", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, rate_limit), NULL },
464 { "coa_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, coa_name), NULL },
467 { NULL, -1, 0, NULL, NULL }
471 static RADCLIENT *client_parse(CONF_SECTION *cs, int in_server)
476 name2 = cf_section_name2(cs);
478 cf_log_err_cs(cs, "Missing client name");
483 * The size is fine.. Let's create the buffer
485 c = talloc_zero(cs, RADCLIENT);
488 memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
490 if (cf_section_parse(cs, c, client_config) < 0) {
491 cf_log_err_cs(cs, "Error parsing client section");
503 * Global clients can set servers to use, per-server clients cannot.
505 if (in_server && c->server) {
506 cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server");
511 * Newer style client definitions with either ipaddr or ipaddr6
514 if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
518 * Sets ipv4/ipv6 address and prefix.
520 c->ipaddr = cl_ipaddr;
523 * Set the long name to be the result of a reverse lookup on the IP address.
525 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
526 c->longname = talloc_typed_strdup(c, buffer);
529 * Set the short name to the name2.
531 if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2);
533 * No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax.
536 WARN("No 'ipaddr' or 'ipv4addr' or 'ipv6addr' field found in client %s. Please fix your configuration",
538 WARN("Support for old-style clients will be removed in a future release");
541 if (cf_pair_find(cs, "proto") != NULL) {
542 cf_log_err_cs(cs, "Cannot use 'proto' inside of old-style client definition");
546 if (fr_pton(&c->ipaddr, name2, 0, true) < 0) {
547 cf_log_err_cs(cs, "Failed parsing client name \"%s\" as ip address or hostname: %s", name2,
552 c->longname = talloc_typed_strdup(c, name2);
553 if (!c->shortname) c->shortname = talloc_typed_strdup(c, c->longname);
557 * Prefix override (this needs to die)
559 if (cl_prefix != 256) {
560 WARN("'netmask' field found in client %s is deprecated, use CIDR notation instead. "
561 "Please fix your configuration", name2);
562 WARN("Support for 'netmask' will be removed in a future release");
564 switch (c->ipaddr.af) {
566 if (cl_prefix > 32) {
567 cf_log_err_cs(cs, "Invalid IPv4 mask length \"%i\". Should be between 0-32",
574 if (cl_prefix > 128) {
575 cf_log_err_cs(cs, "Invalid IPv6 mask length \"%i\". Should be between 0-128",
584 fr_ipaddr_mask(&c->ipaddr, cl_prefix);
587 c->proto = IPPROTO_UDP;
589 if (strcmp(hs_proto, "udp") == 0) {
593 } else if (strcmp(hs_proto, "tcp") == 0) {
595 c->proto = IPPROTO_TCP;
597 } else if (strcmp(hs_proto, "tls") == 0) {
599 c->proto = IPPROTO_TCP;
600 c->tls_required = true;
602 } else if (strcmp(hs_proto, "radsec") == 0) {
604 c->proto = IPPROTO_TCP;
605 c->tls_required = true;
607 } else if (strcmp(hs_proto, "*") == 0) {
609 c->proto = IPPROTO_IP; /* fake for dual */
612 cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto);
618 * If a src_ipaddr is specified, when we send the return packet
619 * we will use this address instead of the src from the
623 #ifdef WITH_UDPFROMTO
624 switch (c->ipaddr.af) {
626 if (fr_pton4(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 0) {
627 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
633 if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, 0, true, false) < 0) {
634 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
642 WARN("Server not built with udpfromto, ignoring client src_ipaddr");
648 * A response_window of zero is OK, and means that it's
649 * ignored by the rest of the server timers.
651 if (timerisset(&c->response_window)) {
652 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000);
653 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0);
654 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0);
657 #ifdef WITH_DYNAMIC_CLIENTS
658 if (c->client_server) {
659 c->secret = talloc_typed_strdup(c, "testing123");
661 if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) ||
662 ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) {
663 cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address");
671 if (!c->secret || (c->secret[0] == '\0')) {
673 char const *value = NULL;
674 CONF_PAIR *cp = cf_pair_find(cs, "dhcp");
676 if (cp) value = cf_pair_value(cp);
679 * Secrets aren't needed for DHCP.
681 if (value && (strcmp(value, "yes") == 0)) return c;
686 * If the client is TLS only, the secret can be
687 * omitted. When omitted, it's hard-coded to
688 * "radsec". See RFC 6614.
690 if (c->tls_required) {
691 c->secret = talloc_typed_strdup(cs, "radsec");
697 "secret must be at least 1 character long");
704 * Point the client to the home server pool, OR to the
705 * home server. This gets around the problem of figuring
706 * out which port to use.
709 c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA);
711 c->coa_server = home_server_byname(c->coa_name,
714 if (!c->coa_pool && !c->coa_server) {
715 cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name);
722 if ((c->proto == IPPROTO_TCP) || (c->proto == IPPROTO_IP)) {
723 if ((c->limit.idle_timeout > 0) && (c->limit.idle_timeout < 5))
724 c->limit.idle_timeout = 5;
725 if ((c->limit.lifetime > 0) && (c->limit.lifetime < 5))
726 c->limit.lifetime = 5;
727 if ((c->limit.lifetime > 0) && (c->limit.idle_timeout > c->limit.lifetime))
728 c->limit.idle_timeout = 0;
737 * Create the linked list of clients from the new configuration
738 * type. This way we don't have to change too much in the other
742 RADCLIENT_LIST *clients_parse_section(CONF_SECTION *section, bool tls_required)
744 RADCLIENT_LIST *clients_parse_section(CONF_SECTION *section, UNUSED bool tls_required)
747 bool global = false, in_server = false;
750 RADCLIENT_LIST *clients;
753 * Be forgiving. If there's already a clients, return
754 * it. Otherwise create a new one.
756 clients = cf_data_find(section, "clients");
757 if (clients) return clients;
759 clients = clients_init(section);
760 if (!clients) return NULL;
762 if (cf_top_section(section) == section) global = true;
764 if (strcmp("server", cf_section_name1(section)) == 0) in_server = true;
767 * Associate the clients structure with the section.
769 if (cf_data_add(section, "clients", clients, NULL) < 0) {
770 cf_log_err_cs(section,
771 "Failed to associate clients with section %s",
772 cf_section_name1(section));
773 clients_free(clients);
777 for (cs = cf_subsection_find_next(section, NULL, "client");
779 cs = cf_subsection_find_next(section, cs, "client")) {
780 c = client_parse(cs, in_server);
787 * TLS clients CANNOT use non-TLS listeners.
788 * non-TLS clients CANNOT use TLS listeners.
790 if (tls_required != c->tls_required) {
791 cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener");
793 clients_free(clients);
799 * FIXME: Add the client as data via cf_data_add,
800 * for migration issues.
803 #ifdef WITH_DYNAMIC_CLIENTS
805 if (c->client_server) {
810 struct stat stat_buf;
814 * Find the directory where individual
815 * client definitions are stored.
817 cp = cf_pair_find(cs, "directory");
818 if (!cp) goto add_client;
820 value = cf_pair_value(cp);
823 "The \"directory\" entry must not be empty");
828 DEBUG("including dynamic clients in %s", value);
830 dir = opendir(value);
832 cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno));
838 * Read the directory, ignoring "." files.
840 while ((dp = readdir(dir)) != NULL) {
844 if (dp->d_name[0] == '.') continue;
847 * Check for valid characters
849 for (p = dp->d_name; *p != '\0'; p++) {
850 if (isalpha((int)*p) ||
853 (*p == '.')) continue;
856 if (*p != '\0') continue;
858 snprintf(buf2, sizeof(buf2), "%s/%s",
861 if ((stat(buf2, &stat_buf) != 0) ||
862 S_ISDIR(stat_buf.st_mode)) continue;
864 dc = client_read(buf2, in_server, true);
867 "Failed reading client file \"%s\"", buf2);
874 * Validate, and add to the list.
876 if (!client_validate(clients, c, dc)) {
882 } /* loop over the directory */
885 #endif /* HAVE_DIRENT_H */
888 #endif /* WITH_DYNAMIC_CLIENTS */
889 if (!client_add(clients, c)) {
891 "Failed to add client %s",
892 cf_section_name2(cs));
900 * Replace the global list of clients with the new one.
901 * The old one is still referenced from the original
902 * configuration, and will be freed when that is freed.
905 root_clients = clients;
911 #ifdef WITH_DYNAMIC_CLIENTS
913 * We overload this structure a lot.
915 static const CONF_PARSER dynamic_config[] = {
916 { "FreeRADIUS-Client-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, ipaddr), NULL },
917 { "FreeRADIUS-Client-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, ipaddr), NULL },
918 { "FreeRADIUS-Client-IP-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV4_PREFIX, RADCLIENT, ipaddr), NULL },
919 { "FreeRADIUS-Client-IPv6-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV6_PREFIX, RADCLIENT, ipaddr), NULL },
920 { "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
921 { "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
923 { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
925 { "FreeRADIUS-Client-Secret", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
926 { "FreeRADIUS-Client-Shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
927 { "FreeRADIUS-Client-NAS-Type", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
928 { "FreeRADIUS-Client-Virtual-Server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
930 { NULL, -1, 0, NULL, NULL }
934 bool client_validate(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
939 * No virtual server defined. Inherit the parent's
942 if (master->server && !c->server) {
943 c->server = talloc_typed_strdup(c, master->server);
947 * If the client network isn't global (not tied to a
948 * virtual server), then ensure that this clients server
949 * is the same as the enclosing networks virtual server.
951 if (master->server &&
952 (strcmp(master->server, c->server) != 0)) {
953 DEBUG("- Cannot add client %s: Virtual server %s is not the same as the virtual server for the network",
954 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->server);
959 if (!client_add(clients, c)) {
960 DEBUG("- Cannot add client %s: Internal error", ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)));
966 * Initialize the remaining fields.
969 c->lifetime = master->lifetime;
970 c->created = time(NULL);
971 c->longname = talloc_typed_strdup(c, c->shortname);
973 DEBUG("- Added client %s with shared secret %s",
974 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)),
984 /** Add a client from a result set (LDAP, SQL, et al)
986 * @param ctx Talloc context.
987 * @param identifier Client IP Address / IPv4 subnet / IPv6 subnet / FQDN.
988 * @param secret Client secret.
989 * @param shortname Client friendly name.
990 * @param type NAS-Type.
991 * @param server Virtual-Server to associate clients with.
992 * @param require_ma If true all packets from client must include a message-authenticator.
993 * @return The new client, or NULL on error.
995 RADCLIENT *client_from_query(TALLOC_CTX *ctx, char const *identifier, char const *secret, char const *shortname,
996 char const *type, char const *server, bool require_ma)
1001 rad_assert(identifier);
1004 c = talloc_zero(ctx, RADCLIENT);
1006 if (fr_pton(&c->ipaddr, identifier, 0, true) < 0) {
1007 ERROR("%s", fr_strerror());
1013 #ifdef WITH_DYNAMIC_CLIENTS
1016 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1017 c->longname = talloc_typed_strdup(c, buffer);
1020 * Other values (secret, shortname, nas_type, virtual_server)
1022 c->secret = talloc_typed_strdup(c, secret);
1023 if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
1024 if (type) c->nas_type = talloc_typed_strdup(c, type);
1025 if (server) c->server = talloc_typed_strdup(c, server);
1026 c->message_authenticator = require_ma;
1031 RADCLIENT *client_from_request(RADCLIENT_LIST *clients, REQUEST *request)
1038 if (!clients || !request) return NULL;
1040 c = talloc_zero(clients, RADCLIENT);
1041 c->cs = request->client->cs;
1042 c->ipaddr.af = AF_UNSPEC;
1043 c->src_ipaddr.af = AF_UNSPEC;
1045 for (i = 0; dynamic_config[i].name != NULL; i++) {
1046 DICT_ATTR const *da;
1049 da = dict_attrbyname(dynamic_config[i].name);
1051 DEBUG("- Cannot add client %s: attribute \"%s\"is not in the dictionary",
1052 ip_ntoh(&request->packet->src_ipaddr,
1053 buffer, sizeof(buffer)),
1054 dynamic_config[i].name);
1060 vp = pairfind(request->config_items, da->attr, da->vendor, TAG_ANY);
1063 * Not required. Skip it.
1065 if (!dynamic_config[i].dflt) continue;
1067 DEBUG("- Cannot add client %s: Required attribute \"%s\" is missing.",
1068 ip_ntoh(&request->packet->src_ipaddr,
1069 buffer, sizeof(buffer)),
1070 dynamic_config[i].name);
1074 switch (dynamic_config[i].type) {
1075 case PW_TYPE_IPV4_ADDR:
1076 if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) {
1077 c->ipaddr.af = AF_INET;
1078 c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1079 c->ipaddr.prefix = 32;
1080 } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) {
1081 #ifdef WITH_UDPFROMTO
1082 c->src_ipaddr.af = AF_INET;
1083 c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1085 WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address");
1091 case PW_TYPE_IPV6_ADDR:
1092 if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) {
1093 c->ipaddr.af = AF_INET6;
1094 c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1095 c->ipaddr.prefix = 128;
1096 } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) {
1097 #ifdef WITH_UDPFROMTO
1098 c->src_ipaddr.af = AF_INET6;
1099 c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1101 WARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address");
1107 case PW_TYPE_IPV4_PREFIX:
1108 if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) {
1109 c->ipaddr.af = AF_INET;
1110 memcpy(&c->ipaddr.ipaddr.ip4addr.s_addr, &(vp->vp_ipv4prefix[2]), sizeof(c->ipaddr.ipaddr.ip4addr.s_addr));
1111 fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f));
1116 case PW_TYPE_IPV6_PREFIX:
1117 if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) {
1118 c->ipaddr.af = AF_INET6;
1119 memcpy(&c->ipaddr.ipaddr.ip6addr, &(vp->vp_ipv6prefix[2]), sizeof(c->ipaddr.ipaddr.ip6addr));
1120 fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]);
1125 case PW_TYPE_STRING:
1126 p = (char **) ((char *) c + dynamic_config[i].offset);
1127 if (*p) talloc_free(*p);
1128 if (vp->vp_strvalue[0]) {
1129 *p = talloc_typed_strdup(c->cs, vp->vp_strvalue);
1135 case PW_TYPE_BOOLEAN:
1136 pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset));
1137 *pi = vp->vp_integer;
1145 if (c->ipaddr.af == AF_UNSPEC) {
1146 DEBUG("- Cannot add client %s: No IP address was specified.",
1147 ip_ntoh(&request->packet->src_ipaddr,
1148 buffer, sizeof(buffer)));
1157 * Need to apply the same mask as we set for the client
1158 * else clients created with FreeRADIUS-Client-IPv6-Prefix
1159 * or FreeRADIUS-Client-IPv4-Prefix will fail this check.
1161 addr = request->packet->src_ipaddr;
1162 fr_ipaddr_mask(&addr, c->ipaddr.prefix);
1163 if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) {
1166 DEBUG("- Cannot add client %s: IP address %s do not match",
1167 ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1168 ip_ntoh(&c->ipaddr, buf2, sizeof(buf2)));
1173 if (!c->secret || !*c->secret) {
1174 DEBUG("- Cannot add client %s: No secret was specified.",
1175 ip_ntoh(&request->packet->src_ipaddr,
1176 buffer, sizeof(buffer)));
1180 if (!client_validate(clients, request->client, c)) {
1184 if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) {
1185 DEBUG("- Cannot add client %s: Client IP and src address are different IP version.",
1186 ip_ntoh(&request->packet->src_ipaddr,
1187 buffer, sizeof(buffer)));
1196 * Read a client definition from the given filename.
1198 RADCLIENT *client_read(char const *filename, int in_server, int flag)
1205 if (!filename) return NULL;
1207 cs = cf_file_read(filename);
1208 if (!cs) return NULL;
1210 cs = cf_section_sub_find(cs, "client");
1212 ERROR("No \"client\" section found in client file");
1216 c = client_parse(cs, in_server);
1217 if (!c) return NULL;
1219 p = strrchr(filename, FR_DIR_SEP);
1226 if (!flag) return c;
1229 * Additional validations
1231 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1232 if (strcmp(p, buffer) != 0) {
1233 DEBUG("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p);