diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index de0fb67fe..319be6358 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -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; /** @@ -105,21 +99,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 */ @@ -318,23 +297,6 @@ static unique_policy_t get_unique_policy(private_peer_cfg_t *this) return this->unique; } -/** - * 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. */ @@ -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; diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 7b9b01a63..d88feacda 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -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 @@ -81,23 +80,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. * @@ -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, diff --git a/src/charon/credentials/auth_info.c b/src/charon/credentials/auth_info.c index 5d4a0f24e..42e1ea4c1 100644 --- a/src/charon/credentials/auth_info.c +++ b/src/charon/credentials/auth_info.c @@ -25,6 +25,10 @@ #include 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: diff --git a/src/charon/credentials/auth_info.h b/src/charon/credentials/auth_info.h index 5fe2919f8..52433433a 100644 --- a/src/charon/credentials/auth_info.h +++ b/src/charon/credentials/auth_info.h @@ -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, diff --git a/src/charon/plugins/eap_aka/eap_aka.c b/src/charon/plugins/eap_aka/eap_aka.c index 3bf3ccbc5..bab56bbd4 100644 --- a/src/charon/plugins/eap_aka/eap_aka.c +++ b/src/charon/plugins/eap_aka/eap_aka.c @@ -828,6 +828,19 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code return payload; } +/** + * 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 */ @@ -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; diff --git a/src/charon/plugins/eap_gtc/eap_gtc.c b/src/charon/plugins/eap_gtc/eap_gtc.c index fd39e5ad7..409858dd3 100644 --- a/src/charon/plugins/eap_gtc/eap_gtc.c +++ b/src/charon/plugins/eap_gtc/eap_gtc.c @@ -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; } diff --git a/src/charon/plugins/eap_identity/eap_identity.c b/src/charon/plugins/eap_identity/eap_identity.c index f6835c7f2..e5b4ae8d6 100644 --- a/src/charon/plugins/eap_identity/eap_identity.c +++ b/src/charon/plugins/eap_identity/eap_identity.c @@ -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,38 +36,97 @@ 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. */ @@ -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); } +/** + * Generic constructor + */ +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); + + 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; + + 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 = malloc_thing(private_eap_identity_t); + 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; - 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*,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.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; - /* private data */ - this->peer = 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; } diff --git a/src/charon/plugins/eap_identity/eap_identity.h b/src/charon/plugins/eap_identity/eap_identity.h index 5d297f798..d45f6ca20 100644 --- a/src/charon/plugins/eap_identity/eap_identity.h +++ b/src/charon/plugins/eap_identity/eap_identity.h @@ -38,6 +38,16 @@ struct eap_identity_t { eap_method_t eap_method_interface; }; +/** + * 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. * diff --git a/src/charon/plugins/eap_identity/eap_identity_plugin.c b/src/charon/plugins/eap_identity/eap_identity_plugin.c index 22a884a3e..f322ca387 100644 --- a/src/charon/plugins/eap_identity/eap_identity_plugin.c +++ b/src/charon/plugins/eap_identity/eap_identity_plugin.c @@ -26,6 +26,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); diff --git a/src/charon/plugins/eap_md5/eap_md5.c b/src/charon/plugins/eap_md5/eap_md5.c index 7f41b2e18..533948000 100644 --- a/src/charon/plugins/eap_md5/eap_md5.c +++ b/src/charon/plugins/eap_md5/eap_md5.c @@ -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; } diff --git a/src/charon/plugins/eap_sim/eap_sim.c b/src/charon/plugins/eap_sim/eap_sim.c index 27c2c3a17..11d2e74bc 100644 --- a/src/charon/plugins/eap_sim/eap_sim.c +++ b/src/charon/plugins/eap_sim/eap_sim.c @@ -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) diff --git a/src/charon/plugins/medcli/medcli_config.c b/src/charon/plugins/medcli/medcli_config.c index 610ce2601..05699f7af 100644 --- a/src/charon/plugins/medcli/medcli_config.c +++ b/src/charon/plugins/medcli/medcli_config.c @@ -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 */ diff --git a/src/charon/plugins/medsrv/medsrv_config.c b/src/charon/plugins/medsrv/medsrv_config.c index 1017b9de0..4cea6b7b6 100644 --- a/src/charon/plugins/medsrv/medsrv_config.c +++ b/src/charon/plugins/medsrv/medsrv_config.c @@ -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 */ diff --git a/src/charon/plugins/nm/nm_service.c b/src/charon/plugins/nm/nm_service.c index 8e69c78e7..9f617b860 100644 --- a/src/charon/plugins/nm/nm_service.c +++ b/src/charon/plugins/nm/nm_service.c @@ -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 */ diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c index 7a2e96fe6..8efa1cb2e 100644 --- a/src/charon/plugins/sql/sql_config.c +++ b/src/charon/plugins/sql/sql_config.c @@ -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; } diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c index 374ae096d..9df19dcc5 100644 --- a/src/charon/plugins/stroke/stroke_config.c +++ b/src/charon/plugins/stroke/stroke_config.c @@ -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); + } } /** diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c index b1cd29380..ad93576be 100644 --- a/src/charon/plugins/stroke/stroke_cred.c +++ b/src/charon/plugins/stroke/stroke_cred.c @@ -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); diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c index 20f05aca7..993bdae43 100644 --- a/src/charon/plugins/stroke/stroke_list.c +++ b/src/charon/plugins/stroke/stroke_list.c @@ -47,6 +47,23 @@ struct private_stroke_list_t { time_t uptime; }; +/** + * 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 */ @@ -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)) diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c index 706a5ae4f..175322aa8 100644 --- a/src/charon/plugins/stroke/stroke_socket.c +++ b/src/charon/plugins/stroke/stroke_socket.c @@ -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"); diff --git a/src/charon/plugins/uci/uci_config.c b/src/charon/plugins/uci/uci_config.c index b66957e9b..c9d54a532 100644 --- a/src/charon/plugins/uci/uci_config.c +++ b/src/charon/plugins/uci/uci_config.c @@ -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); diff --git a/src/charon/sa/authenticators/authenticator.c b/src/charon/sa/authenticators/authenticator.c index 8e246a280..cdd3245fe 100644 --- a/src/charon/sa/authenticators/authenticator.c +++ b/src/charon/sa/authenticators/authenticator.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2006-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -33,22 +33,27 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS, "ECDSA-256 signature", "ECDSA-384 signature", "ECDSA-521 signature"); -ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_ECDSA_521, - "EAP"); -ENUM_END(auth_method_names, AUTH_EAP); +ENUM_END(auth_method_names, AUTH_ECDSA_521); + +ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP, + "public key", + "pre-shared key", + "EAP", +); /** * Described in header. */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method) +authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa, + auth_class_t class) { - switch (auth_method) + switch (class) { - case CONF_AUTH_PUBKEY: + case AUTH_CLASS_PUBKEY: return (authenticator_t*)pubkey_authenticator_create(ike_sa); - case CONF_AUTH_PSK: + case AUTH_CLASS_PSK: return (authenticator_t*)psk_authenticator_create(ike_sa); - case CONF_AUTH_EAP: + case AUTH_CLASS_EAP: return (authenticator_t*)eap_authenticator_create(ike_sa); default: return NULL; @@ -58,9 +63,10 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t aut /** * Described in header. */ -authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload) +authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa, + auth_method_t method) { - switch (auth_payload->get_auth_method(auth_payload)) + switch (method) { case AUTH_RSA: case AUTH_ECDSA_256: diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h index 54a6b03ad..bf264d4e4 100644 --- a/src/charon/sa/authenticators/authenticator.h +++ b/src/charon/sa/authenticators/authenticator.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -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 @@ -34,7 +35,7 @@ typedef struct authenticator_t authenticator_t; #include /** - * 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, }; /** @@ -83,12 +78,32 @@ enum auth_method_t { */ extern enum_name_t *auth_method_names; +/** + * Class of authentication to use. This is different to auth_method_t in that + * it does not specify a method, but a class of acceptable methods. The found + * certificate finally dictates wich method is used. + */ +enum auth_class_t { + /** authentication using public keys (RSA, ECDSA) */ + AUTH_CLASS_PUBKEY = 1, + /** authentication using a pre-shared secrets */ + AUTH_CLASS_PSK = 2, + /** authentication using EAP */ + AUTH_CLASS_EAP = 3, +}; + +/** + * enum strings for auth_class_t + */ +extern enum_name_t *auth_class_names; + /** * Authenticator interface implemented by the various authenticators. * * Currently the following two AUTH methods are supported: * - shared key message integrity code * - RSA digital signature + * - EAP using the EAP framework and one of the EAP plugins * - ECDSA is supported using OpenSSL */ struct authenticator_t { @@ -96,15 +111,14 @@ struct authenticator_t { /** * Verify a received authentication payload. * - * @param ike_sa_init binary representation of received ike_sa_init - * @param my_nonce the sent nonce - * @param auth_payload authentication payload to verify - * + * @param ike_sa_init binary representation of received ike_sa_init + * @param my_nonce the sent nonce + * @param auth_payload authentication payload to verify * @return - * - SUCCESS, - * - FAILED if verification failed - * - INVALID_ARG if auth_method does not match - * - NOT_FOUND if credentials not found + * - SUCCESS, + * - FAILED if verification failed + * - INVALID_ARG if auth_method does not match + * - NOT_FOUND if credentials not found */ status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init, chunk_t my_nonce, auth_payload_t *auth_payload); @@ -112,13 +126,12 @@ struct authenticator_t { /** * Build an authentication payload to send to the other peer. * - * @param ike_sa_init binary representation of sent ike_sa_init - * @param other_nonce the received nonce - * @param[out] auth_payload the resulting authentication payload - * + * @param ike_sa_init binary representation of sent ike_sa_init + * @param other_nonce the received nonce + * @param auth_payload the resulting authentication payload * @return - * - SUCCESS, - * - NOT_FOUND if the data for AUTH method could not be found + * - SUCCESS, + * - NOT_FOUND if credentials not found */ status_t (*build) (authenticator_t *this, chunk_t ike_sa_init, chunk_t other_nonce, auth_payload_t **auth_payload); @@ -130,23 +143,23 @@ struct authenticator_t { }; /** - * Creates an authenticator for the specified auth method (as configured). + * Creates an authenticator for the specified auth class (as configured). * * @param ike_sa associated ike_sa - * @param auth_method authentication method to use for build()/verify() - * + * @param class class of authentication to use * @return authenticator_t object */ -authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t auth_method); +authenticator_t *authenticator_create_from_class(ike_sa_t *ike_sa, + auth_class_t class); /** - * Creates an authenticator from the given auth payload. + * Creates an authenticator for method (as received in payload). * * @param ike_sa associated ike_sa - * @param auth_payload auth payload - * + * @param method method as found in payload * @return authenticator_t object */ -authenticator_t *authenticator_create_from_auth_payload(ike_sa_t *ike_sa, auth_payload_t *auth_payload); +authenticator_t *authenticator_create_from_method(ike_sa_t *ike_sa, + auth_method_t method); #endif /* AUTHENTICATOR_H_ @} */ diff --git a/src/charon/sa/authenticators/eap/eap_method.h b/src/charon/sa/authenticators/eap/eap_method.h index 2652f6e6f..b2a50269a 100644 --- a/src/charon/sa/authenticators/eap/eap_method.h +++ b/src/charon/sa/authenticators/eap/eap_method.h @@ -95,6 +95,8 @@ extern enum_name_t *eap_code_names; * authentication. Even if a mutual EAP method is used, the traditional * AUTH payloads are required. Only these include the nonces and messages from * ike_sa_init and therefore prevent man in the middle attacks. + * The EAP method must use an initial EAP identifier value != 0, as a preceding + * EAP-Identity exchange always uses identifier 0. */ struct eap_method_t { @@ -148,7 +150,8 @@ struct eap_method_t { /** * Get the MSK established by this EAP method. * - * Not all EAP methods establish a shared secret. + * Not all EAP methods establish a shared secret. For implementations of + * the EAP-Identity method, get_msk() returns the received identity. * * @param msk chunk receiving internal stored MSK * @return @@ -171,6 +174,8 @@ struct eap_method_t { * Constructors for server and peers are identical, to support both roles * of a EAP method, a plugin needs register two constructors in the * eap_manager_t. + * The passed identites are of type ID_EAP and valid only during the + * constructor invocation. * * @param server ID of the server to use for credential lookup * @param peer ID of the peer to use for credential lookup diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index 195853626..8cdf3249a 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -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... */ @@ -129,6 +144,79 @@ static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init, return SUCCESS; } +/** + * 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 */ @@ -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: @@ -270,6 +360,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 */ @@ -286,6 +397,10 @@ static status_t process_server(private_eap_authenticator_t *this, case NEED_MORE: return NEED_MORE; case SUCCESS: + if (this->do_eap_identity) + { + return process_eap_identity(this, out); + } if (this->method->get_msk(this->method, &this->msk) == SUCCESS) { this->msk = chunk_clone(this->msk); @@ -409,6 +524,9 @@ static void destroy(private_eap_authenticator_t *this) */ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa) { + peer_cfg_t *config; + auth_info_t *auth; + identification_t *id; private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t); /* public functions */ @@ -425,6 +543,25 @@ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa) this->role = EAP_PEER; this->method = NULL; this->msk = chunk_empty; + this->do_eap_identity = FALSE; + this->type = 0; + this->vendor = 0; + config = ike_sa->get_peer_cfg(ike_sa); + if (config) + { + auth = config->get_auth(config); + if (auth->get_item(auth, AUTHN_EAP_IDENTITY, (void**)&id)) + { + if (id->get_type(id) == ID_ANY) + { /* %any as configured EAP identity runs EAP-Identity first */ + this->do_eap_identity = TRUE; + } + else + { + ike_sa->set_eap_identity(ike_sa, id->clone(id)); + } + } + } return &this->public; } diff --git a/src/charon/sa/authenticators/eap_authenticator.h b/src/charon/sa/authenticators/eap_authenticator.h index 717ee9f4c..c98771c76 100644 --- a/src/charon/sa/authenticators/eap_authenticator.h +++ b/src/charon/sa/authenticators/eap_authenticator.h @@ -29,7 +29,7 @@ typedef struct eap_authenticator_t eap_authenticator_t; #include /** - * 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 diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 58bcb260c..563a43a86 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -169,6 +169,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 */ @@ -1540,6 +1545,23 @@ static void set_other_id(private_ike_sa_t *this, identification_t *other) this->other_id = 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. */ @@ -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; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index be50fe935..e45d18cea 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -329,6 +329,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. * diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index 6eeb15ef3..295496367 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -149,6 +149,44 @@ static bool check_uniqueness(private_ike_auth_t *this) return cancel; } +/** + * 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 */ @@ -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); diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c index 920a0f619..825cf0711 100644 --- a/src/charon/sa/tasks/ike_cert_post.c +++ b/src/charon/sa/tasks/ike_cert_post.c @@ -97,6 +97,11 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certifi return payload; } +/** + * from ike_auth.c + */ +auth_class_t get_auth_class(peer_cfg_t *config); + /** * add certificates to 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)) { diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c index cbd90bd6a..d682eeb16 100644 --- a/src/libstrongswan/chunk.c +++ b/src/libstrongswan/chunk.c @@ -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); } diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h index 195d01fcd..8d63f6092 100644 --- a/src/libstrongswan/chunk.h +++ b/src/libstrongswan/chunk.h @@ -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 diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index e1fb54007..4b7ba357b 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -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; } diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index 29318ce47..3b1f55ab2 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -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, }; /** diff --git a/src/starter/args.c b/src/starter/args.c index fb3587eb2..b373be97c 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -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 }, diff --git a/src/starter/confread.h b/src/starter/confread.h index 90f729d64..8e1584526 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -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; diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5 index 796b6aa0e..afbf547ba 100644 --- a/src/starter/ipsec.conf.5 +++ b/src/starter/ipsec.conf.5 @@ -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. diff --git a/src/starter/keywords.h b/src/starter/keywords.h index b893cf52d..9470c75e5 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -71,6 +71,7 @@ typedef enum { KW_AUTH, KW_AUTHBY, KW_EAP, + KW_EAP_IDENTITY, KW_MOBIKE, KW_FORCEENCAPS, KW_IKELIFETIME, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 7e414fb9f..b54da8ca8 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -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 diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 6f2fb40ac..8fbfc0bdb 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -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) { diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 40447e37f..c3ea8316e 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -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;