ported parts of two-sim branch
authorMartin Willi <martin@strongswan.org>
Fri, 22 Aug 2008 10:44:51 +0000 (10:44 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 22 Aug 2008 10:44:51 +0000 (10:44 -0000)
eap_identity parameter to exchange in eap_identity
some auth_info/peer_cfg refactorings
fixed some bugs, introduced new ones

40 files changed:
src/charon/config/peer_cfg.c
src/charon/config/peer_cfg.h
src/charon/credentials/auth_info.c
src/charon/credentials/auth_info.h
src/charon/plugins/eap_aka/eap_aka.c
src/charon/plugins/eap_gtc/eap_gtc.c
src/charon/plugins/eap_identity/eap_identity.c
src/charon/plugins/eap_identity/eap_identity.h
src/charon/plugins/eap_identity/eap_identity_plugin.c
src/charon/plugins/eap_md5/eap_md5.c
src/charon/plugins/eap_sim/eap_sim.c
src/charon/plugins/medcli/medcli_config.c
src/charon/plugins/medsrv/medsrv_config.c
src/charon/plugins/nm/nm_service.c
src/charon/plugins/sql/sql_config.c
src/charon/plugins/stroke/stroke_config.c
src/charon/plugins/stroke/stroke_cred.c
src/charon/plugins/stroke/stroke_list.c
src/charon/plugins/stroke/stroke_socket.c
src/charon/plugins/uci/uci_config.c
src/charon/sa/authenticators/authenticator.c
src/charon/sa/authenticators/authenticator.h
src/charon/sa/authenticators/eap/eap_method.h
src/charon/sa/authenticators/eap_authenticator.c
src/charon/sa/authenticators/eap_authenticator.h
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/tasks/ike_auth.c
src/charon/sa/tasks/ike_cert_post.c
src/libstrongswan/chunk.c
src/libstrongswan/chunk.h
src/libstrongswan/utils/identification.c
src/libstrongswan/utils/identification.h
src/starter/args.c
src/starter/confread.h
src/starter/ipsec.conf.5
src/starter/keywords.h
src/starter/keywords.txt
src/starter/starterstroke.c
src/stroke/stroke_msg.h

index de0fb67..319be63 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -37,12 +37,6 @@ ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
        "UNIQUE_KEEP",
 );
 
-ENUM(config_auth_method_names, CONF_AUTH_PUBKEY, CONF_AUTH_EAP,
-       "PUBKEY",
-       "PSK",
-       "EAP",
-);
-
 typedef struct private_peer_cfg_t private_peer_cfg_t;
 
 /**
@@ -106,21 +100,6 @@ struct private_peer_cfg_t {
        unique_policy_t unique;
        
        /**
-        * Method to use for own authentication data
-        */
-       config_auth_method_t auth_method;
-       
-       /**
-        * EAP type to use for peer authentication
-        */
-       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;
@@ -319,23 +298,6 @@ static unique_policy_t get_unique_policy(private_peer_cfg_t *this)
 }
 
 /**
- * Implementation of peer_cfg_t.get_auth_method.
- */
-static config_auth_method_t get_auth_method(private_peer_cfg_t *this)
-{
-       return this->auth_method;
-}
-
-/**
- * Implementation of peer_cfg_t.get_eap_type.
- */
-static eap_type_t get_eap_type(private_peer_cfg_t *this, u_int32_t *vendor)
-{
-       *vendor = this->eap_vendor;
-       return this->eap_type;
-}
-
-/**
  * Implementation of peer_cfg_t.get_keyingtries.
  */
 static u_int32_t get_keyingtries(private_peer_cfg_t *this)
@@ -469,9 +431,6 @@ static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
                this->other_id->equals(this->other_id, other->other_id) &&
                this->cert_policy == other->cert_policy &&
                this->unique == other->unique &&
-               this->auth_method == other->auth_method &&
-               this->eap_type == other->eap_type &&
-               this->eap_vendor == other->eap_vendor &&
                this->keyingtries == other->keyingtries &&
                this->use_mobike == other->use_mobike &&
                this->rekey_time == other->rekey_time &&
@@ -533,8 +492,6 @@ static void destroy(private_peer_cfg_t *this)
 peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
                                                        identification_t *my_id, identification_t *other_id,
                                                        cert_policy_t cert_policy, unique_policy_t unique,
-                                                       config_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 dpd,
@@ -556,8 +513,6 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
        this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
        this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
        this->public.get_unique_policy = (unique_policy_t (*) (peer_cfg_t *))get_unique_policy;
-       this->public.get_auth_method = (config_auth_method_t (*) (peer_cfg_t *))get_auth_method;
-       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;
@@ -586,9 +541,6 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
        this->other_id = other_id;
        this->cert_policy = cert_policy;
        this->unique = unique;
-       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 7b9b01a..d88feac 100644 (file)
@@ -27,7 +27,6 @@
 
 typedef enum cert_policy_t cert_policy_t;
 typedef enum unique_policy_t unique_policy_t;
-typedef enum config_auth_method_t config_auth_method_t;
 typedef struct peer_cfg_t peer_cfg_t;
 
 #include <library.h>
@@ -82,23 +81,6 @@ enum unique_policy_t {
 extern enum_name_t *unique_policy_names;
 
 /**
- * Authentication method for this IKE_SA.
- */
-enum config_auth_method_t {
-       /** authentication using public keys (RSA, ECDSA) */
-       CONF_AUTH_PUBKEY =      1,
-       /** authentication using a pre-shared secret */
-       CONF_AUTH_PSK =         2,
-       /** authentication using EAP */
-       CONF_AUTH_EAP =         3,
-};
-
-/**
- * enum strings for config_auth_method_t
- */
-extern enum_name_t *config_auth_method_names;
-
-/**
  * Configuration of a peer, specified by IDs.
  *
  * The peer config defines a connection between two given IDs. It contains
@@ -220,25 +202,6 @@ struct peer_cfg_t {
         * @return                      unique policy
         */
        unique_policy_t (*get_unique_policy) (peer_cfg_t *this);
-
-       /**
-        * Get the authentication method to use to authenticate us.
-        * 
-        * @return                      authentication method
-        */
-       config_auth_method_t (*get_auth_method) (peer_cfg_t *this);
-       
-       /**
-        * 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 vendor        receives vendor specifier, 0 for predefined EAP types
-        * @return                      authentication method
-        */
-       eap_type_t (*get_eap_type) (peer_cfg_t *this, u_int32_t *vendor);
        
        /**
         * Get the max number of retries after timeout.
@@ -372,9 +335,6 @@ struct peer_cfg_t {
  * @param other_id                     identification_t for the remote guy
  * @param cert_policy          should we send a certificate payload?
  * @param unique                       uniqueness of an IKE_SA
- * @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
@@ -393,8 +353,6 @@ struct peer_cfg_t {
 peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
                                                        identification_t *my_id, identification_t *other_id,
                                                        cert_policy_t cert_policy, unique_policy_t unique,
-                                                       config_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 dpd,
index 5d4a0f2..42e1ea4 100644 (file)
 #include <credentials/certificates/certificate.h>
 
 ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP,
+       "AUTHN_AUTH_CLASS",
+       "AUTHN_EAP_TYPE",
+       "AUTHN_EAP_VENDOR",
+       "AUTHN_EAP_IDENTITY",
        "AUTHN_CA_CERT",
        "AUTHN_CA_CERT_KEYID",
        "AUTHN_CA_CERT_NAME",
@@ -208,14 +212,18 @@ static void add_item(private_auth_info_t *this, auth_item_t type, void *value)
                        item->value = validation;
                        break;
                }
+               case AUTHN_AUTH_CLASS:
+               case AUTHN_EAP_TYPE:
+               case AUTHN_EAP_VENDOR:
                case AUTHZ_EAP:
                {
-                       eap_method_t *method = malloc_thing(eap_method_t);
+                       u_int *intval = malloc_thing(u_int);
 
-                       *method = *(eap_method_t*)value;
-                       item->value = method;
+                       *intval = *(u_int*)value;
+                       item->value = intval;
                        break;
                }
+               case AUTHN_EAP_IDENTITY:
                case AUTHN_CA_CERT_KEYID:
                case AUTHN_CA_CERT_NAME:
                case AUTHZ_CA_CERT_NAME:
@@ -246,6 +254,10 @@ static bool complies(private_auth_info_t *this, auth_info_t *constraints)
        {
                switch (t1)
                {
+                       case AUTHN_AUTH_CLASS:
+                       case AUTHN_EAP_TYPE:
+                       case AUTHN_EAP_VENDOR:
+                       case AUTHN_EAP_IDENTITY:
                        case AUTHN_CA_CERT_KEYID:
                        case AUTHN_CA_CERT:
                        case AUTHN_CA_CERT_NAME:
@@ -444,6 +456,7 @@ static bool equals(private_auth_info_t *this, private_auth_info_t *other)
                                                }
                                                continue;
                                        }
+                                       case AUTHN_EAP_IDENTITY:
                                        case AUTHN_CA_CERT_KEYID:
                                        case AUTHN_CA_CERT_NAME:
                                        case AUTHZ_CA_CERT_NAME:
@@ -460,6 +473,16 @@ static bool equals(private_auth_info_t *this, private_auth_info_t *other)
                                                }
                                                continue;
                                        }
+                                       case AUTHN_AUTH_CLASS:
+                                       case AUTHN_EAP_TYPE:
+                                       case AUTHN_EAP_VENDOR:
+                                       {
+                                               if (*(u_int*)i1->value == *(u_int*)i2->value)
+                                               {
+                                                       found = TRUE;
+                                                       break;
+                                               }
+                                       }
                                        case AUTHZ_PUBKEY:
                                        case AUTHZ_PSK:
                                        case AUTHZ_EAP:
@@ -511,6 +534,9 @@ static void destroy_item_value(item_t *item)
                        cert->destroy(cert);
                        break;
                }
+               case AUTHN_AUTH_CLASS:
+               case AUTHN_EAP_TYPE:
+               case AUTHN_EAP_VENDOR:
                case AUTHN_IM_HASH_URL:
                case AUTHN_SUBJECT_HASH_URL:
                case AUTHZ_CRL_VALIDATION:
@@ -520,6 +546,7 @@ static void destroy_item_value(item_t *item)
                        free(item->value);
                        break;
                }
+               case AUTHN_EAP_IDENTITY:
                case AUTHN_CA_CERT_KEYID:
                case AUTHN_CA_CERT_NAME:
                case AUTHZ_CA_CERT_NAME:
index 5fe2919..5243343 100644 (file)
@@ -60,6 +60,14 @@ enum auth_item_t {
         * items provided to authentication process
         */
        
+       /** authentication class to use, value is auth_class_t* */
+       AUTHN_AUTH_CLASS,
+       /** EAP method to request from peer, value is eap_type_t* */
+       AUTHN_EAP_TYPE,
+       /** EAP vendor to used in conjunction with EAP method, value is u_int32_t* */
+       AUTHN_EAP_VENDOR,
+       /** EAP identity to use within EAP-Identity exchange */
+       AUTHN_EAP_IDENTITY,
        /** CA certificate to use for authentication, value is certificate_t* */
        AUTHN_CA_CERT,
        /** Keyid of a CA certificate to use, value is identification_t* */
@@ -83,7 +91,7 @@ enum auth_item_t {
        AUTHZ_PUBKEY,
        /** subject has ben authenticated using preshared secrets, value is shared_key_t* */ 
        AUTHZ_PSK,
-       /** subject has been authenticated using EAP, value is eap_method_t */
+       /** subject has been authenticated using EAP, value is eap_type_t* */
        AUTHZ_EAP,
        /** certificate authority, value is certificate_t* */
        AUTHZ_CA_CERT,
index 3bf3ccb..bab56bb 100644 (file)
@@ -829,6 +829,19 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code
 }
 
 /**
+ * generate a new non-zero identifier
+ */
+static u_char get_identifier()
+{
+       u_char id;
+       
+       do {
+               id = random();
+       } while (!id);
+       return id;
+}
+
+/**
  * Initiate a AKA-Challenge using SQN
  */
 static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn,
@@ -900,7 +913,7 @@ static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn,
        derive_keys(this, this->peer);
        
        /* build payload */
-       *out = build_aka_payload(this, EAP_REQUEST, 0, AKA_CHALLENGE,
+       *out = build_aka_payload(this, EAP_REQUEST, get_identifier(), AKA_CHALLENGE,
                                                         AT_RAND, this->rand, AT_AUTN, autn, AT_MAC,
                                                         chunk_empty, AT_END);
        return NEED_MORE;
@@ -1449,6 +1462,8 @@ static bool is_mutual(private_eap_aka_t *this)
  */
 static void destroy(private_eap_aka_t *this)
 {
+       this->server->destroy(this->server);
+       this->peer->destroy(this->peer);
        DESTROY_IF(this->sha1);
        DESTROY_IF(this->signer);
        DESTROY_IF(this->prf);
@@ -1479,8 +1494,8 @@ static private_eap_aka_t *eap_aka_create_generic(identification_t *server,
        this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
        
        /* private data */
-       this->server = server;
-       this->peer = peer;
+       this->server = server->clone(server);
+       this->peer = peer->clone(peer);
        this->k_encr = chunk_empty;
        this->k_auth = chunk_empty;
        this->msk = chunk_empty;
index fd39e5a..409858d 100644 (file)
@@ -253,6 +253,8 @@ static bool is_mutual(private_eap_gtc_t *this)
  */
 static void destroy(private_eap_gtc_t *this)
 {
+       this->peer->destroy(this->peer);
+       this->server->destroy(this->server);
        free(this);
 }
 
@@ -272,9 +274,9 @@ static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
        this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
        
        /* private data */
-       this->peer = peer;
-       this->server = server;
-       this->identifier = random();
+       this->peer = peer->clone(peer);
+       this->server = server->clone(server);
+       this->identifier = 0;
        
        return this;
 }
@@ -289,6 +291,11 @@ eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *pee
        this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
        this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
 
+       /* generate a non-zero identifier */
+       do {
+               this->identifier = random();
+       } while (!this->identifier);
+
        return &this->public;
 }
 
index f6835c7..e5b4ae8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -36,39 +36,98 @@ struct private_eap_identity_t {
         * ID of the peer
         */
        identification_t *peer;
+       
+       /**
+        * received identity chunk
+        */
+       chunk_t identity;
 };
 
+typedef struct eap_identity_header_t eap_identity_header_t;
+
+/**
+ * packed EAP Identity header struct
+ */
+struct eap_identity_header_t {
+       /** EAP code (REQUEST/RESPONSE) */
+       u_int8_t code;
+       /** unique message identifier */
+       u_int8_t identifier;
+       /** length of whole message */
+       u_int16_t length;
+       /** EAP type */
+       u_int8_t type;
+       /** identity data */
+       u_int8_t data[];
+} __attribute__((__packed__));
+
 /**
  * Implementation of eap_method_t.process for the peer
  */
-static status_t process(private_eap_identity_t *this,
-                                               eap_payload_t *in, eap_payload_t **out)
+static status_t process_peer(private_eap_identity_t *this,
+                                                        eap_payload_t *in, eap_payload_t **out)
 {
-       chunk_t id, hdr;
+       chunk_t id;
+       eap_identity_header_t *hdr;
+       size_t len;
        
-       hdr = chunk_alloca(5);
        id = this->peer->get_encoding(this->peer);
+       len = sizeof(eap_identity_header_t) + id.len;
        
-       *(hdr.ptr + 0) = EAP_RESPONSE;
-       *(hdr.ptr + 1) = in->get_identifier(in);
-       *(u_int16_t*)(hdr.ptr + 2) = htons(hdr.len + id.len);
-       *(hdr.ptr + 4) = EAP_IDENTITY;
+       hdr = alloca(len);
+       hdr->code = EAP_RESPONSE;
+       hdr->identifier = in->get_identifier(in);
+       hdr->length = htons(len);
+       hdr->type = EAP_IDENTITY;
+       memcpy(hdr->data, id.ptr, id.len);
        
-       *out = eap_payload_create_data(chunk_cata("cc", hdr, id));
+       *out = eap_payload_create_data(chunk_create((u_char*)hdr, len));
        return SUCCESS;
-       
 }
 
 /**
  * Implementation of eap_method_t.initiate for the peer
  */
-static status_t initiate(private_eap_identity_t *this, eap_payload_t **out)
+static status_t initiate_peer(private_eap_identity_t *this, eap_payload_t **out)
 {
        /* peer never initiates */
        return FAILED;
 }
 
 /**
+ * Implementation of eap_method_t.process for the server
+ */
+static status_t process_server(private_eap_identity_t *this,
+                                                          eap_payload_t *in, eap_payload_t **out)
+{
+       chunk_t data;
+       
+       data = chunk_skip(in->get_data(in), 5);
+       if (data.len)
+       {
+               this->identity = chunk_clone(data);
+       }
+       return SUCCESS;
+}
+
+/**
+ * Implementation of eap_method_t.initiate for the server
+ */
+static status_t initiate_server(private_eap_identity_t *this, eap_payload_t **out)
+{
+       eap_identity_header_t hdr;
+       
+       hdr.code = EAP_REQUEST;
+       hdr.identifier = 0;
+       hdr.length = htons(sizeof(eap_identity_header_t));
+       hdr.type = EAP_IDENTITY;
+       
+       *out = eap_payload_create_data(chunk_create((u_char*)&hdr,
+                                                                                               sizeof(eap_identity_header_t)));
+       return NEED_MORE;
+}
+
+/**
  * Implementation of eap_method_t.get_type.
  */
 static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor)
@@ -82,6 +141,11 @@ static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor)
  */
 static status_t get_msk(private_eap_identity_t *this, chunk_t *msk)
 {
+       if (this->identity.ptr)
+       {
+               *msk = this->identity;
+               return SUCCESS;
+       }
        return FAILED;
 }
 
@@ -98,27 +162,58 @@ static bool is_mutual(private_eap_identity_t *this)
  */
 static void destroy(private_eap_identity_t *this)
 {
+       this->peer->destroy(this->peer);
+       free(this->identity.ptr);
        free(this);
 }
 
-/*
- * Described in header.
+/**
+ * Generic constructor
  */
-eap_identity_t *eap_identity_create_peer(identification_t *server,
-                                                                                identification_t *peer)
+static private_eap_identity_t *eap_identity_create(identification_t *server,
+                                                                                                  identification_t *peer)
 {
        private_eap_identity_t *this = malloc_thing(private_eap_identity_t);
        
-       /* 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.initiate = NULL;
+       this->public.eap_method_interface.process = NULL;
        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;
        
-       /* private data */
-       this->peer = peer;
+       this->peer = peer->clone(peer);
+       this->identity = chunk_empty;
+       
+       return this;
+}
+
+/*
+ * Described in header.
+ */
+eap_identity_t *eap_identity_create_peer(identification_t *server,
+                                                                                identification_t *peer)
+{
+       private_eap_identity_t *this = eap_identity_create(server, peer);
+       
+       /* public functions */
+       this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
+       this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
+       
+       return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+eap_identity_t *eap_identity_create_server(identification_t *server,
+                                                                                  identification_t *peer)
+{
+       private_eap_identity_t *this = eap_identity_create(server, peer);
+       
+       /* public functions */
+       this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
+       this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
        
        return &this->public;
 }
index 5d297f7..d45f6ca 100644 (file)
@@ -39,6 +39,16 @@ struct eap_identity_t {
 };
 
 /**
+ * Creates the EAP method EAP Identity, acting as server.
+ *
+ * @param server       ID of the EAP server
+ * @param peer         ID of the EAP client
+ * @return                     eap_identity_t object
+ */
+eap_identity_t *eap_identity_create_server(identification_t *server,
+                                                                                  identification_t *peer);
+
+/**
  * Creates the EAP method EAP Identity, acting as peer.
  *
  * @param server       ID of the EAP server
index 22a884a..f322ca3 100644 (file)
@@ -27,6 +27,8 @@
 static void destroy(eap_identity_plugin_t *this)
 {
        charon->eap->remove_method(charon->eap,
+                                                          (eap_constructor_t)eap_identity_create_server);
+       charon->eap->remove_method(charon->eap,
                                                           (eap_constructor_t)eap_identity_create_peer);
        free(this);
 }
@@ -40,6 +42,8 @@ plugin_t *plugin_create()
        
        this->plugin.destroy = (void(*)(plugin_t*))destroy;
        
+       charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_SERVER,
+                                                       (eap_constructor_t)eap_identity_create_server);
        charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER,
                                                        (eap_constructor_t)eap_identity_create_peer);
        
index 7f41b2e..5339480 100644 (file)
@@ -242,6 +242,8 @@ static bool is_mutual(private_eap_md5_t *this)
  */
 static void destroy(private_eap_md5_t *this)
 {
+       this->peer->destroy(this->peer);
+       this->server->destroy(this->server);
        chunk_free(&this->challenge);
        free(this);
 }
@@ -262,10 +264,10 @@ static private_eap_md5_t *eap_md5_create_generic(identification_t *server,
        this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
        
        /* private data */
-       this->peer = peer;
-       this->server = server;
+       this->peer = peer->clone(peer);
+       this->server = server->clone(server);
        this->challenge = chunk_empty;
-       this->identifier = random();
+       this->identifier = 0;
        
        return this;
 }
@@ -280,6 +282,11 @@ eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *pee
        this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
        this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
 
+       /* generate a non-zero identifier */
+       do {
+               this->identifier = random();
+       } while (!this->identifier);
+
        return &this->public;
 }
 
index 27c2c3a..11d2e74 100644 (file)
@@ -1016,6 +1016,7 @@ static bool is_mutual(private_eap_sim_t *this)
  */
 static void destroy(private_eap_sim_t *this)
 {
+       this->peer->destroy(this->peer);
        dlclose(this->handle);
        DESTROY_IF(this->hasher);
        DESTROY_IF(this->prf);
@@ -1046,7 +1047,7 @@ eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server,
        this->get_triplet = NULL;
        this->nonce = chunk_empty;
        this->sreses = chunk_empty;
-       this->peer = peer;
+       this->peer = peer->clone(peer);
        this->tries = MAX_TRIES;
        this->version.ptr = version;
        this->version.len = sizeof(version);
@@ -1055,7 +1056,10 @@ eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server,
        this->k_encr = chunk_empty;
        this->msk = chunk_empty;
        this->emsk = chunk_empty;
-       this->identifier = random();
+       /* generate a non-zero identifier */
+       do {
+               this->identifier = random();
+       } while (!this->identifier);
        
        this->handle = dlopen(SIM_READER_LIB, RTLD_LAZY);
        if (this->handle == NULL)
index 610ce26..05699f7 100644 (file)
@@ -120,8 +120,7 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
                "mediation", 2, ike_cfg,
                identification_create_from_encoding(ID_KEY_ID, me),
                identification_create_from_encoding(ID_KEY_ID, other),
-               CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY,
-               0, 0,                                                   /* EAP method, vendor */
+               CERT_NEVER_SEND, UNIQUE_REPLACE, 
                1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
                this->rekey*5, this->rekey*3,   /* jitter, overtime */
                TRUE, this->dpd,                                /* mobike, dpddelay */
@@ -149,8 +148,7 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
                name, 2, this->ike->get_ref(this->ike),
                identification_create_from_encoding(ID_KEY_ID, me),
                identification_create_from_encoding(ID_KEY_ID, other),
-               CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY,
-               0, 0,                                                   /* EAP method, vendor */
+               CERT_NEVER_SEND, UNIQUE_REPLACE, 
                1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
                this->rekey*5, this->rekey*3,   /* jitter, overtime */
                TRUE, this->dpd,                                /* mobike, dpddelay */
@@ -213,8 +211,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
                                name, 2, this->ike->get_ref(this->ike),
                                identification_create_from_encoding(ID_KEY_ID, me),
                                identification_create_from_encoding(ID_KEY_ID, other),
-                               CERT_NEVER_SEND, UNIQUE_REPLACE, AUTH_RSA,
-                               0, 0,                                                   /* EAP method, vendor */
+                               CERT_NEVER_SEND, UNIQUE_REPLACE, 
                                1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
                                this->rekey*5, this->rekey*3,   /* jitter, overtime */
                                TRUE, this->dpd,                                /* mobike, dpddelay */
index 1017b9d..4cea6b7 100644 (file)
@@ -99,8 +99,7 @@ static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this,
                        peer_cfg = peer_cfg_create(
                                name, 2, this->ike->get_ref(this->ike),
                                me->clone(me), other->clone(other),
-                               CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY,
-                               0, 0,                                                   /* EAP method, vendor */
+                               CERT_NEVER_SEND, UNIQUE_REPLACE,
                                1, this->rekey*60, 0,                   /* keytries, rekey, reauth */
                                this->rekey*5, this->rekey*3,   /* jitter, overtime */
                                TRUE, this->dpd,                                /* mobike, dpddelay */
index 8e69c78..9f617b8 100644 (file)
@@ -171,7 +171,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        child_cfg_t *child_cfg;
        traffic_selector_t *ts;
        ike_sa_t *ike_sa;
-       config_auth_method_t method = CONF_AUTH_EAP;
+       auth_info_t *auth;
+       auth_class_t auth_class = AUTH_CLASS_EAP;
        
        /**
         * Read parameters
@@ -212,11 +213,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        {
                if (streq(str, "psk"))
                {
-                       method = CONF_AUTH_PSK;
+                       auth_class = AUTH_CLASS_PSK;
                }
                else if (streq(str, "pubkey"))
                {
-                       method = CONF_AUTH_PUBKEY;
+                       auth_class = AUTH_CLASS_PUBKEY;
                }
        }
        
@@ -247,13 +248,14 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user,
                                        identification_create_from_encoding(ID_ANY, chunk_empty),
-                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, method,
-                                       0, 0, 1, /* EAP method, vendor, keyingtries */
+                                       CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
                                        18000, 0, /* rekey 5h, reauth none */
                                        600, 600, /* jitter, over 10min */
                                        TRUE, 0, /* mobike, DPD */
                                        virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
                                        NULL, FALSE, NULL, NULL); /* pool, mediation */
+       auth = peer_cfg->get_auth(peer_cfg);
+       auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_class);
        child_cfg = child_cfg_create(CONFIG_NAME,
                                                                 3600, 3000, /* lifetime 1h, rekey 50min */
                                                                 300, /* jitter 5min */
index 7a2e96f..8efa1cb 100644 (file)
@@ -267,6 +267,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                peer_cfg_t *peer_cfg, *mediated_cfg;
                ike_cfg_t *ike;
                host_t *vip = NULL;
+               auth_info_t *auth;
                
                local_id = identification_create_from_encoding(l_type, l_data);
                remote_id = identification_create_from_encoding(r_type, r_data);
@@ -291,10 +292,19 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                {
                        peer_cfg = peer_cfg_create(
                                        name, 2, ike, local_id, remote_id, cert_policy, uniqueid,
-                                       auth_method, eap_type, eap_vendor, keyingtries, 
-                                       rekeytime, reauthtime, jitter, overtime, mobike,
-                                       dpd_delay, vip, pool,
+                                       keyingtries, rekeytime, reauthtime, jitter, overtime,
+                                       mobike, dpd_delay, vip, pool,
                                        mediation, mediated_cfg, peer_id);
+                       auth = peer_cfg->get_auth(peer_cfg);
+                       auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_method);
+                       if (eap_type)
+                       {
+                               auth->add_item(auth, AUTHN_EAP_TYPE, &eap_type);
+                               if (eap_vendor)
+                               {
+                                       auth->add_item(auth, AUTHN_EAP_VENDOR, &eap_vendor);
+                               }
+                       }
                        add_child_cfgs(this, peer_cfg, id);
                        return peer_cfg;
                }
index 374ae09..9df19dc 100644 (file)
@@ -499,8 +499,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
         * uses to serve pool addresses. */
        return peer_cfg_create(msg->add_conn.name,
                msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other,
-               msg->add_conn.me.sendcert, unique, msg->add_conn.auth_method,
-               msg->add_conn.eap_type, msg->add_conn.eap_vendor,
+               msg->add_conn.me.sendcert, unique, 
                msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
                msg->add_conn.mobike, msg->add_conn.dpd.delay,
                vip, msg->add_conn.other.sourceip_size ?
@@ -514,7 +513,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
 static void build_auth_info(private_stroke_config_t *this,
                                                        stroke_msg_t *msg, auth_info_t *auth)
 {
-       identification_t *my_ca = NULL, *other_ca = NULL;
+       identification_t *my_ca = NULL, *other_ca = NULL, *id;
        bool my_ca_same = FALSE;
        bool other_ca_same = FALSE;
        cert_validation_t valid;
@@ -601,6 +600,30 @@ static void build_auth_info(private_stroke_config_t *this,
                }
                my_ca->destroy(my_ca);
        }
+       auth->add_item(auth, AUTHN_AUTH_CLASS, &msg->add_conn.auth_method);
+       if (msg->add_conn.eap_type)
+       {
+               auth->add_item(auth, AUTHN_EAP_TYPE, &msg->add_conn.eap_type);
+               if (msg->add_conn.eap_vendor)
+               {
+                       auth->add_item(auth, AUTHN_EAP_VENDOR, &msg->add_conn.eap_vendor);
+               }
+       }
+       if (msg->add_conn.eap_identity)
+       {
+               if (streq(msg->add_conn.eap_identity, "%identity"))
+               {
+                       id = identification_create_from_encoding(ID_ANY, chunk_empty);
+               }
+               else
+               {
+                       id = identification_create_from_encoding(ID_EAP, chunk_create(
+                                                                               msg->add_conn.eap_identity,
+                                                                               strlen(msg->add_conn.eap_identity)));
+               }
+               auth->add_item(auth, AUTHN_EAP_IDENTITY, id);
+               id->destroy(id);
+       }
 }
 
 /**
index b1cd293..ad93576 100644 (file)
@@ -827,20 +827,27 @@ static void load_secrets(private_stroke_cred_t *this)
                                {
                                        continue;
                                }
-
-                               /* NULL terminate the ID string */
-                               *(id.ptr + id.len) = '\0';
-
-                               peer_id = identification_create_from_string(id.ptr);
-                               if (peer_id == NULL)
+                               
+                               if (type == SHARED_EAP)
                                {
-                                       DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
-                                       goto error;
+                                       /* we use a special EAP identity type for EAP secrets */
+                                       peer_id = identification_create_from_encoding(ID_EAP, id);
                                }
-                               if (peer_id->get_type(peer_id) == ID_ANY)
+                               else
                                {
-                                       peer_id->destroy(peer_id);
-                                       continue;
+                                       /* NULL terminate the ID string */
+                                       *(id.ptr + id.len) = '\0';
+                                       peer_id = identification_create_from_string(id.ptr);
+                                       if (peer_id == NULL)
+                                       {
+                                               DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
+                                               goto error;
+                                       }
+                                       if (peer_id->get_type(peer_id) == ID_ANY)
+                                       {
+                                               peer_id->destroy(peer_id);
+                                               continue;
+                                       }
                                }
                                
                                shared_key->add_owner(shared_key, peer_id);
index 20f05ac..993bdae 100644 (file)
@@ -48,6 +48,23 @@ struct private_stroke_list_t {
 };
 
 /**
+ * get the authentication class of a config
+ */
+auth_class_t get_auth_class(peer_cfg_t *config)
+{
+       auth_class_t *class;
+       auth_info_t *auth_info;
+       
+       auth_info = config->get_auth(config);
+       if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
+       {
+               return *class;
+       }
+       /* fallback to pubkey authentication */
+       return AUTH_CLASS_PUBKEY;
+}
+
+/**
  * log an IKE_SA to out
  */
 static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
@@ -81,12 +98,8 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
                        }
                        if (reauth)
                        {
-                               peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa);
-
-                               fprintf(out, ", %N reauthentication in %V",
-                                               config_auth_method_names,
-                                               peer_cfg->get_auth_method(peer_cfg),
-                                               &reauth);
+                               fprintf(out, ", %N reauthentication in %V", auth_class_names,
+                                               get_auth_class(ike_sa->get_peer_cfg(ike_sa)), &reauth);
                        }
                        if (!rekey && !reauth)
                        {
@@ -272,14 +285,13 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                                        ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
                                        ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
                        fprintf(out, "%12s:  %N authentication",  peer_cfg->get_name(peer_cfg),
-                                       config_auth_method_names, peer_cfg->get_auth_method(peer_cfg));
+                                       auth_class_names, get_auth_class(peer_cfg));
                        dpd = peer_cfg->get_dpd(peer_cfg);
                        if (dpd)
                        {
                                fprintf(out, ", dpddelay=%us", dpd);
                        }
                        fprintf(out, "\n");
-
                        /* TODO: list CAs and groups */
                        children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                        while (children->enumerate(children, &child_cfg))
index 706a5ae..175322a 100644 (file)
@@ -169,10 +169,12 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
        DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
        pop_end(msg, "left", &msg->add_conn.me);
        pop_end(msg, "right", &msg->add_conn.other);
+       pop_string(msg, &msg->add_conn.eap_identity);
        pop_string(msg, &msg->add_conn.algorithms.ike);
        pop_string(msg, &msg->add_conn.algorithms.esp);
        pop_string(msg, &msg->add_conn.ikeme.mediated_by);
        pop_string(msg, &msg->add_conn.ikeme.peerid);
+       DBG2(DBG_CFG, "  eap_identity=%s", msg->add_conn.eap_identity);
        DBG2(DBG_CFG, "  ike=%s", msg->add_conn.algorithms.ike);
        DBG2(DBG_CFG, "  esp=%s", msg->add_conn.algorithms.esp);
        DBG2(DBG_CFG, "  mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
index b66957e..c9d54a5 100644 (file)
@@ -163,6 +163,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
        char *remote_id, *remote_addr, *remote_net;
        child_cfg_t *child_cfg;
        ike_cfg_t *ike_cfg;
+       auth_info_t *auth;
+       auth_class_t class;
        
        /* defaults */
        name = "unnamed";
@@ -186,13 +188,15 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
                ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
                this->peer_cfg = peer_cfg_create(
                                        name, 2, ike_cfg, create_id(local_id), create_id(remote_id),
-                                       CERT_SEND_IF_ASKED, UNIQUE_NO, CONF_AUTH_PSK,
-                                       0, 0,                                                   /* EAP method, vendor */
+                                       CERT_SEND_IF_ASKED, UNIQUE_NO,
                                        1, create_rekey(ike_rekey), 0,  /* keytries, rekey, reauth */
                                        1800, 900,                                              /* jitter, overtime */
                                        TRUE, 60,                                               /* mobike, dpddelay */
                                        NULL, NULL,                                     /* vip, pool */
                                        FALSE, NULL, NULL);                     /* mediation, med by, peer id */
+               auth = this->peer_cfg->get_auth(this->peer_cfg);
+               class = AUTH_CLASS_PSK;
+               auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
                child_cfg = child_cfg_create(name,
                                        create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300,
                                        NULL, TRUE,     MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
index 8e246a2..cdd3245 100644 (file)
@@ -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
@@ -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:
index 54a6b03..bf264d4 100644 (file)
@@ -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
  *
@@ -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_ @} */
index 2652f6e..b2a5026 100644 (file)
@@ -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
index 1958536..8cdf324 100644 (file)
@@ -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;
 }
index 717ee9f..c98771c 100644 (file)
@@ -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
index 58bcb26..563a43a 100644 (file)
@@ -170,6 +170,11 @@ struct private_ike_sa_t {
        identification_t *other_id;
        
        /**
+        * EAP Identity exchange in EAP-Identity method
+        */
+       identification_t *eap_identity;;
+       
+       /**
         * set of extensions the peer supports
         */
        ike_extension_t extensions;
@@ -1541,6 +1546,23 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other)
 }
 
 /**
+ * Implementation of ike_sa_t.get_eap_identity.
+ */
+static identification_t* get_eap_identity(private_ike_sa_t *this)
+{
+       return this->eap_identity;
+}
+
+/**
+ * Implementation of ike_sa_t.set_eap_identity.
+ */
+static void set_eap_identity(private_ike_sa_t *this, identification_t *id)
+{
+       DESTROY_IF(this->eap_identity);
+       this->eap_identity = id;
+}
+
+/**
  * Implementation of ike_sa_t.derive_keys.
  */
 static status_t derive_keys(private_ike_sa_t *this,
@@ -2476,6 +2498,7 @@ static void destroy(private_ike_sa_t *this)
        DESTROY_IF(this->other_host);
        DESTROY_IF(this->my_id);
        DESTROY_IF(this->other_id);
+       DESTROY_IF(this->eap_identity);
        
        DESTROY_IF(this->ike_cfg);
        DESTROY_IF(this->peer_cfg);
@@ -2520,6 +2543,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id;
        this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id;
        this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id;
+       this->public.get_eap_identity = (identification_t* (*)(ike_sa_t*)) get_eap_identity;
+       this->public.set_eap_identity = (void (*)(ike_sa_t*,identification_t*)) set_eap_identity;
        this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
        this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
        this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
@@ -2578,6 +2603,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
        this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
        this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
+       this->eap_identity = NULL;
        this->extensions = 0;
        this->conditions = 0;
        this->selected_proposal = NULL;
index be50fe9..e45d18c 100644 (file)
@@ -330,6 +330,22 @@ struct ike_sa_t {
        void (*set_other_id) (ike_sa_t *this, identification_t *other);
        
        /**
+        * Get the peers EAP identity.
+        *
+        * The EAP identity is exchanged in a EAP-Identity exchange.
+        * 
+        * @return                              identification, NULL if none set
+        */
+       identification_t* (*get_eap_identity) (ike_sa_t *this);
+       
+       /**
+        * Set the peer's EAP identity.
+        * 
+        * @param id                    identification
+        */
+       void (*set_eap_identity) (ike_sa_t *this, identification_t *id);
+       
+       /**
         * Get the config used to setup this IKE_SA.
         * 
         * @return                              ike_config
index 6eeb15e..2954963 100644 (file)
@@ -150,6 +150,44 @@ static bool check_uniqueness(private_ike_auth_t *this)
 }
 
 /**
+ * get the authentication class of a config
+ */
+auth_class_t get_auth_class(peer_cfg_t *config)
+{
+       auth_class_t *class;
+       auth_info_t *auth_info;
+       
+       auth_info = config->get_auth(config);
+       if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
+       {
+               return *class;
+       }
+       /* fallback to pubkey authentication */
+       return AUTH_CLASS_PUBKEY;
+}
+
+/**
+ * get the eap type/vendor
+ */
+static eap_type_t get_eap_type(peer_cfg_t *config, u_int32_t *vendor)
+{
+       auth_info_t *auth_info;
+       u_int *ptr;
+       
+       *vendor = 0;
+       auth_info = config->get_auth(config);
+       if (auth_info->get_item(auth_info, AUTHN_EAP_VENDOR, (void**)&ptr))
+       {
+               *vendor = *ptr;
+       }
+       if (auth_info->get_item(auth_info, AUTHN_EAP_TYPE, (void**)&ptr))
+       {
+               return *ptr;
+       }
+       return EAP_NAK;
+}
+
+/**
  * build the AUTH payload
  */
 static status_t build_auth(private_ike_auth_t *this, message_t *message)
@@ -157,7 +195,6 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
        authenticator_t *auth;
        auth_payload_t *auth_payload;
        peer_cfg_t *config;
-       config_auth_method_t method;
        status_t status;
        
        /* create own authenticator and add auth payload */
@@ -167,13 +204,12 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
                SIG_IKE(UP_FAILED, "unable to authenticate, no peer config found");
                return FAILED;
        }
-       method = config->get_auth_method(config);
        
-       auth = authenticator_create(this->ike_sa, method);
+       auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
        if (auth == NULL)
        {
-               SIG_IKE(UP_FAILED, "configured authentication method %N not supported",
-                       config_auth_method_names, method);
+               SIG_IKE(UP_FAILED, "configured authentication class %N not supported",
+                       auth_class_names, get_auth_class(config));
                return FAILED;
        }
        
@@ -244,8 +280,8 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
        }
        
        auth_method = auth_payload->get_auth_method(auth_payload);
-       auth = authenticator_create_from_auth_payload(this->ike_sa, auth_payload);
-
+       auth = authenticator_create_from_method(this->ike_sa,
+                                                                       auth_payload->get_auth_method(auth_payload));
        if (auth == NULL)
        {
                SIG_IKE(UP_FAILED, "authentication method %N used by '%D' not "
@@ -414,7 +450,7 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
        {
                SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
                         this->ike_sa->get_other_id(this->ike_sa), 
-                        auth_method_names, AUTH_EAP);
+                        auth_class_names, AUTH_CLASS_EAP);
                if (this->initiator)
                {
                        return FAILED;
@@ -514,7 +550,7 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
                default:
                        SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
                                this->ike_sa->get_other_id(this->ike_sa),
-                               auth_method_names, AUTH_EAP);
+                               auth_class_names, AUTH_CLASS_EAP);
                        status = FAILED;
                        break;
        }
@@ -540,7 +576,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message)
        }
        
        config = this->ike_sa->get_peer_cfg(this->ike_sa);
-       if (config->get_auth_method(config) == CONF_AUTH_EAP)
+       if (get_auth_class(config) == AUTH_CLASS_EAP)
        {
                this->eap_auth = eap_authenticator_create(this->ike_sa);
        }
@@ -580,7 +616,6 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
                case NOT_FOUND:
                        /* use EAP if no AUTH payload found */
                        this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE);
-                       this->eap_auth = eap_authenticator_create(this->ike_sa);
                        break;
                default:
                        return NEED_MORE;
@@ -597,7 +632,10 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
                this->ike_sa->set_peer_cfg(this->ike_sa, config);
                config->destroy(config);
        }
-       
+       if (!this->peer_authenticated)
+       {       
+               this->eap_auth = eap_authenticator_create(this->ike_sa);
+       }
        return NEED_MORE;
 }
 
@@ -662,7 +700,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
        }
        
        /* initiate EAP authenitcation */
-       eap_type = config->get_eap_type(config, &eap_vendor);
+       eap_type = 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);
index 920a0f6..825cf07 100644 (file)
@@ -98,6 +98,11 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certifi
 }
 
 /**
+ * from ike_auth.c
+ */
+auth_class_t get_auth_class(peer_cfg_t *config);
+
+/**
  * add certificates to message
  */
 static void build_certs(private_ike_cert_post_t *this, message_t *message)
@@ -105,7 +110,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
        peer_cfg_t *peer_cfg;
        
        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-       if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == CONF_AUTH_PUBKEY)
+       if (peer_cfg && get_auth_class(peer_cfg) == AUTH_CLASS_PUBKEY)
        {
                switch (peer_cfg->get_cert_policy(peer_cfg))
                {
index cbd90bd..d682eeb 100644 (file)
@@ -298,16 +298,28 @@ static char hex2bin(char hex)
 chunk_t chunk_from_hex(chunk_t hex, char *buf)
 {
        int i, len;
+       bool odd = FALSE;
        
-       len = hex.len / 2;
+       len = (hex.len / 2);
+       if (hex.len % 2)
+       {
+               odd = TRUE;
+               len++;
+       }
        if (!buf)
        {
                buf = malloc(len);
        }
-       for (i = 0; i < len; i++)
+       /* buffer is filled from the right */
+       memset(buf, 0, len);
+       hex.ptr += hex.len;
+       for (i = len - 1; i >= 0; i--)
        {
-               buf[i] =  hex2bin(*hex.ptr++) << 4;
-               buf[i] |= hex2bin(*hex.ptr++);
+               buf[i] = hex2bin(*(--hex.ptr));
+               if (i > 0 || !odd)
+               {
+                       buf[i] |= hex2bin(*(--hex.ptr)) << 4;
+               }
        }
        return chunk_create(buf, len);
 }
index 195d01f..8d63f60 100644 (file)
@@ -100,7 +100,8 @@ chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
 /**
  * Convert a hex encoded in a binary chunk.
  *
- * If buf is supplied, it must hold at least (hex.len / 2).
+ * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
+ * bytes. It is filled by the right to give correct values for short inputs.
  *
  * @param hex                  hex encoded input data
  * @param buf                  buffer to write decoded data, NULL to malloc
@@ -164,7 +165,7 @@ void chunk_clear(chunk_t *chunk);
 /**
  * Clone a chunk on heap
  */
-#define chunk_clone(chunk) chunk_create_clone(malloc(chunk.len), chunk)
+#define chunk_clone(chunk) chunk_create_clone((chunk).len ? malloc(chunk.len) : NULL, chunk)
 
 /**
  * Clone a chunk on stack
index e1fb540..4b7ba35 100644 (file)
@@ -915,6 +915,7 @@ static int print(FILE *stream, const struct printf_info *info,
                case ID_FQDN:
                case ID_RFC822_ADDR:
                case ID_DER_ASN1_GN_URI:
+               case ID_EAP:
                        proper = sanitize_chunk(this->encoded);
                        snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
                        chunk_free(&proper);
@@ -1169,6 +1170,7 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
                case ID_PUBKEY_INFO_SHA1:
                case ID_PUBKEY_SHA1:
                case ID_CERT_DER_SHA1:
+               case ID_EAP:
                default:
                        break;
        }
index 29318ce..3b1f55a 100644 (file)
@@ -142,6 +142,11 @@ enum id_type_t {
         * SHA1 hash of the binary DER encoding of a certificate
         */
        ID_CERT_DER_SHA1,
+       
+       /**
+        * Generic EAP identity
+        */
+       ID_EAP,
 };
 
 /**
index fb3587e..b373be9 100644 (file)
@@ -202,6 +202,7 @@ static const token_info_t token_info[] =
     { ARG_MISC, 0, NULL  /* KW_AUTH */                                             },
     { ARG_MISC, 0, NULL  /* KW_AUTHBY */                                           },
     { ARG_MISC, 0, NULL  /* KW_EAP */                                              },
+    { ARG_STR,  offsetof(starter_conn_t, eap_identity), NULL                       },
     { ARG_MISC, 0, NULL  /* KW_MOBIKE */                                           },
     { ARG_MISC, 0, NULL  /* KW_FORCEENCAPS */                                      },
     { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL                },
index 90f729d..8e15845 100644 (file)
@@ -105,6 +105,7 @@ struct starter_conn {
        keyexchange_t   keyexchange;
        u_int32_t       eap_type;
        u_int32_t       eap_vendor;
+       char            *eap_identity;
        lset_t          policy;
        time_t          sa_ike_life_seconds;
        time_t          sa_ipsec_life_seconds;
index 796b6aa..afbf547 100644 (file)
@@ -366,6 +366,14 @@ in the form
 .B eap=7-12345
 ) can be used to specify vendor specific EAP types.
 .TP
+.B eap_identity
+defines the identity the client uses to reply to a EAP Identity request.
+If defined on the EAP server, the defined identity will be used as peer
+identity during EAP authentication. The special value 
+.B %identity
+uses the EAP Identity method to ask the client for a EAP identity. If not
+defined, the IKEv2 identity will be used as EAP identity.
+.TP
 .B esp
 ESP encryption/authentication algorithm to be used
 for the connection, e.g.
index b893cf5..9470c75 100644 (file)
@@ -71,6 +71,7 @@ typedef enum {
     KW_AUTH,
     KW_AUTHBY,
     KW_EAP,
+    KW_EAP_IDENTITY,
     KW_MOBIKE,
     KW_FORCEENCAPS,
     KW_IKELIFETIME,
index 7e414fb..b54da8c 100644 (file)
@@ -50,6 +50,7 @@ keep_alive,        KW_KEEP_ALIVE
 force_keepalive,   KW_FORCE_KEEPALIVE
 virtual_private,   KW_VIRTUAL_PRIVATE
 eap,               KW_EAP
+eap_identity,      KW_EAP_IDENTITY
 mobike,                   KW_MOBIKE
 forceencaps,       KW_FORCEENCAPS
 pkcs11module,      KW_PKCS11MODULE
index 6f2fb40..8fbfc0b 100644 (file)
@@ -227,6 +227,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
        }
        msg.add_conn.eap_type = conn->eap_type;
        msg.add_conn.eap_vendor = conn->eap_vendor;
+       msg.add_conn.eap_identity = push_string(&msg, conn->eap_identity);
        
        if (conn->policy & POLICY_TUNNEL)
        {
index 40447e3..c3ea831 100644 (file)
@@ -203,6 +203,7 @@ struct stroke_msg_t {
                        int auth_method;
                        u_int32_t eap_type;
                        u_int32_t eap_vendor;
+                       char *eap_identity;
                        int mode;
                        int mobike;
                        int force_encap;