*/
static void send_response(private_tnc_pdp_t *this,
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;
chunk_t data;
+ u_int32_t tunnel_type;
response = radius_message_create(code);
if (eap)
}
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->sign(response, request->get_authenticator(request),
this->secret, this->hasher, this->signer, NULL, TRUE);
eap_payload_t *in, *out = NULL;
eap_method_t *method;
eap_type_t eap_type;
+ u_int32_t eap_vendor;
chunk_t data, message = chunk_empty;
chunk_t user_name = chunk_empty, nas_id = chunk_empty;
+ identification_t *group = NULL;
radius_message_code_t code = RMC_ACCESS_CHALLENGE;
- u_int32_t eap_vendor;
int type;
enumerator = request->create_enumerator(request);
eap_type = in->get_type(in, &eap_vendor);
DBG3(DBG_CFG, "%N payload %B", eap_type_names, eap_type, &message);
- free(message.ptr);
if (eap_type == EAP_IDENTITY)
{
if (message.len < 5)
{
- return;
+ goto end;
}
eap_identity = chunk_create(message.ptr + 5, message.len - 5);
peer = identification_create_from_data(eap_identity);
-
method = charon->eap->create_instance(charon->eap, this->type,
0, EAP_SERVER, this->server, peer);
- peer->destroy(peer);
if (!method)
{
- in->destroy(in);
- return;
+ peer->destroy(peer);
+ 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);
}
else
{
- method = this->connections->get_method(this->connections, nas_id,
- user_name);
+ ike_sa_t *ike_sa;
+ 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)
{
- return;
+ goto end;
}
+ charon->bus->set_sa(charon->bus, ike_sa);
switch (method->process(method, in, &out))
{
break;
case SUCCESS:
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);
out = eap_payload_create_code(EAP_SUCCESS,
in->get_identifier(in));
out = eap_payload_create_code(EAP_FAILURE,
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)
{
this->connections->remove(this->connections, nas_id, user_name);
}
- send_response(this, request, code, out, source);
+end:
+ free(message.ptr);
in->destroy(in);
- out->destroy(out);
}
}
tnc_pdp_t *tnc_pdp_create(u_int16_t port)
{
private_tnc_pdp_t *this;
- char *secret, *server;
+ char *secret, *server, *eap_type_str;
INIT(this,
.public = {
.destroy = _destroy,
},
- .type = EAP_TTLS,
.ipv4 = open_socket(this, AF_INET, port),
.ipv6 = open_socket(this, AF_INET6, port),
.hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5),
this->secret = chunk_create(secret, strlen(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, NULL, NULL, JOB_PRIO_CRITICAL);
* EAP method state
*/
eap_method_t *method;
+
+ /**
+ * IKE SA used for bus communication
+ */
+ ike_sa_t *ike_sa;
};
/**
static void free_entry(entry_t *this)
{
this->method->destroy(this->method);
+ this->ike_sa->destroy(this->ike_sa);
free(this->nas_id.ptr);
free(this->user_name.ptr);
free(this);
METHOD(tnc_pdp_connections_t, add, void,
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;
entry_t *entry;
+ ike_sa_id_t *ike_sa_id;
+ ike_sa_t *ike_sa;
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);
while (enumerator->enumerate(enumerator, &entry))
{
{
found = TRUE;
entry->method->destroy(entry->method);
+ entry->ike_sa->destroy(entry->ike_sa);
DBG1(DBG_CFG, "removed stale RADIUS connection");
entry->method = method;
+ entry->ike_sa = ike_sa;
break;
}
}
entry->nas_id = chunk_clone(nas_id);
entry->user_name = chunk_clone(user_name);
entry->method = method;
+ entry->ike_sa = ike_sa;
this->list->insert_last(this->list, entry);
}
dbg_nas_user(nas_id, user_name, FALSE, "created");
enumerator->destroy(enumerator);
}
-METHOD(tnc_pdp_connections_t, get_method, eap_method_t*,
- private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
+METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
+ private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
+ ike_sa_t **ike_sa)
{
enumerator_t *enumerator;
entry_t *entry;
if (equals_entry(entry, nas_id, user_name))
{
found = entry->method;
+ *ike_sa = entry->ike_sa;
break;
}
}
.public = {
.add = _add,
.remove = _remove_,
- .get_method = _get_method,
+ .get_state = _get_state,
.destroy = _destroy,
},
.list = linked_list_create(),
typedef struct tnc_pdp_connections_t tnc_pdp_connections_t;
#include <library.h>
+#include <sa/ike_sa.h>
#include <sa/authenticators/eap/eap_method.h>
/**
*
* @param nas_id NAS identifier of Policy Enforcement Point
* @param user_name User name of TNC Client
+ * @param peer Peer identity
* @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,
- eap_method_t *method);
+ identification_t *peer, eap_method_t *method);
/**
* Remove a TNC PEP RADIUS Connection
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 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
*/
- eap_method_t* (*get_method)(tnc_pdp_connections_t *this, chunk_t nas_id,
- chunk_t user_name);
+ eap_method_t* (*get_state)(tnc_pdp_connections_t *this, chunk_t nas_id,
+ chunk_t user_name, ike_sa_t **ike_sa);
/**
* Destroys a tnc_pdp_connections_t object.