Merge branch 'ikev1-clean' into ikev1-master
Conflicts: configure.in man/ipsec.conf.5.in src/libcharon/daemon.c src/libcharon/plugins/eap_ttls/eap_ttls_peer.c src/libcharon/plugins/eap_radius/eap_radius_accounting.c src/libcharon/plugins/eap_radius/eap_radius_forward.c src/libcharon/plugins/farp/farp_listener.c src/libcharon/sa/ike_sa.c src/libcharon/sa/keymat.c src/libcharon/sa/task_manager.c src/libcharon/sa/trap_manager.c src/libstrongswan/plugins/x509/x509_cert.c src/libstrongswan/utils.h Applied lost changes of moved files keymat.c and task_manager.c. Updated listener_t.message hook signature in new plugins.
This commit is contained in:
@@ -273,11 +273,11 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
hostname, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
|
||||
peer_cfg = peer_cfg_create("android", 2, ike_cfg, CERT_SEND_IF_ASKED,
|
||||
peer_cfg = peer_cfg_create("android", IKEV2, ike_cfg, CERT_SEND_IF_ASKED,
|
||||
UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, 0, /* mobike, DPD */
|
||||
TRUE, FALSE, 0, /* mobike, aggressive, DPD */
|
||||
host_create_from_string("0.0.0.0", 0) /* virt */,
|
||||
NULL, FALSE, NULL, NULL); /* pool, mediation */
|
||||
|
||||
@@ -300,12 +300,17 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
0, "255.255.255.255", 65535);
|
||||
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
|
||||
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
|
||||
/* get an additional reference because initiate consumes one */
|
||||
child_cfg->get_ref(child_cfg);
|
||||
|
||||
/* get us an IKE_SA */
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
|
||||
peer_cfg);
|
||||
if (!ike_sa)
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
send_status(this, VPN_ERROR_CONNECTION_FAILED);
|
||||
return JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
if (!ike_sa->get_peer_cfg(ike_sa))
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
|
||||
@@ -318,6 +323,8 @@ static job_requeue_t initiate(private_android_service_t *this)
|
||||
/* confirm that we received the request */
|
||||
send_status(this, i);
|
||||
|
||||
/* get an additional reference because initiate consumes one */
|
||||
child_cfg->get_ref(child_cfg);
|
||||
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_CFG, "failed to initiate tunnel");
|
||||
|
||||
@@ -176,9 +176,9 @@ METHOD(listener_t, ike_updown, bool,
|
||||
|
||||
METHOD(listener_t, message_hook, bool,
|
||||
private_duplicheck_listener_t *this, ike_sa_t *ike_sa,
|
||||
message_t *message, bool incoming)
|
||||
message_t *message, bool incoming, bool plain)
|
||||
{
|
||||
if (incoming && !message->get_request(message))
|
||||
if (incoming && plain && !message->get_request(message))
|
||||
{
|
||||
identification_t *id;
|
||||
entry_t *entry;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_aka_peer_t eap_aka_peer_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* EAP-AKA peer implementation.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_aka_server_t eap_aka_server_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* EAP-AKA server implementation.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_gtc_t eap_gtc_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using EAP-GTC.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_identity_t eap_identity_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using EAP Identity.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_md5_t eap_md5_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using EAP-MD5 (CHAP).
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_mschapv2_t eap_mschapv2_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using EAP-MS-CHAPv2.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_peap_t eap_peap_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of eap_method_t using EAP-PEAP.
|
||||
|
||||
@@ -26,7 +26,7 @@ typedef struct eap_peap_peer_t eap_peap_peer_t;
|
||||
#include "tls_application.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* TLS application data handler as peer.
|
||||
|
||||
@@ -26,7 +26,7 @@ typedef struct eap_peap_server_t eap_peap_server_t;
|
||||
#include "tls_application.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* TLS application data handler as server.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_radius_t eap_radius_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using a RADIUS server.
|
||||
|
||||
@@ -271,10 +271,10 @@ METHOD(listener_t, ike_updown, bool,
|
||||
|
||||
METHOD(listener_t, message_hook, bool,
|
||||
private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
|
||||
message_t *message, bool incoming)
|
||||
message_t *message, bool incoming, bool plain)
|
||||
{
|
||||
/* start accounting here, virtual IP now is set */
|
||||
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
if (plain && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
message->get_exchange_type(message) == IKE_AUTH &&
|
||||
!incoming && !message->get_request(message))
|
||||
{
|
||||
|
||||
@@ -319,11 +319,11 @@ void eap_radius_forward_to_ike(radius_message_t *response)
|
||||
|
||||
METHOD(listener_t, message, bool,
|
||||
private_eap_radius_forward_t *this,
|
||||
ike_sa_t *ike_sa, message_t *message, bool incoming)
|
||||
ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
|
||||
{
|
||||
linked_list_t *queue;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_AUTH)
|
||||
if (plain && message->get_exchange_type(message) == IKE_AUTH)
|
||||
{
|
||||
if (incoming)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#ifndef EAP_SIM_PEER_H_
|
||||
#define EAP_SIM_PEER_H_
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
typedef struct eap_sim_peer_t eap_sim_peer_t;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#ifndef EAP_SIM_SERVER_H_
|
||||
#define EAP_SIM_SERVER_H_
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
typedef struct eap_sim_server_t eap_sim_server_t;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_tls_t eap_tls_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of eap_method_t using EAP-TLS.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_tnc_t eap_tnc_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the eap_method_t interface using EAP-TNC.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef struct eap_ttls_t eap_ttls_t;
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of eap_method_t using EAP-TTLS.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <debug.h>
|
||||
#include <daemon.h>
|
||||
#include <radius_message.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <debug.h>
|
||||
#include <daemon.h>
|
||||
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
#include <sa/eap/eap_method.h>
|
||||
|
||||
typedef struct private_eap_ttls_server_t private_eap_ttls_server_t;
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ typedef struct {
|
||||
ha_message_t *midi;
|
||||
/* last responder mid */
|
||||
ha_message_t *midr;
|
||||
/* last IV update */
|
||||
ha_message_t *iv;
|
||||
} entry_t;
|
||||
|
||||
/**
|
||||
@@ -114,6 +116,7 @@ static void entry_destroy(entry_t *entry)
|
||||
entry->add->destroy(entry->add);
|
||||
DESTROY_IF(entry->midi);
|
||||
DESTROY_IF(entry->midr);
|
||||
DESTROY_IF(entry->iv);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
@@ -164,6 +167,16 @@ METHOD(ha_cache_t, cache, void,
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
case HA_IKE_IV:
|
||||
entry = this->cache->get(this->cache, ike_sa);
|
||||
if (entry)
|
||||
{
|
||||
DESTROY_IF(entry->iv);
|
||||
entry->iv = message;
|
||||
break;
|
||||
}
|
||||
message->destroy(message);
|
||||
break;
|
||||
case HA_IKE_DELETE:
|
||||
entry = this->cache->remove(this->cache, ike_sa);
|
||||
if (entry)
|
||||
@@ -212,7 +225,8 @@ static status_t rekey_children(ike_sa_t *ike_sa)
|
||||
DBG1(DBG_CFG, "resyncing CHILD_SA using a delete");
|
||||
status = ike_sa->delete_child_sa(ike_sa,
|
||||
child_sa->get_protocol(child_sa),
|
||||
child_sa->get_spi(child_sa, TRUE));
|
||||
child_sa->get_spi(child_sa, TRUE),
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -308,6 +322,10 @@ METHOD(ha_cache_t, resync, void,
|
||||
{
|
||||
this->socket->push(this->socket, entry->midr);
|
||||
}
|
||||
if (entry->iv)
|
||||
{
|
||||
this->socket->push(this->socket, entry->iv);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
#include "ha_dispatcher.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <sa/ikev2/keymat_v2.h>
|
||||
#include <sa/ikev1/keymat_v1.h>
|
||||
#include <processing/jobs/callback_job.h>
|
||||
#include <processing/jobs/adopt_children_job.h>
|
||||
|
||||
typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
|
||||
typedef struct ha_diffie_hellman_t ha_diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* Private data of an ha_dispatcher_t object.
|
||||
@@ -62,14 +66,65 @@ struct private_ha_dispatcher_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret
|
||||
* DH implementation for HA synced DH values
|
||||
*/
|
||||
static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret)
|
||||
struct ha_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
*/
|
||||
chunk_t secret;
|
||||
|
||||
/**
|
||||
* Own public value
|
||||
*/
|
||||
chunk_t pub;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, dh_get_shared_secret, status_t,
|
||||
ha_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
*secret = chunk_clone((*(chunk_t*)this->destroy));
|
||||
*secret = chunk_clone(this->secret);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, dh_get_my_public_value, void,
|
||||
ha_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_clone(this->pub);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, dh_destroy, void,
|
||||
ha_diffie_hellman_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HA synced DH implementation
|
||||
*/
|
||||
static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub)
|
||||
{
|
||||
ha_diffie_hellman_t *this;
|
||||
|
||||
INIT(this,
|
||||
.dh = {
|
||||
.get_shared_secret = _dh_get_shared_secret,
|
||||
.get_my_public_value = _dh_get_my_public_value,
|
||||
.destroy = _dh_destroy,
|
||||
},
|
||||
.secret = secret,
|
||||
.pub = pub,
|
||||
);
|
||||
|
||||
return &this->dh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process messages of type IKE_ADD
|
||||
*/
|
||||
@@ -79,9 +134,12 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
ha_message_value_t value;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa = NULL, *old_sa = NULL;
|
||||
ike_version_t version = IKEV2;
|
||||
u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
|
||||
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
|
||||
chunk_t secret = chunk_empty, old_skd = chunk_empty;
|
||||
chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
|
||||
bool ok = FALSE;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
@@ -89,12 +147,16 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
switch (attribute)
|
||||
{
|
||||
case HA_IKE_ID:
|
||||
ike_sa = ike_sa_create(value.ike_sa_id);
|
||||
ike_sa = ike_sa_create(value.ike_sa_id,
|
||||
value.ike_sa_id->is_initiator(value.ike_sa_id), version);
|
||||
break;
|
||||
case HA_IKE_REKEY_ID:
|
||||
old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
|
||||
value.ike_sa_id);
|
||||
break;
|
||||
case HA_IKE_VERSION:
|
||||
version = value.u8;
|
||||
break;
|
||||
case HA_NONCE_I:
|
||||
nonce_i = value.chunk;
|
||||
break;
|
||||
@@ -104,6 +166,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
case HA_SECRET:
|
||||
secret = value.chunk;
|
||||
break;
|
||||
case HA_LOCAL_DH:
|
||||
dh_local = value.chunk;
|
||||
break;
|
||||
case HA_REMOTE_DH:
|
||||
dh_remote = value.chunk;
|
||||
break;
|
||||
case HA_PSK:
|
||||
psk = value.chunk;
|
||||
break;
|
||||
case HA_OLD_SKD:
|
||||
old_skd = value.chunk;
|
||||
break;
|
||||
@@ -131,13 +202,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
if (ike_sa)
|
||||
{
|
||||
proposal_t *proposal;
|
||||
keymat_t *keymat;
|
||||
/* quick and dirty hack of a DH implementation ;-) */
|
||||
diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
|
||||
.destroy = (void*)&secret };
|
||||
diffie_hellman_t *dh;
|
||||
|
||||
proposal = proposal_create(PROTO_IKE, 0);
|
||||
keymat = ike_sa->get_keymat(ike_sa);
|
||||
if (integ)
|
||||
{
|
||||
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
|
||||
@@ -151,8 +218,35 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
|
||||
}
|
||||
charon->bus->set_sa(charon->bus, ike_sa);
|
||||
if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r,
|
||||
ike_sa->get_id(ike_sa), old_prf, old_skd))
|
||||
dh = ha_diffie_hellman_create(secret, dh_local);
|
||||
if (ike_sa->get_version(ike_sa) == IKEV2)
|
||||
{
|
||||
keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
|
||||
|
||||
ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i,
|
||||
nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd);
|
||||
}
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
|
||||
shared_key_t *shared = NULL;
|
||||
auth_method_t method = AUTH_RSA;
|
||||
|
||||
if (psk.len)
|
||||
{
|
||||
method = AUTH_PSK;
|
||||
shared = shared_key_create(SHARED_IKE, chunk_clone(psk));
|
||||
}
|
||||
if (keymat_v1->create_hasher(keymat_v1, proposal))
|
||||
{
|
||||
ok = keymat_v1->derive_ike_keys(keymat_v1, proposal,
|
||||
dh, dh_remote, nonce_i, nonce_r,
|
||||
ike_sa->get_id(ike_sa), method, shared);
|
||||
}
|
||||
DESTROY_IF(shared);
|
||||
}
|
||||
dh->destroy(dh);
|
||||
if (ok)
|
||||
{
|
||||
if (old_sa)
|
||||
{
|
||||
@@ -168,6 +262,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
|
||||
old_sa = NULL;
|
||||
}
|
||||
ike_sa->set_state(ike_sa, IKE_CONNECTING);
|
||||
ike_sa->set_proposal(ike_sa, proposal);
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
message = NULL;
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
@@ -289,6 +384,8 @@ static void process_ike_update(private_ha_dispatcher_t *this,
|
||||
set_extension(ike_sa, value.u32, EXT_STRONGSWAN);
|
||||
set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION);
|
||||
set_extension(ike_sa, value.u32, EXT_MS_WINDOWS);
|
||||
set_extension(ike_sa, value.u32, EXT_XAUTH);
|
||||
set_extension(ike_sa, value.u32, EXT_DPD);
|
||||
break;
|
||||
case HA_CONDITIONS:
|
||||
set_condition(ike_sa, value.u32, COND_NAT_ANY);
|
||||
@@ -299,6 +396,8 @@ static void process_ike_update(private_ha_dispatcher_t *this,
|
||||
set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN);
|
||||
set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR);
|
||||
set_condition(ike_sa, value.u32, COND_STALE);
|
||||
set_condition(ike_sa, value.u32, COND_INIT_CONTACT_SEEN);
|
||||
set_condition(ike_sa, value.u32, COND_XAUTH_AUTHENTICATED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -333,6 +432,11 @@ static void process_ike_update(private_ha_dispatcher_t *this,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
lib->processor->queue_job(lib->processor, (job_t*)
|
||||
adopt_children_job_create(ike_sa->get_id(ike_sa)));
|
||||
}
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
@@ -388,6 +492,57 @@ static void process_ike_mid(private_ha_dispatcher_t *this,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process messages of type IKE_IV
|
||||
*/
|
||||
static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message)
|
||||
{
|
||||
ha_message_attribute_t attribute;
|
||||
ha_message_value_t value;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa = NULL;
|
||||
chunk_t iv = chunk_empty;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
{
|
||||
switch (attribute)
|
||||
{
|
||||
case HA_IKE_ID:
|
||||
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
|
||||
value.ike_sa_id);
|
||||
break;
|
||||
case HA_IV:
|
||||
iv = value.chunk;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (ike_sa)
|
||||
{
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
if (iv.len)
|
||||
{
|
||||
keymat_v1_t *keymat;
|
||||
|
||||
keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
|
||||
keymat->update_iv(keymat, 0, iv);
|
||||
keymat->confirm_iv(keymat, 0);
|
||||
}
|
||||
}
|
||||
this->cache->cache(this->cache, ike_sa, message);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
message->destroy(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process messages of type IKE_DELETE
|
||||
*/
|
||||
@@ -465,8 +620,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
||||
child_cfg_t *config = NULL;
|
||||
child_sa_t *child_sa;
|
||||
proposal_t *proposal;
|
||||
keymat_t *keymat;
|
||||
bool initiator = FALSE, failed = FALSE;
|
||||
bool initiator = FALSE, failed = FALSE, ok = FALSE;
|
||||
u_int32_t inbound_spi = 0, outbound_spi = 0;
|
||||
u_int16_t inbound_cpi = 0, outbound_cpi = 0;
|
||||
u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
|
||||
@@ -476,9 +630,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
||||
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
|
||||
chunk_t encr_i, integ_i, encr_r, integ_r;
|
||||
linked_list_t *local_ts, *remote_ts;
|
||||
/* quick and dirty hack of a DH implementation */
|
||||
diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
|
||||
.destroy = (void*)&secret };
|
||||
diffie_hellman_t *dh = NULL;
|
||||
|
||||
enumerator = message->create_attribute_enumerator(message);
|
||||
while (enumerator->enumerate(enumerator, &attribute, &value))
|
||||
@@ -572,10 +724,30 @@ static void process_child_add(private_ha_dispatcher_t *this,
|
||||
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
|
||||
}
|
||||
proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
|
||||
keymat = ike_sa->get_keymat(ike_sa);
|
||||
if (secret.len)
|
||||
{
|
||||
dh = ha_diffie_hellman_create(secret, chunk_empty);
|
||||
}
|
||||
if (ike_sa->get_version(ike_sa) == IKEV2)
|
||||
{
|
||||
keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
|
||||
|
||||
if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL,
|
||||
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
|
||||
ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh,
|
||||
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
|
||||
}
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
|
||||
u_int32_t spi_i, spi_r;
|
||||
|
||||
spi_i = initiator ? inbound_spi : outbound_spi;
|
||||
spi_r = initiator ? outbound_spi : inbound_spi;
|
||||
|
||||
ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r,
|
||||
nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
|
||||
}
|
||||
DESTROY_IF(dh);
|
||||
if (!ok)
|
||||
{
|
||||
DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
|
||||
child_sa->destroy(child_sa);
|
||||
@@ -825,6 +997,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
|
||||
case HA_IKE_MID_RESPONDER:
|
||||
process_ike_mid(this, message, FALSE);
|
||||
break;
|
||||
case HA_IKE_IV:
|
||||
process_ike_iv(this, message);
|
||||
break;
|
||||
case HA_IKE_DELETE:
|
||||
process_ike_delete(this, message);
|
||||
break;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
#include "ha_ike.h"
|
||||
|
||||
#include <sa/ikev2/keymat_v2.h>
|
||||
#include <sa/ikev1/keymat_v1.h>
|
||||
|
||||
typedef struct private_ha_ike_t private_ha_ike_t;
|
||||
|
||||
/**
|
||||
@@ -69,7 +72,8 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
|
||||
|
||||
METHOD(listener_t, ike_keys, bool,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
|
||||
chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
|
||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey,
|
||||
shared_key_t *shared)
|
||||
{
|
||||
ha_message_t *m;
|
||||
chunk_t secret;
|
||||
@@ -86,14 +90,15 @@ METHOD(listener_t, ike_keys, bool,
|
||||
}
|
||||
|
||||
m = ha_message_create(HA_IKE_ADD);
|
||||
m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa));
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
|
||||
if (rekey)
|
||||
if (rekey && rekey->get_version(rekey) == IKEV2)
|
||||
{
|
||||
chunk_t skd;
|
||||
keymat_t *keymat;
|
||||
keymat_v2_t *keymat;
|
||||
|
||||
keymat = rekey->get_keymat(rekey);
|
||||
keymat = (keymat_v2_t*)rekey->get_keymat(rekey);
|
||||
m->add_attribute(m, HA_IKE_REKEY_ID, rekey->get_id(rekey));
|
||||
m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd));
|
||||
m->add_attribute(m, HA_OLD_SKD, skd);
|
||||
@@ -120,6 +125,17 @@ METHOD(listener_t, ike_keys, bool,
|
||||
m->add_attribute(m, HA_NONCE_R, nonce_r);
|
||||
m->add_attribute(m, HA_SECRET, secret);
|
||||
chunk_clear(&secret);
|
||||
if (ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
dh->get_my_public_value(dh, &secret);
|
||||
m->add_attribute(m, HA_LOCAL_DH, secret);
|
||||
chunk_free(&secret);
|
||||
m->add_attribute(m, HA_REMOTE_DH, dh_other);
|
||||
if (shared)
|
||||
{
|
||||
m->add_attribute(m, HA_PSK, shared->get_key(shared));
|
||||
}
|
||||
}
|
||||
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
@@ -159,7 +175,9 @@ METHOD(listener_t, ike_updown, bool,
|
||||
| copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
|
||||
| copy_condition(ike_sa, COND_CERTREQ_SEEN)
|
||||
| copy_condition(ike_sa, COND_ORIGINAL_INITIATOR)
|
||||
| copy_condition(ike_sa, COND_STALE);
|
||||
| copy_condition(ike_sa, COND_STALE)
|
||||
| copy_condition(ike_sa, COND_INIT_CONTACT_SEEN)
|
||||
| copy_condition(ike_sa, COND_XAUTH_AUTHENTICATED);
|
||||
|
||||
extension = copy_extension(ike_sa, EXT_NATT)
|
||||
| copy_extension(ike_sa, EXT_MOBIKE)
|
||||
@@ -167,7 +185,9 @@ METHOD(listener_t, ike_updown, bool,
|
||||
| copy_extension(ike_sa, EXT_MULTIPLE_AUTH)
|
||||
| copy_extension(ike_sa, EXT_STRONGSWAN)
|
||||
| copy_extension(ike_sa, EXT_EAP_ONLY_AUTHENTICATION)
|
||||
| copy_extension(ike_sa, EXT_MS_WINDOWS);
|
||||
| copy_extension(ike_sa, EXT_MS_WINDOWS)
|
||||
| copy_extension(ike_sa, EXT_XAUTH)
|
||||
| copy_extension(ike_sa, EXT_DPD);
|
||||
|
||||
id = ike_sa->get_id(ike_sa);
|
||||
|
||||
@@ -222,49 +242,116 @@ METHOD(listener_t, ike_state_change, bool,
|
||||
}
|
||||
|
||||
METHOD(listener_t, message_hook, bool,
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming)
|
||||
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message,
|
||||
bool incoming, bool plain)
|
||||
{
|
||||
if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
|
||||
{ /* do not sync SA between nodes */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (message->get_exchange_type(message) != IKE_SA_INIT &&
|
||||
message->get_request(message))
|
||||
{ /* we sync on requests, but skip it on IKE_SA_INIT */
|
||||
ha_message_t *m;
|
||||
if (plain && ike_sa->get_version(ike_sa) == IKEV2)
|
||||
{
|
||||
if (message->get_exchange_type(message) != IKE_SA_INIT &&
|
||||
message->get_request(message))
|
||||
{ /* we sync on requests, but skip it on IKE_SA_INIT */
|
||||
ha_message_t *m;
|
||||
|
||||
if (incoming)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_RESPONDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_INITIATOR);
|
||||
}
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
message->get_exchange_type(message) == IKE_AUTH &&
|
||||
!message->get_request(message))
|
||||
{ /* After IKE_SA has been established, sync peers virtual IP.
|
||||
* We cannot sync it in the state_change hook, it is installed later.
|
||||
* TODO: where to sync local VIP? */
|
||||
ha_message_t *m;
|
||||
host_t *vip;
|
||||
|
||||
vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
|
||||
if (vip)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_UPDATE);
|
||||
if (incoming)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_RESPONDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_INITIATOR);
|
||||
}
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_REMOTE_VIP, vip);
|
||||
m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
|
||||
message->get_exchange_type(message) == IKE_AUTH &&
|
||||
!message->get_request(message))
|
||||
{ /* After IKE_SA has been established, sync peers virtual IP.
|
||||
* We cannot sync it in the state_change hook, it is installed later.
|
||||
* TODO: where to sync local VIP? */
|
||||
ha_message_t *m;
|
||||
host_t *vip;
|
||||
|
||||
vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
|
||||
if (vip)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_UPDATE);
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_REMOTE_VIP, vip);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
|
||||
{
|
||||
ha_message_t *m;
|
||||
keymat_v1_t *keymat;
|
||||
u_int32_t mid;
|
||||
chunk_t iv;
|
||||
host_t *vip;
|
||||
|
||||
mid = message->get_message_id(message);
|
||||
if (mid == 0)
|
||||
{
|
||||
keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
|
||||
iv = keymat->get_iv(keymat, mid);
|
||||
m = ha_message_create(HA_IKE_IV);
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_IV, iv);
|
||||
free(iv.ptr);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
if (!incoming && message->get_exchange_type(message) == TRANSACTION)
|
||||
{
|
||||
vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
|
||||
if (vip)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_UPDATE);
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_REMOTE_VIP, vip);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plain && ike_sa->get_version(ike_sa) == IKEV1 &&
|
||||
message->get_exchange_type(message) == INFORMATIONAL_V1)
|
||||
{
|
||||
ha_message_t *m;
|
||||
notify_payload_t *notify;
|
||||
chunk_t data;
|
||||
u_int32_t seq;
|
||||
|
||||
notify = message->get_notify(message, DPD_R_U_THERE);
|
||||
if (notify)
|
||||
{
|
||||
data = notify->get_notification_data(notify);
|
||||
if (data.len == 4)
|
||||
{
|
||||
seq = untoh32(data.ptr);
|
||||
if (incoming)
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_RESPONDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = ha_message_create(HA_IKE_MID_INITIATOR);
|
||||
}
|
||||
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_MID, seq + 1);
|
||||
this->socket->push(this->socket, m);
|
||||
this->cache->cache(this->cache, ike_sa, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ struct private_ha_message_t {
|
||||
chunk_t buf;
|
||||
};
|
||||
|
||||
ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
|
||||
ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV,
|
||||
"IKE_ADD",
|
||||
"IKE_UPDATE",
|
||||
"IKE_MID_INITIATOR",
|
||||
@@ -58,6 +58,7 @@ ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
|
||||
"SEGMENT_TAKE",
|
||||
"STATUS",
|
||||
"RESYNC",
|
||||
"IKE_IV",
|
||||
);
|
||||
|
||||
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
|
||||
@@ -66,6 +67,7 @@ typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
|
||||
* Encoding if an ike_sa_id_t
|
||||
*/
|
||||
struct ike_sa_id_encoding_t {
|
||||
u_int8_t ike_version;
|
||||
u_int64_t initiator_spi;
|
||||
u_int64_t responder_spi;
|
||||
u_int8_t initiator;
|
||||
@@ -156,6 +158,7 @@ METHOD(ha_message_t, add_attribute, void,
|
||||
enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
|
||||
this->buf.len += sizeof(ike_sa_id_encoding_t);
|
||||
enc->initiator = id->is_initiator(id);
|
||||
enc->ike_version = id->get_ike_version(id);
|
||||
enc->initiator_spi = id->get_initiator_spi(id);
|
||||
enc->responder_spi = id->get_responder_spi(id);
|
||||
break;
|
||||
@@ -213,6 +216,7 @@ METHOD(ha_message_t, add_attribute, void,
|
||||
break;
|
||||
}
|
||||
/* u_int8_t */
|
||||
case HA_IKE_VERSION:
|
||||
case HA_INITIATOR:
|
||||
case HA_IPSEC_MODE:
|
||||
case HA_IPCOMP:
|
||||
@@ -263,6 +267,10 @@ METHOD(ha_message_t, add_attribute, void,
|
||||
case HA_NONCE_I:
|
||||
case HA_NONCE_R:
|
||||
case HA_SECRET:
|
||||
case HA_LOCAL_DH:
|
||||
case HA_REMOTE_DH:
|
||||
case HA_PSK:
|
||||
case HA_IV:
|
||||
case HA_OLD_SKD:
|
||||
{
|
||||
chunk_t chunk;
|
||||
@@ -351,8 +359,9 @@ METHOD(enumerator_t, attribute_enumerate, bool,
|
||||
return FALSE;
|
||||
}
|
||||
enc = (ike_sa_id_encoding_t*)(this->buf.ptr);
|
||||
value->ike_sa_id = ike_sa_id_create(enc->initiator_spi,
|
||||
enc->responder_spi, enc->initiator);
|
||||
value->ike_sa_id = ike_sa_id_create(enc->ike_version,
|
||||
enc->initiator_spi, enc->responder_spi,
|
||||
enc->initiator);
|
||||
*attr_out = attr;
|
||||
this->cleanup = (void*)value->ike_sa_id->destroy;
|
||||
this->cleanup_data = value->ike_sa_id;
|
||||
@@ -426,6 +435,7 @@ METHOD(enumerator_t, attribute_enumerate, bool,
|
||||
return TRUE;
|
||||
}
|
||||
/* u_int8_t */
|
||||
case HA_IKE_VERSION:
|
||||
case HA_INITIATOR:
|
||||
case HA_IPSEC_MODE:
|
||||
case HA_IPCOMP:
|
||||
@@ -479,6 +489,10 @@ METHOD(enumerator_t, attribute_enumerate, bool,
|
||||
case HA_NONCE_I:
|
||||
case HA_NONCE_R:
|
||||
case HA_SECRET:
|
||||
case HA_LOCAL_DH:
|
||||
case HA_REMOTE_DH:
|
||||
case HA_PSK:
|
||||
case HA_IV:
|
||||
case HA_OLD_SKD:
|
||||
{
|
||||
size_t len;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/**
|
||||
* Protocol version of this implementation
|
||||
*/
|
||||
#define HA_MESSAGE_VERSION 2
|
||||
#define HA_MESSAGE_VERSION 3
|
||||
|
||||
typedef struct ha_message_t ha_message_t;
|
||||
typedef enum ha_message_type_t ha_message_type_t;
|
||||
@@ -63,6 +63,8 @@ enum ha_message_type_t {
|
||||
HA_STATUS,
|
||||
/** segments the receiving node is requested to resync */
|
||||
HA_RESYNC,
|
||||
/** IV synchronization for IKEv1 Main/Aggressive mode */
|
||||
HA_IKE_IV,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,7 +78,7 @@ extern enum_name_t *ha_message_type_names;
|
||||
enum ha_message_attribute_t {
|
||||
/** ike_sa_id_t*, to identify IKE_SA */
|
||||
HA_IKE_ID = 1,
|
||||
/** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */
|
||||
/** ike_sa_id_t*, identifies IKE_SA which gets rekeyed */
|
||||
HA_IKE_REKEY_ID,
|
||||
/** identification_t*, local identity */
|
||||
HA_LOCAL_ID,
|
||||
@@ -142,6 +144,16 @@ enum ha_message_attribute_t {
|
||||
HA_SEGMENT,
|
||||
/** u_int16_t, Extended Sequence numbers */
|
||||
HA_ESN,
|
||||
/** u_int8_t, IKE version */
|
||||
HA_IKE_VERSION,
|
||||
/** chunk_t, own DH public value */
|
||||
HA_LOCAL_DH,
|
||||
/** chunk_t, remote DH public value */
|
||||
HA_REMOTE_DH,
|
||||
/** chunk_t, shared secret for IKEv1 key derivation */
|
||||
HA_PSK,
|
||||
/** chunk_t, IV for next IKEv1 message */
|
||||
HA_IV,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -206,8 +206,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
|
||||
ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT,
|
||||
remote, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create("ha", 2, ike_cfg, CERT_NEVER_SEND,
|
||||
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30,
|
||||
peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
|
||||
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
|
||||
NULL, NULL, FALSE, NULL, NULL);
|
||||
|
||||
auth_cfg = auth_cfg_create();
|
||||
|
||||
@@ -189,9 +189,9 @@ METHOD(listener_t, ike_state_change, bool,
|
||||
|
||||
METHOD(listener_t, message_hook, bool,
|
||||
private_led_listener_t *this, ike_sa_t *ike_sa,
|
||||
message_t *message, bool incoming)
|
||||
message_t *message, bool incoming, bool plain)
|
||||
{
|
||||
if (incoming || message->get_request(message))
|
||||
if (plain && (incoming || message->get_request(message)))
|
||||
{
|
||||
blink_activity(this);
|
||||
}
|
||||
|
||||
@@ -249,11 +249,12 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
|
||||
"0.0.0.0", IKEV2_UDP_PORT, this->remote, IKEV2_UDP_PORT);
|
||||
}
|
||||
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
|
||||
peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
|
||||
peer_cfg = peer_cfg_create("load-test", IKEV2, ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */
|
||||
this->ike_rekey, 0, /* rekey, reauth */
|
||||
0, this->ike_rekey, /* jitter, overtime */
|
||||
FALSE, this->dpd_delay, /* mobike, dpddelay */
|
||||
FALSE, FALSE, /* mobike, aggressive mode */
|
||||
this->dpd_delay, /* dpddelay */
|
||||
this->vip ? this->vip->clone(this->vip) : NULL,
|
||||
this->pool, FALSE, NULL, NULL);
|
||||
if (num)
|
||||
|
||||
@@ -327,11 +327,12 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
hostname, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
|
||||
peer_cfg = peer_cfg_create(this->current, 2, ike_cfg, CERT_SEND_IF_ASKED,
|
||||
peer_cfg = peer_cfg_create(this->current, IKEV2, ike_cfg,
|
||||
CERT_SEND_IF_ASKED,
|
||||
UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, 0, /* mobike, DPD */
|
||||
TRUE, FALSE, 0, /* mobike, aggressive, DPD */
|
||||
host_create_from_string("0.0.0.0", 0) /* virt */,
|
||||
NULL, FALSE, NULL, NULL); /* pool, mediation */
|
||||
|
||||
@@ -354,12 +355,16 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
0, "255.255.255.255", 65535);
|
||||
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
|
||||
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
|
||||
/* get an additional reference because initiate consumes one */
|
||||
child_cfg->get_ref(child_cfg);
|
||||
|
||||
/* get us an IKE_SA */
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
|
||||
peer_cfg);
|
||||
if (!ike_sa)
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
this->status = VPN_STATUS_CONNECTION_FAILED;
|
||||
return FALSE;
|
||||
}
|
||||
if (!ike_sa->get_peer_cfg(ike_sa))
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
|
||||
@@ -373,6 +378,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
|
||||
this->public.listener.ike_state_change = _ike_state_change;
|
||||
charon->bus->add_listener(charon->bus, &this->public.listener);
|
||||
|
||||
/* get an additional reference because initiate consumes one */
|
||||
child_cfg->get_ref(child_cfg);
|
||||
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_CFG, "failed to initiate tunnel");
|
||||
|
||||
@@ -122,11 +122,11 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
"0.0.0.0", IKEV2_UDP_PORT, address, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
med_cfg = peer_cfg_create(
|
||||
"mediation", 2, ike_cfg,
|
||||
"mediation", IKEV2, ike_cfg,
|
||||
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 */
|
||||
TRUE, FALSE, this->dpd, /* mobike, aggressive, dpddelay */
|
||||
NULL, NULL, /* vip, pool */
|
||||
TRUE, NULL, NULL); /* mediation, med by, peer id */
|
||||
e->destroy(e);
|
||||
@@ -159,11 +159,11 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
|
||||
return NULL;
|
||||
}
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, 2, this->ike->get_ref(this->ike),
|
||||
name, IKEV2, this->ike->get_ref(this->ike),
|
||||
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 */
|
||||
TRUE, FALSE, this->dpd, /* mobike, aggressive, dpddelay */
|
||||
NULL, NULL, /* vip, pool */
|
||||
FALSE, med_cfg, /* mediation, med by */
|
||||
identification_create_from_encoding(ID_KEY_ID, other));
|
||||
@@ -234,11 +234,11 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
return FALSE;
|
||||
}
|
||||
this->current = peer_cfg_create(
|
||||
name, 2, this->ike->get_ref(this->ike),
|
||||
name, IKEV2, this->ike->get_ref(this->ike),
|
||||
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 */
|
||||
TRUE, FALSE, this->dpd, /* mobike, aggr., dpddelay */
|
||||
NULL, NULL, /* vip, pool */
|
||||
FALSE, NULL, NULL); /* mediation, med by, peer id */
|
||||
|
||||
|
||||
@@ -88,11 +88,11 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
|
||||
if (e->enumerate(e, &name))
|
||||
{
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, 2, this->ike->get_ref(this->ike),
|
||||
name, IKEV2, this->ike->get_ref(this->ike),
|
||||
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 */
|
||||
TRUE, FALSE, this->dpd, /* mobike, aggr., dpddelay */
|
||||
NULL, NULL, /* vip, pool */
|
||||
TRUE, NULL, NULL); /* mediation, med by, peer id */
|
||||
e->destroy(e);
|
||||
|
||||
@@ -499,11 +499,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
ike_cfg = ike_cfg_create(TRUE, encap,
|
||||
"0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg,
|
||||
peer_cfg = peer_cfg_create(priv->name, IKEV2, ike_cfg,
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
|
||||
36000, 0, /* rekey 10h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, 0, /* mobike, DPD */
|
||||
TRUE, FALSE, 0, /* mobike, aggressive, DPD */
|
||||
virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
|
||||
NULL, FALSE, NULL, NULL); /* pool, mediation */
|
||||
auth = auth_cfg_create();
|
||||
@@ -533,6 +533,13 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
*/
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
|
||||
peer_cfg);
|
||||
if (!ike_sa)
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
|
||||
"IKE version not supported.");
|
||||
return FALSE;
|
||||
}
|
||||
if (!ike_sa->get_peer_cfg(ike_sa))
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
|
||||
@@ -550,6 +557,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
/**
|
||||
* Initiate
|
||||
*/
|
||||
child_cfg->get_ref(child_cfg);
|
||||
if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
|
||||
{
|
||||
charon->bus->remove_listener(charon->bus, &priv->listener);
|
||||
|
||||
@@ -172,9 +172,9 @@ static void add_radius_attribute(private_radattr_listener_t *this,
|
||||
|
||||
METHOD(listener_t, message, bool,
|
||||
private_radattr_listener_t *this,
|
||||
ike_sa_t *ike_sa, message_t *message, bool incoming)
|
||||
ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
|
||||
{
|
||||
if (ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
|
||||
if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
|
||||
message->get_exchange_type(message) == IKE_AUTH &&
|
||||
message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
|
||||
{
|
||||
|
||||
@@ -294,7 +294,7 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
|
||||
xmlTextWriterStartElement(writer, "configlist");
|
||||
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
|
||||
NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
enumerator_t *children;
|
||||
@@ -302,11 +302,6 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
|
||||
ike_cfg_t *ike_cfg;
|
||||
linked_list_t *list;
|
||||
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||
{ /* only IKEv2 connections yet */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* <peerconfig> */
|
||||
xmlTextWriterStartElement(writer, "peerconfig");
|
||||
xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
|
||||
|
||||
@@ -368,9 +368,9 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
|
||||
if (ike)
|
||||
{
|
||||
peer_cfg = peer_cfg_create(
|
||||
name, 2, ike, cert_policy, uniqueid,
|
||||
name, IKEV2, ike, cert_policy, uniqueid,
|
||||
keyingtries, rekeytime, reauthtime, jitter, overtime,
|
||||
mobike, dpd_delay, vip, pool,
|
||||
mobike, FALSE, dpd_delay, vip, pool,
|
||||
mediation, mediated_cfg, peer_id);
|
||||
auth = auth_cfg_create();
|
||||
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
|
||||
|
||||
@@ -266,7 +266,6 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
|
||||
char *auth, *id, *cert, *ca;
|
||||
stroke_end_t *end, *other_end;
|
||||
auth_cfg_t *cfg;
|
||||
char eap_buf[32];
|
||||
|
||||
/* select strings */
|
||||
if (local)
|
||||
@@ -314,47 +313,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
if (local)
|
||||
{ /* "leftauth" not defined, fall back to deprecated "authby" */
|
||||
switch (msg->add_conn.auth_method)
|
||||
{
|
||||
default:
|
||||
case AUTH_CLASS_PUBKEY:
|
||||
auth = "pubkey";
|
||||
break;
|
||||
case AUTH_CLASS_PSK:
|
||||
auth = "psk";
|
||||
break;
|
||||
case AUTH_CLASS_EAP:
|
||||
auth = "eap";
|
||||
break;
|
||||
case AUTH_CLASS_ANY:
|
||||
auth = "any";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* "rightauth" not defined, fall back to deprecated "eap" */
|
||||
if (msg->add_conn.eap_type)
|
||||
{
|
||||
if (msg->add_conn.eap_vendor)
|
||||
{
|
||||
snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
|
||||
msg->add_conn.eap_type,
|
||||
msg->add_conn.eap_vendor);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
|
||||
msg->add_conn.eap_type);
|
||||
}
|
||||
auth = eap_buf;
|
||||
}
|
||||
else
|
||||
{ /* not EAP => no constraints for this peer */
|
||||
auth = "any";
|
||||
}
|
||||
}
|
||||
auth = "pubkey";
|
||||
}
|
||||
else
|
||||
{ /* no second authentication round, fine. But load certificates
|
||||
@@ -469,6 +428,22 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
|
||||
{
|
||||
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
|
||||
}
|
||||
else if (strneq(auth, "xauth", 5))
|
||||
{
|
||||
char *pos;
|
||||
|
||||
pos = strchr(auth, '-');
|
||||
if (pos)
|
||||
{
|
||||
cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
|
||||
}
|
||||
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
|
||||
if (msg->add_conn.xauth_identity)
|
||||
{
|
||||
cfg->add(cfg, AUTH_RULE_XAUTH_IDENTITY,
|
||||
identification_create_from_string(msg->add_conn.xauth_identity));
|
||||
}
|
||||
}
|
||||
else if (strneq(auth, "eap", 3))
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
@@ -670,10 +645,10 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
* the pool name as the connection name, which the attribute provider
|
||||
* uses to serve pool addresses. */
|
||||
peer_cfg = peer_cfg_create(msg->add_conn.name,
|
||||
msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
|
||||
msg->add_conn.version, ike_cfg,
|
||||
msg->add_conn.me.sendcert, unique,
|
||||
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.aggressive, msg->add_conn.dpd.delay,
|
||||
vip, msg->add_conn.other.sourceip_mask ?
|
||||
msg->add_conn.name : msg->add_conn.other.sourceip,
|
||||
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
|
||||
|
||||
@@ -126,14 +126,6 @@ METHOD(stroke_control_t, initiate, void,
|
||||
msg->initiate.name);
|
||||
if (peer_cfg)
|
||||
{
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||
{
|
||||
DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
|
||||
peer_cfg->get_ike_version(peer_cfg));
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
|
||||
if (child_cfg == NULL)
|
||||
{
|
||||
@@ -157,14 +149,10 @@ METHOD(stroke_control_t, initiate, void,
|
||||
}
|
||||
else
|
||||
{
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
|
||||
NULL, NULL, NULL, NULL);
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(
|
||||
charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
|
||||
if (child_cfg)
|
||||
{
|
||||
@@ -568,14 +556,6 @@ METHOD(stroke_control_t, route, void,
|
||||
msg->route.name);
|
||||
if (peer_cfg)
|
||||
{
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||
{
|
||||
DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
|
||||
peer_cfg->get_ike_version(peer_cfg));
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
|
||||
if (child_cfg == NULL)
|
||||
{
|
||||
@@ -599,14 +579,10 @@ METHOD(stroke_control_t, route, void,
|
||||
}
|
||||
else
|
||||
{
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
|
||||
NULL, NULL, NULL, NULL);
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(
|
||||
charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
|
||||
if (child_cfg)
|
||||
{
|
||||
|
||||
@@ -603,7 +603,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
|
||||
pin_data.keyid = chunk;
|
||||
pin_data.try = 1;
|
||||
cb = callback_cred_create_shared((void*)pin_cb, &pin_data);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &cb->set);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -612,7 +612,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
|
||||
id = identification_create_from_encoding(ID_KEY_ID, chunk);
|
||||
mem = mem_cred_create();
|
||||
mem->add_shared(mem, shared, id, NULL);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &mem->set);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
|
||||
}
|
||||
|
||||
/* unlock: smartcard needs the pin and potentially calls public set */
|
||||
@@ -720,7 +720,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
|
||||
pp_data.path = path;
|
||||
pp_data.try = 1;
|
||||
cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &cb->set);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
|
||||
|
||||
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
|
||||
BUILD_FROM_FILE, path, BUILD_END);
|
||||
@@ -737,7 +737,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
|
||||
shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret);
|
||||
mem = mem_cred_create();
|
||||
mem->add_shared(mem, shared, NULL);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &mem->set);
|
||||
lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
|
||||
|
||||
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
|
||||
BUILD_FROM_FILE, path, BUILD_END);
|
||||
|
||||
@@ -118,8 +118,9 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
|
||||
|
||||
ike_proposal = ike_sa->get_proposal(ike_sa);
|
||||
|
||||
fprintf(out, "%12s[%d]: IKE SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
|
||||
fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
|
||||
ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
|
||||
ike_version_names, ike_sa->get_version(ike_sa),
|
||||
id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
|
||||
id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
|
||||
|
||||
@@ -319,11 +320,7 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
|
||||
auth->get(auth, AUTH_RULE_IDENTITY));
|
||||
|
||||
auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
|
||||
if (auth_class != AUTH_CLASS_EAP)
|
||||
{
|
||||
fprintf(out, "%N authentication\n", auth_class_names, auth_class);
|
||||
}
|
||||
else
|
||||
if (auth_class == AUTH_CLASS_EAP)
|
||||
{
|
||||
if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
|
||||
{
|
||||
@@ -350,6 +347,21 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
else if (auth_class == AUTH_CLASS_XAUTH)
|
||||
{
|
||||
fprintf(out, "%N authentication: %s", auth_class_names, auth_class,
|
||||
auth->get(auth, AUTH_RULE_XAUTH_BACKEND) ?: "any");
|
||||
id = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
|
||||
if (id)
|
||||
{
|
||||
fprintf(out, " with XAuth identity '%Y'", id);
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "%N authentication\n", auth_class_names, auth_class);
|
||||
}
|
||||
|
||||
cert = auth->get(auth, AUTH_RULE_CA_CERT);
|
||||
if (cert)
|
||||
@@ -479,18 +491,18 @@ METHOD(stroke_list_t, status, void,
|
||||
|
||||
fprintf(out, "Connections:\n");
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(
|
||||
charon->backends, NULL, NULL, NULL, NULL);
|
||||
charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
|
||||
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
|
||||
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
|
||||
fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
|
||||
ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
|
||||
fprintf(out, "%12s: %s...%s (%N)", peer_cfg->get_name(peer_cfg),
|
||||
ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg),
|
||||
ike_version_names, peer_cfg->get_ike_version(peer_cfg));
|
||||
|
||||
dpd = peer_cfg->get_dpd(peer_cfg);
|
||||
if (dpd)
|
||||
@@ -666,15 +678,12 @@ static void list_public_key(public_key_t *public, FILE *out)
|
||||
private_key_t *private = NULL;
|
||||
chunk_t keyid;
|
||||
identification_t *id;
|
||||
auth_cfg_t *auth;
|
||||
|
||||
if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
|
||||
{
|
||||
id = identification_create_from_encoding(ID_KEY_ID, keyid);
|
||||
auth = auth_cfg_create();
|
||||
private = lib->credmgr->get_private(lib->credmgr,
|
||||
public->get_type(public), id, auth);
|
||||
auth->destroy(auth);
|
||||
public->get_type(public), id, NULL);
|
||||
id->destroy(id);
|
||||
}
|
||||
|
||||
@@ -782,8 +791,8 @@ static void stroke_list_certs(linked_list_t *list, char *label,
|
||||
x509_flag_t flag_mask;
|
||||
|
||||
/* mask all auxiliary flags */
|
||||
flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH |
|
||||
X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS );
|
||||
flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH | X509_IKE_INTERMEDIATE |
|
||||
X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS);
|
||||
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, (void**)&cert))
|
||||
|
||||
@@ -221,12 +221,14 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
|
||||
pop_end(msg, "right", &msg->add_conn.other);
|
||||
pop_string(msg, &msg->add_conn.eap_identity);
|
||||
pop_string(msg, &msg->add_conn.aaa_identity);
|
||||
pop_string(msg, &msg->add_conn.xauth_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, " aaa_identity=%s", msg->add_conn.aaa_identity);
|
||||
DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
|
||||
DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
|
||||
DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
|
||||
DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
|
||||
@@ -235,6 +237,7 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
|
||||
DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
|
||||
DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
|
||||
DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
|
||||
DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
|
||||
|
||||
this->config->add(this->config, msg);
|
||||
this->attribute->add_pool(this->attribute, msg);
|
||||
|
||||
@@ -172,10 +172,10 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
|
||||
local_addr, IKEV2_UDP_PORT, remote_addr, IKEV2_UDP_PORT);
|
||||
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
|
||||
this->peer_cfg = peer_cfg_create(
|
||||
name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
|
||||
name, IKEV2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
|
||||
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
|
||||
1800, 900, /* jitter, overtime */
|
||||
TRUE, 60, /* mobike, dpddelay */
|
||||
TRUE, FALSE, 60, /* mobike, aggr., dpddelay */
|
||||
NULL, NULL, /* vip, pool */
|
||||
FALSE, NULL, NULL); /* mediation, med by, peer id */
|
||||
auth = auth_cfg_create();
|
||||
|
||||
@@ -84,7 +84,7 @@ static void status(private_uci_control_t *this, char *name)
|
||||
FILE *out = NULL;
|
||||
|
||||
configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
|
||||
NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (configs->enumerate(configs, &peer_cfg))
|
||||
{
|
||||
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
|
||||
-I$(top_srcdir)/src/libcharon
|
||||
|
||||
AM_CFLAGS = -rdynamic
|
||||
|
||||
if MONOLITHIC
|
||||
noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-xauth-eap.la
|
||||
endif
|
||||
|
||||
libstrongswan_xauth_eap_la_SOURCES = \
|
||||
xauth_eap_plugin.h xauth_eap_plugin.c \
|
||||
xauth_eap.h xauth_eap.c
|
||||
|
||||
libstrongswan_xauth_eap_la_LDFLAGS = -module -avoid-version
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "xauth_eap.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <credentials/sets/callback_cred.h>
|
||||
|
||||
typedef struct private_xauth_eap_t private_xauth_eap_t;
|
||||
|
||||
/**
|
||||
* Private data of an xauth_eap_t object.
|
||||
*/
|
||||
struct private_xauth_eap_t {
|
||||
|
||||
/**
|
||||
* Public interface.
|
||||
*/
|
||||
xauth_eap_t public;
|
||||
|
||||
/**
|
||||
* ID of the server
|
||||
*/
|
||||
identification_t *server;
|
||||
|
||||
/**
|
||||
* ID of the peer
|
||||
*/
|
||||
identification_t *peer;
|
||||
|
||||
/**
|
||||
* Callback credential set
|
||||
*/
|
||||
callback_cred_t *cred;
|
||||
|
||||
/**
|
||||
* XAuth password
|
||||
*/
|
||||
chunk_t pass;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback credential set function
|
||||
*/
|
||||
static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type,
|
||||
identification_t *me, identification_t *other,
|
||||
id_match_t *match_me, id_match_t *match_other)
|
||||
{
|
||||
shared_key_t *shared;
|
||||
|
||||
if (!this->pass.len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (type != SHARED_EAP && type != SHARED_ANY)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (me)
|
||||
{
|
||||
if (!this->peer->equals(this->peer, me))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (match_me)
|
||||
{
|
||||
*match_me = ID_MATCH_PERFECT;
|
||||
}
|
||||
}
|
||||
else if (match_me)
|
||||
{
|
||||
*match_me = ID_MATCH_ANY;
|
||||
}
|
||||
if (other)
|
||||
{
|
||||
if (!this->server->equals(this->server, other))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (match_other)
|
||||
{
|
||||
*match_other = ID_MATCH_PERFECT;
|
||||
}
|
||||
}
|
||||
else if (match_other)
|
||||
{
|
||||
*match_other = ID_MATCH_ANY;
|
||||
}
|
||||
shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass));
|
||||
this->pass = chunk_empty;
|
||||
return shared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do EAP exchanges to verify secret
|
||||
*/
|
||||
static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend)
|
||||
{
|
||||
eap_payload_t *request, *response;
|
||||
eap_method_t *frontend;
|
||||
eap_type_t type;
|
||||
u_int32_t vendor;
|
||||
status_t status;
|
||||
|
||||
if (backend->initiate(backend, &request) != NEED_MORE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
type = request->get_type(request, &vendor);
|
||||
frontend = charon->eap->create_instance(charon->eap, type, vendor,
|
||||
EAP_PEER, this->server, this->peer);
|
||||
if (!frontend)
|
||||
{
|
||||
DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported",
|
||||
eap_type_names, type);
|
||||
request->destroy(request);
|
||||
return FALSE;
|
||||
}
|
||||
while (TRUE)
|
||||
{
|
||||
/* credential set is active in frontend only, but not in backend */
|
||||
lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE);
|
||||
status = frontend->process(frontend, request, &response);
|
||||
lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set);
|
||||
request->destroy(request);
|
||||
if (status != NEED_MORE)
|
||||
{ /* clients should never return SUCCESS */
|
||||
frontend->destroy(frontend);
|
||||
return FALSE;
|
||||
}
|
||||
status = backend->process(backend, response, &request);
|
||||
response->destroy(response);
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
frontend->destroy(frontend);
|
||||
return TRUE;
|
||||
case NEED_MORE:
|
||||
break;
|
||||
default:
|
||||
frontend->destroy(frontend);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, initiate, status_t,
|
||||
private_xauth_eap_t *this, cp_payload_t **out)
|
||||
{
|
||||
cp_payload_t *cp;
|
||||
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, process, status_t,
|
||||
private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out)
|
||||
{
|
||||
configuration_attribute_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
identification_t *id;
|
||||
chunk_t user = chunk_empty;
|
||||
eap_method_t *backend;
|
||||
eap_type_t type;
|
||||
char *name;
|
||||
bool ok;
|
||||
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
switch (attr->get_type(attr))
|
||||
{
|
||||
case XAUTH_USER_NAME:
|
||||
user = attr->get_chunk(attr);
|
||||
break;
|
||||
case XAUTH_USER_PASSWORD:
|
||||
this->pass = attr->get_chunk(attr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!user.ptr || !this->pass.ptr)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer did not respond to our XAuth request");
|
||||
return FAILED;
|
||||
}
|
||||
if (user.len)
|
||||
{
|
||||
id = identification_create_from_data(user);
|
||||
if (!id)
|
||||
{
|
||||
DBG1(DBG_IKE, "failed to parse provided XAuth username");
|
||||
return FAILED;
|
||||
}
|
||||
this->peer->destroy(this->peer);
|
||||
this->peer = id;
|
||||
}
|
||||
|
||||
name = lib->settings->get_str(lib->settings,
|
||||
"charon.plugins.xauth-eap.backend", "radius");
|
||||
type = eap_type_from_string(name);
|
||||
if (!type)
|
||||
{
|
||||
DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name);
|
||||
return FAILED;
|
||||
}
|
||||
backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER,
|
||||
this->server, this->peer);
|
||||
if (!backend)
|
||||
{
|
||||
DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name);
|
||||
return FAILED;
|
||||
}
|
||||
ok = verify_eap(this, backend);
|
||||
backend->destroy(backend);
|
||||
if (ok)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, get_identity, identification_t*,
|
||||
private_xauth_eap_t *this)
|
||||
{
|
||||
return this->peer;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, destroy, void,
|
||||
private_xauth_eap_t *this)
|
||||
{
|
||||
this->cred->destroy(this->cred);
|
||||
this->server->destroy(this->server);
|
||||
this->peer->destroy(this->peer);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_eap_t *xauth_eap_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
{
|
||||
private_xauth_eap_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.xauth_method = {
|
||||
.initiate = _initiate,
|
||||
.process = _process,
|
||||
.get_identity = _get_identity,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.server = server->clone(server),
|
||||
.peer = peer->clone(peer),
|
||||
);
|
||||
|
||||
this->cred = callback_cred_create_shared((void*)shared_cb, this);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup xauth_eap_i xauth_eap
|
||||
* @{ @ingroup xauth_eap
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_EAP_H_
|
||||
#define XAUTH_EAP_H_
|
||||
|
||||
typedef struct xauth_eap_t xauth_eap_t;
|
||||
|
||||
#include <sa/xauth/xauth_method.h>
|
||||
|
||||
/**
|
||||
* XAuth method that verifies XAuth credentials using EAP methods.
|
||||
*
|
||||
* To reuse existing authentication infrastructure, this XAuth method uses
|
||||
* EAP to verify XAuth Username/Passwords. It is primarily designed to work
|
||||
* with the EAP-RADIUS backend and can use any password-based EAP method
|
||||
* over it. The credentials are fed locally on the IKE responder to a EAP
|
||||
* client which talks to the backend instance, usually a RADIUS server.
|
||||
*/
|
||||
struct xauth_eap_t {
|
||||
|
||||
/**
|
||||
* Implemented xauth_method_t interface.
|
||||
*/
|
||||
xauth_method_t xauth_method;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the XAuth method using EAP, acting as server.
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @return xauth_eap_t object
|
||||
*/
|
||||
xauth_eap_t *xauth_eap_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
|
||||
#endif /** XAUTH_EAP_H_ @}*/
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "xauth_eap_plugin.h"
|
||||
#include "xauth_eap.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
xauth_eap_plugin_t *this)
|
||||
{
|
||||
return "xauth-eap";
|
||||
}
|
||||
|
||||
METHOD(plugin_t, get_features, int,
|
||||
xauth_eap_plugin_t *this, plugin_feature_t *features[])
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
PLUGIN_CALLBACK(xauth_method_register, xauth_eap_create_server),
|
||||
PLUGIN_PROVIDE(XAUTH_SERVER, "eap"),
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
}
|
||||
|
||||
METHOD(plugin_t, destroy, void,
|
||||
xauth_eap_plugin_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
plugin_t *xauth_eap_plugin_create()
|
||||
{
|
||||
xauth_eap_plugin_t *this;
|
||||
|
||||
INIT(this,
|
||||
.plugin = {
|
||||
.get_name = _get_name,
|
||||
.get_features = _get_features,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
return &this->plugin;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup xauth_eap xauth_eap
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup xauth_eap_plugin xauth_eap_plugin
|
||||
* @{ @ingroup xauth_eap
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_EAP_PLUGIN_H_
|
||||
#define XAUTH_EAP_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct xauth_eap_plugin_t xauth_eap_plugin_t;
|
||||
|
||||
/**
|
||||
* XAuth plugin using EAP to verify credentials.
|
||||
*/
|
||||
struct xauth_eap_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
#endif /** XAUTH_EAP_PLUGIN_H_ @}*/
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
|
||||
-I$(top_srcdir)/src/libcharon
|
||||
|
||||
AM_CFLAGS = -rdynamic
|
||||
|
||||
if MONOLITHIC
|
||||
noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-xauth-generic.la
|
||||
endif
|
||||
|
||||
libstrongswan_xauth_generic_la_SOURCES = \
|
||||
xauth_generic_plugin.h xauth_generic_plugin.c \
|
||||
xauth_generic.h xauth_generic.c
|
||||
|
||||
libstrongswan_xauth_generic_la_LDFLAGS = -module -avoid-version
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "xauth_generic.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct private_xauth_generic_t private_xauth_generic_t;
|
||||
|
||||
/**
|
||||
* Private data of an xauth_generic_t object.
|
||||
*/
|
||||
struct private_xauth_generic_t {
|
||||
|
||||
/**
|
||||
* Public interface.
|
||||
*/
|
||||
xauth_generic_t public;
|
||||
|
||||
/**
|
||||
* ID of the server
|
||||
*/
|
||||
identification_t *server;
|
||||
|
||||
/**
|
||||
* ID of the peer
|
||||
*/
|
||||
identification_t *peer;
|
||||
|
||||
};
|
||||
|
||||
METHOD(xauth_method_t, initiate_peer, status_t,
|
||||
private_xauth_generic_t *this, cp_payload_t **out)
|
||||
{
|
||||
/* peer never initiates */
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, process_peer, status_t,
|
||||
private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
|
||||
{
|
||||
shared_key_t *shared;
|
||||
cp_payload_t *cp;
|
||||
chunk_t user, pass;
|
||||
|
||||
shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->peer,
|
||||
this->server);
|
||||
if (!shared)
|
||||
{
|
||||
DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'", this->peer,
|
||||
this->server);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
user = this->peer->get_encoding(this->peer);
|
||||
pass = shared->get_key(shared);
|
||||
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
|
||||
shared->destroy(shared);
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, initiate_server, status_t,
|
||||
private_xauth_generic_t *this, cp_payload_t **out)
|
||||
{
|
||||
cp_payload_t *cp;
|
||||
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, process_server, status_t,
|
||||
private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
|
||||
{
|
||||
configuration_attribute_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
shared_key_t *shared;
|
||||
identification_t *id;
|
||||
chunk_t user = chunk_empty, pass = chunk_empty;
|
||||
status_t status = FAILED;
|
||||
int tried = 0;
|
||||
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
switch (attr->get_type(attr))
|
||||
{
|
||||
case XAUTH_USER_NAME:
|
||||
user = attr->get_chunk(attr);
|
||||
break;
|
||||
case XAUTH_USER_PASSWORD:
|
||||
pass = attr->get_chunk(attr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!user.ptr || !pass.ptr)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer did not respond to our XAuth request");
|
||||
return FAILED;
|
||||
}
|
||||
if (user.len)
|
||||
{
|
||||
id = identification_create_from_data(user);
|
||||
if (!id)
|
||||
{
|
||||
DBG1(DBG_IKE, "failed to parse provided XAuth username");
|
||||
return FAILED;
|
||||
}
|
||||
this->peer->destroy(this->peer);
|
||||
this->peer = id;
|
||||
}
|
||||
|
||||
enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
|
||||
SHARED_EAP, this->server, this->peer);
|
||||
while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
|
||||
{
|
||||
if (chunk_equals(shared->get_key(shared), pass))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
tried++;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
if (!tried)
|
||||
{
|
||||
DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'",
|
||||
this->server, this->peer);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IKE, "none of %d found XAuth secrets for '%Y' - '%Y' "
|
||||
"matched", tried, this->server, this->peer);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, get_identity, identification_t*,
|
||||
private_xauth_generic_t *this)
|
||||
{
|
||||
return this->peer;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, destroy, void,
|
||||
private_xauth_generic_t *this)
|
||||
{
|
||||
this->server->destroy(this->server);
|
||||
this->peer->destroy(this->peer);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_peer(identification_t *server,
|
||||
identification_t *peer)
|
||||
{
|
||||
private_xauth_generic_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.xauth_method = {
|
||||
.initiate = _initiate_peer,
|
||||
.process = _process_peer,
|
||||
.get_identity = _get_identity,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.server = server->clone(server),
|
||||
.peer = peer->clone(peer),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
{
|
||||
private_xauth_generic_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.xauth_method = {
|
||||
.initiate = _initiate_server,
|
||||
.process = _process_server,
|
||||
.get_identity = _get_identity,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.server = server->clone(server),
|
||||
.peer = peer->clone(peer),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup xauth_generic_i xauth_generic
|
||||
* @{ @ingroup xauth_generic
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_GENERIC_H_
|
||||
#define XAUTH_GENERIC_H_
|
||||
|
||||
typedef struct xauth_generic_t xauth_generic_t;
|
||||
|
||||
#include <sa/xauth/xauth_method.h>
|
||||
|
||||
/**
|
||||
* Implementation of the xauth_method_t interface using cleartext secrets
|
||||
* from any credential set.
|
||||
*/
|
||||
struct xauth_generic_t {
|
||||
|
||||
/**
|
||||
* Implemented xauth_method_t interface.
|
||||
*/
|
||||
xauth_method_t xauth_method;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the generic XAuth method, acting as server.
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @return xauth_generic_t object
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
|
||||
/**
|
||||
* Creates the generic XAuth method, acting as peer.
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @return xauth_generic_t object
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_peer(identification_t *server,
|
||||
identification_t *peer);
|
||||
|
||||
#endif /** XAUTH_GENERIC_H_ @}*/
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "xauth_generic_plugin.h"
|
||||
#include "xauth_generic.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
xauth_generic_plugin_t *this)
|
||||
{
|
||||
return "xauth-generic";
|
||||
}
|
||||
|
||||
METHOD(plugin_t, get_features, int,
|
||||
xauth_generic_plugin_t *this, plugin_feature_t *features[])
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
PLUGIN_CALLBACK(xauth_method_register, xauth_generic_create_server),
|
||||
PLUGIN_PROVIDE(XAUTH_SERVER, "generic"),
|
||||
PLUGIN_CALLBACK(xauth_method_register, xauth_generic_create_peer),
|
||||
PLUGIN_PROVIDE(XAUTH_PEER, "generic"),
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
}
|
||||
|
||||
METHOD(plugin_t, destroy, void,
|
||||
xauth_generic_plugin_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
plugin_t *xauth_generic_plugin_create()
|
||||
{
|
||||
xauth_generic_plugin_t *this;
|
||||
|
||||
INIT(this,
|
||||
.plugin = {
|
||||
.get_name = _get_name,
|
||||
.get_features = _get_features,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
return &this->plugin;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup xauth_generic xauth_generic
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup xauth_generic_plugin xauth_generic_plugin
|
||||
* @{ @ingroup xauth_generic
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_GENERIC_PLUGIN_H_
|
||||
#define XAUTH_GENERIC_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct xauth_generic_plugin_t xauth_generic_plugin_t;
|
||||
|
||||
/**
|
||||
* XAuth generic plugin using secrets defined in ipsec.secrets.
|
||||
*/
|
||||
struct xauth_generic_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
#endif /** XAUTH_GENERIC_PLUGIN_H_ @}*/
|
||||
Reference in New Issue
Block a user