implemented Expanded EAP types to support vendor specific methods
authorMartin Willi <martin@strongswan.org>
Thu, 13 Dec 2007 17:31:21 +0000 (17:31 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 13 Dec 2007 17:31:21 +0000 (17:31 -0000)
19 files changed:
src/charon/config/backends/sqlite_backend.c
src/charon/config/peer_cfg.c
src/charon/config/peer_cfg.h
src/charon/control/interfaces/stroke_interface.c
src/charon/encoding/payloads/eap_payload.c
src/charon/encoding/payloads/eap_payload.h
src/charon/sa/authenticators/eap/eap_aka.c
src/charon/sa/authenticators/eap/eap_md5.c
src/charon/sa/authenticators/eap/eap_method.c
src/charon/sa/authenticators/eap/eap_method.h
src/charon/sa/authenticators/eap/eap_sim.c
src/charon/sa/authenticators/eap_authenticator.c
src/charon/sa/authenticators/eap_authenticator.h
src/charon/sa/tasks/ike_auth.c
src/starter/confread.c
src/starter/confread.h
src/starter/ipsec.conf.5
src/starter/starterstroke.c
src/stroke/stroke.h

index 806ccaf..e1c96c8 100644 (file)
@@ -186,7 +186,7 @@ static peer_cfg_t *process_peer_cfg_row(private_sqlite_backend_t *this,
                        2, ike_cfg,     local_id, remote_id, NULL, NULL, linked_list_create(),
                        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 */
index fa842c5..0b5d391 100644 (file)
@@ -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;
index 12c1f5c..7f1dbca 100644 (file)
@@ -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,
index 26c55be..b51d53e 100755 (executable)
@@ -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,
index 79ab32f..345114a 100644 (file)
@@ -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;
 }
+
index 13c0ade..3addbb8 100644 (file)
@@ -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.
index fc2ffcd..8fb1f85 100644 (file)
@@ -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;
index 8fe74ed..ca5c1d6 100644 (file)
@@ -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;
index e4a58f0..7434ca2 100644 (file)
@@ -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;
 }
index d43dc00..8675fd8 100644 (file)
@@ -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.
index e369c56..c9eb5ce 100644 (file)
@@ -698,8 +698,9 @@ static status_t initiate(private_eap_sim_t *this, eap_payload_t **out)
 /**
  * Implementation of eap_method_t.get_type.
  */
-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;
index 6e2f73a..6250604 100644 (file)
@@ -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 */
index 64a3267..cf2180e 100644 (file)
@@ -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.
index 29c38ee..de88a0a 100644 (file)
@@ -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)
        {
index b758ffd..5dfcf93 100644 (file)
@@ -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"))
                        {
index 11ca29d..3f18840 100644 (file)
@@ -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;
index 4327b55..56032c7 100644 (file)
@@ -350,13 +350,21 @@ in case of inactivity. This only applies to IKEv1, in IKEv2 the default
 retransmission timeout applies, as every exchange is used to detect dead peers.
 .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
index c946691..67e0cad 100644 (file)
@@ -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)
        {
index 55cefef..7ccddfb 100644 (file)
@@ -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;