implemented Expanded EAP types to support vendor specific methods

This commit is contained in:
Martin Willi
2007-12-13 17:31:21 +00:00
parent 3243ac6d5e
commit 0f806802ae
19 changed files with 226 additions and 79 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ static peer_cfg_t *process_peer_cfg_row(private_sqlite_backend_t *this,
2, ike_cfg, local_id, remote_id, NULL, NULL, linked_list_create(), 2, ike_cfg, local_id, remote_id, NULL, NULL, linked_list_create(),
sqlite3_column_int(stmt, 4), /* cert_policy */ sqlite3_column_int(stmt, 4), /* cert_policy */
sqlite3_column_int(stmt, 5), /* auth_method */ sqlite3_column_int(stmt, 5), /* auth_method */
sqlite3_column_int(stmt, 6), /* eap_type */ sqlite3_column_int(stmt, 6), 0 /* eap_type, vendor */
sqlite3_column_int(stmt, 7), /* keyingtries */ sqlite3_column_int(stmt, 7), /* keyingtries */
sqlite3_column_int(stmt, 8), /* rekey_time */ sqlite3_column_int(stmt, 8), /* rekey_time */
sqlite3_column_int(stmt, 9), /* reauth_time */ sqlite3_column_int(stmt, 9), /* reauth_time */
+10 -2
View File
@@ -126,6 +126,11 @@ struct private_peer_cfg_t {
*/ */
eap_type_t eap_type; eap_type_t eap_type;
/**
* EAP vendor ID if vendor specific type is used
*/
u_int32_t eap_vendor;
/** /**
* number of tries after giving up if peer does not respond * number of tries after giving up if peer does not respond
*/ */
@@ -338,8 +343,9 @@ static auth_method_t get_auth_method(private_peer_cfg_t *this)
/** /**
* Implementation of connection_t.get_eap_type. * Implementation of connection_t.get_eap_type.
*/ */
static eap_type_t get_eap_type(private_peer_cfg_t *this) static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor)
{ {
*vendor = this->eap_vendor;
return this->eap_type; return this->eap_type;
} }
@@ -518,6 +524,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
identification_t *my_ca, identification_t *other_ca, identification_t *my_ca, identification_t *other_ca,
linked_list_t *groups, cert_policy_t cert_policy, linked_list_t *groups, cert_policy_t cert_policy,
auth_method_t auth_method, eap_type_t eap_type, auth_method_t auth_method, eap_type_t eap_type,
u_int32_t eap_vendor,
u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time, u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t over_time, bool mobike,
@@ -542,7 +549,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups; this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups;
this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy; this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method; this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type; this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *,u_int32_t*))get_eap_type;
this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries; this->public.get_keyingtries = (u_int32_t (*) (peer_cfg_t *))get_keyingtries;
this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time; this->public.get_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time;
this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time; this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time;
@@ -574,6 +581,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->cert_policy = cert_policy; this->cert_policy = cert_policy;
this->auth_method = auth_method; this->auth_method = auth_method;
this->eap_type = eap_type; this->eap_type = eap_type;
this->eap_vendor = eap_vendor;
this->keyingtries = keyingtries; this->keyingtries = keyingtries;
this->rekey_time = rekey_time; this->rekey_time = rekey_time;
this->reauth_time = reauth_time; this->reauth_time = reauth_time;
+8 -1
View File
@@ -229,11 +229,16 @@ struct peer_cfg_t {
/** /**
* @brief Get the EAP type to use for peer authentication. * @brief Get the EAP type to use for peer authentication.
*
* If vendor specific types are used, a vendor ID != 0 is returned to
* to vendor argument. Then the returned type is specific for that
* vendor ID.
* *
* @param this calling object * @param this calling object
* @param vendor receives vendor specifier, 0 for predefined EAP types
* @return authentication method * @return authentication method
*/ */
eap_type_t (*get_eap_type) (peer_cfg_t *this); eap_type_t (*get_eap_type) (peer_cfg_t *this, u_int32_t *vendor);
/** /**
* @brief Get the max number of retries after timeout. * @brief Get the max number of retries after timeout.
@@ -393,6 +398,7 @@ struct peer_cfg_t {
* @param cert_policy should we send a certificate payload? * @param cert_policy should we send a certificate payload?
* @param auth_method auth method to use to authenticate us * @param auth_method auth method to use to authenticate us
* @param eap_type EAP type to use for peer authentication * @param eap_type EAP type to use for peer authentication
* @param eap_vendor EAP vendor identifier, if vendor specific type is used
* @param keyingtries how many keying tries should be done before giving up * @param keyingtries how many keying tries should be done before giving up
* @param rekey_time timeout before starting rekeying * @param rekey_time timeout before starting rekeying
* @param reauth_time timeout before starting reauthentication * @param reauth_time timeout before starting reauthentication
@@ -416,6 +422,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
identification_t *my_ca, identification_t *other_ca, identification_t *my_ca, identification_t *other_ca,
linked_list_t *groups, cert_policy_t cert_policy, linked_list_t *groups, cert_policy_t cert_policy,
auth_method_t auth_method, eap_type_t eap_type, auth_method_t auth_method, eap_type_t eap_type,
u_int32_t eap_vendor,
u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time, u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t over_time, bool mobike,
@@ -245,6 +245,7 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
char *interface; char *interface;
bool use_existing = FALSE; bool use_existing = FALSE;
iterator_t *iterator; iterator_t *iterator;
u_int32_t vendor;
pop_string(msg, &msg->add_conn.name); pop_string(msg, &msg->add_conn.name);
DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name); DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
@@ -543,7 +544,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
&& ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg)) && ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg))
&& peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
&& peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
&& peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type) && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type
&& vendor == msg->add_conn.eap_vendor)
{ {
DBG1(DBG_CFG, "reusing existing configuration '%s'", DBG1(DBG_CFG, "reusing existing configuration '%s'",
peer_cfg->get_name(peer_cfg)); peer_cfg->get_name(peer_cfg));
@@ -626,8 +628,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1, peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
ike_cfg, my_id, other_id, my_ca, other_ca, other_groups, ike_cfg, my_id, other_id, my_ca, other_ca, other_groups,
msg->add_conn.me.sendcert, msg->add_conn.me.sendcert, msg->add_conn.auth_method,
msg->add_conn.auth_method, msg->add_conn.eap_type, msg->add_conn.eap_type, msg->add_conn.eap_vendor,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over, msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.mobike,
msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip, msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip,
+16 -3
View File
@@ -235,11 +235,23 @@ static u_int8_t get_identifier(private_eap_payload_t *this)
/** /**
* Implementation of eap_payload_t.get_type. * Implementation of eap_payload_t.get_type.
*/ */
static eap_type_t get_type(private_eap_payload_t *this) static eap_type_t get_type(private_eap_payload_t *this, u_int32_t *vendor)
{ {
eap_type_t type;
*vendor = 0;
if (this->data.len > 4) if (this->data.len > 4)
{ {
return *(this->data.ptr + 4); type = *(this->data.ptr + 4);
if (type != EAP_EXPANDED)
{
return type;
}
if (this->data.len >= 12)
{
*vendor = ntohl(*(u_int32_t*)(this->data.ptr + 4)) & 0x00FFFFFF;
return ntohl(*(u_int32_t*)(this->data.ptr + 8));
}
} }
return 0; return 0;
} }
@@ -275,7 +287,7 @@ eap_payload_t *eap_payload_create()
this->public.set_data = (void (*) (eap_payload_t *,chunk_t))set_data; this->public.set_data = (void (*) (eap_payload_t *,chunk_t))set_data;
this->public.get_code = (eap_code_t (*) (eap_payload_t*))get_code; this->public.get_code = (eap_code_t (*) (eap_payload_t*))get_code;
this->public.get_identifier = (u_int8_t (*) (eap_payload_t*))get_identifier; this->public.get_identifier = (u_int8_t (*) (eap_payload_t*))get_identifier;
this->public.get_type = (eap_type_t (*) (eap_payload_t*))get_type; this->public.get_type = (eap_type_t (*) (eap_payload_t*,u_int32_t*))get_type;
/* private variables */ /* private variables */
this->critical = FALSE; this->critical = FALSE;
@@ -329,3 +341,4 @@ eap_payload_t *eap_payload_create_nak()
this->set_data(this, data); this->set_data(this, data);
return this; return this;
} }
+3 -2
View File
@@ -95,9 +95,10 @@ struct eap_payload_t {
* @brief Get the EAP method type. * @brief Get the EAP method type.
* *
* @param this calling eap_payload_t object * @param this calling eap_payload_t object
* @return EAP method type * @param vendor pointer receiving vendor identifier
* @return EAP method type, vendor specific if vendor != 0
*/ */
eap_type_t (*get_type) (eap_payload_t *this); eap_type_t (*get_type) (eap_payload_t *this, u_int32_t *vendor);
/** /**
* @brief Destroys an eap_payload_t object. * @brief Destroys an eap_payload_t object.
+7 -4
View File
@@ -42,6 +42,8 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include "eap_aka.h" #include "eap_aka.h"
@@ -582,8 +584,8 @@ static status_t load_key(identification_t *me, identification_t *other, chunk_t
{ {
chunk_t shared_key; chunk_t shared_key;
if (charon->credentials->get_shared_key(charon->credentials, me, if (charon->credentials->get_eap_key(charon->credentials, me,
other, &shared_key) != SUCCESS) other, &shared_key) != SUCCESS)
{ {
return NOT_FOUND; return NOT_FOUND;
} }
@@ -1353,8 +1355,9 @@ static status_t peer_initiate(private_eap_aka_t *this, eap_payload_t **out)
/** /**
* Implementation of eap_method_t.get_type. * Implementation of eap_method_t.get_type.
*/ */
static eap_type_t get_type(private_eap_aka_t *this) static eap_type_t get_type(private_eap_aka_t *this, u_int32_t *vendor)
{ {
*vendor = 0;
return EAP_AKA; return EAP_AKA;
} }
@@ -1417,7 +1420,7 @@ eap_aka_t *eap_create(eap_role_t role,
free(this); free(this);
return NULL; return NULL;
} }
this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*))get_type; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+3 -2
View File
@@ -212,8 +212,9 @@ static status_t process_server(private_eap_md5_t *this,
/** /**
* Implementation of eap_method_t.get_type. * Implementation of eap_method_t.get_type.
*/ */
static eap_type_t get_type(private_eap_md5_t *this) static eap_type_t get_type(private_eap_md5_t *this, u_int32_t *vendor)
{ {
*vendor = 0;
return EAP_MD5; return EAP_MD5;
} }
@@ -265,7 +266,7 @@ eap_md5_t *eap_create(eap_role_t role,
free(this); free(this);
return NULL; return NULL;
} }
this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*))get_type; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
+31 -11
View File
@@ -45,7 +45,10 @@ ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_TOKEN_CARD,
"EAP_SIM"); "EAP_SIM");
ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM, ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
"EAP_AKA"); "EAP_AKA");
ENUM_END(eap_type_names, EAP_AKA); ENUM_NEXT(eap_type_names, EAP_EXPANDED, EAP_EXPERIMENTAL, EAP_AKA,
"EAP_EXPANDED",
"EAP_EXPERIMENTAL");
ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
ENUM(eap_code_names, EAP_REQUEST, EAP_FAILURE, ENUM(eap_code_names, EAP_REQUEST, EAP_FAILURE,
"EAP_REQUEST", "EAP_REQUEST",
@@ -67,6 +70,7 @@ typedef struct module_entry_t module_entry_t;
*/ */
struct module_entry_t { struct module_entry_t {
eap_type_t type; eap_type_t type;
u_int32_t vendor;
void *handle; void *handle;
eap_constructor_t constructor; eap_constructor_t constructor;
}; };
@@ -85,7 +89,8 @@ void eap_method_unload()
while (modules->remove_last(modules, (void**)&entry) == SUCCESS) while (modules->remove_last(modules, (void**)&entry) == SUCCESS)
{ {
DBG2(DBG_CFG, "unloaded module for %N", eap_type_names, entry->type); DBG2(DBG_CFG, "unloaded module EAP module %d-%d",
entry->type, entry->vendor);
dlclose(entry->handle); dlclose(entry->handle);
free(entry); free(entry);
} }
@@ -165,11 +170,19 @@ void eap_method_load(char *directory)
dlclose(module.handle); dlclose(module.handle);
continue; continue;
} }
module.type = method->get_type(method); module.type = method->get_type(method, &module.vendor);
method->destroy(method); method->destroy(method);
DBG1(DBG_CFG, " loaded EAP method %N successfully from %s", if (module.vendor)
eap_type_names, module.type, entry->d_name); {
DBG1(DBG_CFG, " loaded EAP method %d, vendor %d successfully from %s",
module.type, module.vendor, entry->d_name);
}
else
{
DBG1(DBG_CFG, " loaded EAP method %N successfully from %s",
eap_type_names, module.type, entry->d_name);
}
loaded_module = malloc_thing(module_entry_t); loaded_module = malloc_thing(module_entry_t);
memcpy(loaded_module, &module, sizeof(module)); memcpy(loaded_module, &module, sizeof(module));
@@ -181,9 +194,8 @@ void eap_method_load(char *directory)
/* /*
* Described in header. * Described in header.
*/ */
eap_method_t *eap_method_create(eap_type_t type, eap_role_t role, eap_method_t *eap_method_create(eap_type_t type, u_int32_t vendor, eap_role_t role,
identification_t *server, identification_t *server, identification_t *peer)
identification_t *peer)
{ {
eap_method_t *method = NULL; eap_method_t *method = NULL;
iterator_t *iterator; iterator_t *iterator;
@@ -192,7 +204,7 @@ eap_method_t *eap_method_create(eap_type_t type, eap_role_t role,
iterator = modules->create_iterator(modules, TRUE); iterator = modules->create_iterator(modules, TRUE);
while (iterator->iterate(iterator, (void**)&entry)) while (iterator->iterate(iterator, (void**)&entry))
{ {
if (entry->type == type) if (entry->type == type && entry->vendor == vendor)
{ {
method = entry->constructor(role, server, peer); method = entry->constructor(role, server, peer);
if (method) if (method)
@@ -205,8 +217,16 @@ eap_method_t *eap_method_create(eap_type_t type, eap_role_t role,
if (method == NULL) if (method == NULL)
{ {
DBG1(DBG_CFG, "no EAP module found for %N %N", if (vendor)
eap_type_names, type, eap_role_names, role); {
DBG1(DBG_CFG, "no vendor %d specific EAP module found for method "
"%d %N", vendor, type, eap_role_names, role);
}
else
{
DBG1(DBG_CFG, "no EAP module found for %N %N",
eap_type_names, type, eap_role_names, role);
}
} }
return method; return method;
} }
@@ -62,6 +62,8 @@ enum eap_type_t {
EAP_TOKEN_CARD = 6, EAP_TOKEN_CARD = 6,
EAP_SIM = 18, EAP_SIM = 18,
EAP_AKA = 23, EAP_AKA = 23,
EAP_EXPANDED = 254,
EAP_EXPERIMENTAL = 255,
}; };
/** /**
@@ -148,9 +150,10 @@ struct eap_method_t {
* @brief Get the EAP type implemented in this method. * @brief Get the EAP type implemented in this method.
* *
* @param this calling object * @param this calling object
* @param vendor pointer receiving vendor identifier for type, 0 for none
* @return type of the EAP method * @return type of the EAP method
*/ */
eap_type_t (*get_type) (eap_method_t *this); eap_type_t (*get_type) (eap_method_t *this, u_int32_t *vendor);
/** /**
* @brief Check if this EAP method authenticates the server. * @brief Check if this EAP method authenticates the server.
@@ -188,6 +191,7 @@ struct eap_method_t {
* @brief Creates an EAP method for a specific type and role. * @brief Creates an EAP method for a specific type and role.
* *
* @param eap_type EAP type to use * @param eap_type EAP type to use
* @param eap_vendor vendor identifier if a vendor specifc EAP type is used
* @param role role of the eap_method, server or peer * @param role role of the eap_method, server or peer
* @param server ID of acting server * @param server ID of acting server
* @param peer ID of involved peer (client) * @param peer ID of involved peer (client)
@@ -195,8 +199,9 @@ struct eap_method_t {
* *
* @ingroup eap * @ingroup eap
*/ */
eap_method_t *eap_method_create(eap_type_t eap_type, eap_role_t role, eap_method_t *eap_method_create(eap_type_t eap_type, u_int32_t eap_vendor,
identification_t *server, identification_t *peer); eap_role_t role, identification_t *server,
identification_t *peer);
/** /**
* @brief (Re-)Load all EAP modules in the EAP modules directory. * @brief (Re-)Load all EAP modules in the EAP modules directory.
+3 -2
View File
@@ -698,8 +698,9 @@ static status_t initiate(private_eap_sim_t *this, eap_payload_t **out)
/** /**
* Implementation of eap_method_t.get_type. * Implementation of eap_method_t.get_type.
*/ */
static eap_type_t get_type(private_eap_sim_t *this) static eap_type_t get_type(private_eap_sim_t *this, u_int32_t *vendor)
{ {
*vendor = 0;
return EAP_SIM; return EAP_SIM;
} }
@@ -786,7 +787,7 @@ eap_sim_t *eap_create(eap_role_t role,
/* public functions */ /* public functions */
this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*))get_type; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
@@ -138,7 +138,7 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
* Implementation of eap_authenticator_t.initiate * Implementation of eap_authenticator_t.initiate
*/ */
static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
eap_payload_t **out) u_int32_t vendor, eap_payload_t **out)
{ {
/* if initiate() is called, role is always server */ /* if initiate() is called, role is always server */
this->role = EAP_SERVER; this->role = EAP_SERVER;
@@ -151,21 +151,30 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
return FAILED; return FAILED;
} }
DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type); if (vendor)
this->method = eap_method_create(type, this->role, {
DBG1(DBG_IKE, "requesting vendor specific EAP authentication %d-%d",
type, vendor);
}
else
{
DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type);
}
this->method = eap_method_create(type, vendor, this->role,
this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa)); this->ike_sa->get_other_id(this->ike_sa));
if (this->method == NULL) if (this->method == NULL)
{ {
DBG1(DBG_IKE, "configured EAP server method %N not supported, sending %N",
eap_type_names, type, eap_code_names, EAP_FAILURE); DBG1(DBG_IKE, "configured EAP server method not supported, sending %N",
eap_code_names, EAP_FAILURE);
*out = eap_payload_create_code(EAP_FAILURE); *out = eap_payload_create_code(EAP_FAILURE);
return FAILED; return FAILED;
} }
if (this->method->initiate(this->method, out) != NEED_MORE) if (this->method->initiate(this->method, out) != NEED_MORE)
{ {
DBG1(DBG_IKE, "failed to initiate %N, sending %N", DBG1(DBG_IKE, "failed to initiate EAP exchange, sending %N",
eap_type_names, type, eap_code_names, EAP_FAILURE); eap_type_names, type, eap_code_names, EAP_FAILURE);
*out = eap_payload_create_code(EAP_FAILURE); *out = eap_payload_create_code(EAP_FAILURE);
return FAILED; return FAILED;
@@ -179,11 +188,14 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
static status_t process_peer(private_eap_authenticator_t *this, static status_t process_peer(private_eap_authenticator_t *this,
eap_payload_t *in, eap_payload_t **out) eap_payload_t *in, eap_payload_t **out)
{ {
eap_type_t type = in->get_type(in); eap_type_t type;
u_int32_t vendor;
if (type == EAP_IDENTITY) type = in->get_type(in, &vendor);
if (!vendor && type == EAP_IDENTITY)
{ {
eap_method_t *method = eap_method_create(type, EAP_PEER, eap_method_t *method = eap_method_create(type, 0, EAP_PEER,
this->ike_sa->get_other_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa)); this->ike_sa->get_my_id(this->ike_sa));
@@ -205,32 +217,57 @@ static status_t process_peer(private_eap_authenticator_t *this,
/* create an eap_method for the first call */ /* create an eap_method for the first call */
if (this->method == NULL) if (this->method == NULL)
{ {
DBG1(DBG_IKE, "EAP server requested %N authentication", if (vendor)
eap_type_names, type); {
this->method = eap_method_create(type, EAP_PEER, DBG1(DBG_IKE, "EAP server requested vendor specific EAP method %d-%d",
type, vendor);
}
else
{
DBG1(DBG_IKE, "EAP server requested %N authentication",
eap_type_names, type);
}
this->method = eap_method_create(type, vendor, EAP_PEER,
this->ike_sa->get_other_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa)); this->ike_sa->get_my_id(this->ike_sa));
if (this->method == NULL) if (this->method == NULL)
{ {
DBG1(DBG_IKE, "EAP server requested unsupported " DBG1(DBG_IKE, "EAP server requested unsupported "
"EAP method %N, sending EAP_NAK", eap_type_names, type); "EAP method, sending EAP_NAK");
*out = eap_payload_create_nak(); *out = eap_payload_create_nak();
return NEED_MORE; return NEED_MORE;
} }
} }
type = this->method->get_type(this->method, &vendor);
switch (this->method->process(this->method, in, out)) switch (this->method->process(this->method, in, out))
{ {
case NEED_MORE: case NEED_MORE:
return NEED_MORE; return NEED_MORE;
case SUCCESS: case SUCCESS:
DBG1(DBG_IKE, "EAP method %N succeded", if (vendor)
eap_type_names, this->method->get_type(this->method)); {
DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeded",
type, vendor);
}
else
{
DBG1(DBG_IKE, "EAP method %N succeded", eap_type_names, type);
}
return SUCCESS; return SUCCESS;
case FAILED: case FAILED:
default: default:
DBG1(DBG_IKE, "EAP method %N failed", if (vendor)
eap_type_names, this->method->get_type(this->method)); {
DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed",
type, vendor);
}
else
{
DBG1(DBG_IKE, "EAP method %N failed",
eap_type_names, type);
}
return FAILED; return FAILED;
} }
} }
@@ -241,6 +278,11 @@ static status_t process_peer(private_eap_authenticator_t *this,
static status_t process_server(private_eap_authenticator_t *this, static status_t process_server(private_eap_authenticator_t *this,
eap_payload_t *in, eap_payload_t **out) eap_payload_t *in, eap_payload_t **out)
{ {
eap_type_t type;
u_int32_t vendor;
type = this->method->get_type(this->method, &vendor);
switch (this->method->process(this->method, in, out)) switch (this->method->process(this->method, in, out))
{ {
case NEED_MORE: case NEED_MORE:
@@ -248,22 +290,35 @@ static status_t process_server(private_eap_authenticator_t *this,
case SUCCESS: case SUCCESS:
if (this->method->get_msk(this->method, &this->msk) == SUCCESS) if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
{ {
DBG1(DBG_IKE, "EAP method %N succeded, MSK established",
eap_type_names, this->method->get_type(this->method));
this->msk = chunk_clone(this->msk); this->msk = chunk_clone(this->msk);
} }
if (vendor)
{
DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeded, "
"%sMSK established", type, vendor,
this->msk.ptr ? "" : "no ");
}
else else
{ {
DBG1(DBG_IKE, "EAP method %N succeded, no MSK established", DBG1(DBG_IKE, "EAP method %N succeded, %sMSK established",
eap_type_names, this->method->get_type(this->method)); eap_type_names, type, this->msk.ptr ? "" : "no ");
} }
*out = eap_payload_create_code(EAP_SUCCESS); *out = eap_payload_create_code(EAP_SUCCESS);
return SUCCESS; return SUCCESS;
case FAILED: case FAILED:
default: default:
DBG1(DBG_IKE, "EAP method %N failed for peer %D", if (vendor)
eap_type_names, this->method->get_type(this->method), {
this->ike_sa->get_other_id(this->ike_sa)); DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
"peer %D", type, vendor,
this->ike_sa->get_other_id(this->ike_sa));
}
else
{
DBG1(DBG_IKE, "EAP method %N failed for peer %D",
eap_type_names, type,
this->ike_sa->get_other_id(this->ike_sa));
}
*out = eap_payload_create_code(EAP_FAILURE); *out = eap_payload_create_code(EAP_FAILURE);
return FAILED; return FAILED;
} }
@@ -363,7 +418,7 @@ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa)
this->public.authenticator_interface.destroy = (void(*)(authenticator_t*))destroy; this->public.authenticator_interface.destroy = (void(*)(authenticator_t*))destroy;
this->public.is_mutual = (bool(*)(eap_authenticator_t*))is_mutual; this->public.is_mutual = (bool(*)(eap_authenticator_t*))is_mutual;
this->public.initiate = (status_t(*)(eap_authenticator_t*,eap_type_t,eap_payload_t**))initiate; this->public.initiate = (status_t(*)(eap_authenticator_t*,eap_type_t,u_int32_t,eap_payload_t**))initiate;
this->public.process = (status_t(*)(eap_authenticator_t*,eap_payload_t*,eap_payload_t**))process; this->public.process = (status_t(*)(eap_authenticator_t*,eap_payload_t*,eap_payload_t**))process;
/* private data */ /* private data */
@@ -105,15 +105,16 @@ struct eap_authenticator_t {
* this method. If initiate() returns NEED_MORE, the EAP authentication * this method. If initiate() returns NEED_MORE, the EAP authentication
* process started. In any case, a payload is created in "out". * process started. In any case, a payload is created in "out".
* *
* @param this calling object * @param this calling object
* @param type EAP method to use to authenticate client * @param type EAP method to use to authenticate client
* @param out created initiaal EAP message to send * @param vendor EAP vendor identifier, if type is vendor specific, or 0
* @param out created initiaal EAP message to send
* @return * @return
* - FAILED, if initiation failed * - FAILED, if initiation failed
* - NEED_MORE, if more EAP exchanges reqired * - NEED_MORE, if more EAP exchanges reqired
*/ */
status_t (*initiate) (eap_authenticator_t* this, eap_type_t type, status_t (*initiate) (eap_authenticator_t* this, eap_type_t type,
eap_payload_t **out); u_int32_t vendor, eap_payload_t **out);
/** /**
* @brief Process an EAP message. * @brief Process an EAP message.
+5 -3
View File
@@ -548,6 +548,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
{ {
peer_cfg_t *config; peer_cfg_t *config;
eap_type_t eap_type; eap_type_t eap_type;
u_int32_t eap_vendor;
eap_payload_t *eap_payload; eap_payload_t *eap_payload;
status_t status; status_t status;
@@ -592,10 +593,11 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
return FAILED; return FAILED;
} }
/* initiate EAP authenitcation */ /* initiate EAP authenitcation */
eap_type = config->get_eap_type(config); eap_type = config->get_eap_type(config, &eap_vendor);
status = this->eap_auth->initiate(this->eap_auth, eap_type, &eap_payload); status = this->eap_auth->initiate(this->eap_auth, eap_type,
eap_vendor, &eap_payload);
message->add_payload(message, (payload_t*)eap_payload); message->add_payload(message, (payload_t*)eap_payload);
if (status != NEED_MORE) if (status != NEED_MORE)
{ {
+23 -6
View File
@@ -509,29 +509,46 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
} }
break; break;
case KW_EAP: case KW_EAP:
/* TODO: a gperf function for all EAP types */ {
char *sep;
/* check for vendor-type format */
sep = strchr(kw->value, '-');
if (sep)
{
*(sep++) = '\0';
conn->eap_type = atoi(kw->value);
conn->eap_vendor = atoi(sep);
if (conn->eap_type == 0 || conn->eap_vendor == 0)
{
plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value);
cfg->err++;
}
break;
}
if (streq(kw->value, "aka")) if (streq(kw->value, "aka"))
{ {
conn->eap = 23; conn->eap_type = 23;
} }
else if (streq(kw->value, "sim")) else if (streq(kw->value, "sim"))
{ {
conn->eap = 18; conn->eap_type = 18;
} }
else if (streq(kw->value, "md5")) else if (streq(kw->value, "md5"))
{ {
conn->eap = 4; conn->eap_type = 4;
} }
else else
{ {
conn->eap = atoi(kw->value); conn->eap_type = atoi(kw->value);
if (conn->eap == 0) if (conn->eap_type == 0)
{ {
plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value); plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value);
cfg->err++; cfg->err++;
} }
} }
break; break;
}
case KW_KEYINGTRIES: case KW_KEYINGTRIES:
if (streq(kw->value, "%forever")) if (streq(kw->value, "%forever"))
{ {
+2 -1
View File
@@ -106,7 +106,8 @@ struct starter_conn {
starter_state_t state; starter_state_t state;
keyexchange_t keyexchange; keyexchange_t keyexchange;
int eap; u_int32_t eap_type;
u_int32_t eap_vendor;
lset_t policy; lset_t policy;
time_t sa_ike_life_seconds; time_t sa_ike_life_seconds;
time_t sa_ipsec_life_seconds; time_t sa_ipsec_life_seconds;
+12 -4
View File
@@ -350,13 +350,21 @@ in case of inactivity. This only applies to IKEv1, in IKEv2 the default
retransmission timeout applies, as every exchange is used to detect dead peers. retransmission timeout applies, as every exchange is used to detect dead peers.
.TP .TP
.B eap .B eap
defines the EAP type to be used if defines the EAP type to propose as server if the client has
.B authby=eap .B authby=eap
is selected. Acceptable values are selected. Acceptable values are
.B aka .B aka
for EAP-AKA and for EAP-AKA,
.B sim .B sim
for EAP-SIM. for EAP-SIM and
.B md5
for EAP-MD5.
Additionally, IANA assigned EAP method numbers are accepted, or a definition
in the form
.B eap=type-vendor
(e.g.
.B eap=7-12345
) can be used to specify vendor specific EAP types.
.TP .TP
.B esp .B esp
ESP encryption/authentication algorithm to be used ESP encryption/authentication algorithm to be used
+2 -1
View File
@@ -197,7 +197,8 @@ int starter_stroke_add_conn(starter_conn_t *conn)
{ {
msg.add_conn.auth_method = AUTH_EAP; msg.add_conn.auth_method = AUTH_EAP;
} }
msg.add_conn.eap_type = conn->eap; msg.add_conn.eap_type = conn->eap_type;
msg.add_conn.eap_vendor = conn->eap_vendor;
if (conn->policy & POLICY_TUNNEL) if (conn->policy & POLICY_TUNNEL)
{ {
+2 -1
View File
@@ -182,7 +182,8 @@ struct stroke_msg_t {
char *name; char *name;
int ikev2; int ikev2;
int auth_method; int auth_method;
int eap_type; u_int32_t eap_type;
u_int32_t eap_vendor;
int mode; int mode;
int mobike; int mobike;
int force_encap; int force_encap;