diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-10-29 20:30:44 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-10-29 20:30:44 +0000 |
commit | 74f0bbfc53cb5fa519e4e27ece53735ab51b397c (patch) | |
tree | 0dbab9c835be15577ff05b474b6361bb326d66ce /src/charon/sa/authenticators | |
parent | 5c1fa2516bda1ccf8eb00178c0beb196c2020a94 (diff) | |
download | vyos-strongswan-74f0bbfc53cb5fa519e4e27ece53735ab51b397c.tar.gz vyos-strongswan-74f0bbfc53cb5fa519e4e27ece53735ab51b397c.zip |
- New upstream release.
Diffstat (limited to 'src/charon/sa/authenticators')
-rw-r--r-- | src/charon/sa/authenticators/authenticator.c | 30 | ||||
-rw-r--r-- | src/charon/sa/authenticators/authenticator.h | 75 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_method.c | 10 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_method.h | 13 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/sim_manager.c | 125 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/sim_manager.h | 136 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap_authenticator.c | 183 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap_authenticator.h | 6 |
8 files changed, 500 insertions, 78 deletions
diff --git a/src/charon/sa/authenticators/authenticator.c b/src/charon/sa/authenticators/authenticator.c index c301e4933..827c7a69a 100644 --- a/src/charon/sa/authenticators/authenticator.c +++ b/src/charon/sa/authenticators/authenticator.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2006-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: authenticator.c 4051 2008-06-10 09:08:27Z tobias $ + * $Id: authenticator.c 4276 2008-08-22 10:44:51Z martin $ */ #include <string.h> @@ -33,22 +33,27 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS, "ECDSA-256 signature", "ECDSA-384 signature", "ECDSA-521 signature"); -ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_ECDSA_521, - "EAP"); -ENUM_END(auth_method_names, AUTH_EAP); +ENUM_END(auth_method_names, AUTH_ECDSA_521); + +ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP, + "public key", + "pre-shared key", + "EAP", +); /** * Described in header. */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method) +authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa, + auth_class_t class) { - switch (auth_method) + switch (class) { - case CONF_AUTH_PUBKEY: + case AUTH_CLASS_PUBKEY: return (authenticator_t*)pubkey_authenticator_create(ike_sa); - case CONF_AUTH_PSK: + case AUTH_CLASS_PSK: return (authenticator_t*)psk_authenticator_create(ike_sa); - case CONF_AUTH_EAP: + case AUTH_CLASS_EAP: return (authenticator_t*)eap_authenticator_create(ike_sa); default: return NULL; @@ -58,9 +63,10 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t aut /** * Described in header. */ -authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload) +authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa, + auth_method_t method) { - switch (auth_payload->get_auth_method(auth_payload)) + switch (method) { case AUTH_RSA: case AUTH_ECDSA_256: diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h index 3c961d23e..aa5a73e86 100644 --- a/src/charon/sa/authenticators/authenticator.h +++ b/src/charon/sa/authenticators/authenticator.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: authenticator.h 4051 2008-06-10 09:08:27Z tobias $ + * $Id: authenticator.h 4276 2008-08-22 10:44:51Z martin $ */ /** @@ -26,6 +26,7 @@ #define AUTHENTICATOR_H_ typedef enum auth_method_t auth_method_t; +typedef enum auth_class_t auth_class_t; typedef struct authenticator_t authenticator_t; #include <library.h> @@ -34,7 +35,7 @@ typedef struct authenticator_t authenticator_t; #include <encoding/payloads/auth_payload.h> /** - * Method to use for authentication. + * Method to use for authentication, as defined in IKEv2. */ enum auth_method_t { /** @@ -70,12 +71,6 @@ enum auth_method_t { * ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754 */ AUTH_ECDSA_521 = 11, - - /** - * EAP authentication. This value is never negotiated and therefore - * a value from private use. - */ - AUTH_EAP = 201, }; /** @@ -84,11 +79,31 @@ enum auth_method_t { extern enum_name_t *auth_method_names; /** + * Class of authentication to use. This is different to auth_method_t in that + * it does not specify a method, but a class of acceptable methods. The found + * certificate finally dictates wich method is used. + */ +enum auth_class_t { + /** authentication using public keys (RSA, ECDSA) */ + AUTH_CLASS_PUBKEY = 1, + /** authentication using a pre-shared secrets */ + AUTH_CLASS_PSK = 2, + /** authentication using EAP */ + AUTH_CLASS_EAP = 3, +}; + +/** + * enum strings for auth_class_t + */ +extern enum_name_t *auth_class_names; + +/** * Authenticator interface implemented by the various authenticators. * * Currently the following two AUTH methods are supported: * - shared key message integrity code * - RSA digital signature + * - EAP using the EAP framework and one of the EAP plugins * - ECDSA is supported using OpenSSL */ struct authenticator_t { @@ -96,15 +111,14 @@ struct authenticator_t { /** * Verify a received authentication payload. * - * @param ike_sa_init binary representation of received ike_sa_init - * @param my_nonce the sent nonce - * @param auth_payload authentication payload to verify - * + * @param ike_sa_init binary representation of received ike_sa_init + * @param my_nonce the sent nonce + * @param auth_payload authentication payload to verify * @return - * - SUCCESS, - * - FAILED if verification failed - * - INVALID_ARG if auth_method does not match - * - NOT_FOUND if credentials not found + * - SUCCESS, + * - FAILED if verification failed + * - INVALID_ARG if auth_method does not match + * - NOT_FOUND if credentials not found */ status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init, chunk_t my_nonce, auth_payload_t *auth_payload); @@ -112,13 +126,12 @@ struct authenticator_t { /** * Build an authentication payload to send to the other peer. * - * @param ike_sa_init binary representation of sent ike_sa_init - * @param other_nonce the received nonce - * @param[out] auth_payload the resulting authentication payload - * + * @param ike_sa_init binary representation of sent ike_sa_init + * @param other_nonce the received nonce + * @param auth_payload the resulting authentication payload * @return - * - SUCCESS, - * - NOT_FOUND if the data for AUTH method could not be found + * - SUCCESS, + * - NOT_FOUND if credentials not found */ status_t (*build) (authenticator_t *this, chunk_t ike_sa_init, chunk_t other_nonce, auth_payload_t **auth_payload); @@ -130,23 +143,23 @@ struct authenticator_t { }; /** - * Creates an authenticator for the specified auth method (as configured). + * Creates an authenticator for the specified auth class (as configured). * * @param ike_sa associated ike_sa - * @param auth_method authentication method to use for build()/verify() - * + * @param class class of authentication to use * @return authenticator_t object */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method); +authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa, + auth_class_t class); /** - * Creates an authenticator from the given auth payload. + * Creates an authenticator for method (as received in payload). * * @param ike_sa associated ike_sa - * @param auth_payload auth payload - * + * @param method method as found in payload * @return authenticator_t object */ -authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload); +authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa, + auth_method_t method); #endif /* AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/eap/eap_method.c b/src/charon/sa/authenticators/eap/eap_method.c index 5e2db5489..11b12fb49 100644 --- a/src/charon/sa/authenticators/eap/eap_method.c +++ b/src/charon/sa/authenticators/eap/eap_method.c @@ -12,19 +12,19 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: eap_method.c 3589 2008-03-13 14:14:44Z martin $ + * $Id: eap_method.c 4269 2008-08-21 12:10:07Z martin $ */ #include "eap_method.h" -ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_TOKEN_CARD, +ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC, "EAP_IDENTITY", "EAP_NOTIFICATION", "EAP_NAK", "EAP_MD5", - "EAP_ONE_TIME_PASSWORD", - "EAP_TOKEN_CARD"); -ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_TOKEN_CARD, + "EAP_OTP", + "EAP_GTC"); +ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC, "EAP_SIM"); ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM, "EAP_AKA"); diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h index eda6f545e..663117931 100644 --- a/src/charon/sa/authenticators/eap/eap_method.h +++ b/src/charon/sa/authenticators/eap/eap_method.h @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: eap_method.h 3589 2008-03-13 14:14:44Z martin $ + * $Id: eap_method.h 4276 2008-08-22 10:44:51Z martin $ */ /** @@ -52,8 +52,8 @@ enum eap_type_t { EAP_NOTIFICATION = 2, EAP_NAK = 3, EAP_MD5 = 4, - EAP_ONE_TIME_PASSWORD = 5, - EAP_TOKEN_CARD = 6, + EAP_OTP = 5, + EAP_GTC = 6, EAP_SIM = 18, EAP_AKA = 23, EAP_EXPANDED = 254, @@ -95,6 +95,8 @@ extern enum_name_t *eap_code_names; * authentication. Even if a mutual EAP method is used, the traditional * AUTH payloads are required. Only these include the nonces and messages from * ike_sa_init and therefore prevent man in the middle attacks. + * The EAP method must use an initial EAP identifier value != 0, as a preceding + * EAP-Identity exchange always uses identifier 0. */ struct eap_method_t { @@ -148,7 +150,8 @@ struct eap_method_t { /** * Get the MSK established by this EAP method. * - * Not all EAP methods establish a shared secret. + * Not all EAP methods establish a shared secret. For implementations of + * the EAP-Identity method, get_msk() returns the received identity. * * @param msk chunk receiving internal stored MSK * @return @@ -171,6 +174,8 @@ struct eap_method_t { * Constructors for server and peers are identical, to support both roles * of a EAP method, a plugin needs register two constructors in the * eap_manager_t. + * The passed identites are of type ID_EAP and valid only during the + * constructor invocation. * * @param server ID of the server to use for credential lookup * @param peer ID of the peer to use for credential lookup diff --git a/src/charon/sa/authenticators/eap/sim_manager.c b/src/charon/sa/authenticators/eap/sim_manager.c new file mode 100644 index 000000000..e6817ca20 --- /dev/null +++ b/src/charon/sa/authenticators/eap/sim_manager.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "sim_manager.h" + +#include <utils/linked_list.h> + +typedef struct private_sim_manager_t private_sim_manager_t; + +/** + * Private data of an sim_manager_t object. + */ +struct private_sim_manager_t { + + /** + * Public sim_manager_t interface. + */ + sim_manager_t public; + + /** + * list of added cards + */ + linked_list_t *cards; + + /** + * list of added provider + */ + linked_list_t *provider; +}; + +/** + * Implementation of sim_manager_t.add_card + */ +static void add_card(private_sim_manager_t *this, sim_card_t *card) +{ + this->cards->insert_last(this->cards, card); +} + +/** + * Implementation of sim_manager_t.remove_card + */ +static void remove_card(private_sim_manager_t *this, sim_card_t *card) +{ + this->cards->remove(this->cards, card, NULL); +} + +/** + * Implementation of sim_manager_t.create_card_enumerator + */ +static enumerator_t* create_card_enumerator(private_sim_manager_t *this) +{ + return this->cards->create_enumerator(this->cards); +} + +/** + * Implementation of sim_manager_t.add_provider + */ +static void add_provider(private_sim_manager_t *this, + sim_provider_t *provider) +{ + this->provider->insert_last(this->provider, provider); +} + +/** + * Implementation of sim_manager_t.remove_provider + */ +static void remove_provider(private_sim_manager_t *this, + sim_provider_t *provider) +{ + this->provider->remove(this->provider, provider, NULL); +} + +/** + * Implementation of sim_manager_t.create_provider_enumerator + */ +static enumerator_t* create_provider_enumerator(private_sim_manager_t *this) +{ + return this->provider->create_enumerator(this->provider); +} + +/** + * Implementation of sim_manager_t.destroy. + */ +static void destroy(private_sim_manager_t *this) +{ + this->cards->destroy(this->cards); + this->provider->destroy(this->provider); + free(this); +} + +/** + * See header + */ +sim_manager_t *sim_manager_create() +{ + private_sim_manager_t *this = malloc_thing(private_sim_manager_t); + + this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card; + this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card; + this->public.create_card_enumerator = (enumerator_t*(*)(sim_manager_t*))create_card_enumerator; + this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider; + this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider; + this->public.create_provider_enumerator = (enumerator_t*(*)(sim_manager_t*))create_provider_enumerator; + this->public.destroy = (void(*)(sim_manager_t*))destroy; + + this->cards = linked_list_create(); + this->provider = linked_list_create(); + + return &this->public; +} + diff --git a/src/charon/sa/authenticators/eap/sim_manager.h b/src/charon/sa/authenticators/eap/sim_manager.h new file mode 100644 index 000000000..7fb1f2858 --- /dev/null +++ b/src/charon/sa/authenticators/eap/sim_manager.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sim_manager sim_manager + * @{ @ingroup eap + */ + +#ifndef SIM_MANAGER_H_ +#define SIM_MANAGER_H_ + +#include <utils/identification.h> +#include <utils/enumerator.h> + +typedef struct sim_manager_t sim_manager_t; +typedef struct sim_card_t sim_card_t; +typedef struct sim_provider_t sim_provider_t; + +/** + * Interface for a SIM card (used as EAP client). + */ +struct sim_card_t { + + /** + * Get the identity of a SIM card. + * + * The returned identity owned by the sim_card and not destroyed outside. + * The SIM card may return ID_ANY if it does not support/use an IMSI. + * + * @return identity of type ID_EAP/ID_ANY + */ + identification_t* (*get_imsi)(sim_card_t *this); + + /** + * Calculate SRES/KC from a RAND. + * + * @param rand RAND input buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if SRES/KC calculated, FALSE on error + */ + bool (*get_triplet)(sim_card_t *this, + char rand[16], char sres[4], char kc[8]); +}; + +/** + * Interface for a triplet provider (used as EAP server). + */ +struct sim_provider_t { + + /** + * Get a single triplet to authenticate a EAP client. + * + * @param imsi client identity of type ID_EAP + * @param rand RAND output buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if triplet received, FALSE otherwise + */ + bool (*get_triplet)(sim_provider_t *this, identification_t *imsi, + char rand[16], char sres[4], char kc[8]); +}; + +/** + * The EAP-SIM manager handles multiple SIM cards and providers. + */ +struct sim_manager_t { + + /** + * Register a SIM card (client) at the manager. + * + * @param card sim card to register + */ + void (*add_card)(sim_manager_t *this, sim_card_t *card); + + /** + * Unregister a previously registered card from the manager. + * + * @param card sim card to unregister + */ + void (*remove_card)(sim_manager_t *this, sim_card_t *card); + + /** + * Create an enumerator over all registered cards. + * + * @return enumerator over sim_card_t's + */ + enumerator_t* (*create_card_enumerator)(sim_manager_t *this); + + /** + * Register a triplet provider (server) at the manager. + * + * @param card sim card to register + */ + void (*add_provider)(sim_manager_t *this, sim_provider_t *provider); + + /** + * Unregister a previously registered provider from the manager. + * + * @param card sim card to unregister + */ + void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider); + + /** + * Create an enumerator over all registered provider. + * + * @return enumerator over sim_provider_t's + */ + enumerator_t* (*create_provider_enumerator)(sim_manager_t *this); + + /** + * Destroy a manager instance. + */ + void (*destroy)(sim_manager_t *this); +}; + +/** + * Create an SIM manager to handle multiple SIM cards/providers. + * + * @return sim_t object + */ +sim_manager_t *sim_manager_create(); + +#endif /* SIM_MANAGER_H_ @}*/ diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index 95bb5e57f..0909d6563 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: eap_authenticator.c 3589 2008-03-13 14:14:44Z martin $ + * $Id: eap_authenticator.c 4292 2008-08-26 19:54:47Z andreas $ */ #include <string.h> @@ -54,6 +54,21 @@ struct private_eap_authenticator_t { * MSK used to build and verify auth payload */ chunk_t msk; + + /** + * should we do a EAP-Identity exchange as server? + */ + bool do_eap_identity; + + /** + * saved EAP type if we do eap_identity + */ + eap_type_t type; + + /** + * saved vendor id if we do eap_identity + */ + u_int32_t vendor; }; /** @@ -93,7 +108,7 @@ static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init, chunk_free(&auth_data); DBG1(DBG_IKE, "authentication of '%D' with %N successful", - other_id, auth_method_names, AUTH_EAP); + other_id, auth_class_names, AUTH_CLASS_EAP); return SUCCESS; } @@ -107,7 +122,7 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init, identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa); DBG1(DBG_IKE, "authentication of '%D' (myself) with %N", - my_id, auth_method_names, AUTH_EAP); + my_id, auth_class_names, AUTH_CLASS_EAP); if (this->msk.len) { /* use MSK if EAP method established one... */ @@ -130,6 +145,79 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init, } /** + * get the peers identity to use in the EAP method + */ +static identification_t *get_peer_id(private_eap_authenticator_t *this) +{ + identification_t *id; + peer_cfg_t *config; + auth_info_t *auth; + + id = this->ike_sa->get_eap_identity(this->ike_sa); + if (!id) + { + config = this->ike_sa->get_peer_cfg(this->ike_sa); + auth = config->get_auth(config); + if (!auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id)) + { + if (this->role == EAP_PEER) + { + id = this->ike_sa->get_my_id(this->ike_sa); + } + else + { + id = this->ike_sa->get_other_id(this->ike_sa); + } + } + } + if (id->get_type(id) == ID_EAP) + { + return id->clone(id); + } + return identification_create_from_encoding(ID_EAP, id->get_encoding(id)); +} + +/** + * get the servers identity to use in the EAP method + */ +static identification_t *get_server_id(private_eap_authenticator_t *this) +{ + identification_t *id; + + if (this->role == EAP_SERVER) + { + id = this->ike_sa->get_my_id(this->ike_sa); + } + else + { + id = this->ike_sa->get_other_id(this->ike_sa); + } + if (id->get_type(id) == ID_EAP) + { + return id->clone(id); + } + return identification_create_from_encoding(ID_EAP, id->get_encoding(id)); +} + +/** + * load an EAP method using the correct identities + */ +static eap_method_t *load_method(private_eap_authenticator_t *this, + eap_type_t type, u_int32_t vendor, eap_role_t role) +{ + identification_t *server, *peer; + eap_method_t *method; + + server = get_server_id(this); + peer = get_peer_id(this); + method = charon->eap->create_instance(charon->eap, type, vendor, role, + server, peer); + server->destroy(server); + peer->destroy(peer); + return method; +} + +/** * Implementation of eap_authenticator_t.initiate */ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, @@ -138,6 +226,14 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, /* if initiate() is called, role is always server */ this->role = EAP_SERVER; + if (this->do_eap_identity) + { /* do an EAP-Identity request first */ + this->type = type; + this->vendor = vendor; + vendor = 0; + type = EAP_IDENTITY; + } + if (type == 0) { DBG1(DBG_IKE, @@ -148,20 +244,23 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, if (vendor) { - DBG1(DBG_IKE, "requesting vendor specific EAP authentication %d-%d", + DBG1(DBG_IKE, "requesting vendor specific EAP method %d-%d", type, vendor); } else { - DBG1(DBG_IKE, "requesting %N authentication", eap_type_names, type); + DBG1(DBG_IKE, "requesting EAP method %N", eap_type_names, type); } - this->method = charon->eap->create_instance(charon->eap, type, vendor, - this->role, this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); - + this->method = load_method(this, type, vendor, this->role); if (this->method == NULL) { - + if (vendor == 0 && type == EAP_IDENTITY) + { + DBG1(DBG_IKE, "skipping %N, no implementation found", + eap_type_names, type); + this->do_eap_identity = FALSE; + return initiate(this, this->type, this->vendor, out); + } DBG1(DBG_IKE, "configured EAP server method not supported, sending %N", eap_code_names, EAP_FAILURE); *out = eap_payload_create_code(EAP_FAILURE, 0); @@ -192,10 +291,7 @@ static status_t process_peer(private_eap_authenticator_t *this, { eap_method_t *method; - method = charon->eap->create_instance(charon->eap, type, 0, EAP_PEER, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa)); - + method = load_method(this, type, 0, EAP_PEER); if (method == NULL || method->process(method, in, out) != SUCCESS) { DBG1(DBG_IKE, "EAP server requested %N, but unable to process", @@ -203,10 +299,7 @@ static status_t process_peer(private_eap_authenticator_t *this, DESTROY_IF(method); return FAILED; } - - DBG1(DBG_IKE, "EAP server requested %N, sending IKE identity", - eap_type_names, type); - + DBG1(DBG_IKE, "EAP server requested %N", eap_type_names, type); method->destroy(method); return NEED_MORE; } @@ -224,10 +317,7 @@ static status_t process_peer(private_eap_authenticator_t *this, DBG1(DBG_IKE, "EAP server requested %N authentication", eap_type_names, type); } - this->method = charon->eap->create_instance(charon->eap, - type, vendor, EAP_PEER, - this->ike_sa->get_other_id(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa)); + this->method = load_method(this, type, vendor, EAP_PEER); if (this->method == NULL) { DBG1(DBG_IKE, "EAP server requested unsupported " @@ -251,7 +341,7 @@ static status_t process_peer(private_eap_authenticator_t *this, } else { - DBG1(DBG_IKE, "EAP method %N succeded", eap_type_names, type); + DBG1(DBG_IKE, "EAP method %N succeeded", eap_type_names, type); } return SUCCESS; case FAILED: @@ -271,6 +361,27 @@ static status_t process_peer(private_eap_authenticator_t *this, } /** + * handle an EAP-Identity response on the server + */ +static status_t process_eap_identity(private_eap_authenticator_t *this, + eap_payload_t **out) +{ + chunk_t data; + identification_t *id; + + if (this->method->get_msk(this->method, &data) == SUCCESS) + { + id = identification_create_from_encoding(ID_EAP, data); + DBG1(DBG_IKE, "using EAP identity '%D'", id); + this->ike_sa->set_eap_identity(this->ike_sa, id); + } + /* restart EAP exchange, but with real method */ + this->method->destroy(this->method); + this->do_eap_identity = FALSE; + return initiate(this, this->type, this->vendor, out); +} + +/** * Processing method for a server */ static status_t process_server(private_eap_authenticator_t *this, @@ -286,6 +397,10 @@ static status_t process_server(private_eap_authenticator_t *this, case NEED_MORE: return NEED_MORE; case SUCCESS: + if (this->do_eap_identity) + { + return process_eap_identity(this, out); + } if (this->method->get_msk(this->method, &this->msk) == SUCCESS) { this->msk = chunk_clone(this->msk); @@ -409,6 +524,9 @@ static void destroy(private_eap_authenticator_t *this) */ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa) { + peer_cfg_t *config; + auth_info_t *auth; + identification_t *id; private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t); /* public functions */ @@ -425,6 +543,25 @@ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa) this->role = EAP_PEER; this->method = NULL; this->msk = chunk_empty; + this->do_eap_identity = FALSE; + this->type = 0; + this->vendor = 0; + config = ike_sa->get_peer_cfg(ike_sa); + if (config) + { + auth = config->get_auth(config); + if (auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id)) + { + if (id->get_type(id) == ID_ANY) + { /* %any as configured EAP identity runs EAP-Identity first */ + this->do_eap_identity = TRUE; + } + else + { + ike_sa->set_eap_identity(ike_sa, id->clone(id)); + } + } + } return &this->public; } diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h index 2dad59fbb..bd300a584 100644 --- a/src/charon/sa/authenticators/eap_authenticator.h +++ b/src/charon/sa/authenticators/eap_authenticator.h @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: eap_authenticator.h 3589 2008-03-13 14:14:44Z martin $ + * $Id: eap_authenticator.h 4276 2008-08-22 10:44:51Z martin $ */ /** @@ -29,7 +29,7 @@ typedef struct eap_authenticator_t eap_authenticator_t; #include <encoding/payloads/eap_payload.h> /** - * Implementation of the authenticator_t interface using AUTH_EAP. + * Implementation of the authenticator_t interface using AUTH_CLASS_EAP. * * Authentication using EAP involves the most complex authenticator. It stays * alive over multiple ike_auth transactions and handles multiple EAP @@ -137,7 +137,7 @@ struct eap_authenticator_t { }; /** - * Creates an authenticator for AUTH_EAP. + * Creates an authenticator for AUTH_CLASS_EAP. * * @param ike_sa associated ike_sa * @return eap_authenticator_t object |