diff options
Diffstat (limited to 'src/libcharon/plugins/eap_radius/eap_radius_plugin.c')
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_plugin.c | 150 |
1 files changed, 139 insertions, 11 deletions
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index 7d2788c3e..91aae2f62 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -17,17 +17,130 @@ #include "eap_radius.h" #include "radius_client.h" +#include "radius_server.h" #include <daemon.h> /** - * Implementation of plugin_t.destroy + * Default RADIUS server port, when not configured */ -static void destroy(eap_radius_plugin_t *this) +#define RADIUS_PORT 1812 + +typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t; + +/** + * Private data of an eap_radius_plugin_t object. + */ +struct private_eap_radius_plugin_t { + + /** + * Public radius_plugin_t interface. + */ + eap_radius_plugin_t public; + + /** + * List of RADIUS servers + */ + linked_list_t *servers; +}; + +/** + * Instance of the EAP plugin + */ +static private_eap_radius_plugin_t *instance = NULL; + +METHOD(plugin_t, destroy, void, + private_eap_radius_plugin_t *this) { charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create); - radius_client_cleanup(); + this->servers->destroy_offset(this->servers, + offsetof(radius_server_t, destroy)); free(this); + instance = NULL; +} + +/** + * Load RADIUS servers from configuration + */ +static bool load_servers(private_eap_radius_plugin_t *this) +{ + enumerator_t *enumerator; + radius_server_t *server; + char *nas_identifier, *secret, *address, *section; + int port, sockets, preference; + + address = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.server", NULL); + if (address) + { /* legacy configuration */ + secret = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.secret", NULL); + if (!secret) + { + DBG1(DBG_CFG, "no RADUIS secret defined"); + return FALSE; + } + nas_identifier = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.nas_identifier", "strongSwan"); + port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.port", RADIUS_PORT); + sockets = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.sockets", 1); + server = radius_server_create(address, port, nas_identifier, + secret, sockets, 0); + if (!server) + { + DBG1(DBG_CFG, "no RADUIS server defined"); + return FALSE; + } + this->servers->insert_last(this->servers, server); + return TRUE; + } + + enumerator = lib->settings->create_section_enumerator(lib->settings, + "charon.plugins.eap-radius.servers"); + while (enumerator->enumerate(enumerator, §ion)) + { + address = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.address", NULL, section); + if (!address) + { + DBG1(DBG_CFG, "RADIUS server '%s' misses address, skipped", section); + continue; + } + secret = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.secret", NULL, section); + if (!secret) + { + DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section); + continue; + } + nas_identifier = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.nas_identifier", + "strongSwan", section); + port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section); + sockets = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.sockets", 1, section); + preference = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.preference", 0, section); + server = radius_server_create(address, port, nas_identifier, + secret, sockets, preference); + if (!server) + { + DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section); + continue; + } + this->servers->insert_last(this->servers, server); + } + enumerator->destroy(enumerator); + + if (this->servers->get_count(this->servers) == 0) + { + DBG1(DBG_CFG, "no valid RADIUS server configuration found"); + return FALSE; + } + return TRUE; } /* @@ -35,20 +148,35 @@ static void destroy(eap_radius_plugin_t *this) */ plugin_t *eap_radius_plugin_create() { - eap_radius_plugin_t *this; + private_eap_radius_plugin_t *this; + + INIT(this, + .public.plugin.destroy = _destroy, + .servers = linked_list_create(), + ); - if (!radius_client_init()) + if (!load_servers(this)) { - DBG1(DBG_CFG, "RADIUS plugin initialization failed"); + destroy(this); return NULL; } - - this = malloc_thing(eap_radius_plugin_t); - this->plugin.destroy = (void(*)(plugin_t*))destroy; - charon->eap->add_method(charon->eap, EAP_RADIUS, 0, EAP_SERVER, (eap_constructor_t)eap_radius_create); - return &this->plugin; + instance = this; + + return &this->public.plugin; +} + +/** + * See header + */ +enumerator_t *eap_radius_create_server_enumerator() +{ + if (instance) + { + return instance->servers->create_enumerator(instance->servers); + } + return enumerator_create_empty(); } |