ported parts of two-sim branch

eap_identity parameter to exchange in eap_identity
	some auth_info/peer_cfg refactorings
	fixed some bugs, introduced new ones
This commit is contained in:
Martin Willi
2008-08-22 10:44:51 +00:00
parent 7c112a12c0
commit 822901061b
40 changed files with 676 additions and 253 deletions
+1 -49
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2007-2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -37,12 +37,6 @@ ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
"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; typedef struct private_peer_cfg_t private_peer_cfg_t;
/** /**
@@ -105,21 +99,6 @@ struct private_peer_cfg_t {
*/ */
unique_policy_t unique; 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 * 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; 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. * 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->other_id->equals(this->other_id, other->other_id) &&
this->cert_policy == other->cert_policy && this->cert_policy == other->cert_policy &&
this->unique == other->unique && 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->keyingtries == other->keyingtries &&
this->use_mobike == other->use_mobike && this->use_mobike == other->use_mobike &&
this->rekey_time == other->rekey_time && 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, 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, identification_t *my_id, identification_t *other_id,
cert_policy_t cert_policy, unique_policy_t unique, 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 keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time, u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t dpd, 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_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_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_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_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_rekey_time = (u_int32_t(*)(peer_cfg_t*))get_rekey_time;
this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time; this->public.get_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->other_id = other_id;
this->cert_policy = cert_policy; this->cert_policy = cert_policy;
this->unique = unique; this->unique = unique;
this->auth_method = auth_method;
this->eap_type = eap_type;
this->eap_vendor = eap_vendor;
this->keyingtries = keyingtries; this->keyingtries = keyingtries;
this->rekey_time = rekey_time; this->rekey_time = rekey_time;
this->reauth_time = reauth_time; this->reauth_time = reauth_time;
-42
View File
@@ -27,7 +27,6 @@
typedef enum cert_policy_t cert_policy_t; typedef enum cert_policy_t cert_policy_t;
typedef enum unique_policy_t unique_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; typedef struct peer_cfg_t peer_cfg_t;
#include <library.h> #include <library.h>
@@ -81,23 +80,6 @@ enum unique_policy_t {
*/ */
extern enum_name_t *unique_policy_names; 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. * Configuration of a peer, specified by IDs.
* *
@@ -221,25 +203,6 @@ struct peer_cfg_t {
*/ */
unique_policy_t (*get_unique_policy) (peer_cfg_t *this); 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. * 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 other_id identification_t for the remote guy
* @param cert_policy should we send a certificate payload? * @param cert_policy should we send a certificate payload?
* @param unique uniqueness of an IKE_SA * @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 keyingtries how many keying tries should be done before giving up
* @param rekey_time timeout before starting rekeying * @param rekey_time timeout before starting rekeying
* @param reauth_time timeout before starting reauthentication * @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, 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, identification_t *my_id, identification_t *other_id,
cert_policy_t cert_policy, unique_policy_t unique, 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 keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time, u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike, u_int32_t dpd, u_int32_t over_time, bool mobike, u_int32_t dpd,
+30 -3
View File
@@ -25,6 +25,10 @@
#include <credentials/certificates/certificate.h> #include <credentials/certificates/certificate.h>
ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP, 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",
"AUTHN_CA_CERT_KEYID", "AUTHN_CA_CERT_KEYID",
"AUTHN_CA_CERT_NAME", "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; item->value = validation;
break; break;
} }
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
case AUTHZ_EAP: case AUTHZ_EAP:
{ {
eap_method_t *method = malloc_thing(eap_method_t); u_int *intval = malloc_thing(u_int);
*method = *(eap_method_t*)value; *intval = *(u_int*)value;
item->value = method; item->value = intval;
break; break;
} }
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID: case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME: case AUTHN_CA_CERT_NAME:
case AUTHZ_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) 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_KEYID:
case AUTHN_CA_CERT: case AUTHN_CA_CERT:
case AUTHN_CA_CERT_NAME: case AUTHN_CA_CERT_NAME:
@@ -444,6 +456,7 @@ static bool equals(private_auth_info_t *this, private_auth_info_t *other)
} }
continue; continue;
} }
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID: case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME: case AUTHN_CA_CERT_NAME:
case AUTHZ_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; 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_PUBKEY:
case AUTHZ_PSK: case AUTHZ_PSK:
case AUTHZ_EAP: case AUTHZ_EAP:
@@ -511,6 +534,9 @@ static void destroy_item_value(item_t *item)
cert->destroy(cert); cert->destroy(cert);
break; break;
} }
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
case AUTHN_IM_HASH_URL: case AUTHN_IM_HASH_URL:
case AUTHN_SUBJECT_HASH_URL: case AUTHN_SUBJECT_HASH_URL:
case AUTHZ_CRL_VALIDATION: case AUTHZ_CRL_VALIDATION:
@@ -520,6 +546,7 @@ static void destroy_item_value(item_t *item)
free(item->value); free(item->value);
break; break;
} }
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID: case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME: case AUTHN_CA_CERT_NAME:
case AUTHZ_CA_CERT_NAME: case AUTHZ_CA_CERT_NAME:
+9 -1
View File
@@ -60,6 +60,14 @@ enum auth_item_t {
* items provided to authentication process * 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* */ /** CA certificate to use for authentication, value is certificate_t* */
AUTHN_CA_CERT, AUTHN_CA_CERT,
/** Keyid of a CA certificate to use, value is identification_t* */ /** Keyid of a CA certificate to use, value is identification_t* */
@@ -83,7 +91,7 @@ enum auth_item_t {
AUTHZ_PUBKEY, AUTHZ_PUBKEY,
/** subject has ben authenticated using preshared secrets, value is shared_key_t* */ /** subject has ben authenticated using preshared secrets, value is shared_key_t* */
AUTHZ_PSK, 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, AUTHZ_EAP,
/** certificate authority, value is certificate_t* */ /** certificate authority, value is certificate_t* */
AUTHZ_CA_CERT, AUTHZ_CA_CERT,
+18 -3
View File
@@ -828,6 +828,19 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code
return payload; 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 * 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); derive_keys(this, this->peer);
/* build payload */ /* 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, AT_RAND, this->rand, AT_AUTN, autn, AT_MAC,
chunk_empty, AT_END); chunk_empty, AT_END);
return NEED_MORE; return NEED_MORE;
@@ -1449,6 +1462,8 @@ static bool is_mutual(private_eap_aka_t *this)
*/ */
static void destroy(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->sha1);
DESTROY_IF(this->signer); DESTROY_IF(this->signer);
DESTROY_IF(this->prf); 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; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
/* private data */ /* private data */
this->server = server; this->server = server->clone(server);
this->peer = peer; this->peer = peer->clone(peer);
this->k_encr = chunk_empty; this->k_encr = chunk_empty;
this->k_auth = chunk_empty; this->k_auth = chunk_empty;
this->msk = chunk_empty; this->msk = chunk_empty;
+10 -3
View File
@@ -253,6 +253,8 @@ static bool is_mutual(private_eap_gtc_t *this)
*/ */
static void destroy(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); 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; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
/* private data */ /* private data */
this->peer = peer; this->peer = peer->clone(peer);
this->server = server; this->server = server->clone(server);
this->identifier = random(); this->identifier = 0;
return this; 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.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; 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; return &this->public;
} }
+116 -21
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2007 Martin Willi * Copyright (C) 2007-2008 Martin Willi
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
* This program is free software; you can redistribute it and/or modify it * 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 * ID of the peer
*/ */
identification_t *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 * Implementation of eap_method_t.process for the peer
*/ */
static status_t process(private_eap_identity_t *this, static status_t process_peer(private_eap_identity_t *this,
eap_payload_t *in, eap_payload_t **out) 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); id = this->peer->get_encoding(this->peer);
len = sizeof(eap_identity_header_t) + id.len;
*(hdr.ptr + 0) = EAP_RESPONSE; hdr = alloca(len);
*(hdr.ptr + 1) = in->get_identifier(in); hdr->code = EAP_RESPONSE;
*(u_int16_t*)(hdr.ptr + 2) = htons(hdr.len + id.len); hdr->identifier = in->get_identifier(in);
*(hdr.ptr + 4) = EAP_IDENTITY; 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; return SUCCESS;
} }
/** /**
* Implementation of eap_method_t.initiate for the peer * 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 */ /* peer never initiates */
return FAILED; 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. * 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) static status_t get_msk(private_eap_identity_t *this, chunk_t *msk)
{ {
if (this->identity.ptr)
{
*msk = this->identity;
return SUCCESS;
}
return FAILED; return FAILED;
} }
@@ -98,27 +162,58 @@ static bool is_mutual(private_eap_identity_t *this)
*/ */
static void destroy(private_eap_identity_t *this) static void destroy(private_eap_identity_t *this)
{ {
this->peer->destroy(this->peer);
free(this->identity.ptr);
free(this); 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. * Described in header.
*/ */
eap_identity_t *eap_identity_create_peer(identification_t *server, eap_identity_t *eap_identity_create_peer(identification_t *server,
identification_t *peer) 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 */ /* public functions */
this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; 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; this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
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 */ return &this->public;
this->peer = peer; }
/*
* 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; return &this->public;
} }
@@ -38,6 +38,16 @@ struct eap_identity_t {
eap_method_t eap_method_interface; 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. * Creates the EAP method EAP Identity, acting as peer.
* *
@@ -26,6 +26,8 @@
*/ */
static void destroy(eap_identity_plugin_t *this) 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, charon->eap->remove_method(charon->eap,
(eap_constructor_t)eap_identity_create_peer); (eap_constructor_t)eap_identity_create_peer);
free(this); free(this);
@@ -40,6 +42,8 @@ plugin_t *plugin_create()
this->plugin.destroy = (void(*)(plugin_t*))destroy; 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, charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER,
(eap_constructor_t)eap_identity_create_peer); (eap_constructor_t)eap_identity_create_peer);
+10 -3
View File
@@ -242,6 +242,8 @@ static bool is_mutual(private_eap_md5_t *this)
*/ */
static void destroy(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); chunk_free(&this->challenge);
free(this); 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; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
/* private data */ /* private data */
this->peer = peer; this->peer = peer->clone(peer);
this->server = server; this->server = server->clone(server);
this->challenge = chunk_empty; this->challenge = chunk_empty;
this->identifier = random(); this->identifier = 0;
return this; 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.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; 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; return &this->public;
} }
+6 -2
View File
@@ -1016,6 +1016,7 @@ static bool is_mutual(private_eap_sim_t *this)
*/ */
static void destroy(private_eap_sim_t *this) static void destroy(private_eap_sim_t *this)
{ {
this->peer->destroy(this->peer);
dlclose(this->handle); dlclose(this->handle);
DESTROY_IF(this->hasher); DESTROY_IF(this->hasher);
DESTROY_IF(this->prf); 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->get_triplet = NULL;
this->nonce = chunk_empty; this->nonce = chunk_empty;
this->sreses = chunk_empty; this->sreses = chunk_empty;
this->peer = peer; this->peer = peer->clone(peer);
this->tries = MAX_TRIES; this->tries = MAX_TRIES;
this->version.ptr = version; this->version.ptr = version;
this->version.len = sizeof(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->k_encr = chunk_empty;
this->msk = chunk_empty; this->msk = chunk_empty;
this->emsk = 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); this->handle = dlopen(SIM_READER_LIB, RTLD_LAZY);
if (this->handle == NULL) if (this->handle == NULL)
+3 -6
View 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, "mediation", 2, ike_cfg,
identification_create_from_encoding(ID_KEY_ID, me), identification_create_from_encoding(ID_KEY_ID, me),
identification_create_from_encoding(ID_KEY_ID, other), identification_create_from_encoding(ID_KEY_ID, other),
CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, CERT_NEVER_SEND, UNIQUE_REPLACE,
0, 0, /* EAP method, vendor */
1, this->rekey*60, 0, /* keytries, rekey, reauth */ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, this->dpd, /* mobike, dpddelay */ 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), name, 2, this->ike->get_ref(this->ike),
identification_create_from_encoding(ID_KEY_ID, me), identification_create_from_encoding(ID_KEY_ID, me),
identification_create_from_encoding(ID_KEY_ID, other), identification_create_from_encoding(ID_KEY_ID, other),
CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, CERT_NEVER_SEND, UNIQUE_REPLACE,
0, 0, /* EAP method, vendor */
1, this->rekey*60, 0, /* keytries, rekey, reauth */ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, this->dpd, /* mobike, dpddelay */ 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), name, 2, this->ike->get_ref(this->ike),
identification_create_from_encoding(ID_KEY_ID, me), identification_create_from_encoding(ID_KEY_ID, me),
identification_create_from_encoding(ID_KEY_ID, other), identification_create_from_encoding(ID_KEY_ID, other),
CERT_NEVER_SEND, UNIQUE_REPLACE, AUTH_RSA, CERT_NEVER_SEND, UNIQUE_REPLACE,
0, 0, /* EAP method, vendor */
1, this->rekey*60, 0, /* keytries, rekey, reauth */ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, this->dpd, /* mobike, dpddelay */ TRUE, this->dpd, /* mobike, dpddelay */
+1 -2
View File
@@ -99,8 +99,7 @@ static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this,
peer_cfg = peer_cfg_create( peer_cfg = peer_cfg_create(
name, 2, this->ike->get_ref(this->ike), name, 2, this->ike->get_ref(this->ike),
me->clone(me), other->clone(other), me->clone(me), other->clone(other),
CERT_NEVER_SEND, UNIQUE_REPLACE, CONF_AUTH_PUBKEY, CERT_NEVER_SEND, UNIQUE_REPLACE,
0, 0, /* EAP method, vendor */
1, this->rekey*60, 0, /* keytries, rekey, reauth */ 1, this->rekey*60, 0, /* keytries, rekey, reauth */
this->rekey*5, this->rekey*3, /* jitter, overtime */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, this->dpd, /* mobike, dpddelay */ TRUE, this->dpd, /* mobike, dpddelay */
+7 -5
View File
@@ -171,7 +171,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg_t *child_cfg; child_cfg_t *child_cfg;
traffic_selector_t *ts; traffic_selector_t *ts;
ike_sa_t *ike_sa; 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 * Read parameters
@@ -212,11 +213,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
{ {
if (streq(str, "psk")) if (streq(str, "psk"))
{ {
method = CONF_AUTH_PSK; auth_class = AUTH_CLASS_PSK;
} }
else if (streq(str, "pubkey")) 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)); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user, peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user,
identification_create_from_encoding(ID_ANY, chunk_empty), identification_create_from_encoding(ID_ANY, chunk_empty),
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, method, CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
0, 0, 1, /* EAP method, vendor, keyingtries */
18000, 0, /* rekey 5h, reauth none */ 18000, 0, /* rekey 5h, reauth none */
600, 600, /* jitter, over 10min */ 600, 600, /* jitter, over 10min */
TRUE, 0, /* mobike, DPD */ TRUE, 0, /* mobike, DPD */
virtual ? host_create_from_string("0.0.0.0", 0) : NULL, virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
NULL, FALSE, NULL, NULL); /* pool, mediation */ 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, child_cfg = child_cfg_create(CONFIG_NAME,
3600, 3000, /* lifetime 1h, rekey 50min */ 3600, 3000, /* lifetime 1h, rekey 50min */
300, /* jitter 5min */ 300, /* jitter 5min */
+13 -3
View 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; peer_cfg_t *peer_cfg, *mediated_cfg;
ike_cfg_t *ike; ike_cfg_t *ike;
host_t *vip = NULL; host_t *vip = NULL;
auth_info_t *auth;
local_id = identification_create_from_encoding(l_type, l_data); local_id = identification_create_from_encoding(l_type, l_data);
remote_id = identification_create_from_encoding(r_type, r_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( peer_cfg = peer_cfg_create(
name, 2, ike, local_id, remote_id, cert_policy, uniqueid, name, 2, ike, local_id, remote_id, cert_policy, uniqueid,
auth_method, eap_type, eap_vendor, keyingtries, keyingtries, rekeytime, reauthtime, jitter, overtime,
rekeytime, reauthtime, jitter, overtime, mobike, mobike, dpd_delay, vip, pool,
dpd_delay, vip, pool,
mediation, mediated_cfg, peer_id); 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); add_child_cfgs(this, peer_cfg, id);
return peer_cfg; return peer_cfg;
} }
+26 -3
View File
@@ -499,8 +499,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
* uses to serve pool addresses. */ * uses to serve pool addresses. */
return peer_cfg_create(msg->add_conn.name, return peer_cfg_create(msg->add_conn.name,
msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other, msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other,
msg->add_conn.me.sendcert, unique, msg->add_conn.auth_method, msg->add_conn.me.sendcert, unique,
msg->add_conn.eap_type, msg->add_conn.eap_vendor,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over, msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.dpd.delay, msg->add_conn.mobike, msg->add_conn.dpd.delay,
vip, msg->add_conn.other.sourceip_size ? 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, static void build_auth_info(private_stroke_config_t *this,
stroke_msg_t *msg, auth_info_t *auth) 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 my_ca_same = FALSE;
bool other_ca_same = FALSE; bool other_ca_same = FALSE;
cert_validation_t valid; cert_validation_t valid;
@@ -601,6 +600,30 @@ static void build_auth_info(private_stroke_config_t *this,
} }
my_ca->destroy(my_ca); 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);
}
} }
/** /**
+17 -10
View File
@@ -828,19 +828,26 @@ static void load_secrets(private_stroke_cred_t *this)
continue; continue;
} }
/* NULL terminate the ID string */ if (type == SHARED_EAP)
*(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); /* we use a special EAP identity type for EAP secrets */
goto error; peer_id = identification_create_from_encoding(ID_EAP, id);
} }
if (peer_id->get_type(peer_id) == ID_ANY) else
{ {
peer_id->destroy(peer_id); /* NULL terminate the ID string */
continue; *(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); shared_key->add_owner(shared_key, peer_id);
+20 -8
View File
@@ -47,6 +47,23 @@ struct private_stroke_list_t {
time_t uptime; 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 * 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) if (reauth)
{ {
peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa); fprintf(out, ", %N reauthentication in %V", auth_class_names,
get_auth_class(ike_sa->get_peer_cfg(ike_sa)), &reauth);
fprintf(out, ", %N reauthentication in %V",
config_auth_method_names,
peer_cfg->get_auth_method(peer_cfg),
&reauth);
} }
if (!rekey && !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_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)); 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), 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); dpd = peer_cfg->get_dpd(peer_cfg);
if (dpd) if (dpd)
{ {
fprintf(out, ", dpddelay=%us", dpd); fprintf(out, ", dpddelay=%us", dpd);
} }
fprintf(out, "\n"); fprintf(out, "\n");
/* TODO: list CAs and groups */ /* TODO: list CAs and groups */
children = peer_cfg->create_child_cfg_enumerator(peer_cfg); children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg)) while (children->enumerate(children, &child_cfg))
@@ -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); DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
pop_end(msg, "left", &msg->add_conn.me); pop_end(msg, "left", &msg->add_conn.me);
pop_end(msg, "right", &msg->add_conn.other); 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.ike);
pop_string(msg, &msg->add_conn.algorithms.esp); pop_string(msg, &msg->add_conn.algorithms.esp);
pop_string(msg, &msg->add_conn.ikeme.mediated_by); pop_string(msg, &msg->add_conn.ikeme.mediated_by);
pop_string(msg, &msg->add_conn.ikeme.peerid); 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, " ike=%s", msg->add_conn.algorithms.ike);
DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp); DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no"); DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
+6 -2
View 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; char *remote_id, *remote_addr, *remote_net;
child_cfg_t *child_cfg; child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg; ike_cfg_t *ike_cfg;
auth_info_t *auth;
auth_class_t class;
/* defaults */ /* defaults */
name = "unnamed"; 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)); ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create( this->peer_cfg = peer_cfg_create(
name, 2, ike_cfg, create_id(local_id), create_id(remote_id), name, 2, ike_cfg, create_id(local_id), create_id(remote_id),
CERT_SEND_IF_ASKED, UNIQUE_NO, CONF_AUTH_PSK, CERT_SEND_IF_ASKED, UNIQUE_NO,
0, 0, /* EAP method, vendor */
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */ 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
1800, 900, /* jitter, overtime */ 1800, 900, /* jitter, overtime */
TRUE, 60, /* mobike, dpddelay */ TRUE, 60, /* mobike, dpddelay */
NULL, NULL, /* vip, pool */ NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */ 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, child_cfg = child_cfg_create(name,
create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300, create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300,
NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE); NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
+17 -11
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2006 Martin Willi * Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
* This program is free software; you can redistribute it and/or modify it * 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-256 signature",
"ECDSA-384 signature", "ECDSA-384 signature",
"ECDSA-521 signature"); "ECDSA-521 signature");
ENUM_NEXT(auth_method_names, AUTH_EAP, AUTH_EAP, AUTH_ECDSA_521, ENUM_END(auth_method_names, AUTH_ECDSA_521);
"EAP");
ENUM_END(auth_method_names, AUTH_EAP); ENUM(auth_class_names, AUTH_CLASS_PUBKEY, AUTH_CLASS_EAP,
"public key",
"pre-shared key",
"EAP",
);
/** /**
* Described in header. * 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); return (authenticator_t*)pubkey_authenticator_create(ike_sa);
case CONF_AUTH_PSK: case AUTH_CLASS_PSK:
return (authenticator_t*)psk_authenticator_create(ike_sa); return (authenticator_t*)psk_authenticator_create(ike_sa);
case CONF_AUTH_EAP: case AUTH_CLASS_EAP:
return (authenticator_t*)eap_authenticator_create(ike_sa); return (authenticator_t*)eap_authenticator_create(ike_sa);
default: default:
return NULL; return NULL;
@@ -58,9 +63,10 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa, config_auth_method_t aut
/** /**
* Described in header. * 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_RSA:
case AUTH_ECDSA_256: case AUTH_ECDSA_256:
+43 -30
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -26,6 +26,7 @@
#define AUTHENTICATOR_H_ #define AUTHENTICATOR_H_
typedef enum auth_method_t auth_method_t; typedef enum auth_method_t auth_method_t;
typedef enum auth_class_t auth_class_t;
typedef struct authenticator_t authenticator_t; typedef struct authenticator_t authenticator_t;
#include <library.h> #include <library.h>
@@ -34,7 +35,7 @@ typedef struct authenticator_t authenticator_t;
#include <encoding/payloads/auth_payload.h> #include <encoding/payloads/auth_payload.h>
/** /**
* Method to use for authentication. * Method to use for authentication, as defined in IKEv2.
*/ */
enum auth_method_t { 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 * ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754
*/ */
AUTH_ECDSA_521 = 11, 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; 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. * Authenticator interface implemented by the various authenticators.
* *
* Currently the following two AUTH methods are supported: * Currently the following two AUTH methods are supported:
* - shared key message integrity code * - shared key message integrity code
* - RSA digital signature * - RSA digital signature
* - EAP using the EAP framework and one of the EAP plugins
* - ECDSA is supported using OpenSSL * - ECDSA is supported using OpenSSL
*/ */
struct authenticator_t { struct authenticator_t {
@@ -96,15 +111,14 @@ struct authenticator_t {
/** /**
* Verify a received authentication payload. * Verify a received authentication payload.
* *
* @param ike_sa_init binary representation of received ike_sa_init * @param ike_sa_init binary representation of received ike_sa_init
* @param my_nonce the sent nonce * @param my_nonce the sent nonce
* @param auth_payload authentication payload to verify * @param auth_payload authentication payload to verify
*
* @return * @return
* - SUCCESS, * - SUCCESS,
* - FAILED if verification failed * - FAILED if verification failed
* - INVALID_ARG if auth_method does not match * - INVALID_ARG if auth_method does not match
* - NOT_FOUND if credentials not found * - NOT_FOUND if credentials not found
*/ */
status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init, status_t (*verify) (authenticator_t *this, chunk_t ike_sa_init,
chunk_t my_nonce, auth_payload_t *auth_payload); 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. * Build an authentication payload to send to the other peer.
* *
* @param ike_sa_init binary representation of sent ike_sa_init * @param ike_sa_init binary representation of sent ike_sa_init
* @param other_nonce the received nonce * @param other_nonce the received nonce
* @param[out] auth_payload the resulting authentication payload * @param auth_payload the resulting authentication payload
*
* @return * @return
* - SUCCESS, * - SUCCESS,
* - NOT_FOUND if the data for AUTH method could not be found * - NOT_FOUND if credentials not found
*/ */
status_t (*build) (authenticator_t *this, chunk_t ike_sa_init, status_t (*build) (authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload); 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 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 * @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 ike_sa associated ike_sa
* @param auth_payload auth payload * @param method method as found in payload
*
* @return authenticator_t object * @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_ @} */ #endif /* AUTHENTICATOR_H_ @} */
@@ -95,6 +95,8 @@ extern enum_name_t *eap_code_names;
* authentication. Even if a mutual EAP method is used, the traditional * authentication. Even if a mutual EAP method is used, the traditional
* AUTH payloads are required. Only these include the nonces and messages from * AUTH payloads are required. Only these include the nonces and messages from
* ike_sa_init and therefore prevent man in the middle attacks. * 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 { struct eap_method_t {
@@ -148,7 +150,8 @@ struct eap_method_t {
/** /**
* Get the MSK established by this EAP method. * 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 * @param msk chunk receiving internal stored MSK
* @return * @return
@@ -171,6 +174,8 @@ struct eap_method_t {
* Constructors for server and peers are identical, to support both roles * Constructors for server and peers are identical, to support both roles
* of a EAP method, a plugin needs register two constructors in the * of a EAP method, a plugin needs register two constructors in the
* eap_manager_t. * 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 server ID of the server to use for credential lookup
* @param peer ID of the peer to use for credential lookup * @param peer ID of the peer to use for credential lookup
+159 -22
View File
@@ -54,6 +54,21 @@ struct private_eap_authenticator_t {
* MSK used to build and verify auth payload * MSK used to build and verify auth payload
*/ */
chunk_t msk; 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); chunk_free(&auth_data);
DBG1(DBG_IKE, "authentication of '%D' with %N successful", 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; 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); identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N", 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) if (this->msk.len)
{ /* use MSK if EAP method established one... */ { /* 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; 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 * 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 */ /* if initiate() is called, role is always server */
this->role = EAP_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) if (type == 0)
{ {
DBG1(DBG_IKE, DBG1(DBG_IKE,
@@ -148,20 +244,23 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type,
if (vendor) if (vendor)
{ {
DBG1(DBG_IKE, "requesting vendor specific EAP authentication %d-%d", DBG1(DBG_IKE, "requesting vendor specific EAP method %d-%d",
type, vendor); type, vendor);
} }
else 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->method = load_method(this, type, vendor, this->role);
this->role, this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa));
if (this->method == NULL) 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", DBG1(DBG_IKE, "configured EAP server method not supported, sending %N",
eap_code_names, EAP_FAILURE); eap_code_names, EAP_FAILURE);
*out = eap_payload_create_code(EAP_FAILURE, 0); *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; eap_method_t *method;
method = charon->eap->create_instance(charon->eap, type, 0, EAP_PEER, method = load_method(this, type, 0, EAP_PEER);
this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa));
if (method == NULL || method->process(method, in, out) != SUCCESS) if (method == NULL || method->process(method, in, out) != SUCCESS)
{ {
DBG1(DBG_IKE, "EAP server requested %N, but unable to process", 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); DESTROY_IF(method);
return FAILED; return FAILED;
} }
DBG1(DBG_IKE, "EAP server requested %N", eap_type_names, type);
DBG1(DBG_IKE, "EAP server requested %N, sending IKE identity",
eap_type_names, type);
method->destroy(method); method->destroy(method);
return NEED_MORE; 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", DBG1(DBG_IKE, "EAP server requested %N authentication",
eap_type_names, type); eap_type_names, type);
} }
this->method = charon->eap->create_instance(charon->eap, this->method = load_method(this, type, vendor, EAP_PEER);
type, vendor, EAP_PEER,
this->ike_sa->get_other_id(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa));
if (this->method == NULL) if (this->method == NULL)
{ {
DBG1(DBG_IKE, "EAP server requested unsupported " DBG1(DBG_IKE, "EAP server requested unsupported "
@@ -251,7 +341,7 @@ static status_t process_peer(private_eap_authenticator_t *this,
} }
else 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; return SUCCESS;
case FAILED: 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 * Processing method for a server
*/ */
@@ -286,6 +397,10 @@ static status_t process_server(private_eap_authenticator_t *this,
case NEED_MORE: case NEED_MORE:
return NEED_MORE; return NEED_MORE;
case SUCCESS: case SUCCESS:
if (this->do_eap_identity)
{
return process_eap_identity(this, out);
}
if (this->method->get_msk(this->method, &this->msk) == SUCCESS) if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
{ {
this->msk = chunk_clone(this->msk); 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) 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); private_eap_authenticator_t *this = malloc_thing(private_eap_authenticator_t);
/* public functions */ /* public functions */
@@ -425,6 +543,25 @@ eap_authenticator_t *eap_authenticator_create(ike_sa_t *ike_sa)
this->role = EAP_PEER; this->role = EAP_PEER;
this->method = NULL; this->method = NULL;
this->msk = chunk_empty; 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; return &this->public;
} }
@@ -29,7 +29,7 @@ typedef struct eap_authenticator_t eap_authenticator_t;
#include <encoding/payloads/eap_payload.h> #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 * Authentication using EAP involves the most complex authenticator. It stays
* alive over multiple ike_auth transactions and handles multiple EAP * 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 * @param ike_sa associated ike_sa
* @return eap_authenticator_t object * @return eap_authenticator_t object
+26
View File
@@ -169,6 +169,11 @@ struct private_ike_sa_t {
*/ */
identification_t *other_id; identification_t *other_id;
/**
* EAP Identity exchange in EAP-Identity method
*/
identification_t *eap_identity;;
/** /**
* set of extensions the peer supports * 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; 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. * 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->other_host);
DESTROY_IF(this->my_id); DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id); DESTROY_IF(this->other_id);
DESTROY_IF(this->eap_identity);
DESTROY_IF(this->ike_cfg); DESTROY_IF(this->ike_cfg);
DESTROY_IF(this->peer_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.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.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.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.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.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; 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->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->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_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->extensions = 0;
this->conditions = 0; this->conditions = 0;
this->selected_proposal = NULL; this->selected_proposal = NULL;
+16
View File
@@ -329,6 +329,22 @@ struct ike_sa_t {
*/ */
void (*set_other_id) (ike_sa_t *this, identification_t *other); 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. * Get the config used to setup this IKE_SA.
* *
+51 -13
View File
@@ -149,6 +149,44 @@ static bool check_uniqueness(private_ike_auth_t *this)
return cancel; 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 * build the AUTH payload
*/ */
@@ -157,7 +195,6 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
authenticator_t *auth; authenticator_t *auth;
auth_payload_t *auth_payload; auth_payload_t *auth_payload;
peer_cfg_t *config; peer_cfg_t *config;
config_auth_method_t method;
status_t status; status_t status;
/* create own authenticator and add auth payload */ /* 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"); SIG_IKE(UP_FAILED, "unable to authenticate, no peer config found");
return FAILED; 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) if (auth == NULL)
{ {
SIG_IKE(UP_FAILED, "configured authentication method %N not supported", SIG_IKE(UP_FAILED, "configured authentication class %N not supported",
config_auth_method_names, method); auth_class_names, get_auth_class(config));
return FAILED; 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_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) if (auth == NULL)
{ {
SIG_IKE(UP_FAILED, "authentication method %N used by '%D' not " 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", SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa),
auth_method_names, AUTH_EAP); auth_class_names, AUTH_CLASS_EAP);
if (this->initiator) if (this->initiator)
{ {
return FAILED; return FAILED;
@@ -514,7 +550,7 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
default: default:
SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed", SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa), this->ike_sa->get_other_id(this->ike_sa),
auth_method_names, AUTH_EAP); auth_class_names, AUTH_CLASS_EAP);
status = FAILED; status = FAILED;
break; 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); 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); 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: case NOT_FOUND:
/* use EAP if no AUTH payload found */ /* use EAP if no AUTH payload found */
this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE); this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE);
this->eap_auth = eap_authenticator_create(this->ike_sa);
break; break;
default: default:
return NEED_MORE; 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); this->ike_sa->set_peer_cfg(this->ike_sa, config);
config->destroy(config); config->destroy(config);
} }
if (!this->peer_authenticated)
{
this->eap_auth = eap_authenticator_create(this->ike_sa);
}
return NEED_MORE; return NEED_MORE;
} }
@@ -662,7 +700,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
} }
/* initiate EAP authenitcation */ /* 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, status = this->eap_auth->initiate(this->eap_auth, eap_type,
eap_vendor, &eap_payload); eap_vendor, &eap_payload);
message->add_payload(message, (payload_t*)eap_payload); message->add_payload(message, (payload_t*)eap_payload);
+6 -1
View File
@@ -97,6 +97,11 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certifi
return payload; return payload;
} }
/**
* from ike_auth.c
*/
auth_class_t get_auth_class(peer_cfg_t *config);
/** /**
* add certificates to message * 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_t *peer_cfg;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); 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)) switch (peer_cfg->get_cert_policy(peer_cfg))
{ {
+16 -4
View File
@@ -298,16 +298,28 @@ static char hex2bin(char hex)
chunk_t chunk_from_hex(chunk_t hex, char *buf) chunk_t chunk_from_hex(chunk_t hex, char *buf)
{ {
int i, len; int i, len;
bool odd = FALSE;
len = hex.len / 2; len = (hex.len / 2);
if (hex.len % 2)
{
odd = TRUE;
len++;
}
if (!buf) if (!buf)
{ {
buf = malloc(len); 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); return chunk_create(buf, len);
} }
+3 -2
View 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. * 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 hex hex encoded input data
* @param buf buffer to write decoded data, NULL to malloc * @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 * 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 * Clone a chunk on stack
+2
View File
@@ -915,6 +915,7 @@ static int print(FILE *stream, const struct printf_info *info,
case ID_FQDN: case ID_FQDN:
case ID_RFC822_ADDR: case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI: case ID_DER_ASN1_GN_URI:
case ID_EAP:
proper = sanitize_chunk(this->encoded); proper = sanitize_chunk(this->encoded);
snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr); snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
chunk_free(&proper); 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_INFO_SHA1:
case ID_PUBKEY_SHA1: case ID_PUBKEY_SHA1:
case ID_CERT_DER_SHA1: case ID_CERT_DER_SHA1:
case ID_EAP:
default: default:
break; break;
} }
+5
View File
@@ -142,6 +142,11 @@ enum id_type_t {
* SHA1 hash of the binary DER encoding of a certificate * SHA1 hash of the binary DER encoding of a certificate
*/ */
ID_CERT_DER_SHA1, ID_CERT_DER_SHA1,
/**
* Generic EAP identity
*/
ID_EAP,
}; };
/** /**
+1
View File
@@ -202,6 +202,7 @@ static const token_info_t token_info[] =
{ ARG_MISC, 0, NULL /* KW_AUTH */ }, { ARG_MISC, 0, NULL /* KW_AUTH */ },
{ ARG_MISC, 0, NULL /* KW_AUTHBY */ }, { ARG_MISC, 0, NULL /* KW_AUTHBY */ },
{ ARG_MISC, 0, NULL /* KW_EAP */ }, { 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_MOBIKE */ },
{ ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ }, { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ },
{ ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL },
+1
View File
@@ -105,6 +105,7 @@ struct starter_conn {
keyexchange_t keyexchange; keyexchange_t keyexchange;
u_int32_t eap_type; u_int32_t eap_type;
u_int32_t eap_vendor; u_int32_t eap_vendor;
char *eap_identity;
lset_t policy; lset_t policy;
time_t sa_ike_life_seconds; time_t sa_ike_life_seconds;
time_t sa_ipsec_life_seconds; time_t sa_ipsec_life_seconds;
+8
View File
@@ -366,6 +366,14 @@ in the form
.B eap=7-12345 .B eap=7-12345
) can be used to specify vendor specific EAP types. ) can be used to specify vendor specific EAP types.
.TP .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 .B esp
ESP encryption/authentication algorithm to be used ESP encryption/authentication algorithm to be used
for the connection, e.g. for the connection, e.g.
+1
View File
@@ -71,6 +71,7 @@ typedef enum {
KW_AUTH, KW_AUTH,
KW_AUTHBY, KW_AUTHBY,
KW_EAP, KW_EAP,
KW_EAP_IDENTITY,
KW_MOBIKE, KW_MOBIKE,
KW_FORCEENCAPS, KW_FORCEENCAPS,
KW_IKELIFETIME, KW_IKELIFETIME,
+1
View File
@@ -50,6 +50,7 @@ keep_alive, KW_KEEP_ALIVE
force_keepalive, KW_FORCE_KEEPALIVE force_keepalive, KW_FORCE_KEEPALIVE
virtual_private, KW_VIRTUAL_PRIVATE virtual_private, KW_VIRTUAL_PRIVATE
eap, KW_EAP eap, KW_EAP
eap_identity, KW_EAP_IDENTITY
mobike, KW_MOBIKE mobike, KW_MOBIKE
forceencaps, KW_FORCEENCAPS forceencaps, KW_FORCEENCAPS
pkcs11module, KW_PKCS11MODULE pkcs11module, KW_PKCS11MODULE
+1
View 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_type = conn->eap_type;
msg.add_conn.eap_vendor = conn->eap_vendor; msg.add_conn.eap_vendor = conn->eap_vendor;
msg.add_conn.eap_identity = push_string(&msg, conn->eap_identity);
if (conn->policy & POLICY_TUNNEL) if (conn->policy & POLICY_TUNNEL)
{ {
+1
View File
@@ -203,6 +203,7 @@ struct stroke_msg_t {
int auth_method; int auth_method;
u_int32_t eap_type; u_int32_t eap_type;
u_int32_t eap_vendor; u_int32_t eap_vendor;
char *eap_identity;
int mode; int mode;
int mobike; int mobike;
int force_encap; int force_encap;