27 RCSID(
"$Id: 7b5f3dc09929f5996d10cebad77273d4e595f302 $")
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/trie.h>
67 static int8_t
client_cmp(
void const *one,
void const *two)
74 if (ret != 0)
return ret;
79 if ((a->
proto == IPPROTO_IP) || (b->
proto == IPPROTO_IP))
return 0;
114 if (!clients)
return NULL;
120 if (!clients->v4_udp) {
126 if (!clients->v6_udp) {
132 if (!clients->v4_tcp) {
138 if (!clients->v6_tcp) {
162 if (ipaddr->
af == AF_INET) {
163 if (
proto == IPPROTO_TCP)
return clients->v4_tcp;
165 return clients->v4_udp;
170 if (
proto == IPPROTO_TCP)
return clients->v6_tcp;
172 return clients->v6_udp;
193 if (!client)
return false;
224 if (client->
server != NULL) {
229 ERROR(
"Failed to find configuration section in client. Ignoring 'virtual_server' directive");
235 ERROR(
"Failed to find virtual server %s", client->
server);
244 if (!subcs)
goto global_clients;
254 ERROR(
"Failed to associate clients with virtual server %s", client->
server);
273 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
276 trie = clients_trie(clients, &client->
ipaddr, client->
proto);
333 (void) talloc_steal(clients, client);
352 trie = clients_trie(clients, &client->
ipaddr, client->
proto);
386 if (!clients || !ipaddr)
return NULL;
389 trie = clients_trie(clients, ipaddr,
proto);
394 if (
proto == AF_INET) {
403 for (i = max; i >= 0; i--) {
404 if (!clients->
tree[i])
continue;
406 my_client.
ipaddr = *ipaddr;
464 #define TLS_UNUSED UNUSED
480 if (clients)
return clients;
486 if (!clients)
return NULL;
493 if (
cf_root(section) == section) global =
true;
507 int client_proto = IPPROTO_UDP;
514 cf_log_err(cs,
"'proto' field must have a value");
519 if (strcmp(
value,
"udp") == 0) {
522 }
else if (strcmp(
value,
"tcp") == 0) {
523 client_proto = IPPROTO_TCP;
525 }
else if (strcmp(
value,
"tls") == 0) {
526 client_proto = IPPROTO_TCP;
528 }
else if (strcmp(
value,
"*") == 0) {
529 client_proto = IPPROTO_IP;
543 if ((client_proto != IPPROTO_IP) && (
proto != client_proto))
continue;
565 if (tls_required != c->tls_required) {
566 cf_log_err(cs,
"Client does not have the same TLS configuration as the listener");
660 if (!
value)
continue;
721 talloc_set_name_const(c,
"fr_client_t");
730 cf_log_err(cs,
"Error parsing client section");
747 size_t bin_len, hex_len, converted;
753 hex_len = talloc_array_length(
value) - 3;
754 bin_len = (hex_len / 2) + 1;
759 if (converted < (bin_len - 1)) {
760 cf_log_err(cs,
"Invalid hex string in shared secret");
765 c->
secret = (
char const *) bin;
774 cf_log_err(cs,
"Clients inside of a 'server' section cannot point to a server");
784 }
else if (server_cs) {
816 cf_log_err(cs,
"No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration "
817 "directive found in client %s", name2);
821 c->
proto = IPPROTO_UDP;
826 }
else if (strcmp(
hs_proto,
"tcp") == 0) {
828 c->
proto = IPPROTO_TCP;
830 }
else if (strcmp(
hs_proto,
"tls") == 0) {
832 c->
proto = IPPROTO_TCP;
833 c->tls_required =
true;
836 }
else if (strcmp(
hs_proto,
"*") == 0) {
838 c->
proto = IPPROTO_IP;
890 if (c->tls_required) {
895 if ((c->
proto == IPPROTO_TCP) || (c->
proto == IPPROTO_IP)) {
919 char src_buf[128],
buffer[256];
922 if (!request)
return NULL;
930 RDEBUG2(
"Converting &control.FreeRADIUS-Client-* to client {...} section");
940 switch (
vp->
da->attr) {
941 case FR_FREERADIUS_CLIENT_IP_ADDRESS:
946 case FR_FREERADIUS_CLIENT_IP_PREFIX:
951 case FR_FREERADIUS_CLIENT_IPV6_ADDRESS:
956 case FR_FREERADIUS_CLIENT_IPV6_PREFIX:
961 case FR_FREERADIUS_CLIENT_SECRET:
966 case FR_FREERADIUS_CLIENT_NAS_TYPE:
971 case FR_FREERADIUS_CLIENT_SHORTNAME:
976 case FR_FREERADIUS_CLIENT_SRC_IP_ADDRESS:
981 case FR_FREERADIUS_CLIENT_REQUIRE_MA:
982 attr =
"require_message_authenticator";
990 case FR_FREERADIUS_CLIENT_TRACK_CONNECTIONS:
991 attr =
"track_connections";
1000 RERROR(
"Ignoring attribute %s",
vp->
da->name);
1006 RERROR(
"Error creating equivalent conf pair for %s",
vp->
da->name);
1047 if (!filename)
return NULL;
1050 if (!cs)
return NULL;
1059 ERROR(
"No \"client\" section found in client file");
1064 if (!c)
return NULL;
1065 talloc_steal(cs, c);
1067 p = strrchr(filename, FR_DIR_SEP);
1074 if (!check_dns)
return c;
1080 if (strcmp(p,
buffer) != 0) {
1081 ERROR(
"Invalid client definition in %s: IP address %s does not match name %s", filename,
buffer, p);
1099 }
while (!client && (
parent = request->parent));
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.
#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_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_item_next(_ci, _prev)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#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.
char * fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print the address portion of a fr_ipaddr_t.
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
union fr_ipaddr_t::@121 addr
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
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.
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.
bool message_authenticator
Require RADIUS message authenticator in requests.
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_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)
static char const * proto(int id, int porttype)
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
#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.
The main red black tree structure.
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
fr_time_delta_t idle_timeout
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
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_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_find(char const *name)
Return virtual server matching the specified name.