IPComp for IKEv2
This commit is contained in:
+84
-10
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2008 Tobias Brunner
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -70,6 +71,8 @@ struct private_child_sa_t {
|
||||
identification_t *id;
|
||||
/** actual used SPI, 0 if unused */
|
||||
u_int32_t spi;
|
||||
/** Compression Parameter Index (CPI) used, 0 if unused */
|
||||
u_int16_t cpi;
|
||||
} me, other;
|
||||
|
||||
/**
|
||||
@@ -147,6 +150,16 @@ struct private_child_sa_t {
|
||||
*/
|
||||
bool encap;
|
||||
|
||||
/**
|
||||
* Specifies the IPComp transform used (IPCOMP_NONE if disabled)
|
||||
*/
|
||||
ipcomp_transform_t ipcomp;
|
||||
|
||||
/**
|
||||
* TRUE if we allocated (or tried to allocate) a CPI
|
||||
*/
|
||||
bool cpi_allocated;
|
||||
|
||||
/**
|
||||
* mode this SA uses, tunnel/transport
|
||||
*/
|
||||
@@ -570,10 +583,21 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
|
||||
|
||||
/* send SA down to the kernel */
|
||||
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
|
||||
|
||||
if (this->ipcomp != IPCOMP_NONE)
|
||||
{
|
||||
/* we install an additional IPComp SA */
|
||||
u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
|
||||
status = charon->kernel_interface->add_sa(charon->kernel_interface,
|
||||
src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
|
||||
ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode,
|
||||
this->ipcomp, FALSE, mine);
|
||||
}
|
||||
|
||||
status = charon->kernel_interface->add_sa(charon->kernel_interface,
|
||||
src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
|
||||
this->enc_alg, this->enc_size, this->int_alg, this->int_size,
|
||||
prf_plus, mode, this->encap, mine);
|
||||
prf_plus, mode, IPCOMP_NONE, this->encap, mine);
|
||||
|
||||
this->install_time = time(NULL);
|
||||
this->rekey_time = this->install_time + soft;
|
||||
@@ -677,15 +701,15 @@ static status_t add_policies(private_child_sa_t *this,
|
||||
/* install 3 policies: out, in and forward */
|
||||
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
|
||||
this->protocol, this->reqid, high_prio, mode);
|
||||
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
|
||||
this->protocol, this->reqid, high_prio, mode);
|
||||
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
|
||||
|
||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
|
||||
this->protocol, this->reqid, high_prio, mode);
|
||||
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
@@ -786,10 +810,20 @@ static status_t update_hosts(private_child_sa_t *this,
|
||||
|
||||
this->encap = encap;
|
||||
|
||||
/* update our (initator) SAs */
|
||||
if (this->ipcomp != IPCOMP_NONE)
|
||||
{
|
||||
/* update our (initator) IPComp SA */
|
||||
charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
|
||||
IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
|
||||
/* update his (responder) IPComp SA */
|
||||
charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)),
|
||||
IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
|
||||
}
|
||||
|
||||
/* update our (initator) SA */
|
||||
charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
|
||||
this->protocol, this->other.addr, this->me.addr, other, me, encap);
|
||||
/* update his (responder) SAs */
|
||||
/* update his (responder) SA */
|
||||
charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
|
||||
this->protocol, this->me.addr, this->other.addr, me, other, encap);
|
||||
|
||||
@@ -837,13 +871,13 @@ static status_t update_hosts(private_child_sa_t *this,
|
||||
/* reinstall updated policies */
|
||||
charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
|
||||
this->protocol, this->reqid, TRUE, this->mode);
|
||||
this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
|
||||
charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
other, me, policy->other_ts, policy->my_ts, POLICY_IN,
|
||||
this->protocol, this->reqid, TRUE, this->mode);
|
||||
this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
|
||||
charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||
other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
|
||||
this->protocol, this->reqid, TRUE, this->mode);
|
||||
this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
@@ -874,6 +908,30 @@ static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
|
||||
this->virtual_ip = ip->clone(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_sa_t.activate_ipcomp.
|
||||
*/
|
||||
static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
|
||||
u_int16_t other_cpi)
|
||||
{
|
||||
this->ipcomp = ipcomp;
|
||||
this->other.cpi = other_cpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_sa_t.get_my_cpi.
|
||||
*/
|
||||
static u_int16_t get_my_cpi(private_child_sa_t *this)
|
||||
{
|
||||
if (!this->cpi_allocated)
|
||||
{
|
||||
charon->kernel_interface->get_cpi(charon->kernel_interface,
|
||||
this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
|
||||
this->cpi_allocated = TRUE;
|
||||
}
|
||||
return this->me.cpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of child_sa_t.destroy.
|
||||
*/
|
||||
@@ -907,6 +965,16 @@ static void destroy(private_child_sa_t *this)
|
||||
charon->kernel_interface->del_sa(charon->kernel_interface,
|
||||
this->other.addr, this->other.spi, this->protocol);
|
||||
}
|
||||
if (this->me.cpi)
|
||||
{
|
||||
charon->kernel_interface->del_sa(charon->kernel_interface,
|
||||
this->other.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
|
||||
}
|
||||
if (this->other.cpi)
|
||||
{
|
||||
charon->kernel_interface->del_sa(charon->kernel_interface,
|
||||
this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP);
|
||||
}
|
||||
|
||||
/* delete all policies in the kernel */
|
||||
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
|
||||
@@ -967,6 +1035,8 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
|
||||
this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
|
||||
this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
|
||||
this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
|
||||
this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
|
||||
this->public.get_my_cpi = (u_int16_t(*)(child_sa_t*))get_my_cpi;
|
||||
this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
|
||||
this->public.destroy = (void(*)(child_sa_t*))destroy;
|
||||
|
||||
@@ -976,10 +1046,14 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
|
||||
this->me.id = my_id->clone(my_id);
|
||||
this->other.id = other_id->clone(other_id);
|
||||
this->me.spi = 0;
|
||||
this->me.cpi = 0;
|
||||
this->other.spi = 0;
|
||||
this->other.cpi = 0;
|
||||
this->alloc_ah_spi = 0;
|
||||
this->alloc_esp_spi = 0;
|
||||
this->encap = encap;
|
||||
this->cpi_allocated = FALSE;
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
this->state = CHILD_CREATED;
|
||||
/* reuse old reqid if we are rekeying an existing CHILD_SA */
|
||||
this->reqid = rekey ? rekey : ++reqid;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2008 Tobias Brunner
|
||||
* Copyright (C) 2006-2007 Martin Willi
|
||||
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -253,6 +254,22 @@ struct child_sa_t {
|
||||
*/
|
||||
void (*set_virtual_ip) (child_sa_t *this, host_t *ip);
|
||||
|
||||
/**
|
||||
* Activate IPComp by setting the transform ID and CPI values.
|
||||
*
|
||||
* @param ipcomp the IPComp transform to use
|
||||
* @param other_cpi other Compression Parameter Index
|
||||
*/
|
||||
void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp,
|
||||
u_int16_t other_cpi);
|
||||
|
||||
/**
|
||||
* Returns the Compression Parameter Index (CPI) allocated from the kernel.
|
||||
*
|
||||
* @return allocated CPI
|
||||
*/
|
||||
u_int16_t (*get_my_cpi) (child_sa_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a child_sa.
|
||||
*/
|
||||
|
||||
@@ -1219,7 +1219,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
|
||||
|
||||
/* install kernel policies */
|
||||
child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
|
||||
this->other_id, child_cfg, FALSE, 0);
|
||||
this->other_id, child_cfg, 0, FALSE);
|
||||
me = this->my_host;
|
||||
if (this->my_virtual_ip)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tobias Brunner
|
||||
* Copyright (C) 2005-2007 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -99,6 +100,21 @@ struct private_child_create_t {
|
||||
*/
|
||||
mode_t mode;
|
||||
|
||||
/**
|
||||
* IPComp transform to use
|
||||
*/
|
||||
ipcomp_transform_t ipcomp;
|
||||
|
||||
/**
|
||||
* IPComp transform proposed or accepted by the other peer
|
||||
*/
|
||||
ipcomp_transform_t ipcomp_received;
|
||||
|
||||
/**
|
||||
* Other Compression Parameter Index (CPI)
|
||||
*/
|
||||
u_int16_t other_cpi;
|
||||
|
||||
/**
|
||||
* reqid to use if we are rekeying
|
||||
*/
|
||||
@@ -326,6 +342,12 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
|
||||
}
|
||||
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
|
||||
|
||||
if (this->ipcomp != IPCOMP_NONE)
|
||||
{
|
||||
this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
|
||||
this->other_cpi);
|
||||
}
|
||||
|
||||
if (this->initiator)
|
||||
{
|
||||
status = this->child_sa->update(this->child_sa, this->proposal,
|
||||
@@ -415,6 +437,36 @@ static void build_payloads(private_child_create_t *this, message_t *message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an IPCOMP_SUPPORTED notify to the message, if possible
|
||||
*/
|
||||
static void build_ipcomp_supported_notify(private_child_create_t *this, message_t *message)
|
||||
{
|
||||
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
|
||||
{
|
||||
DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, IPComp is disabled");
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
u_int16_t cpi = this->child_sa->get_my_cpi(this->child_sa);
|
||||
if (cpi)
|
||||
{
|
||||
chunk_t cpi_chunk, tid_chunk, data;
|
||||
u_int8_t tid = this->ipcomp;
|
||||
cpi_chunk = chunk_from_thing(cpi);
|
||||
tid_chunk = chunk_from_thing(tid);
|
||||
data = chunk_cat("cc", cpi_chunk, tid_chunk);
|
||||
message->add_notify(message, FALSE, IPCOMP_SUPPORTED, data);
|
||||
chunk_free(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp is disabled");
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read payloads from message
|
||||
*/
|
||||
@@ -470,6 +522,25 @@ static void process_payloads(private_child_create_t *this, message_t *message)
|
||||
case USE_BEET_MODE:
|
||||
this->mode = MODE_BEET;
|
||||
break;
|
||||
case IPCOMP_SUPPORTED:
|
||||
{
|
||||
chunk_t data = notify_payload->get_notification_data(notify_payload);
|
||||
u_int16_t cpi = *(u_int16_t*)data.ptr;
|
||||
ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
|
||||
switch(ipcomp)
|
||||
{
|
||||
case IPCOMP_DEFLATE:
|
||||
this->other_cpi = cpi;
|
||||
this->ipcomp_received = ipcomp;
|
||||
break;
|
||||
case IPCOMP_LZS:
|
||||
case IPCOMP_LZJH:
|
||||
default:
|
||||
DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
|
||||
" ID we don't support %N", ipcomp_transform_names, ipcomp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -576,6 +647,12 @@ static status_t build_i(private_child_create_t *this, message_t *message)
|
||||
this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
|
||||
}
|
||||
|
||||
if (this->config->use_ipcomp(this->config)) {
|
||||
/* IPCOMP_DEFLATE is the only transform we support at the moment */
|
||||
this->ipcomp = IPCOMP_DEFLATE;
|
||||
build_ipcomp_supported_notify(this, message);
|
||||
}
|
||||
|
||||
build_payloads(this, message);
|
||||
|
||||
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
|
||||
@@ -693,6 +770,16 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
||||
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
|
||||
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
|
||||
|
||||
if (this->config->use_ipcomp(this->config) && this->ipcomp_received != IPCOMP_NONE)
|
||||
{
|
||||
this->ipcomp = this->ipcomp_received;
|
||||
build_ipcomp_supported_notify(this, message);
|
||||
}
|
||||
else if (this->ipcomp_received != IPCOMP_NONE)
|
||||
{
|
||||
DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify but IPComp is disabled, ignoring");
|
||||
}
|
||||
|
||||
switch (select_and_install(this, no_dh))
|
||||
{
|
||||
case SUCCESS:
|
||||
@@ -799,6 +886,25 @@ static status_t process_i(private_child_create_t *this, message_t *message)
|
||||
|
||||
process_payloads(this, message);
|
||||
|
||||
if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
|
||||
{
|
||||
SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify but we did not "
|
||||
"send one previously, no CHILD_SA built");
|
||||
return SUCCESS;
|
||||
}
|
||||
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
|
||||
"IPComp is disabled");
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
}
|
||||
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
|
||||
{
|
||||
SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify for a transform "
|
||||
"we did not propose, no CHILD_SA built");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (select_and_install(this, no_dh) == SUCCESS)
|
||||
{
|
||||
SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully",
|
||||
@@ -877,6 +983,9 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
|
||||
this->dh = NULL;
|
||||
this->child_sa = NULL;
|
||||
this->mode = MODE_TUNNEL;
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
this->ipcomp_received = IPCOMP_NONE;
|
||||
this->other_cpi = 0;
|
||||
this->reqid = 0;
|
||||
this->established = FALSE;
|
||||
}
|
||||
@@ -950,6 +1059,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
|
||||
this->dh_group = MODP_NONE;
|
||||
this->child_sa = NULL;
|
||||
this->mode = MODE_TUNNEL;
|
||||
this->ipcomp = IPCOMP_NONE;
|
||||
this->ipcomp_received = IPCOMP_NONE;
|
||||
this->other_cpi = 0;
|
||||
this->reqid = 0;
|
||||
this->established = FALSE;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user