Install negotiated IKEv1 CHILD_SA negotiated in quick mode
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <daemon.h>
|
||||
#include <sa/keymat_v1.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
#include <encoding/payloads/id_payload.h>
|
||||
@@ -39,6 +40,11 @@ struct private_quick_mode_t {
|
||||
*/
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
/**
|
||||
* TRUE if we are initiating quick mode
|
||||
*/
|
||||
bool initiator;
|
||||
|
||||
/**
|
||||
* Traffic selector of initiator
|
||||
*/
|
||||
@@ -59,6 +65,16 @@ struct private_quick_mode_t {
|
||||
*/
|
||||
chunk_t nonce_r;
|
||||
|
||||
/**
|
||||
* Initiators ESP SPI
|
||||
*/
|
||||
u_int32_t spi_i;
|
||||
|
||||
/**
|
||||
* Responder ESP SPI
|
||||
*/
|
||||
u_int32_t spi_r;
|
||||
|
||||
/**
|
||||
* selected CHILD_SA proposal
|
||||
*/
|
||||
@@ -74,6 +90,11 @@ struct private_quick_mode_t {
|
||||
*/
|
||||
child_sa_t *child_sa;
|
||||
|
||||
/**
|
||||
* IKEv1 keymat
|
||||
*/
|
||||
keymat_v1_t *keymat;
|
||||
|
||||
/** states of quick mode */
|
||||
enum {
|
||||
QM_INIT,
|
||||
@@ -81,6 +102,100 @@ struct private_quick_mode_t {
|
||||
} state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Install negotiated CHILD_SA
|
||||
*/
|
||||
static bool install(private_quick_mode_t *this)
|
||||
{
|
||||
status_t status, status_i, status_o;
|
||||
chunk_t encr_i, encr_r, integ_i, integ_r;
|
||||
linked_list_t *tsi, *tsr;
|
||||
|
||||
this->child_sa->set_proposal(this->child_sa, this->proposal);
|
||||
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
|
||||
this->child_sa->set_mode(this->child_sa, MODE_TUNNEL);
|
||||
this->child_sa->set_protocol(this->child_sa,
|
||||
this->proposal->get_protocol(this->proposal));
|
||||
|
||||
status_i = status_o = FAILED;
|
||||
encr_i = encr_r = integ_i = integ_r = chunk_empty;
|
||||
tsi = linked_list_create();
|
||||
tsr = linked_list_create();
|
||||
tsi->insert_last(tsi, this->tsi);
|
||||
tsr->insert_last(tsr, this->tsr);
|
||||
if (this->keymat->derive_child_keys(this->keymat, this->proposal, NULL,
|
||||
this->nonce_i, this->nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
|
||||
{
|
||||
if (this->initiator)
|
||||
{
|
||||
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
||||
this->spi_i, 0, TRUE, FALSE, tsi, tsr);
|
||||
status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
||||
this->spi_r, 0, FALSE, FALSE, tsi, tsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
||||
this->spi_r, 0, TRUE, FALSE, tsr, tsi);
|
||||
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
||||
this->spi_i, 0, FALSE, FALSE, tsr, tsi);
|
||||
}
|
||||
}
|
||||
chunk_clear(&integ_i);
|
||||
chunk_clear(&integ_r);
|
||||
chunk_clear(&encr_i);
|
||||
chunk_clear(&encr_r);
|
||||
|
||||
if (status_i != SUCCESS || status_o != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
|
||||
(status_i != SUCCESS) ? "inbound " : "",
|
||||
(status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
|
||||
(status_o != SUCCESS) ? "outbound " : "");
|
||||
tsi->destroy(tsi);
|
||||
tsr->destroy(tsr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (this->initiator)
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
|
||||
}
|
||||
tsi->destroy(tsi);
|
||||
tsr->destroy(tsr);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
|
||||
NULL, this->nonce_i, this->nonce_r);
|
||||
|
||||
/* add to IKE_SA, and remove from task */
|
||||
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
|
||||
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
|
||||
|
||||
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
|
||||
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
|
||||
this->child_sa->get_name(this->child_sa),
|
||||
this->child_sa->get_reqid(this->child_sa),
|
||||
ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
|
||||
ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
|
||||
this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
|
||||
this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
|
||||
|
||||
charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
|
||||
|
||||
this->child_sa = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(task_t, build_i, status_t,
|
||||
private_quick_mode_t *this, message_t *message)
|
||||
{
|
||||
@@ -88,14 +203,35 @@ METHOD(task_t, build_i, status_t,
|
||||
{
|
||||
case QM_INIT:
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
sa_payload_t *sa_payload;
|
||||
nonce_payload_t *nonce_payload;
|
||||
id_payload_t *id_payload;
|
||||
traffic_selector_t *ts;
|
||||
linked_list_t *list;
|
||||
proposal_t *proposal;
|
||||
rng_t *rng;
|
||||
|
||||
this->child_sa = child_sa_create(
|
||||
this->ike_sa->get_my_host(this->ike_sa),
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->config, 0, FALSE);
|
||||
|
||||
list = this->config->get_proposals(this->config, TRUE);
|
||||
|
||||
this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
|
||||
if (!this->spi_i)
|
||||
{
|
||||
DBG1(DBG_IKE, "allocating SPI from kernel failed");
|
||||
return FAILED;
|
||||
}
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &proposal))
|
||||
{
|
||||
proposal->set_spi(proposal, this->spi_i);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
sa_payload = sa_payload_create_from_proposal_list(
|
||||
SECURITY_ASSOCIATION_V1, list);
|
||||
list->destroy_offset(list, offsetof(proposal_t, destroy));
|
||||
@@ -234,6 +370,7 @@ METHOD(task_t, process_r, status_t,
|
||||
DBG1(DBG_IKE, "no matching proposal found");
|
||||
return FAILED;
|
||||
}
|
||||
this->spi_i = this->proposal->get_spi(this->proposal);
|
||||
|
||||
nonce_payload = (nonce_payload_t*)message->get_payload(message,
|
||||
NONCE_V1);
|
||||
@@ -246,12 +383,21 @@ METHOD(task_t, process_r, status_t,
|
||||
|
||||
/* TODO-IKEv1: verify HASH(1) */
|
||||
|
||||
this->child_sa = child_sa_create(
|
||||
this->ike_sa->get_my_host(this->ike_sa),
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->config, 0, FALSE);
|
||||
return NEED_MORE;
|
||||
}
|
||||
case QM_NEGOTIATED:
|
||||
{
|
||||
/* TODO-IKEv1: verify HASH(3) */
|
||||
|
||||
if (!install(this))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
default:
|
||||
@@ -271,6 +417,14 @@ METHOD(task_t, build_r, status_t,
|
||||
id_payload_t *id_payload;
|
||||
rng_t *rng;
|
||||
|
||||
this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
|
||||
if (!this->spi_r)
|
||||
{
|
||||
DBG1(DBG_IKE, "allocating SPI from kernel failed");
|
||||
return FAILED;
|
||||
}
|
||||
this->proposal->set_spi(this->proposal, this->spi_r);
|
||||
|
||||
sa_payload = sa_payload_create_from_proposal(
|
||||
SECURITY_ASSOCIATION_V1, this->proposal);
|
||||
message->add_payload(message, &sa_payload->payload_interface);
|
||||
@@ -370,6 +524,8 @@ METHOD(task_t, process_i, status_t,
|
||||
DBG1(DBG_IKE, "no matching proposal found");
|
||||
return FAILED;
|
||||
}
|
||||
this->spi_r = this->proposal->get_spi(this->proposal);
|
||||
|
||||
nonce_payload = (nonce_payload_t*)message->get_payload(message,
|
||||
NONCE_V1);
|
||||
if (!nonce_payload)
|
||||
@@ -381,6 +537,11 @@ METHOD(task_t, process_i, status_t,
|
||||
|
||||
/* TODO-IKEv1: verify HASH(2) */
|
||||
|
||||
if (!install(this))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
this->state = QM_NEGOTIATED;
|
||||
return NEED_MORE;
|
||||
}
|
||||
@@ -431,7 +592,9 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
|
||||
},
|
||||
},
|
||||
.ike_sa = ike_sa,
|
||||
.initiator = config != NULL,
|
||||
.config = config,
|
||||
.keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
|
||||
.state = QM_INIT,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user