diff options
author | Martin Willi <martin@revosec.ch> | 2012-02-22 10:34:06 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-05 18:06:13 +0100 |
commit | 85932ad24e30c0016c48d9dfbf7858e204e2c58a (patch) | |
tree | 2f1d6632c7f2eb0d15a32cdc820bc1f0f46b98ea /src | |
parent | 3a42c089043fb73780bf6a3cb465e53ebdc213bb (diff) | |
download | strongswan-85932ad24e30c0016c48d9dfbf7858e204e2c58a.tar.bz2 strongswan-85932ad24e30c0016c48d9dfbf7858e204e2c58a.tar.xz |
Added infrastructure to listen to RADIUS Dynamic Authorization Extension requests
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/plugins/eap_radius/Makefile.am | 1 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_dae.c | 183 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_dae.h | 44 |
3 files changed, 228 insertions, 0 deletions
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index c07f9ab95..403f85806 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -14,6 +14,7 @@ libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ eap_radius_accounting.h eap_radius_accounting.c \ + eap_radius_dae.h eap_radius_dae.c \ radius_server.h radius_server.c \ radius_socket.h radius_socket.c \ radius_client.h radius_client.c \ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c new file mode 100644 index 000000000..c6f5d84b3 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "eap_radius_dae.h" + +#include "radius_message.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <unistd.h> +#include <errno.h> + +#include <daemon.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> + +#define RADIUS_DAE_PORT 3799 + +typedef struct private_eap_radius_dae_t private_eap_radius_dae_t; + +/** + * Private data of an eap_radius_dae_t object. + */ +struct private_eap_radius_dae_t { + + /** + * Public eap_radius_dae_t interface. + */ + eap_radius_dae_t public; + + /** + * RADIUS session state + */ + eap_radius_accounting_t *accounting; + + /** + * Socket to listen on authorization extension port + */ + int fd; + + /** + * Listen job + */ + callback_job_t *job; +}; + +/** + * Receive RADIUS DAE requests + */ +static job_requeue_t receive(private_eap_radius_dae_t *this) +{ + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + radius_message_t *request; + char buf[2048]; + ssize_t len; + bool oldstate; + + oldstate = thread_cancelability(TRUE); + len = recvfrom(this->fd, buf, sizeof(buf), 0, + (struct sockaddr*)&addr, &addr_len); + thread_cancelability(oldstate); + + if (len > 0) + { + request = radius_message_parse_response(chunk_create(buf, len)); + if (request) + { + switch (request->get_code(request)) + { + case RMC_DISCONNECT_REQUEST: + /* TODO */ + case RMC_COA_REQUEST: + /* TODO */ + default: + DBG1(DBG_CFG, "ignoring unsupported RADIUS DAE %N message", + radius_message_code_names, request->get_code(request)); + break; + } + request->destroy(request); + } + else + { + DBG1(DBG_NET, "ignoring invalid RADIUS DAE request"); + } + } + else + { + DBG1(DBG_NET, "receving RADIUS DAE request failed: %s", strerror(errno)); + } + return JOB_REQUEUE_DIRECT; +} + +/** + * Open DAE socket + */ +static bool open_socket(private_eap_radius_dae_t *this) +{ + host_t *host; + + this->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (this->fd == -1) + { + DBG1(DBG_CFG, "unable to open RADIUS DAE socket: %s", strerror(errno)); + return FALSE; + } + + host = host_create_from_string( + lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.dae.listen", "0.0.0.0"), + lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.dae.port", RADIUS_DAE_PORT)); + if (!host) + { + DBG1(DBG_CFG, "invalid RADIUS DAE listen address"); + return FALSE; + } + + if (bind(this->fd, host->get_sockaddr(host), + *host->get_sockaddr_len(host)) == -1) + { + DBG1(DBG_CFG, "unable to bind RADIUS DAE socket: %s", strerror(errno)); + host->destroy(host); + return FALSE; + } + host->destroy(host); + return TRUE; +} + +METHOD(eap_radius_dae_t, destroy, void, + private_eap_radius_dae_t *this) +{ + if (this->job) + { + this->job->cancel(this->job); + } + if (this->fd != -1) + { + close(this->fd); + } + free(this); +} + +/** + * See header + */ +eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting) +{ + private_eap_radius_dae_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .accounting = accounting, + .fd = -1, + ); + + if (!open_socket(this)) + { + destroy(this); + return NULL; + } + + this->job = callback_job_create_with_prio((callback_job_cb_t)receive, + this, NULL, NULL, JOB_PRIO_CRITICAL); + lib->processor->queue_job(lib->processor, (job_t*)this->job); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.h b/src/libcharon/plugins/eap_radius/eap_radius_dae.h new file mode 100644 index 000000000..759eadb49 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 eap_radius_dae eap_radius_dae + * @{ @ingroup eap_radius + */ + +#ifndef EAP_RADIUS_DAE_H_ +#define EAP_RADIUS_DAE_H_ + +#include "eap_radius_accounting.h" + +typedef struct eap_radius_dae_t eap_radius_dae_t; + +/** + * Dynamic Authorization Extensions (RFC 5176) for EAP-RADIUS. + */ +struct eap_radius_dae_t { + + /** + * Destroy a eap_radius_dae_t. + */ + void (*destroy)(eap_radius_dae_t *this); +}; + +/** + * Create a eap_radius_dae instance. + */ +eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting); + +#endif /** EAP_RADIUS_DAE_H_ @}*/ |