diff options
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r-- | src/libcharon/sa/eap/eap_manager.c | 40 | ||||
-rw-r--r-- | src/libcharon/sa/eap/eap_manager.h | 12 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/phase1.c | 16 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/authenticators/eap_authenticator.c | 58 |
4 files changed, 114 insertions, 12 deletions
diff --git a/src/libcharon/sa/eap/eap_manager.c b/src/libcharon/sa/eap/eap_manager.c index d38754e01..520c0ce56 100644 --- a/src/libcharon/sa/eap/eap_manager.c +++ b/src/libcharon/sa/eap/eap_manager.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -104,6 +105,44 @@ METHOD(eap_manager_t, remove_method, void, this->lock->unlock(this->lock); } +/** + * filter the registered methods + */ +static bool filter_methods(uintptr_t role, eap_entry_t **entry, + eap_type_t *type, void *in, u_int32_t *vendor) +{ + if ((*entry)->role != (eap_role_t)role) + { + return FALSE; + } + if ((*entry)->vendor == 0 && + ((*entry)->type < 4 || (*entry)->type == EAP_EXPANDED || + (*entry)->type > EAP_EXPERIMENTAL)) + { /* filter invalid types */ + return FALSE; + } + if (type) + { + *type = (*entry)->type; + } + if (vendor) + { + *vendor = (*entry)->vendor; + } + return TRUE; +} + +METHOD(eap_manager_t, create_enumerator, enumerator_t*, + private_eap_manager_t *this, eap_role_t role) +{ + this->lock->read_lock(this->lock); + return enumerator_create_cleaner( + enumerator_create_filter( + this->methods->create_enumerator(this->methods), + (void*)filter_methods, (void*)(uintptr_t)role, NULL), + (void*)this->lock->unlock, this->lock); +} + METHOD(eap_manager_t, create_instance, eap_method_t*, private_eap_manager_t *this, eap_type_t type, u_int32_t vendor, eap_role_t role, identification_t *server, identification_t *peer) @@ -150,6 +189,7 @@ eap_manager_t *eap_manager_create() .public = { .add_method = _add_method, .remove_method = _remove_method, + .create_enumerator = _create_enumerator, .create_instance = _create_instance, .destroy = _destroy, }, diff --git a/src/libcharon/sa/eap/eap_manager.h b/src/libcharon/sa/eap/eap_manager.h index 868eaef06..e318ef57a 100644 --- a/src/libcharon/sa/eap/eap_manager.h +++ b/src/libcharon/sa/eap/eap_manager.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -54,6 +55,17 @@ struct eap_manager_t { void (*remove_method)(eap_manager_t *this, eap_constructor_t constructor); /** + * Enumerate the registered EAP authentication methods for the given role. + * + * @note Only authentication types are enumerated (e.g. EAP-Identity is not + * even though it is registered as method with this manager). + * + * @param role EAP role of methods to enumerate + * @return enumerator over (eap_type_t type, u_int32_t vendor) + */ + enumerator_t* (*create_enumerator)(eap_manager_t *this, eap_role_t role); + + /** * Create a new EAP method instance. * * @param type type of the EAP method diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c index fea2f2c60..4096141ec 100644 --- a/src/libcharon/sa/ikev1/phase1.c +++ b/src/libcharon/sa/ikev1/phase1.c @@ -587,14 +587,26 @@ METHOD(phase1_t, select_config, peer_cfg_t*, METHOD(phase1_t, get_id, identification_t*, private_phase1_t *this, peer_cfg_t *peer_cfg, bool local) { + identification_t *id = NULL; auth_cfg_t *auth; auth = get_auth_cfg(peer_cfg, local); if (auth) { - return auth->get(auth, AUTH_RULE_IDENTITY); + id = auth->get(auth, AUTH_RULE_IDENTITY); + if (local && (!id || id->get_type(id) == ID_ANY)) + { /* no ID configured, use local IP address */ + host_t *me; + + me = this->ike_sa->get_my_host(this->ike_sa); + if (!me->is_anyaddr(me)) + { + id = identification_create_from_sockaddr(me->get_sockaddr(me)); + auth->add(auth, AUTH_RULE_IDENTITY, id); + } + } } - return NULL; + return id; } METHOD(phase1_t, has_virtual_ip, bool, diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c index 2c282dc06..aa0644033 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2006-2009 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -186,9 +187,9 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, if (this->method) { action = "initiating"; - type = this->method->get_type(this->method, &vendor); if (this->method->initiate(this->method, &out) == NEED_MORE) { + type = this->method->get_type(this->method, &vendor); if (vendor) { DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method (id 0x%02X)", @@ -201,6 +202,8 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, } return out; } + /* type might have changed for virtual methods */ + type = this->method->get_type(this->method, &vendor); } if (vendor) { @@ -233,9 +236,10 @@ static void replace_eap_identity(private_eap_authenticator_t *this) static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, eap_payload_t *in) { - eap_type_t type, received_type; - u_int32_t vendor, received_vendor; + eap_type_t type, received_type, conf_type; + u_int32_t vendor, received_vendor, conf_vendor; eap_payload_t *out; + auth_cfg_t *auth; if (in->get_code(in) != EAP_RESPONSE) { @@ -250,15 +254,25 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, { if (received_vendor == 0 && received_type == EAP_NAK) { - DBG1(DBG_IKE, "received %N, sending %N", - eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE); + auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); + conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE); + conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR); + if ((type == EAP_IDENTITY && !vendor) || + (type == conf_type && vendor == conf_vendor)) + { + DBG1(DBG_IKE, "received %N, sending %N", + eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE); + return eap_payload_create_code(EAP_FAILURE, + in->get_identifier(in)); + } + /* virtual methods handle NAKs in process() */ } else { DBG1(DBG_IKE, "received invalid EAP response, sending %N", eap_code_names, EAP_FAILURE); + return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in)); } - return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in)); } switch (this->method->process(this->method, in, &out)) @@ -302,6 +316,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in)); case FAILED: default: + /* type might have changed for virtual methods */ + type = this->method->get_type(this->method, &vendor); if (vendor) { DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for " @@ -324,8 +340,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, eap_payload_t *in) { - eap_type_t type; - u_int32_t vendor; + eap_type_t type, conf_type; + u_int32_t vendor, conf_vendor; auth_cfg_t *auth; eap_payload_t *out; identification_t *id; @@ -357,9 +373,11 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, this->method->destroy(this->method); this->method = NULL; } + /* FIXME: sending a Nak is not correct here as EAP_IDENTITY (1) is no + * EAP method (types 3-253, 255) */ DBG1(DBG_IKE, "%N not supported, sending EAP_NAK", eap_type_names, type); - return eap_payload_create_nak(in->get_identifier(in)); + return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE); } if (this->method == NULL) { @@ -373,11 +391,31 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", eap_type_names, type, in->get_identifier(in)); } + auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); + conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE); + conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR); + if (conf_type != EAP_NAK && + (conf_type != type || conf_vendor != vendor)) + { + if (conf_vendor) + { + DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK", + conf_type, conf_vendor); + } + else + { + DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK", + eap_type_names, conf_type); + } + return eap_payload_create_nak(in->get_identifier(in), conf_type, + conf_vendor, in->is_expanded(in)); + } this->method = load_method(this, type, vendor, EAP_PEER); if (!this->method) { DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK"); - return eap_payload_create_nak(in->get_identifier(in)); + return eap_payload_create_nak(in->get_identifier(in), 0, 0, + in->is_expanded(in)); } } |