aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/sa/ikev1
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev1')
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c6
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_natd.c39
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.c124
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c6
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c65
5 files changed, 204 insertions, 36 deletions
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 954dea880..7336d5d64 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -235,7 +235,8 @@ METHOD(task_t, build_i, status_t,
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = this->ike_cfg->get_proposals(this->ike_cfg);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
- this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ this->lifetime, 0, this->method, MODE_NONE,
+ ENCAP_NONE, 0);
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -520,7 +521,8 @@ METHOD(task_t, build_r, status_t,
identification_t *id;
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
- this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ this->lifetime, 0, this->method, MODE_NONE,
+ ENCAP_NONE, 0);
message->add_payload(message, &sa_payload->payload_interface);
if (!this->ph1->add_nonce_ke(this->ph1, message))
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
index 50bf1612d..5a71c34d8 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -15,6 +15,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 "isakmp_natd.h"
#include <string.h>
@@ -75,6 +97,18 @@ struct private_isakmp_natd_t {
};
/**
+ * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
+ */
+static payload_type_t get_nat_d_payload_type(ike_sa_t *ike_sa)
+{
+ if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
+ {
+ return NAT_D_DRAFT_00_03_V1;
+ }
+ return NAT_D_V1;
+}
+
+/**
* Build NAT detection hash for a host.
*/
static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
@@ -162,7 +196,7 @@ static hash_payload_t *build_natd_payload(private_isakmp_natd_t *this, bool src,
{
return NULL;
}
- payload = hash_payload_create(NAT_D_V1);
+ payload = hash_payload_create(get_nat_d_payload_type(this->ike_sa));
payload->set_hash(payload, hash);
chunk_free(&hash);
return payload;
@@ -221,7 +255,8 @@ static void process_payloads(private_isakmp_natd_t *this, message_t *message)
enumerator = message->create_payload_enumerator(message);
while (enumerator->enumerate(enumerator, &payload))
{
- if (payload->get_type(payload) != NAT_D_V1)
+ if (payload->get_type(payload) != NAT_D_V1 &&
+ payload->get_type(payload) != NAT_D_DRAFT_00_03_V1)
{
continue;
}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
index 4c6f823f4..506d05b87 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -13,6 +13,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 "isakmp_vendor.h"
#include <daemon.h>
@@ -39,6 +61,11 @@ struct private_isakmp_vendor_t {
* Are we the inititator of this task
*/
bool initiator;
+
+ /**
+ * Index of best nat traversal VID found
+ */
+ int best_natt_ext;
};
/**
@@ -65,52 +92,59 @@ static struct {
{ "XAuth", EXT_XAUTH, TRUE, 8,
"\x09\x00\x26\x89\xdf\xd6\xb7\x12"},
- /* NAT-Traversal, MD5("RFC 3947") */
- { "NAT-T (RFC 3947)", EXT_NATT, TRUE, 16,
- "\x4a\x13\x1c\x81\x07\x03\x58\x45\x5c\x57\x28\xf2\x0e\x95\x45\x2f"},
-
/* Dead peer detection, RFC 3706 */
{ "DPD", EXT_DPD, TRUE, 16,
"\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"},
- { "draft-stenberg-ipsec-nat-traversal-01", 0, FALSE, 16,
- "\x27\xba\xb5\xdc\x01\xea\x07\x60\xea\x4e\x31\x90\xac\x27\xc0\xd0"},
+ { "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
+ "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
- { "draft-stenberg-ipsec-nat-traversal-02", 0, FALSE, 16,
- "\x61\x05\xc4\x22\xe7\x68\x47\xe4\x3f\x96\x84\x80\x12\x92\xae\xcd"},
+}, vendor_natt_ids[] = {
- { "draft-ietf-ipsec-nat-t-ike", 0, FALSE, 16,
- "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62"},
+ /* NAT-Traversal VIDs ordered by preference */
- { "draft-ietf-ipsec-nat-t-ike-00", 0, FALSE, 16,
- "\x44\x85\x15\x2d\x18\xb6\xbb\xcd\x0b\xe8\xa8\x46\x95\x79\xdd\xcc"},
+ /* NAT-Traversal, MD5("RFC 3947") */
+ { "NAT-T (RFC 3947)", EXT_NATT, TRUE, 16,
+ "\x4a\x13\x1c\x81\x07\x03\x58\x45\x5c\x57\x28\xf2\x0e\x95\x45\x2f"},
+
+ { "draft-ietf-ipsec-nat-t-ike-03", EXT_NATT | EXT_NATT_DRAFT_02_03,
+ FALSE, 16,
+ "\x7d\x94\x19\xa6\x53\x10\xca\x6f\x2c\x17\x9d\x92\x15\x52\x9d\x56"},
- { "draft-ietf-ipsec-nat-t-ike-02", 0, FALSE, 16,
+ { "draft-ietf-ipsec-nat-t-ike-02", EXT_NATT | EXT_NATT_DRAFT_02_03,
+ FALSE, 16,
"\xcd\x60\x46\x43\x35\xdf\x21\xf8\x7c\xfd\xb2\xfc\x68\xb6\xa4\x48"},
- { "draft-ietf-ipsec-nat-t-ike-02\\n", 0, FALSE, 16,
+ { "draft-ietf-ipsec-nat-t-ike-02\\n", EXT_NATT | EXT_NATT_DRAFT_02_03,
+ TRUE, 16,
"\x90\xcb\x80\x91\x3e\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f"},
- { "draft-ietf-ipsec-nat-t-ike-03", 0, FALSE, 16,
- "\x7d\x94\x19\xa6\x53\x10\xca\x6f\x2c\x17\x9d\x92\x15\x52\x9d\x56"},
+ { "draft-ietf-ipsec-nat-t-ike-08", 0, FALSE, 16,
+ "\x8f\x8d\x83\x82\x6d\x24\x6b\x6f\xc7\xa8\xa6\xa4\x28\xc1\x1d\xe8"},
- { "draft-ietf-ipsec-nat-t-ike-04", 0, FALSE, 16,
- "\x99\x09\xb6\x4e\xed\x93\x7c\x65\x73\xde\x52\xac\xe9\x52\xfa\x6b"},
+ { "draft-ietf-ipsec-nat-t-ike-07", 0, FALSE, 16,
+ "\x43\x9b\x59\xf8\xba\x67\x6c\x4c\x77\x37\xae\x22\xea\xb8\xf5\x82"},
+
+ { "draft-ietf-ipsec-nat-t-ike-06", 0, FALSE, 16,
+ "\x4d\x1e\x0e\x13\x6d\xea\xfa\x34\xc4\xf3\xea\x9f\x02\xec\x72\x85"},
{ "draft-ietf-ipsec-nat-t-ike-05", 0, FALSE, 16,
"\x80\xd0\xbb\x3d\xef\x54\x56\x5e\xe8\x46\x45\xd4\xc8\x5c\xe3\xee"},
- { "draft-ietf-ipsec-nat-t-ike-06", 0, FALSE, 16,
- "\x4d\x1e\x0e\x13\x6d\xea\xfa\x34\xc4\xf3\xea\x9f\x02\xec\x72\x85"},
+ { "draft-ietf-ipsec-nat-t-ike-04", 0, FALSE, 16,
+ "\x99\x09\xb6\x4e\xed\x93\x7c\x65\x73\xde\x52\xac\xe9\x52\xfa\x6b"},
- { "draft-ietf-ipsec-nat-t-ike-07", 0, FALSE, 16,
- "\x43\x9b\x59\xf8\xba\x67\x6c\x4c\x77\x37\xae\x22\xea\xb8\xf5\x82"},
+ { "draft-ietf-ipsec-nat-t-ike-00", 0, FALSE, 16,
+ "\x44\x85\x15\x2d\x18\xb6\xbb\xcd\x0b\xe8\xa8\x46\x95\x79\xdd\xcc"},
- { "draft-ietf-ipsec-nat-t-ike-08", 0, FALSE, 16,
- "\x8f\x8d\x83\x82\x6d\x24\x6b\x6f\xc7\xa8\xa6\xa4\x28\xc1\x1d\xe8"},
+ { "draft-ietf-ipsec-nat-t-ike", 0, FALSE, 16,
+ "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62"},
- { "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
- "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
+ { "draft-stenberg-ipsec-nat-traversal-02", 0, FALSE, 16,
+ "\x61\x05\xc4\x22\xe7\x68\x47\xe4\x3f\x96\x84\x80\x12\x92\xae\xcd"},
+
+ { "draft-stenberg-ipsec-nat-traversal-01", 0, FALSE, 16,
+ "\x27\xba\xb5\xdc\x01\xea\x07\x60\xea\x4e\x31\x90\xac\x27\xc0\xd0"},
};
METHOD(task_t, build, status_t,
@@ -136,6 +170,17 @@ METHOD(task_t, build, status_t,
message->add_payload(message, &vid_payload->payload_interface);
}
}
+ for (i = 0; i < countof(vendor_natt_ids); i++)
+ {
+ if (this->initiator && vendor_natt_ids[i].send ||
+ this->best_natt_ext == i)
+ {
+ vid_payload = vendor_id_payload_create_data(VENDOR_ID_V1,
+ chunk_clone(chunk_create(vendor_natt_ids[i].id,
+ vendor_natt_ids[i].len)));
+ message->add_payload(message, &vid_payload->payload_interface);
+ }
+ }
return this->initiator ? NEED_MORE : SUCCESS;
}
@@ -170,6 +215,26 @@ METHOD(task_t, process, status_t,
vendor_ids[i].extension);
}
found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ {
+ for (i = 0; i < countof(vendor_natt_ids); i++)
+ {
+ if (chunk_equals(data, chunk_create(vendor_natt_ids[i].id,
+ vendor_natt_ids[i].len)))
+ {
+ DBG1(DBG_IKE, "received %s vendor ID",
+ vendor_natt_ids[i].desc);
+ if (vendor_natt_ids[i].extension &&
+ (i < this->best_natt_ext || this->best_natt_ext < 0))
+ {
+ this->best_natt_ext = i;
+ }
+ found = TRUE;
+ break;
+ }
}
}
if (!found)
@@ -180,6 +245,12 @@ METHOD(task_t, process, status_t,
}
enumerator->destroy(enumerator);
+ if (this->best_natt_ext >= 0)
+ {
+ this->ike_sa->enable_extension(this->ike_sa,
+ vendor_natt_ids[this->best_natt_ext].extension);
+ }
+
return this->initiator ? SUCCESS : NEED_MORE;
}
@@ -220,6 +291,7 @@ isakmp_vendor_t *isakmp_vendor_create(ike_sa_t *ike_sa, bool initiator)
},
.initiator = initiator,
.ike_sa = ike_sa,
+ .best_natt_ext = -1,
);
return &this->public;
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 9ccf9abf5..bc9d4bbc3 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -241,7 +241,8 @@ METHOD(task_t, build_i, status_t,
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = this->ike_cfg->get_proposals(this->ike_cfg);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
- this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ this->lifetime, 0, this->method, MODE_NONE,
+ ENCAP_NONE, 0);
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -455,7 +456,8 @@ METHOD(task_t, build_r, status_t,
sa_payload_t *sa_payload;
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
- this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
+ this->lifetime, 0, this->method, MODE_NONE,
+ ENCAP_NONE, 0);
message->add_payload(message, &sa_payload->payload_interface);
return NEED_MORE;
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 86ddcc9d9..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>
@@ -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);
@@ -767,9 +821,10 @@ METHOD(task_t, build_i, status_t,
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);
@@ -1060,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)
@@ -1086,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))