Added infrastructure to listen to RADIUS Dynamic Authorization Extension requests

This commit is contained in:
Martin Willi 2012-02-22 10:34:06 +01:00
parent 3a42c08904
commit 85932ad24e
3 changed files with 228 additions and 0 deletions

View File

@ -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 \

View File

@ -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;
}

View File

@ -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_ @}*/