aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2011-04-21 11:40:25 +0200
committerMartin Willi <martin@revosec.ch>2011-04-21 14:01:25 +0200
commitf9a552f011cda2eb00373fba3e745ae279357cea (patch)
treeef396b4c0e6a03a8b8392c8a89528b437c7ed214
parent5b0bcfb1fc4aabb6535db91e70f7f262328e664f (diff)
downloadstrongswan-f9a552f011cda2eb00373fba3e745ae279357cea.tar.bz2
strongswan-f9a552f011cda2eb00373fba3e745ae279357cea.tar.xz
Resolve and connect to RADIUS servers not before required
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.c4
-rw-r--r--src/libcharon/plugins/eap_radius/radius_client.c17
-rw-r--r--src/libcharon/plugins/eap_radius/radius_server.c28
-rw-r--r--src/libcharon/plugins/eap_radius/radius_server.h11
-rw-r--r--src/libcharon/plugins/eap_radius/radius_socket.c81
-rw-r--r--src/libcharon/plugins/eap_radius/radius_socket.h8
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c1
7 files changed, 94 insertions, 56 deletions
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
index 9b1525662..c218bd48b 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
@@ -82,7 +82,7 @@ static void load_servers(private_eap_radius_plugin_t *this)
"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,
+ server = radius_server_create(address, address, port, nas_identifier,
secret, sockets, 0);
if (!server)
{
@@ -120,7 +120,7 @@ static void load_servers(private_eap_radius_plugin_t *this)
"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,
+ server = radius_server_create(section, address, port, nas_identifier,
secret, sockets, preference);
if (!server)
{
diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c
index 0d7276af4..245308e59 100644
--- a/src/libcharon/plugins/eap_radius/radius_client.c
+++ b/src/libcharon/plugins/eap_radius/radius_client.c
@@ -98,13 +98,14 @@ METHOD(radius_client_t, request, radius_message_t*,
req->add(req, RAT_STATE, this->state);
}
socket = this->server->get_socket(this->server);
- DBG1(DBG_CFG, "sending RADIUS %N to %#H", radius_message_code_names,
- req->get_code(req), this->server->get_address(this->server));
+ DBG1(DBG_CFG, "sending RADIUS %N to server '%s'", radius_message_code_names,
+ req->get_code(req), this->server->get_name(this->server));
res = socket->request(socket, req);
if (res)
{
- DBG1(DBG_CFG, "received RADIUS %N from %#H", radius_message_code_names,
- res->get_code(res), this->server->get_address(this->server));
+ DBG1(DBG_CFG, "received RADIUS %N from server '%s'",
+ radius_message_code_names, res->get_code(res),
+ this->server->get_name(this->server));
save_state(this, res);
if (res->get_code(res) == RMC_ACCESS_ACCEPT)
{
@@ -160,16 +161,16 @@ radius_client_t *radius_client_create()
/* for two with equal preference, 50-50 chance */
(current == best && random() % 2 == 0))
{
- DBG2(DBG_CFG, "RADIUS server %H is candidate: %d",
- server->get_address(server), current);
+ DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d",
+ server->get_name(server), current);
best = current;
DESTROY_IF(this->server);
this->server = server->get_ref(server);
}
else
{
- DBG2(DBG_CFG, "RADIUS server %H skipped: %d",
- server->get_address(server), current);
+ DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d",
+ server->get_name(server), current);
}
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c
index 37a2d331e..3baf39807 100644
--- a/src/libcharon/plugins/eap_radius/radius_server.c
+++ b/src/libcharon/plugins/eap_radius/radius_server.c
@@ -32,11 +32,6 @@ struct private_radius_server_t {
radius_server_t public;
/**
- * RADIUS server address
- */
- host_t *host;
-
- /**
* list of radius sockets, as radius_socket_t
*/
linked_list_t *sockets;
@@ -57,9 +52,9 @@ struct private_radius_server_t {
condvar_t *condvar;
/**
- * RADIUS secret
+ * Server name
*/
- chunk_t secret;
+ char *name;
/**
* NAS-Identifier
@@ -152,10 +147,10 @@ METHOD(radius_server_t, get_preference, int,
return pref;
}
-METHOD(radius_server_t, get_address, host_t*,
+METHOD(radius_server_t, get_name, char*,
private_radius_server_t *this)
{
- return this->host;
+ return this->name;
}
METHOD(radius_server_t, get_ref, radius_server_t*,
@@ -171,12 +166,10 @@ METHOD(radius_server_t, destroy, void,
{
if (ref_put(&this->ref))
{
- DESTROY_IF(this->host);
this->mutex->destroy(this->mutex);
this->condvar->destroy(this->condvar);
this->sockets->destroy_offset(this->sockets,
offsetof(radius_socket_t, destroy));
- free(this->nas_identifier.ptr);
free(this);
}
}
@@ -184,7 +177,7 @@ METHOD(radius_server_t, destroy, void,
/**
* See header
*/
-radius_server_t *radius_server_create(char *server, u_int16_t port,
+radius_server_t *radius_server_create(char *name, char *address, u_int16_t port,
char *nas_identifier, char *secret, int sockets, int preference)
{
private_radius_server_t *this;
@@ -196,7 +189,7 @@ radius_server_t *radius_server_create(char *server, u_int16_t port,
.put_socket = _put_socket,
.get_nas_identifier = _get_nas_identifier,
.get_preference = _get_preference,
- .get_address = _get_address,
+ .get_name = _get_name,
.get_ref = _get_ref,
.destroy = _destroy,
},
@@ -206,19 +199,14 @@ radius_server_t *radius_server_create(char *server, u_int16_t port,
.sockets = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
- .host = host_create_from_dns(server, 0, port),
+ .name = name,
.preference = preference,
.ref = 1,
);
- if (!this->host)
- {
- destroy(this);
- return NULL;
- }
while (sockets--)
{
- socket = radius_socket_create(this->host,
+ socket = radius_socket_create(address, port,
chunk_create(secret, strlen(secret)));
if (!socket)
{
diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h
index a9bc72180..c59361c49 100644
--- a/src/libcharon/plugins/eap_radius/radius_server.h
+++ b/src/libcharon/plugins/eap_radius/radius_server.h
@@ -61,11 +61,11 @@ struct radius_server_t {
int (*get_preference)(radius_server_t *this);
/**
- * Get the address of the RADIUS server.
+ * Get the name of the RADIUS server.
*
- * @return address, internal data
+ * @return server name
*/
- host_t* (*get_address)(radius_server_t *this);
+ char* (*get_name)(radius_server_t *this);
/**
* Increase reference count of this server.
@@ -83,14 +83,15 @@ struct radius_server_t {
/**
* Create a radius_server instance.
*
- * @param server server address
+ * @param name server name
+ * @param address server address
* @param port server port
* @param nas_identifier NAS-Identifier to use with this server
* @param secret secret to use with this server
* @param sockets number of sockets to create in pool
* @param preference preference boost for this server
*/
-radius_server_t *radius_server_create(char *server, u_int16_t port,
+radius_server_t *radius_server_create(char *name, char *address, u_int16_t port,
char *nas_identifier, char *secret, int sockets, int preference);
#endif /** RADIUS_SERVER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_socket.c b/src/libcharon/plugins/eap_radius/radius_socket.c
index 76993e756..b3229c288 100644
--- a/src/libcharon/plugins/eap_radius/radius_socket.c
+++ b/src/libcharon/plugins/eap_radius/radius_socket.c
@@ -49,6 +49,16 @@ struct private_radius_socket_t {
int fd;
/**
+ * Server address
+ */
+ char *address;
+
+ /**
+ * Server port
+ */
+ u_int16_t port;
+
+ /**
* current RADIUS identifier
*/
u_int8_t identifier;
@@ -74,6 +84,45 @@ struct private_radius_socket_t {
chunk_t secret;
};
+/**
+ * Check or establish RADIUS connection
+ */
+static bool check_connection(private_radius_socket_t *this)
+{
+ if (this->fd == -1)
+ {
+ host_t *server;
+
+ server = host_create_from_dns(this->address, AF_UNSPEC, this->port);
+ if (!server)
+ {
+ DBG1(DBG_CFG, "resolving RADIUS server address '%s' failed",
+ this->address);
+ return FALSE;
+ }
+ this->fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP);
+ if (this->fd == -1)
+ {
+ DBG1(DBG_CFG, "opening RADIUS socket for %#H failed: %s",
+ server, strerror(errno));
+ server->destroy(server);
+ return FALSE;
+ }
+ if (connect(this->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(this->fd);
+ this->fd = -1;
+ return FALSE;
+ }
+ server->destroy(server);
+ }
+ return TRUE;
+}
+
METHOD(radius_socket_t, request, radius_message_t*,
private_radius_socket_t *this, radius_message_t *request)
{
@@ -85,6 +134,11 @@ METHOD(radius_socket_t, request, radius_message_t*,
/* sign the request */
request->sign(request, this->rng, this->signer);
+ if (!check_connection(this))
+ {
+ return NULL;
+ }
+
data = request->get_encoding(request);
/* timeout after 2, 3, 4, 5 seconds */
for (i = 2; i <= 5; i++)
@@ -257,15 +311,18 @@ METHOD(radius_socket_t, destroy, void,
DESTROY_IF(this->hasher);
DESTROY_IF(this->signer);
DESTROY_IF(this->rng);
- chunk_clear(&this->secret);
- close(this->fd);
+ if (this->fd != -1)
+ {
+ close(this->fd);
+ }
free(this);
}
/**
* See header
*/
-radius_socket_t *radius_socket_create(host_t *host, chunk_t secret)
+radius_socket_t *radius_socket_create(char *address, u_int16_t port,
+ chunk_t secret)
{
private_radius_socket_t *this;
@@ -275,23 +332,11 @@ radius_socket_t *radius_socket_create(host_t *host, chunk_t secret)
.decrypt_msk = _decrypt_msk,
.destroy = _destroy,
},
+ .address = address,
+ .port = port,
+ .fd = -1,
);
- this->fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP);
- if (this->fd < 0)
- {
- DBG1(DBG_CFG, "opening RADIUS socket failed: %s", strerror(errno));
- free(this);
- return NULL;
- }
- if (connect(this->fd, host->get_sockaddr(host),
- *host->get_sockaddr_len(host)) < 0)
- {
- DBG1(DBG_CFG, "connecting RADIUS socket failed");
- close(this->fd);
- free(this);
- return NULL;
- }
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h
index fe8491a8f..2875008eb 100644
--- a/src/libcharon/plugins/eap_radius/radius_socket.h
+++ b/src/libcharon/plugins/eap_radius/radius_socket.h
@@ -34,7 +34,7 @@ struct radius_socket_t {
/**
* Send a RADIUS request, wait for response.
-
+ *
* The socket fills in RADIUS Message identifier, builds a
* Request-Authenticator and calculates the Message-Authenticator
* attribute.
@@ -66,9 +66,11 @@ struct radius_socket_t {
/**
* Create a radius_socket instance.
*
- * @param host RADIUS server address to connect to
+ * @param address server name
+ * @param port server port
* @param secret RADIUS secret
*/
-radius_socket_t *radius_socket_create(host_t *host, chunk_t secret);
+radius_socket_t *radius_socket_create(char *address, u_int16_t port,
+ chunk_t secret);
#endif /** RADIUS_SOCKET_H_ @}*/
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
index 6cae0034b..d442acb00 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -183,6 +183,7 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
if (this->method)
{
action = "initiating";
+ type = this->method->get_type(this->method, &vendor);
if (this->method->initiate(this->method, &out) == NEED_MORE)
{
if (vendor)