- created encoding package

This commit is contained in:
Martin Willi
2005-11-23 09:57:18 +00:00
parent 716abc9f83
commit 4a96223884
44 changed files with 99 additions and 100 deletions
@@ -0,0 +1,54 @@
/**
* @file encodings.c
*
* @brief Type definitions for parser and generator,
* also payload types are defined here.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "encodings.h"
mapping_t encoding_type_m[] = {
{U_INT_4, "U_INT_4"},
{U_INT_8, "U_INT_8"},
{U_INT_16, "U_INT_16"},
{U_INT_32, "U_INT_32"},
{U_INT_64, "U_INT_64"},
{IKE_SPI, "IKE_SPI"},
{RESERVED_BIT, "RESERVED_BIT"},
{RESERVED_BYTE, "RESERVED_BYTE"},
{FLAG, "FLAG"},
{PAYLOAD_LENGTH, "PAYLOAD_LENGTH"},
{HEADER_LENGTH, "HEADER_LENGTH"},
{SPI_SIZE, "SPI_SIZE"},
{SPI, "SPI"},
{KEY_EXCHANGE_DATA, "KEY_EXCHANGE_DATA"},
{NOTIFICATION_DATA, "NOTIFICATION_DATA"},
{PROPOSALS, "PROPOSALS"},
{TRANSFORMS, "TRANSFORMS"},
{TRANSFORM_ATTRIBUTES, "TRANSFORM_ATTRIBUTES"},
{ATTRIBUTE_FORMAT, "ATTRIBUTE_FORMAT"},
{ATTRIBUTE_TYPE, "ATTRIBUTE_TYPE"},
{ATTRIBUTE_LENGTH_OR_VALUE, "ATTRIBUTE_LENGTH_OR_VALUE"},
{ATTRIBUTE_VALUE, "ATTRIBUTE_VALUE"},
{NONCE_DATA, "NONCE_DATA"},
{MAPPING_END, NULL}
};
+359
View File
@@ -0,0 +1,359 @@
/**
* @file encodings.h
*
* @brief Type definitions for parser and generator,
* also payload types are defined here.
*
* Header is parsed like a payload and gets its one payload_id
* from PRIVATE USE space. Also the substructures
* of specific payload types get their own payload_id
* from PRIVATE_USE space. See RFC for mor informations.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef ENCODINGS_H_
#define ENCODINGS_H_
#include <types.h>
#include <definitions.h>
/**
* @brief All different kinds of encoding types.
*
* Each field of an IKEv2-Message (in header or payload)
* which has to be parsed or generated differently has its own
* type defined here.
*/
typedef enum encoding_type_e encoding_type_t;
enum encoding_type_e{
/**
* Representing a 4 Bit unsigned int value
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 4 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 4 bit forward afterwards.
*/
U_INT_4,
/**
* Representing a 8 Bit unsigned int value
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
U_INT_8,
/**
* Representing a 16 Bit unsigned int value
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
U_INT_16,
/**
* Representing a 32 Bit unsigned int value
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
U_INT_32,
/**
* Representing a 64 Bit unsigned int value
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 64 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 64 bit forward afterwards.
*/
U_INT_64,
/**
* @brief represents a RESERVED_BIT used in FLAG-Bytes
*
* When generating, the next bit is set to zero and the current write
* position is moved one bit forward.
* No value is read from the associated data struct.
* The current write position is moved 1 bit forward afterwards.
*
* When parsing, the current read pointer is moved one bit forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 bit forward afterwards.
*/
RESERVED_BIT,
/**
* @brief represents a RESERVED_BYTE
*
* When generating, the next byte is set to zero and the current write
* position is moved one byte forward.
* No value is read from the associated data struct.
* The current write position is moved 1 byte forward afterwards.
*
* When parsing, the current read pointer is moved one byte forward.
* No value is written to the associated data struct.
* The current read pointer is moved 1 byte forward afterwards.
*/
RESERVED_BYTE,
/**
* Representing a 1 Bit flag.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards
*/
FLAG,
/**
* Representating a length field of a payload
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
PAYLOAD_LENGTH,
/**
* Representating a length field of a header
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 32 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 32 bit forward afterwards.
*/
HEADER_LENGTH,
/**
* Representating a spi size field
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 8 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 8 bit forward afterwards.
*/
SPI_SIZE,
/**
* Representating a spi field
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
SPI,
/**
* Representating a Key Exchange Data field
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 8) bytes are read and written into the chunk pointing to.
*/
KEY_EXCHANGE_DATA,
/**
* Representating a Notification field
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - spi size - 8) bytes are read and written into the chunk pointing to.
*/
NOTIFICATION_DATA,
/**
* Representating one or more proposal substructures
*
* The offset points to a linked_list_t pointer.
*
* When generating the proposal_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed proposal_substructure_t objects have
* to be stored in the pointed linked_list.
*/
PROPOSALS,
/**
* Representating one or more transform substructures
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_substructure_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_substructure_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORMS,
/**
* Representating one or more Attributes of a transform substructure
*
* The offset points to a linked_list_t pointer.
*
* When generating the transform_attribute_t objects are stored
* in the pointed linked_list.
*
* When parsing the parsed transform_attribute_t objects have
* to be stored in the pointed linked_list.
*/
TRANSFORM_ATTRIBUTES,
/**
* Representing a 1 Bit flag specifying the format of a transform attribute.
*
* When generation, the next bit is set to 1 if the associated value
* in the data struct is TRUE, 0 otherwise. The current write position
* is moved 1 bit forward afterwards.
*
* When parsing, the next bit is read and stored in the associated data
* struct. 0 means FALSE, 1 means TRUE, The current read pointer
* is moved 1 bit forward afterwards.
*/
ATTRIBUTE_FORMAT,
/**
* Representing a 15 Bit unsigned int value used as attribute type
* in an attribute transform
*
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 15 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 15 bit forward afterwards.
*/
ATTRIBUTE_TYPE,
/**
* Depending on the field of type ATTRIBUTE_FORMAT
* this field contains the length or the value of an transform attribute.
* Its stored in a 16 unsigned integer field
*
* When generating it must be changed from host to network order.
* The value is read from the associated data struct.
* The current write position is moved 16 bit forward afterwards.
*
* When parsing it must be changed from network to host order.
* The value is written to the associated data struct.
* The current read pointer is moved 16 bit forward afterwards.
*/
ATTRIBUTE_LENGTH_OR_VALUE,
/*
* Depending on the field of type ATTRIBUTE_FORMAT
* this field is available or missing and so parsed/generated
* or not parsed/not generated
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing SPI_SIZE bytes are read and written into the chunk pointing to.
*/
ATTRIBUTE_VALUE,
/**
* Representating a Nonce Data field
*
* When generating the content of the chunkt pointing to
* is written.
*
* When parsing (Payload Length - 4) bytes are read and written into the chunk pointing to.
*/
NONCE_DATA,
/**
* Representating an IKE_SPI field in an IKEv2 Header
*
* When generating the value of the u_int64_t pointing to
* is written (host and networ order is not changed).
*
* When parsing 8 bytes are read and written into the u_int64_t pointing to.
*/
IKE_SPI
};
/**
* mappings to map encoding_type_t's to strings
*/
extern mapping_t encoding_type_m[];
/**
* An encoding rule is a mapping of a specific encoding type to
* a location in the data struct where the current field is stored to
* or read from.
*
* For examples see directory encodings/.
*
* This rules are used by parser and generator.
*/
typedef struct encoding_rule_s encoding_rule_t;
struct encoding_rule_s{
/**
* Encoding type
*/
encoding_type_t type;
/**
* Offset in the data struct
*
* When parsing, data are written to this offset of the
* data struct.
*
* When generating, data are read from this offset in the
* data struct.
*/
u_int32_t offset;
};
#endif /*ENCODINGS_H_*/
@@ -0,0 +1,446 @@
/**
* @file ike_header.c
*
* @brief Declaration of the class ike_header_t.
*
* An object of this type represents an ike header and is used to
* generate and parse ike headers.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "ike_header.h"
#include <encoding/payloads/encodings.h>
#include <utils/allocator.h>
typedef struct private_ike_header_s private_ike_header_t;
struct private_ike_header_s {
/**
* public interface
*/
ike_header_t public;
/**
* SPI of the initiator
*/
u_int64_t initiator_spi;
/**
* SPI of the responder
*/
u_int64_t responder_spi;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* IKE major version
*/
u_int8_t maj_version;
/**
* IKE minor version
*/
u_int8_t min_version;
/**
* Exchange type
*/
u_int8_t exchange_type;
/**
* Flags of the Message
*
*/
struct {
/**
* Sender is initiator of the associated IKE_SA_INIT-Exchange
*/
bool initiator;
/**
* is protocol supporting higher version?
*/
bool version;
/**
* TRUE, if this is a response, FALSE if its a Request
*/
bool response;
} flags;
/**
* Associated Message-ID
*/
u_int32_t message_id;
/**
* Length of the whole IKEv2-Message (header and all payloads)
*/
u_int32_t length;
};
/**
* mappings used to get strings for exchange_type_t
*/
mapping_t exchange_type_m[] = {
{EXCHANGE_TYPE_UNDEFINED, "EXCHANGE_TYPE_UNDEFINED"},
{IKE_SA_INIT, "IKE_SA_INIT"},
{IKE_AUTH, "IKE_AUTH"},
{CREATE_CHILD_SA, "CREATE_CHILD_SA"},
{INFORMATIONAL, "INFORMATIONAL"}
};
/**
* Encoding rules to parse or generate a IKEv2-Header
*
* The defined offsets are the positions in a object of type
* ike_header_t.
*
*/
encoding_rule_t ike_header_encodings[] = {
/* 8 Byte SPI, stored in the field initiator_spi */
{ IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
/* 8 Byte SPI, stored in the field responder_spi */
{ IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ike_header_t, next_payload) },
/* 4 Bit major version, stored in the field maj_version */
{ U_INT_4, offsetof(private_ike_header_t, maj_version) },
/* 4 Bit minor version, stored in the field min_version */
{ U_INT_4, offsetof(private_ike_header_t, min_version) },
/* 8 Bit for the exchange type */
{ U_INT_8, offsetof(private_ike_header_t, exchange_type) },
/* 2 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 3 Bit flags, stored in the fields response, version and initiator */
{ FLAG, offsetof(private_ike_header_t, flags.response) },
{ FLAG, offsetof(private_ike_header_t, flags.version) },
{ FLAG, offsetof(private_ike_header_t, flags.initiator) },
/* 3 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* 4 Byte message id, stored in the field message_id */
{ U_INT_32, offsetof(private_ike_header_t, message_id) },
/* 4 Byte length fied, stored in the field length */
{ HEADER_LENGTH, offsetof(private_ike_header_t, length) }
};
/* 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Initiator's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! IKE_SA Responder's SPI !
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Message ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_ike_header_t *this)
{
if ((this->exchange_type < IKE_SA_INIT) || (this->exchange_type > INFORMATIONAL))
{
/* unsupported exchange type */
return FAILED;
}
if (this->initiator_spi == 0)
{
/* initiator spi not set */
return FAILED;
}
if ((this->responder_spi == 0) && (!this->flags.initiator))
{
/* must be original initiator*/
return FAILED;
}
if ((this->responder_spi == 0) && (this->flags.response))
{
/* must be request*/
return FAILED;
}
/* verification of version is not done in here */
return SUCCESS;
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(payload_t *this,payload_type_t type)
{
((private_ike_header_t *)this)->next_payload = type;
return SUCCESS;
}
/**
* Implements ike_header_t's get_initiator_spi fuction.
* See #ike_header_t.get_initiator_spi for description.
*/
static u_int64_t get_initiator_spi(private_ike_header_t *this)
{
return this->initiator_spi;
}
/**
* Implements ike_header_t's set_initiator_spi fuction.
* See #ike_header_t.set_initiator_spi for description.
*/
static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi)
{
this->initiator_spi = initiator_spi;
}
/**
* Implements ike_header_t's get_responder_spi fuction.
* See #ike_header_t.get_responder_spi for description.
*/
static u_int64_t get_responder_spi(private_ike_header_t *this)
{
return this->responder_spi;
}
/**
* Implements ike_header_t's set_responder_spi fuction.
* See #ike_header_t.set_responder_spi for description.
*/
static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi)
{
this->responder_spi = responder_spi;
}
/**
* Implements ike_header_t's get_maj_version fuction.
* See #ike_header_t.get_maj_version for description.
*/
static u_int8_t get_maj_version(private_ike_header_t *this)
{
return this->maj_version;
}
/**
* Implements ike_header_t's get_min_version fuction.
* See #ike_header_t.get_min_version for description.
*/
static u_int8_t get_min_version(private_ike_header_t *this)
{
return this->min_version;
}
/**
* Implements ike_header_t's get_response_flag fuction.
* See #ike_header_t.get_response_flag for description.
*/
static bool get_response_flag(private_ike_header_t *this)
{
return this->flags.response;
}
/**
* Implements ike_header_t's set_response_flag fuction.
* See #ike_header_t.set_response_flag for description.
*/
static void set_response_flag(private_ike_header_t *this, bool response)
{
this->flags.response = response;
}
/**
* Implements ike_header_t's get_version_flag fuction.
* See #ike_header_t.get_version_flag for description.
*/
static bool get_version_flag(private_ike_header_t *this)
{
return this->flags.version;
}
/**
* Implements ike_header_t's get_initiator_flag fuction.
* See #ike_header_t.get_initiator_flag for description.
*/
static bool get_initiator_flag(private_ike_header_t *this)
{
return this->flags.initiator;
}
/**
* Implements ike_header_t's set_initiator_flag fuction.
* See #ike_header_t.set_initiator_flag for description.
*/
static void set_initiator_flag(private_ike_header_t *this, bool initiator)
{
this->flags.initiator = initiator;
}
/**
* Implements ike_header_t's get_exchange_type function
* See #ike_header_t.get_exchange_type for description.
*/
static u_int8_t get_exchange_type(private_ike_header_t *this)
{
return this->exchange_type;
}
/**
* Implements ike_header_t's set_exchange_type function.
* See #ike_header_t.set_exchange_type for description.
*/
static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type)
{
this->exchange_type = exchange_type;
}
/**
* Implements ike_header_t's get_message_id function.
* See #ike_header_t.get_message_id for description.
*/
static u_int32_t get_message_id(private_ike_header_t *this)
{
return this->message_id;
}
/**
* Implements ike_header_t's set_message_id function.
* See #ike_header_t.set_message_id for description.
*/
static void set_message_id(private_ike_header_t *this, u_int32_t message_id)
{
this->message_id = message_id;
}
/**
* Implements payload_t's and ike_header_t's destroy function.
* See #payload_s.destroy or ike_header_s.destroy for description.
*/
static status_t destroy(ike_header_t *this)
{
allocator_free(this);
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ike_header_encodings;
*rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(payload_t *this)
{
return HEADER;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(payload_t *this)
{
return (((private_ike_header_t*)this)->next_payload);
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(payload_t *this)
{
return (((private_ike_header_t*)this)->length);
}
/*
* Described in header
*/
ike_header_t *ike_header_create()
{
private_ike_header_t *this = allocator_alloc_thing(private_ike_header_t);
if (this == NULL)
{
return NULL;
}
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = get_encoding_rules;
this->public.payload_interface.get_length = get_length;
this->public.payload_interface.get_next_type = get_next_type;
this->public.payload_interface.set_next_type = set_next_type;
this->public.payload_interface.get_type = get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
this->public.destroy = destroy;
this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi;
this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi;
this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi;
this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi;
this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version;
this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version;
this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag;
this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag;
this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag;
this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag;
this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag;
this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type;
this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type;
this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id;
this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id;
/* set default values of the fields */
this->initiator_spi = 0;
this->responder_spi = 0;
this->next_payload = 0;
this->maj_version = IKE_MAJOR_VERSION;
this->min_version = IKE_MINOR_VERSION;
this->exchange_type = EXCHANGE_TYPE_UNDEFINED;
this->flags.initiator = TRUE;
this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG;
this->flags.response = FALSE;
this->message_id = 0;
this->length = IKE_HEADER_LENGTH;
return (ike_header_t*)this;
}
@@ -0,0 +1,242 @@
/**
* @file ike_header.h
*
* @brief Declaration of the class ike_header_t.
*
* An object of this type represents an ike header and is used to
* generate and parse ike headers.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef IKE_HEADER_H_
#define IKE_HEADER_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Major Version of IKEv2
*/
#define IKE_MAJOR_VERSION 2
/**
* Minor Version of IKEv2
*/
#define IKE_MINOR_VERSION 0
/**
* Flag in IKEv2-Header. Always 0
*/
#define HIGHER_VERSION_SUPPORTED_FLAG 0
/**
* Length of IKE Header in Bytes
*/
#define IKE_HEADER_LENGTH 28
/**
* @brief Different types of IKE-Exchanges.
*
* See RFC for different types.
*/
typedef enum exchange_type_e exchange_type_t;
enum exchange_type_e{
/**
* EXCHANGE_TYPE_UNDEFINED, not a official message type :-)
*/
EXCHANGE_TYPE_UNDEFINED = 240,
/**
* IKE_SA_INIT
*/
IKE_SA_INIT = 34,
/**
* IKE_AUTH
*/
IKE_AUTH = 35,
/**
* CREATE_CHILD_SA
*/
CREATE_CHILD_SA = 36,
/**
* INFORMATIONAL
*/
INFORMATIONAL = 37
};
extern mapping_t exchange_type_m[];
/**
* Object representing an IKEv2-Header
*
* The header format of an IKEv2-Message is compatible to the
* ISAKMP-Header format to allow implementations supporting
* both versions of the IKE-protocol.
*
*/
typedef struct ike_header_s ike_header_t;
struct ike_header_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief get the initiator spi
*
* @param this ike_header_t object
* @return initiator_spi
*/
u_int64_t (*get_initiator_spi) (ike_header_t *this);
/**
* @brief set the initiator spi
*
* @param this ike_header_t object
* @param initiator_spi initiator_spi
*/
void (*set_initiator_spi) (ike_header_t *this, u_int64_t initiator_spi);
/**
* @brief get the responder spi
*
* @param this ike_header_t object
* @return responder_spi
*/
u_int64_t (*get_responder_spi) (ike_header_t *this);
/**
* @brief set the responder spi
*
* @param this ike_header_t object
* @param responder_spi responder_spi
*/
void (*set_responder_spi) (ike_header_t *this, u_int64_t responder_spi);
/**
* @brief get the major version
*
* @param this ike_header_t object
* @return major version
*/
u_int8_t (*get_maj_version) (ike_header_t *this);
/**
* @brief get the mainor version
*
* @param this ike_header_t object
* @return minor version
*/
u_int8_t (*get_min_version) (ike_header_t *this);
/**
* @brief get the response flag
*
* @param this ike_header_t object
* @return response flag
*/
bool (*get_response_flag) (ike_header_t *this);
/**
* @brief Set the response flag
*
* @param this ike_header_t object
* @param response response flag
*
*/
void (*set_response_flag) (ike_header_t *this, bool response);
/**
* @brief get "higher version supported"-flag
*
* @param this ike_header_t object
* @return version flag
*/
bool (*get_version_flag) (ike_header_t *this);
/**
* @brief get the initiator flag
*
* @param this ike_header_t object
* @return initiator flag
*/
bool (*get_initiator_flag) (ike_header_t *this);
/**
* @brief Set the initiator flag
*
* @param this ike_header_t object
* @param initiator initiator flag
*
*/
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
/**
* @brief get the exchange type
*
* @param this ike_header_t object
* @return exchange type
*/
u_int8_t (*get_exchange_type) (ike_header_t *this);
/**
* @brief set the exchange type
*
* @param this ike_header_t object
* @param exchange_type exchange type
*/
void (*set_exchange_type) (ike_header_t *this, u_int8_t exchange_type);
/**
* @brief get the message id
*
* @param this ike_header_t object
* @return message id
*/
u_int32_t (*get_message_id) (ike_header_t *this);
/**
* @brief set the message id
*
* @param this ike_header_t object
* @param initiator_spi message id
*/
void (*set_message_id) (ike_header_t *this, u_int32_t message_id);
/**
* @brief Destroys a ike_header_t object.
*
* @param this ike_header_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (ike_header_t *this);
};
/**
* @brief Create an ike_header_t object
*
* @return
* - created ike_header, or
* - NULL if failed
*/
ike_header_t *ike_header_create();
#endif /*IKE_HEADER_H_*/
@@ -0,0 +1,319 @@
/**
* @file ke_payload.c
*
* @brief Declaration of the class ke_payload_t.
*
* An object of this type represents an IKEv2 KE-Payload.
*
* See section 3.4 of RFC for details of this payload type.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "ke_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/allocator.h>
/**
* Private data of an ke_payload_t Object
*
*/
typedef struct private_ke_payload_s private_ke_payload_t;
struct private_ke_payload_s {
/**
* public ke_payload_t interface
*/
ke_payload_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Critical flag
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* DH Group Number
*/
diffie_hellman_group_t dh_group_number;
/**
* Key Exchange Data of this KE payload
*/
chunk_t key_exchange_data;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_ke_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-KE Payload
*
* The defined offsets are the positions in a object of type
* private_ke_payload_t.
*
*/
encoding_rule_t ke_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_ke_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
/* DH Group number as 16 bit field*/
{ U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
{ RESERVED_BYTE, 0 },
{ RESERVED_BYTE, 0 },
/* Key Exchange Data is from variable size */
{ KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data) }
};
/*
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 !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! DH Group # ! RESERVED !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Key Exchange Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_ke_payload_t *this)
{
if (this->critical)
{
/* critical bit is set! */
return FAILED;
}
/* dh group is not verified in here */
return SUCCESS;
}
/**
* Implements payload_t's and ke_payload_t's destroy function.
* See #payload_s.destroy or ke_payload_s.destroy for description.
*/
static status_t destroy(private_ke_payload_t *this)
{
if (this->key_exchange_data.ptr != NULL)
{
allocator_free(this->key_exchange_data.ptr);
}
allocator_free(this);
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = ke_payload_encodings;
*rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_ke_payload_t *this)
{
return KEY_EXCHANGE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_ke_payload_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_ke_payload_t *this,payload_type_t type)
{
this->next_payload = type;
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_ke_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implements private_ke_payload_t's compute_length function.
* See #private_ke_payload_s.compute_length for description.
*/
static status_t compute_length (private_ke_payload_t *this)
{
size_t length = KE_PAYLOAD_HEADER_LENGTH;
if (this->key_exchange_data.ptr != NULL)
{
length += this->key_exchange_data.len;
}
this->payload_length = length;
return SUCCESS;
}
/**
* Implements ke_payload_t's get_key_exchange_data function.
* See #ke_payload_t.get_key_exchange_data for description.
*/
chunk_t get_key_exchange_data(private_ke_payload_t *this)
{
return (this->key_exchange_data);
}
/**
* Implements ke_payload_t's set_key_exchange_data function.
* See #ke_payload_t.set_key_exchange_data for description.
*/
status_t set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
{
/* destroy existing data first */
if (this->key_exchange_data.ptr != NULL)
{
/* free existing value */
allocator_free(this->key_exchange_data.ptr);
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
}
this->key_exchange_data.ptr = allocator_clone_bytes(key_exchange_data.ptr,key_exchange_data.len);
if (this->key_exchange_data.ptr == NULL)
{
return OUT_OF_RES;
}
this->key_exchange_data.len = key_exchange_data.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implements ke_payload_t's get_dh_group_number function.
* See #ke_payload_t.get_dh_group_number for description.
*/
diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this)
{
return this->dh_group_number;
}
/**
* Implements ke_payload_t's set_dh_group_number function.
* See #ke_payload_t.set_dh_group_number for description.
*/
status_t set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number)
{
this->dh_group_number = dh_group_number;
return SUCCESS;
}
/*
* Described in header
*/
ke_payload_t *ke_payload_create()
{
private_ke_payload_t *this = allocator_alloc_thing(private_ke_payload_t);
if (this == NULL)
{
return NULL;
}
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
this->public.set_key_exchange_data = (status_t (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number;
this->public.set_dh_group_number =(status_t (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number;
this->public.destroy = (status_t (*) (ke_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = KE_PAYLOAD_CRITICAL_FLAG;
this->next_payload = NO_PAYLOAD;
this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
this->key_exchange_data.ptr = NULL;
this->key_exchange_data.len = 0;
this->dh_group_number = 0;
return (&(this->public));
}
@@ -0,0 +1,120 @@
/**
* @file ke_payload.h
*
* @brief Declaration of the class ke_payload_t.
*
* An object of this type represents an IKEv2 KE-Payload.
*
* See section 3.4 of RFC for details of this payload type.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef KE_PAYLOAD_H_
#define KE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <utils/linked_list.h>
/**
* Critical flag must not be set
*/
#define KE_PAYLOAD_CRITICAL_FLAG FALSE;
/**
* KE payload length in bytes without any key exchange data
*/
#define KE_PAYLOAD_HEADER_LENGTH 8
/**
* Object representing an IKEv2-KE Payload
*
* The KE Payload format is described in RFC section 3.4.
*
*/
typedef struct ke_payload_s ke_payload_t;
struct ke_payload_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Returns the currently set key exchange data of this KE payload.
*
* @warning Returned data are not copied.
*
* @param this calling ke_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
/**
* @brief Sets the key exchange data of this KE payload.
*
* @warning Value is getting copied.
*
* @param this calling ke_payload_t object
* @param key_exchange_data chunk_t pointing to the value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data);
/**
* @brief Gets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @return DH Group Number of this payload
*/
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
/**
* @brief Sets the Diffie-Hellman Group Number of this KE payload.
*
* @param this calling ke_payload_t object
* @param dh_group_number DH Group to set
* @return SUCCESS
*/
status_t (*set_dh_group_number) (ke_payload_t *this, diffie_hellman_group_t dh_group_number);
/**
* @brief Destroys an ke_payload_t object.
*
* @param this ke_payload_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (ke_payload_t *this);
};
/**
* @brief Creates an empty ke_payload_t object
*
* @return
* - created ke_payload_t object, or
* - NULL if failed
*/
ke_payload_t *ke_payload_create();
#endif /*KE_PAYLOAD_H_*/
@@ -0,0 +1,271 @@
/**
* @file nonce_payload.h
*
* @brief Declaration of the class nonce_payload_t.
*
* An object of this type represents an IKEv2 Nonce-Payload.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "nonce_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/allocator.h>
/**
* Private data of an nonce_payload_t' Object
*
*/
typedef struct private_nonce_payload_s private_nonce_payload_t;
struct private_nonce_payload_s {
/**
* public nonce_payload_t interface
*/
nonce_payload_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Critical flag
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* the contained nonce value
*/
chunk_t nonce;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_nonce_payload_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_nonce_payload_t *this);
};
/**
* Encoding rules to parse or generate a nonce payload
*
* The defined offsets are the positions in a object of type
* private_nonce_payload_t.
*
*/
encoding_rule_t nonce_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_nonce_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_nonce_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole nonce payload*/
{ PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) },
/* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */
{ NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }
};
/* 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 !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Nonce Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_nonce_payload_t *this)
{
if (this->critical)
{
/* critical bit is set! */
return FAILED;
}
if ((this->nonce.len < 16) || ((this->nonce.len > 256)))
{
/* nonce length is wrong */
return FAILED;
}
return SUCCESS;
}
/**
* Implements nonce_payload_t's set_nonce function.
* See #nonce_payload_t.set_nonce for description.
*/
static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce)
{
if (nonce.len >= 16 && nonce.len <= 256)
{
this->nonce.ptr = allocator_clone_bytes(nonce.ptr, nonce.len);
if (this->nonce.ptr == NULL)
{
return OUT_OF_RES;
}
this->nonce.len = nonce.len;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
return SUCCESS;
}
return INVALID_ARG;
}
/**
* Implements nonce_payload_t's get_nonce function.
* See #nonce_payload_t.get_nonce for description.
*/
static status_t get_nonce(private_nonce_payload_t *this, chunk_t *nonce)
{
nonce->ptr = allocator_clone_bytes(this->nonce.ptr,this->nonce.len);
if (nonce->ptr == NULL)
{
return OUT_OF_RES;
}
nonce->len = this->nonce.len;
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = nonce_payload_encodings;
*rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_nonce_payload_t *this)
{
return NONCE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_nonce_payload_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_nonce_payload_t *this,payload_type_t type)
{
this->next_payload = type;
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_nonce_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implements payload_t's and nonce_payload_t's destroy function.
* See #payload_s.destroy or nonce_payload_s.destroy for description.
*/
static status_t destroy(private_nonce_payload_t *this)
{
if (this->nonce.ptr != NULL)
{
allocator_free(this->nonce.ptr);
}
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
nonce_payload_t *nonce_payload_create()
{
private_nonce_payload_t *this = allocator_alloc_thing(private_nonce_payload_t);
if (this == NULL)
{
return NULL;
}
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.destroy = (status_t (*) (nonce_payload_t *)) destroy;
this->public.set_nonce = (status_t (*) (nonce_payload_t *,chunk_t)) set_nonce;
this->public.get_nonce = (status_t (*) (nonce_payload_t *,chunk_t*)) get_nonce;
/* private variables */
this->critical = FALSE;
this->next_payload = NO_PAYLOAD;
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH;
this->nonce.ptr = NULL;
this->nonce.len = 0;
return (&(this->public));
}
@@ -0,0 +1,93 @@
/**
* @file nonce_payload.h
*
* @brief Declaration of the class nonce_payload_t.
*
* An object of this type represents an IKEv2 Nonce-Payload.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NONCE_PAYLOAD_H_
#define NONCE_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* length of a nonce payload without a nonce in int
*/
#define NONCE_PAYLOAD_HEADER_LENGTH 4
/**
* Object representing an IKEv2 Nonce payload
*
* The Nonce payload format is described in draft section 3.3.
*
*/
typedef struct nonce_payload_s nonce_payload_t;
struct nonce_payload_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Set the nonce value.
*
* The nonce must have length between 16 and 256 bytes
*
* @param this calling nonce_payload_t object
* @param nonce chunk containing the nonce, will be cloned
* @return
* - SUCCESS or
* - INVALID_ARG, if nonce has an invalid size
*/
status_t (*set_nonce) (nonce_payload_t *this, chunk_t nonce);
/**
* @brief Get the nonce value.
*
* @param this calling nonce_payload_t object
* @param[out] nonce chunk where nonce data is located (cloned)
* @return SUCCESS in any case
*/
status_t (*get_nonce) (nonce_payload_t *this, chunk_t *nonce);
/**
* @brief Destroys an nonce_payload_t object.
*
* @param this nonce_payload_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (nonce_payload_t *this);
};
/**
* @brief Creates an empty nonce_payload_t object
*
* @return
* - created nonce_payload_t object, or
* - NULL if failed
*/
nonce_payload_t *nonce_payload_create();
#endif /*NONCE_PAYLOAD_H_*/
@@ -0,0 +1,419 @@
/**
* @file notify_payload.c
*
* @brief Declaration of the class notify_payload_t.
*
* An object of this type represents an IKEv2 Notify-Payload.
*
* See section 3.10 of Draft for details of this payload type.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "notify_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/allocator.h>
/**
* Private data of an notify_payload_t Object
*
*/
typedef struct private_notify_payload_s private_notify_payload_t;
struct private_notify_payload_s {
/**
* public notify_payload_t interface
*/
notify_payload_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Critical flag
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* protocol id
*/
u_int8_t protocol_id;
/**
* spi size
*/
u_int8_t spi_size;
/**
* notify message type
*/
u_int16_t notify_message_type;
/**
* Security parameter index (spi)
*/
chunk_t spi;
/**
* Notification data
*/
chunk_t notification_data;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_ke_payload_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_notify_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-Notify Payload
*
* The defined offsets are the positions in a object of type
* private_notify_payload_t.
*
*/
encoding_rule_t notify_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_notify_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole payload*/
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
/* Protocol ID as 8 bit field*/
{ U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
/* SPI Size as 8 bit field*/
{ SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
/* Notify message type as 16 bit field*/
{ U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
/* SPI as variable length field*/
{ SPI, offsetof(private_notify_payload_t, spi) },
/* Key Exchange Data is from variable size */
{ NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
};
/*
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 !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Protocol ID ! SPI Size ! Notify Message Type !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Security Parameter Index (SPI) ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Notification Data ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_notify_payload_t *this)
{
if (this->critical)
{
/* critical bit is set! */
return FAILED;
}
if (this->protocol_id > 3)
{
/* reserved for future use */
return FAILED;
}
/* notify message types and data is not getting checked in here */
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = notify_payload_encodings;
*rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_notify_payload_t *this)
{
return KEY_EXCHANGE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_notify_payload_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_notify_payload_t *this,payload_type_t type)
{
this->next_payload = type;
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_notify_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implements private_ke_payload_t's compute_length function.
* See #private_ke_payload_s.compute_length for description.
*/
static status_t compute_length (private_notify_payload_t *this)
{
size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
if (this->notification_data.ptr != NULL)
{
length += this->notification_data.len;
}
if (this->spi.ptr != NULL)
{
length += this->spi.len;
}
this->payload_length = length;
return SUCCESS;
}
/**
* Implements notify_payload_t's get_protocol_id function.
* See #notify_payload_s.get_protocol_id for description.
*/
u_int8_t get_protocol_id(private_notify_payload_t *this)
{
return this->protocol_id;
}
/**
* Implements notify_payload_t's set_protocol_id function.
* See #notify_payload_s.set_protocol_id for description.
*/
status_t set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
return SUCCESS;
}
/**
* Implements notify_payload_t's get_notification_data function.
* See #notify_payload_s.get_notification_data for description.
*/
u_int16_t get_notify_message_type(private_notify_payload_t *this)
{
return this->notify_message_type;
}
/**
* Implements notify_payload_t's get_notification_data function.
* See #notify_payload_s.get_notification_data for description.
*/
status_t set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
{
this->notify_message_type = notify_message_type;
return SUCCESS;
}
/**
* Implements notify_payload_t's get_spi function.
* See #notify_payload_s.get_spi for description.
*/
chunk_t get_spi(private_notify_payload_t *this)
{
return (this->spi);
}
/**
* Implements notify_payload_t's set_spi function.
* See #notify_payload_s.set_spi for description.
*/
status_t set_spi(private_notify_payload_t *this, chunk_t spi)
{
/* destroy existing data first */
if (this->spi.ptr != NULL)
{
/* free existing value */
allocator_free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
}
this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
if (this->spi.ptr == NULL)
{
return OUT_OF_RES;
}
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implements notify_payload_t's get_notification_data function.
* See #notify_payload_s.get_notification_data for description.
*/
chunk_t get_notification_data(private_notify_payload_t *this)
{
return (this->notification_data);
}
/**
* Implements notify_payload_t's get_notification_data function.
* See #notify_payload_s.get_notification_data for description.
*/
status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
{
/* destroy existing data first */
if (this->notification_data.ptr != NULL)
{
/* free existing value */
allocator_free(this->notification_data.ptr);
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
}
this->notification_data.ptr = allocator_clone_bytes(notification_data.ptr,notification_data.len);
if (this->notification_data.ptr == NULL)
{
return OUT_OF_RES;
}
this->notification_data.len = notification_data.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implements payload_t's and notify_payload_t's destroy function.
* See #payload_s.destroy or notify_payload_s.destroy for description.
*/
static status_t destroy(private_notify_payload_t *this)
{
if (this->notification_data.ptr != NULL)
{
allocator_free(this->notification_data.ptr);
}
if (this->spi.ptr != NULL)
{
allocator_free(this->spi.ptr);
}
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
notify_payload_t *notify_payload_create()
{
private_notify_payload_t *this = allocator_alloc_thing(private_notify_payload_t);
if (this == NULL)
{
return NULL;
}
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
this->public.set_protocol_id = (status_t (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
this->public.set_notify_message_type = (status_t (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
this->public.set_spi = (status_t (*) (notify_payload_t *,chunk_t)) set_spi;
this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
this->public.set_notification_data = (status_t (*) (notify_payload_t *,chunk_t)) set_notification_data;
this->public.destroy = (status_t (*) (notify_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = NOTIFY_PAYLOAD_CRITICAL_FLAG;
this->next_payload = NO_PAYLOAD;
this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
this->protocol_id = 0;
this->notify_message_type = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->notification_data.ptr = NULL;
this->notification_data.len = 0;
return (&(this->public));
}
@@ -0,0 +1,159 @@
/**
* @file notify_payload.h
*
* @brief Declaration of the class notify_payload_t.
*
* An object of this type represents an IKEv2 Notify-Payload.
*
* See section 3.10 of Draft for details of this payload type.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NOTIFY_PAYLOAD_H_
#define NOTIFY_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <utils/linked_list.h>
/**
* Critical flag must not be set
*/
#define NOTIFY_PAYLOAD_CRITICAL_FLAG FALSE;
/**
* Notify payload length in bytes without any spi and notification data
*/
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
/**
* Object representing an IKEv2-Notify Payload
*
* The Notify Payload format is described in Draft section 3.10.
*
*/
typedef struct notify_payload_s notify_payload_t;
struct notify_payload_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Gets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @return protocol id of this payload
*/
u_int8_t (*get_protocol_id) (notify_payload_t *this);
/**
* @brief Sets the protocol id of this payload.
*
* @param this calling notify_payload_t object
* @param protocol_id protocol id to set
* @return SUCCESS
*/
status_t (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id);
/**
* @brief Gets the notify message type of this payload.
*
* @param this calling notify_payload_t object
* @return notify message type of this payload
*/
u_int16_t (*get_notify_message_type) (notify_payload_t *this);
/**
* @brief Sets notify message type of this payload.
*
* @param this calling notify_payload_t object
* @param notify_message_type notify message type to set
* @return SUCCESS
*/
status_t (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type);
/**
* @brief Returns the currently set spi of this payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (notify_payload_t *this);
/**
* @brief Sets the spi of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param spi chunk_t pointing to the value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_spi) (notify_payload_t *this, chunk_t spi);
/**
* @brief Returns the currently set notification data of payload.
*
* @warning Returned data are not copied.
*
* @param this calling notify_payload_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_notification_data) (notify_payload_t *this);
/**
* @brief Sets the notification data of this payload.
*
* @warning Value is getting copied.
*
* @param this calling notify_payload_t object
* @param notification_data chunk_t pointing to the value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_notification_data) (notify_payload_t *this, chunk_t notification_data);
/**
* @brief Destroys an notify_payload_t object.
*
* @param this notify_payload_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (notify_payload_t *this);
};
/**
* @brief Creates an empty notify_payload_t object
*
* @return
* - created notify_payload_t object, or
* - NULL if failed
*/
notify_payload_t *notify_payload_create();
#endif /*NOTIFY_PAYLOAD_H_*/
+92
View File
@@ -0,0 +1,92 @@
/**
* @file payload.c
*
* @brief Generic payload interface
*
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "payload.h"
#include <encoding/payloads/ike_header.h>
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/ke_payload.h>
#include <encoding/payloads/notify_payload.h>
/*
* build the mappings for payload_type_t
*/
mapping_t payload_type_m[] = {
{NO_PAYLOAD, "NO_PAYLOAD"},
{SECURITY_ASSOCIATION, "SECURITY_ASSOCIATION"},
{KEY_EXCHANGE, "KEY_EXCHANGE"},
{ID_INITIATOR, "ID_INITIATOR"},
{ID_RESPONDER, "ID_RESPONDER"},
{CERTIFICATE, "CERTIFICATE"},
{CERTIFICATE_REQUEST, "CERTIFICATE_REQUEST"},
{AUTHENTICATION, "AUTHENTICATION"},
{NONCE, "NONCE"},
{NOTIFY, "NOTIFY"},
{DELETE, "DELETE"},
{VENDOR_ID, "VENDOR_ID"},
{TRAFFIC_SELECTOR_INITIATOR, "TRAFFIC_SELECTOR_INITIATOR"},
{TRAFFIC_SELECTOR_RESPONDER, "TRAFFIC_SELECTOR_RESPONDER"},
{ENCRYPTED, "ENCRYPTED"},
{CONFIGURATION, "CONFIGURATION"},
{EXTENSIBLE_AUTHENTICATION, "EXTENSIBLE_AUTHENTICATION"},
{HEADER, "HEADER"},
{PROPOSAL_SUBSTRUCTURE, "PROPOSAL_SUBSTRUCTURE"},
{TRANSFORM_SUBSTRUCTURE, "TRANSFORM_SUBSTRUCTURE"},
{TRANSFORM_ATTRIBUTE, "TRANSFORM_ATTRIBUTE"},
{MAPPING_END, NULL}
};
/*
* see header
*/
payload_t *payload_create(payload_type_t type)
{
switch (type)
{
case HEADER:
return (payload_t*)ike_header_create();
case SECURITY_ASSOCIATION:
return (payload_t*)sa_payload_create();
case PROPOSAL_SUBSTRUCTURE:
return (payload_t*)proposal_substructure_create();
case TRANSFORM_SUBSTRUCTURE:
return (payload_t*)transform_substructure_create();
case TRANSFORM_ATTRIBUTE:
return (payload_t*)transform_attribute_create();
case NONCE:
return (payload_t*)nonce_payload_create();
case KEY_EXCHANGE:
return (payload_t*)ke_payload_create();
case NOTIFY:
return (payload_t*)notify_payload_create();
default:
return NULL;
}
}
+240
View File
@@ -0,0 +1,240 @@
/**
* @file payload.h
*
* @brief Generic payload interface
*
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PAYLOAD_H_
#define PAYLOAD_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/encodings.h>
/**
* Payload-Types of a IKEv2-Message
*
*
* Header and substructures are also defined as
* payload types with values from PRIVATE USE space.
*/
typedef enum payload_type_e payload_type_t;
enum payload_type_e{
/**
* NO_PAYLOAD
*/
NO_PAYLOAD = 0,
/**
* SA
*/
SECURITY_ASSOCIATION = 33,
/**
* KE
*/
KEY_EXCHANGE = 34,
/**
* IDi
*/
ID_INITIATOR = 35,
/**
* IDr
*/
ID_RESPONDER = 36,
/**
* CERT
*/
CERTIFICATE = 37,
/**
* CERTREQ
*/
CERTIFICATE_REQUEST = 38,
/**
* AUTH
*/
AUTHENTICATION = 39,
/**
* Ni, Nr
*/
NONCE = 40,
/**
* N
*/
NOTIFY = 41,
/**
* D
*/
DELETE = 42,
/**
* V
*/
VENDOR_ID = 43,
/**
* TSi
*/
TRAFFIC_SELECTOR_INITIATOR = 44,
/**
* TSr
*/
TRAFFIC_SELECTOR_RESPONDER = 45,
/**
* E
*/
ENCRYPTED = 46,
/**
* CP
*/
CONFIGURATION = 47,
/**
* EAP
*/
EXTENSIBLE_AUTHENTICATION = 48,
/**
* Header has a value of PRIVATE USE space
*
* This payload type is not send over wire and just
* used internally to handle IKEv2-Header like a payload.
*/
HEADER = 140,
/**
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space
*
* This payload type is not send over wire and just
* used internally to handle a proposal substructure like a payload.
*/
PROPOSAL_SUBSTRUCTURE = 141,
/**
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space
*
* This payload type is not send over wire and just
* used internally to handle a transform substructure like a payload.
*/
TRANSFORM_SUBSTRUCTURE = 142,
/**
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space
*
* This payload type is not send over wire and just
* used internally to handle a transform attribute like a payload.
*/
TRANSFORM_ATTRIBUTE = 143,
};
/*
* build string mapping array for payload_type_t
*/
extern mapping_t payload_type_m[];
/**
* @brief Generic interface for all payload types (inclusive
* header and substructures)
*
*
*/
typedef struct payload_s payload_t;
struct payload_s {
/**
* @brief Destroys a payload and all included substructures.
*
* @param this payload to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (payload_t *this);
/**
* @brief Get encoding rules for this payload
*
* @param this calling object
* @param[out] rules location to store pointer of first rule
* @param[out] rule_count location to store number of rules
* @return
* SUCCESS in any case
*/
status_t (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
/**
* @brief get type of payload
*
* @param this calling object
* @return type of this payload
*/
payload_type_t (*get_type) (payload_t *this);
/**
* @brief get type of next payload or zero if this is the last one
*
* @param this calling object
* @return type of next payload
*/
payload_type_t (*get_next_type) (payload_t *this);
/**
* @brief set type of next payload
*
* @param this calling object
* @param type type of next payload
* @return SUCCESS in any case
*/
status_t (*set_next_type) (payload_t *this,payload_type_t type);
/**
* @brief get length of payload
*
* @param this calling object
* @return length of this payload
*/
size_t (*get_length) (payload_t *this);
/**
* @brief Verifies payload structure and makes consistence check
*
* @param this calling object
* @return
* - SUCCESS
* - FAILED if consistence not given
*/
status_t (*verify) (payload_t *this);
};
/**
* @brief Create an empty payload.
*
* Useful for the parser, who wants a generic constructor for all payloads.
* It supports all payload_t methods.
*
* @param type type of the payload to create
* @return
* - created payload, or
* - NULL if failed
*/
payload_t *payload_create(payload_type_t type);
#endif /*PAYLOAD_H_*/
@@ -0,0 +1,512 @@
/**
* @file proposal_substructure.h
*
* @brief Declaration of the class proposal_substructure_t.
*
* An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "proposal_substructure.h"
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/transform_substructure.h>
#include <types.h>
#include <utils/allocator.h>
#include <utils/linked_list.h>
/**
* Private data of an proposal_substructure_t' Object
*
*/
typedef struct private_proposal_substructure_s private_proposal_substructure_t;
struct private_proposal_substructure_s {
/**
* public proposal_substructure_t interface
*/
proposal_substructure_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Length of this payload
*/
u_int16_t proposal_length;
/**
* Proposal number
*/
u_int8_t proposal_number;
/**
* Protocol ID
*/
u_int8_t protocol_id;
/**
* SPI size of the following SPI
*/
u_int8_t spi_size;
/**
* Number of transforms
*/
u_int8_t transforms_count;
/**
* SPI is stored as chunk
*/
chunk_t spi;
/**
* Transforms are stored in a linked_list_t
*/
linked_list_t * transforms;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_proposal_substructure_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_proposal_substructure_t *this);
};
/**
* Encoding rules to parse or generate a Proposal substructure
*
* The defined offsets are the positions in a object of type
* private_proposal_substructure_t.
*
*/
encoding_rule_t proposal_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole proposal substructure payload*/
{ PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
/* proposal number is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
/* protocol ID is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
/* SPI Size has its own type */
{ SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
/* Number of transforms is a number of 8 bit */
{ U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
/* SPI is a chunk of variable size*/
{ SPI, offsetof(private_proposal_substructure_t, spi) },
/* Transforms are stored in a transform substructure,
offset points to a linked_list_t pointer */
{ TRANSFORMS, offsetof(private_proposal_substructure_t, transforms) }
};
/*
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 2 ! RESERVED ! Proposal Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ SPI (variable) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Transforms> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_proposal_substructure_t *this)
{
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != PROPOSAL_SUBSTRUCTURE))
{
/* must be 0 or 2 */
return FAILED;
}
if (this->transforms_count != this->transforms->get_count(this->transforms))
{
/* must be the same! */
return FAILED;
}
if (this->protocol_id > 4)
{
/* reserved are not supported */
return FAILED;
}
/* proposal number is checked in SA payload */
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_proposal_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = proposal_substructure_encodings;
*rule_count = sizeof(proposal_substructure_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_proposal_substructure_t *this)
{
return PROPOSAL_SUBSTRUCTURE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_proposal_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_proposal_substructure_t *this,payload_type_t type)
{
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_proposal_substructure_t *this)
{
return this->proposal_length;
}
/**
* Implements proposal_substructure_t's create_transform_substructure_iterator function.
* See #proposal_substructure_s.create_transform_substructure_iterator for description.
*/
static status_t create_transform_substructure_iterator (private_proposal_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
{
return (this->transforms->create_iterator(this->transforms,iterator,forward));
}
/**
* Implements proposal_substructure_t's add_transform_substructure function.
* See #proposal_substructure_s.add_transform_substructure for description.
*/
static status_t add_transform_substructure (private_proposal_substructure_t *this,transform_substructure_t *transform)
{
status_t status;
if (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *last_transform;
status = this->transforms->get_last(this->transforms,(void **) &last_transform);
/* last transform is now not anymore last one */
last_transform->set_is_last_transform(last_transform,FALSE);
}
transform->set_is_last_transform(transform,TRUE);
status = this->transforms->insert_last(this->transforms,(void *) transform);
this->compute_length(this);
return status;
}
/**
* Implements proposal_substructure_t's set_proposal_number function.
* See #proposal_substructure_s.set_proposal_number for description.
*/
static status_t set_proposal_number(private_proposal_substructure_t *this,u_int8_t proposal_number)
{
this->proposal_number = proposal_number;
return SUCCESS;
}
/**
* Implements proposal_substructure_t's get_proposal_number function.
* See #proposal_substructure_s.get_proposal_number for description.
*/
static u_int8_t get_proposal_number (private_proposal_substructure_t *this)
{
return (this->proposal_number);
}
/**
* Implements proposal_substructure_t's set_protocol_id function.
* See #proposal_substructure_s.set_protocol_id for description.
*/
static status_t set_protocol_id(private_proposal_substructure_t *this,u_int8_t protocol_id)
{
this->protocol_id = protocol_id;
return SUCCESS;
}
/**
* Implements proposal_substructure_t's get_protocol_id function.
* See #proposal_substructure_s.get_protocol_id for description.
*/
static u_int8_t get_protocol_id (private_proposal_substructure_t *this)
{
return (this->protocol_id);
}
/**
* Implements proposal_substructure_t's set_spi function.
* See #proposal_substructure_s.set_spi for description.
*/
static status_t set_spi (private_proposal_substructure_t *this, chunk_t spi)
{
/* first delete already set spi value */
if (this->spi.ptr != NULL)
{
allocator_free(this->spi.ptr);
this->spi.ptr = NULL;
this->spi.len = 0;
this->compute_length(this);
}
this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
if (this->spi.ptr == NULL)
{
return OUT_OF_RES;
}
this->spi.len = spi.len;
this->spi_size = spi.len;
this->compute_length(this);
return SUCCESS;
}
/**
* Implements proposal_substructure_t's get_spi function.
* See #proposal_substructure_s.get_spi for description.
*/
static chunk_t get_spi (private_proposal_substructure_t *this)
{
chunk_t spi;
spi.ptr = this->spi.ptr;
spi.len = this->spi.len;
return spi;
}
/**
* Implements private_proposal_substructure_t's compute_length function.
* See #private_proposal_substructure_s.compute_length for description.
*/
static status_t compute_length (private_proposal_substructure_t *this)
{
linked_list_iterator_t *iterator;
status_t status;
size_t transforms_count = 0;
size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
status = this->transforms->create_iterator(this->transforms,&iterator,TRUE);
if (status != SUCCESS)
{
return length;
}
while (iterator->has_next(iterator))
{
payload_t * current_transform;
iterator->current(iterator,(void **) &current_transform);
length += current_transform->get_length(current_transform);
transforms_count++;
}
iterator->destroy(iterator);
length += this->spi.len;
this->transforms_count= transforms_count;
this->proposal_length = length;
return SUCCESS;
}
/**
* Implements proposal_substructure_t's clone function.
* See #proposal_substructure_s.clone for description.
*/
static status_t clone(private_proposal_substructure_t *this, private_proposal_substructure_t **clone)
{
private_proposal_substructure_t * new_clone;
linked_list_iterator_t *transforms;
status_t status;
new_clone = (private_proposal_substructure_t *) proposal_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->proposal_number = this->proposal_number;
new_clone->protocol_id = this->protocol_id;
new_clone->spi_size = this->spi_size;
if (this->spi.ptr != NULL)
{
new_clone->spi.ptr = allocator_clone_bytes(this->spi.ptr,this->spi.len);
if (new_clone->spi.ptr == NULL)
{
new_clone->public.destroy(&(new_clone->public));
return OUT_OF_RES;
}
new_clone->spi.len = this->spi.len;
}
status = this->transforms->create_iterator(this->transforms,&transforms,FALSE);
if (status != SUCCESS)
{
new_clone->public.destroy(&(new_clone->public));
return status;
}
while (transforms->has_next(transforms))
{
transform_substructure_t *current_transform;
transform_substructure_t *current_transform_clone;
status = transforms->current(transforms,(void **) &current_transform);
if (status != SUCCESS)
{
transforms->destroy(transforms);
new_clone->public.destroy(&(new_clone->public));
return status;
}
status = current_transform->clone(current_transform,&current_transform_clone);
if (status != SUCCESS)
{
transforms->destroy(transforms);
new_clone->public.destroy(&(new_clone->public));
return status;
}
status = new_clone->public.add_transform_substructure(&(new_clone->public),current_transform_clone);
if (status != SUCCESS)
{
transforms->destroy(transforms);
current_transform_clone->destroy(current_transform_clone);
new_clone->public.destroy(&(new_clone->public));
return status;
}
}
transforms->destroy(transforms);
*clone = new_clone;
return SUCCESS;
}
/**
* Implements payload_t's and proposal_substructure_t's destroy function.
* See #payload_s.destroy or proposal_substructure_s.destroy for description.
*/
static status_t destroy(private_proposal_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->transforms->get_count(this->transforms) > 0)
{
transform_substructure_t *current_transform;
if (this->transforms->remove_last(this->transforms,(void **)&current_transform) != SUCCESS)
{
break;
}
current_transform->destroy(current_transform);
}
this->transforms->destroy(this->transforms);
if (this->spi.ptr != NULL)
{
allocator_free(this->spi.ptr);
}
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
proposal_substructure_t *proposal_substructure_create()
{
private_proposal_substructure_t *this = allocator_alloc_thing(private_proposal_substructure_t);
if (this == NULL)
{
return NULL;
}
/* interface functions */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_substructure_iterator = (status_t (*) (proposal_substructure_t *,linked_list_iterator_t **,bool)) create_transform_substructure_iterator;
this->public.add_transform_substructure = (status_t (*) (proposal_substructure_t *,transform_substructure_t *)) add_transform_substructure;
this->public.set_proposal_number = (status_t (*) (proposal_substructure_t *,u_int8_t))set_proposal_number;
this->public.get_proposal_number = (u_int8_t (*) (proposal_substructure_t *)) get_proposal_number;
this->public.set_protocol_id = (status_t (*) (proposal_substructure_t *,u_int8_t))set_protocol_id;
this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id;
this->public.set_spi = (status_t (*) (proposal_substructure_t *,chunk_t))set_spi;
this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi;
this->public.clone = (status_t (*) (proposal_substructure_t *, proposal_substructure_t **)) clone;
this->public.destroy = (status_t (*) (proposal_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->proposal_length = 0;
this->proposal_number = 0;
this->protocol_id = 0;
this->transforms_count = 0;
this->spi_size = 0;
this->spi.ptr = NULL;
this->spi.len = 0;
this->transforms = linked_list_create();
if (this->transforms == NULL)
{
allocator_free(this);
return NULL;
}
return (&(this->public));
}
@@ -0,0 +1,186 @@
/**
* @file proposal_substructure.h
*
* @brief Declaration of the class proposal_substructure_t.
*
* An object of this type represents an IKEv2 PROPOSAL Substructure and contains transforms.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PROPOSAL_SUBSTRUCTURE_H_
#define PROPOSAL_SUBSTRUCTURE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_substructure.h>
#include <utils/linked_list.h>
/**
* Length of the proposal substructure header
* (without spi)
*/
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
/**
* Protocol ID of a proposal
*/
typedef enum protocol_id_e protocol_id_t;
enum protocol_id_e {
UNDEFINED_PROTOCOL_ID = 201,
IKE = 1,
AH = 2,
ESP = 3,
};
/**
* Object representing an IKEv2- PROPOSAL SUBSTRUCTURE
*
* The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
*
*/
typedef struct proposal_substructure_s proposal_substructure_t;
struct proposal_substructure_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
* When deleting any transform over this iterator, call
* get_size to make sure the length and number values are ok.
*
* @param this calling proposal_substructure_t object
* @param iterator the created iterator is stored at the pointed pointer
* @param[in] forward iterator direction (TRUE: front to end)
* @return
* - SUCCESS or
* - OUT_OF_RES if iterator could not be created
*/
status_t (*create_transform_substructure_iterator) (proposal_substructure_t *this,linked_list_iterator_t **iterator, bool forward);
/**
* @brief Adds a transform_substructure_t object to this object.
*
* @warning The added transform_substructure_t object is
* getting destroyed in destroy function of proposal_substructure_t.
*
* @param this calling proposal_substructure_t object
* @param transform transform_substructure_t object to add
* @return - SUCCESS if succeeded
* - FAILED otherwise
*/
status_t (*add_transform_substructure) (proposal_substructure_t *this,transform_substructure_t *transform);
/**
* @brief Sets the proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id proposal number to set
* @return - SUCCESS
*/
status_t (*set_proposal_number) (proposal_substructure_t *this,u_int8_t proposal_number);
/**
* @brief get proposal number of current proposal.
*
* @param this calling proposal_substructure_t object
* @return proposal number of current proposal substructure.
*/
u_int8_t (*get_proposal_number) (proposal_substructure_t *this);
/**
* @brief Sets the protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @param id protocol id to set
* @return - SUCCESS
*/
status_t (*set_protocol_id) (proposal_substructure_t *this,u_int8_t protocol_id);
/**
* @brief get protocol id of current proposal.
*
* @param this calling proposal_substructure_t object
* @return protocol id of current proposal substructure.
*/
u_int8_t (*get_protocol_id) (proposal_substructure_t *this);
/**
* @brief Returns the currently set SPI of this proposal.
*
* @warning Returned data are not copied
*
* @param this calling proposal_substructure_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_spi) (proposal_substructure_t *this);
/**
* @brief Sets the SPI of the current proposal.
*
* @warning SPI is getting copied
*
* @param this calling proposal_substructure_t object
* @param spi chunk_t pointing to the value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_spi) (proposal_substructure_t *this, chunk_t spi);
/**
* @brief Clones an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to clone
* @param clone cloned object will be written there
* @return
* - SUCCESS
* - OUT_OF_RES
*/
status_t (*clone) (proposal_substructure_t *this,proposal_substructure_t **clone);
/**
* @brief Destroys an proposal_substructure_t object.
*
* @param this proposal_substructure_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (proposal_substructure_t *this);
};
/**
* @brief Creates an empty proposal_substructure_t object
*
* @return
* - created proposal_substructure_t object, or
* - NULL if failed
*/
proposal_substructure_t *proposal_substructure_create();
#endif /*PROPOSAL_SUBSTRUCTURE_H_*/
@@ -0,0 +1,343 @@
/**
* @file sa_payload.c
*
* @brief Declaration of the class sa_payload_t.
*
* An object of this type represents an IKEv2 SA-Payload and contains proposal
* substructures.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "sa_payload.h"
#include <encoding/payloads/encodings.h>
#include <utils/allocator.h>
#include <utils/linked_list.h>
/**
* Private data of an sa_payload_t' Object
*
*/
typedef struct private_sa_payload_s private_sa_payload_t;
struct private_sa_payload_s {
/**
* public sa_payload_t interface
*/
sa_payload_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Critical flag
*/
bool critical;
/**
* Length of this payload
*/
u_int16_t payload_length;
/**
* Proposals in this payload are stored in a linked_list_t
*/
linked_list_t * proposals;
/**
* @brief Computes the length of this payload.
*
* @param this calling private_sa_payload_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_sa_payload_t *this);
};
/**
* Encoding rules to parse or generate a IKEv2-SA Payload
*
* The defined offsets are the positions in a object of type
* private_sa_payload_t.
*
*/
encoding_rule_t sa_payload_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
/* the critical bit */
{ FLAG, offsetof(private_sa_payload_t, critical) },
/* 7 Bit reserved bits, nowhere stored */
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
{ RESERVED_BIT, 0 },
/* Length of the whole SA payload*/
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ PROPOSALS, offsetof(private_sa_payload_t, proposals) }
};
/*
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 !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ <Proposals> ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_sa_payload_t *this)
{
int proposal_number = 1;
status_t status;
linked_list_iterator_t *iterator;
bool first = TRUE;
if (this->critical)
{
/* critical bit set! */
return FAILED;
}
/* check proposal numbering */
status = this->proposals->create_iterator(this->proposals,&iterator,TRUE);
if (status != SUCCESS)
{
return status;
}
while(iterator->has_next(iterator))
{
proposal_substructure_t *current_proposal;
status = iterator->current(iterator,(void **)&current_proposal);
{
break;
}
if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
{
if (first)
{
/* first number must be 1 */
status = FAILED;
break;
}
if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
{
/* must be only one more then previous proposal */
status = FAILED;
break;
}
}
else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
{
iterator->destroy(iterator);
/* must not be smaller then proceeding one */
status = FAILED;
break;
}
first = FALSE;
}
iterator->destroy(iterator);
return status;
}
/**
* Implements payload_t's and sa_payload_t's destroy function.
* See #payload_s.destroy or sa_payload_s.destroy for description.
*/
static status_t destroy(private_sa_payload_t *this)
{
/* all proposals are getting destroyed */
while (this->proposals->get_count(this->proposals) > 0)
{
proposal_substructure_t *current_proposal;
if (this->proposals->remove_last(this->proposals,(void **)&current_proposal) != SUCCESS)
{
break;
}
current_proposal->destroy(current_proposal);
}
this->proposals->destroy(this->proposals);
allocator_free(this);
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = sa_payload_encodings;
*rule_count = sizeof(sa_payload_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_sa_payload_t *this)
{
return SECURITY_ASSOCIATION;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_sa_payload_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_sa_payload_t *this,payload_type_t type)
{
this->next_payload = type;
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_sa_payload_t *this)
{
this->compute_length(this);
return this->payload_length;
}
/**
* Implements sa_payload_t's create_proposal_substructure_iterator function.
* See #sa_payload_s.create_proposal_substructure_iterator for description.
*/
static status_t create_proposal_substructure_iterator (private_sa_payload_t *this,linked_list_iterator_t **iterator,bool forward)
{
return (this->proposals->create_iterator(this->proposals,iterator,forward));
}
/**
* Implements sa_payload_t's add_proposal_substructure function.
* See #sa_payload_s.add_proposal_substructure for description.
*/
static status_t add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal)
{
status_t status;
status = this->proposals->insert_last(this->proposals,(void *) proposal);
this->compute_length(this);
return status;
}
/**
* Implements private_sa_payload_t's compute_length function.
* See #private_sa_payload_s.compute_length for description.
*/
static status_t compute_length (private_sa_payload_t *this)
{
linked_list_iterator_t *iterator;
status_t status;
size_t length = SA_PAYLOAD_HEADER_LENGTH;
status = this->proposals->create_iterator(this->proposals,&iterator,TRUE);
if (status != SUCCESS)
{
return length;
}
while (iterator->has_next(iterator))
{
payload_t *current_proposal;
iterator->current(iterator,(void **) &current_proposal);
length += current_proposal->get_length(current_proposal);
}
iterator->destroy(iterator);
this->payload_length = length;
return SUCCESS;
}
/*
* Described in header
*/
sa_payload_t *sa_payload_create()
{
private_sa_payload_t *this = allocator_alloc_thing(private_sa_payload_t);
if (this == NULL)
{
return NULL;
}
/* public interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.create_proposal_substructure_iterator = (status_t (*) (sa_payload_t *,linked_list_iterator_t **,bool)) create_proposal_substructure_iterator;
this->public.add_proposal_substructure = (status_t (*) (sa_payload_t *,proposal_substructure_t *)) add_proposal_substructure;
this->public.destroy = (status_t (*) (sa_payload_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->critical = SA_PAYLOAD_CRITICAL_FLAG;
this->next_payload = NO_PAYLOAD;
this->payload_length = SA_PAYLOAD_HEADER_LENGTH;
this->proposals = linked_list_create();
if (this->proposals == NULL)
{
allocator_free(this);
return NULL;
}
return (&(this->public));
}
@@ -0,0 +1,110 @@
/**
* @file sa_payload.h
*
* @brief Declaration of the class sa_payload_t.
*
* An object of this type represents an IKEv2 SA-Payload and contains proposal
* substructures.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef SA_PAYLOAD_H_
#define SA_PAYLOAD_H_
#include <types.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/proposal_substructure.h>
#include <utils/linked_list.h>
/**
* Critical flag must not be set
*/
#define SA_PAYLOAD_CRITICAL_FLAG FALSE;
/**
* SA_PAYLOAD length in bytes without any proposal substructure
*/
#define SA_PAYLOAD_HEADER_LENGTH 4
/**
* Object representing an IKEv2-SA Payload
*
* The SA Payload format is described in RFC section 3.3.
*
*/
typedef struct sa_payload_s sa_payload_t;
struct sa_payload_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored proposal_substructure_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an proposal using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling sa_payload_t object
* @param iterator the created iterator is stored at the pointed pointer
* @param[in] forward iterator direction (TRUE: front to end)
* @return
* - SUCCESS or
* - OUT_OF_RES if iterator could not be created
*/
status_t (*create_proposal_substructure_iterator) (sa_payload_t *this,linked_list_iterator_t **iterator, bool forward);
/**
* @brief Adds a proposal_substructure_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of sa_payload_t.
*
* @param this calling sa_payload_t object
* @param proposal proposal_substructure_t object to add
* @return - SUCCESS if succeeded
* - FAILED otherwise
*/
status_t (*add_proposal_substructure) (sa_payload_t *this,proposal_substructure_t *proposal);
/**
* @brief Destroys an sa_payload_t object.
*
* @param this sa_payload_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (sa_payload_t *this);
};
/**
* @brief Creates an empty sa_payload_t object
*
* @return
* - created sa_payload_t object, or
* - NULL if failed
*/
sa_payload_t *sa_payload_create();
#endif /*SA_PAYLOAD_H_*/
@@ -0,0 +1,363 @@
/**
* @file transform_attribute.c
*
* @brief Declaration of the class transform_attribute_t.
*
* An object of this type represents an IKEv2 TRANSFORM attribute.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "transform_attribute.h"
#include <encoding/payloads/encodings.h>
#include <types.h>
#include <utils/allocator.h>
/**
* Private data of an transform_attribute_t Object
*
*/
typedef struct private_transform_attribute_s private_transform_attribute_t;
struct private_transform_attribute_s {
/**
* public transform_attribute_t interface
*/
transform_attribute_t public;
/**
* Attribute Format Flag
*
* - TRUE means value is stored in attribute_length_or_value
* - FALSE means value is stored in attribute_value
*/
bool attribute_format;
/**
* Type of the attribute
*/
u_int16_t attribute_type;
/**
* Attribute Length if attribute_format is 0, attribute Value otherwise
*/
u_int16_t attribute_length_or_value;
/**
* Attribute value as chunk if attribute_format is 0 (FALSE)
*/
chunk_t attribute_value;
};
/**
* string mappings for transform_attribute_type_t
*/
mapping_t transform_attribute_type_m[] = {
{ATTRIBUTE_UNDEFINED, "ATTRIBUTE_UNDEFINED"},
{KEY_LENGTH, "KEY_LENGTH"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a Transform attribute
*
* The defined offsets are the positions in a object of type
* private_transform_attribute_t.
*
*/
encoding_rule_t transform_attribute_encodings[] = {
/* Flag defining the format of this payload */
{ ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
/* Length or value, depending on the attribute format flag */
{ ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) },
/* Value of attribute if attribute format flag is zero */
{ ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!A! Attribute Type ! AF=0 Attribute Length !
!F! ! AF=1 Attribute Value !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! AF=0 Attribute Value !
! AF=1 Not Transmitted !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_transform_attribute_t *this)
{
if (this->attribute_type != KEY_LENGTH)
{
return FAILED;
}
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_attribute_encodings;
*rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_transform_attribute_t *this)
{
return (NO_PAYLOAD);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_transform_attribute_t *this,payload_type_t type)
{
return SUCCESS;
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_transform_attribute_t *this)
{
if (this->attribute_format == TRUE)
{
/*Attribute size is only 4 byte */
return 4;
}
return (this->attribute_length_or_value + 4);
}
/**
* Implements transform_attribute_t's set_value function.
* See #transform_attribute_s.set_value for description.
*/
static status_t set_value_chunk(private_transform_attribute_t *this, chunk_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
allocator_free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
if (value.len > 2)
{
this->attribute_value.ptr = allocator_clone_bytes(value.ptr,value.len);
if (this->attribute_value.ptr == NULL)
{
return OUT_OF_RES;
}
this->attribute_value.len = value.len;
this->attribute_length_or_value = value.len;
/* attribute has not a fixed length */
this->attribute_format = FALSE;
}
else
{
memcpy(&(this->attribute_length_or_value),value.ptr,value.len);
}
return SUCCESS;
}
/**
* Implements transform_attribute_t's set_value function.
* See #transform_attribute_s.set_value for description.
*/
static status_t set_value(private_transform_attribute_t *this, u_int16_t value)
{
if (this->attribute_value.ptr != NULL)
{
/* free existing value */
allocator_free(this->attribute_value.ptr);
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
}
this->attribute_length_or_value = value;
return SUCCESS;
}
/**
* Implements transform_attribute_t's get_value_chunk function.
* See #transform_attribute_s.get_value_chunk for description.
*/
static chunk_t get_value_chunk (private_transform_attribute_t *this)
{
chunk_t value;
if (this->attribute_format == FALSE)
{
value.ptr = this->attribute_value.ptr;
value.len = this->attribute_value.len;
}
else
{
value.ptr = (void *) &(this->attribute_length_or_value);
value.len = 2;
}
return value;
}
/**
* Implements transform_attribute_t's get_value function.
* See #transform_attribute_s.get_value for description.
*/
static u_int16_t get_value (private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
/**
* Implements transform_attribute_t's set_attribute_type function.
* See #transform_attribute_s.set_attribute_type for description.
*/
static status_t set_attribute_type (private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
return SUCCESS;
}
/**
* Implements transform_attribute_t's get_attribute_type function.
* See #transform_attribute_s.get_attribute_type for description.
*/
static u_int16_t get_attribute_type (private_transform_attribute_t *this)
{
return this->attribute_type;
}
/**
* Implements transform_attribute_t's clone function.
* See transform_attribute_s.clone for description.
*/
static status_t clone(private_transform_attribute_t *this,transform_attribute_t **clone)
{
private_transform_attribute_t *new_clone;
new_clone = (private_transform_attribute_t *) transform_attribute_create();
new_clone->attribute_format = this->attribute_format;
new_clone->attribute_type = this->attribute_type;
new_clone->attribute_length_or_value = this->attribute_length_or_value;
if (!new_clone->attribute_format)
{
new_clone->attribute_value.ptr = allocator_clone_bytes(this->attribute_value.ptr,this->attribute_value.len);
new_clone->attribute_value.len = this->attribute_value.len;
if (new_clone->attribute_value.ptr == NULL)
{
new_clone->public.destroy(&(new_clone->public));
return OUT_OF_RES;
}
}
*clone = (transform_attribute_t *) new_clone;
return SUCCESS;
}
/**
* Implements payload_t's and transform_attribute_t's destroy function.
* See #payload_s.destroy or transform_attribute_s.destroy for description.
*/
static status_t destroy(private_transform_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
allocator_free(this->attribute_value.ptr);
}
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
transform_attribute_t *transform_attribute_create()
{
private_transform_attribute_t *this = allocator_alloc_thing(private_transform_attribute_t);
if (this == NULL)
{
return NULL;
}
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.set_value_chunk = (status_t (*) (transform_attribute_t *,chunk_t)) set_value_chunk;
this->public.set_value = (status_t (*) (transform_attribute_t *,u_int16_t)) set_value;
this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk;
this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value;
this->public.set_attribute_type = (status_t (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type;
this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type;
this->public.clone = (status_t (*) (transform_attribute_t *,transform_attribute_t **)) clone;
this->public.destroy = (status_t (*) (transform_attribute_t *)) destroy;
/* set default values of the fields */
this->attribute_format = TRUE;
this->attribute_type = 0;
this->attribute_length_or_value = 0;
this->attribute_value.ptr = NULL;
this->attribute_value.len = 0;
return (&(this->public));
}
@@ -0,0 +1,153 @@
/**
* @file transform_attribute.h
*
* @brief Declaration of the class transform_attribute_t.
*
* An object of this type represents an IKEv2 TRANSFORM attribute.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TRANSFORM_ATTRIBUTE_H_
#define TRANSFORM_ATTRIBUTE_H_
#include <types.h>
#include <encoding/payloads/payload.h>
/**
* Type of the attribute, as in IKEv2 draft 3.3.5
*/
typedef enum transform_attribute_type_e transform_attribute_type_t;
enum transform_attribute_type_e {
ATTRIBUTE_UNDEFINED = 16384,
KEY_LENGTH = 14
};
/**
* string mappings for transform_attribute_type_t
*/
extern mapping_t transform_attribute_type_m[];
/**
* Object representing an IKEv2- TRANSFORM Attribute
*
* The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
*
*/
typedef struct transform_attribute_s transform_attribute_t;
struct transform_attribute_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Returns the currently set value of the attribute
*
* @warning Returned data are not copied
*
* @param this calling transform_attribute_t object
* @return chunk_t pointing to the value
*/
chunk_t (*get_value_chunk) (transform_attribute_t *this);
/**
* @brief Returns the currently set value of the attribute
*
* @warning Returned data are not copied
*
* @param this calling transform_attribute_t object
* @return value
*/
u_int16_t (*get_value) (transform_attribute_t *this);
/**
* @brief Sets the value of the attribute.
*
* @warning Value is getting copied
*
* @param this calling transform_attribute_t object
* @param value chunk_t pointing to the value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
/**
* @brief Sets the value of the attribute.
*
* @param this calling transform_attribute_t object
* @param value value to set
* @return
* - SUCCESS or
* - OUT_OF_RES
*/
status_t (*set_value) (transform_attribute_t *this, u_int16_t value);
/**
* @brief Sets the type of the attribute.
*
* @param this calling transform_attribute_t object
* @param type type to set (most significant bit is set to zero)
* @return SUCCESS
*/
status_t (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
/**
* @brief get the type of the attribute.
*
* @param this calling transform_attribute_t object
* @return type of the value
*/
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
/**
* @brief Clones an transform_attribute_t object.
*
* @param this transform_attribute_t object to clone
* @param clone the new clone will be written there
* @return
* - OUT_OF_RES
* - SUCCESS
*/
status_t (*clone) (transform_attribute_t *this,transform_attribute_t **clone);
/**
* @brief Destroys an transform_attribute_t object.
*
* @param this transform_attribute_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (transform_attribute_t *this);
};
/**
* @brief Creates an empty transform_attribute_t object
*
* @return
* - created transform_attribute_t object, or
* - NULL if failed
*/
transform_attribute_t *transform_attribute_create();
#endif /*TRANSFORM_ATTRIBUTE_H_*/
@@ -0,0 +1,577 @@
/**
* @file transform_substructure.h
*
* @brief Declaration of the class transform_substructure_t.
*
* An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/* offsetof macro */
#include <stddef.h>
#include "transform_substructure.h"
#include <encoding/payloads/transform_attribute.h>
#include <encoding/payloads/encodings.h>
#include <types.h>
#include <utils/allocator.h>
#include <utils/linked_list.h>
/**
* Private data of an transform_substructure_t' Object
*
*/
typedef struct private_transform_substructure_s private_transform_substructure_t;
struct private_transform_substructure_s {
/**
* public transform_substructure_t interface
*/
transform_substructure_t public;
/**
* next payload type
*/
u_int8_t next_payload;
/**
* Length of this payload
*/
u_int16_t transform_length;
/**
* Type of the transform
*/
u_int8_t transform_type;
/**
* Transform ID
*/
u_int16_t transform_id;
/**
* Transforms Attributes are stored in a linked_list_t
*/
linked_list_t *attributes;
/**
* @brief Computes the length of this substructure.
*
* @param this calling private_transform_substructure_t object
* @return
* SUCCESS in any case
*/
status_t (*compute_length) (private_transform_substructure_t *this);
};
/**
* string mappings for transform_type_t
*/
mapping_t transform_type_m[] = {
{UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"},
{ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"},
{PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"},
{INTEGRITIY_ALGORITHM, "INTEGRITIY_ALGORITHM"},
{DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"},
{EXTENDED_SEQUENCE_NUNBERS, "EXTENDED_SEQUENCE_NUNBERS"},
{MAPPING_END, NULL}
};
/**
* string mappings for encryption_algorithm_t
*/
mapping_t encryption_algorithm_m[] = {
{ENCR_UNDEFINED, "ENCR_UNDEFINED"},
{ENCR_DES_IV64, "ENCR_DES_IV64"},
{ENCR_DES, "ENCR_DES"},
{ENCR_3DES, "ENCR_3DES"},
{ENCR_RC5, "ENCR_RC5"},
{ENCR_IDEA, "ENCR_IDEA"},
{ENCR_CAST, "ENCR_CAST"},
{ENCR_BLOWFISH, "ENCR_BLOWFISH"},
{ENCR_3IDEA, "ENCR_3IDEA"},
{ENCR_DES_IV32, "ENCR_DES_IV32"},
{ENCR_NULL, "ENCR_NULL"},
{ENCR_AES_CBC, "ENCR_AES_CBC"},
{ENCR_AES_CTR, "ENCR_AES_CTR"},
{MAPPING_END, NULL}
};
/**
* string mappings for encryption_algorithm_t
*/
mapping_t pseudo_random_function_m[] = {
{PRF_UNDEFINED, "PRF_UNDEFINED"},
{PRF_HMAC_MD5, "PRF_HMAC_MD5"},
{PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
{PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
{PRF_AES128_CBC, "PRF_AES128_CBC"},
{MAPPING_END, NULL}
};
/**
* string mappings for integrity_algorithm_t
*/
mapping_t integrity_algorithm_m[] = {
{AUTH_UNDEFINED, "AUTH_UNDEFINED"},
{AUTH_HMAC_MD5_96, "AUTH_HMAC_MD5_96"},
{AUTH_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"},
{AUTH_DES_MAC, "AUTH_DES_MAC"},
{AUTH_KPDK_MD5, "AUTH_KPDK_MD5"},
{AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"},
{MAPPING_END, NULL}
};
/**
* string mappings for diffie_hellman_group_t
*/
mapping_t diffie_hellman_group_m[] = {
{MODP_UNDEFINED, "MODP_UNDEFINED"},
{MODP_768_BIT, "MODP_768_BIT"},
{MODP_1024_BIT, "MODP_1024_BIT"},
{MODP_1536_BIT, "MODP_1536_BIT"},
{MODP_2048_BIT, "MODP_2048_BIT"},
{MODP_3072_BIT, "MODP_3072_BIT"},
{MODP_4096_BIT, "MODP_4096_BIT"},
{MODP_6144_BIT, "MODP_6144_BIT"},
{MODP_8192_BIT, "MODP_8192_BIT"},
{MAPPING_END, NULL}
};
/**
* string mappings for extended_sequence_numbers_t
*/
mapping_t extended_sequence_numbers_m[] = {
{NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"},
{EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"},
{MAPPING_END, NULL}
};
/**
* Encoding rules to parse or generate a Transform substructure
*
* The defined offsets are the positions in a object of type
* private_transform_substructure_t.
*
*/
encoding_rule_t transform_substructure_encodings[] = {
/* 1 Byte next payload type, stored in the field next_payload */
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* Length of the whole transform substructure*/
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
/* transform type is a number of 8 bit */
{ U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
/* Reserved Byte is skipped */
{ RESERVED_BYTE, 0 },
/* tranform ID is a number of 8 bit */
{ U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
/* Attributes are stored in a transform attribute,
offset points to a linked_list_t pointer */
{ TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 0 (last) or 3 ! RESERVED ! Transform Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!Transform Type ! RESERVED ! Transform ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! !
~ Transform Attributes ~
! !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Implements payload_t's verify function.
* See #payload_s.verify for description.
*/
static status_t verify(private_transform_substructure_t *this)
{
if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != TRANSFORM_SUBSTRUCTURE))
{
/* must be 0 or 3 */
return FAILED;
}
switch (this->transform_type)
{
case ENCRYPTION_ALGORITHM:
{
if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
{
return FAILED;
}
break;
}
case PSEUDO_RANDOM_FUNCTION:
{
if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
{
return FAILED;
}
break;
}
case INTEGRITIY_ALGORITHM:
{
if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
{
return FAILED;
}
break;
}
case DIFFIE_HELLMAN_GROUP:
{
switch (this->transform_id)
{
case MODP_768_BIT:
case MODP_1024_BIT:
case MODP_1536_BIT:
case MODP_2048_BIT:
case MODP_3072_BIT:
case MODP_4096_BIT:
case MODP_6144_BIT:
case MODP_8192_BIT:
{
break;
}
default:
{
return FAILED;
}
}
break;
}
case EXTENDED_SEQUENCE_NUNBERS:
{
if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
{
return FAILED;
}
break;
}
default:
{
/* not a supported transform type! */
return FAILED;
}
}
/* proposal number is checked in SA payload */
return SUCCESS;
}
/**
* Implements payload_t's get_encoding_rules function.
* See #payload_s.get_encoding_rules for description.
*/
static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
{
*rules = transform_substructure_encodings;
*rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
return SUCCESS;
}
/**
* Implements payload_t's get_type function.
* See #payload_s.get_type for description.
*/
static payload_type_t get_type(private_transform_substructure_t *this)
{
return TRANSFORM_SUBSTRUCTURE;
}
/**
* Implements payload_t's get_next_type function.
* See #payload_s.get_next_type for description.
*/
static payload_type_t get_next_type(private_transform_substructure_t *this)
{
return (this->next_payload);
}
/**
* Implements payload_t's get_length function.
* See #payload_s.get_length for description.
*/
static size_t get_length(private_transform_substructure_t *this)
{
this->compute_length(this);
return this->transform_length;
}
/**
* Implements transform_substructure_t's create_transform_attribute_iterator function.
* See #transform_substructure_s.create_transform_attribute_iterator for description.
*/
static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
{
return (this->attributes->create_iterator(this->attributes,iterator,forward));
}
/**
* Implements transform_substructure_t's add_transform_attribute function.
* See #transform_substructure_s.add_transform_attribute for description.
*/
static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
{
status_t status;
status = this->attributes->insert_last(this->attributes,(void *) attribute);
this->compute_length(this);
return status;
}
/**
* Implements transform_substructure_t's set_is_last_transform function.
* See #transform_substructure_s.set_is_last_transform for description.
*/
static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
{
this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
return SUCCESS;
}
/**
* Implements transform_substructure_t's get_is_last_transform function.
* See #transform_substructure_s.get_is_last_transform for description.
*/
static bool get_is_last_transform (private_transform_substructure_t *this)
{
return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
}
/**
* Implements payload_t's set_next_type function.
* See #payload_s.set_next_type for description.
*/
static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
{
return SUCCESS;
}
/**
* Implements transform_substructure_t's set_transform_type function.
* See #transform_substructure_s.set_transform_type for description.
*/
static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
{
this->transform_type = type;
return SUCCESS;
}
/**
* Implements transform_substructure_t's get_transform_type function.
* See #transform_substructure_s.get_transform_type for description.
*/
static u_int8_t get_transform_type (private_transform_substructure_t *this)
{
return this->transform_type;
}
/**
* Implements transform_substructure_t's set_transform_id function.
* See #transform_substructure_s.set_transform_id for description.
*/
static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
{
this->transform_id = id;
return SUCCESS;
}
/**
* Implements transform_substructure_t's get_transform_id function.
* See #transform_substructure_s.get_transform_id for description.
*/
static u_int16_t get_transform_id (private_transform_substructure_t *this)
{
return this->transform_id;
}
/**
* Implements private_transform_substructure_t's compute_length function.
* See #private_transform_substructure_s.compute_length for description.
*/
static status_t compute_length (private_transform_substructure_t *this)
{
linked_list_iterator_t *iterator;
status_t status;
size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
if (status != SUCCESS)
{
return length;
}
while (iterator->has_next(iterator))
{
payload_t * current_attribute;
iterator->current(iterator,(void **) &current_attribute);
length += current_attribute->get_length(current_attribute);
}
iterator->destroy(iterator);
this->transform_length = length;
return SUCCESS;
}
/**
* Implements transform_substructure_t's clone function.
* See transform_substructure_s.clone for description.
*/
static status_t clone(private_transform_substructure_t *this,transform_substructure_t **clone)
{
private_transform_substructure_t *new_clone;
linked_list_iterator_t *attributes;
status_t status;
new_clone = (private_transform_substructure_t *) transform_substructure_create();
new_clone->next_payload = this->next_payload;
new_clone->transform_type = this->transform_type;
new_clone->transform_id = this->transform_id;
status = this->attributes->create_iterator(this->attributes,&attributes,FALSE);
if (status != SUCCESS)
{
new_clone->public.destroy(&(new_clone->public));
return status;
}
while (attributes->has_next(attributes))
{
transform_attribute_t *current_attribute;
transform_attribute_t *current_attribute_clone;
status = attributes->current(attributes,(void **) &current_attribute);
if (status != SUCCESS)
{
attributes->destroy(attributes);
new_clone->public.destroy(&(new_clone->public));
return status;
}
status = current_attribute->clone(current_attribute,&current_attribute_clone);
if (status != SUCCESS)
{
attributes->destroy(attributes);
new_clone->public.destroy(&(new_clone->public));
return status;
}
status = new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
if (status != SUCCESS)
{
attributes->destroy(attributes);
current_attribute_clone->destroy(current_attribute_clone);
new_clone->public.destroy(&(new_clone->public));
return status;
}
}
attributes->destroy(attributes);
*clone = &(new_clone->public);
return SUCCESS;
}
/**
* Implements payload_t's and transform_substructure_t's destroy function.
* See #payload_s.destroy or transform_substructure_s.destroy for description.
*/
static status_t destroy(private_transform_substructure_t *this)
{
/* all proposals are getting destroyed */
while (this->attributes->get_count(this->attributes) > 0)
{
transform_attribute_t *current_attribute;
if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
{
break;
}
current_attribute->destroy(current_attribute);
}
this->attributes->destroy(this->attributes);
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
transform_substructure_t *transform_substructure_create()
{
private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
if (this == NULL)
{
return NULL;
}
/* payload interface */
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
/* public functions */
this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator;
this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
this->public.clone = (status_t (*) (transform_substructure_t *,transform_substructure_t **)) clone;
this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
/* private functions */
this->compute_length = compute_length;
/* set default values of the fields */
this->next_payload = NO_PAYLOAD;
this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
this->transform_id = 0;
this->transform_type = 0;
this->attributes = linked_list_create();
if (this->attributes == NULL)
{
allocator_free(this);
return NULL;
}
return (&(this->public));
}
@@ -0,0 +1,298 @@
/**
* @file transform_substructure.h
*
* @brief Declaration of the class transform_substructure_t.
*
* An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
*
*/
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef TRANSFORM_SUBSTRUCTURE_H_
#define TRANSFORM_SUBSTRUCTURE_H_
#include <types.h>
#include <definitions.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/transform_attribute.h>
#include <utils/linked_list.h>
/**
* IKEv1 Value for a transform payload
*/
#define TRANSFORM_TYPE_VALUE 3
/**
* Length of the transform substructure header in bytes
*/
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
/**
* Type of a transform, as in IKEv2 draft 3.3.2
*/
typedef enum transform_type_e transform_type_t;
enum transform_type_e {
UNDEFINED_TRANSFORM_TYPE = 241,
ENCRYPTION_ALGORITHM = 1,
PSEUDO_RANDOM_FUNCTION = 2,
INTEGRITIY_ALGORITHM = 3,
DIFFIE_HELLMAN_GROUP = 4,
EXTENDED_SEQUENCE_NUNBERS = 5
};
/**
* string mappings for transform_type_t
*/
extern mapping_t transform_type_m[];
/**
* Encryption algorithm, as in IKEv2 draft 3.3.2
*/
typedef enum encryption_algorithm_e encryption_algorithm_t;
enum encryption_algorithm_e {
ENCR_UNDEFINED = 1024,
ENCR_DES_IV64 = 1,
ENCR_DES = 2,
ENCR_3DES = 3,
ENCR_RC5 = 4,
ENCR_IDEA = 5,
ENCR_CAST = 6,
ENCR_BLOWFISH = 7,
ENCR_3IDEA = 8,
ENCR_DES_IV32 = 9,
RESERVED = 10,
ENCR_NULL = 11,
ENCR_AES_CBC = 12,
ENCR_AES_CTR = 13
};
/**
* string mappings for encryption_algorithm_t
*/
extern mapping_t encryption_algorithm_m[];
/**
* Pseudo random function, as in IKEv2 draft 3.3.2
*/
typedef enum pseudo_random_function_e pseudo_random_function_t;
enum pseudo_random_function_e {
PRF_UNDEFINED = 1024,
PRF_HMAC_MD5 = 1,
PRF_HMAC_SHA1 = 2,
PRF_HMAC_TIGER = 3,
PRF_AES128_CBC = 4
};
/**
* string mappings for encryption_algorithm_t
*/
extern mapping_t pseudo_random_function_m[];
/**
* Integrity algorithm, as in IKEv2 draft 3.3.2
*/
typedef enum integrity_algorithm_e integrity_algorithm_t;
enum integrity_algorithm_e {
AUTH_UNDEFINED = 1024,
AUTH_HMAC_MD5_96 = 1,
AUTH_HMAC_SHA1_96 = 2,
AUTH_DES_MAC = 3,
AUTH_KPDK_MD5 = 4,
AUTH_AES_XCBC_96 = 5
};
/**
* string mappings for integrity_algorithm_t
*/
extern mapping_t integrity_algorithm_m[];
/**
* Diffie-Hellman group, as in IKEv2 draft 3.3.2 and RFC 3526
*/
typedef enum diffie_hellman_group_e diffie_hellman_group_t;
enum diffie_hellman_group_e {
MODP_UNDEFINED = 1024,
MODP_768_BIT = 1,
MODP_1024_BIT = 2,
MODP_1536_BIT = 5,
MODP_2048_BIT = 14,
MODP_3072_BIT = 15,
MODP_4096_BIT = 16,
MODP_6144_BIT = 17,
MODP_8192_BIT = 18
};
/**
* string mappings for diffie_hellman_group_t
*/
extern mapping_t diffie_hellman_group_m[];
/**
* Extended sequence numbers, as in IKEv2 draft 3.3.2
*/
typedef enum extended_sequence_numbers_e extended_sequence_numbers_t;
enum extended_sequence_numbers_e {
NO_EXT_SEQ_NUMBERS = 0,
EXT_SEQ_NUMBERS = 1
};
/**
* string mappings for extended_sequence_numbers_t
*/
extern mapping_t extended_sequence_numbers_m[];
/**
* Object representing an IKEv2- TRANSFORM SUBSTRUCTURE
*
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
*
*/
typedef struct transform_substructure_s transform_substructure_t;
struct transform_substructure_s {
/**
* implements payload_t interface
*/
payload_t payload_interface;
/**
* @brief Creates an iterator of stored transform_attribute_t objects.
*
* @warning The created iterator has to get destroyed by the caller!
*
* @warning When deleting an transform attribute using this iterator,
* the length of this transform substructure has to be refreshed
* by calling get_length()!
*
* @param this calling transform_substructure_t object
* @param iterator the created iterator is stored at the pointed pointer
* @param[in] forward iterator direction (TRUE: front to end)
* @return
* - SUCCESS or
* - OUT_OF_RES if iterator could not be created
*/
status_t (*create_transform_attribute_iterator) (transform_substructure_t *this,linked_list_iterator_t **iterator, bool forward);
/**
* @brief Adds a transform_attribute_t object to this object.
*
* @warning The added proposal_substructure_t object is
* getting destroyed in destroy function of transform_substructure_t.
*
* @param this calling transform_substructure_t object
* @param proposal transform_attribute_t object to add
* @return - SUCCESS if succeeded
* - FAILED otherwise
*/
status_t (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute);
/**
* @brief Sets the next_payload field of this substructure
*
* If this is the last transform, next payload field is set to 0,
* otherwise to 3 (payload type of transform in IKEv1)
*
* @param this calling transform_substructure_t object
* @param is_last When TRUE, next payload field is set to 0, otherwise to 3
* @return - SUCCESS
*/
status_t (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
/**
* @brief Checks if this is the last transform.
*
* @param this calling transform_substructure_t object
* @return TRUE if this is the last Transform, FALSE otherwise
*/
bool (*get_is_last_transform) (transform_substructure_t *this);
/**
* @brief Sets transform type of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param type type value to set
* @return - SUCCESS
*/
status_t (*set_transform_type) (transform_substructure_t *this,u_int8_t type);
/**
* @brief get transform type of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform type of current transform substructure.
*/
u_int8_t (*get_transform_type) (transform_substructure_t *this);
/**
* @brief Sets transform id of the current transform substructure.
*
* @param this calling transform_substructure_t object
* @param id transform id to set
* @return - SUCCESS
*/
status_t (*set_transform_id) (transform_substructure_t *this,u_int16_t id);
/**
* @brief get transform id of the current transform.
*
* @param this calling transform_substructure_t object
* @return Transform id of current transform substructure.
*/
u_int16_t (*get_transform_id) (transform_substructure_t *this);
/**
* @brief Clones an transform_substructure_t object.
*
* @param this transform_substructure_t object to clone
* @param clone pointer to a transform_substructure_t object pointer
* where the new object is stored to.
* @return
* - OUT_OF_RES
* - SUCCESS in any case
*/
status_t (*clone) (transform_substructure_t *this,transform_substructure_t **clone);
/**
* @brief Destroys an transform_substructure_t object.
*
* @param this transform_substructure_t object to destroy
* @return
* SUCCESS in any case
*/
status_t (*destroy) (transform_substructure_t *this);
};
/**
* @brief Creates an empty transform_substructure_t object
*
* @return
* - created transform_substructure_t object, or
* - NULL if failed
*/
transform_substructure_t *transform_substructure_create();
#endif /*TRANSFORM_SUBSTRUCTURE_H_*/