diff options
Diffstat (limited to 'src/libcharon/sa/ikev1')
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/aggressive_mode.c | 6 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/isakmp_natd.c | 39 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/isakmp_vendor.c | 124 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/main_mode.c | 6 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_mode.c | 65 |
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)) |