diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/config/backends/sqlite_backend.c | 2 | ||||
-rw-r--r-- | src/charon/config/peer_cfg.c | 12 | ||||
-rw-r--r-- | src/charon/config/peer_cfg.h | 9 | ||||
-rwxr-xr-x | src/charon/control/interfaces/stroke_interface.c | 8 | ||||
-rw-r--r-- | src/charon/encoding/payloads/eap_payload.c | 19 | ||||
-rw-r--r-- | src/charon/encoding/payloads/eap_payload.h | 5 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_aka.c | 11 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_md5.c | 5 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_method.c | 42 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_method.h | 11 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_sim.c | 5 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap_authenticator.c | 105 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap_authenticator.h | 9 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_auth.c | 8 | ||||
-rw-r--r-- | src/starter/confread.c | 29 | ||||
-rw-r--r-- | src/starter/confread.h | 3 | ||||
-rw-r--r-- | src/starter/ipsec.conf.5 | 16 | ||||
-rw-r--r-- | src/starter/starterstroke.c | 3 | ||||
-rw-r--r-- | src/stroke/stroke.h | 3 |
19 files changed, 226 insertions, 79 deletions
diff --git a/src/charon/config/backends/sqlite_backend.c b/src/charon/config/backends/sqlite_backend.c index 806ccafc4..e1c96c870 100644 --- a/src/charon/config/backends/sqlite_backend.c +++ b/src/charon/config/backends/sqlite_backend.c @@ -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(), sqlite3_column_int(stmt, 4), /* cert_policy */ 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, 8), /* rekey_time */ sqlite3_column_int(stmt, 9), /* reauth_time */ diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index fa842c514..0b5d391c4 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -127,6 +127,11 @@ struct private_peer_cfg_t { 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 */ u_int32_t keyingtries; @@ -338,8 +343,9 @@ static auth_method_t get_auth_method(private_peer_cfg_t *this) /** * 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; } @@ -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, linked_list_t *groups, cert_policy_t cert_policy, 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 reauth_time, u_int32_t jitter_time, 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_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_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_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; @@ -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->auth_method = auth_method; this->eap_type = eap_type; + this->eap_vendor = eap_vendor; this->keyingtries = keyingtries; this->rekey_time = rekey_time; this->reauth_time = reauth_time; diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 12c1f5c45..7f1dbcab6 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -229,11 +229,16 @@ struct peer_cfg_t { /** * @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 vendor receives vendor specifier, 0 for predefined EAP types * @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. @@ -393,6 +398,7 @@ struct peer_cfg_t { * @param cert_policy should we send a certificate payload? * @param auth_method auth method to use to authenticate us * @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 rekey_time timeout before starting rekeying * @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, linked_list_t *groups, cert_policy_t cert_policy, 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 reauth_time, u_int32_t jitter_time, u_int32_t over_time, bool mobike, diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index 26c55be2d..b51d53ebd 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -245,6 +245,7 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) char *interface; bool use_existing = FALSE; iterator_t *iterator; + u_int32_t vendor; pop_string(msg, &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)) && 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_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'", 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, ike_cfg, my_id, other_id, my_ca, other_ca, other_groups, - msg->add_conn.me.sendcert, - msg->add_conn.auth_method, msg->add_conn.eap_type, + msg->add_conn.me.sendcert, msg->add_conn.auth_method, + msg->add_conn.eap_type, msg->add_conn.eap_vendor, msg->add_conn.rekey.tries, rekey, reauth, jitter, over, msg->add_conn.mobike, msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip, diff --git a/src/charon/encoding/payloads/eap_payload.c b/src/charon/encoding/payloads/eap_payload.c index 79ab32fe5..345114af0 100644 --- a/src/charon/encoding/payloads/eap_payload.c +++ b/src/charon/encoding/payloads/eap_payload.c @@ -235,11 +235,23 @@ static u_int8_t get_identifier(private_eap_payload_t *this) /** * 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) { - 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; } @@ -275,7 +287,7 @@ eap_payload_t *eap_payload_create() 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_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 */ this->critical = FALSE; @@ -329,3 +341,4 @@ eap_payload_t *eap_payload_create_nak() this->set_data(this, data); return this; } + diff --git a/src/charon/encoding/payloads/eap_payload.h b/src/charon/encoding/payloads/eap_payload.h index 13c0ade80..3addbb838 100644 --- a/src/charon/encoding/payloads/eap_payload.h +++ b/src/charon/encoding/payloads/eap_payload.h @@ -95,9 +95,10 @@ struct eap_payload_t { * @brief Get the EAP method type. * * @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. diff --git a/src/charon/sa/authenticators/eap/eap_aka.c b/src/charon/sa/authenticators/eap/eap_aka.c index fc2ffcd3f..8fb1f85cd 100644 --- a/src/charon/sa/authenticators/eap/eap_aka.c +++ b/src/charon/sa/authenticators/eap/eap_aka.c @@ -42,6 +42,8 @@ #include <string.h> #include <unistd.h> +#include <sys/time.h> +#include <time.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; - if (charon->credentials->get_shared_key(charon->credentials, me, - other, &shared_key) != SUCCESS) + if (charon->credentials->get_eap_key(charon->credentials, me, + other, &shared_key) != SUCCESS) { 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. */ -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; } @@ -1417,7 +1420,7 @@ eap_aka_t *eap_create(eap_role_t role, free(this); 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.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; diff --git a/src/charon/sa/authenticators/eap/eap_md5.c b/src/charon/sa/authenticators/eap/eap_md5.c index 8fe74ed25..ca5c1d6b7 100644 --- a/src/charon/sa/authenticators/eap/eap_md5.c +++ b/src/charon/sa/authenticators/eap/eap_md5.c @@ -212,8 +212,9 @@ static status_t process_server(private_eap_md5_t *this, /** * 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; } @@ -265,7 +266,7 @@ eap_md5_t *eap_create(eap_role_t role, free(this); 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.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c index e4a58f0a3..7434ca2a1 100644 --- a/src/charon/sa/authenticators/eap/eap_method.c +++ b/src/charon/sa/authenticators/eap/eap_method.c @@ -45,7 +45,10 @@ ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_TOKEN_CARD, "EAP_SIM"); ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM, "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, "EAP_REQUEST", @@ -67,6 +70,7 @@ typedef struct module_entry_t module_entry_t; */ struct module_entry_t { eap_type_t type; + u_int32_t vendor; void *handle; eap_constructor_t constructor; }; @@ -85,7 +89,8 @@ void eap_method_unload() 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); free(entry); } @@ -165,11 +170,19 @@ void eap_method_load(char *directory) dlclose(module.handle); continue; } - module.type = method->get_type(method); + module.type = method->get_type(method, &module.vendor); method->destroy(method); - DBG1(DBG_CFG, " loaded EAP method %N successfully from %s", - eap_type_names, module.type, entry->d_name); + if (module.vendor) + { + 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); memcpy(loaded_module, &module, sizeof(module)); @@ -181,9 +194,8 @@ void eap_method_load(char *directory) /* * Described in header. */ -eap_method_t *eap_method_create(eap_type_t type, eap_role_t role, - identification_t *server, - identification_t *peer) +eap_method_t *eap_method_create(eap_type_t type, u_int32_t vendor, eap_role_t role, + identification_t *server, identification_t *peer) { eap_method_t *method = NULL; 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); while (iterator->iterate(iterator, (void**)&entry)) { - if (entry->type == type) + if (entry->type == type && entry->vendor == vendor) { method = entry->constructor(role, server, peer); if (method) @@ -205,8 +217,16 @@ eap_method_t *eap_method_create(eap_type_t type, eap_role_t role, if (method == NULL) { - DBG1(DBG_CFG, "no EAP module found for %N %N", - eap_type_names, type, eap_role_names, role); + if (vendor) + { + 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; } diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h index d43dc001f..8675fd8ec 100644 --- a/src/charon/sa/authenticators/eap/eap_method.h +++ b/src/charon/sa/authenticators/eap/eap_method.h @@ -62,6 +62,8 @@ enum eap_type_t { EAP_TOKEN_CARD = 6, EAP_SIM = 18, 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. * * @param this calling object + * @param vendor pointer receiving vendor identifier for type, 0 for none * @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. @@ -188,6 +191,7 @@ struct eap_method_t { * @brief Creates an EAP method for a specific type and role. * * @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 server ID of acting server * @param peer ID of involved peer (client) @@ -195,8 +199,9 @@ struct eap_method_t { * * @ingroup eap */ -eap_method_t *eap_method_create(eap_type_t eap_type, eap_role_t role, - identification_t *server, identification_t *peer); +eap_method_t *eap_method_create(eap_type_t eap_type, u_int32_t eap_vendor, + eap_role_t role, identification_t *server, + identification_t *peer); /** * @brief (Re-)Load all EAP modules in the EAP modules directory. diff --git a/src/charon/sa/authenticators/eap/eap_sim.c b/src/charon/sa/authenticators/eap/eap_sim.c index e369c56e3..c9eb5ce8f 100644 --- a/src/charon/sa/authenticators/eap/eap_sim.c +++ b/src/charon/sa/authenticators/eap/eap_sim.c @@ -698,8 +698,9 @@ static status_t initiate(private_eap_sim_t *this, eap_payload_t **out) /** * 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; } @@ -786,7 +787,7 @@ eap_sim_t *eap_create(eap_role_t role, /* public functions */ 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.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.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index 6e2f73a43..6250604a6 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -138,7 +138,7 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init, * Implementation of eap_authenticator_t.initiate */ 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 */ this->role = EAP_SERVER; @@ -151,21 +151,30 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, return FAILED; } - DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type); - this->method = eap_method_create(type, this->role, + if (vendor) + { + 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_other_id(this->ike_sa)); 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); return FAILED; } 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); *out = eap_payload_create_code(EAP_FAILURE); 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, 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_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 */ if (this->method == NULL) { - DBG1(DBG_IKE, "EAP server requested %N authentication", - eap_type_names, type); - this->method = eap_method_create(type, EAP_PEER, + if (vendor) + { + 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_my_id(this->ike_sa)); if (this->method == NULL) { 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(); return NEED_MORE; } } + type = this->method->get_type(this->method, &vendor); + switch (this->method->process(this->method, in, out)) { case NEED_MORE: return NEED_MORE; case SUCCESS: - DBG1(DBG_IKE, "EAP method %N succeded", - eap_type_names, this->method->get_type(this->method)); + if (vendor) + { + 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; case FAILED: default: - DBG1(DBG_IKE, "EAP method %N failed", - eap_type_names, this->method->get_type(this->method)); + if (vendor) + { + 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; } } @@ -241,6 +278,11 @@ static status_t process_peer(private_eap_authenticator_t *this, static status_t process_server(private_eap_authenticator_t *this, 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)) { case NEED_MORE: @@ -248,22 +290,35 @@ static status_t process_server(private_eap_authenticator_t *this, case 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); } + if (vendor) + { + DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeded, " + "%sMSK established", type, vendor, + this->msk.ptr ? "" : "no "); + } else { - DBG1(DBG_IKE, "EAP method %N succeded, no MSK established", - eap_type_names, this->method->get_type(this->method)); + DBG1(DBG_IKE, "EAP method %N succeded, %sMSK established", + eap_type_names, type, this->msk.ptr ? "" : "no "); } *out = eap_payload_create_code(EAP_SUCCESS); return SUCCESS; case FAILED: default: - DBG1(DBG_IKE, "EAP method %N failed for peer %D", - eap_type_names, this->method->get_type(this->method), - this->ike_sa->get_other_id(this->ike_sa)); + if (vendor) + { + 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); 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.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; /* private data */ diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h index 64a3267d7..cf2180ee3 100644 --- a/src/charon/sa/authenticators/eap_authenticator.h +++ b/src/charon/sa/authenticators/eap_authenticator.h @@ -105,15 +105,16 @@ struct eap_authenticator_t { * this method. If initiate() returns NEED_MORE, the EAP authentication * process started. In any case, a payload is created in "out". * - * @param this calling object - * @param type EAP method to use to authenticate client - * @param out created initiaal EAP message to send + * @param this calling object + * @param type EAP method to use to authenticate client + * @param vendor EAP vendor identifier, if type is vendor specific, or 0 + * @param out created initiaal EAP message to send * @return * - FAILED, if initiation failed * - NEED_MORE, if more EAP exchanges reqired */ 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. diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index 29c38ee83..de88a0abe 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -548,6 +548,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) { peer_cfg_t *config; eap_type_t eap_type; + u_int32_t eap_vendor; eap_payload_t *eap_payload; 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); return FAILED; } - + /* initiate EAP authenitcation */ - eap_type = config->get_eap_type(config); - status = this->eap_auth->initiate(this->eap_auth, eap_type, &eap_payload); + eap_type = config->get_eap_type(config, &eap_vendor); + status = this->eap_auth->initiate(this->eap_auth, eap_type, + eap_vendor, &eap_payload); message->add_payload(message, (payload_t*)eap_payload); if (status != NEED_MORE) { diff --git a/src/starter/confread.c b/src/starter/confread.c index b758ffdf2..5dfcf93d6 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -509,29 +509,46 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) } break; 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")) { - conn->eap = 23; + conn->eap_type = 23; } else if (streq(kw->value, "sim")) { - conn->eap = 18; + conn->eap_type = 18; } else if (streq(kw->value, "md5")) { - conn->eap = 4; + conn->eap_type = 4; } else { - conn->eap = atoi(kw->value); - if (conn->eap == 0) + conn->eap_type = atoi(kw->value); + if (conn->eap_type == 0) { plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; + } case KW_KEYINGTRIES: if (streq(kw->value, "%forever")) { diff --git a/src/starter/confread.h b/src/starter/confread.h index 11ca29d86..3f1884048 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -106,7 +106,8 @@ struct starter_conn { starter_state_t state; keyexchange_t keyexchange; - int eap; + u_int32_t eap_type; + u_int32_t eap_vendor; lset_t policy; time_t sa_ike_life_seconds; time_t sa_ipsec_life_seconds; diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5 index 4327b5531..56032c766 100644 --- a/src/starter/ipsec.conf.5 +++ b/src/starter/ipsec.conf.5 @@ -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. .TP .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 -is selected. Acceptable values are +selected. Acceptable values are .B aka -for EAP-AKA and +for EAP-AKA, .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 .B esp ESP encryption/authentication algorithm to be used diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index c94669115..67e0cadcc 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -197,7 +197,8 @@ int starter_stroke_add_conn(starter_conn_t *conn) { 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) { diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index 55cefef98..7ccddfb3e 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -182,7 +182,8 @@ struct stroke_msg_t { char *name; int ikev2; int auth_method; - int eap_type; + u_int32_t eap_type; + u_int32_t eap_vendor; int mode; int mobike; int force_encap; |