eap-radius: Add support to specify and bind a specific source address
Using a specific address can be useful in scenarios where dynamic routing could change the path to the RADIUS server and a changing source address is a problem for the server. Closes strongswan/strongswan#2598
This commit is contained in:
@@ -84,6 +84,9 @@ charon.plugins.eap-radius.secret =
|
||||
charon.plugins.eap-radius.server =
|
||||
IP/Hostname of RADIUS server.
|
||||
|
||||
charon.plugins.eap-radius.source =
|
||||
Optional specific source IP to use.
|
||||
|
||||
charon.plugins.eap-radius.retransmit_base = 1.4
|
||||
Base to use for calculating exponential back off.
|
||||
|
||||
@@ -96,12 +99,12 @@ charon.plugins.eap-radius.retransmit_tries = 4
|
||||
charon.plugins.eap-radius.servers {}
|
||||
Section to specify multiple RADIUS servers.
|
||||
|
||||
Section to specify multiple RADIUS servers. The **nas_identifier**,
|
||||
**secret**, **sockets** and **port** (or **auth_port**) options can be
|
||||
specified for each server. A server's IP/Hostname can be configured using
|
||||
the **address** option. The **acct_port** [1813] option can be used to
|
||||
specify the port used for RADIUS accounting. For each RADIUS server a
|
||||
priority can be specified using the **preference** [0] option. The
|
||||
Section to specify multiple RADIUS servers. The **source**,
|
||||
**nas_identifier**, **secret**, **sockets** and **port** (or **auth_port**)
|
||||
options can be specified for each server. A server's IP/Hostname can be
|
||||
configured using the **address** option. The **acct_port** [1813] option can
|
||||
be used to specify the port used for RADIUS accounting. For each RADIUS
|
||||
server a priority can be specified using the **preference** [0] option. The
|
||||
retransmission time for each server can set set using **retransmit_base**,
|
||||
**retransmit_timeout** and **retransmit_tries**.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Tobias Brunner
|
||||
* Copyright (C) 2013-2025 Tobias Brunner
|
||||
* Copyright (C) 2009 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -119,7 +119,7 @@ static void load_configs(private_eap_radius_plugin_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
radius_config_t *config;
|
||||
char *nas_identifier, *secret, *address, *section;
|
||||
char *nas_identifier, *secret, *address, *source, *section;
|
||||
int auth_port, acct_port, sockets, preference;
|
||||
u_int retransmit_tries;
|
||||
double retransmit_timeout, retransmit_base;
|
||||
@@ -135,6 +135,8 @@ static void load_configs(private_eap_radius_plugin_t *this)
|
||||
DBG1(DBG_CFG, "no RADIUS secret defined");
|
||||
return;
|
||||
}
|
||||
source = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.eap-radius.source", NULL, lib->ns);
|
||||
nas_identifier = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.eap-radius.nas_identifier", "strongSwan",
|
||||
lib->ns);
|
||||
@@ -150,7 +152,7 @@ static void load_configs(private_eap_radius_plugin_t *this)
|
||||
retransmit_base = lib->settings->get_double(lib->settings,
|
||||
"%s.plugins.eap-radius.retransmit_base", 1.4, lib->ns);
|
||||
|
||||
config = radius_config_create(address, address, auth_port, ACCT_PORT,
|
||||
config = radius_config_create(address, address, source, auth_port, ACCT_PORT,
|
||||
nas_identifier, secret, sockets, 0,
|
||||
retransmit_tries, retransmit_timeout,
|
||||
retransmit_base);
|
||||
@@ -183,6 +185,11 @@ static void load_configs(private_eap_radius_plugin_t *this)
|
||||
DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section);
|
||||
continue;
|
||||
}
|
||||
source = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.eap-radius.servers.%s.source",
|
||||
lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.eap-radius.source", NULL, lib->ns),
|
||||
lib->ns, section);
|
||||
nas_identifier = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.eap-radius.servers.%s.nas_identifier",
|
||||
lib->settings->get_str(lib->settings,
|
||||
@@ -228,7 +235,7 @@ static void load_configs(private_eap_radius_plugin_t *this)
|
||||
"%s.plugins.eap-radius.servers.%s.preference", 0,
|
||||
lib->ns, section);
|
||||
|
||||
config = radius_config_create(section, address, auth_port, acct_port,
|
||||
config = radius_config_create(section, address, source, auth_port, acct_port,
|
||||
nas_identifier, secret, sockets, preference,
|
||||
retransmit_tries, retransmit_timeout,
|
||||
retransmit_base);
|
||||
|
||||
@@ -200,7 +200,7 @@ METHOD(radius_config_t, destroy, void,
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
radius_config_t *radius_config_create(char *name, char *address,
|
||||
radius_config_t *radius_config_create(char *name, char *address, char *source,
|
||||
uint16_t auth_port, uint16_t acct_port,
|
||||
char *nas_identifier, char *secret,
|
||||
int sockets, int preference,
|
||||
@@ -232,7 +232,7 @@ radius_config_t *radius_config_create(char *name, char *address,
|
||||
|
||||
while (sockets--)
|
||||
{
|
||||
socket = radius_socket_create(address, auth_port, acct_port,
|
||||
socket = radius_socket_create(address, source, auth_port, acct_port,
|
||||
chunk_create(secret, strlen(secret)),
|
||||
tries, timeout, base);
|
||||
if (!socket)
|
||||
|
||||
@@ -108,6 +108,7 @@ struct radius_config_t {
|
||||
*
|
||||
* @param name server name
|
||||
* @param address server address
|
||||
* @param source optional source address
|
||||
* @param auth_port server port for authentication
|
||||
* @param acct_port server port for accounting
|
||||
* @param nas_identifier NAS-Identifier to use with this server
|
||||
@@ -118,7 +119,7 @@ struct radius_config_t {
|
||||
* @param timeout retransmission timeout
|
||||
* @param base base to calculate retransmission timeout
|
||||
*/
|
||||
radius_config_t *radius_config_create(char *name, char *address,
|
||||
radius_config_t *radius_config_create(char *name, char *address, char *source,
|
||||
uint16_t auth_port, uint16_t acct_port,
|
||||
char *nas_identifier, char *secret,
|
||||
int sockets, int preference,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2025 Tobias Brunner
|
||||
* Copyright (C) 2010 Martin Willi
|
||||
*
|
||||
* Copyright (C) secunet Security Networks AG
|
||||
@@ -83,6 +84,11 @@ struct private_radius_socket_t {
|
||||
*/
|
||||
char *address;
|
||||
|
||||
/**
|
||||
* Source address
|
||||
*/
|
||||
char *source;
|
||||
|
||||
/**
|
||||
* current RADIUS identifier
|
||||
*/
|
||||
@@ -130,10 +136,10 @@ struct private_radius_socket_t {
|
||||
static bool check_connection(private_radius_socket_t *this,
|
||||
int *fd, uint16_t port)
|
||||
{
|
||||
host_t *server, *src = NULL;
|
||||
|
||||
if (*fd == -1)
|
||||
{
|
||||
host_t *server;
|
||||
|
||||
server = host_create_from_dns(this->address, AF_UNSPEC, port);
|
||||
if (!server)
|
||||
{
|
||||
@@ -149,19 +155,42 @@ static bool check_connection(private_radius_socket_t *this,
|
||||
server->destroy(server);
|
||||
return FALSE;
|
||||
}
|
||||
if (this->source)
|
||||
{
|
||||
src = host_create_from_string_and_family(this->source,
|
||||
server->get_family(server), 0);
|
||||
if (!src)
|
||||
{
|
||||
DBG1(DBG_CFG, "invalid source address '%s' to reach RADIUS "
|
||||
"server %#H", this->source, server);
|
||||
goto error;
|
||||
}
|
||||
if (bind(*fd, src->get_sockaddr(src),
|
||||
*src->get_sockaddr_len(src)) == -1)
|
||||
{
|
||||
DBG1(DBG_CFG, "binding RADIUS socket to %H failed: %s", src,
|
||||
strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (connect(*fd, server->get_sockaddr(server),
|
||||
*server->get_sockaddr_len(server)) < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "connecting RADIUS socket to %#H failed: %s",
|
||||
server, strerror(errno));
|
||||
server->destroy(server);
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
return FALSE;
|
||||
goto error;
|
||||
}
|
||||
server->destroy(server);
|
||||
DESTROY_IF(src);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
server->destroy(server);
|
||||
DESTROY_IF(src);
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,7 +412,8 @@ METHOD(radius_socket_t, destroy, void,
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
radius_socket_t *radius_socket_create(char *address, uint16_t auth_port,
|
||||
radius_socket_t *radius_socket_create(char *address, char *source,
|
||||
uint16_t auth_port,
|
||||
uint16_t acct_port, chunk_t secret,
|
||||
u_int tries, double timeout, double base)
|
||||
{
|
||||
@@ -396,6 +426,7 @@ radius_socket_t *radius_socket_create(char *address, uint16_t auth_port,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.address = address,
|
||||
.source = source,
|
||||
.auth_port = auth_port,
|
||||
.auth_fd = -1,
|
||||
.acct_port = acct_port,
|
||||
|
||||
@@ -90,6 +90,7 @@ struct radius_socket_t {
|
||||
* Create a radius_socket instance.
|
||||
*
|
||||
* @param address server name
|
||||
* @param source optional source address
|
||||
* @param auth_port server port for authentication
|
||||
* @param acct_port server port for accounting
|
||||
* @param secret RADIUS secret
|
||||
@@ -97,8 +98,9 @@ struct radius_socket_t {
|
||||
* @param timeout retransmission timeout
|
||||
* @param base base to calculate retransmission timeout
|
||||
*/
|
||||
radius_socket_t *radius_socket_create(char *address, uint16_t auth_port,
|
||||
uint16_t acct_port, chunk_t secret,
|
||||
u_int tries, double timeout, double base);
|
||||
radius_socket_t *radius_socket_create(char *address, char *source,
|
||||
uint16_t auth_port, uint16_t acct_port,
|
||||
chunk_t secret, u_int tries,
|
||||
double timeout, double base);
|
||||
|
||||
#endif /** RADIUS_SOCKET_H_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user