summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev1/tasks/quick_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev1/tasks/quick_mode.c')
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c91
1 files changed, 71 insertions, 20 deletions
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 6271e5b05..12ee594b9 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -165,6 +165,11 @@ struct private_quick_mode_t {
*/
ipsec_mode_t mode;
+ /*
+ * SA protocol (ESP|AH) negotiated
+ */
+ protocol_id_t proto;
+
/**
* Use UDP encapsulation
*/
@@ -722,7 +727,7 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
notify_payload_t *notify;
notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
- PROTO_ESP, type);
+ this->proto, type);
notify->set_spi(notify, this->spi_i);
this->ike_sa->queue_task(this->ike_sa,
@@ -733,6 +738,38 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
return ALREADY_DONE;
}
+/**
+ * Prepare a list of proposals from child_config containing only the specified
+ * DH group, unless it is set to MODP_NONE.
+ */
+static linked_list_t *get_proposals(private_quick_mode_t *this,
+ diffie_hellman_group_t group)
+{
+ linked_list_t *list;
+ proposal_t *proposal;
+ enumerator_t *enumerator;
+
+ list = this->config->get_proposals(this->config, FALSE);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ if (group != MODP_NONE)
+ {
+ if (!proposal->has_dh_group(proposal, group))
+ {
+ list->remove_at(list, enumerator);
+ proposal->destroy(proposal);
+ continue;
+ }
+ proposal->strip_dh(proposal, group);
+ }
+ proposal->set_spi(proposal, this->spi_i);
+ }
+ enumerator->destroy(enumerator);
+
+ return list;
+}
+
METHOD(task_t, build_i, status_t,
private_quick_mode_t *this, message_t *message)
{
@@ -740,7 +777,6 @@ METHOD(task_t, build_i, status_t,
{
case QM_INIT:
{
- enumerator_t *enumerator;
sa_payload_t *sa_payload;
linked_list_t *list, *tsi, *tsr;
proposal_t *proposal;
@@ -770,42 +806,55 @@ METHOD(task_t, build_i, status_t,
}
}
- this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+ list = this->config->get_proposals(this->config, MODP_NONE);
+ if (list->get_first(list, (void**)&proposal) == SUCCESS)
+ {
+ this->proto = proposal->get_protocol(proposal);
+ }
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
+ this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto);
if (!this->spi_i)
{
DBG1(DBG_IKE, "allocating SPI from kernel failed");
return FAILED;
}
+
group = this->config->get_dh_group(this->config);
if (group != MODP_NONE)
{
+ proposal_t *proposal;
+ u_int16_t preferred_group;
+
+ proposal = this->ike_sa->get_proposal(this->ike_sa);
+ proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+ &preferred_group, NULL);
+ /* try the negotiated DH group from IKE_SA */
+ list = get_proposals(this, preferred_group);
+ if (list->get_count(list))
+ {
+ group = preferred_group;
+ }
+ else
+ {
+ /* fall back to the first configured DH group */
+ list->destroy(list);
+ list = get_proposals(this, group);
+ }
+
this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
group);
if (!this->dh)
{
DBG1(DBG_IKE, "configured DH group %N not supported",
diffie_hellman_group_names, group);
+ list->destroy_offset(list, offsetof(proposal_t, destroy));
return FAILED;
}
}
-
- list = this->config->get_proposals(this->config, FALSE);
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &proposal))
+ else
{
- if (group != MODP_NONE)
- {
- if (!proposal->has_dh_group(proposal, group))
- {
- list->remove_at(list, enumerator);
- proposal->destroy(proposal);
- continue;
- }
- proposal->strip_dh(proposal, group);
- }
- proposal->set_spi(proposal, this->spi_i);
+ list = get_proposals(this, MODP_NONE);
}
- enumerator->destroy(enumerator);
get_lifetimes(this);
encap = get_encap(this->ike_sa, this->udp);
@@ -1103,7 +1152,8 @@ METHOD(task_t, build_r, status_t,
sa_payload_t *sa_payload;
encap_t encap;
- this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+ this->proto = this->proposal->get_protocol(this->proposal);
+ this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto);
if (!this->spi_r)
{
DBG1(DBG_IKE, "allocating SPI from kernel failed");
@@ -1311,6 +1361,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
.state = QM_INIT,
.tsi = tsi ? tsi->clone(tsi) : NULL,
.tsr = tsr ? tsr->clone(tsr) : NULL,
+ .proto = PROTO_ESP,
);
if (config)