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