27 RCSID(
"$Id: 95a5c55d3a3cc97ce2ec2a34f66600e3550fb718 $")
29 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
30 #include <freeradius-devel/server/cf_file.h>
31 #include <freeradius-devel/server/cf_parse.h>
32 #include <freeradius-devel/server/client.h>
33 #include <freeradius-devel/server/main_config.h>
34 #include <freeradius-devel/server/module.h>
35 #include <freeradius-devel/server/virtual_servers.h>
36 #include <freeradius-devel/unlang/call.h>
38 #include <freeradius-devel/util/debug.h>
39 #include <freeradius-devel/util/base16.h>
40 #include <freeradius-devel/util/misc.h>
41 #include <freeradius-devel/util/sbuff.h>
42 #include <freeradius-devel/util/value.h>
43 #include <freeradius-devel/util/trie.h>
44 #include <freeradius-devel/util/token.h>
70 static int8_t
client_cmp(
void const *one,
void const *two)
77 if (ret != 0)
return ret;
82 if ((a->
proto == IPPROTO_IP) || (b->
proto == IPPROTO_IP))
return 0;
117 if (!clients)
return NULL;
123 if (!clients->v4_udp) {
129 if (!clients->v6_udp) {
135 if (!clients->v4_tcp) {
141 if (!clients->v6_tcp) {
165 if (ipaddr->
af == AF_INET) {
166 if (
proto == IPPROTO_TCP)
return clients->v4_tcp;
168 return clients->v4_udp;
173 if (
proto == IPPROTO_TCP)
return clients->v6_tcp;
175 return clients->v6_udp;
196 if (!client)
return false;
227 if (client->
server != NULL) {
232 ERROR(
"Failed to find configuration section in client. Ignoring 'virtual_server' directive");
238 ERROR(
"Failed to find virtual server %s", client->
server);
247 if (!subcs)
goto global_clients;
257 ERROR(
"Failed to associate clients with virtual server %s", client->
server);
276 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
279 trie = clients_trie(clients, &client->
ipaddr, client->
proto);
336 (void) talloc_steal(clients, client);
355 trie = clients_trie(clients, &client->
ipaddr, client->
proto);
389 if (!clients || !ipaddr)
return NULL;
392 trie = clients_trie(clients, ipaddr,
proto);
397 if (
proto == AF_INET) {
406 for (i = max; i >= 0; i--) {
407 if (!clients->
tree[i])
continue;
409 my_client.
ipaddr = *ipaddr;
475 #define TLS_UNUSED UNUSED
491 if (clients)
return clients;
497 if (!clients)
return NULL;
504 if (
cf_root(section) == section) global =
true;
518 int client_proto = IPPROTO_UDP;
525 cf_log_err(cs,
"'proto' field must have a value");
530 if (strcmp(
value,
"udp") == 0) {
533 }
else if (strcmp(
value,
"tcp") == 0) {
534 client_proto = IPPROTO_TCP;
536 }
else if (strcmp(
value,
"tls") == 0) {
537 client_proto = IPPROTO_TCP;
539 }
else if (strcmp(
value,
"*") == 0) {
540 client_proto = IPPROTO_IP;
554 if ((client_proto != IPPROTO_IP) && (
proto != client_proto))
continue;
576 if (tls_required != c->tls_required) {
577 cf_log_err(cs,
"Client does not have the same TLS configuration as the listener");
671 if (!
value)
continue;
732 talloc_set_name_const(c,
"fr_client_t");
741 cf_log_err(cs,
"Error parsing client section");
758 size_t bin_len, hex_len, converted;
764 hex_len = talloc_array_length(
value) - 3;
765 bin_len = (hex_len / 2) + 1;
770 if (converted < (bin_len - 1)) {
771 cf_log_err(cs,
"Invalid hex string in shared secret");
776 c->
secret = (
char const *) bin;
786 cf_log_err(cs,
"Clients inside of a 'server' section cannot point to a server");
799 }
else if (server_cs) {
831 cf_log_err(cs,
"No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration "
832 "directive found in client %s", name2);
836 c->
proto = IPPROTO_UDP;
841 }
else if (strcmp(
hs_proto,
"tcp") == 0) {
843 c->
proto = IPPROTO_TCP;
845 }
else if (strcmp(
hs_proto,
"tls") == 0) {
847 c->
proto = IPPROTO_TCP;
848 c->tls_required =
true;
851 }
else if (strcmp(
hs_proto,
"*") == 0) {
853 c->
proto = IPPROTO_IP;
905 if (c->tls_required) {
910 if ((c->
proto == IPPROTO_TCP) || (c->
proto == IPPROTO_IP)) {
937 if (!request)
return NULL;
943 RERROR(
"Failed to generate dynamic client name");
947 fr_sbuff_set_to_start(tmp);
951 RDEBUG2(
"Converting &control.FreeRADIUS-Client-* to client {...} section");
962 switch (
vp->
da->attr) {
963 case FR_FREERADIUS_CLIENT_IP_ADDRESS:
966 fr_sbuff_set_to_start(tmp);
968 RERROR(
"Failed to convert %pP to string",
vp);
976 case FR_FREERADIUS_CLIENT_IP_PREFIX:
980 case FR_FREERADIUS_CLIENT_IPV6_ADDRESS:
984 case FR_FREERADIUS_CLIENT_IPV6_PREFIX:
988 case FR_FREERADIUS_CLIENT_SECRET:
993 case FR_FREERADIUS_CLIENT_NAS_TYPE:
998 case FR_FREERADIUS_CLIENT_SHORTNAME:
1003 case FR_FREERADIUS_CLIENT_SRC_IP_ADDRESS:
1004 attr =
"src_ipaddr";
1007 case FR_FREERADIUS_CLIENT_REQUIRE_MA:
1008 attr =
"require_message_authenticator";
1011 case FR_FREERADIUS_CLIENT_LIMIT_PROXY_STATE:
1012 attr =
"limit_proxy_state";
1015 case FR_FREERADIUS_CLIENT_TRACK_CONNECTIONS:
1016 attr =
"track_connections";
1020 attr =
vp->
da->name;
1021 fr_sbuff_set_to_start(tmp);
1030 RERROR(
"Error creating equivalent conf pair for %s",
vp->
da->name);
1067 if (!filename)
return NULL;
1070 if (!cs)
return NULL;
1079 ERROR(
"No \"client\" section found in client file");
1084 if (!c)
return NULL;
1085 talloc_steal(cs, c);
1087 p = strrchr(filename, FR_DIR_SEP);
1094 if (!check_dns)
return c;
1100 if (strcmp(p,
buffer) != 0) {
1101 ERROR(
"Invalid client definition in %s: IP address %s does not match name %s", filename,
buffer, p);
static int const char char buffer[256]
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
int cf_file_read(CONF_SECTION *cs, char const *filename)
int cf_section_pass2(CONF_SECTION *cs)
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
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.
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
#define cf_item_add(_parent, _child)
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_item_next(_ci, _curr)
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static bool fr_dict_attr_is_top_level(fr_dict_attr_t const *da)
Return true if this attribute is parented directly off the dictionary root.
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)
char * fr_inet_ntop_prefix(char out[static FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print a fr_ipaddr_t as a CIDR style network prefix.
char const * fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
Perform reverse resolution of an IP address.
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
union fr_ipaddr_t::@130 addr
fr_time_delta_t response_window
How long the client has to respond.
char const * server
Name of the virtual server client is associated with.
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
fr_radius_require_ma_t require_message_authenticator
Require RADIUS message authenticator for incoming packets.
char const * secret
Secret PSK.
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
int(* client_value_cb_t)(char **out, CONF_PAIR const *cp, void *data)
Callback for retrieving values when building client sections.
int proto
Protocol number.
CONF_SECTION * cs
CONF_SECTION that was parsed to generate the client.
char const * longname
Client identifier.
fr_socket_limit_t limit
Connections per client (TCP clients only).
char const * shortname
Client nickname.
bool use_connected
do we use connected sockets for this client
CONF_SECTION * server_cs
Virtual server that the client is associated with.
Describes a host allowed to send packets to the server.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
main_config_t const * main_config
Main server configuration.
fr_time_delta_t max_request_time
How long a request can be processed for before timing out.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask_bits)
size_t fr_radius_limit_proxy_state_table_len
size_t fr_radius_require_ma_table_len
fr_table_num_sorted_t const fr_radius_limit_proxy_state_table[]
fr_table_num_sorted_t const fr_radius_require_ma_table[]
static char const * proto(int id, int porttype)
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
The main red black tree structure.
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
fr_time_delta_t idle_timeout
fr_client_t * client_find(fr_client_list_t const *clients, fr_ipaddr_t const *ipaddr, int proto)
static int8_t client_cmp(void const *one, void const *two)
char const * name
Name of the client list.
fr_client_list_t * client_list_init(CONF_SECTION *cs)
Return a new client list.
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...
fr_client_list_t * client_list_parse_section(CONF_SECTION *section, int proto, TLS_UNUSED bool tls_required)
void client_free(fr_client_t *client)
Free a client.
fr_client_t * client_read(char const *filename, CONF_SECTION *server_cs, bool check_dns)
Read a single client from a file.
static fr_ipaddr_t cl_ipaddr
#define TLS_UNUSED
Create a list of clients from a client section.
fr_client_t * client_from_request(request_t *request)
Search up a list of requests trying to locate one which has a client.
static conf_parser_t limit_config[]
static char const * cl_srcipaddr
static const conf_parser_t client_config[]
static fr_client_list_t * root_clients
Global client list.
void client_list_free(void)
fr_client_t * client_findbynumber(UNUSED const fr_client_list_t *clients, UNUSED int number)
fr_client_t * client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *server_cs, size_t extra)
Allocate a new client from a config section.
void client_delete(fr_client_list_t *clients, fr_client_t *client)
bool client_add(fr_client_list_t *clients, fr_client_t *client)
Add a client to a fr_client_list_t.
fr_client_t * client_afrom_request(TALLOC_CTX *ctx, request_t *request)
Create a new client, consuming all attributes in the control list of the request.
static char const * hs_proto
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int talloc_const_free(void const *ptr)
Free const'd memory.
#define fr_time_delta_lt(_a, _b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_wrap(_time)
#define fr_time_delta_ispos(_a)
static fr_time_delta_t fr_time_delta_from_usec(int64_t usec)
fr_trie_t * fr_trie_alloc(TALLOC_CTX *ctx, fr_trie_key_t get_key, fr_free_t free_data)
Allocate a trie.
void * fr_trie_remove_by_key(fr_trie_t *ft, void const *key, size_t keylen)
Remove a key and return the associated user ctx.
void * fr_trie_match_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Match a key and length in a trie and return user ctx, if any.
int fr_trie_insert_by_key(fr_trie_t *ft, void const *key, size_t keylen, void const *data)
Insert a key and user ctx into a trie.
void * fr_trie_lookup_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Lookup a key in a trie and return user ctx, if any.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
fr_sbuff_escape_rules_t fr_value_escape_single
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
#define fr_box_ipaddr(_val)
static size_t char ** out
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.