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 */
                        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 */
                        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_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;
         * 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.
  */
 /**
  * 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;
 }
 
        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,
                                                        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,
                                                        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_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;
        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->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;
        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.
        
        /**
         * @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 this          calling object
+        * @param vendor        receives vendor specifier, 0 for predefined EAP types
         * @return                      authentication method
         */
         * @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.
        
        /**
         * @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 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
  * @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,
                                                        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,
                                                        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;
        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);
        
        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
                &&  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));
                {
                        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,
                
                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,
                                        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.
  */
 /**
  * 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)
        {
        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;
 }
        }
        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.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;
        
        /* private variables */
        this->critical = FALSE;
@@ -329,3 +341,4 @@ eap_payload_t *eap_payload_create_nak()
        this->set_data(this, data);
        return this;
 }
        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
         * @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.
        
        /**
         * @brief Destroys an eap_payload_t object.
index fc2ffcd..8fb1f85 100644 (file)
@@ -42,6 +42,8 @@
 
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
 
 #include "eap_aka.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;
 
 {
        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;
        }
        {
                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.
  */
 /**
  * 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;
 }
 
        return EAP_AKA;
 }
 
@@ -1417,7 +1420,7 @@ eap_aka_t *eap_create(eap_role_t role,
                        free(this);
                        return NULL;
        }
                        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;
        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.
  */
 /**
  * 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;
 }
 
        return EAP_MD5;
 }
 
@@ -265,7 +266,7 @@ eap_md5_t *eap_create(eap_role_t role,
                        free(this);
                        return NULL;
        }
                        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;
        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");
        "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",
 
 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;
  */
 struct module_entry_t {
        eap_type_t type;
+       u_int32_t vendor;
        void *handle;
        eap_constructor_t constructor;
 };
        void *handle;
        eap_constructor_t constructor;
 };
@@ -85,7 +89,8 @@ void eap_method_unload()
                
                while (modules->remove_last(modules, (void**)&entry) == SUCCESS)
                {
                
                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);
                }
                        dlclose(entry->handle);
                        free(entry);
                }
@@ -165,11 +170,19 @@ void eap_method_load(char *directory)
                        dlclose(module.handle);
                        continue;
                }
                        dlclose(module.handle);
                        continue;
                }
-               module.type = method->get_type(method);
+               module.type = method->get_type(method, &module.vendor);
                method->destroy(method);
                
                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));
                         
                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.
  */
 /*
  * 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;
 {
        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))
        {
        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)
                {
                        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)
        {
        
        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;
 }
        }
        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_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
         * @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
         */
         * @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.
        
        /**
         * @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
  * @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)
  * @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
  */
  *
  * @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.
 
 /**
  * @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.
  */
 /**
  * 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;
 }
 
        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;
        /* 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;
        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,
  * 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;
 {
        /* 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;
        }
        
                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)
        {
                                                                         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)
        {
                *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;  
                         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)
 {
 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));
                
                                                                           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)
        {
        /* 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 "
                                                        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;
                }
        }
        
                        *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:
        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:
                        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;
        }
 }
                        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)
 {
 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:
        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)
                        {
                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);
                        }
                                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
                        {
                        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:
                        }
                        *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;
        }
                        *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.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 */
        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".
         *
         * 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,
         * @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.
        
        /**
         * @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;
 {
        peer_cfg_t *config;
        eap_type_t eap_type;
+       u_int32_t eap_vendor;
        eap_payload_t *eap_payload;
        status_t status;
 
        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;
        }
                message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
                return FAILED;
        }
-               
+       
        /* initiate EAP authenitcation */
        /* 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)
        {
        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:
                        }
                        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"))
                        {
                        if (streq(kw->value, "aka"))
                        {
-                               conn->eap = 23;
+                               conn->eap_type = 23;
                        }
                        else if (streq(kw->value, "sim"))
                        {
                        }
                        else if (streq(kw->value, "sim"))
                        {
-                               conn->eap = 18;
+                               conn->eap_type = 18;
                        }
                        else if (streq(kw->value, "md5"))
                        {
                        }
                        else if (streq(kw->value, "md5"))
                        {
-                               conn->eap = 4;
+                               conn->eap_type = 4;
                        }
                        else
                        {
                        }
                        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;
                                {
                                        plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value);
                                        cfg->err++;
                                }
                        }
                        break;
+               }
                case KW_KEYINGTRIES:
                        if (streq(kw->value, "%forever"))
                        {
                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;
        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;
        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
 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
 .B authby=eap
-is selected. Acceptable values are
+selected. Acceptable values are
 .B aka
 .B aka
-for EAP-AKA and
+for EAP-AKA,
 .B sim
 .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
 .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.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)
        {
        
        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;
                        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;
                        int mode;
                        int mobike;
                        int force_encap;