summaryrefslogtreecommitdiff
path: root/src/charon/sa/authenticators
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2008-10-29 20:30:44 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2008-10-29 20:30:44 +0000
commit74f0bbfc53cb5fa519e4e27ece53735ab51b397c (patch)
tree0dbab9c835be15577ff05b474b6361bb326d66ce /src/charon/sa/authenticators
parent5c1fa2516bda1ccf8eb00178c0beb196c2020a94 (diff)
downloadvyos-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.c30
-rw-r--r--src/charon/sa/authenticators/authenticator.h75
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.c10
-rw-r--r--src/charon/sa/authenticators/eap/eap_method.h13
-rw-r--r--src/charon/sa/authenticators/eap/sim_manager.c125
-rw-r--r--src/charon/sa/authenticators/eap/sim_manager.h136
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.c183
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.h6
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