diff options
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r-- | src/libcharon/plugins/eap_radius/Makefile.am | 9 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius.c | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_accounting.c | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_dae.c | 2 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_forward.h | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_plugin.c | 43 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_plugin.h | 9 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_client.c | 185 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_client.h | 66 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_message.c | 491 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_message.h | 287 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_server.c | 221 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_server.h | 100 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_socket.c | 386 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_socket.h | 77 |
15 files changed, 55 insertions, 1839 deletions
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index 96bfa6fcb..181497ab5 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -1,12 +1,13 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius AM_CFLAGS = -rdynamic if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-radius.la else +libstrongswan_eap_radius_la_LIBADD = $(top_builddir)/src/libradius/libradius.la plugin_LTLIBRARIES = libstrongswan-eap-radius.la endif @@ -15,10 +16,6 @@ libstrongswan_eap_radius_la_SOURCES = \ eap_radius.h eap_radius.c \ eap_radius_accounting.h eap_radius_accounting.c \ eap_radius_dae.h eap_radius_dae.c \ - eap_radius_forward.h eap_radius_forward.c \ - radius_server.h radius_server.c \ - radius_socket.h radius_socket.c \ - radius_client.h radius_client.c \ - radius_message.h radius_message.c + eap_radius_forward.h eap_radius_forward.c libstrongswan_eap_radius_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index f2b47e3f0..051d46ecf 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -14,10 +14,11 @@ */ #include "eap_radius.h" +#include "eap_radius_plugin.h" #include "eap_radius_forward.h" -#include "radius_message.h" -#include "radius_client.h" +#include <radius_message.h> +#include <radius_client.h> #include <daemon.h> @@ -462,7 +463,7 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer "charon.plugins.eap-radius.filter_id", FALSE), ); - this->client = radius_client_create(); + this->client = eap_radius_create_client(); if (!this->client) { free(this); diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c index 25013f62d..45be22704 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c @@ -14,11 +14,12 @@ */ #include "eap_radius_accounting.h" +#include "eap_radius_plugin.h" #include <time.h> -#include "radius_message.h" -#include "radius_client.h" +#include <radius_message.h> +#include <radius_client.h> #include <daemon.h> #include <utils/hashtable.h> #include <threading/mutex.h> @@ -125,7 +126,7 @@ static bool send_message(private_eap_radius_accounting_t *this, radius_client_t *client; bool ack = FALSE; - client = radius_client_create(); + client = eap_radius_create_client(); if (client) { response = client->request(client, request); diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c index 3ea587309..1cc19afaa 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_dae.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c @@ -15,7 +15,7 @@ #include "eap_radius_dae.h" -#include "radius_message.h" +#include <radius_message.h> #include <sys/types.h> #include <sys/stat.h> diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.h b/src/libcharon/plugins/eap_radius/eap_radius_forward.h index e1a8c4170..2c1dbf7a8 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_forward.h +++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.h @@ -15,13 +15,13 @@ /** * @defgroup eap_radius_forward eap_radius_forward - * @{ @ingroup + * @{ @ingroup eap_radius */ #ifndef EAP_RADIUS_FORWARD_H_ #define EAP_RADIUS_FORWARD_H_ -#include "radius_message.h" +#include <radius_message.h> #include <bus/listeners/listener.h> diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index e544aaf3e..0caecc1ad 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -19,8 +19,9 @@ #include "eap_radius_accounting.h" #include "eap_radius_dae.h" #include "eap_radius_forward.h" -#include "radius_client.h" -#include "radius_server.h" + +#include <radius_client.h> +#include <radius_server.h> #include <daemon.h> #include <threading/rwlock.h> @@ -261,15 +262,43 @@ plugin_t *eap_radius_plugin_create() /** * See header */ -enumerator_t *eap_radius_create_server_enumerator() +radius_client_t *eap_radius_create_client() { if (instance) { + enumerator_t *enumerator; + radius_server_t *server, *selected = NULL; + int current, best = -1; + instance->lock->read_lock(instance->lock); - return enumerator_create_cleaner( - instance->servers->create_enumerator(instance->servers), - (void*)instance->lock->unlock, instance->lock); + enumerator = instance->servers->create_enumerator(instance->servers); + while (enumerator->enumerate(enumerator, &server)) + { + current = server->get_preference(server); + if (current > best || + /* for two with equal preference, 50-50 chance */ + (current == best && random() % 2 == 0)) + { + DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d", + server->get_name(server), current); + best = current; + DESTROY_IF(selected); + selected = server->get_ref(server); + } + else + { + DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d", + server->get_name(server), current); + } + } + enumerator->destroy(enumerator); + instance->lock->unlock(instance->lock); + + if (selected) + { + return radius_client_create(selected); + } } - return enumerator_create_empty(); + return NULL; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h index cb724364a..1570bd566 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h @@ -25,7 +25,8 @@ #define EAP_RADIUS_PLUGIN_H_ #include <plugins/plugin.h> -#include <utils/enumerator.h> + +#include <radius_client.h> typedef struct eap_radius_plugin_t eap_radius_plugin_t; @@ -44,10 +45,10 @@ struct eap_radius_plugin_t { }; /** - * Create an enumerator over all loaded RADIUS servers. + * Get a RADIUS client instance to connect to servers. * - * @return enumerator over radius_server_t + * @return RADIUS client */ -enumerator_t *eap_radius_create_server_enumerator(); +radius_client_t *eap_radius_create_client(); #endif /** EAP_RADIUS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c deleted file mode 100644 index 1a67096cb..000000000 --- a/src/libcharon/plugins/eap_radius/radius_client.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "radius_client.h" - -#include "eap_radius_plugin.h" -#include "radius_server.h" - -#include <unistd.h> -#include <errno.h> - -#include <debug.h> -#include <utils/host.h> -#include <utils/linked_list.h> -#include <threading/condvar.h> -#include <threading/mutex.h> - -typedef struct private_radius_client_t private_radius_client_t; - -/** - * Private data of an radius_client_t object. - */ -struct private_radius_client_t { - - /** - * Public radius_client_t interface. - */ - radius_client_t public; - - /** - * Selected RADIUS server - */ - radius_server_t *server; - - /** - * RADIUS servers State attribute - */ - chunk_t state; - - /** - * EAP MSK, from MPPE keys - */ - chunk_t msk; -}; - -/** - * Save the state attribute to include in further request - */ -static void save_state(private_radius_client_t *this, radius_message_t *msg) -{ - enumerator_t *enumerator; - int type; - chunk_t data; - - enumerator = msg->create_enumerator(msg); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_STATE) - { - free(this->state.ptr); - this->state = chunk_clone(data); - enumerator->destroy(enumerator); - return; - } - } - enumerator->destroy(enumerator); - /* no state attribute found, remove state */ - chunk_free(&this->state); -} - -METHOD(radius_client_t, request, radius_message_t*, - private_radius_client_t *this, radius_message_t *req) -{ - char virtual[] = {0x00,0x00,0x00,0x05}; - radius_socket_t *socket; - radius_message_t *res; - - /* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */ - req->add(req, RAT_NAS_PORT_TYPE, chunk_create(virtual, sizeof(virtual))); - /* add our NAS-Identifier */ - req->add(req, RAT_NAS_IDENTIFIER, - this->server->get_nas_identifier(this->server)); - /* add State attribute, if server sent one */ - if (this->state.ptr) - { - req->add(req, RAT_STATE, this->state); - } - socket = this->server->get_socket(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 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) - { - chunk_clear(&this->msk); - this->msk = socket->decrypt_msk(socket, req, res); - } - this->server->put_socket(this->server, socket, TRUE); - return res; - } - this->server->put_socket(this->server, socket, FALSE); - return NULL; -} - -METHOD(radius_client_t, get_msk, chunk_t, - private_radius_client_t *this) -{ - return this->msk; -} - -METHOD(radius_client_t, destroy, void, - private_radius_client_t *this) -{ - this->server->destroy(this->server); - chunk_clear(&this->msk); - free(this->state.ptr); - free(this); -} - -/** - * See header - */ -radius_client_t *radius_client_create() -{ - private_radius_client_t *this; - enumerator_t *enumerator; - radius_server_t *server; - int current, best = -1; - - INIT(this, - .public = { - .request = _request, - .get_msk = _get_msk, - .destroy = _destroy, - }, - ); - - enumerator = eap_radius_create_server_enumerator(); - while (enumerator->enumerate(enumerator, &server)) - { - current = server->get_preference(server); - if (current > best || - /* for two with equal preference, 50-50 chance */ - (current == best && random() % 2 == 0)) - { - 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 '%s' skipped: %d", - server->get_name(server), current); - } - } - enumerator->destroy(enumerator); - - if (!this->server) - { - free(this); - return NULL; - } - - return &this->public; -} - diff --git a/src/libcharon/plugins/eap_radius/radius_client.h b/src/libcharon/plugins/eap_radius/radius_client.h deleted file mode 100644 index e4f3a7222..000000000 --- a/src/libcharon/plugins/eap_radius/radius_client.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup radius_client radius_client - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_CLIENT_H_ -#define RADIUS_CLIENT_H_ - -#include "radius_message.h" - -typedef struct radius_client_t radius_client_t; - -/** - * RADIUS client functionality. - * - * To communicate with a RADIUS server, create a client and send messages over - * it. The client allocates a socket from the best RADIUS server abailable. - */ -struct radius_client_t { - - /** - * Send a RADIUS request and wait for the response. - * - * The client fills in NAS-Identifier nad NAS-Port-Type - * - * @param msg RADIUS request message to send - * @return response, NULL if timed out/verification failed - */ - radius_message_t* (*request)(radius_client_t *this, radius_message_t *msg); - - /** - * Get the EAP MSK after successful RADIUS authentication. - * - * @return MSK, allocated - */ - chunk_t (*get_msk)(radius_client_t *this); - - /** - * Destroy the client, release the socket. - */ - void (*destroy)(radius_client_t *this); -}; - -/** - * Create a RADIUS client. - * - * @return radius_client_t object - */ -radius_client_t *radius_client_create(); - -#endif /** RADIUS_CLIENT_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_message.c b/src/libcharon/plugins/eap_radius/radius_message.c deleted file mode 100644 index ad8875423..000000000 --- a/src/libcharon/plugins/eap_radius/radius_message.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "radius_message.h" - -#include <debug.h> -#include <crypto/hashers/hasher.h> - -typedef struct private_radius_message_t private_radius_message_t; -typedef struct rmsg_t rmsg_t; -typedef struct rattr_t rattr_t; - -/** - * RADIUS message header - */ -struct rmsg_t { - /** message code, radius_message_code_t */ - u_int8_t code; - /** message identifier */ - u_int8_t identifier; - /** length of Code, Identifier, Length, Authenticator and Attributes */ - u_int16_t length; - /** message authenticator, MD5 hash */ - u_int8_t authenticator[HASH_SIZE_MD5]; - /** variable list of packed attributes */ - u_int8_t attributes[]; -} __attribute__((packed)); - -/** - * RADIUS message attribute. - */ -struct rattr_t { - /** attribute type, radius_attribute_type_t */ - u_int8_t type; - /** length of the attriubte, including the Type, Length and Value fields */ - u_int8_t length; - /** variable length attribute value */ - u_int8_t value[]; -} __attribute__((packed)); - -/** - * Private data of an radius_message_t object. - */ -struct private_radius_message_t { - - /** - * Public radius_message_t interface. - */ - radius_message_t public; - - /** - * message data, allocated - */ - rmsg_t *msg; -}; - -ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONSE, - "Access-Request", - "Access-Accept", - "Access-Reject", - "Accounting-Request", - "Accounting-Response"); -ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE, - "Access-Challenge"); -ENUM_NEXT(radius_message_code_names, RMC_DISCONNECT_REQUEST, RMC_COA_NAK, RMC_ACCESS_CHALLENGE, - "Disconnect-Request", - "Disconnect-ACK", - "Disconnect-NAK", - "CoA-Request", - "CoA-ACK", - "CoA-NAK"); -ENUM_END(radius_message_code_names, RMC_COA_NAK); - -ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX, - "User-Name", - "User-Password", - "CHAP-Password", - "NAS-IP-Address", - "NAS-Port", - "Service-Type", - "Framed-Protocol", - "Framed-IP-Address", - "Framed-IP-Netmask", - "Framed-Routing", - "Filter-Id", - "Framed-MTU", - "Framed-Compression", - "Login-IP-Host", - "Login-Service", - "Login-TCP-Port", - "Unassigned", - "Reply-Message", - "Callback-Number", - "Callback-Id", - "Unassigned", - "Framed-Route", - "Framed-IPX-Network", - "State", - "Class", - "Vendor-Specific", - "Session-Timeout", - "Idle-Timeout", - "Termination-Action", - "Called-Station-Id", - "Calling-Station-Id", - "NAS-Identifier", - "Proxy-State", - "Login-LAT-Service", - "Login-LAT-Node", - "Login-LAT-Group", - "Framed-AppleTalk-Link", - "Framed-AppleTalk-Network", - "Framed-AppleTalk-Zone", - "Acct-Status-Type", - "Acct-Delay-Time", - "Acct-Input-Octets", - "Acct-Output-Octets", - "Acct-Session-Id", - "Acct-Authentic", - "Acct-Session-Time", - "Acct-Input-Packets", - "Acct-Output-Packets", - "Acct-Terminate-Cause", - "Acct-Multi-Session-Id", - "Acct-Link-Count", - "Acct-Input-Gigawords", - "Acct-Output-Gigawords", - "Unassigned", - "Event-Timestamp", - "Egress-VLANID", - "Ingress-Filters", - "Egress-VLAN-Name", - "User-Priority-Table", - "CHAP-Challenge", - "NAS-Port-Type", - "Port-Limit", - "Login-LAT-Port", - "Tunnel-Type", - "Tunnel-Medium-Type", - "Tunnel-Client-Endpoint", - "Tunnel-Server-Endpoint", - "Acct-Tunnel-Connection", - "Tunnel-Password", - "ARAP-Password", - "ARAP-Features", - "ARAP-Zone-Access", - "ARAP-Security", - "ARAP-Security-Data", - "Password-Retry", - "Prompt", - "Connect-Info", - "Configuration-Token", - "EAP-Message", - "Message-Authenticator", - "Tunnel-Private-Group-ID", - "Tunnel-Assignment-ID", - "Tunnel-Preference", - "ARAP-Challenge-Response", - "Acct-Interim-Interval", - "Acct-Tunnel-Packets-Lost", - "NAS-Port-Id", - "Framed-Pool", - "CUI", - "Tunnel-Client-Auth-ID", - "Tunnel-Server-Auth-ID", - "NAS-Filter-Rule", - "Unassigned", - "Originating-Line-Info", - "NAS-IPv6-Address", - "Framed-Interface-Id", - "Framed-IPv6-Prefix", - "Login-IPv6-Host", - "Framed-IPv6-Route", - "Framed-IPv6-Pool", - "Error-Cause", - "EAP-Key-Name", - "Digest-Response", - "Digest-Realm", - "Digest-Nonce", - "Digest-Response-Auth", - "Digest-Nextnonce", - "Digest-Method", - "Digest-URI", - "Digest-Qop", - "Digest-Algorithm", - "Digest-Entity-Body-Hash", - "Digest-CNonce", - "Digest-Nonce-Count", - "Digest-Username", - "Digest-Opaque", - "Digest-Auth-Param", - "Digest-AKA-Auts", - "Digest-Domain", - "Digest-Stale", - "Digest-HA1", - "SIP-AOR", - "Delegated-IPv6-Prefix", - "MIP6-Feature-Vector", - "MIP6-Home-Link-Prefix"); - -/** - * Attribute enumerator implementation - */ -typedef struct { - /** implements enumerator interface */ - enumerator_t public; - /** currently pointing attribute */ - rattr_t *next; - /** bytes left */ - int left; -} attribute_enumerator_t; - -METHOD(enumerator_t, attribute_enumerate, bool, - attribute_enumerator_t *this, int *type, chunk_t *data) -{ - if (this->left == 0) - { - return FALSE; - } - if (this->left < sizeof(rattr_t) || - this->left < this->next->length) - { - DBG1(DBG_IKE, "RADIUS message truncated"); - return FALSE; - } - *type = this->next->type; - data->ptr = this->next->value; - data->len = this->next->length - sizeof(rattr_t); - this->left -= this->next->length; - this->next = ((void*)this->next) + this->next->length; - return TRUE; -} - -METHOD(radius_message_t, create_enumerator, enumerator_t*, - private_radius_message_t *this) -{ - attribute_enumerator_t *e; - - if (ntohs(this->msg->length) < sizeof(rmsg_t) + sizeof(rattr_t)) - { - return enumerator_create_empty(); - } - INIT(e, - .public = { - .enumerate = (void*)_attribute_enumerate, - .destroy = (void*)free, - }, - .next = (rattr_t*)this->msg->attributes, - .left = ntohs(this->msg->length) - sizeof(rmsg_t), - ); - return &e->public; -} - -METHOD(radius_message_t, add, void, - private_radius_message_t *this, radius_attribute_type_t type, chunk_t data) -{ - rattr_t *attribute; - - data.len = min(data.len, 253); - this->msg = realloc(this->msg, - ntohs(this->msg->length) + sizeof(rattr_t) + data.len); - attribute = ((void*)this->msg) + ntohs(this->msg->length); - attribute->type = type; - attribute->length = data.len + sizeof(rattr_t); - memcpy(attribute->value, data.ptr, data.len); - this->msg->length = htons(ntohs(this->msg->length) + attribute->length); -} - -METHOD(radius_message_t, sign, void, - private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer, rng_t *rng) -{ - if (rng == NULL) - { - chunk_t msg; - - if (req_auth) - { - memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5); - } - else - { - memset(this->msg->authenticator, 0, sizeof(this->msg->authenticator)); - } - msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length)); - hasher->get_hash(hasher, msg, NULL); - hasher->get_hash(hasher, secret, this->msg->authenticator); - } - else - { - char buf[HASH_SIZE_MD5]; - - /* build Request-Authenticator */ - rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator); - - /* build Message-Authenticator attribute, using 16 null bytes */ - memset(buf, 0, sizeof(buf)); - add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf))); - signer->get_signature(signer, - chunk_create((u_char*)this->msg, ntohs(this->msg->length)), - ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5); - } -} - -METHOD(radius_message_t, verify, bool, - private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer) -{ - char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5]; - enumerator_t *enumerator; - int type; - chunk_t data, msg; - bool has_eap = FALSE, has_auth = FALSE; - - /* replace Response by Request Authenticator for verification */ - memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5); - if (req_auth) - { - memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5); - } - else - { - memset(this->msg->authenticator, 0, HASH_SIZE_MD5); - } - msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length)); - - /* verify Response-Authenticator */ - hasher->get_hash(hasher, msg, NULL); - hasher->get_hash(hasher, secret, buf); - if (!memeq(buf, res_auth, HASH_SIZE_MD5)) - { - DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed"); - return FALSE; - } - - /* verify Message-Authenticator attribute */ - enumerator = create_enumerator(this); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_MESSAGE_AUTHENTICATOR) - { - if (data.len != HASH_SIZE_MD5) - { - DBG1(DBG_CFG, "RADIUS Message-Authenticator invalid length"); - enumerator->destroy(enumerator); - return FALSE; - } - memcpy(buf, data.ptr, data.len); - memset(data.ptr, 0, data.len); - if (signer->verify_signature(signer, msg, - chunk_create(buf, sizeof(buf)))) - { - /* restore Message-Authenticator */ - memcpy(data.ptr, buf, data.len); - has_auth = TRUE; - break; - } - else - { - DBG1(DBG_CFG, "RADIUS Message-Authenticator verification failed"); - enumerator->destroy(enumerator); - return FALSE; - } - } - else if (type == RAT_EAP_MESSAGE) - { - has_eap = TRUE; - } - } - enumerator->destroy(enumerator); - /* restore Response-Authenticator */ - memcpy(this->msg->authenticator, res_auth, HASH_SIZE_MD5); - - if (has_eap && !has_auth) - { /* Message-Authenticator is required if we have an EAP-Message */ - DBG1(DBG_CFG, "RADIUS Message-Authenticator attribute missing"); - return FALSE; - } - return TRUE; -} - -METHOD(radius_message_t, get_code, radius_message_code_t, - private_radius_message_t *this) -{ - return this->msg->code; -} - -METHOD(radius_message_t, get_identifier, u_int8_t, - private_radius_message_t *this) -{ - return this->msg->identifier; -} - -METHOD(radius_message_t, set_identifier, void, - private_radius_message_t *this, u_int8_t identifier) -{ - this->msg->identifier = identifier; -} - -METHOD(radius_message_t, get_authenticator, u_int8_t*, - private_radius_message_t *this) -{ - return this->msg->authenticator; -} - - -METHOD(radius_message_t, get_encoding, chunk_t, - private_radius_message_t *this) -{ - return chunk_create((u_char*)this->msg, ntohs(this->msg->length)); -} - -METHOD(radius_message_t, destroy, void, - private_radius_message_t *this) -{ - free(this->msg); - free(this); -} - -/** - * Generic constructor - */ -static private_radius_message_t *radius_message_create_empty() -{ - private_radius_message_t *this; - - INIT(this, - .public = { - .create_enumerator = _create_enumerator, - .add = _add, - .get_code = _get_code, - .get_identifier = _get_identifier, - .set_identifier = _set_identifier, - .get_authenticator = _get_authenticator, - .get_encoding = _get_encoding, - .sign = _sign, - .verify = _verify, - .destroy = _destroy, - }, - ); - - return this; -} - -/** - * See header - */ -radius_message_t *radius_message_create(radius_message_code_t code) -{ - private_radius_message_t *this = radius_message_create_empty(); - - INIT(this->msg, - .code = code, - .identifier = 0, - .length = htons(sizeof(rmsg_t)), - ); - - return &this->public; -} - -/** - * See header - */ -radius_message_t *radius_message_parse(chunk_t data) -{ - private_radius_message_t *this = radius_message_create_empty(); - - this->msg = malloc(data.len); - memcpy(this->msg, data.ptr, data.len); - if (data.len < sizeof(rmsg_t) || - ntohs(this->msg->length) != data.len) - { - DBG1(DBG_IKE, "RADIUS message has invalid length"); - destroy(this); - return NULL; - } - return &this->public; -} - diff --git a/src/libcharon/plugins/eap_radius/radius_message.h b/src/libcharon/plugins/eap_radius/radius_message.h deleted file mode 100644 index 355714505..000000000 --- a/src/libcharon/plugins/eap_radius/radius_message.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup radius_message radius_message - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_MESSAGE_H_ -#define RADIUS_MESSAGE_H_ - -#include <library.h> - -typedef struct radius_message_t radius_message_t; -typedef enum radius_message_code_t radius_message_code_t; -typedef enum radius_attribute_type_t radius_attribute_type_t; - -/** - * RADIUS Message Codes. - */ -enum radius_message_code_t { - RMC_ACCESS_REQUEST = 1, - RMC_ACCESS_ACCEPT = 2, - RMC_ACCESS_REJECT = 3, - RMC_ACCOUNTING_REQUEST = 4, - RMC_ACCOUNTING_RESPONSE = 5, - RMC_ACCESS_CHALLENGE = 11, - RMC_DISCONNECT_REQUEST = 40, - RMC_DISCONNECT_ACK = 41, - RMC_DISCONNECT_NAK = 42, - RMC_COA_REQUEST = 43, - RMC_COA_ACK = 44, - RMC_COA_NAK = 45, -}; - -/** - * Enum names for radius_attribute_type_t. - */ -extern enum_name_t *radius_message_code_names; - -/** - * RADIUS Attribute Types. - */ -enum radius_attribute_type_t { - RAT_USER_NAME = 1, - RAT_USER_PASSWORD = 2, - RAT_CHAP_PASSWORD = 3, - RAT_NAS_IP_ADDRESS = 4, - RAT_NAS_PORT = 5, - RAT_SERVICE_TYPE = 6, - RAT_FRAMED_PROTOCOL = 7, - RAT_FRAMED_IP_ADDRESS = 8, - RAT_FRAMED_IP_NETMASK = 9, - RAT_FRAMED_ROUTING = 10, - RAT_FILTER_ID = 11, - RAT_FRAMED_MTU = 12, - RAT_FRAMED_COMPRESSION = 13, - RAT_LOGIN_IP_HOST = 14, - RAT_LOGIN_SERVICE = 15, - RAT_LOGIN_TCP_PORT = 16, - RAT_REPLY_MESSAGE = 18, - RAT_CALLBACK_NUMBER = 19, - RAT_CALLBACK_ID = 20, - RAT_FRAMED_ROUTE = 22, - RAT_FRAMED_IPX_NETWORK = 23, - RAT_STATE = 24, - RAT_CLASS = 25, - RAT_VENDOR_SPECIFIC = 26, - RAT_SESSION_TIMEOUT = 27, - RAT_IDLE_TIMEOUT = 28, - RAT_TERMINATION_ACTION = 29, - RAT_CALLED_STATION_ID = 30, - RAT_CALLING_STATION_ID = 31, - RAT_NAS_IDENTIFIER = 32, - RAT_PROXY_STATE = 33, - RAT_LOGIN_LAT_SERVICE = 34, - RAT_LOGIN_LAT_NODE = 35, - RAT_LOGIN_LAT_GROUP = 36, - RAT_FRAMED_APPLETALK_LINK = 37, - RAT_FRAMED_APPLETALK_NETWORK = 38, - RAT_FRAMED_APPLETALK_ZONE = 39, - RAT_ACCT_STATUS_TYPE = 40, - RAT_ACCT_DELAY_TIME = 41, - RAT_ACCT_INPUT_OCTETS = 42, - RAT_ACCT_OUTPUT_OCTETS = 43, - RAT_ACCT_SESSION_ID = 44, - RAT_ACCT_AUTHENTIC = 45, - RAT_ACCT_SESSION_TIME = 46, - RAT_ACCT_INPUT_PACKETS = 47, - RAT_ACCT_OUTPUT_PACKETS = 48, - RAT_ACCT_TERMINATE_CAUSE = 49, - RAT_ACCT_MULTI_SESSION_ID = 50, - RAT_ACCT_LINK_COUNT = 51, - RAT_ACCT_INPUT_GIGAWORDS = 52, - RAT_ACCT_OUTPUT_GIGAWORDS = 53, - RAT_EVENT_TIMESTAMP = 55, - RAT_EGRESS_VLANID = 56, - RAT_INGRESS_FILTERS = 57, - RAT_EGRESS_VLAN_NAME = 58, - RAT_USER_PRIORITY_TABLE = 59, - RAT_CHAP_CHALLENGE = 60, - RAT_NAS_PORT_TYPE = 61, - RAT_PORT_LIMIT = 62, - RAT_LOGIN_LAT_PORT = 63, - RAT_TUNNEL_TYPE = 64, - RAT_TUNNEL_MEDIUM_TYPE = 65, - RAT_TUNNEL_CLIENT_ENDPOINT = 66, - RAT_TUNNEL_SERVER_ENDPOINT = 67, - RAT_ACCT_TUNNEL_CONNECTION = 68, - RAT_TUNNEL_PASSWORD = 69, - RAT_ARAP_PASSWORD = 70, - RAT_ARAP_FEATURES = 71, - RAT_ARAP_ZONE_ACCESS = 72, - RAT_ARAP_SECURITY = 73, - RAT_ARAP_SECURITY_DATA = 74, - RAT_PASSWORD_RETRY = 75, - RAT_PROMPT = 76, - RAT_CONNECT_INFO = 77, - RAT_CONFIGURATION_TOKEN = 78, - RAT_EAP_MESSAGE = 79, - RAT_MESSAGE_AUTHENTICATOR = 80, - RAT_TUNNEL_PRIVATE_GROUP_ID = 81, - RAT_TUNNEL_ASSIGNMENT_ID = 82, - RAT_TUNNEL_PREFERENCE = 83, - RAT_ARAP_CHALLENGE_RESPONSE = 84, - RAT_ACCT_INTERIM_INTERVAL = 85, - RAT_ACCT_TUNNEL_PACKETS_LOST = 86, - RAT_NAS_PORT_ID = 87, - RAT_FRAMED_POOL = 88, - RAT_CUI = 89, - RAT_TUNNEL_CLIENT_AUTH_ID = 90, - RAT_TUNNEL_SERVER_AUTH_ID = 91, - RAT_NAS_FILTER_RULE = 92, - RAT_UNASSIGNED = 93, - RAT_ORIGINATING_LINE_INFO = 94, - RAT_NAS_IPV6_ADDRESS = 95, - RAT_FRAMED_INTERFACE_ID = 96, - RAT_FRAMED_IPV6_PREFIX = 97, - RAT_LOGIN_IPV6_HOST = 98, - RAT_FRAMED_IPV6_ROUTE = 99, - RAT_FRAMED_IPV6_POOL = 100, - RAT_ERROR_CAUSE = 101, - RAT_EAP_KEY_NAME = 102, - RAT_DIGEST_RESPONSE = 103, - RAT_DIGEST_REALM = 104, - RAT_DIGEST_NONCE = 105, - RAT_DIGEST_RESPONSE_AUTH = 106, - RAT_DIGEST_NEXTNONCE = 107, - RAT_DIGEST_METHOD = 108, - RAT_DIGEST_URI = 109, - RAT_DIGEST_QOP = 110, - RAT_DIGEST_ALGORITHM = 111, - RAT_DIGEST_ENTITY_BODY_HASH = 112, - RAT_DIGEST_CNONCE = 113, - RAT_DIGEST_NONCE_COUNT = 114, - RAT_DIGEST_USERNAME = 115, - RAT_DIGEST_OPAQUE = 116, - RAT_DIGEST_AUTH_PARAM = 117, - RAT_DIGEST_AKA_AUTS = 118, - RAT_DIGEST_DOMAIN = 119, - RAT_DIGEST_STALE = 120, - RAT_DIGEST_HA1 = 121, - RAT_SIP_AOR = 122, - RAT_DELEGATED_IPV6_PREFIX = 123, - RAT_MIP6_FEATURE_VECTOR = 124, - RAT_MIP6_HOME_LINK_PREFIX = 125, -}; - -/** - * Enum names for radius_attribute_type_t. - */ -extern enum_name_t *radius_attribute_type_names; - -/** - * A RADIUS message, contains attributes. - */ -struct radius_message_t { - - /** - * Create an enumerator over contained RADIUS attributes. - * - * @return enumerator over (int type, chunk_t data) - */ - enumerator_t* (*create_enumerator)(radius_message_t *this); - - /** - * Add a RADIUS attribute to the message. - * - * @param type type of attribute to add - * @param attribute data, gets cloned - */ - void (*add)(radius_message_t *this, radius_attribute_type_t type, - chunk_t data); - - /** - * Get the message type (code). - * - * @return message code - */ - radius_message_code_t (*get_code)(radius_message_t *this); - - /** - * Get the message identifier. - * - * @return message identifier - */ - u_int8_t (*get_identifier)(radius_message_t *this); - - /** - * Set the message identifier. - * - * @param identifier message identifier - */ - void (*set_identifier)(radius_message_t *this, u_int8_t identifier); - - /** - * Get the 16 byte authenticator. - * - * @return pointer to the Authenticator field - */ - u_int8_t* (*get_authenticator)(radius_message_t *this); - - /** - * Get the RADIUS message in its encoded form. - * - * @return chunk pointing to internal RADIUS message. - */ - chunk_t (*get_encoding)(radius_message_t *this); - - /** - * Calculate and add the Message-Authenticator attribute to the message. - * - * @param req_auth 16 byte Authenticator of request, or NULL - * @param secret shared RADIUS secret - * @param signer HMAC-MD5 signer with secret set - * @param hasher MD5 hasher - * @param rng RNG to create Message-Authenticator, NULL to omit - */ - void (*sign)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer, rng_t *rng); - - /** - * Verify the integrity of a received RADIUS message. - * - * @param req_auth 16 byte Authenticator of request, or NULL - * @param secret shared RADIUS secret - * @param signer HMAC-MD5 signer with secret set - * @param hasher MD5 hasher - */ - bool (*verify)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer); - - /** - * Destroy the message. - */ - void (*destroy)(radius_message_t *this); -}; - -/** - * Create an empty RADIUS message. - * - * @param code request type - * @return radius_message_t object - */ -radius_message_t *radius_message_create(radius_message_code_t code); - -/** - * Parse and verify a recevied RADIUS message. - * - * @param data received message data - * @return radius_message_t object, NULL if length invalid - */ -radius_message_t *radius_message_parse(chunk_t data); - -#endif /** RADIUS_MESSAGE_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c deleted file mode 100644 index 282f50892..000000000 --- a/src/libcharon/plugins/eap_radius/radius_server.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "radius_server.h" - -#include <threading/mutex.h> -#include <threading/condvar.h> -#include <utils/linked_list.h> - -typedef struct private_radius_server_t private_radius_server_t; - -/** - * Private data of an radius_server_t object. - */ -struct private_radius_server_t { - - /** - * Public radius_server_t interface. - */ - radius_server_t public; - - /** - * list of radius sockets, as radius_socket_t - */ - linked_list_t *sockets; - - /** - * Total number of sockets, in list + currently in use - */ - int socket_count; - - /** - * mutex to lock sockets list - */ - mutex_t *mutex; - - /** - * condvar to wait for sockets - */ - condvar_t *condvar; - - /** - * Server name - */ - char *name; - - /** - * NAS-Identifier - */ - chunk_t nas_identifier; - - /** - * Preference boost for this server - */ - int preference; - - /** - * Is the server currently reachable - */ - bool reachable; - - /** - * Retry counter for unreachable servers - */ - int retry; - - /** - * reference count - */ - refcount_t ref; -}; - -METHOD(radius_server_t, get_socket, radius_socket_t*, - private_radius_server_t *this) -{ - radius_socket_t *skt; - - this->mutex->lock(this->mutex); - while (this->sockets->remove_first(this->sockets, (void**)&skt) != SUCCESS) - { - this->condvar->wait(this->condvar, this->mutex); - } - this->mutex->unlock(this->mutex); - return skt; -} - -METHOD(radius_server_t, put_socket, void, - private_radius_server_t *this, radius_socket_t *skt, bool result) -{ - this->mutex->lock(this->mutex); - this->sockets->insert_last(this->sockets, skt); - this->mutex->unlock(this->mutex); - this->condvar->signal(this->condvar); - this->reachable = result; -} - -METHOD(radius_server_t, get_nas_identifier, chunk_t, - private_radius_server_t *this) -{ - return this->nas_identifier; -} - -METHOD(radius_server_t, get_preference, int, - private_radius_server_t *this) -{ - int pref; - - if (this->socket_count == 0) - { /* don't have sockets, huh? */ - return -1; - } - /* calculate preference between 0-100 + boost */ - pref = this->preference; - pref += this->sockets->get_count(this->sockets) * 100 / this->socket_count; - if (this->reachable) - { /* reachable server get a boost: pref = 110-210 + boost */ - return pref + 110; - } - /* Not reachable. Increase preference randomly to let it retry from - * time to time, especially if other servers have high load. */ - this->retry++; - if (this->retry % 128 == 0) - { /* every 64th request gets 210, same as unloaded reachable */ - return pref + 110; - } - if (this->retry % 32 == 0) - { /* every 32th request gets 190, wins against average loaded */ - return pref + 90; - } - if (this->retry % 8 == 0) - { /* every 8th request gets 110, same as server under load */ - return pref + 10; - } - /* other get ~100, less than fully loaded */ - return pref; -} - -METHOD(radius_server_t, get_name, char*, - private_radius_server_t *this) -{ - return this->name; -} - -METHOD(radius_server_t, get_ref, radius_server_t*, - private_radius_server_t *this) -{ - ref_get(&this->ref); - return &this->public; -} - - -METHOD(radius_server_t, destroy, void, - private_radius_server_t *this) -{ - if (ref_put(&this->ref)) - { - this->mutex->destroy(this->mutex); - this->condvar->destroy(this->condvar); - this->sockets->destroy_offset(this->sockets, - offsetof(radius_socket_t, destroy)); - free(this); - } -} - -/** - * See header - */ -radius_server_t *radius_server_create(char *name, char *address, - u_int16_t auth_port, u_int16_t acct_port, - char *nas_identifier, char *secret, - int sockets, int preference) -{ - private_radius_server_t *this; - radius_socket_t *socket; - - INIT(this, - .public = { - .get_socket = _get_socket, - .put_socket = _put_socket, - .get_nas_identifier = _get_nas_identifier, - .get_preference = _get_preference, - .get_name = _get_name, - .get_ref = _get_ref, - .destroy = _destroy, - }, - .reachable = TRUE, - .nas_identifier = chunk_create(nas_identifier, strlen(nas_identifier)), - .socket_count = sockets, - .sockets = linked_list_create(), - .mutex = mutex_create(MUTEX_TYPE_DEFAULT), - .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), - .name = name, - .preference = preference, - .ref = 1, - ); - - while (sockets--) - { - socket = radius_socket_create(address, auth_port, acct_port, - chunk_create(secret, strlen(secret))); - if (!socket) - { - destroy(this); - return NULL; - } - this->sockets->insert_last(this->sockets, socket); - } - return &this->public; -} diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h deleted file mode 100644 index 93b0e5d8d..000000000 --- a/src/libcharon/plugins/eap_radius/radius_server.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup radius_server radius_server - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_SERVER_H_ -#define RADIUS_SERVER_H_ - -typedef struct radius_server_t radius_server_t; - -#include "radius_socket.h" - -/** - * RADIUS server configuration. - */ -struct radius_server_t { - - /** - * Get a RADIUS socket from the pool to communicate with this server. - * - * @return RADIUS socket - */ - radius_socket_t* (*get_socket)(radius_server_t *this); - - /** - * Release a socket to the pool after use. - * - * @param skt RADIUS socket to release - * @param result result of the socket use, TRUE for success - */ - void (*put_socket)(radius_server_t *this, radius_socket_t *skt, bool result); - - /** - * Get the NAS-Identifier to use with this server. - * - * @return NAS-Identifier, internal data - */ - chunk_t (*get_nas_identifier)(radius_server_t *this); - - /** - * Get the preference of this server. - * - * Based on the available sockets and the server reachability a preference - * value is calculated: better servers return a higher value. - */ - int (*get_preference)(radius_server_t *this); - - /** - * Get the name of the RADIUS server. - * - * @return server name - */ - char* (*get_name)(radius_server_t *this); - - /** - * Increase reference count of this server. - * - * @return this - */ - radius_server_t* (*get_ref)(radius_server_t *this); - - /** - * Destroy a radius_server_t. - */ - void (*destroy)(radius_server_t *this); -}; - -/** - * Create a radius_server instance. - * - * @param name server name - * @param address server 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 - * @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 *name, char *address, - u_int16_t auth_port, u_int16_t acct_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 deleted file mode 100644 index 875bd61e9..000000000 --- a/src/libcharon/plugins/eap_radius/radius_socket.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "radius_socket.h" - -#include <errno.h> -#include <unistd.h> - -#include <debug.h> - -/** - * Vendor-Id of Microsoft specific attributes - */ -#define VENDOR_ID_MICROSOFT 311 - -/** - * Microsoft specific vendor attributes - */ -#define MS_MPPE_SEND_KEY 16 -#define MS_MPPE_RECV_KEY 17 - -typedef struct private_radius_socket_t private_radius_socket_t; - -/** - * Private data of an radius_socket_t object. - */ -struct private_radius_socket_t { - - /** - * Public radius_socket_t interface. - */ - radius_socket_t public; - - /** - * Server port for authentication - */ - u_int16_t auth_port; - - /** - * socket file descriptor for authentication - */ - int auth_fd; - - /** - * Server port for accounting - */ - u_int16_t acct_port; - - /** - * socket file descriptor for accounting - */ - int acct_fd; - - /** - * Server address - */ - char *address; - - /** - * current RADIUS identifier - */ - u_int8_t identifier; - - /** - * hasher to use for response verification - */ - hasher_t *hasher; - - /** - * HMAC-MD5 signer to build Message-Authenticator attribute - */ - signer_t *signer; - - /** - * random number generator for RADIUS request authenticator - */ - rng_t *rng; - - /** - * RADIUS secret - */ - chunk_t secret; -}; - -/** - * Check or establish RADIUS connection - */ -static bool check_connection(private_radius_socket_t *this, - int *fd, u_int16_t port) -{ - if (*fd == -1) - { - host_t *server; - - server = host_create_from_dns(this->address, AF_UNSPEC, port); - if (!server) - { - DBG1(DBG_CFG, "resolving RADIUS server address '%s' failed", - this->address); - return FALSE; - } - *fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP); - if (*fd == -1) - { - DBG1(DBG_CFG, "opening RADIUS socket for %#H failed: %s", - server, strerror(errno)); - server->destroy(server); - return FALSE; - } - 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; - } - server->destroy(server); - } - return TRUE; -} - -METHOD(radius_socket_t, request, radius_message_t*, - private_radius_socket_t *this, radius_message_t *request) -{ - chunk_t data; - int i, *fd; - u_int16_t port; - rng_t *rng = NULL; - - if (request->get_code(request) == RMC_ACCOUNTING_REQUEST) - { - fd = &this->acct_fd; - port = this->acct_port; - } - else - { - fd = &this->auth_fd; - port = this->auth_port; - rng = this->rng; - } - - /* set Message Identifier */ - request->set_identifier(request, this->identifier++); - /* sign the request */ - request->sign(request, NULL, this->secret, this->hasher, this->signer, rng); - - if (!check_connection(this, fd, port)) - { - return NULL; - } - - data = request->get_encoding(request); - /* timeout after 2, 3, 4, 5 seconds */ - for (i = 2; i <= 5; i++) - { - radius_message_t *response; - bool retransmit = FALSE; - struct timeval tv; - char buf[4096]; - fd_set fds; - int res; - - if (send(*fd, data.ptr, data.len, 0) != data.len) - { - DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); - return NULL; - } - tv.tv_sec = i; - tv.tv_usec = 0; - - while (TRUE) - { - FD_ZERO(&fds); - FD_SET(*fd, &fds); - res = select((*fd) + 1, &fds, NULL, NULL, &tv); - /* TODO: updated tv to time not waited. Linux does this for us. */ - if (res < 0) - { /* failed */ - DBG1(DBG_CFG, "waiting for RADIUS message failed: %s", - strerror(errno)); - break; - } - if (res == 0) - { /* timeout */ - DBG1(DBG_CFG, "retransmitting RADIUS message"); - retransmit = TRUE; - break; - } - res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT); - if (res <= 0) - { - DBG1(DBG_CFG, "receiving RADIUS message failed: %s", - strerror(errno)); - break; - } - response = radius_message_parse(chunk_create(buf, res)); - if (response) - { - if (response->verify(response, - request->get_authenticator(request), this->secret, - this->hasher, this->signer)) - { - return response; - } - response->destroy(response); - } - DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); - } - if (!retransmit) - { - break; - } - } - DBG1(DBG_CFG, "RADIUS server is not responding"); - return NULL; -} - -/** - * Decrypt a MS-MPPE-Send/Recv-Key - */ -static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt, - chunk_t C, radius_message_t *request) -{ - chunk_t A, R, P, seed; - u_char *c, *p; - - /** - * From RFC2548 (encryption): - * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) - * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) - * . . . - * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) - */ - - if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5) - { - return chunk_empty; - } - - A = chunk_create((u_char*)&salt, sizeof(salt)); - R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); - P = chunk_alloca(C.len); - p = P.ptr; - c = C.ptr; - - seed = chunk_cata("cc", R, A); - - while (c < C.ptr + C.len) - { - /* b(i) = MD5(S + c(i-1)) */ - this->hasher->get_hash(this->hasher, this->secret, NULL); - this->hasher->get_hash(this->hasher, seed, p); - - /* p(i) = b(i) xor c(1) */ - memxor(p, c, HASH_SIZE_MD5); - - /* prepare next round */ - seed = chunk_create(c, HASH_SIZE_MD5); - c += HASH_SIZE_MD5; - p += HASH_SIZE_MD5; - } - - /* remove truncation, first byte is key length */ - if (*P.ptr >= P.len) - { /* decryption failed? */ - return chunk_empty; - } - return chunk_clone(chunk_create(P.ptr + 1, *P.ptr)); -} - -METHOD(radius_socket_t, decrypt_msk, chunk_t, - private_radius_socket_t *this, radius_message_t *request, - radius_message_t *response) -{ - struct { - u_int32_t id; - u_int8_t type; - u_int8_t length; - u_int16_t salt; - u_int8_t key[]; - } __attribute__((packed)) *mppe_key; - enumerator_t *enumerator; - chunk_t data, send = chunk_empty, recv = chunk_empty; - int type; - - enumerator = response->create_enumerator(response); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_VENDOR_SPECIFIC && - data.len > sizeof(*mppe_key)) - { - mppe_key = (void*)data.ptr; - if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT && - mppe_key->length == data.len - sizeof(mppe_key->id)) - { - data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key)); - if (mppe_key->type == MS_MPPE_SEND_KEY) - { - send = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - if (mppe_key->type == MS_MPPE_RECV_KEY) - { - recv = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - } - } - } - enumerator->destroy(enumerator); - if (send.ptr && recv.ptr) - { - return chunk_cat("mm", recv, send); - } - chunk_clear(&send); - chunk_clear(&recv); - return chunk_empty; -} - -METHOD(radius_socket_t, destroy, void, - private_radius_socket_t *this) -{ - DESTROY_IF(this->hasher); - DESTROY_IF(this->signer); - DESTROY_IF(this->rng); - if (this->auth_fd != -1) - { - close(this->auth_fd); - }; - if (this->acct_fd != -1) - { - close(this->acct_fd); - } - free(this); -} - -/** - * See header - */ -radius_socket_t *radius_socket_create(char *address, u_int16_t auth_port, - u_int16_t acct_port, chunk_t secret) -{ - private_radius_socket_t *this; - - INIT(this, - .public = { - .request = _request, - .decrypt_msk = _decrypt_msk, - .destroy = _destroy, - }, - .address = address, - .auth_port = auth_port, - .auth_fd = -1, - .acct_port = acct_port, - .acct_fd = -1, - ); - - 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); - if (!this->hasher || !this->signer || !this->rng) - { - DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required"); - destroy(this); - return NULL; - } - this->secret = secret; - this->signer->set_key(this->signer, secret); - /* we use a random identifier, helps if we restart often */ - this->identifier = random(); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h deleted file mode 100644 index 0301ec6d0..000000000 --- a/src/libcharon/plugins/eap_radius/radius_socket.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup radius_socket radius_socket - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_SOCKET_H_ -#define RADIUS_SOCKET_H_ - -typedef struct radius_socket_t radius_socket_t; - -#include "radius_message.h" - -#include <utils/host.h> - -/** - * RADIUS socket to a server. - */ -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. - * The received response gets verified using the Response-Identifier - * and the Message-Authenticator attribute. - * - * @param request request message - * @return response message, NULL if timed out - */ - radius_message_t* (*request)(radius_socket_t *this, - radius_message_t *request); - - /** - * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key. - * - * @param request associated RADIUS request message - * @param response RADIUS response message containing attributes - * @return allocated MSK, empty chunk if none found - */ - chunk_t (*decrypt_msk)(radius_socket_t *this, radius_message_t *request, - radius_message_t *response); - - /** - * Destroy a radius_socket_t. - */ - void (*destroy)(radius_socket_t *this); -}; - -/** - * Create a radius_socket instance. - * - * @param address server name - * @param auth_port server port for authentication - * @param acct_port server port for accounting - * @param secret RADIUS secret - */ -radius_socket_t *radius_socket_create(char *address, u_int16_t auth_port, - u_int16_t acct_port, chunk_t secret); - -#endif /** RADIUS_SOCKET_H_ @}*/ |