implemented RADIUS Filter-ID attribute
This commit is contained in:
@@ -181,10 +181,12 @@ static void send_message(private_tnc_pdp_t *this, radius_message_t *message,
|
|||||||
*/
|
*/
|
||||||
static void send_response(private_tnc_pdp_t *this,
|
static void send_response(private_tnc_pdp_t *this,
|
||||||
radius_message_t *request, radius_message_code_t code,
|
radius_message_t *request, radius_message_code_t code,
|
||||||
eap_payload_t *eap, host_t *client)
|
eap_payload_t *eap, identification_t *group,
|
||||||
|
host_t *client)
|
||||||
{
|
{
|
||||||
radius_message_t *response;
|
radius_message_t *response;
|
||||||
chunk_t data;
|
chunk_t data;
|
||||||
|
u_int32_t tunnel_type;
|
||||||
|
|
||||||
response = radius_message_create(code);
|
response = radius_message_create(code);
|
||||||
if (eap)
|
if (eap)
|
||||||
@@ -201,6 +203,14 @@ static void send_response(private_tnc_pdp_t *this,
|
|||||||
}
|
}
|
||||||
response->add(response, RAT_EAP_MESSAGE, data);
|
response->add(response, RAT_EAP_MESSAGE, data);
|
||||||
}
|
}
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
tunnel_type = RADIUS_TUNNEL_TYPE_ESP;
|
||||||
|
htoun32(data.ptr, tunnel_type);
|
||||||
|
data.len = sizeof(tunnel_type);
|
||||||
|
response->add(response, RAT_TUNNEL_TYPE, data);
|
||||||
|
response->add(response, RAT_FILTER_ID, group->get_encoding(group));
|
||||||
|
}
|
||||||
response->set_identifier(response, request->get_identifier(request));
|
response->set_identifier(response, request->get_identifier(request));
|
||||||
response->sign(response, request->get_authenticator(request),
|
response->sign(response, request->get_authenticator(request),
|
||||||
this->secret, this->hasher, this->signer, NULL, TRUE);
|
this->secret, this->hasher, this->signer, NULL, TRUE);
|
||||||
@@ -221,10 +231,11 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
|
|||||||
eap_payload_t *in, *out = NULL;
|
eap_payload_t *in, *out = NULL;
|
||||||
eap_method_t *method;
|
eap_method_t *method;
|
||||||
eap_type_t eap_type;
|
eap_type_t eap_type;
|
||||||
|
u_int32_t eap_vendor;
|
||||||
chunk_t data, message = chunk_empty;
|
chunk_t data, message = chunk_empty;
|
||||||
chunk_t user_name = chunk_empty, nas_id = chunk_empty;
|
chunk_t user_name = chunk_empty, nas_id = chunk_empty;
|
||||||
|
identification_t *group = NULL;
|
||||||
radius_message_code_t code = RMC_ACCESS_CHALLENGE;
|
radius_message_code_t code = RMC_ACCESS_CHALLENGE;
|
||||||
u_int32_t eap_vendor;
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
enumerator = request->create_enumerator(request);
|
enumerator = request->create_enumerator(request);
|
||||||
@@ -258,7 +269,6 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
|
|||||||
eap_type = in->get_type(in, &eap_vendor);
|
eap_type = in->get_type(in, &eap_vendor);
|
||||||
|
|
||||||
DBG3(DBG_CFG, "%N payload %B", eap_type_names, eap_type, &message);
|
DBG3(DBG_CFG, "%N payload %B", eap_type_names, eap_type, &message);
|
||||||
free(message.ptr);
|
|
||||||
|
|
||||||
if (eap_type == EAP_IDENTITY)
|
if (eap_type == EAP_IDENTITY)
|
||||||
{
|
{
|
||||||
@@ -267,30 +277,36 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
|
|||||||
|
|
||||||
if (message.len < 5)
|
if (message.len < 5)
|
||||||
{
|
{
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
eap_identity = chunk_create(message.ptr + 5, message.len - 5);
|
eap_identity = chunk_create(message.ptr + 5, message.len - 5);
|
||||||
peer = identification_create_from_data(eap_identity);
|
peer = identification_create_from_data(eap_identity);
|
||||||
|
|
||||||
method = charon->eap->create_instance(charon->eap, this->type,
|
method = charon->eap->create_instance(charon->eap, this->type,
|
||||||
0, EAP_SERVER, this->server, peer);
|
0, EAP_SERVER, this->server, peer);
|
||||||
peer->destroy(peer);
|
|
||||||
if (!method)
|
if (!method)
|
||||||
{
|
{
|
||||||
in->destroy(in);
|
peer->destroy(peer);
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
this->connections->add(this->connections, nas_id, user_name, method);
|
this->connections->add(this->connections, nas_id, user_name, peer,
|
||||||
|
method);
|
||||||
method->initiate(method, &out);
|
method->initiate(method, &out);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
method = this->connections->get_method(this->connections, nas_id,
|
ike_sa_t *ike_sa;
|
||||||
user_name);
|
auth_cfg_t *auth;
|
||||||
|
auth_rule_t type;
|
||||||
|
identification_t *data;
|
||||||
|
enumerator_t *e;
|
||||||
|
|
||||||
|
method = this->connections->get_state(this->connections, nas_id,
|
||||||
|
user_name, &ike_sa);
|
||||||
if (!method)
|
if (!method)
|
||||||
{
|
{
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
|
charon->bus->set_sa(charon->bus, ike_sa);
|
||||||
|
|
||||||
switch (method->process(method, in, &out))
|
switch (method->process(method, in, &out))
|
||||||
{
|
{
|
||||||
@@ -299,6 +315,19 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
|
|||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
code = RMC_ACCESS_ACCEPT;
|
code = RMC_ACCESS_ACCEPT;
|
||||||
|
|
||||||
|
auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
|
||||||
|
e = auth->create_enumerator(auth);
|
||||||
|
while (e->enumerate(e, &type, &data))
|
||||||
|
{
|
||||||
|
/* look for group memberships */
|
||||||
|
if (type == AUTH_RULE_GROUP)
|
||||||
|
{
|
||||||
|
group = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e->destroy(e);
|
||||||
|
|
||||||
DESTROY_IF(out);
|
DESTROY_IF(out);
|
||||||
out = eap_payload_create_code(EAP_SUCCESS,
|
out = eap_payload_create_code(EAP_SUCCESS,
|
||||||
in->get_identifier(in));
|
in->get_identifier(in));
|
||||||
@@ -310,16 +339,20 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request,
|
|||||||
out = eap_payload_create_code(EAP_FAILURE,
|
out = eap_payload_create_code(EAP_FAILURE,
|
||||||
in->get_identifier(in));
|
in->get_identifier(in));
|
||||||
}
|
}
|
||||||
|
charon->bus->set_sa(charon->bus, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send_response(this, request, code, out, group, source);
|
||||||
|
out->destroy(out);
|
||||||
|
|
||||||
if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT)
|
if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT)
|
||||||
{
|
{
|
||||||
this->connections->remove(this->connections, nas_id, user_name);
|
this->connections->remove(this->connections, nas_id, user_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
send_response(this, request, code, out, source);
|
end:
|
||||||
|
free(message.ptr);
|
||||||
in->destroy(in);
|
in->destroy(in);
|
||||||
out->destroy(out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,13 +485,12 @@ METHOD(tnc_pdp_t, destroy, void,
|
|||||||
tnc_pdp_t *tnc_pdp_create(u_int16_t port)
|
tnc_pdp_t *tnc_pdp_create(u_int16_t port)
|
||||||
{
|
{
|
||||||
private_tnc_pdp_t *this;
|
private_tnc_pdp_t *this;
|
||||||
char *secret, *server;
|
char *secret, *server, *eap_type_str;
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.type = EAP_TTLS,
|
|
||||||
.ipv4 = open_socket(this, AF_INET, port),
|
.ipv4 = open_socket(this, AF_INET, port),
|
||||||
.ipv6 = open_socket(this, AF_INET6, port),
|
.ipv6 = open_socket(this, AF_INET6, port),
|
||||||
.hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5),
|
.hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5),
|
||||||
@@ -507,6 +539,16 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port)
|
|||||||
this->secret = chunk_create(secret, strlen(secret));
|
this->secret = chunk_create(secret, strlen(secret));
|
||||||
this->signer->set_key(this->signer, this->secret);
|
this->signer->set_key(this->signer, this->secret);
|
||||||
|
|
||||||
|
eap_type_str = lib->settings->get_str(lib->settings,
|
||||||
|
"charon.plugins.tnc-pdp.method", "ttls");
|
||||||
|
this->type = eap_type_from_string(eap_type_str);
|
||||||
|
if (this->type == 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "unrecognized eap method \"%s\"", eap_type_str);
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DBG1(DBG_IKE, "eap method %N selected", eap_type_names, this->type);
|
||||||
|
|
||||||
this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
|
this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
|
||||||
this, NULL, NULL, JOB_PRIO_CRITICAL);
|
this, NULL, NULL, JOB_PRIO_CRITICAL);
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ struct entry_t {
|
|||||||
* EAP method state
|
* EAP method state
|
||||||
*/
|
*/
|
||||||
eap_method_t *method;
|
eap_method_t *method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IKE SA used for bus communication
|
||||||
|
*/
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,6 +69,7 @@ struct entry_t {
|
|||||||
static void free_entry(entry_t *this)
|
static void free_entry(entry_t *this)
|
||||||
{
|
{
|
||||||
this->method->destroy(this->method);
|
this->method->destroy(this->method);
|
||||||
|
this->ike_sa->destroy(this->ike_sa);
|
||||||
free(this->nas_id.ptr);
|
free(this->nas_id.ptr);
|
||||||
free(this->user_name.ptr);
|
free(this->user_name.ptr);
|
||||||
free(this);
|
free(this);
|
||||||
@@ -100,12 +106,19 @@ static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
|
|||||||
|
|
||||||
METHOD(tnc_pdp_connections_t, add, void,
|
METHOD(tnc_pdp_connections_t, add, void,
|
||||||
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
|
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
|
||||||
eap_method_t *method)
|
identification_t *peer, eap_method_t *method)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
entry_t *entry;
|
entry_t *entry;
|
||||||
|
ike_sa_id_t *ike_sa_id;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
bool found = FALSE;
|
bool found = FALSE;
|
||||||
|
|
||||||
|
ike_sa_id = ike_sa_id_create(0, 0, FALSE);
|
||||||
|
ike_sa = ike_sa_create(ike_sa_id);
|
||||||
|
ike_sa_id->destroy(ike_sa_id);
|
||||||
|
ike_sa->set_other_id(ike_sa, peer);
|
||||||
|
|
||||||
enumerator = this->list->create_enumerator(this->list);
|
enumerator = this->list->create_enumerator(this->list);
|
||||||
while (enumerator->enumerate(enumerator, &entry))
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
{
|
{
|
||||||
@@ -113,8 +126,10 @@ METHOD(tnc_pdp_connections_t, add, void,
|
|||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
entry->method->destroy(entry->method);
|
entry->method->destroy(entry->method);
|
||||||
|
entry->ike_sa->destroy(entry->ike_sa);
|
||||||
DBG1(DBG_CFG, "removed stale RADIUS connection");
|
DBG1(DBG_CFG, "removed stale RADIUS connection");
|
||||||
entry->method = method;
|
entry->method = method;
|
||||||
|
entry->ike_sa = ike_sa;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +141,7 @@ METHOD(tnc_pdp_connections_t, add, void,
|
|||||||
entry->nas_id = chunk_clone(nas_id);
|
entry->nas_id = chunk_clone(nas_id);
|
||||||
entry->user_name = chunk_clone(user_name);
|
entry->user_name = chunk_clone(user_name);
|
||||||
entry->method = method;
|
entry->method = method;
|
||||||
|
entry->ike_sa = ike_sa;
|
||||||
this->list->insert_last(this->list, entry);
|
this->list->insert_last(this->list, entry);
|
||||||
}
|
}
|
||||||
dbg_nas_user(nas_id, user_name, FALSE, "created");
|
dbg_nas_user(nas_id, user_name, FALSE, "created");
|
||||||
@@ -151,8 +167,9 @@ METHOD(tnc_pdp_connections_t, remove_, void,
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tnc_pdp_connections_t, get_method, eap_method_t*,
|
METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
|
||||||
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
|
private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
|
||||||
|
ike_sa_t **ike_sa)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
entry_t *entry;
|
entry_t *entry;
|
||||||
@@ -164,6 +181,7 @@ METHOD(tnc_pdp_connections_t, get_method, eap_method_t*,
|
|||||||
if (equals_entry(entry, nas_id, user_name))
|
if (equals_entry(entry, nas_id, user_name))
|
||||||
{
|
{
|
||||||
found = entry->method;
|
found = entry->method;
|
||||||
|
*ike_sa = entry->ike_sa;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +209,7 @@ tnc_pdp_connections_t *tnc_pdp_connections_create(void)
|
|||||||
.public = {
|
.public = {
|
||||||
.add = _add,
|
.add = _add,
|
||||||
.remove = _remove_,
|
.remove = _remove_,
|
||||||
.get_method = _get_method,
|
.get_state = _get_state,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.list = linked_list_create(),
|
.list = linked_list_create(),
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
typedef struct tnc_pdp_connections_t tnc_pdp_connections_t;
|
typedef struct tnc_pdp_connections_t tnc_pdp_connections_t;
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
#include <sa/ike_sa.h>
|
||||||
#include <sa/authenticators/eap/eap_method.h>
|
#include <sa/authenticators/eap/eap_method.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,10 +37,11 @@ struct tnc_pdp_connections_t {
|
|||||||
*
|
*
|
||||||
* @param nas_id NAS identifier of Policy Enforcement Point
|
* @param nas_id NAS identifier of Policy Enforcement Point
|
||||||
* @param user_name User name of TNC Client
|
* @param user_name User name of TNC Client
|
||||||
|
* @param peer Peer identity
|
||||||
* @param method EAP method state for this TNC PEP Connection
|
* @param method EAP method state for this TNC PEP Connection
|
||||||
*/
|
*/
|
||||||
void (*add)(tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
|
void (*add)(tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
|
||||||
eap_method_t *method);
|
identification_t *peer, eap_method_t *method);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a TNC PEP RADIUS Connection
|
* Remove a TNC PEP RADIUS Connection
|
||||||
@@ -51,14 +53,15 @@ struct tnc_pdp_connections_t {
|
|||||||
chunk_t user_name);
|
chunk_t user_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the EAP method of a registered TNC PEP RADIUS Connection
|
* Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection
|
||||||
*
|
*
|
||||||
* @param nas_id NAS identifier of Policy Enforcement Point
|
* @param nas_id NAS identifier of Policy Enforcement Point
|
||||||
* @param user_name User name of TNC Client
|
* @param user_name User name of TNC Client
|
||||||
|
* @param ike_sa IKE_SA used for bus communication only
|
||||||
* @return EAP method for this connection or NULL if not found
|
* @return EAP method for this connection or NULL if not found
|
||||||
*/
|
*/
|
||||||
eap_method_t* (*get_method)(tnc_pdp_connections_t *this, chunk_t nas_id,
|
eap_method_t* (*get_state)(tnc_pdp_connections_t *this, chunk_t nas_id,
|
||||||
chunk_t user_name);
|
chunk_t user_name, ike_sa_t **ike_sa);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys a tnc_pdp_connections_t object.
|
* Destroys a tnc_pdp_connections_t object.
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#define MAX_RADIUS_ATTRIBUTE_SIZE 253
|
#define MAX_RADIUS_ATTRIBUTE_SIZE 253
|
||||||
|
|
||||||
|
#define RADIUS_TUNNEL_TYPE_ESP 9
|
||||||
|
|
||||||
typedef struct radius_message_t radius_message_t;
|
typedef struct radius_message_t radius_message_t;
|
||||||
typedef enum radius_message_code_t radius_message_code_t;
|
typedef enum radius_message_code_t radius_message_code_t;
|
||||||
typedef enum radius_attribute_type_t radius_attribute_type_t;
|
typedef enum radius_attribute_type_t radius_attribute_type_t;
|
||||||
|
|||||||
Reference in New Issue
Block a user