aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2012-07-13 15:23:00 +0200
committerTobias Brunner <tobias@strongswan.org>2012-08-08 15:41:03 +0200
commitb37758c41eb3137a4398847e729d6fa3d70617a6 (patch)
tree5e740c45f9d75f7b2bd286e8fb5827cef3124d69 /src
parent2e1a19136d8123e5a8c9aa99afbb4a51d92ec2a6 (diff)
downloadstrongswan-b37758c41eb3137a4398847e729d6fa3d70617a6.tar.bz2
strongswan-b37758c41eb3137a4398847e729d6fa3d70617a6.tar.xz
Represent the payload of an ESP packet as ip_packet_t instead of a chunk_t
Diffstat (limited to 'src')
-rw-r--r--src/libipsec/esp_packet.c94
-rw-r--r--src/libipsec/esp_packet.h23
2 files changed, 76 insertions, 41 deletions
diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c
index 75d8a7a94..bfcab95eb 100644
--- a/src/libipsec/esp_packet.c
+++ b/src/libipsec/esp_packet.c
@@ -47,7 +47,7 @@ struct private_esp_packet_t {
/**
* Payload of this packet
*/
- chunk_t payload;
+ ip_packet_t *payload;
/**
* Next Header info (e.g. IPPROTO_IPIP)
@@ -59,7 +59,7 @@ struct private_esp_packet_t {
/**
* Forward declaration for clone()
*/
-static private_esp_packet_t *esp_packet_create_empty(packet_t *packet);
+static private_esp_packet_t *esp_packet_create_internal(packet_t *packet);
METHOD(packet_t, set_source, void,
private_esp_packet_t *this, host_t *src)
@@ -108,8 +108,8 @@ METHOD(packet_t, clone, packet_t*,
{
private_esp_packet_t *pkt;
- pkt = esp_packet_create_empty(this->packet->clone(this->packet));
- pkt->payload = chunk_clone(this->payload);
+ pkt = esp_packet_create_internal(this->packet->clone(this->packet));
+ pkt->payload = this->payload ? this->payload->clone(this->payload) : NULL;
pkt->next_header = this->next_header;
return &pkt->public.packet;
}
@@ -155,35 +155,44 @@ static bool check_padding(chunk_t padding)
/**
* Remove the padding from the payload and set the next header info
*/
-static bool remove_padding(private_esp_packet_t *this)
+static bool remove_padding(private_esp_packet_t *this, chunk_t plaintext)
{
u_int8_t next_header, pad_length;
- chunk_t padding;
+ chunk_t padding, payload;
bio_reader_t *reader;
- reader = bio_reader_create(this->payload);
+ reader = bio_reader_create(plaintext);
if (!reader->read_uint8_end(reader, &next_header) ||
!reader->read_uint8_end(reader, &pad_length))
{
DBG1(DBG_ESP, "parsing ESP payload failed: invalid length");
- reader->destroy(reader);
- return FALSE;
+ goto failed;
}
if (!reader->read_data_end(reader, pad_length, &padding) ||
!check_padding(padding))
{
DBG1(DBG_ESP, "parsing ESP payload failed: invalid padding");
- reader->destroy(reader);
+ goto failed;
+ }
+ this->payload = ip_packet_create(reader->peek(reader));
+ reader->destroy(reader);
+ if (!this->payload)
+ {
+ DBG1(DBG_ESP, "parsing ESP payload failed: unsupported payload");
return FALSE;
}
- this->payload = reader->peek(reader);
this->next_header = next_header;
- reader->destroy(reader);
+ payload = this->payload->get_encoding(this->payload);
DBG3(DBG_ESP, "ESP payload:\n payload %B\n padding %B\n "
- "padding length = %hhu, next header = %hhu", &this->payload,
- &padding, pad_length, this->next_header);
+ "padding length = %hhu, next header = %hhu", &payload, &padding,
+ pad_length, this->next_header);
return TRUE;
+
+failed:
+ reader->destroy(reader);
+ chunk_free(&plaintext);
+ return FALSE;
}
METHOD(esp_packet_t, decrypt, status_t,
@@ -191,11 +200,12 @@ METHOD(esp_packet_t, decrypt, status_t,
{
bio_reader_t *reader;
u_int32_t spi, seq;
- chunk_t data, iv, icv, ciphertext;
+ chunk_t data, iv, icv, ciphertext, plaintext;
crypter_t *crypter;
signer_t *signer;
- chunk_free(&this->payload);
+ DESTROY_IF(this->payload);
+ this->payload = NULL;
data = this->packet->get_data(this->packet);
crypter = esp_context->get_crypter(esp_context);
@@ -233,15 +243,14 @@ METHOD(esp_packet_t, decrypt, status_t,
}
esp_context->set_authenticated_seqno(esp_context, seq);
- if (!crypter->decrypt(crypter, ciphertext, iv, &this->payload))
+ if (!crypter->decrypt(crypter, ciphertext, iv, &plaintext))
{
DBG1(DBG_ESP, "ESP decryption failed");
return FAILED;
}
- if (!remove_padding(this))
+ if (!remove_padding(this, plaintext))
{
- chunk_free(&this->payload);
return PARSE_ERROR;
}
return SUCCESS;
@@ -263,7 +272,7 @@ static void generate_padding(chunk_t padding)
METHOD(esp_packet_t, encrypt, status_t,
private_esp_packet_t *this, esp_context_t *esp_context, u_int32_t spi)
{
- chunk_t iv, icv, padding, ciphertext, auth_data;
+ chunk_t iv, icv, padding, payload, ciphertext, auth_data;
bio_writer_t *writer;
u_int32_t next_seqno;
size_t blocksize, plainlen;
@@ -293,7 +302,9 @@ METHOD(esp_packet_t, encrypt, status_t,
icv.len = signer->get_block_size(signer);
/* plaintext = payload, padding, pad_length, next_header */
- plainlen = this->payload.len + 2;
+ payload = this->payload ? this->payload->get_encoding(this->payload)
+ : chunk_empty;
+ plainlen = payload.len + 2;
padding.len = blocksize - (plainlen % blocksize);
plainlen += padding.len;
@@ -318,7 +329,7 @@ METHOD(esp_packet_t, encrypt, status_t,
ciphertext.ptr += ciphertext.len;
ciphertext.len = plainlen;
- writer->write_data(writer, this->payload);
+ writer->write_data(writer, payload);
padding = writer->skip(writer, padding.len);
generate_padding(padding);
@@ -327,7 +338,7 @@ METHOD(esp_packet_t, encrypt, status_t,
writer->write_uint8(writer, this->next_header);
DBG3(DBG_ESP, "ESP before encryption:\n payload = %B\n padding = %B\n "
- "padding length = %hhu, next header = %hhu", &this->payload, &padding,
+ "padding length = %hhu, next header = %hhu", &payload, &padding,
(u_int8_t)padding.len, this->next_header);
/* encrypt the content inline */
@@ -363,21 +374,31 @@ METHOD(esp_packet_t, get_next_header, u_int8_t,
return this->next_header;
}
-METHOD(esp_packet_t, get_payload, chunk_t,
+METHOD(esp_packet_t, get_payload, ip_packet_t*,
private_esp_packet_t *this)
{
return this->payload;
}
+METHOD(esp_packet_t, extract_payload, ip_packet_t*,
+ private_esp_packet_t *this)
+{
+ ip_packet_t *payload;
+
+ payload = this->payload;
+ this->payload = NULL;
+ return payload;
+}
+
METHOD2(esp_packet_t, packet_t, destroy, void,
private_esp_packet_t *this)
{
- chunk_free(&this->payload);
+ DESTROY_IF(this->payload);
this->packet->destroy(this->packet);
free(this);
}
-static private_esp_packet_t *esp_packet_create_empty(packet_t *packet)
+static private_esp_packet_t *esp_packet_create_internal(packet_t *packet)
{
private_esp_packet_t *this;
@@ -396,11 +417,12 @@ static private_esp_packet_t *esp_packet_create_empty(packet_t *packet)
},
.get_source = _get_source,
.get_destination = _get_destination,
- .get_payload = _get_payload,
.get_next_header = _get_next_header,
.parse_header = _parse_header,
.decrypt = _decrypt,
.encrypt = _encrypt,
+ .get_payload = _get_payload,
+ .extract_payload = _extract_payload,
.destroy = _destroy,
},
.packet = packet,
@@ -416,7 +438,7 @@ esp_packet_t *esp_packet_create_from_packet(packet_t *packet)
{
private_esp_packet_t *this;
- this = esp_packet_create_empty(packet);
+ this = esp_packet_create_internal(packet);
return &this->public;
}
@@ -425,16 +447,22 @@ esp_packet_t *esp_packet_create_from_packet(packet_t *packet)
* Described in header.
*/
esp_packet_t *esp_packet_create_from_payload(host_t *src, host_t *dst,
- chunk_t payload,
- u_int8_t next_header)
+ ip_packet_t *payload)
{
private_esp_packet_t *this;
packet_t *packet;
packet = packet_create_from_data(src, dst, chunk_empty);
- this = esp_packet_create_empty(packet);
- this->next_header = next_header;
+ this = esp_packet_create_internal(packet);
this->payload = payload;
-
+ if (payload)
+ {
+ this->next_header = payload->get_version(payload) == 4 ? IPPROTO_IPIP
+ : IPPROTO_IPV6;
+ }
+ else
+ {
+ this->next_header = IPPROTO_NONE;
+ }
return &this->public;
}
diff --git a/src/libipsec/esp_packet.h b/src/libipsec/esp_packet.h
index 7dbbd1986..a1d1602c1 100644
--- a/src/libipsec/esp_packet.h
+++ b/src/libipsec/esp_packet.h
@@ -23,6 +23,7 @@
#ifndef ESP_PACKET_H_
#define ESP_PACKET_H_
+#include "ip_packet.h"
#include "esp_context.h"
#include <library.h>
@@ -105,12 +106,20 @@ struct esp_packet_t {
u_int8_t (*get_next_header)(esp_packet_t *this);
/**
- * Get the plaintext payload of this packet (e.g. inner IP packet).
+ * Get the plaintext payload of this packet.
*
* @return plaintext payload (internal data),
- * chunk_empty if not decrypted
+ * NULL if not decrypted
*/
- chunk_t (*get_payload)(esp_packet_t *this);
+ ip_packet_t *(*get_payload)(esp_packet_t *this);
+
+ /**
+ * Extract the plaintext payload from this packet.
+ *
+ * @return plaintext payload (has to be destroyed),
+ * NULL if not decrypted
+ */
+ ip_packet_t *(*extract_payload)(esp_packet_t *this);
/**
* Destroy an esp_packet_t
@@ -128,17 +137,15 @@ struct esp_packet_t {
esp_packet_t *esp_packet_create_from_packet(packet_t *packet);
/**
- * Create an ESP packet from a plaintext payload (e.g. inner IP packet)
+ * Create an ESP packet from a plaintext payload
*
* @param src source address
* @param dst destination address
- * @param payload plaintext payload (e.g. inner IP packet), gets owned
- * @param next_header next header type of the payload (e.g IPPROTO_IPIP)
+ * @param payload plaintext payload, gets owned
* @return esp_packet_t instance
*/
esp_packet_t *esp_packet_create_from_payload(host_t *src, host_t *dst,
- chunk_t payload,
- u_int8_t next_header);
+ ip_packet_t *payload);
#endif /** ESP_PACKET_H_ @}*/