summaryrefslogtreecommitdiff
path: root/src/libcharon/encoding
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
committerYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
commit83b8aebb19fe6e49e13a05d4e8f5ab9a06177642 (patch)
tree51255545ba43b84aa5d673bd0eb557cbd0155c9e /src/libcharon/encoding
parent2b8de74ff4c334c25e89988c4a401b24b5bcf03d (diff)
downloadvyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.tar.gz
vyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.zip
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libcharon/encoding')
-rw-r--r--src/libcharon/encoding/message.c16
-rw-r--r--src/libcharon/encoding/parser.c21
-rw-r--r--src/libcharon/encoding/parser.h12
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c15
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.h10
-rw-r--r--src/libcharon/encoding/payloads/encrypted_payload.c1
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c7
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c10
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.h2
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c22
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.h2
-rw-r--r--src/libcharon/encoding/payloads/payload.c62
-rw-r--r--src/libcharon/encoding/payloads/payload.h3
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c276
14 files changed, 265 insertions, 194 deletions
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index cb6c97f25..0a596ffb0 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -180,6 +180,7 @@ static payload_order_t ike_sa_init_r_order[] = {
*/
static payload_rule_t ike_auth_i_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
{PLV2_EAP, 0, 1, TRUE, TRUE},
{PLV2_AUTH, 0, 1, TRUE, TRUE},
@@ -227,6 +228,7 @@ static payload_order_t ike_auth_i_order[] = {
{PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES},
{PLV2_NOTIFY, 0},
{PLV2_VENDOR_ID, 0},
+ {PLV2_FRAGMENT, 0},
};
/**
@@ -234,6 +236,7 @@ static payload_order_t ike_auth_i_order[] = {
*/
static payload_rule_t ike_auth_r_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
{PLV2_EAP, 0, 1, TRUE, TRUE},
{PLV2_AUTH, 0, 1, TRUE, TRUE},
@@ -270,6 +273,7 @@ static payload_order_t ike_auth_r_order[] = {
{PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES},
{PLV2_NOTIFY, 0},
{PLV2_VENDOR_ID, 0},
+ {PLV2_FRAGMENT, 0},
};
/**
@@ -277,6 +281,7 @@ static payload_order_t ike_auth_r_order[] = {
*/
static payload_rule_t informational_i_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
{PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
{PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
@@ -295,6 +300,7 @@ static payload_order_t informational_i_order[] = {
{PLV2_NOTIFY, 0},
{PLV2_DELETE, 0},
{PLV2_CONFIGURATION, 0},
+ {PLV2_FRAGMENT, 0},
};
/**
@@ -302,6 +308,7 @@ static payload_order_t informational_i_order[] = {
*/
static payload_rule_t informational_r_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
{PLV2_CONFIGURATION, 0, 1, TRUE, FALSE},
{PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE},
@@ -320,6 +327,7 @@ static payload_order_t informational_r_order[] = {
{PLV2_NOTIFY, 0},
{PLV2_DELETE, 0},
{PLV2_CONFIGURATION, 0},
+ {PLV2_FRAGMENT, 0},
};
/**
@@ -327,6 +335,7 @@ static payload_order_t informational_r_order[] = {
*/
static payload_rule_t create_child_sa_i_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE},
{PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
{PLV2_NONCE, 1, 1, TRUE, FALSE},
@@ -353,6 +362,7 @@ static payload_order_t create_child_sa_i_order[] = {
{PLV2_TS_INITIATOR, 0},
{PLV2_TS_RESPONDER, 0},
{PLV2_NOTIFY, 0},
+ {PLV2_FRAGMENT, 0},
};
/**
@@ -360,6 +370,7 @@ static payload_order_t create_child_sa_i_order[] = {
*/
static payload_rule_t create_child_sa_r_rules[] = {
/* payload type min max encr suff */
+ {PLV2_FRAGMENT, 0, 1, TRUE, TRUE},
{PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE},
{PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE},
{PLV2_NONCE, 1, 1, TRUE, FALSE},
@@ -386,6 +397,7 @@ static payload_order_t create_child_sa_r_order[] = {
{PLV2_TS_RESPONDER, 0},
{PLV2_NOTIFY, ADDITIONAL_TS_POSSIBLE},
{PLV2_NOTIFY, 0},
+ {PLV2_FRAGMENT, 0},
};
#ifdef ME
@@ -2143,6 +2155,8 @@ METHOD(message_t, parse_header, status_t,
}
ike_header->destroy(ike_header);
+ this->parser->set_major_version(this->parser, this->major_version);
+
DBG2(DBG_ENC, "parsed a %N %s header", exchange_type_names,
this->exchange_type, this->major_version == IKEV1_MAJOR_VERSION ?
"message" : (this->is_request ? "request" : "response"));
@@ -2463,7 +2477,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
was_encrypted = "encrypted fragment payload";
}
- if (payload_is_known(type) && !was_encrypted &&
+ if (payload_is_known(type, this->major_version) && !was_encrypted &&
!is_connectivity_check(this, payload) &&
this->exchange_type != AGGRESSIVE)
{
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index d6240fde2..f8340367e 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -59,6 +59,11 @@ struct private_parser_t {
parser_t public;
/**
+ * major IKE version
+ */
+ u_int8_t major_version;
+
+ /**
* Current bit for reading in input data.
*/
u_int8_t bit_pos;
@@ -369,7 +374,14 @@ METHOD(parser_t, parse_payload, status_t,
encoding_rule_t *rule;
/* create instance of the payload to parse */
- pld = payload_create(payload_type);
+ if (payload_is_known(payload_type, this->major_version))
+ {
+ pld = payload_create(payload_type);
+ }
+ else
+ {
+ pld = (payload_t*)unknown_payload_create(payload_type);
+ }
DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
payload_type_names, payload_type, this->input_roof - this->byte_pos);
@@ -629,6 +641,12 @@ METHOD(parser_t, reset_context, void,
this->bit_pos = 0;
}
+METHOD(parser_t, set_major_version, void,
+ private_parser_t *this, u_int8_t major_version)
+{
+ this->major_version = major_version;
+}
+
METHOD(parser_t, destroy, void,
private_parser_t *this)
{
@@ -646,6 +664,7 @@ parser_t *parser_create(chunk_t data)
.public = {
.parse_payload = _parse_payload,
.reset_context = _reset_context,
+ .set_major_version = _set_major_version,
.get_remaining_byte_count = _get_remaining_byte_count,
.destroy = _destroy,
},
diff --git a/src/libcharon/encoding/parser.h b/src/libcharon/encoding/parser.h
index 27c5f03fe..5fd3e86ee 100644
--- a/src/libcharon/encoding/parser.h
+++ b/src/libcharon/encoding/parser.h
@@ -29,7 +29,7 @@ typedef struct parser_t parser_t;
#include <encoding/payloads/payload.h>
/**
- * A parser_t class to parse IKEv2 payloads.
+ * A parser_t class to parse IKE payloads.
*
* A parser is used for parsing one chunk of data. Multiple
* payloads can be parsed out of the chunk using parse_payload.
@@ -50,7 +50,8 @@ struct parser_t {
* - SUCCESSFUL if succeeded,
* - PARSE_ERROR if corrupted/invalid data found
*/
- status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload);
+ status_t (*parse_payload) (parser_t *this, payload_type_t payload_type,
+ payload_t **payload);
/**
* Gets the remaining byte count which is not currently parsed.
@@ -63,6 +64,13 @@ struct parser_t {
void (*reset_context) (parser_t *this);
/**
+ * Set the major IKE version.
+ *
+ * @param major_version the major IKE version
+ */
+ void (*set_major_version) (parser_t *this, u_int8_t major_version);
+
+ /**
* Destroys a parser_t object.
*/
void (*destroy) (parser_t *this);
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
index c2ab3b951..f11ea485c 100644
--- a/src/libcharon/encoding/payloads/delete_payload.c
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
@@ -281,6 +282,19 @@ METHOD(delete_payload_t, set_ike_spi, void,
this->payload_length = get_header_length(this) + this->spi_size;
}
+METHOD(delete_payload_t, get_ike_spi, bool,
+ private_delete_payload_t *this, u_int64_t *spi_i, u_int64_t *spi_r)
+{
+ if (this->protocol_id != PROTO_IKE ||
+ this->spis.len < 2 * sizeof(u_int64_t))
+ {
+ return FALSE;
+ }
+ memcpy(spi_i, this->spis.ptr, sizeof(u_int64_t));
+ memcpy(spi_r, this->spis.ptr + sizeof(u_int64_t), sizeof(u_int64_t));
+ return TRUE;
+}
+
/**
* SPI enumerator implementation
*/
@@ -352,6 +366,7 @@ delete_payload_t *delete_payload_create(payload_type_t type,
.get_protocol_id = _get_protocol_id,
.add_spi = _add_spi,
.set_ike_spi = _set_ike_spi,
+ .get_ike_spi = _get_ike_spi,
.create_spi_enumerator = _create_spi_enumerator,
.destroy = _destroy,
},
diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h
index 46a89eab6..6728718cd 100644
--- a/src/libcharon/encoding/payloads/delete_payload.h
+++ b/src/libcharon/encoding/payloads/delete_payload.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -61,6 +62,15 @@ struct delete_payload_t {
void (*set_ike_spi)(delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r);
/**
+ * Get the IKE SPIs from an IKEv1 delete.
+ *
+ * @param spi_i initiator SPI
+ * @param spi_r responder SPI
+ * @return TRUE if SPIs extracted successfully
+ */
+ bool (*get_ike_spi)(delete_payload_t *this, u_int64_t *spi_i, u_int64_t *spi_r);
+
+ /**
* Get an enumerator over the SPIs in network order.
*
* @return enumerator over SPIs, u_int32_t
diff --git a/src/libcharon/encoding/payloads/encrypted_payload.c b/src/libcharon/encoding/payloads/encrypted_payload.c
index 5c574c34d..04372fdf0 100644
--- a/src/libcharon/encoding/payloads/encrypted_payload.c
+++ b/src/libcharon/encoding/payloads/encrypted_payload.c
@@ -561,6 +561,7 @@ static status_t parse(private_encrypted_payload_t *this, chunk_t plain)
payload_type_t type;
parser = parser_create(plain);
+ parser->set_major_version(parser, this->type == PLV1_ENCRYPTED ? 1 : 2);
type = this->next_payload;
while (type != PL_NONE)
{
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
index a002a8f21..bb8aab748 100644
--- a/src/libcharon/encoding/payloads/id_payload.c
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -258,17 +258,20 @@ static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
ts_type_t type)
{
+ traffic_selector_t *ts;
chunk_t net, netmask;
int i;
net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
- netmask = chunk_skip(this->id_data, this->id_data.len / 2);
+ netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2));
for (i = 0; i < net.len; i++)
{
netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
}
- return traffic_selector_create_from_bytes(this->protocol_id, type,
+ ts = traffic_selector_create_from_bytes(this->protocol_id, type,
net, this->port, netmask, this->port ?: 65535);
+ chunk_free(&netmask);
+ return ts;
}
/**
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
index 4f552d6ac..50fd73f90 100644
--- a/src/libcharon/encoding/payloads/ke_payload.c
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -247,9 +247,15 @@ ke_payload_t *ke_payload_create(payload_type_t type)
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
diffie_hellman_t *dh)
{
- private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type);
+ private_ke_payload_t *this;
+ chunk_t value;
- dh->get_my_public_value(dh, &this->key_exchange_data);
+ if (!dh->get_my_public_value(dh, &value))
+ {
+ return NULL;
+ }
+ this = (private_ke_payload_t*)ke_payload_create(type);
+ this->key_exchange_data = value;
this->dh_group_number = dh->get_dh_group(dh);
this->payload_length += this->key_exchange_data.len;
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
index dfc6308b4..96c5096a5 100644
--- a/src/libcharon/encoding/payloads/ke_payload.h
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -73,7 +73,7 @@ ke_payload_t *ke_payload_create(payload_type_t type);
*
* @param type PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE
* @param dh diffie hellman object containing group and key
- * @return ke_payload_t object
+ * @return ke_payload_t object, NULL on error
*/
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
diffie_hellman_t *dh);
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index 94723ddd7..f32a1273f 100644
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_
"ME_CONNECT_FAILED");
ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_NOTIFY_STATUS");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, MS_NOTIFY_STATUS,
"INITIAL_CONTACT",
"SET_WINDOW_SIZE",
"ADDITIONAL_TS_POSSIBLE",
@@ -112,8 +112,9 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY
"ERX_SUPPORTED",
"IFOM_CAPABILITY",
"SENDER_REQUEST_ID",
- "FRAGMENTATION_SUPPORTED");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED,
+ "FRAGMENTATION_SUPPORTED",
+ "SIGNATURE_HASH_ALGORITHMS");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
@@ -174,7 +175,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S
"ME_CONN_FAIL");
ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_STATUS");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, MS_NOTIFY_STATUS,
"INIT_CONTACT",
"SET_WINSIZE",
"ADD_TS_POSS",
@@ -221,8 +222,9 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_
"ERX_SUP",
"IFOM_CAP",
"SENDER_REQ_ID",
- "FRAG_SUP");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED,
+ "FRAG_SUP",
+ "HASH_ALG");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
@@ -473,6 +475,14 @@ METHOD(payload_t, verify, status_t,
}
break;
}
+ case SIGNATURE_HASH_ALGORITHMS:
+ {
+ if (this->notify_data.len % 2)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
case AUTH_LIFETIME:
{
if (this->notify_data.len != 4)
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index 25521c2bb..690757383 100644
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -151,6 +151,8 @@ enum notify_type_t {
SENDER_REQUEST_ID = 16429,
/* IKEv2 fragmentation supported, RFC 7383 */
FRAGMENTATION_SUPPORTED = 16430,
+ /* Signature Hash Algorithms, RFC 7427 */
+ SIGNATURE_HASH_ALGORITHMS = 16431,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index 600b6dd68..a1cd2f945 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -266,37 +266,51 @@ payload_t *payload_create(payload_type_t type)
/**
* See header.
*/
-bool payload_is_known(payload_type_t type)
+bool payload_is_known(payload_type_t type, u_int8_t maj_ver)
{
- if (type == PL_HEADER)
+ if (type >= PL_HEADER)
{
return TRUE;
}
- if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION)
+ switch (maj_ver)
{
- return TRUE;
- }
- if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA)
- {
- return TRUE;
- }
- if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP)
- {
- return TRUE;
- }
- if (type == PLV2_FRAGMENT)
- {
- return TRUE;
- }
+ case 0:
+ case IKEV1_MAJOR_VERSION:
+ if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION)
+ {
+ return TRUE;
+ }
+ if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA)
+ {
+ return TRUE;
+ }
+ if (type >= PLV1_NAT_D_DRAFT_00_03 && type <= PLV1_FRAGMENT)
+ {
+ return TRUE;
+ }
+ if (maj_ver)
+ {
+ break;
+ }
+ /* fall-through */
+ case IKEV2_MAJOR_VERSION:
+ if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP)
+ {
+ return TRUE;
+ }
+ if (type == PLV2_FRAGMENT)
+ {
+ return TRUE;
+ }
#ifdef ME
- if (type == PLV2_ID_PEER)
- {
- return TRUE;
- }
+ if (type == PLV2_ID_PEER)
+ {
+ return TRUE;
+ }
#endif
- if (type >= PLV1_NAT_D_DRAFT_00_03 && type <= PLV1_FRAGMENT)
- {
- return TRUE;
+ break;
+ default:
+ break;
}
return FALSE;
}
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index 036cd422d..920779bd1 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -405,9 +405,10 @@ payload_t *payload_create(payload_type_t type);
* Check if a specific payload is implemented, or handled as unknown payload.
*
* @param type type of the payload to check
+ * @param maj_ver major IKE version (use 0 to skip version check)
* @return FALSE if payload type handled as unknown payload
*/
-bool payload_is_known(payload_type_t type);
+bool payload_is_known(payload_type_t type, u_int8_t maj_ver);
/**
* Get the value field in a payload using encoding rules.
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 53e8cf3ad..48dcfeb24 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -224,26 +224,7 @@ typedef enum {
/* FreeS/WAN proprietary */
IKEV1_ESP_ENCR_SERPENT = 252,
IKEV1_ESP_ENCR_TWOFISH = 253,
-} ikev1_esp_encr_transid_t;
-
-/**
- * IKEv1 Transform ID ESP authentication algorithm.
- */
-typedef enum {
- IKEV1_ESP_AUTH_HMAC_MD5 = 1,
- IKEV1_ESP_AUTH_HMAC_SHA = 2,
- IKEV1_ESP_AUTH_DES_MAC = 3,
- IKEV1_ESP_AUTH_KPDK = 4,
- IKEV1_ESP_AUTH_HMAC_SHA2_256 = 5,
- IKEV1_ESP_AUTH_HMAC_SHA2_384 = 6,
- IKEV1_ESP_AUTH_HMAC_SHA2_512 = 7,
- IKEV1_ESP_AUTH_HMAC_RIPEMD = 8,
- IKEV1_ESP_AUTH_AES_XCBC_MAC = 9,
- IKEV1_ESP_AUTH_SIG_RSA = 10,
- IKEV1_ESP_AUTH_AES_128_GMAC = 11,
- IKEV1_ESP_AUTH_AES_192_GMAC = 12,
- IKEV1_ESP_AUTH_AES_256_GMAC = 13,
-} ikev1_esp_auth_transid_it;
+} ikev1_esp_transid_t;
/**
* IKEv1 Transform ID AH authentication algorithm.
@@ -264,6 +245,25 @@ typedef enum {
} ikev1_ah_transid_t;
/**
+ * IKEv1 authentication algorithm.
+ */
+typedef enum {
+ IKEV1_AUTH_HMAC_MD5 = 1,
+ IKEV1_AUTH_HMAC_SHA = 2,
+ IKEV1_AUTH_DES_MAC = 3,
+ IKEV1_AUTH_KPDK = 4,
+ IKEV1_AUTH_HMAC_SHA2_256 = 5,
+ IKEV1_AUTH_HMAC_SHA2_384 = 6,
+ IKEV1_AUTH_HMAC_SHA2_512 = 7,
+ IKEV1_AUTH_HMAC_RIPEMD = 8,
+ IKEV1_AUTH_AES_XCBC_MAC = 9,
+ IKEV1_AUTH_SIG_RSA = 10,
+ IKEV1_AUTH_AES_128_GMAC = 11,
+ IKEV1_AUTH_AES_192_GMAC = 12,
+ IKEV1_AUTH_AES_256_GMAC = 13,
+} ikev1_auth_algo_t;
+
+/**
* IKEv1 ESP Encapsulation mode.
*/
typedef enum {
@@ -345,7 +345,7 @@ METHOD(payload_t, verify, status_t,
switch (this->protocol_id)
{
case PROTO_IPCOMP:
- if (this->spi.len != 2)
+ if (this->spi.len != 2 && this->spi.len != 4)
{
DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
return FAILED;
@@ -536,7 +536,7 @@ METHOD(proposal_substructure_t, get_cpi, bool,
{
if (cpi)
{
- *cpi = *((u_int16_t*)this->spi.ptr);
+ *cpi = htons(untoh16(this->spi.ptr + this->spi.len - 2));
}
enumerator->destroy(enumerator);
return TRUE;
@@ -620,7 +620,7 @@ static algo_map_t map_prf[] = {
/**
* ESP encryption algorithm mapping
*/
-static algo_map_t map_esp_encr[] = {
+static algo_map_t map_esp[] = {
{ IKEV1_ESP_ENCR_DES_IV64, ENCR_DES_IV64 },
{ IKEV1_ESP_ENCR_DES, ENCR_DES },
{ IKEV1_ESP_ENCR_3DES, ENCR_3DES },
@@ -646,23 +646,6 @@ static algo_map_t map_esp_encr[] = {
};
/**
- * ESP authentication algorithm mapping
- */
-static algo_map_t map_esp_auth[] = {
- { IKEV1_ESP_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 },
- { IKEV1_ESP_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
- { IKEV1_ESP_AUTH_DES_MAC, AUTH_DES_MAC },
- { IKEV1_ESP_AUTH_KPDK, AUTH_KPDK_MD5 },
- { IKEV1_ESP_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
- { IKEV1_ESP_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
- { IKEV1_ESP_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
- { IKEV1_ESP_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
- { IKEV1_ESP_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC },
- { IKEV1_ESP_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC },
- { IKEV1_ESP_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
-};
-
-/**
* AH authentication algorithm mapping
*/
static algo_map_t map_ah[] = {
@@ -679,34 +662,30 @@ static algo_map_t map_ah[] = {
};
/**
- * Get IKEv2 algorithm from IKEv1 identifier
+ * ESP/AH authentication algorithm mapping
*/
-static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
+static algo_map_t map_auth[] = {
+ { IKEV1_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 },
+ { IKEV1_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
+ { IKEV1_AUTH_DES_MAC, AUTH_DES_MAC },
+ { IKEV1_AUTH_KPDK, AUTH_KPDK_MD5 },
+ { IKEV1_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
+ { IKEV1_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
+ { IKEV1_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
+ { IKEV1_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
+ { IKEV1_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC },
+ { IKEV1_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC },
+ { IKEV1_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
+};
+
+/**
+ * Map an IKEv1 to an IKEv2 identifier
+ */
+static u_int16_t ikev2_from_ikev1(algo_map_t *map, int count, u_int16_t def,
+ u_int16_t value)
{
- algo_map_t *map;
- u_int16_t def;
- int i, count;
+ int i;
- switch (type)
- {
- case ENCRYPTION_ALGORITHM:
- map = map_encr;
- count = countof(map_encr);
- def = ENCR_UNDEFINED;
- break;
- case INTEGRITY_ALGORITHM:
- map = map_integ;
- count = countof(map_integ);
- def = AUTH_UNDEFINED;
- break;
- case PSEUDO_RANDOM_FUNCTION:
- map = map_prf;
- count = countof(map_prf);
- def = PRF_UNDEFINED;
- break;
- default:
- return 0;
- }
for (i = 0; i < count; i++)
{
if (map[i].ikev1 == value)
@@ -718,30 +697,12 @@ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
}
/**
- * Get IKEv1 algorithm from IKEv2 identifier
+ * Map an IKEv2 to an IKEv1 identifier
*/
-static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
+static u_int16_t ikev1_from_ikev2(algo_map_t *map, int count, u_int16_t value)
{
- algo_map_t *map;
- int i, count;
+ int i;
- switch (type)
- {
- case ENCRYPTION_ALGORITHM:
- map = map_encr;
- count = countof(map_encr);
- break;
- case INTEGRITY_ALGORITHM:
- map = map_integ;
- count = countof(map_integ);
- break;
- case PSEUDO_RANDOM_FUNCTION:
- map = map_prf;
- count = countof(map_prf);
- break;
- default:
- return 0;
- }
for (i = 0; i < count; i++)
{
if (map[i].ikev2 == value)
@@ -753,87 +714,96 @@ static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
}
/**
- * Get IKEv2 algorithm from IKEv1 ESP transaction ID
+ * Get IKEv2 algorithm from IKEv1 identifier
*/
-static u_int16_t get_alg_from_ikev1_transid(protocol_id_t proto,
- transform_type_t type, u_int16_t value)
+static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value)
{
- algo_map_t *map;
- u_int16_t def;
- int i, count;
-
switch (type)
{
case ENCRYPTION_ALGORITHM:
- map = map_esp_encr;
- count = countof(map_esp_encr);
- def = ENCR_UNDEFINED;
- break;
+ return ikev2_from_ikev1(map_encr, countof(map_encr),
+ ENCR_UNDEFINED, value);
case INTEGRITY_ALGORITHM:
- if (proto == PROTO_ESP)
- {
- map = map_esp_auth;
- count = countof(map_esp_auth);
- }
- else
- {
- map = map_ah;
- count = countof(map_ah);
- }
- def = AUTH_UNDEFINED;
- break;
+ return ikev2_from_ikev1(map_integ, countof(map_integ),
+ AUTH_UNDEFINED, value);
+ case PSEUDO_RANDOM_FUNCTION:
+ return ikev2_from_ikev1(map_prf, countof(map_prf),
+ PRF_UNDEFINED, value);
default:
return 0;
}
- for (i = 0; i < count; i++)
+}
+
+/**
+ * Get IKEv1 algorithm from IKEv2 identifier
+ */
+static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value)
+{
+ switch (type)
{
- if (map[i].ikev1 == value)
- {
- return map[i].ikev2;
- }
+ case ENCRYPTION_ALGORITHM:
+ return ikev1_from_ikev2(map_encr, countof(map_encr), value);
+ case INTEGRITY_ALGORITHM:
+ return ikev1_from_ikev2(map_integ, countof(map_integ), value);
+ case PSEUDO_RANDOM_FUNCTION:
+ return ikev1_from_ikev2(map_prf, countof(map_prf), value);
+ default:
+ return 0;
}
- return def;
}
/**
- * Get IKEv1 ESP/AH transaction ID from IKEv2 identifier
+ * Get IKEv2 algorithm from IKEv1 ESP/AH transform ID
*/
-static u_int16_t get_ikev1_transid_from_alg(protocol_id_t proto,
- transform_type_t type, u_int16_t value)
+static u_int16_t get_alg_from_ikev1_transid(transform_type_t type,
+ u_int16_t value)
{
- algo_map_t *map;
- int i, count;
-
switch (type)
{
case ENCRYPTION_ALGORITHM:
- map = map_esp_encr;
- count = countof(map_esp_encr);
- break;
+ return ikev2_from_ikev1(map_esp, countof(map_esp),
+ ENCR_UNDEFINED, value);
case INTEGRITY_ALGORITHM:
- if (proto == PROTO_ESP)
- {
- map = map_esp_auth;
- count = countof(map_esp_auth);
- }
- else
- {
- map = map_ah;
- count = countof(map_ah);
- }
- break;
+ return ikev2_from_ikev1(map_ah, countof(map_ah),
+ AUTH_UNDEFINED, value);
default:
return 0;
}
- for (i = 0; i < count; i++)
+}
+
+/**
+ * Get IKEv1 ESP/AH transform ID from IKEv2 identifier
+ */
+static u_int16_t get_ikev1_transid_from_alg(transform_type_t type,
+ u_int16_t value)
+{
+ switch (type)
{
- if (map[i].ikev2 == value)
- {
- return map[i].ikev1;
- }
+ case ENCRYPTION_ALGORITHM:
+ return ikev1_from_ikev2(map_esp, countof(map_esp), value);
+ case INTEGRITY_ALGORITHM:
+ return ikev1_from_ikev2(map_ah, countof(map_ah), value);
+ default:
+ return 0;
}
- return 0;
}
+
+/**
+ * Get IKEv1 authentication algorithm from IKEv2 identifier
+ */
+static u_int16_t get_alg_from_ikev1_auth(u_int16_t value)
+{
+ return ikev2_from_ikev1(map_auth, countof(map_auth), AUTH_UNDEFINED, value);
+}
+
+/**
+ * Get IKEv1 authentication algorithm from IKEv2 identifier
+ */
+static u_int16_t get_ikev1_auth_from_alg(u_int16_t value)
+{
+ return ikev1_from_ikev2(map_auth, countof(map_auth), value);
+}
+
/**
* Get IKEv1 authentication attribute from auth_method_t
*/
@@ -971,8 +941,7 @@ static void add_to_proposal_v1(proposal_t *proposal,
break;
case TATTR_PH2_AUTH_ALGORITHM:
proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
- get_alg_from_ikev1_transid(proto, INTEGRITY_ALGORITHM,
- value), 0);
+ get_alg_from_ikev1_auth(value), 0);
break;
case TATTR_PH2_GROUP:
proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
@@ -989,7 +958,7 @@ static void add_to_proposal_v1(proposal_t *proposal,
NO_EXT_SEQ_NUMBERS, 0);
if (proto == PROTO_ESP)
{
- encr = get_alg_from_ikev1_transid(proto, ENCRYPTION_ALGORITHM,
+ encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
transform->get_transform_id(transform));
if (encr)
{
@@ -1354,19 +1323,17 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
ipsec_mode_t mode, encap_t udp, int number)
{
transform_substructure_t *transform = NULL;
- u_int16_t alg, key_size;
+ u_int16_t alg, transid, key_size;
enumerator_t *enumerator;
- protocol_id_t proto;
- proto = proposal->get_protocol(proposal);
enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
if (enumerator->enumerate(enumerator, &alg, &key_size))
{
- alg = get_ikev1_transid_from_alg(proto, ENCRYPTION_ALGORITHM, alg);
- if (alg)
+ transid = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
+ if (transid)
{
transform = transform_substructure_create_type(
- PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
+ PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
if (key_size)
{
transform->add_transform_attribute(transform,
@@ -1380,13 +1347,14 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
if (enumerator->enumerate(enumerator, &alg, &key_size))
{
- alg = get_ikev1_transid_from_alg(proto, INTEGRITY_ALGORITHM, alg);
- if (alg)
+ transid = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
+ alg = get_ikev1_auth_from_alg(alg);
+ if (transid && alg)
{
if (!transform)
{
transform = transform_substructure_create_type(
- PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
+ PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
}
transform->add_transform_attribute(transform,
transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,