aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/encoding/payloads/attribute_payload_v1.c231
-rw-r--r--src/libcharon/encoding/payloads/attribute_payload_v1.h93
-rw-r--r--src/libcharon/encoding/payloads/data_attribute_v1.c260
-rw-r--r--src/libcharon/encoding/payloads/data_attribute_v1.h88
4 files changed, 672 insertions, 0 deletions
diff --git a/src/libcharon/encoding/payloads/attribute_payload_v1.c b/src/libcharon/encoding/payloads/attribute_payload_v1.c
new file mode 100644
index 000000000..3aa0bc3a1
--- /dev/null
+++ b/src/libcharon/encoding/payloads/attribute_payload_v1.c
@@ -0,0 +1,231 @@
+
+#include <stddef.h>
+
+#include "attribute_payload_v1.h"
+
+#include <encoding/payloads/encodings.h>
+#include <utils/linked_list.h>
+
+ENUM(config_type_v1_names, ISAKMP_CFG_REQUEST, ISAKMP_CFG_ACK,
+ "ISAKMP_CFG_REQUEST",
+ "ISAKMP_CFG_REPLY",
+ "ISAKMP_CFG_SET",
+ "ISAKMP_CFG_ACK",
+);
+
+typedef struct private_attribute_payload_v1_t private_attribute_payload_v1_t;
+
+/**
+ * Private data of an attribute_payload_v1_t object.
+ */
+struct private_attribute_payload_v1_t {
+
+ /**
+ * Public cp_payload_t interface.
+ */
+ attribute_payload_v1_t public;
+
+ /**
+ * Next payload type.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Length of this payload.
+ */
+ u_int16_t payload_length;
+
+ /**
+ * List of attributes, as configuration_attribute_t
+ */
+ linked_list_t *attributes;
+
+ /**
+ * Reserved bytes
+ */
+ u_int8_t reserved_byte[2];
+
+ /**
+ * Identifier
+ */
+ u_int16_t identifier;
+
+ /**
+ * Config Type.
+ */
+ u_int8_t type;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-CP Payload
+ *
+ * The defined offsets are the positions in a object of type
+ * private_attribute_payload_v1_t.
+ */
+encoding_rule_t attribute_payload_v1_encodings[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_attribute_payload_v1_t, next_payload) },
+ /* reserved byte */
+ { RESERVED_BYTE, offsetof(private_attribute_payload_v1_t, reserved_byte[0]) },
+ /* Length of the whole Attribute payload*/
+ { PAYLOAD_LENGTH, offsetof(private_attribute_payload_v1_t, payload_length) },
+ /* Config type */
+ { U_INT_8, offsetof(private_attribute_payload_v1_t, type) },
+ /* 3 reserved bytes */
+ { RESERVED_BYTE, offsetof(private_attribute_payload_v1_t, reserved_byte[1])},
+
+ /* Identifier */
+ { U_INT_16, offsetof(private_attribute_payload_v1_t, identifier)},
+
+ /* List of configuration attributes */
+ { PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE, offsetof(private_attribute_payload_v1_t, attributes) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload ! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! CFG Type ! RESERVED ! Identifier !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! !
+ ~ Configuration Attributes ~
+ ! !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_attribute_payload_v1_t *this)
+{
+ status_t status = SUCCESS;
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ status = attribute->verify(attribute);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return status;
+}
+
+METHOD(payload_t, get_encoding_rules, void,
+ private_attribute_payload_v1_t *this, encoding_rule_t **rules, size_t *rule_count)
+{
+ *rules = attribute_payload_v1_encodings;
+ *rule_count = countof(attribute_payload_v1_encodings);
+}
+
+METHOD(payload_t, get_type, payload_type_t,
+ private_attribute_payload_v1_t *this)
+{
+ return ATTRIBUTE_V1;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_attribute_payload_v1_t *this)
+{
+ return this->next_payload;
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_attribute_payload_v1_t *this,payload_type_t type)
+{
+ this->next_payload = type;
+}
+
+/**
+ * recompute the length of the payload.
+ */
+static void compute_length(private_attribute_payload_v1_t *this)
+{
+ enumerator_t *enumerator;
+ payload_t *attribute;
+
+ this->payload_length = ATTRIBUTE_PAYLOAD_V1_HEADER_LENGTH;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ this->payload_length += attribute->get_length(attribute);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_attribute_payload_v1_t *this)
+{
+ return this->payload_length;
+}
+
+METHOD(attribute_payload_v1_t, create_attribute_enumerator, enumerator_t*,
+ private_attribute_payload_v1_t *this)
+{
+ return this->attributes->create_enumerator(this->attributes);
+}
+
+METHOD(attribute_payload_v1_t, add_attribute, void,
+ private_attribute_payload_v1_t *this, data_attribute_v1_t *attribute)
+{
+ this->attributes->insert_last(this->attributes, attribute);
+ compute_length(this);
+}
+
+METHOD(attribute_payload_v1_t, get_config_type, config_type_v1_t,
+ private_attribute_payload_v1_t *this)
+{
+ return this->type;
+}
+
+METHOD2(payload_t, attribute_payload_v1_t, destroy, void,
+ private_attribute_payload_v1_t *this)
+{
+ this->attributes->destroy_offset(this->attributes,
+ offsetof(data_attribute_v1_t, destroy));
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+attribute_payload_v1_t *attribute_payload_v1_create_type(config_type_v1_t type)
+{
+ private_attribute_payload_v1_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ .add_attribute = _add_attribute,
+ .get_type = _get_config_type,
+ .destroy = _destroy,
+ },
+ .next_payload = NO_PAYLOAD,
+ .payload_length = ATTRIBUTE_PAYLOAD_V1_HEADER_LENGTH,
+ .attributes = linked_list_create(),
+ .type = type,
+ );
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+attribute_payload_v1_t *attribute_payload_v1_create()
+{
+ return attribute_payload_v1_create_type(ISAKMP_CFG_REQUEST);
+}
diff --git a/src/libcharon/encoding/payloads/attribute_payload_v1.h b/src/libcharon/encoding/payloads/attribute_payload_v1.h
new file mode 100644
index 000000000..d59d9981e
--- /dev/null
+++ b/src/libcharon/encoding/payloads/attribute_payload_v1.h
@@ -0,0 +1,93 @@
+
+/**
+ * @defgroup attribute_payload_v1 attribute_payload_v1
+ * @{ @ingroup payloads
+ */
+
+#ifndef ATTRIBUTE_PAYLOAD_V1_H_
+#define ATTRIBUTE_PAYLOAD_V1_H_
+
+typedef enum config_type_v1_t config_type_v1_t;
+typedef struct attribute_payload_v1_t attribute_payload_v1_t;
+
+#include <library.h>
+#include <encoding/payloads/payload.h>
+#include <encoding/payloads/data_attribute_v1.h>
+#include <utils/enumerator.h>
+
+/**
+ * ATTRIBUTE_PAYLOAD_V1 length in bytes without any proposal substructure.
+ */
+#define ATTRIBUTE_PAYLOAD_V1_HEADER_LENGTH 8
+
+/**
+ * Config Type of an Attribute Payload.
+ */
+enum config_type_v1_t {
+ ISAKMP_CFG_REQUEST = 1,
+ ISAKMP_CFG_REPLY = 2,
+ ISAKMP_CFG_SET = 3,
+ ISAKMP_CFG_ACK = 4,
+};
+
+/**
+ * enum name for config_type_v1_t.
+ */
+extern enum_name_t *config_type_v1_names;
+
+/**
+ * Class representing an ISAKMP Config Mode Attribute Payload.
+ *
+ * The Attribute Payload format is described in draft-ietf-ipsec-isakmp-mode-cfg-o5.txt section 3.2.
+ */
+struct attribute_payload_v1_t {
+
+ /**
+ * The payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Creates an enumerator of stored data_attribute_v1_t objects.
+ *
+ * @return enumerator over configration_attribute_t
+ */
+ enumerator_t *(*create_attribute_enumerator) (attribute_payload_v1_t *this);
+
+ /**
+ * Adds a configuration attribute to the attribute payload.
+ *
+ * @param attribute attribute to add
+ */
+ void (*add_attribute)(attribute_payload_v1_t *this,
+ data_attribute_v1_t *attribute);
+
+ /**
+ * Get the attribute payload type.
+ *
+ * @return type of attribute payload
+ */
+ config_type_v1_t (*get_type) (attribute_payload_v1_t *this);
+
+ /**
+ * Destroys an attribute_payload_v1_t object.
+ */
+ void (*destroy) (attribute_payload_v1_t *this);
+};
+
+/**
+ * Creates an empty attribute payload
+ *
+ * @return empty attribute payload
+ */
+attribute_payload_v1_t *attribute_payload_v1_create();
+
+/**
+ * Creates an attribute_payload_v1_t with type and value
+ *
+ * @param config_type type of attribute payload to create
+ * @return created attribute payload
+ */
+attribute_payload_v1_t *attribute_payload_v1_create_type(config_type_v1_t config_type);
+
+#endif /** ATTRIBUTE_PAYLOAD_V1_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/data_attribute_v1.c b/src/libcharon/encoding/payloads/data_attribute_v1.c
new file mode 100644
index 000000000..37f7c0072
--- /dev/null
+++ b/src/libcharon/encoding/payloads/data_attribute_v1.c
@@ -0,0 +1,260 @@
+
+#include <stddef.h>
+
+#include "data_attribute_v1.h"
+
+#include <encoding/payloads/encodings.h>
+#include <library.h>
+#include <daemon.h>
+
+typedef struct private_data_attribute_v1_t private_data_attribute_v1_t;
+
+/**
+ * Private data of an data_attribute_v1_t object.
+ */
+struct private_data_attribute_v1_t {
+
+ /**
+ * Public data_attribute_v1_t interface.
+ */
+ data_attribute_v1_t public;
+
+ /**
+ * Reserved bit
+ */
+ bool af_flag;
+
+ /**
+ * Type of the attribute.
+ */
+ u_int16_t type;
+
+ /**
+ * Length of the attribute.
+ */
+ u_int16_t length_or_value;
+
+ /**
+ * Attribute value as chunk.
+ */
+ chunk_t value;
+};
+
+/**
+ * Encoding rules to parse or generate a configuration attribute.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_data_attribute_v1_t.
+ */
+encoding_rule_t data_attribute_v1_encodings[] = {
+ /* AF Flag */
+ { FLAG, offsetof(private_data_attribute_v1_t, af_flag)},
+ /* type of the attribute as 15 bit unsigned integer */
+ { ATTRIBUTE_TYPE, offsetof(private_data_attribute_v1_t, type) },
+ /* Length of attribute value */
+ { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_data_attribute_v1_t, length_or_value) },
+ /* Value of attribute if attribute format flag is zero */
+ { ATTRIBUTE_VALUE, offsetof(private_data_attribute_v1_t, value) }
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !R| Attribute Type ! Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ Value ~
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_data_attribute_v1_t *this)
+{
+ bool failed = FALSE;
+
+ if (this->length_or_value != this->value.len)
+ {
+ DBG1(DBG_ENC, "invalid attribute length");
+ return FAILED;
+ }
+
+ switch (this->type)
+ {
+ case INTERNAL_IP4_ADDRESS:
+ case INTERNAL_IP4_NETMASK:
+ case INTERNAL_IP4_DNS:
+ case INTERNAL_IP4_NBNS:
+ case INTERNAL_ADDRESS_EXPIRY:
+ case INTERNAL_IP4_DHCP:
+ if (this->length_or_value != 0 && this->length_or_value != 4)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP4_SUBNET:
+ if (this->length_or_value != 0 && this->length_or_value != 8)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_ADDRESS:
+ case INTERNAL_IP6_SUBNET:
+ if (this->length_or_value != 0 && this->length_or_value != 17)
+ {
+ failed = TRUE;
+ }
+ break;
+ case INTERNAL_IP6_DNS:
+ case INTERNAL_IP6_NBNS:
+ case INTERNAL_IP6_DHCP:
+ if (this->length_or_value != 0 && this->length_or_value != 16)
+ {
+ failed = TRUE;
+ }
+ break;
+ case SUPPORTED_ATTRIBUTES:
+ if (this->length_or_value % 2)
+ {
+ failed = TRUE;
+ }
+ break;
+ case APPLICATION_VERSION:
+ /* any length acceptable */
+ break;
+ default:
+ DBG1(DBG_ENC, "unknown attribute type %N",
+ configuration_attribute_type_names, this->type);
+ break;
+ }
+
+ if (failed)
+ {
+ DBG1(DBG_ENC, "invalid attribute length %d for %N",
+ this->length_or_value, configuration_attribute_type_names, this->type);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(payload_t, get_encoding_rules, void,
+ private_data_attribute_v1_t *this, encoding_rule_t **rules,
+ size_t *rule_count)
+{
+ *rules = data_attribute_v1_encodings;
+ *rule_count = countof(data_attribute_v1_encodings);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_data_attribute_v1_t *this)
+{
+ return 4;
+}
+
+METHOD(payload_t, get_type, payload_type_t,
+ private_data_attribute_v1_t *this)
+{
+ return DATA_ATTRIBUTE_V1;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_data_attribute_v1_t *this)
+{
+ return NO_PAYLOAD;
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_data_attribute_v1_t *this, payload_type_t type)
+{
+}
+
+METHOD(payload_t, get_length, size_t,
+ private_data_attribute_v1_t *this)
+{
+ return get_header_length(this) + this->value.len;
+}
+
+METHOD(data_attribute_v1_t, get_dattr_type, configuration_attribute_type_t,
+ private_data_attribute_v1_t *this)
+{
+ return this->type;
+}
+
+METHOD(data_attribute_v1_t, get_value, u_int16_t,
+ private_data_attribute_v1_t *this)
+{
+ return this->length_or_value;
+}
+
+METHOD(data_attribute_v1_t, get_value_chunk, chunk_t,
+ private_data_attribute_v1_t *this)
+{
+ return this->value;
+}
+
+METHOD2(payload_t, data_attribute_v1_t, destroy, void,
+ private_data_attribute_v1_t *this)
+{
+ free(this->value.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+data_attribute_v1_t *data_attribute_v1_create()
+{
+ private_data_attribute_v1_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_value_chunk = _get_value_chunk,
+ .get_type = _get_dattr_type,
+ .destroy = _destroy,
+ },
+ );
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+data_attribute_v1_t *data_attribute_v1_create_value(
+ configuration_attribute_type_t type, chunk_t value)
+{
+ private_data_attribute_v1_t *this;
+
+ this = (private_data_attribute_v1_t*)data_attribute_v1_create();
+ this->type = ((u_int16_t)type) & 0x7FFF;
+ this->value = chunk_clone(value);
+ this->length_or_value = value.len;
+ this->af_flag = FALSE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+data_attribute_v1_t *data_attribute_v1_create_basic(
+ configuration_attribute_type_t type, u_int16_t value)
+{
+ private_data_attribute_v1_t *this;
+
+ this = (private_data_attribute_v1_t*)data_attribute_v1_create();
+ this->type = ((u_int16_t)type) & 0x7FFF;
+ this->length_or_value = value;
+ this->af_flag = TRUE;
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/data_attribute_v1.h b/src/libcharon/encoding/payloads/data_attribute_v1.h
new file mode 100644
index 000000000..568b3143a
--- /dev/null
+++ b/src/libcharon/encoding/payloads/data_attribute_v1.h
@@ -0,0 +1,88 @@
+
+/**
+ * @defgroup data_attribute_v1 data_attribute_v1
+ * @{ @ingroup payloads
+ */
+
+#ifndef DATA_ATTRIBUTE_V1_H_
+#define DATA_ATTRIBUTE_V1_H_
+
+typedef struct data_attribute_v1_t data_attribute_v1_t;
+
+#include <library.h>
+#include <attributes/attributes.h>
+#include <encoding/payloads/payload.h>
+
+/**
+ * Configuration attribute header length in bytes.
+ */
+#define DATA_ATTRIBUTE_V1_HEADER_LENGTH 4
+
+/**
+ * Class representing an IKEv1-Data Attribute.
+ *
+ * The DATA_ATTRIBUTE_V1 format is described in RFC section 3.15.1.
+ */
+struct data_attribute_v1_t {
+
+ /**
+ * Implements payload_t interface.
+ */
+ payload_t payload_interface;
+
+ /**
+ * Get the type of the attribute.
+ *
+ * @return type of the data attribute
+ */
+ configuration_attribute_type_t (*get_type)(data_attribute_v1_t *this);
+
+ /**
+ * Returns the value of the attribute.
+ *
+ * @return the basic internal value
+ */
+ u_int16_t (*get_value) (data_attribute_v1_t *this);
+
+ /**
+ * Returns the value of the attribute.
+ *
+ * @return chunk_t pointing to the internal value
+ */
+ chunk_t (*get_value_chunk) (data_attribute_v1_t *this);
+
+ /**
+ * Destroys an configuration_attribute_t object.
+ */
+ void (*destroy) (data_attribute_v1_t *this);
+};
+
+/**
+ * Creates an empty data attribute.
+ *
+ * @return created data attribute
+ */
+data_attribute_v1_t *data_attribute_v1_create();
+
+/**
+ * Creates a data attribute with type and value.
+ *
+ * @param type type of data attribute
+ * @param value value, gets cloned
+ * @return created data attribute
+ */
+data_attribute_v1_t *data_attribute_v1_create_value(
+ configuration_attribute_type_t type, chunk_t value);
+
+
+/**
+ * Creates a data attribute with type and value.
+ *
+ * @param type type of data attribute
+ * @param value value
+ * @return created data attribute
+ */
+data_attribute_v1_t *data_attribute_v1_create_basic(
+ configuration_attribute_type_t type, u_int16_t value);
+
+#endif /** DATA_ATTRIBUTE_V1_H_ @}*/