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.c103
1 files changed, 86 insertions, 17 deletions
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 82a7238c3..1eae6aa93 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -16,6 +16,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2012 Volker RĂ¼melin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "quick_mode.h"
#include <string.h>
@@ -561,7 +583,7 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
}
- if (!this->initiator && this->mode == MODE_TRANSPORT && this->udp &&
+ if (this->mode == MODE_TRANSPORT && this->udp &&
(!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
{ /* change TS in case of a NAT in transport mode */
DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
@@ -572,11 +594,11 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
if (this->initiator)
{
- /* check if peer selection valid */
+ /* check if peer selection is valid */
if (!tsr->is_contained_in(tsr, this->tsr) ||
!tsi->is_contained_in(tsi, this->tsi))
{
- DBG1(DBG_IKE, "peer selected invalid traffic selectors: ",
+ DBG1(DBG_IKE, "peer selected invalid traffic selectors: "
"%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
tsi->destroy(tsi);
tsr->destroy(tsr);
@@ -596,6 +618,34 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
}
/**
+ * Get encap
+ */
+static encap_t get_encap(ike_sa_t* ike_sa, bool udp)
+{
+ if (!udp)
+ {
+ return ENCAP_NONE;
+ }
+ if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
+ {
+ return ENCAP_UDP_DRAFT_00_03;
+ }
+ return ENCAP_UDP;
+}
+
+/**
+ * Get NAT-OA payload type (RFC 3947 or RFC 3947 drafts).
+ */
+static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
+{
+ if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
+ {
+ return NAT_OA_DRAFT_00_03_V1;
+ }
+ return NAT_OA_V1;
+}
+
+/**
* Add NAT-OA payloads
*/
static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
@@ -603,6 +653,7 @@ static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
identification_t *id;
id_payload_t *nat_oa;
host_t *src, *dst;
+ payload_type_t nat_oa_payload_type;
src = message->get_source(message);
dst = message->get_destination(message);
@@ -610,15 +661,17 @@ static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
src = this->initiator ? src : dst;
dst = this->initiator ? dst : src;
+ nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
+
/* first NAT-OA is the initiator's address */
id = identification_create_from_sockaddr(src->get_sockaddr(src));
- nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
+ nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
message->add_payload(message, (payload_t*)nat_oa);
id->destroy(id);
/* second NAT-OA is that of the responder */
id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
- nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
+ nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
message->add_payload(message, (payload_t*)nat_oa);
id->destroy(id);
}
@@ -697,6 +750,7 @@ METHOD(task_t, build_i, status_t,
linked_list_t *list, *tsi, *tsr;
proposal_t *proposal;
diffie_hellman_group_t group;
+ encap_t encap;
this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
this->mode = this->config->get_mode(this->config);
@@ -735,19 +789,42 @@ METHOD(task_t, build_i, status_t,
DBG1(DBG_IKE, "allocating SPI from kernel failed");
return FAILED;
}
+ group = this->config->get_dh_group(this->config);
+ if (group != MODP_NONE)
+ {
+ 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);
+ return FAILED;
+ }
+ }
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);
get_lifetimes(this);
+ encap = get_encap(this->ike_sa, this->udp);
sa_payload = sa_payload_create_from_proposals_v1(list,
this->lifetime, this->lifebytes, AUTH_NONE,
- this->mode, this->udp, this->cpi_i);
+ this->mode, encap, this->cpi_i);
list->destroy_offset(list, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -755,18 +832,8 @@ METHOD(task_t, build_i, status_t,
{
return FAILED;
}
-
- group = this->config->get_dh_group(this->config);
if (group != MODP_NONE)
{
- 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);
- return FAILED;
- }
add_ke(this, message);
}
if (!this->tsi)
@@ -1048,6 +1115,7 @@ METHOD(task_t, build_r, status_t,
case QM_INIT:
{
sa_payload_t *sa_payload;
+ encap_t encap;
this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
if (!this->spi_r)
@@ -1074,9 +1142,10 @@ METHOD(task_t, build_r, status_t,
add_nat_oa_payloads(this, message);
}
+ encap = get_encap(this->ike_sa, this->udp);
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
this->lifetime, this->lifebytes, AUTH_NONE,
- this->mode, this->udp, this->cpi_r);
+ this->mode, encap, this->cpi_r);
message->add_payload(message, &sa_payload->payload_interface);
if (!add_nonce(this, &this->nonce_r, message))