Merge branch 'ikev1'
Conflicts: configure.in man/ipsec.conf.5.in src/libcharon/encoding/generator.c src/libcharon/encoding/payloads/notify_payload.c src/libcharon/encoding/payloads/notify_payload.h src/libcharon/encoding/payloads/payload.c src/libcharon/network/receiver.c src/libcharon/sa/authenticator.c src/libcharon/sa/authenticator.h src/libcharon/sa/ikev2/tasks/ike_init.c src/libcharon/sa/task_manager.c src/libstrongswan/credentials/auth_cfg.c
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -108,6 +109,11 @@ struct private_generator_t {
|
||||
* to hold the length of the transform attribute in bytes.
|
||||
*/
|
||||
u_int16_t attribute_length;
|
||||
|
||||
/**
|
||||
* TRUE, if debug messages should be logged during generation.
|
||||
*/
|
||||
bool debug;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -155,8 +161,11 @@ static void make_space_available(private_generator_t *this, int bits)
|
||||
new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
|
||||
out_position_offset = this->out_position - this->buffer;
|
||||
|
||||
DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
|
||||
old_buffer_size, new_buffer_size);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
|
||||
old_buffer_size, new_buffer_size);
|
||||
}
|
||||
|
||||
this->buffer = realloc(this->buffer,new_buffer_size);
|
||||
this->out_position = (this->buffer + out_position_offset);
|
||||
@@ -205,7 +214,7 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
break;
|
||||
case U_INT_16:
|
||||
case PAYLOAD_LENGTH:
|
||||
case CONFIGURATION_ATTRIBUTE_LENGTH:
|
||||
case ATTRIBUTE_LENGTH:
|
||||
number_of_bits = 16;
|
||||
break;
|
||||
case U_INT_32:
|
||||
@@ -244,7 +253,10 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
low = *(this->out_position) & 0x0F;
|
||||
/* high is set, low_val is not changed */
|
||||
*(this->out_position) = high | low;
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
}
|
||||
/* write position is not changed, just bit position is moved */
|
||||
this->current_bit = 4;
|
||||
}
|
||||
@@ -255,7 +267,10 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
/* low of current byte in buffer has to be set to the new value*/
|
||||
low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
|
||||
*(this->out_position) = high | low;
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
}
|
||||
this->out_position++;
|
||||
this->current_bit = 0;
|
||||
}
|
||||
@@ -274,7 +289,10 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
{
|
||||
/* 8 bit values are written as they are */
|
||||
*this->out_position = *((u_int8_t *)(this->data_struct + offset));
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", *(this->out_position));
|
||||
}
|
||||
this->out_position++;
|
||||
break;
|
||||
}
|
||||
@@ -299,7 +317,10 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
val |= 0x8000;
|
||||
}
|
||||
val = htons(val);
|
||||
DBG3(DBG_ENC, " => %d", val);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", val);
|
||||
}
|
||||
/* write bytes to buffer (set bit is overwritten) */
|
||||
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
|
||||
this->current_bit = 0;
|
||||
@@ -308,17 +329,23 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
}
|
||||
case U_INT_16:
|
||||
case PAYLOAD_LENGTH:
|
||||
case CONFIGURATION_ATTRIBUTE_LENGTH:
|
||||
case ATTRIBUTE_LENGTH:
|
||||
{
|
||||
u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
|
||||
DBG3(DBG_ENC, " => %b", &val, sizeof(u_int16_t));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " %b", &val, sizeof(u_int16_t));
|
||||
}
|
||||
write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
|
||||
break;
|
||||
}
|
||||
case U_INT_32:
|
||||
{
|
||||
u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
|
||||
DBG3(DBG_ENC, " => %b", &val, sizeof(u_int32_t));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " %b", &val, sizeof(u_int32_t));
|
||||
}
|
||||
write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
|
||||
break;
|
||||
}
|
||||
@@ -327,8 +354,11 @@ static void generate_u_int_type(private_generator_t *this,
|
||||
/* 64 bit are written as-is, no host order conversion */
|
||||
write_bytes_to_buffer(this, this->data_struct + offset,
|
||||
sizeof(u_int64_t));
|
||||
DBG3(DBG_ENC, " => %b", this->data_struct + offset,
|
||||
sizeof(u_int64_t));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " %b", this->data_struct + offset,
|
||||
sizeof(u_int64_t));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -361,7 +391,10 @@ static void generate_flag(private_generator_t *this, u_int32_t offset)
|
||||
}
|
||||
|
||||
*(this->out_position) = *(this->out_position) | flag;
|
||||
DBG3(DBG_ENC, " => %d", *this->out_position);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", *this->out_position);
|
||||
}
|
||||
|
||||
this->current_bit++;
|
||||
if (this->current_bit >= 8)
|
||||
@@ -380,12 +413,16 @@ static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
|
||||
|
||||
if (this->current_bit != 0)
|
||||
{
|
||||
DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
|
||||
DBG1(DBG_ENC, "can not generate a chunk at bitpos %d",
|
||||
this->current_bit);
|
||||
return ;
|
||||
}
|
||||
|
||||
value = (chunk_t *)(this->data_struct + offset);
|
||||
DBG3(DBG_ENC, " => %B", value);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, " %B", value);
|
||||
}
|
||||
|
||||
write_bytes_to_buffer(this, value->ptr, value->len);
|
||||
}
|
||||
@@ -397,15 +434,17 @@ METHOD(generator_t, get_chunk, chunk_t,
|
||||
|
||||
*lenpos = (u_int32_t*)(this->buffer + this->header_length_offset);
|
||||
data = chunk_create(this->buffer, get_length(this));
|
||||
DBG3(DBG_ENC, "generated data of this generator %B", &data);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG3(DBG_ENC, "generated data of this generator %B", &data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
METHOD(generator_t, generate_payload, void,
|
||||
private_generator_t *this,payload_t *payload)
|
||||
{
|
||||
int i, offset_start;
|
||||
size_t rule_count;
|
||||
int i, offset_start, rule_count;
|
||||
encoding_rule_t *rules;
|
||||
payload_type_t payload_type;
|
||||
|
||||
@@ -414,17 +453,23 @@ METHOD(generator_t, generate_payload, void,
|
||||
|
||||
offset_start = this->out_position - this->buffer;
|
||||
|
||||
DBG2(DBG_ENC, "generating payload of type %N",
|
||||
payload_type_names, payload_type);
|
||||
if (this->debug)
|
||||
{
|
||||
DBG2(DBG_ENC, "generating payload of type %N",
|
||||
payload_type_names, payload_type);
|
||||
}
|
||||
|
||||
/* each payload has its own encoding rules */
|
||||
payload->get_encoding_rules(payload, &rules, &rule_count);
|
||||
rule_count = payload->get_encoding_rules(payload, &rules);
|
||||
|
||||
for (i = 0; i < rule_count;i++)
|
||||
{
|
||||
DBG2(DBG_ENC, " generating rule %d %N",
|
||||
i, encoding_type_names, rules[i].type);
|
||||
switch (rules[i].type)
|
||||
if (this->debug)
|
||||
{
|
||||
DBG2(DBG_ENC, " generating rule %d %N",
|
||||
i, encoding_type_names, rules[i].type);
|
||||
}
|
||||
switch ((int)rules[i].type)
|
||||
{
|
||||
case U_INT_4:
|
||||
case U_INT_8:
|
||||
@@ -436,7 +481,7 @@ METHOD(generator_t, generate_payload, void,
|
||||
case SPI_SIZE:
|
||||
case TS_TYPE:
|
||||
case ATTRIBUTE_TYPE:
|
||||
case CONFIGURATION_ATTRIBUTE_LENGTH:
|
||||
case ATTRIBUTE_LENGTH:
|
||||
generate_u_int_type(this, rules[i].type, rules[i].offset);
|
||||
break;
|
||||
case RESERVED_BIT:
|
||||
@@ -449,26 +494,19 @@ METHOD(generator_t, generate_payload, void,
|
||||
break;
|
||||
case ADDRESS:
|
||||
case SPI:
|
||||
case KEY_EXCHANGE_DATA:
|
||||
case NOTIFICATION_DATA:
|
||||
case NONCE_DATA:
|
||||
case ID_DATA:
|
||||
case AUTH_DATA:
|
||||
case CERT_DATA:
|
||||
case CERTREQ_DATA:
|
||||
case SPIS:
|
||||
case CONFIGURATION_ATTRIBUTE_VALUE:
|
||||
case VID_DATA:
|
||||
case EAP_DATA:
|
||||
case CHUNK_DATA:
|
||||
case ENCRYPTED_DATA:
|
||||
case UNKNOWN_DATA:
|
||||
generate_from_chunk(this, rules[i].offset);
|
||||
break;
|
||||
case PROPOSALS:
|
||||
case TRANSFORMS:
|
||||
case TRANSFORM_ATTRIBUTES:
|
||||
case CONFIGURATION_ATTRIBUTES:
|
||||
case TRAFFIC_SELECTORS:
|
||||
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
|
||||
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
|
||||
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
|
||||
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
|
||||
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
|
||||
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
|
||||
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
|
||||
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
|
||||
case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
|
||||
{
|
||||
linked_list_t *proposals;
|
||||
enumerator_t *enumerator;
|
||||
@@ -507,7 +545,10 @@ METHOD(generator_t, generate_payload, void,
|
||||
{
|
||||
if (!this->attribute_format)
|
||||
{
|
||||
DBG2(DBG_ENC, "attribute value has not fixed size");
|
||||
if (this->debug)
|
||||
{
|
||||
DBG2(DBG_ENC, "attribute value has not fixed size");
|
||||
}
|
||||
/* the attribute value is generated */
|
||||
generate_from_chunk(this, rules[i].offset);
|
||||
}
|
||||
@@ -519,11 +560,14 @@ METHOD(generator_t, generate_payload, void,
|
||||
return;
|
||||
}
|
||||
}
|
||||
DBG2(DBG_ENC, "generating %N payload finished",
|
||||
payload_type_names, payload_type);
|
||||
DBG3(DBG_ENC, "generated data for this payload %b",
|
||||
this->buffer + offset_start,
|
||||
(u_int)(this->out_position - this->buffer - offset_start));
|
||||
if (this->debug)
|
||||
{
|
||||
DBG2(DBG_ENC, "generating %N payload finished",
|
||||
payload_type_names, payload_type);
|
||||
DBG3(DBG_ENC, "generated data for this payload %b",
|
||||
this->buffer + offset_start,
|
||||
(u_int)(this->out_position - this->buffer - offset_start));
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(generator_t, destroy, void,
|
||||
@@ -547,6 +591,7 @@ generator_t *generator_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.buffer = malloc(GENERATOR_DATA_BUFFER_SIZE),
|
||||
.debug = TRUE,
|
||||
);
|
||||
|
||||
this->out_position = this->buffer;
|
||||
@@ -555,3 +600,14 @@ generator_t *generator_create()
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
generator_t *generator_create_no_dbg()
|
||||
{
|
||||
private_generator_t *this = (private_generator_t*)generator_create();
|
||||
|
||||
this->debug = FALSE;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -72,4 +72,12 @@ struct generator_t {
|
||||
*/
|
||||
generator_t *generator_create(void);
|
||||
|
||||
/**
|
||||
* Constructor to create a generator that does not log any debug messages > 1.
|
||||
*
|
||||
* @return generator_t object.
|
||||
*/
|
||||
generator_t *generator_create_no_dbg(void);
|
||||
|
||||
|
||||
#endif /** GENERATOR_H_ @}*/
|
||||
|
||||
+640
-106
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2007 Tobias Brunner
|
||||
* Copyright (C) 2006-2011 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
@@ -27,15 +27,15 @@
|
||||
typedef struct message_t message_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <network/packet.h>
|
||||
#include <encoding/payloads/ike_header.h>
|
||||
#include <encoding/payloads/notify_payload.h>
|
||||
#include <sa/keymat.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <crypto/aead.h>
|
||||
|
||||
/**
|
||||
* This class is used to represent an IKEv2-Message.
|
||||
* This class is used to represent an IKE-Message.
|
||||
*
|
||||
* The message handles parsing and generation of payloads
|
||||
* via parser_t/generator_t. Encryption is done transparently
|
||||
@@ -182,7 +182,7 @@ struct message_t {
|
||||
* all payloads to encrypt are added to the encryption payload, which is
|
||||
* always the last one.
|
||||
*
|
||||
* @param payload payload to append
|
||||
* @param payload payload to append
|
||||
*/
|
||||
void (*add_payload) (message_t *this, payload_t *payload);
|
||||
|
||||
@@ -208,14 +208,14 @@ struct message_t {
|
||||
/**
|
||||
* Parses header of message.
|
||||
*
|
||||
* Begins parisng of a message created via message_create_from_packet().
|
||||
* Begins parsing of a message created via message_create_from_packet().
|
||||
* The parsing context is stored, so a subsequent call to parse_body()
|
||||
* will continue the parsing process.
|
||||
*
|
||||
* @return
|
||||
* - SUCCESS if header could be parsed
|
||||
* - SUCCESS if header could be parsed
|
||||
* - PARSE_ERROR if corrupted/invalid data found
|
||||
* - FAILED if consistence check of header failed
|
||||
* - FAILED if consistency check of header failed
|
||||
*/
|
||||
status_t (*parse_header) (message_t *this);
|
||||
|
||||
@@ -228,15 +228,15 @@ struct message_t {
|
||||
* If there are encrypted payloads, they get decrypted and verified using
|
||||
* the given aead transform (if given).
|
||||
*
|
||||
* @param aead aead transform to verify/decrypt message
|
||||
* @param keymat keymat to verify/decrypt message
|
||||
* @return
|
||||
* - SUCCESS if parsing successful
|
||||
* - SUCCESS if parsing successful
|
||||
* - PARSE_ERROR if message parsing failed
|
||||
* - VERIFY_ERROR if message verification failed (bad syntax)
|
||||
* - FAILED if integrity check failed
|
||||
* - INVALID_STATE if aead not supplied, but needed
|
||||
* - VERIFY_ERROR if message verification failed (bad syntax)
|
||||
* - FAILED if integrity check failed
|
||||
* - INVALID_STATE if aead not supplied, but needed
|
||||
*/
|
||||
status_t (*parse_body) (message_t *this, aead_t *aead);
|
||||
status_t (*parse_body) (message_t *this, keymat_t *keymat);
|
||||
|
||||
/**
|
||||
* Generates the UDP packet of specific message.
|
||||
@@ -247,15 +247,15 @@ struct message_t {
|
||||
* Generation is only done once, multiple calls will just return a copy
|
||||
* of the packet.
|
||||
*
|
||||
* @param aead aead transform to encrypt/sign message
|
||||
* @param keymat keymat to encrypt/sign message
|
||||
* @param packet copy of generated packet
|
||||
* @return
|
||||
* - SUCCESS if packet could be generated
|
||||
* - INVALID_STATE if exchange type is currently not set
|
||||
* - NOT_FOUND if no rules found for message generation
|
||||
* - INVALID_STATE if aead not supplied but needed.
|
||||
* - SUCCESS if packet could be generated
|
||||
* - INVALID_STATE if exchange type is currently not set
|
||||
* - NOT_FOUND if no rules found for message generation
|
||||
* - INVALID_STATE if aead not supplied but needed.
|
||||
*/
|
||||
status_t (*generate) (message_t *this, aead_t *aead, packet_t **packet);
|
||||
status_t (*generate) (message_t *this, keymat_t *keymat, packet_t **packet);
|
||||
|
||||
/**
|
||||
* Check if the message has already been encoded using generate().
|
||||
@@ -278,7 +278,7 @@ struct message_t {
|
||||
* Sets the source host informations.
|
||||
*
|
||||
* @warning host_t object is not getting cloned and gets destroyed by
|
||||
* message_t.destroy or next call of message_t.set_source.
|
||||
* message_t.destroy or next call of message_t.set_source.
|
||||
*
|
||||
* @param host host_t object representing source host
|
||||
*/
|
||||
@@ -298,7 +298,7 @@ struct message_t {
|
||||
* Sets the destination host informations.
|
||||
*
|
||||
* @warning host_t object is not getting cloned and gets destroyed by
|
||||
* message_t.destroy or next call of message_t.set_destination.
|
||||
* message_t.destroy or next call of message_t.set_destination.
|
||||
*
|
||||
* @param host host_t object representing destination host
|
||||
*/
|
||||
@@ -344,9 +344,9 @@ struct message_t {
|
||||
packet_t * (*get_packet) (message_t *this);
|
||||
|
||||
/**
|
||||
* Returns a clone of the internal stored packet_t data.
|
||||
* Returns a chunk pointing to internal packet_t data.
|
||||
*
|
||||
* @return clone of the internal stored packet_t data.
|
||||
* @return packet data.
|
||||
*/
|
||||
chunk_t (*get_packet_data) (message_t *this);
|
||||
|
||||
@@ -357,26 +357,27 @@ struct message_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an message_t object from a incoming UDP Packet.
|
||||
* Creates a message_t object from an incoming UDP packet.
|
||||
*
|
||||
* The given packet gets owned by the message. The message is uninitialized,
|
||||
* call parse_header() to populate header fields.
|
||||
*
|
||||
* @param packet packet_t object which is assigned to message
|
||||
* @return message_t object
|
||||
* @return message_t object
|
||||
*/
|
||||
message_t * message_create_from_packet(packet_t *packet);
|
||||
|
||||
message_t *message_create_from_packet(packet_t *packet);
|
||||
|
||||
/**
|
||||
* Creates an empty message_t object.
|
||||
* Creates an empty message_t object for a specific major/minor version.
|
||||
*
|
||||
* - exchange_type is set to NOT_SET
|
||||
* - original_initiator is set to TRUE
|
||||
* - is_request is set to TRUE
|
||||
*
|
||||
* @return message_t object
|
||||
* @param major major IKE version of this message
|
||||
* @param minor minor IKE version of this message
|
||||
* @return message_t object
|
||||
*/
|
||||
message_t * message_create(void);
|
||||
message_t *message_create(int major, int minor);
|
||||
|
||||
#endif /** MESSAGE_H_ @}*/
|
||||
|
||||
+36
-196
@@ -137,7 +137,7 @@ static bool parse_uint4(private_parser_t *this, int rule_number,
|
||||
}
|
||||
if (output_pos)
|
||||
{
|
||||
DBG3(DBG_ENC, " => %d", *output_pos);
|
||||
DBG3(DBG_ENC, " => %hhu", *output_pos);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ static bool parse_uint8(private_parser_t *this, int rule_number,
|
||||
if (output_pos)
|
||||
{
|
||||
*output_pos = *(this->byte_pos);
|
||||
DBG3(DBG_ENC, " => %d", *output_pos);
|
||||
DBG3(DBG_ENC, " => %hhu", *output_pos);
|
||||
}
|
||||
this->byte_pos++;
|
||||
return TRUE;
|
||||
@@ -183,7 +183,7 @@ static bool parse_uint15(private_parser_t *this, int rule_number,
|
||||
{
|
||||
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
|
||||
*output_pos = ntohs(*output_pos) & ~0x8000;
|
||||
DBG3(DBG_ENC, " => %d", *output_pos);
|
||||
DBG3(DBG_ENC, " => %hu", *output_pos);
|
||||
}
|
||||
this->byte_pos += sizeof(u_int16_t);
|
||||
this->bit_pos = 0;
|
||||
@@ -208,7 +208,7 @@ static bool parse_uint16(private_parser_t *this, int rule_number,
|
||||
{
|
||||
memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
|
||||
*output_pos = ntohs(*output_pos);
|
||||
DBG3(DBG_ENC, " => %d", *output_pos);
|
||||
DBG3(DBG_ENC, " => %hu", *output_pos);
|
||||
}
|
||||
this->byte_pos += sizeof(u_int16_t);
|
||||
return TRUE;
|
||||
@@ -231,7 +231,7 @@ static bool parse_uint32(private_parser_t *this, int rule_number,
|
||||
{
|
||||
memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
|
||||
*output_pos = ntohl(*output_pos);
|
||||
DBG3(DBG_ENC, " => %d", *output_pos);
|
||||
DBG3(DBG_ENC, " => %u", *output_pos);
|
||||
}
|
||||
this->byte_pos += sizeof(u_int32_t);
|
||||
return TRUE;
|
||||
@@ -254,7 +254,7 @@ static bool parse_bytes(private_parser_t *this, int rule_number,
|
||||
if (output_pos)
|
||||
{
|
||||
memcpy(output_pos, this->byte_pos, bytes);
|
||||
DBG3(DBG_ENC, " => %b", output_pos, bytes);
|
||||
DBG3(DBG_ENC, " %b", output_pos, bytes);
|
||||
}
|
||||
this->byte_pos += bytes;
|
||||
return TRUE;
|
||||
@@ -352,7 +352,7 @@ static bool parse_chunk(private_parser_t *this, int rule_number,
|
||||
{
|
||||
*output_pos = chunk_alloc(length);
|
||||
memcpy(output_pos->ptr, this->byte_pos, length);
|
||||
DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
|
||||
DBG3(DBG_ENC, " %b", output_pos->ptr, length);
|
||||
}
|
||||
this->byte_pos += length;
|
||||
return TRUE;
|
||||
@@ -363,11 +363,10 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
{
|
||||
payload_t *pld;
|
||||
void *output;
|
||||
size_t rule_count;
|
||||
int payload_length = 0, spi_size = 0, attribute_length = 0;
|
||||
int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
|
||||
u_int16_t ts_type = 0;
|
||||
bool attribute_format = FALSE;
|
||||
int rule_number;
|
||||
int rule_number, rule_count;
|
||||
encoding_rule_t *rule;
|
||||
|
||||
/* create instance of the payload to parse */
|
||||
@@ -381,15 +380,17 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
|
||||
/* base pointer for output, avoids casting in every rule */
|
||||
output = pld;
|
||||
|
||||
/* parse the payload with its own rulse */
|
||||
pld->get_encoding_rules(pld, &this->rules, &rule_count);
|
||||
rule_count = pld->get_encoding_rules(pld, &this->rules);
|
||||
for (rule_number = 0; rule_number < rule_count; rule_number++)
|
||||
{
|
||||
/* update header length for each rule, as it is dynamic (SPIs) */
|
||||
header_length = pld->get_header_length(pld);
|
||||
|
||||
rule = &(this->rules[rule_number]);
|
||||
DBG2(DBG_ENC, " parsing rule %d %N",
|
||||
rule_number, encoding_type_names, rule->type);
|
||||
switch (rule->type)
|
||||
switch ((int)rule->type)
|
||||
{
|
||||
case U_INT_4:
|
||||
{
|
||||
@@ -457,7 +458,8 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
}
|
||||
/* parsed u_int16 should be aligned */
|
||||
payload_length = *(u_int16_t*)(output + rule->offset);
|
||||
if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
|
||||
/* all payloads must have at least 4 bytes header */
|
||||
if (payload_length < 4)
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
@@ -484,49 +486,41 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROPOSALS:
|
||||
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
|
||||
case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
|
||||
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
|
||||
case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
|
||||
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
|
||||
case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
|
||||
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
|
||||
case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
|
||||
case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
|
||||
{
|
||||
if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
|
||||
if (payload_length < header_length ||
|
||||
!parse_list(this, rule_number, output + rule->offset,
|
||||
PROPOSAL_SUBSTRUCTURE,
|
||||
payload_length - SA_PAYLOAD_HEADER_LENGTH))
|
||||
rule->type - PAYLOAD_LIST,
|
||||
payload_length - header_length))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRANSFORMS:
|
||||
case CHUNK_DATA:
|
||||
{
|
||||
if (payload_length <
|
||||
spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
|
||||
!parse_list(this, rule_number, output + rule->offset,
|
||||
TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
|
||||
PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
|
||||
if (payload_length < header_length ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - header_length))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRANSFORM_ATTRIBUTES:
|
||||
case ENCRYPTED_DATA:
|
||||
{
|
||||
if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
|
||||
!parse_list(this, rule_number, output + rule->offset,
|
||||
TRANSFORM_ATTRIBUTE,
|
||||
payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONFIGURATION_ATTRIBUTES:
|
||||
{
|
||||
if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_list(this, rule_number, output + rule->offset,
|
||||
CONFIGURATION_ATTRIBUTE,
|
||||
payload_length - CP_PAYLOAD_HEADER_LENGTH))
|
||||
if (!parse_chunk(this, rule_number, output + rule->offset,
|
||||
this->input_roof - this->byte_pos))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
@@ -552,7 +546,7 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONFIGURATION_ATTRIBUTE_LENGTH:
|
||||
case ATTRIBUTE_LENGTH:
|
||||
{
|
||||
if (!parse_uint16(this, rule_number, output + rule->offset))
|
||||
{
|
||||
@@ -583,137 +577,6 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NONCE_DATA:
|
||||
{
|
||||
if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_DATA:
|
||||
{
|
||||
if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - ID_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUTH_DATA:
|
||||
{
|
||||
if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CERT_DATA:
|
||||
{
|
||||
if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - CERT_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CERTREQ_DATA:
|
||||
{
|
||||
if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EAP_DATA:
|
||||
{
|
||||
if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - EAP_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPIS:
|
||||
{
|
||||
if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VID_DATA:
|
||||
{
|
||||
if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONFIGURATION_ATTRIBUTE_VALUE:
|
||||
{
|
||||
if (!parse_chunk(this, rule_number, output + rule->offset,
|
||||
attribute_length))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_EXCHANGE_DATA:
|
||||
{
|
||||
if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - KE_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NOTIFICATION_DATA:
|
||||
{
|
||||
if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ENCRYPTED_DATA:
|
||||
{
|
||||
if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TS_TYPE:
|
||||
{
|
||||
if (!parse_uint8(this, rule_number, output + rule->offset))
|
||||
@@ -736,29 +599,6 @@ METHOD(parser_t, parse_payload, status_t,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRAFFIC_SELECTORS:
|
||||
{
|
||||
if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_list(this, rule_number, output + rule->offset,
|
||||
TRAFFIC_SELECTOR_SUBSTRUCTURE,
|
||||
payload_length - TS_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNKNOWN_DATA:
|
||||
{
|
||||
if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
|
||||
!parse_chunk(this, rule_number, output + rule->offset,
|
||||
payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
|
||||
{
|
||||
pld->destroy(pld);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DBG1(DBG_ENC, " no rule to parse rule %d %N",
|
||||
|
||||
@@ -74,7 +74,7 @@ struct private_auth_payload_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_auth_payload_t.
|
||||
*/
|
||||
encoding_rule_t auth_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_auth_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -96,7 +96,7 @@ encoding_rule_t auth_payload_encodings[] = {
|
||||
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[1]) },
|
||||
{ RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[2]) },
|
||||
/* some auth data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ AUTH_DATA, offsetof(private_auth_payload_t, auth_data) }
|
||||
{ CHUNK_DATA, offsetof(private_auth_payload_t, auth_data) }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -119,11 +119,17 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_auth_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = auth_payload_encodings;
|
||||
*rule_count = countof(auth_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_auth_payload_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
@@ -167,7 +173,7 @@ METHOD(auth_payload_t, set_data, void,
|
||||
{
|
||||
free(this->auth_data.ptr);
|
||||
this->auth_data = chunk_clone(data);
|
||||
this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len;
|
||||
this->payload_length = get_header_length(this) + this->auth_data.len;
|
||||
}
|
||||
|
||||
METHOD(auth_payload_t, get_data, chunk_t,
|
||||
@@ -195,6 +201,7 @@ auth_payload_t *auth_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -208,7 +215,7 @@ auth_payload_t *auth_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = AUTH_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,7 @@ typedef struct auth_payload_t auth_payload_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <sa/authenticators/authenticator.h>
|
||||
|
||||
/**
|
||||
* Length of a auth payload without the auth data in bytes.
|
||||
*/
|
||||
#define AUTH_PAYLOAD_HEADER_LENGTH 8
|
||||
#include <sa/authenticator.h>
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 AUTH payload.
|
||||
|
||||
@@ -86,6 +86,11 @@ struct private_cert_payload_t {
|
||||
* TRUE if the "Hash and URL" data is invalid
|
||||
*/
|
||||
bool invalid_hash_and_url;
|
||||
|
||||
/**
|
||||
* The payload type.
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,7 +100,7 @@ struct private_cert_payload_t {
|
||||
* private_cert_payload_t.
|
||||
*
|
||||
*/
|
||||
encoding_rule_t cert_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_cert_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -113,7 +118,7 @@ encoding_rule_t cert_payload_encodings[] = {
|
||||
/* 1 Byte CERT type*/
|
||||
{ U_INT_8, offsetof(private_cert_payload_t, encoding) },
|
||||
/* some cert data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ CERT_DATA, offsetof(private_cert_payload_t, data) }
|
||||
{ CHUNK_DATA, offsetof(private_cert_payload_t, data) }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -166,17 +171,23 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_cert_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = cert_payload_encodings;
|
||||
*rule_count = countof(cert_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_cert_payload_t *this)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_cert_payload_t *this)
|
||||
{
|
||||
return CERTIFICATE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -261,7 +272,7 @@ METHOD2(payload_t, cert_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
cert_payload_t *cert_payload_create()
|
||||
cert_payload_t *cert_payload_create(payload_type_t type)
|
||||
{
|
||||
private_cert_payload_t *this;
|
||||
|
||||
@@ -270,6 +281,7 @@ cert_payload_t *cert_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -283,7 +295,8 @@ cert_payload_t *cert_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = CERT_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -291,10 +304,12 @@ cert_payload_t *cert_payload_create()
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
|
||||
cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
|
||||
certificate_t *cert)
|
||||
{
|
||||
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
|
||||
private_cert_payload_t *this;
|
||||
|
||||
this = (private_cert_payload_t*)cert_payload_create(type);
|
||||
switch (cert->get_type(cert))
|
||||
{
|
||||
case CERT_X509:
|
||||
@@ -312,7 +327,8 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
|
||||
this->payload_length = get_header_length(this) + this->data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -321,23 +337,29 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
|
||||
{
|
||||
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
|
||||
private_cert_payload_t *this;
|
||||
|
||||
this = (private_cert_payload_t*)cert_payload_create(CERTIFICATE);
|
||||
this->encoding = ENC_X509_HASH_AND_URL;
|
||||
this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
|
||||
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
|
||||
this->payload_length = get_header_length(this) + this->data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data)
|
||||
cert_payload_t *cert_payload_create_custom(payload_type_t type,
|
||||
cert_encoding_t encoding, chunk_t data)
|
||||
{
|
||||
private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create();
|
||||
private_cert_payload_t *this;
|
||||
|
||||
this->encoding = type;
|
||||
this = (private_cert_payload_t*)cert_payload_create(type);
|
||||
this->encoding = encoding;
|
||||
this->data = data;
|
||||
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
|
||||
this->payload_length = get_header_length(this) + this->data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,6 @@ typedef enum cert_encoding_t cert_encoding_t;
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Length of a cert payload without the cert data in bytes.
|
||||
*/
|
||||
#define CERT_PAYLOAD_HEADER_LENGTH 5
|
||||
|
||||
/**
|
||||
* Certifcate encodings, as in RFC4306
|
||||
*/
|
||||
@@ -60,9 +55,7 @@ enum cert_encoding_t {
|
||||
extern enum_name_t *cert_encoding_names;
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 CERT payload.
|
||||
*
|
||||
* The CERT payload format is described in RFC section 3.6.
|
||||
* Class representing an IKEv1/IKEv2 CERT payload.
|
||||
*/
|
||||
struct cert_payload_t {
|
||||
|
||||
@@ -103,7 +96,6 @@ struct cert_payload_t {
|
||||
*/
|
||||
char *(*get_url)(cert_payload_t *this);
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the cert_payload object.
|
||||
*/
|
||||
@@ -113,23 +105,26 @@ struct cert_payload_t {
|
||||
/**
|
||||
* Creates an empty certificate payload.
|
||||
*
|
||||
* @param type payload type (for IKEv1 or IKEv2)
|
||||
* @return cert_payload_t object
|
||||
*/
|
||||
cert_payload_t *cert_payload_create(void);
|
||||
cert_payload_t *cert_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a certificate payload with an embedded certificate.
|
||||
*
|
||||
* @param type payload type (for IKEv1 or IKEv2)
|
||||
* @param cert certificate to embed
|
||||
* @return cert_payload_t object
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_from_cert(certificate_t *cert);
|
||||
cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
|
||||
certificate_t *cert);
|
||||
|
||||
/**
|
||||
* Creates a certificate payload with hash and URL encoding of a certificate.
|
||||
* Creates an IKEv2 certificate payload with hash and URL encoding.
|
||||
*
|
||||
* @param hash hash of the DER encoded certificate (get's cloned)
|
||||
* @param url the URL to locate the certificate (get's cloned)
|
||||
* @param url URL to the certificate
|
||||
* @return cert_payload_t object
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
|
||||
@@ -137,10 +132,12 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url);
|
||||
/**
|
||||
* Creates a custom certificate payload using type and associated data.
|
||||
*
|
||||
* @param type encoding type of certificate
|
||||
* @param type payload type (for IKEv1 or IKEv2)
|
||||
* @param encoding encoding type of certificate
|
||||
* @param data associated data (gets owned)
|
||||
* @return cert_payload_t object
|
||||
*/
|
||||
cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data);
|
||||
cert_payload_t *cert_payload_create_custom(payload_type_t type,
|
||||
cert_encoding_t encoding, chunk_t data);
|
||||
|
||||
#endif /** CERT_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -64,15 +64,17 @@ struct private_certreq_payload_t {
|
||||
* The contained certreq data value.
|
||||
*/
|
||||
chunk_t data;
|
||||
|
||||
/**
|
||||
* Payload type CERTIFICATE_REQUEST or CERTIFICATE_REQUEST_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a CERTREQ payload
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_certreq_payload_t.
|
||||
* Encoding rules for CERTREQ payload.
|
||||
*/
|
||||
encoding_rule_t certreq_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_certreq_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -90,7 +92,7 @@ encoding_rule_t certreq_payload_encodings[] = {
|
||||
/* 1 Byte CERTREQ type*/
|
||||
{ U_INT_8, offsetof(private_certreq_payload_t, encoding) },
|
||||
/* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ CERTREQ_DATA, offsetof(private_certreq_payload_t, data) }
|
||||
{ CHUNK_DATA, offsetof(private_certreq_payload_t, data) }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -109,7 +111,8 @@ encoding_rule_t certreq_payload_encodings[] = {
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_certreq_payload_t *this)
|
||||
{
|
||||
if (this->encoding == ENC_X509_SIGNATURE)
|
||||
if (this->type == CERTIFICATE_REQUEST &&
|
||||
this->encoding == ENC_X509_SIGNATURE)
|
||||
{
|
||||
if (this->data.len % HASH_SIZE_SHA1)
|
||||
{
|
||||
@@ -121,17 +124,23 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_certreq_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = certreq_payload_encodings;
|
||||
*rule_count = countof(certreq_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_certreq_payload_t *this)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_certreq_payload_t *this)
|
||||
{
|
||||
return CERTIFICATE_REQUEST;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -152,6 +161,16 @@ METHOD(payload_t, get_length, size_t,
|
||||
return this->payload_length;
|
||||
}
|
||||
|
||||
METHOD(certreq_payload_t, get_dn, identification_t*,
|
||||
private_certreq_payload_t *this)
|
||||
{
|
||||
if (this->data.len)
|
||||
{
|
||||
return identification_create_from_encoding(ID_DER_ASN1_DN, this->data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(certreq_payload_t, add_keyid, void,
|
||||
private_certreq_payload_t *this, chunk_t keyid)
|
||||
{
|
||||
@@ -199,6 +218,10 @@ METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
|
||||
{
|
||||
keyid_enumerator_t *enumerator;
|
||||
|
||||
if (this->type == CERTIFICATE_REQUEST_V1)
|
||||
{
|
||||
return enumerator_create_empty();
|
||||
}
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = (void*)_keyid_enumerate,
|
||||
@@ -231,7 +254,7 @@ METHOD2(payload_t, certreq_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create()
|
||||
certreq_payload_t *certreq_payload_create(payload_type_t type)
|
||||
{
|
||||
private_certreq_payload_t *this;
|
||||
|
||||
@@ -240,6 +263,7 @@ certreq_payload_t *certreq_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -250,9 +274,11 @@ certreq_payload_t *certreq_payload_create()
|
||||
.get_cert_type = _get_cert_type,
|
||||
.add_keyid = _add_keyid,
|
||||
.destroy = _destroy,
|
||||
.get_dn = _get_dn,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -262,8 +288,10 @@ certreq_payload_t *certreq_payload_create()
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
|
||||
{
|
||||
private_certreq_payload_t *this = (private_certreq_payload_t*)certreq_payload_create();
|
||||
private_certreq_payload_t *this;
|
||||
|
||||
this = (private_certreq_payload_t*)
|
||||
certreq_payload_create(CERTIFICATE_REQUEST);
|
||||
switch (type)
|
||||
{
|
||||
case CERT_X509:
|
||||
@@ -278,3 +306,19 @@ certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create_dn(identification_t *id)
|
||||
{
|
||||
private_certreq_payload_t *this;
|
||||
|
||||
this = (private_certreq_payload_t*)
|
||||
certreq_payload_create(CERTIFICATE_REQUEST_V1);
|
||||
|
||||
this->encoding = ENC_X509_SIGNATURE;
|
||||
this->data = chunk_clone(id->get_encoding(id));
|
||||
this->payload_length = get_header_length(this) + this->data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -27,25 +27,20 @@ typedef struct certreq_payload_t certreq_payload_t;
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <encoding/payloads/cert_payload.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
/**
|
||||
* Length of a CERTREQ payload without the CERTREQ data in bytes.
|
||||
*/
|
||||
#define CERTREQ_PAYLOAD_HEADER_LENGTH 5
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 CERTREQ payload.
|
||||
*
|
||||
* The CERTREQ payload format is described in RFC section 3.7.
|
||||
* Class representing an IKEv1/IKEv2 CERTREQ payload.
|
||||
*/
|
||||
struct certreq_payload_t {
|
||||
|
||||
/**
|
||||
* The payload_t interface.
|
||||
*/
|
||||
payload_t payload_interface;
|
||||
|
||||
/**
|
||||
* Create an enumerator over contained keyids.
|
||||
* Create an enumerator over contained keyids (IKEv2 only).
|
||||
*
|
||||
* @return enumerator over chunk_t's.
|
||||
*/
|
||||
@@ -59,13 +54,20 @@ struct certreq_payload_t {
|
||||
certificate_type_t (*get_cert_type)(certreq_payload_t *this);
|
||||
|
||||
/**
|
||||
* Add a certificates keyid to the payload.
|
||||
* Add a certificates keyid to the payload (IKEv2 only).
|
||||
*
|
||||
* @param keyid keyid of the trusted certifcate
|
||||
* @return
|
||||
*/
|
||||
void (*add_keyid)(certreq_payload_t *this, chunk_t keyid);
|
||||
|
||||
/**
|
||||
* Get the distinguished name of the payload (IKEv1 only).
|
||||
*
|
||||
* @return DN as identity, must be destroyed
|
||||
*/
|
||||
identification_t* (*get_dn)(certreq_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an certreq_payload_t object.
|
||||
*/
|
||||
@@ -77,14 +79,22 @@ struct certreq_payload_t {
|
||||
*
|
||||
* @return certreq payload
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create(void);
|
||||
certreq_payload_t *certreq_payload_create(payload_type_t payload_type);
|
||||
|
||||
/**
|
||||
* Creates an empty certreq_payload_t for a kind of certificates.
|
||||
* Creates an empty IKEv2 certreq_payload_t for a kind of certificates.
|
||||
*
|
||||
* @param type type of the added keyids
|
||||
* @return certreq payload
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create_type(certificate_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a IKEv1 certreq_payload_t for a given distinguished name.
|
||||
*
|
||||
* @param id distinguished name, does not get owned
|
||||
* @return certreq payload
|
||||
*/
|
||||
certreq_payload_t *certreq_payload_create_dn(identification_t *id);
|
||||
|
||||
#endif /** CERTREQ_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -36,41 +36,48 @@ struct private_configuration_attribute_t {
|
||||
configuration_attribute_t public;
|
||||
|
||||
/**
|
||||
* Reserved bit
|
||||
* Value encoded in length field?
|
||||
*/
|
||||
bool af_flag;
|
||||
|
||||
/**
|
||||
* Reserved bit (af_flag in IKEv2)
|
||||
*/
|
||||
bool reserved;
|
||||
|
||||
/**
|
||||
* Type of the attribute.
|
||||
*/
|
||||
u_int16_t type;
|
||||
u_int16_t attr_type;
|
||||
|
||||
/**
|
||||
* Length of the attribute.
|
||||
* Length of the attribute, value if af_flag set.
|
||||
*/
|
||||
u_int16_t length;
|
||||
u_int16_t length_or_value;
|
||||
|
||||
/**
|
||||
* Attribute value as chunk.
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Payload type, CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a configuration attribute.
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_configuration_attribute_t.
|
||||
* Encoding rules for a IKEv2 configuration attribute / IKEv1 data attribute
|
||||
*/
|
||||
encoding_rule_t configuration_attribute_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 reserved bit */
|
||||
{ RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved)},
|
||||
{ RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved) },
|
||||
/* type of the attribute as 15 bit unsigned integer */
|
||||
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
|
||||
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
|
||||
/* Length of attribute value */
|
||||
{ CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
|
||||
{ ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length_or_value)},
|
||||
/* Value of attribute if attribute format flag is zero */
|
||||
{ CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
|
||||
{ ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -85,87 +92,142 @@ encoding_rule_t configuration_attribute_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules for a IKEv1 data attribute
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* AF Flag */
|
||||
{ ATTRIBUTE_FORMAT, offsetof(private_configuration_attribute_t, af_flag) },
|
||||
/* type of the attribute as 15 bit unsigned integer */
|
||||
{ ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
|
||||
/* Length of attribute value */
|
||||
{ ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_configuration_attribute_t, length_or_value)},
|
||||
/* Value of attribute if attribute format flag is zero */
|
||||
{ ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
|
||||
};
|
||||
|
||||
/*
|
||||
1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
!F| Attribute Type ! Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
~ Value ~
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
bool failed = FALSE;
|
||||
|
||||
if (this->length != this->value.len)
|
||||
switch (this->attr_type)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid attribute length");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
switch (this->type)
|
||||
{
|
||||
case INTERNAL_IP4_ADDRESS:
|
||||
case INTERNAL_IP4_NETMASK:
|
||||
case INTERNAL_IP4_DNS:
|
||||
case INTERNAL_IP4_NBNS:
|
||||
case INTERNAL_ADDRESS_EXPIRY:
|
||||
case INTERNAL_IP4_DHCP:
|
||||
if (this->length != 0 && this->length != 4)
|
||||
case INTERNAL_IP4_ADDRESS:
|
||||
case INTERNAL_IP4_NETMASK:
|
||||
case INTERNAL_IP4_DNS:
|
||||
case INTERNAL_IP4_NBNS:
|
||||
case INTERNAL_ADDRESS_EXPIRY:
|
||||
case INTERNAL_IP4_DHCP:
|
||||
if (this->length_or_value != 0 && this->length_or_value != 4)
|
||||
{
|
||||
failed = TRUE;
|
||||
}
|
||||
break;
|
||||
case INTERNAL_IP4_SUBNET:
|
||||
if (this->length != 0 && this->length != 8)
|
||||
case INTERNAL_IP4_SUBNET:
|
||||
if (this->length_or_value != 0 && this->length_or_value != 8)
|
||||
{
|
||||
failed = TRUE;
|
||||
}
|
||||
break;
|
||||
case INTERNAL_IP6_ADDRESS:
|
||||
case INTERNAL_IP6_SUBNET:
|
||||
if (this->length != 0 && this->length != 17)
|
||||
case INTERNAL_IP6_ADDRESS:
|
||||
case INTERNAL_IP6_SUBNET:
|
||||
if (this->length_or_value != 0 && this->length_or_value != 17)
|
||||
{
|
||||
failed = TRUE;
|
||||
}
|
||||
break;
|
||||
case INTERNAL_IP6_DNS:
|
||||
case INTERNAL_IP6_NBNS:
|
||||
case INTERNAL_IP6_DHCP:
|
||||
if (this->length != 0 && this->length != 16)
|
||||
case INTERNAL_IP6_DNS:
|
||||
case INTERNAL_IP6_NBNS:
|
||||
case INTERNAL_IP6_DHCP:
|
||||
if (this->length_or_value != 0 && this->length_or_value != 16)
|
||||
{
|
||||
failed = TRUE;
|
||||
}
|
||||
break;
|
||||
case SUPPORTED_ATTRIBUTES:
|
||||
if (this->length % 2)
|
||||
case SUPPORTED_ATTRIBUTES:
|
||||
if (this->length_or_value % 2)
|
||||
{
|
||||
failed = TRUE;
|
||||
}
|
||||
break;
|
||||
case APPLICATION_VERSION:
|
||||
case APPLICATION_VERSION:
|
||||
case INTERNAL_IP4_SERVER:
|
||||
case INTERNAL_IP6_SERVER:
|
||||
case XAUTH_TYPE:
|
||||
case XAUTH_USER_NAME:
|
||||
case XAUTH_USER_PASSWORD:
|
||||
case XAUTH_PASSCODE:
|
||||
case XAUTH_MESSAGE:
|
||||
case XAUTH_CHALLENGE:
|
||||
case XAUTH_DOMAIN:
|
||||
case XAUTH_STATUS:
|
||||
case XAUTH_NEXT_PIN:
|
||||
case XAUTH_ANSWER:
|
||||
case UNITY_BANNER:
|
||||
case UNITY_SAVE_PASSWD:
|
||||
case UNITY_DEF_DOMAIN:
|
||||
case UNITY_SPLITDNS_NAME:
|
||||
case UNITY_SPLIT_INCLUDE:
|
||||
case UNITY_NATT_PORT:
|
||||
case UNITY_LOCAL_LAN:
|
||||
case UNITY_PFS:
|
||||
case UNITY_FW_TYPE:
|
||||
case UNITY_BACKUP_SERVERS:
|
||||
case UNITY_DDNS_HOSTNAME:
|
||||
/* any length acceptable */
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
DBG1(DBG_ENC, "unknown attribute type %N",
|
||||
configuration_attribute_type_names, this->type);
|
||||
configuration_attribute_type_names, this->attr_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid attribute length %d for %N",
|
||||
this->length, configuration_attribute_type_names, this->type);
|
||||
this->length_or_value, configuration_attribute_type_names,
|
||||
this->attr_type);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_configuration_attribute_t *this, encoding_rule_t **rules,
|
||||
size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_configuration_attribute_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = configuration_attribute_encodings;
|
||||
*rule_count = countof(configuration_attribute_encodings);
|
||||
if (this->type == CONFIGURATION_ATTRIBUTE)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
return CONFIGURATION_ATTRIBUTE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -182,21 +244,35 @@ METHOD(payload_t, set_next_type, void,
|
||||
METHOD(payload_t, get_length, size_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
|
||||
return get_header_length(this) + this->value.len;
|
||||
}
|
||||
|
||||
METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
return this->type;
|
||||
return this->attr_type;
|
||||
}
|
||||
|
||||
METHOD(configuration_attribute_t, get_value, chunk_t,
|
||||
METHOD(configuration_attribute_t, get_chunk, chunk_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
if (this->af_flag)
|
||||
{
|
||||
return chunk_from_thing(this->length_or_value);
|
||||
}
|
||||
return this->value;
|
||||
}
|
||||
|
||||
METHOD(configuration_attribute_t, get_value, u_int16_t,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
if (this->af_flag)
|
||||
{
|
||||
return this->length_or_value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, configuration_attribute_t, destroy, void,
|
||||
private_configuration_attribute_t *this)
|
||||
{
|
||||
@@ -207,7 +283,7 @@ METHOD2(payload_t, configuration_attribute_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create()
|
||||
configuration_attribute_t *configuration_attribute_create(payload_type_t type)
|
||||
{
|
||||
private_configuration_attribute_t *this;
|
||||
|
||||
@@ -216,16 +292,19 @@ configuration_attribute_t *configuration_attribute_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
.get_type = _get_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_chunk = _get_chunk,
|
||||
.get_value = _get_value,
|
||||
.get_type = _get_cattr_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.type = type
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -233,15 +312,33 @@ configuration_attribute_t *configuration_attribute_create()
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create_value(
|
||||
configuration_attribute_type_t type, chunk_t value)
|
||||
configuration_attribute_t *configuration_attribute_create_chunk(
|
||||
payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk)
|
||||
{
|
||||
private_configuration_attribute_t *this;
|
||||
|
||||
this = (private_configuration_attribute_t*)configuration_attribute_create();
|
||||
this->type = ((u_int16_t)type) & 0x7FFF;
|
||||
this->value = chunk_clone(value);
|
||||
this->length = value.len;
|
||||
this = (private_configuration_attribute_t*)
|
||||
configuration_attribute_create(type);
|
||||
this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
|
||||
this->value = chunk_clone(chunk);
|
||||
this->length_or_value = chunk.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create_value(
|
||||
configuration_attribute_type_t attr_type, u_int16_t value)
|
||||
{
|
||||
private_configuration_attribute_t *this;
|
||||
|
||||
this = (private_configuration_attribute_t*)
|
||||
configuration_attribute_create(CONFIGURATION_ATTRIBUTE_V1);
|
||||
this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
|
||||
this->length_or_value = value;
|
||||
this->af_flag = TRUE;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -29,14 +29,7 @@ typedef struct configuration_attribute_t configuration_attribute_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Configuration attribute header length in bytes.
|
||||
*/
|
||||
#define CONFIGURATION_ATTRIBUTE_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2-CONFIGURATION Attribute.
|
||||
*
|
||||
* The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
|
||||
* Class representing an IKEv2 configuration attribute / IKEv1 data attribute.
|
||||
*/
|
||||
struct configuration_attribute_t {
|
||||
|
||||
@@ -53,11 +46,18 @@ struct configuration_attribute_t {
|
||||
configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Returns the value of the attribute.
|
||||
* Returns the value of the attribute as chunk.
|
||||
*
|
||||
* @return chunk_t pointing to the internal value
|
||||
*/
|
||||
chunk_t (*get_value) (configuration_attribute_t *this);
|
||||
chunk_t (*get_chunk) (configuration_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Returns the 2 byte value of the attribute as u_int16.
|
||||
*
|
||||
* @return attribute value
|
||||
*/
|
||||
u_int16_t (*get_value) (configuration_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an configuration_attribute_t object.
|
||||
@@ -68,18 +68,30 @@ struct configuration_attribute_t {
|
||||
/**
|
||||
* Creates an empty configuration attribute.
|
||||
*
|
||||
* @return created configuration attribute
|
||||
* @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
|
||||
* @return created configuration attribute
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create();
|
||||
configuration_attribute_t *configuration_attribute_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a configuration attribute with type and value.
|
||||
*
|
||||
* @param type type of configuration attribute
|
||||
* @param value value, gets cloned
|
||||
* @return created configuration attribute
|
||||
* @param type CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
|
||||
* @param attr_type type of configuration attribute
|
||||
* @param chunk attribute value, gets cloned
|
||||
* @return created configuration attribute
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create_chunk(
|
||||
payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk);
|
||||
|
||||
/**
|
||||
* Creates a IKEv1 configuration attribute with 2 bytes value (IKEv1 only).
|
||||
*
|
||||
* @param attr_type type of configuration attribute
|
||||
* @param value attribute value, gets cloned
|
||||
* @return created CONFIGURATION_ATTRIBUTE_V1 configuration attribute
|
||||
*/
|
||||
configuration_attribute_t *configuration_attribute_create_value(
|
||||
configuration_attribute_type_t type, chunk_t value);
|
||||
configuration_attribute_type_t attr_type, u_int16_t value);
|
||||
|
||||
#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/
|
||||
|
||||
Regular → Executable
+109
-35
@@ -44,7 +44,7 @@ struct private_cp_payload_t {
|
||||
/**
|
||||
* Next payload type.
|
||||
*/
|
||||
u_int8_t next_payload;
|
||||
u_int8_t next_payload;
|
||||
|
||||
/**
|
||||
* Critical flag.
|
||||
@@ -66,6 +66,11 @@ struct private_cp_payload_t {
|
||||
*/
|
||||
u_int16_t payload_length;
|
||||
|
||||
/**
|
||||
* Identifier field, IKEv1 only
|
||||
*/
|
||||
u_int16_t identifier;
|
||||
|
||||
/**
|
||||
* List of attributes, as configuration_attribute_t
|
||||
*/
|
||||
@@ -74,38 +79,40 @@ struct private_cp_payload_t {
|
||||
/**
|
||||
* Config Type.
|
||||
*/
|
||||
u_int8_t type;
|
||||
u_int8_t cfg_type;
|
||||
|
||||
/**
|
||||
* CONFIGURATION or CONFIGURATION_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a IKEv2-CP Payload
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_cp_payload_t.
|
||||
* Encoding rules to for an IKEv2 configuration payload
|
||||
*/
|
||||
encoding_rule_t cp_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
{ FLAG, offsetof(private_cp_payload_t, critical) },
|
||||
{ FLAG, offsetof(private_cp_payload_t, critical) },
|
||||
/* 7 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
|
||||
/* Length of the whole CP payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
|
||||
/* Proposals are stored in a proposal substructure,
|
||||
offset points to a linked_list_t pointer */
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, type) },
|
||||
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
|
||||
/* 3 reserved bytes */
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
|
||||
{ CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) }
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])},
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])},
|
||||
/* list of configuration attributes in a list */
|
||||
{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE,
|
||||
offsetof(private_cp_payload_t, attributes) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -122,6 +129,47 @@ encoding_rule_t cp_payload_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules to for an IKEv1 configuration payload
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
{ FLAG, offsetof(private_cp_payload_t, critical) },
|
||||
/* 7 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) },
|
||||
/* Length of the whole CP payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
|
||||
{ U_INT_8, offsetof(private_cp_payload_t, cfg_type) },
|
||||
/* 1 reserved bytes */
|
||||
{ RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])},
|
||||
{ U_INT_16, offsetof(private_cp_payload_t, identifier)},
|
||||
/* list of configuration attributes in a list */
|
||||
{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1,
|
||||
offsetof(private_cp_payload_t, attributes) },
|
||||
};
|
||||
|
||||
/*
|
||||
1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Next Payload ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! CFG Type ! RESERVED ! Identifier !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Configuration Attributes ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_cp_payload_t *this)
|
||||
{
|
||||
@@ -142,17 +190,28 @@ METHOD(payload_t, verify, status_t,
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_cp_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = cp_payload_encodings;
|
||||
*rule_count = countof(cp_payload_encodings);
|
||||
if (this->type == CONFIGURATION)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_cp_payload_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_cp_payload_t *this)
|
||||
{
|
||||
return CONFIGURATION;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -175,7 +234,7 @@ static void compute_length(private_cp_payload_t *this)
|
||||
enumerator_t *enumerator;
|
||||
payload_t *attribute;
|
||||
|
||||
this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
|
||||
this->payload_length = get_header_length(this);
|
||||
|
||||
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||
while (enumerator->enumerate(enumerator, &attribute))
|
||||
@@ -207,7 +266,18 @@ METHOD(cp_payload_t, add_attribute, void,
|
||||
METHOD(cp_payload_t, get_config_type, config_type_t,
|
||||
private_cp_payload_t *this)
|
||||
{
|
||||
return this->type;
|
||||
return this->cfg_type;
|
||||
}
|
||||
|
||||
METHOD(cp_payload_t, get_identifier, u_int16_t,
|
||||
private_cp_payload_t *this)
|
||||
{
|
||||
return this->identifier;
|
||||
}
|
||||
METHOD(cp_payload_t, set_identifier, void,
|
||||
private_cp_payload_t *this, u_int16_t identifier)
|
||||
{
|
||||
this->identifier = identifier;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, cp_payload_t, destroy, void,
|
||||
@@ -221,7 +291,7 @@ METHOD2(payload_t, cp_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
cp_payload_t *cp_payload_create_type(config_type_t type)
|
||||
cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type)
|
||||
{
|
||||
private_cp_payload_t *this;
|
||||
|
||||
@@ -230,6 +300,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -239,11 +310,14 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
|
||||
.create_attribute_enumerator = _create_attribute_enumerator,
|
||||
.add_attribute = _add_attribute,
|
||||
.get_type = _get_config_type,
|
||||
.get_identifier = _get_identifier,
|
||||
.set_identifier = _set_identifier,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = CP_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.attributes = linked_list_create(),
|
||||
.cfg_type = cfg_type,
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
@@ -252,7 +326,7 @@ cp_payload_t *cp_payload_create_type(config_type_t type)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
cp_payload_t *cp_payload_create()
|
||||
cp_payload_t *cp_payload_create(payload_type_t type)
|
||||
{
|
||||
return cp_payload_create_type(CFG_REQUEST);
|
||||
return cp_payload_create_type(type, CFG_REQUEST);
|
||||
}
|
||||
|
||||
Regular → Executable
+22
-13
@@ -30,11 +30,6 @@ typedef struct cp_payload_t cp_payload_t;
|
||||
#include <encoding/payloads/configuration_attribute.h>
|
||||
#include <utils/enumerator.h>
|
||||
|
||||
/**
|
||||
* CP_PAYLOAD length in bytes without any proposal substructure.
|
||||
*/
|
||||
#define CP_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Config Type of an Configuration Payload.
|
||||
*/
|
||||
@@ -51,9 +46,7 @@ enum config_type_t {
|
||||
extern enum_name_t *config_type_names;
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2-CP Payload.
|
||||
*
|
||||
* The CP Payload format is described in RFC section 3.15.
|
||||
* Class representing an IKEv2 configuration / IKEv1 attribute payload.
|
||||
*/
|
||||
struct cp_payload_t {
|
||||
|
||||
@@ -84,6 +77,20 @@ struct cp_payload_t {
|
||||
*/
|
||||
config_type_t (*get_type) (cp_payload_t *this);
|
||||
|
||||
/**
|
||||
* Set the configuration payload identifier (IKEv1 only).
|
||||
*
|
||||
@param identifier identifier to set
|
||||
*/
|
||||
void (*set_identifier) (cp_payload_t *this, u_int16_t identifier);
|
||||
|
||||
/**
|
||||
* Get the configuration payload identifier (IKEv1 only).
|
||||
*
|
||||
* @return identifier
|
||||
*/
|
||||
u_int16_t (*get_identifier) (cp_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an cp_payload_t object.
|
||||
*/
|
||||
@@ -93,16 +100,18 @@ struct cp_payload_t {
|
||||
/**
|
||||
* Creates an empty configuration payload
|
||||
*
|
||||
* @return empty configuration payload
|
||||
* @param type payload type, CONFIGURATION or CONFIGURATION_V1
|
||||
* @return empty configuration payload
|
||||
*/
|
||||
cp_payload_t *cp_payload_create();
|
||||
cp_payload_t *cp_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates an cp_payload_t with type and value
|
||||
*
|
||||
* @param config_type type of configuration payload to create
|
||||
* @return created configuration payload
|
||||
* @param type payload type, CONFIGURATION or CONFIGURATION_V1
|
||||
* @param cfg_type type of configuration payload to create
|
||||
* @return created configuration payload
|
||||
*/
|
||||
cp_payload_t *cp_payload_create_type(config_type_t config_type);
|
||||
cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type);
|
||||
|
||||
#endif /** CP_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -24,9 +24,9 @@ typedef struct private_delete_payload_t private_delete_payload_t;
|
||||
|
||||
/**
|
||||
* Private data of an delete_payload_t object.
|
||||
*
|
||||
*/
|
||||
struct private_delete_payload_t {
|
||||
|
||||
/**
|
||||
* Public delete_payload_t interface.
|
||||
*/
|
||||
@@ -45,13 +45,18 @@ struct private_delete_payload_t {
|
||||
/**
|
||||
* reserved bits
|
||||
*/
|
||||
bool reserved[7];
|
||||
bool reserved[8];
|
||||
|
||||
/**
|
||||
* Length of this payload.
|
||||
*/
|
||||
u_int16_t payload_length;
|
||||
|
||||
/**
|
||||
* IKEv1 Domain of Interpretation
|
||||
*/
|
||||
u_int32_t doi;
|
||||
|
||||
/**
|
||||
* Protocol ID.
|
||||
*/
|
||||
@@ -71,19 +76,21 @@ struct private_delete_payload_t {
|
||||
* The contained SPI's.
|
||||
*/
|
||||
chunk_t spis;
|
||||
|
||||
/**
|
||||
* Payload type, DELETE or DELETE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a DELETE payload
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_delete_payload_t.
|
||||
* Encoding rules for an IKEv2 delete payload.
|
||||
*/
|
||||
encoding_rule_t delete_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
{ FLAG, offsetof(private_delete_payload_t, critical) },
|
||||
{ FLAG, offsetof(private_delete_payload_t, critical) },
|
||||
/* 7 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
|
||||
@@ -98,7 +105,7 @@ encoding_rule_t delete_payload_encodings[] = {
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, spi_size) },
|
||||
{ U_INT_16, offsetof(private_delete_payload_t, spi_count) },
|
||||
/* some delete data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ SPIS, offsetof(private_delete_payload_t, spis) }
|
||||
{ CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -115,6 +122,48 @@ encoding_rule_t delete_payload_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules for an IKEv1 delete payload.
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, next_payload) },
|
||||
/* 8 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) },
|
||||
{ RESERVED_BIT, offsetof(private_delete_payload_t, reserved[7]) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
|
||||
/* Domain of interpretation */
|
||||
{ U_INT_32, offsetof(private_delete_payload_t, doi) },
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
|
||||
{ U_INT_8, offsetof(private_delete_payload_t, spi_size) },
|
||||
{ U_INT_16, offsetof(private_delete_payload_t, spi_count) },
|
||||
/* some delete data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
|
||||
};
|
||||
|
||||
/*
|
||||
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 !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! DOI !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Protocol ID ! SPI Size ! # of SPIs !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Security Parameter Index(es) (SPI) ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_delete_payload_t *this)
|
||||
{
|
||||
@@ -129,10 +178,19 @@ METHOD(payload_t, verify, status_t,
|
||||
break;
|
||||
case PROTO_IKE:
|
||||
case 0:
|
||||
/* IKE deletion has no spi assigned! */
|
||||
if (this->spi_size != 0)
|
||||
{
|
||||
return FAILED;
|
||||
if (this->type == DELETE)
|
||||
{ /* IKEv2 deletion has no spi assigned! */
|
||||
if (this->spi_size != 0)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* IKEv1 uses the two concatenated ISAKMP cookies as SPI */
|
||||
if (this->spi_size != 16)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -145,17 +203,32 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_delete_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = delete_payload_encodings;
|
||||
*rule_count = countof(delete_payload_encodings);
|
||||
if (this->type == DELETE)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_delete_payload_t *this)
|
||||
{
|
||||
if (this->type == DELETE)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
return 12;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_payload_type, payload_type_t,
|
||||
private_delete_payload_t *this)
|
||||
{
|
||||
return DELETE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -198,6 +271,16 @@ METHOD(delete_payload_t, add_spi, void,
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(delete_payload_t, set_ike_spi, void,
|
||||
private_delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r)
|
||||
{
|
||||
free(this->spis.ptr);
|
||||
this->spis = chunk_cat("cc", chunk_from_thing(spi_i),
|
||||
chunk_from_thing(spi_r));
|
||||
this->spi_count = 1;
|
||||
this->payload_length = get_header_length(this) + this->spi_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* SPI enumerator implementation
|
||||
*/
|
||||
@@ -249,7 +332,8 @@ METHOD2(payload_t, delete_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
|
||||
delete_payload_t *delete_payload_create(payload_type_t type,
|
||||
protocol_id_t protocol_id)
|
||||
{
|
||||
private_delete_payload_t *this;
|
||||
|
||||
@@ -258,6 +342,7 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -266,13 +351,27 @@ delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
|
||||
},
|
||||
.get_protocol_id = _get_protocol_id,
|
||||
.add_spi = _add_spi,
|
||||
.set_ike_spi = _set_ike_spi,
|
||||
.create_spi_enumerator = _create_spi_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = DELETE_PAYLOAD_HEADER_LENGTH,
|
||||
.protocol_id = protocol_id,
|
||||
.spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0,
|
||||
.doi = IKEV1_DOI_IPSEC,
|
||||
.type = type,
|
||||
);
|
||||
this->payload_length = get_header_length(this);
|
||||
|
||||
if (protocol_id == PROTO_IKE)
|
||||
{
|
||||
if (type == DELETE_V1)
|
||||
{
|
||||
this->spi_size = 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->spi_size = 4;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -29,14 +29,7 @@ typedef struct delete_payload_t delete_payload_t;
|
||||
#include <encoding/payloads/proposal_substructure.h>
|
||||
|
||||
/**
|
||||
* Length of a delete payload without the SPI in bytes.
|
||||
*/
|
||||
#define DELETE_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 DELETE payload.
|
||||
*
|
||||
* The DELETE payload format is described in RFC section 3.11.
|
||||
* Class representing an IKEv1 or a IKEv2 DELETE payload.
|
||||
*/
|
||||
struct delete_payload_t {
|
||||
|
||||
@@ -59,6 +52,14 @@ struct delete_payload_t {
|
||||
*/
|
||||
void (*add_spi) (delete_payload_t *this, u_int32_t spi);
|
||||
|
||||
/**
|
||||
* Set the IKE SPIs for an IKEv1 delete.
|
||||
*
|
||||
* @param spi_i initiator SPI
|
||||
* @param spi_r responder SPI
|
||||
*/
|
||||
void (*set_ike_spi)(delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r);
|
||||
|
||||
/**
|
||||
* Get an enumerator over the SPIs in network order.
|
||||
*
|
||||
@@ -75,9 +76,11 @@ struct delete_payload_t {
|
||||
/**
|
||||
* Creates an empty delete_payload_t object.
|
||||
*
|
||||
* @param type DELETE or DELETE_V1
|
||||
* @param protocol_id protocol, such as AH|ESP
|
||||
* @return delete_payload_t object
|
||||
*/
|
||||
delete_payload_t *delete_payload_create(protocol_id_t protocol_id);
|
||||
delete_payload_t *delete_payload_create(payload_type_t type,
|
||||
protocol_id_t protocol_id);
|
||||
|
||||
#endif /** DELETE_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "eap_payload.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <eap/eap.h>
|
||||
|
||||
typedef struct private_eap_payload_t private_eap_payload_t;
|
||||
|
||||
@@ -65,7 +66,7 @@ struct private_eap_payload_t {
|
||||
* private_eap_payload_t.
|
||||
*
|
||||
*/
|
||||
static encoding_rule_t eap_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_eap_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -81,7 +82,7 @@ static encoding_rule_t eap_payload_encodings[] = {
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) },
|
||||
/* chunt to data, starting at "code" */
|
||||
{ EAP_DATA, offsetof(private_eap_payload_t, data) },
|
||||
{ CHUNK_DATA, offsetof(private_eap_payload_t, data) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -143,11 +144,17 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_eap_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_eap_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = eap_payload_encodings;
|
||||
*rule_count = sizeof(eap_payload_encodings) / sizeof(encoding_rule_t);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_eap_payload_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_payload_type, payload_type_t,
|
||||
@@ -251,6 +258,7 @@ eap_payload_t *eap_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -265,7 +273,7 @@ eap_payload_t *eap_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = EAP_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -25,13 +25,8 @@
|
||||
typedef struct eap_payload_t eap_payload_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <eap/eap.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <sa/authenticators/eap/eap_method.h>
|
||||
|
||||
/**
|
||||
* Length of a EAP payload without the EAP Message in bytes.
|
||||
*/
|
||||
#define EAP_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 EAP payload.
|
||||
|
||||
@@ -29,30 +29,14 @@ ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA,
|
||||
"HEADER_LENGTH",
|
||||
"SPI_SIZE",
|
||||
"SPI",
|
||||
"KEY_EXCHANGE_DATA",
|
||||
"NOTIFICATION_DATA",
|
||||
"PROPOSALS",
|
||||
"TRANSFORMS",
|
||||
"TRANSFORM_ATTRIBUTES",
|
||||
"CONFIGURATION_ATTRIBUTES",
|
||||
"CONFIGURATION_ATTRIBUTE_VALUE",
|
||||
"ATTRIBUTE_FORMAT",
|
||||
"ATTRIBUTE_TYPE",
|
||||
"ATTRIBUTE_LENGTH_OR_VALUE",
|
||||
"CONFIGURATION_ATTRIBUTE_LENGTH",
|
||||
"ATTRIBUTE_LENGTH",
|
||||
"ATTRIBUTE_VALUE",
|
||||
"TRAFFIC_SELECTORS",
|
||||
"TS_TYPE",
|
||||
"ADDRESS",
|
||||
"NONCE_DATA",
|
||||
"ID_DATA",
|
||||
"AUTH_DATA",
|
||||
"CERT_DATA",
|
||||
"CERTREQ_DATA",
|
||||
"EAP_DATA",
|
||||
"SPIS",
|
||||
"VID_DATA",
|
||||
"UNKNOWN_DATA",
|
||||
"CHUNK_DATA",
|
||||
"IKE_SPI",
|
||||
"ENCRYPTED_DATA",
|
||||
);
|
||||
|
||||
@@ -186,87 +186,6 @@ enum encoding_type_t {
|
||||
*/
|
||||
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,
|
||||
|
||||
/**
|
||||
* Representating one or more Attributes of a configuration payload.
|
||||
*
|
||||
* The offset points to a linked_list_t pointer.
|
||||
*
|
||||
* When generating the configuration_attribute_t objects are stored
|
||||
* in the pointed linked_list.
|
||||
*
|
||||
* When parsing the parsed configuration_attribute_t objects have
|
||||
* to be stored in the pointed linked_list.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTES,
|
||||
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTE_VALUE,
|
||||
|
||||
/**
|
||||
* Representing a 1 Bit flag specifying the format of a transform attribute.
|
||||
*
|
||||
@@ -279,6 +198,7 @@ enum encoding_type_t {
|
||||
* is moved 1 bit forward afterwards.
|
||||
*/
|
||||
ATTRIBUTE_FORMAT,
|
||||
|
||||
/**
|
||||
* Representing a 15 Bit unsigned int value used as attribute type
|
||||
* in an attribute transform.
|
||||
@@ -321,7 +241,7 @@ enum encoding_type_t {
|
||||
* The value is written to the associated data struct.
|
||||
* The current read pointer is moved 16 bit forward afterwards.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTE_LENGTH,
|
||||
ATTRIBUTE_LENGTH,
|
||||
|
||||
/**
|
||||
* Depending on the field of type ATTRIBUTE_FORMAT
|
||||
@@ -335,19 +255,6 @@ enum encoding_type_t {
|
||||
*/
|
||||
ATTRIBUTE_VALUE,
|
||||
|
||||
/**
|
||||
* Representating one or more Traffic selectors of a TS payload.
|
||||
*
|
||||
* The offset points to a linked_list_t pointer.
|
||||
*
|
||||
* When generating the traffic_selector_substructure_t objects are stored
|
||||
* in the pointed linked_list.
|
||||
*
|
||||
* When parsing the parsed traffic_selector_substructure_t objects have
|
||||
* to be stored in the pointed linked_list.
|
||||
*/
|
||||
TRAFFIC_SELECTORS,
|
||||
|
||||
/**
|
||||
* Representating a Traffic selector type field.
|
||||
*
|
||||
@@ -375,94 +282,9 @@ enum encoding_type_t {
|
||||
ADDRESS,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Representing a variable length byte field.
|
||||
*/
|
||||
NONCE_DATA,
|
||||
|
||||
/**
|
||||
* Representating a ID 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.
|
||||
*/
|
||||
ID_DATA,
|
||||
|
||||
/**
|
||||
* Representating a AUTH 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.
|
||||
*/
|
||||
AUTH_DATA,
|
||||
|
||||
/**
|
||||
* Representating a CERT Data field.
|
||||
*
|
||||
* When generating the content of the chunkt pointing to
|
||||
* is written.
|
||||
*
|
||||
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
|
||||
*/
|
||||
CERT_DATA,
|
||||
|
||||
/**
|
||||
* Representating a CERTREQ Data field.
|
||||
*
|
||||
* When generating the content of the chunkt pointing to
|
||||
* is written.
|
||||
*
|
||||
* When parsing (Payload Length - 5) bytes are read and written into the chunk pointing to.
|
||||
*/
|
||||
CERTREQ_DATA,
|
||||
|
||||
/**
|
||||
* Representating an EAP message 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.
|
||||
*/
|
||||
EAP_DATA,
|
||||
|
||||
/**
|
||||
* Representating the SPIS field in a DELETE payload.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
SPIS,
|
||||
|
||||
/**
|
||||
* Representating the VID DATA field in a VENDOR ID payload.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
VID_DATA,
|
||||
|
||||
/**
|
||||
* Representating the DATA of an unknown payload.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
UNKNOWN_DATA,
|
||||
CHUNK_DATA,
|
||||
|
||||
/**
|
||||
* Representating an IKE_SPI field in an IKEv2 Header.
|
||||
@@ -475,9 +297,20 @@ enum encoding_type_t {
|
||||
IKE_SPI,
|
||||
|
||||
/**
|
||||
* Representing the encrypted data body of a encryption payload.
|
||||
* Representating an encrypted IKEv1 message.
|
||||
*/
|
||||
ENCRYPTED_DATA,
|
||||
|
||||
/**
|
||||
* Reprensenting a field containing a set of wrapped payloads.
|
||||
*
|
||||
* This type is not used directly, but as an offset to the wrapped payloads.
|
||||
* The type of the wrapped payload is added to this encoding type.
|
||||
*
|
||||
* @note As payload types are added to this encoding type, it has
|
||||
* to be the last in encoding_type_t.
|
||||
*/
|
||||
PAYLOAD_LIST = 1000 /* no comma, read above! */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Martin Willi
|
||||
* Copyright (C) 2010 revosec AG
|
||||
* Copyright (C) 2011 Tobias Brunner
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -71,6 +72,11 @@ struct private_encryption_payload_t {
|
||||
* Contained payloads
|
||||
*/
|
||||
linked_list_t *payloads;
|
||||
|
||||
/**
|
||||
* Type of payload, ENCRYPTED or ENCRYPTED_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -79,7 +85,7 @@ struct private_encryption_payload_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_encryption_payload_t.
|
||||
*/
|
||||
encoding_rule_t encryption_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
|
||||
/* Critical and 7 reserved bits, all stored for reconstruction */
|
||||
@@ -87,7 +93,7 @@ encoding_rule_t encryption_payload_encodings[] = {
|
||||
/* Length of the whole encryption payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
|
||||
/* encrypted data, stored in a chunk. contains iv, data, padding */
|
||||
{ ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
|
||||
{ CHUNK_DATA, offsetof(private_encryption_payload_t, encrypted) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -109,24 +115,59 @@ encoding_rule_t encryption_payload_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a complete encrypted IKEv1 message.
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_encryption_payload_t.
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* encrypted data, stored in a chunk */
|
||||
{ ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
|
||||
};
|
||||
|
||||
/*
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Encrypted IKE Payloads !
|
||||
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! ! Padding (0-255 octets) !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_encryption_payload_t *this)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_encryption_payload_t *this, encoding_rule_t **rules,
|
||||
size_t *count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_encryption_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = encryption_payload_encodings;
|
||||
*count = countof(encryption_payload_encodings);
|
||||
if (this->type == ENCRYPTED)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_encryption_payload_t *this)
|
||||
{
|
||||
if (this->type == ENCRYPTED)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_encryption_payload_t *this)
|
||||
{
|
||||
return ENCRYPTED;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -138,7 +179,8 @@ METHOD(payload_t, get_next_type, payload_type_t,
|
||||
METHOD(payload_t, set_next_type, void,
|
||||
private_encryption_payload_t *this, payload_type_t type)
|
||||
{
|
||||
/* the next payload is set during add */
|
||||
/* the next payload is set during add, still allow this for IKEv1 */
|
||||
this->next_payload = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +216,7 @@ static void compute_length(private_encryption_payload_t *this)
|
||||
length += this->aead->get_icv_size(this->aead);
|
||||
}
|
||||
}
|
||||
length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
|
||||
length += get_header_length(this);
|
||||
this->payload_length = length;
|
||||
}
|
||||
|
||||
@@ -335,6 +377,47 @@ METHOD(encryption_payload_t, encrypt, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(encryption_payload_t, encrypt_v1, bool,
|
||||
private_encryption_payload_t *this, chunk_t iv)
|
||||
{
|
||||
generator_t *generator;
|
||||
chunk_t plain, padding;
|
||||
size_t bs;
|
||||
|
||||
if (this->aead == NULL)
|
||||
{
|
||||
DBG1(DBG_ENC, "encryption failed, transform missing");
|
||||
chunk_free(&iv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
generator = generator_create();
|
||||
plain = generate(this, generator);
|
||||
bs = this->aead->get_block_size(this->aead);
|
||||
padding.len = bs - (plain.len % bs);
|
||||
|
||||
/* prepare data to encrypt:
|
||||
* | plain | padding | */
|
||||
free(this->encrypted.ptr);
|
||||
this->encrypted = chunk_alloc(plain.len + padding.len);
|
||||
memcpy(this->encrypted.ptr, plain.ptr, plain.len);
|
||||
plain.ptr = this->encrypted.ptr;
|
||||
padding.ptr = plain.ptr + plain.len;
|
||||
memset(padding.ptr, 0, padding.len);
|
||||
generator->destroy(generator);
|
||||
|
||||
DBG3(DBG_ENC, "encrypting payloads:");
|
||||
DBG3(DBG_ENC, "plain %B", &plain);
|
||||
DBG3(DBG_ENC, "padding %B", &padding);
|
||||
|
||||
this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL);
|
||||
chunk_free(&iv);
|
||||
|
||||
DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the payloads after decryption.
|
||||
*/
|
||||
@@ -349,6 +432,13 @@ static status_t parse(private_encryption_payload_t *this, chunk_t plain)
|
||||
{
|
||||
payload_t *payload;
|
||||
|
||||
if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
|
||||
payload_type_names, type);
|
||||
parser->destroy(parser);
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
if (parser->parse_payload(parser, type, &payload) != SUCCESS)
|
||||
{
|
||||
parser->destroy(parser);
|
||||
@@ -438,6 +528,36 @@ METHOD(encryption_payload_t, decrypt, status_t,
|
||||
return parse(this, plain);
|
||||
}
|
||||
|
||||
METHOD(encryption_payload_t, decrypt_v1, status_t,
|
||||
private_encryption_payload_t *this, chunk_t iv)
|
||||
{
|
||||
if (this->aead == NULL)
|
||||
{
|
||||
DBG1(DBG_ENC, "decryption failed, transform missing");
|
||||
chunk_free(&iv);
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
/* data must be a multiple of block size */
|
||||
if (iv.len != this->aead->get_block_size(this->aead) ||
|
||||
this->encrypted.len < iv.len || this->encrypted.len % iv.len)
|
||||
{
|
||||
DBG1(DBG_ENC, "decryption failed, invalid length");
|
||||
chunk_free(&iv);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
DBG3(DBG_ENC, "decrypting payloads:");
|
||||
DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
|
||||
|
||||
this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL);
|
||||
chunk_free(&iv);
|
||||
|
||||
DBG3(DBG_ENC, "plain %B", &this->encrypted);
|
||||
|
||||
return parse(this, this->encrypted);
|
||||
}
|
||||
|
||||
METHOD(encryption_payload_t, set_transform, void,
|
||||
private_encryption_payload_t *this, aead_t* aead)
|
||||
{
|
||||
@@ -455,7 +575,7 @@ METHOD2(payload_t, encryption_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
encryption_payload_t *encryption_payload_create()
|
||||
encryption_payload_t *encryption_payload_create(payload_type_t type)
|
||||
{
|
||||
private_encryption_payload_t *this;
|
||||
|
||||
@@ -464,6 +584,7 @@ encryption_payload_t *encryption_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -479,9 +600,16 @@ encryption_payload_t *encryption_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.payloads = linked_list_create(),
|
||||
.type = type,
|
||||
);
|
||||
|
||||
if (type == ENCRYPTED_V1)
|
||||
{
|
||||
this->public.encrypt = _encrypt_v1;
|
||||
this->public.decrypt = _decrypt_v1;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,6 @@ typedef struct encryption_payload_t encryption_payload_t;
|
||||
#include <crypto/aead.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Encrpytion payload length in bytes without IV and following data.
|
||||
*/
|
||||
#define ENCRYPTION_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* The encryption payload as described in RFC section 3.14.
|
||||
*/
|
||||
@@ -102,8 +97,9 @@ struct encryption_payload_t {
|
||||
/**
|
||||
* Creates an empty encryption_payload_t object.
|
||||
*
|
||||
* @param type ENCRYPTED or ENCRYPTED_V1
|
||||
* @return encryption_payload_t object
|
||||
*/
|
||||
encryption_payload_t *encryption_payload_create(void);
|
||||
encryption_payload_t *encryption_payload_create(payload_type_t type);
|
||||
|
||||
#endif /** ENCRYPTION_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -227,7 +227,7 @@ METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
|
||||
chunk_t data;
|
||||
notify_payload_t *notify;
|
||||
|
||||
notify = notify_payload_create();
|
||||
notify = notify_payload_create(NOTIFY);
|
||||
notify->set_notify_type(notify, ME_ENDPOINT);
|
||||
data = build_notification_data(this);
|
||||
notify->set_notification_data(notify, data);
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* 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 <stddef.h>
|
||||
|
||||
#include "hash_payload.h"
|
||||
|
||||
#include <encoding/payloads/encodings.h>
|
||||
|
||||
typedef struct private_hash_payload_t private_hash_payload_t;
|
||||
|
||||
/**
|
||||
* Private data of an hash_payload_t object.
|
||||
*/
|
||||
struct private_hash_payload_t {
|
||||
|
||||
/**
|
||||
* Public hash_payload_t interface.
|
||||
*/
|
||||
hash_payload_t public;
|
||||
|
||||
/**
|
||||
* Next payload type.
|
||||
*/
|
||||
u_int8_t next_payload;
|
||||
|
||||
/**
|
||||
* Reserved byte
|
||||
*/
|
||||
u_int8_t reserved;
|
||||
|
||||
/**
|
||||
* Length of this payload.
|
||||
*/
|
||||
u_int16_t payload_length;
|
||||
|
||||
/**
|
||||
* The contained hash value.
|
||||
*/
|
||||
chunk_t hash;
|
||||
|
||||
/**
|
||||
* either HASH_V1 or NAT_D_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules for an IKEv1 hash payload
|
||||
*/
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_hash_payload_t, next_payload) },
|
||||
{ RESERVED_BYTE, offsetof(private_hash_payload_t, reserved) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_hash_payload_t, payload_length) },
|
||||
/* Hash Data is from variable size */
|
||||
{ CHUNK_DATA, offsetof(private_hash_payload_t, hash) },
|
||||
};
|
||||
|
||||
/*
|
||||
1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Next Payload ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Hash Data ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_hash_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return this->next_payload;
|
||||
}
|
||||
|
||||
METHOD(payload_t, set_next_type, void,
|
||||
private_hash_payload_t *this, payload_type_t type)
|
||||
{
|
||||
this->next_payload = type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_length, size_t,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return this->payload_length;
|
||||
}
|
||||
|
||||
METHOD(hash_payload_t, set_hash, void,
|
||||
private_hash_payload_t *this, chunk_t hash)
|
||||
{
|
||||
free(this->hash.ptr);
|
||||
this->hash = chunk_clone(hash);
|
||||
this->payload_length = get_header_length(this) + hash.len;
|
||||
}
|
||||
|
||||
METHOD(hash_payload_t, get_hash, chunk_t,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
return this->hash;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, hash_payload_t, destroy, void,
|
||||
private_hash_payload_t *this)
|
||||
{
|
||||
free(this->hash.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
hash_payload_t *hash_payload_create(payload_type_t type)
|
||||
{
|
||||
private_hash_payload_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
.get_type = _get_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.set_hash = _set_hash,
|
||||
.get_hash = _get_hash,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Martin Willi
|
||||
* Copyright (C) 2011 revosec AG
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup hash_payload hash_payload
|
||||
* @{ @ingroup payloads
|
||||
*/
|
||||
|
||||
#ifndef HASH_PAYLOAD_H_
|
||||
#define HASH_PAYLOAD_H_
|
||||
|
||||
typedef struct hash_payload_t hash_payload_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Object representing an IKEv1 hash payload.
|
||||
*/
|
||||
struct hash_payload_t {
|
||||
|
||||
/**
|
||||
* The payload_t interface.
|
||||
*/
|
||||
payload_t payload_interface;
|
||||
|
||||
/**
|
||||
* Set the hash value.
|
||||
*
|
||||
* @param hash chunk containing the hash, will be cloned
|
||||
*/
|
||||
void (*set_hash) (hash_payload_t *this, chunk_t hash);
|
||||
|
||||
/**
|
||||
* Get the hash value.
|
||||
*
|
||||
* @return chunkt to internal hash data
|
||||
*/
|
||||
chunk_t (*get_hash) (hash_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an hash_payload_t object.
|
||||
*/
|
||||
void (*destroy) (hash_payload_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an empty hash_payload_t object.
|
||||
*
|
||||
* @param type either HASH_V1 or NAT_D_V1
|
||||
* @return hash_payload_t object
|
||||
*/
|
||||
hash_payload_t *hash_payload_create(payload_type_t type);
|
||||
|
||||
#endif /** HASH_PAYLOAD_H_ @}*/
|
||||
@@ -1,9 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Martin Willi
|
||||
* Copyright (C) 2005-2011 Martin Willi
|
||||
* Copyright (C) 2010 revosec AG
|
||||
* Copyright (C) 2007 Tobias Brunner
|
||||
* Copyright (C) 2007-2011 Tobias Brunner
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
*
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -28,19 +27,14 @@ typedef struct private_id_payload_t private_id_payload_t;
|
||||
|
||||
/**
|
||||
* Private data of an id_payload_t object.
|
||||
*
|
||||
*/
|
||||
struct private_id_payload_t {
|
||||
|
||||
/**
|
||||
* Public id_payload_t interface.
|
||||
*/
|
||||
id_payload_t public;
|
||||
|
||||
/**
|
||||
* one of ID_INITIATOR, ID_RESPONDER
|
||||
*/
|
||||
payload_type_t payload_type;
|
||||
|
||||
/**
|
||||
* Next payload type.
|
||||
*/
|
||||
@@ -75,19 +69,31 @@ struct private_id_payload_t {
|
||||
* The contained id data value.
|
||||
*/
|
||||
chunk_t id_data;
|
||||
|
||||
/**
|
||||
* Tunneled protocol ID for IKEv1 quick modes.
|
||||
*/
|
||||
u_int8_t protocol_id;
|
||||
|
||||
/**
|
||||
* Tunneled port for IKEv1 quick modes.
|
||||
*/
|
||||
u_int16_t port;
|
||||
|
||||
/**
|
||||
* one of ID_INITIATOR, ID_RESPONDER, IDv1 and NAT_OA_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a ID payload
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_id_payload_t.
|
||||
* Encoding rules for an IKEv2 ID payload
|
||||
*/
|
||||
encoding_rule_t id_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
|
||||
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
{ FLAG, offsetof(private_id_payload_t, critical) },
|
||||
{ FLAG, offsetof(private_id_payload_t, critical) },
|
||||
/* 7 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
|
||||
@@ -97,7 +103,7 @@ encoding_rule_t id_payload_encodings[] = {
|
||||
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
|
||||
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
|
||||
/* 1 Byte ID type*/
|
||||
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
|
||||
/* 3 reserved bytes */
|
||||
@@ -105,7 +111,7 @@ encoding_rule_t id_payload_encodings[] = {
|
||||
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])},
|
||||
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])},
|
||||
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ ID_DATA, offsetof(private_id_payload_t, id_data) }
|
||||
{ CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -122,29 +128,92 @@ encoding_rule_t id_payload_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules for an IKEv1 ID payload
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_id_payload_t, next_payload) },
|
||||
/* Reserved Byte is skipped */
|
||||
{ RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
|
||||
/* 1 Byte ID type*/
|
||||
{ U_INT_8, offsetof(private_id_payload_t, id_type) },
|
||||
{ U_INT_8, offsetof(private_id_payload_t, protocol_id) },
|
||||
{ U_INT_16, offsetof(private_id_payload_t, port) },
|
||||
/* some id data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ CHUNK_DATA, offsetof(private_id_payload_t, id_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 ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! ID Type ! Protocol ID ! Port |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Identification Data ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
if (this->id_type == 0 || this->id_type == 4)
|
||||
bool bad_length = FALSE;
|
||||
|
||||
if (this->type == NAT_OA_V1 &&
|
||||
this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
|
||||
{
|
||||
/* reserved IDs */
|
||||
DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type);
|
||||
DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
|
||||
this->id_type, payload_type_short_names, this->type);
|
||||
return FAILED;
|
||||
}
|
||||
switch (this->id_type)
|
||||
{
|
||||
case ID_IPV4_ADDR_RANGE:
|
||||
case ID_IPV4_ADDR_SUBNET:
|
||||
bad_length = this->id_data.len != 8;
|
||||
break;
|
||||
case ID_IPV6_ADDR_RANGE:
|
||||
case ID_IPV6_ADDR_SUBNET:
|
||||
bad_length = this->id_data.len != 32;
|
||||
break;
|
||||
}
|
||||
if (bad_length)
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid %N length (%d bytes)",
|
||||
id_type_names, this->id_type, this->id_data.len);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_id_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = id_payload_encodings;
|
||||
*rule_count = countof(id_payload_encodings);
|
||||
if (this->type == ID_V1 || this->type == NAT_OA_V1)
|
||||
{
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
return this->payload_type;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -171,6 +240,102 @@ METHOD(id_payload_t, get_identification, identification_t*,
|
||||
return identification_create_from_encoding(this->id_type, this->id_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a traffic selector from an range ID
|
||||
*/
|
||||
static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
|
||||
ts_type_t type)
|
||||
{
|
||||
return traffic_selector_create_from_bytes(this->protocol_id, type,
|
||||
chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
|
||||
chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a traffic selector from an subnet ID
|
||||
*/
|
||||
static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
|
||||
ts_type_t type)
|
||||
{
|
||||
chunk_t net, netmask;
|
||||
int i;
|
||||
|
||||
net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
|
||||
netmask = chunk_skip(this->id_data, this->id_data.len / 2);
|
||||
for (i = 0; i < net.len; i++)
|
||||
{
|
||||
netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
|
||||
}
|
||||
return traffic_selector_create_from_bytes(this->protocol_id, type,
|
||||
net, this->port, netmask, this->port ?: 65535);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a traffic selector from an IP ID
|
||||
*/
|
||||
static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
|
||||
ts_type_t type)
|
||||
{
|
||||
return traffic_selector_create_from_bytes(this->protocol_id, type,
|
||||
this->id_data, this->port, this->id_data, this->port ?: 65535);
|
||||
}
|
||||
|
||||
METHOD(id_payload_t, get_ts, traffic_selector_t*,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
switch (this->id_type)
|
||||
{
|
||||
case ID_IPV4_ADDR_SUBNET:
|
||||
if (this->id_data.len == 8)
|
||||
{
|
||||
return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
case ID_IPV6_ADDR_SUBNET:
|
||||
if (this->id_data.len == 32)
|
||||
{
|
||||
return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
case ID_IPV4_ADDR_RANGE:
|
||||
if (this->id_data.len == 8)
|
||||
{
|
||||
return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
case ID_IPV6_ADDR_RANGE:
|
||||
if (this->id_data.len == 32)
|
||||
{
|
||||
return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
case ID_IPV4_ADDR:
|
||||
if (this->id_data.len == 4)
|
||||
{
|
||||
return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
case ID_IPV6_ADDR:
|
||||
if (this->id_data.len == 16)
|
||||
{
|
||||
return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(id_payload_t, get_encoded, chunk_t,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
u_int16_t port = htons(this->port);
|
||||
return chunk_cat("cccc", chunk_from_thing(this->id_type),
|
||||
chunk_from_thing(this->protocol_id),
|
||||
chunk_from_thing(port), this->id_data);
|
||||
}
|
||||
|
||||
METHOD2(payload_t, id_payload_t, destroy, void,
|
||||
private_id_payload_t *this)
|
||||
{
|
||||
@@ -181,7 +346,7 @@ METHOD2(payload_t, id_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
id_payload_t *id_payload_create(payload_type_t payload_type)
|
||||
id_payload_t *id_payload_create(payload_type_t type)
|
||||
{
|
||||
private_id_payload_t *this;
|
||||
|
||||
@@ -190,6 +355,7 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -197,11 +363,13 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_identification = _get_identification,
|
||||
.get_encoded = _get_encoded,
|
||||
.get_ts = _get_ts,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = ID_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_type = payload_type,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -209,15 +377,89 @@ id_payload_t *id_payload_create(payload_type_t payload_type)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
|
||||
id_payload_t *id_payload_create_from_identification(payload_type_t type,
|
||||
identification_t *id)
|
||||
{
|
||||
private_id_payload_t *this;
|
||||
|
||||
this = (private_id_payload_t*)id_payload_create(payload_type);
|
||||
this = (private_id_payload_t*)id_payload_create(type);
|
||||
this->id_data = chunk_clone(id->get_encoding(id));
|
||||
this->id_type = id->get_type(id);
|
||||
this->payload_length += this->id_data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
|
||||
{
|
||||
private_id_payload_t *this;
|
||||
u_int8_t mask;
|
||||
host_t *net;
|
||||
|
||||
this = (private_id_payload_t*)id_payload_create(ID_V1);
|
||||
|
||||
if (ts->is_host(ts, NULL))
|
||||
{
|
||||
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
|
||||
{
|
||||
this->id_type = ID_IPV4_ADDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->id_type = ID_IPV6_ADDR;
|
||||
}
|
||||
this->id_data = chunk_clone(ts->get_from_address(ts));
|
||||
}
|
||||
else if (ts->to_subnet(ts, &net, &mask))
|
||||
{
|
||||
u_int8_t netmask[16], len, byte;
|
||||
|
||||
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
|
||||
{
|
||||
this->id_type = ID_IPV4_ADDR_SUBNET;
|
||||
len = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->id_type = ID_IPV6_ADDR_SUBNET;
|
||||
len = 16;
|
||||
}
|
||||
memset(netmask, 0, sizeof(netmask));
|
||||
for (byte = 0; byte < sizeof(netmask); byte++)
|
||||
{
|
||||
if (mask < 8)
|
||||
{
|
||||
netmask[byte] = 0xFF << (8 - mask);
|
||||
break;
|
||||
}
|
||||
netmask[byte] = 0xFF;
|
||||
mask -= 8;
|
||||
}
|
||||
this->id_data = chunk_cat("cc", net->get_address(net),
|
||||
chunk_create(netmask, len));
|
||||
net->destroy(net);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
|
||||
{
|
||||
this->id_type = ID_IPV4_ADDR_RANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->id_type = ID_IPV6_ADDR_RANGE;
|
||||
}
|
||||
this->id_data = chunk_cat("cc",
|
||||
ts->get_from_address(ts), ts->get_to_address(ts));
|
||||
net->destroy(net);
|
||||
}
|
||||
this->port = ts->get_from_port(ts);
|
||||
this->protocol_id = ts->get_protocol(ts);
|
||||
this->payload_length += this->id_data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,16 +28,10 @@ typedef struct id_payload_t id_payload_t;
|
||||
#include <library.h>
|
||||
#include <utils/identification.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <selectors/traffic_selector.h>
|
||||
|
||||
/**
|
||||
* Length of a id payload without the data in bytes.
|
||||
*/
|
||||
#define ID_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Object representing an IKEv2 ID payload.
|
||||
*
|
||||
* The ID payload format is described in RFC section 3.5.
|
||||
* Object representing an IKEv1 or an IKEv2 ID payload.
|
||||
*/
|
||||
struct id_payload_t {
|
||||
|
||||
@@ -53,6 +47,20 @@ struct id_payload_t {
|
||||
*/
|
||||
identification_t *(*get_identification) (id_payload_t *this);
|
||||
|
||||
/**
|
||||
* Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity.
|
||||
*
|
||||
* @return traffic selector, NULL on failure
|
||||
*/
|
||||
traffic_selector_t* (*get_ts)(id_payload_t *this);
|
||||
|
||||
/**
|
||||
* Get encoded payload without fixed payload header (used for IKEv1).
|
||||
*
|
||||
* @return encoded payload (gets allocated)
|
||||
*/
|
||||
chunk_t (*get_encoded)(id_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an id_payload_t object.
|
||||
*/
|
||||
@@ -62,19 +70,27 @@ struct id_payload_t {
|
||||
/**
|
||||
* Creates an empty id_payload_t object.
|
||||
*
|
||||
* @param payload_type one of ID_INITIATOR, ID_RESPONDER
|
||||
* @return id_payload_t object
|
||||
* @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
|
||||
* @return id_payload_t object
|
||||
*/
|
||||
id_payload_t *id_payload_create(payload_type_t payload_type);
|
||||
id_payload_t *id_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates an id_payload_t from an existing identification_t object.
|
||||
*
|
||||
* @param payload_type one of ID_INITIATOR, ID_RESPONDER
|
||||
* @param identification identification_t object
|
||||
* @return id_payload_t object
|
||||
* @param type one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
|
||||
* @param id identification_t object
|
||||
* @return id_payload_t object
|
||||
*/
|
||||
id_payload_t *id_payload_create_from_identification(payload_type_t payload_type,
|
||||
identification_t *identification);
|
||||
id_payload_t *id_payload_create_from_identification(payload_type_t type,
|
||||
identification_t *id);
|
||||
|
||||
/**
|
||||
* Create an IKEv1 ID_ADDR_SUBNET/RANGE identity from a traffic selector.
|
||||
*
|
||||
* @param ts traffic selector
|
||||
* @return ID_V1 id_paylad_t object.
|
||||
*/
|
||||
id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts);
|
||||
|
||||
#endif /** ID_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -81,12 +81,27 @@ struct private_ike_header_t {
|
||||
* TRUE, if this is a response, FALSE if its a Request.
|
||||
*/
|
||||
bool response;
|
||||
|
||||
/**
|
||||
* TRUE, if the packet is encrypted (IKEv1).
|
||||
*/
|
||||
bool encryption;
|
||||
|
||||
/**
|
||||
* TRUE, if the commit flag is set (IKEv1).
|
||||
*/
|
||||
bool commit;
|
||||
|
||||
/**
|
||||
* TRUE, if the auth only flag is set (IKEv1).
|
||||
*/
|
||||
bool authonly;
|
||||
} flags;
|
||||
|
||||
/**
|
||||
* Reserved bits of IKE header
|
||||
*/
|
||||
bool reserved[5];
|
||||
bool reserved[2];
|
||||
|
||||
/**
|
||||
* Associated Message-ID.
|
||||
@@ -99,9 +114,15 @@ struct private_ike_header_t {
|
||||
u_int32_t length;
|
||||
};
|
||||
|
||||
ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
|
||||
"EXCHANGE_TYPE_UNDEFINED");
|
||||
ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UNDEFINED,
|
||||
ENUM_BEGIN(exchange_type_names, ID_PROT, TRANSACTION,
|
||||
"ID_PROT",
|
||||
"AUTH_ONLY",
|
||||
"AGGRESSIVE",
|
||||
"INFORMATIONAL_V1",
|
||||
"TRANSACTION");
|
||||
ENUM_NEXT(exchange_type_names, QUICK_MODE, IKE_SESSION_RESUME, TRANSACTION,
|
||||
"QUICK_MODE",
|
||||
"NEW_GROUP_MODE",
|
||||
"IKE_SA_INIT",
|
||||
"IKE_AUTH",
|
||||
"CREATE_CHILD_SA",
|
||||
@@ -110,18 +131,23 @@ ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UN
|
||||
#ifdef ME
|
||||
ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, IKE_SESSION_RESUME,
|
||||
"ME_CONNECT");
|
||||
ENUM_END(exchange_type_names, ME_CONNECT);
|
||||
ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
|
||||
EXCHANGE_TYPE_UNDEFINED, ME_CONNECT,
|
||||
"EXCHANGE_TYPE_UNDEFINED");
|
||||
#else
|
||||
ENUM_END(exchange_type_names, IKE_SESSION_RESUME);
|
||||
ENUM_NEXT(exchange_type_names, EXCHANGE_TYPE_UNDEFINED,
|
||||
EXCHANGE_TYPE_UNDEFINED, IKE_SESSION_RESUME,
|
||||
"EXCHANGE_TYPE_UNDEFINED");
|
||||
#endif /* ME */
|
||||
ENUM_END(exchange_type_names, EXCHANGE_TYPE_UNDEFINED);
|
||||
|
||||
/**
|
||||
* Encoding rules to parse or generate a IKEv2-Header.
|
||||
* Encoding rules to parse or generate a IKE-Header.
|
||||
*
|
||||
* The defined offsets are the positions in a object of type
|
||||
* ike_header_t.
|
||||
*/
|
||||
encoding_rule_t ike_header_encodings[] = {
|
||||
static encoding_rule_t 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 */
|
||||
@@ -137,22 +163,20 @@ encoding_rule_t ike_header_encodings[] = {
|
||||
/* 2 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[1]) },
|
||||
/* 3 Bit flags, stored in the fields response, version and initiator */
|
||||
/* 6 flags */
|
||||
{ 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 */
|
||||
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_ike_header_t, reserved[4]) },
|
||||
{ FLAG, offsetof(private_ike_header_t, flags.authonly) },
|
||||
{ FLAG, offsetof(private_ike_header_t, flags.commit) },
|
||||
{ FLAG, offsetof(private_ike_header_t, flags.encryption)},
|
||||
/* 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) },
|
||||
{ HEADER_LENGTH, offsetof(private_ike_header_t, length) }
|
||||
};
|
||||
|
||||
|
||||
/* 1 2 3
|
||||
/* 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 !
|
||||
@@ -172,35 +196,67 @@ encoding_rule_t ike_header_encodings[] = {
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
if ((this->exchange_type < IKE_SA_INIT) ||
|
||||
((this->exchange_type > INFORMATIONAL)
|
||||
#ifdef ME
|
||||
&& (this->exchange_type != ME_CONNECT)
|
||||
#endif /* ME */
|
||||
))
|
||||
switch (this->exchange_type)
|
||||
{
|
||||
/* unsupported exchange type */
|
||||
return FAILED;
|
||||
case ID_PROT:
|
||||
case AGGRESSIVE:
|
||||
if (this->message_id != 0)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
/* fall */
|
||||
case AUTH_ONLY:
|
||||
case INFORMATIONAL_V1:
|
||||
case TRANSACTION:
|
||||
case QUICK_MODE:
|
||||
case NEW_GROUP_MODE:
|
||||
if (this->maj_version != IKEV1_MAJOR_VERSION)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
break;
|
||||
case IKE_SA_INIT:
|
||||
case IKE_AUTH:
|
||||
case CREATE_CHILD_SA:
|
||||
case INFORMATIONAL:
|
||||
case IKE_SESSION_RESUME:
|
||||
#ifdef ME
|
||||
case ME_CONNECT:
|
||||
#endif /* ME */
|
||||
if (this->maj_version != IKEV2_MAJOR_VERSION)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* unsupported exchange type */
|
||||
return FAILED;
|
||||
}
|
||||
if (this->initiator_spi == 0
|
||||
#ifdef ME
|
||||
/* we allow zero spi for INFORMATIONAL exchanges,
|
||||
* to allow connectivity checks */
|
||||
&& this->exchange_type != INFORMATIONAL
|
||||
#endif /* ME */
|
||||
)
|
||||
if (this->initiator_spi == 0)
|
||||
{
|
||||
/* initiator spi not set */
|
||||
return FAILED;
|
||||
#ifdef ME
|
||||
if (this->exchange_type != INFORMATIONAL)
|
||||
/* we allow zero spi for INFORMATIONAL exchanges,
|
||||
* to allow connectivity checks */
|
||||
#endif /* ME */
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_ike_header_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = ike_header_encodings;
|
||||
*rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
return IKE_HEADER_LENGTH;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
@@ -311,6 +367,43 @@ METHOD(ike_header_t, set_initiator_flag, void,
|
||||
this->flags.initiator = initiator;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, get_encryption_flag, bool,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
return this->flags.encryption;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, set_encryption_flag, void,
|
||||
private_ike_header_t *this, bool encryption)
|
||||
{
|
||||
this->flags.encryption = encryption;
|
||||
}
|
||||
|
||||
|
||||
METHOD(ike_header_t, get_commit_flag, bool,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
return this->flags.commit;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, set_commit_flag, void,
|
||||
private_ike_header_t *this, bool commit)
|
||||
{
|
||||
this->flags.commit = commit;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, get_authonly_flag, bool,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
return this->flags.authonly;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, set_authonly_flag, void,
|
||||
private_ike_header_t *this, bool authonly)
|
||||
{
|
||||
this->flags.authonly = authonly;
|
||||
}
|
||||
|
||||
METHOD(ike_header_t, get_exchange_type, u_int8_t,
|
||||
private_ike_header_t *this)
|
||||
{
|
||||
@@ -353,6 +446,7 @@ ike_header_t *ike_header_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -373,21 +467,38 @@ ike_header_t *ike_header_create()
|
||||
.set_version_flag = _set_version_flag,
|
||||
.get_initiator_flag = _get_initiator_flag,
|
||||
.set_initiator_flag = _set_initiator_flag,
|
||||
.get_encryption_flag = _get_encryption_flag,
|
||||
.set_encryption_flag = _set_encryption_flag,
|
||||
.get_commit_flag = _get_commit_flag,
|
||||
.set_commit_flag = _set_commit_flag,
|
||||
.get_authonly_flag = _get_authonly_flag,
|
||||
.set_authonly_flag = _set_authonly_flag,
|
||||
.get_exchange_type = _get_exchange_type,
|
||||
.set_exchange_type = _set_exchange_type,
|
||||
.get_message_id = _get_message_id,
|
||||
.set_message_id = _set_message_id,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.maj_version = IKE_MAJOR_VERSION,
|
||||
.min_version = IKE_MINOR_VERSION,
|
||||
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
|
||||
.flags = {
|
||||
.initiator = TRUE,
|
||||
.version = HIGHER_VERSION_SUPPORTED_FLAG,
|
||||
},
|
||||
.length = IKE_HEADER_LENGTH,
|
||||
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ike_header_t *ike_header_create_version(int major, int minor)
|
||||
{
|
||||
ike_header_t *this = ike_header_create();
|
||||
|
||||
this->set_maj_version(this, major);
|
||||
this->set_min_version(this, minor);
|
||||
if (major == IKEV2_MAJOR_VERSION)
|
||||
{
|
||||
this->set_initiator_flag(this, TRUE);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Tobias Brunner
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005-2011 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -30,19 +30,24 @@ typedef struct ike_header_t ike_header_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Major Version of IKEv2.
|
||||
* Major Version of IKEv1 we implement.
|
||||
*/
|
||||
#define IKE_MAJOR_VERSION 2
|
||||
#define IKEV1_MAJOR_VERSION 1
|
||||
|
||||
/**
|
||||
* Minor Version of IKEv2.
|
||||
* Minor Version of IKEv1 we implement.
|
||||
*/
|
||||
#define IKE_MINOR_VERSION 0
|
||||
#define IKEV1_MINOR_VERSION 0
|
||||
|
||||
/**
|
||||
* Flag in IKEv2-Header. Always 0.
|
||||
* Major Version of IKEv2 we implement.
|
||||
*/
|
||||
#define HIGHER_VERSION_SUPPORTED_FLAG 0
|
||||
#define IKEV2_MAJOR_VERSION 2
|
||||
|
||||
/**
|
||||
* Minor Version of IKEv2 we implement.
|
||||
*/
|
||||
#define IKEV2_MINOR_VERSION 0
|
||||
|
||||
/**
|
||||
* Length of IKE Header in Bytes.
|
||||
@@ -57,9 +62,39 @@ typedef struct ike_header_t ike_header_t;
|
||||
enum exchange_type_t{
|
||||
|
||||
/**
|
||||
* EXCHANGE_TYPE_UNDEFINED. In private space, since not a official message type.
|
||||
* Identity Protection (Main mode).
|
||||
*/
|
||||
EXCHANGE_TYPE_UNDEFINED = 255,
|
||||
ID_PROT = 2,
|
||||
|
||||
/**
|
||||
* Authentication Only.
|
||||
*/
|
||||
AUTH_ONLY = 3,
|
||||
|
||||
/**
|
||||
* Aggresive (Aggressive mode)
|
||||
*/
|
||||
AGGRESSIVE = 4,
|
||||
|
||||
/**
|
||||
* Informational in IKEv1
|
||||
*/
|
||||
INFORMATIONAL_V1 = 5,
|
||||
|
||||
/**
|
||||
* Transaction (ISAKMP Cfg Mode "draft-ietf-ipsec-isakmp-mode-cfg-05")
|
||||
*/
|
||||
TRANSACTION = 6,
|
||||
|
||||
/**
|
||||
* Quick Mode
|
||||
*/
|
||||
QUICK_MODE = 32,
|
||||
|
||||
/**
|
||||
* New Group Mode
|
||||
*/
|
||||
NEW_GROUP_MODE = 33,
|
||||
|
||||
/**
|
||||
* IKE_SA_INIT.
|
||||
@@ -77,7 +112,7 @@ enum exchange_type_t{
|
||||
CREATE_CHILD_SA = 36,
|
||||
|
||||
/**
|
||||
* INFORMATIONAL.
|
||||
* INFORMATIONAL in IKEv2.
|
||||
*/
|
||||
INFORMATIONAL = 37,
|
||||
|
||||
@@ -85,12 +120,18 @@ enum exchange_type_t{
|
||||
* IKE_SESSION_RESUME (RFC 5723).
|
||||
*/
|
||||
IKE_SESSION_RESUME = 38,
|
||||
|
||||
#ifdef ME
|
||||
/**
|
||||
* ME_CONNECT
|
||||
*/
|
||||
ME_CONNECT = 240
|
||||
ME_CONNECT = 240,
|
||||
#endif /* ME */
|
||||
|
||||
/**
|
||||
* Undefined exchange type, in private space.
|
||||
*/
|
||||
EXCHANGE_TYPE_UNDEFINED = 255,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -99,12 +140,7 @@ enum exchange_type_t{
|
||||
extern enum_name_t *exchange_type_names;
|
||||
|
||||
/**
|
||||
* An object of this type represents an IKEv2 header and is used to
|
||||
* generate and parse IKEv2 headers.
|
||||
*
|
||||
* The header format of an IKEv2-Message is compatible to the
|
||||
* ISAKMP-Header format to allow implementations supporting
|
||||
* both versions of the IKE-protocol.
|
||||
* An object of this type represents an IKE header of either IKEv1 or IKEv2.
|
||||
*/
|
||||
struct ike_header_t {
|
||||
/**
|
||||
@@ -115,7 +151,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the initiator spi.
|
||||
*
|
||||
* @return initiator_spi
|
||||
* @return initiator_spi
|
||||
*/
|
||||
u_int64_t (*get_initiator_spi) (ike_header_t *this);
|
||||
|
||||
@@ -129,7 +165,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the responder spi.
|
||||
*
|
||||
* @return responder_spi
|
||||
* @return responder_spi
|
||||
*/
|
||||
u_int64_t (*get_responder_spi) (ike_header_t *this);
|
||||
|
||||
@@ -143,7 +179,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the major version.
|
||||
*
|
||||
* @return major version
|
||||
* @return major version
|
||||
*/
|
||||
u_int8_t (*get_maj_version) (ike_header_t *this);
|
||||
|
||||
@@ -157,7 +193,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the minor version.
|
||||
*
|
||||
* @return minor version
|
||||
* @return minor version
|
||||
*/
|
||||
u_int8_t (*get_min_version) (ike_header_t *this);
|
||||
|
||||
@@ -171,7 +207,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the response flag.
|
||||
*
|
||||
* @return response flag
|
||||
* @return response flag
|
||||
*/
|
||||
bool (*get_response_flag) (ike_header_t *this);
|
||||
|
||||
@@ -185,7 +221,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get "higher version supported"-flag.
|
||||
*
|
||||
* @return version flag
|
||||
* @return version flag
|
||||
*/
|
||||
bool (*get_version_flag) (ike_header_t *this);
|
||||
|
||||
@@ -199,7 +235,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the initiator flag.
|
||||
*
|
||||
* @return initiator flag
|
||||
* @return initiator flag
|
||||
*/
|
||||
bool (*get_initiator_flag) (ike_header_t *this);
|
||||
|
||||
@@ -210,10 +246,52 @@ struct ike_header_t {
|
||||
*/
|
||||
void (*set_initiator_flag) (ike_header_t *this, bool initiator);
|
||||
|
||||
/**
|
||||
* Get the encryption flag.
|
||||
*
|
||||
* @return encryption flag
|
||||
*/
|
||||
bool (*get_encryption_flag) (ike_header_t *this);
|
||||
|
||||
/**
|
||||
* Set the encryption flag.
|
||||
*
|
||||
* @param encryption encryption flag
|
||||
*/
|
||||
void (*set_encryption_flag) (ike_header_t *this, bool encryption);
|
||||
|
||||
/**
|
||||
* Get the commit flag.
|
||||
*
|
||||
* @return commit flag
|
||||
*/
|
||||
bool (*get_commit_flag) (ike_header_t *this);
|
||||
|
||||
/**
|
||||
* Set the commit flag.
|
||||
*
|
||||
* @param commit commit flag
|
||||
*/
|
||||
void (*set_commit_flag) (ike_header_t *this, bool commit);
|
||||
|
||||
/**
|
||||
* Get the authentication only flag.
|
||||
*
|
||||
* @return authonly flag
|
||||
*/
|
||||
bool (*get_authonly_flag) (ike_header_t *this);
|
||||
|
||||
/**
|
||||
* Set the authentication only flag.
|
||||
*
|
||||
* @param authonly authonly flag
|
||||
*/
|
||||
void (*set_authonly_flag) (ike_header_t *this, bool authonly);
|
||||
|
||||
/**
|
||||
* Get the exchange type.
|
||||
*
|
||||
* @return exchange type
|
||||
* @return exchange type
|
||||
*/
|
||||
u_int8_t (*get_exchange_type) (ike_header_t *this);
|
||||
|
||||
@@ -227,7 +305,7 @@ struct ike_header_t {
|
||||
/**
|
||||
* Get the message id.
|
||||
*
|
||||
* @return message id
|
||||
* @return message id
|
||||
*/
|
||||
u_int32_t (*get_message_id) (ike_header_t *this);
|
||||
|
||||
@@ -245,10 +323,17 @@ struct ike_header_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an ike_header_t object
|
||||
* Create an empty ike_header_t object.
|
||||
*
|
||||
* @return ike_header_t object
|
||||
*/
|
||||
ike_header_t *ike_header_create(void);
|
||||
|
||||
/**
|
||||
* Create an ike_header_t object for a specific major/minor version
|
||||
*
|
||||
* @return ike_header_t object
|
||||
*/
|
||||
ike_header_t *ike_header_create_version(int major, int minor);
|
||||
|
||||
#endif /** IKE_HEADER_H_ @}*/
|
||||
|
||||
@@ -67,15 +67,17 @@ struct private_ke_payload_t {
|
||||
* Key Exchange Data of this KE payload.
|
||||
*/
|
||||
chunk_t key_exchange_data;
|
||||
|
||||
/**
|
||||
* Payload type, KEY_EXCHANGE or KEY_EXCHANGE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 rules for IKEv2 key exchange payload.
|
||||
*/
|
||||
encoding_rule_t ke_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -96,7 +98,7 @@ encoding_rule_t ke_payload_encodings[] = {
|
||||
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
|
||||
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])},
|
||||
/* Key Exchange Data is from variable size */
|
||||
{ KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)}
|
||||
{ CHUNK_DATA, offsetof(private_ke_payload_t, key_exchange_data)},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -113,23 +115,62 @@ encoding_rule_t ke_payload_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_ke_payload_t, next_payload) },
|
||||
/* Reserved Byte */
|
||||
{ RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])},
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
|
||||
/* Key Exchange Data is from variable size */
|
||||
{ CHUNK_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 ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Key Exchange Data ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_ke_payload_t *this)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_ke_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = ke_payload_encodings;
|
||||
*rule_count = countof(ke_payload_encodings);
|
||||
if (this->type == KEY_EXCHANGE)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_ke_payload_t *this)
|
||||
{
|
||||
if (this->type == KEY_EXCHANGE)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_ke_payload_t *this)
|
||||
{
|
||||
return KEY_EXCHANGE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -172,7 +213,7 @@ METHOD2(payload_t, ke_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
ke_payload_t *ke_payload_create()
|
||||
ke_payload_t *ke_payload_create(payload_type_t type)
|
||||
{
|
||||
private_ke_payload_t *this;
|
||||
|
||||
@@ -181,6 +222,7 @@ ke_payload_t *ke_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -192,22 +234,24 @@ ke_payload_t *ke_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = KE_PAYLOAD_HEADER_LENGTH,
|
||||
.dh_group_number = MODP_NONE,
|
||||
.type = type,
|
||||
);
|
||||
this->payload_length = get_header_length(this);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
|
||||
diffie_hellman_t *dh)
|
||||
{
|
||||
private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
|
||||
private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type);
|
||||
|
||||
dh->get_my_public_value(dh, &this->key_exchange_data);
|
||||
this->dh_group_number = dh->get_dh_group(dh);
|
||||
this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH;
|
||||
this->payload_length += this->key_exchange_data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -31,16 +31,10 @@ typedef struct ke_payload_t ke_payload_t;
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
/**
|
||||
* KE payload length in bytes without any key exchange data.
|
||||
*/
|
||||
#define KE_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2-KE Payload.
|
||||
*
|
||||
* The KE Payload format is described in RFC section 3.4.
|
||||
* Class representing an IKEv1 or IKEv2 key exchange payload.
|
||||
*/
|
||||
struct ke_payload_t {
|
||||
|
||||
/**
|
||||
* The payload_t interface.
|
||||
*/
|
||||
@@ -54,32 +48,34 @@ struct ke_payload_t {
|
||||
chunk_t (*get_key_exchange_data) (ke_payload_t *this);
|
||||
|
||||
/**
|
||||
* Gets the Diffie-Hellman Group Number of this KE payload.
|
||||
* Gets the Diffie-Hellman Group Number of this KE payload (IKEv2 only).
|
||||
*
|
||||
* @return DH Group Number of this payload
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an ke_payload_t object.
|
||||
* Destroys a ke_payload_t object.
|
||||
*/
|
||||
void (*destroy) (ke_payload_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an empty ke_payload_t object
|
||||
* Creates an empty ke_payload_t object.
|
||||
*
|
||||
* @return ke_payload_t object
|
||||
* @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
|
||||
* @return ke_payload_t object
|
||||
*/
|
||||
ke_payload_t *ke_payload_create(void);
|
||||
ke_payload_t *ke_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a ke_payload_t from a diffie_hellman_t
|
||||
* Creates a ke_payload_t from a diffie_hellman_t.
|
||||
*
|
||||
* @param diffie_hellman diffie hellman object containing group and key
|
||||
* @return ke_payload_t object
|
||||
* @param type KEY_EXCHANGE or KEY_EXCHANGE_V1
|
||||
* @param dh diffie hellman object containing group and key
|
||||
* @return ke_payload_t object
|
||||
*/
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(
|
||||
diffie_hellman_t *diffie_hellman);
|
||||
ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type,
|
||||
diffie_hellman_t *dh);
|
||||
|
||||
#endif /** KE_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "nonce_payload.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <encoding/payloads/encodings.h>
|
||||
|
||||
typedef struct private_nonce_payload_t private_nonce_payload_t;
|
||||
@@ -57,6 +58,11 @@ struct private_nonce_payload_t {
|
||||
* The contained nonce value.
|
||||
*/
|
||||
chunk_t nonce;
|
||||
|
||||
/**
|
||||
* Payload type, NONCE or NONCE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -65,7 +71,7 @@ struct private_nonce_payload_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_nonce_payload_t.
|
||||
*/
|
||||
encoding_rule_t nonce_payload_encodings[] = {
|
||||
static encoding_rule_t 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 */
|
||||
@@ -81,7 +87,7 @@ encoding_rule_t nonce_payload_encodings[] = {
|
||||
/* 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) },
|
||||
{ CHUNK_DATA, offsetof(private_nonce_payload_t, nonce) },
|
||||
};
|
||||
|
||||
/* 1 2 3
|
||||
@@ -98,24 +104,48 @@ encoding_rule_t nonce_payload_encodings[] = {
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_nonce_payload_t *this)
|
||||
{
|
||||
if (this->nonce.len < 16 || this->nonce.len > 256)
|
||||
bool bad_length = FALSE;
|
||||
|
||||
if (this->nonce.len > 256)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
if (this->type == NONCE &&
|
||||
this->nonce.len < 16)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
if (this->type == NONCE_V1 &&
|
||||
this->nonce.len < 8)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
if (bad_length)
|
||||
{
|
||||
DBG1(DBG_ENC, "%N payload has invalid length (%d bytes)",
|
||||
payload_type_names, this->type, this->nonce.len);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_nonce_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = nonce_payload_encodings;
|
||||
*rule_count = countof(nonce_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_nonce_payload_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_nonce_payload_t *this)
|
||||
{
|
||||
return NONCE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -140,7 +170,7 @@ METHOD(nonce_payload_t, set_nonce, void,
|
||||
private_nonce_payload_t *this, chunk_t nonce)
|
||||
{
|
||||
this->nonce = chunk_clone(nonce);
|
||||
this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len;
|
||||
this->payload_length = get_header_length(this) + nonce.len;
|
||||
}
|
||||
|
||||
METHOD(nonce_payload_t, get_nonce, chunk_t,
|
||||
@@ -159,7 +189,7 @@ METHOD2(payload_t, nonce_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
nonce_payload_t *nonce_payload_create()
|
||||
nonce_payload_t *nonce_payload_create(payload_type_t type)
|
||||
{
|
||||
private_nonce_payload_t *this;
|
||||
|
||||
@@ -168,6 +198,7 @@ nonce_payload_t *nonce_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -179,7 +210,8 @@ nonce_payload_t *nonce_payload_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = NONCE_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -33,14 +33,7 @@ typedef struct nonce_payload_t nonce_payload_t;
|
||||
#define NONCE_SIZE 32
|
||||
|
||||
/**
|
||||
* Length of a nonce payload without a nonce in bytes.
|
||||
*/
|
||||
#define NONCE_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Object representing an IKEv2 Nonce payload.
|
||||
*
|
||||
* The Nonce payload format is described in RFC section 3.3.
|
||||
* Object representing an IKEv1/IKEv2 Nonce payload.
|
||||
*/
|
||||
struct nonce_payload_t {
|
||||
/**
|
||||
@@ -71,8 +64,9 @@ struct nonce_payload_t {
|
||||
/**
|
||||
* Creates an empty nonce_payload_t object
|
||||
*
|
||||
* @return nonce_payload_t object
|
||||
* @param type NONCE or NONCE_V1
|
||||
* @return nonce_payload_t object
|
||||
*/
|
||||
nonce_payload_t *nonce_payload_create(void);
|
||||
nonce_payload_t *nonce_payload_create(payload_type_t type);
|
||||
|
||||
#endif /** NONCE_PAYLOAD_H_ @}*/
|
||||
|
||||
Regular → Executable
+209
-75
@@ -36,11 +36,18 @@ ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYN
|
||||
"INVALID_MESSAGE_ID");
|
||||
ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
|
||||
"INVALID_SPI");
|
||||
ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
|
||||
ENUM_NEXT(notify_type_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
|
||||
"ATTRIBUTES_NOT_SUPPORTED",
|
||||
"NO_PROPOSAL_CHOSEN");
|
||||
ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
|
||||
"INVALID_KE_PAYLOAD");
|
||||
ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
|
||||
ENUM_NEXT(notify_type_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
|
||||
"PAYLOAD_MALFORMED",
|
||||
"INVALID_KE_PAYLOAD",
|
||||
"INVALID_ID_INFORMATION",
|
||||
"INVALID_CERT_ENCODING",
|
||||
"INVALID_CERTIFICATE",
|
||||
"CERT_TYPE_UNSUPPORTED",
|
||||
"INVALID_CERT_AUTHORITY",
|
||||
"INVALID_HASH_INFORMATION",
|
||||
"AUTHENTICATION_FAILED");
|
||||
ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
|
||||
"SINGLE_PAIR_REQUIRED",
|
||||
@@ -102,7 +109,14 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS,
|
||||
"SECURE PASSWORD_METHOD",
|
||||
"PSK_PERSIST",
|
||||
"PSK_CONFIRM");
|
||||
ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, PSK_CONFIRM,
|
||||
ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
|
||||
"INITIAL_CONTACT");
|
||||
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
|
||||
"DPD_R_U_THERE",
|
||||
"DPD_R_U_THERE_ACK");
|
||||
ENUM_NEXT(notify_type_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
|
||||
"UNITY_LOAD_BALANCE");
|
||||
ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
|
||||
"USE_BEET_MODE");
|
||||
ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
|
||||
"ME_MEDIATION",
|
||||
@@ -127,11 +141,18 @@ ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVAL
|
||||
"INVAL_MID");
|
||||
ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
|
||||
"INVAL_SPI");
|
||||
ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
|
||||
ENUM_NEXT(notify_type_short_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
|
||||
"ATTR_UNSUP",
|
||||
"NO_PROP");
|
||||
ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
|
||||
"INVAL_KE");
|
||||
ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
|
||||
ENUM_NEXT(notify_type_short_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
|
||||
"PLD_MAL",
|
||||
"INVAL_KE",
|
||||
"INVAL_ID",
|
||||
"INVAL_CERTEN",
|
||||
"INVAL_CERT",
|
||||
"CERT_UNSUP",
|
||||
"INVAL_CA",
|
||||
"INVAL_HASH",
|
||||
"AUTH_FAILED");
|
||||
ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
|
||||
"SINGLE_PAIR",
|
||||
@@ -193,7 +214,14 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATU
|
||||
"SEC_PASSWD",
|
||||
"PSK_PST",
|
||||
"PSK_CFM");
|
||||
ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, PSK_CONFIRM,
|
||||
ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM,
|
||||
"INITIAL_CONTACT");
|
||||
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
|
||||
"DPD",
|
||||
"DPD_ACK");
|
||||
ENUM_NEXT(notify_type_short_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
|
||||
"UNITY_LB");
|
||||
ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
|
||||
"BEET_MODE");
|
||||
ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
|
||||
"ME_MED",
|
||||
@@ -232,13 +260,18 @@ struct private_notify_payload_t {
|
||||
/**
|
||||
* reserved bits
|
||||
*/
|
||||
bool reserved[7];
|
||||
bool reserved[8];
|
||||
|
||||
/**
|
||||
* Length of this payload.
|
||||
*/
|
||||
u_int16_t payload_length;
|
||||
|
||||
/**
|
||||
* Domain of interpretation, IKEv1 only.
|
||||
*/
|
||||
u_int32_t doi;
|
||||
|
||||
/**
|
||||
* Protocol id.
|
||||
*/
|
||||
@@ -262,40 +295,42 @@ struct private_notify_payload_t {
|
||||
/**
|
||||
* Notification data.
|
||||
*/
|
||||
chunk_t notification_data;
|
||||
chunk_t notify_data;
|
||||
|
||||
/**
|
||||
* Type of payload, NOTIFY or NOTIFY_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 rules for an IKEv2 notification payload
|
||||
*/
|
||||
encoding_rule_t notify_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
|
||||
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
{ FLAG, offsetof(private_notify_payload_t, critical) },
|
||||
{ FLAG, offsetof(private_notify_payload_t, critical) },
|
||||
/* 7 Bit reserved bits, nowhere stored */
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
|
||||
{ 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) },
|
||||
{ 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) },
|
||||
{ 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_type) },
|
||||
{ U_INT_16, offsetof(private_notify_payload_t, notify_type) },
|
||||
/* SPI as variable length field*/
|
||||
{ SPI, offsetof(private_notify_payload_t, spi) },
|
||||
{ SPI, offsetof(private_notify_payload_t, spi) },
|
||||
/* Key Exchange Data is from variable size */
|
||||
{ NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) }
|
||||
{ CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -315,6 +350,57 @@ encoding_rule_t notify_payload_encodings[] = {
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
/**
|
||||
* Encoding rules for an IKEv1 notification payload
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_notify_payload_t, next_payload) },
|
||||
/* 8 reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
|
||||
{ RESERVED_BIT, offsetof(private_notify_payload_t, reserved[7]) },
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
|
||||
/* DOI as 32 bit field*/
|
||||
{ U_INT_32, offsetof(private_notify_payload_t, doi) },
|
||||
/* 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_type) },
|
||||
/* SPI as variable length field*/
|
||||
{ SPI, offsetof(private_notify_payload_t, spi) },
|
||||
/* Key Exchange Data is from variable size */
|
||||
{ CHUNK_DATA, offsetof(private_notify_payload_t, notify_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 ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! DOI !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Protocol ID ! SPI Size ! Notify Message Type !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Security Parameter Index (SPI) ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Notification Data ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_notify_payload_t *this)
|
||||
@@ -337,7 +423,7 @@ METHOD(payload_t, verify, status_t,
|
||||
{
|
||||
case INVALID_KE_PAYLOAD:
|
||||
{
|
||||
if (this->notification_data.len != 2)
|
||||
if (this->type == NOTIFY && this->notify_data.len != 2)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -347,7 +433,7 @@ METHOD(payload_t, verify, status_t,
|
||||
case NAT_DETECTION_DESTINATION_IP:
|
||||
case ME_CONNECTAUTH:
|
||||
{
|
||||
if (this->notification_data.len != HASH_SIZE_SHA1)
|
||||
if (this->notify_data.len != HASH_SIZE_SHA1)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -357,7 +443,7 @@ METHOD(payload_t, verify, status_t,
|
||||
case INVALID_MAJOR_VERSION:
|
||||
case NO_PROPOSAL_CHOSEN:
|
||||
{
|
||||
if (this->notification_data.len != 0)
|
||||
if (this->type == NOTIFY && this->notify_data.len != 0)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -365,7 +451,7 @@ METHOD(payload_t, verify, status_t,
|
||||
}
|
||||
case ADDITIONAL_IP4_ADDRESS:
|
||||
{
|
||||
if (this->notification_data.len != 4)
|
||||
if (this->notify_data.len != 4)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -373,7 +459,7 @@ METHOD(payload_t, verify, status_t,
|
||||
}
|
||||
case ADDITIONAL_IP6_ADDRESS:
|
||||
{
|
||||
if (this->notification_data.len != 16)
|
||||
if (this->notify_data.len != 16)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -381,7 +467,7 @@ METHOD(payload_t, verify, status_t,
|
||||
}
|
||||
case AUTH_LIFETIME:
|
||||
{
|
||||
if (this->notification_data.len != 4)
|
||||
if (this->notify_data.len != 4)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -389,30 +475,37 @@ METHOD(payload_t, verify, status_t,
|
||||
}
|
||||
case IPCOMP_SUPPORTED:
|
||||
{
|
||||
if (this->notification_data.len != 3)
|
||||
if (this->notify_data.len != 3)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ME_ENDPOINT:
|
||||
if (this->notification_data.len != 8 &&
|
||||
this->notification_data.len != 12 &&
|
||||
this->notification_data.len != 24)
|
||||
if (this->notify_data.len != 8 &&
|
||||
this->notify_data.len != 12 &&
|
||||
this->notify_data.len != 24)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
break;
|
||||
case ME_CONNECTID:
|
||||
if (this->notification_data.len < 4 ||
|
||||
this->notification_data.len > 16)
|
||||
if (this->notify_data.len < 4 ||
|
||||
this->notify_data.len > 16)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
break;
|
||||
case ME_CONNECTKEY:
|
||||
if (this->notification_data.len < 16 ||
|
||||
this->notification_data.len > 32)
|
||||
if (this->notify_data.len < 16 ||
|
||||
this->notify_data.len > 32)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
break;
|
||||
case DPD_R_U_THERE:
|
||||
case DPD_R_U_THERE_ACK:
|
||||
if (this->notify_data.len != 4)
|
||||
{
|
||||
bad_length = TRUE;
|
||||
}
|
||||
@@ -425,23 +518,38 @@ METHOD(payload_t, verify, status_t,
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
|
||||
notify_type_names, this->notify_type,
|
||||
this->notification_data.len);
|
||||
this->notify_data.len);
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_notify_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = notify_payload_encodings;
|
||||
*rule_count = countof(notify_payload_encodings);
|
||||
if (this->type == NOTIFY)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_notify_payload_t *this)
|
||||
{
|
||||
if (this->type == NOTIFY)
|
||||
{
|
||||
return 8 + this->spi_size;
|
||||
}
|
||||
return 12 + this->spi_size;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_notify_payload_t *this)
|
||||
{
|
||||
return NOTIFY;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -459,19 +567,9 @@ METHOD(payload_t, set_next_type, void,
|
||||
/**
|
||||
* recompute the payloads length.
|
||||
*/
|
||||
static void compute_length (private_notify_payload_t *this)
|
||||
static void 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;
|
||||
this->payload_length = get_header_length(this) + this->notify_data.len;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_length, size_t,
|
||||
@@ -539,24 +637,55 @@ METHOD(notify_payload_t, set_spi, void,
|
||||
compute_length(this);
|
||||
}
|
||||
|
||||
METHOD(notify_payload_t, get_spi_data, chunk_t,
|
||||
private_notify_payload_t *this)
|
||||
{
|
||||
switch (this->protocol_id)
|
||||
{
|
||||
case PROTO_IKE:
|
||||
if (this->spi.len == 16)
|
||||
{
|
||||
return this->spi;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return chunk_empty;
|
||||
}
|
||||
|
||||
METHOD(notify_payload_t, set_spi_data, void,
|
||||
private_notify_payload_t *this, chunk_t spi)
|
||||
{
|
||||
chunk_free(&this->spi);
|
||||
switch (this->protocol_id)
|
||||
{
|
||||
case PROTO_IKE:
|
||||
this->spi = chunk_clone(spi);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->spi_size = this->spi.len;
|
||||
compute_length(this);
|
||||
}
|
||||
|
||||
METHOD(notify_payload_t, get_notification_data, chunk_t,
|
||||
private_notify_payload_t *this)
|
||||
{
|
||||
return this->notification_data;
|
||||
return this->notify_data;
|
||||
}
|
||||
|
||||
METHOD(notify_payload_t, set_notification_data, void,
|
||||
private_notify_payload_t *this, chunk_t data)
|
||||
{
|
||||
free(this->notification_data.ptr);
|
||||
this->notification_data = chunk_clone(data);
|
||||
free(this->notify_data.ptr);
|
||||
this->notify_data = chunk_clone(data);
|
||||
compute_length(this);
|
||||
}
|
||||
|
||||
METHOD2(payload_t, notify_payload_t, destroy, void,
|
||||
private_notify_payload_t *this)
|
||||
{
|
||||
free(this->notification_data.ptr);
|
||||
free(this->notify_data.ptr);
|
||||
free(this->spi.ptr);
|
||||
free(this);
|
||||
}
|
||||
@@ -564,7 +693,7 @@ METHOD2(payload_t, notify_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
notify_payload_t *notify_payload_create()
|
||||
notify_payload_t *notify_payload_create(payload_type_t type)
|
||||
{
|
||||
private_notify_payload_t *this;
|
||||
|
||||
@@ -573,6 +702,7 @@ notify_payload_t *notify_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -585,13 +715,17 @@ notify_payload_t *notify_payload_create()
|
||||
.set_notify_type = _set_notify_type,
|
||||
.get_spi = _get_spi,
|
||||
.set_spi = _set_spi,
|
||||
.get_spi_data = _get_spi_data,
|
||||
.set_spi_data = _set_spi_data,
|
||||
.get_notification_data = _get_notification_data,
|
||||
.set_notification_data = _set_notification_data,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.doi = IKEV1_DOI_IPSEC,
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH,
|
||||
.type = type,
|
||||
);
|
||||
compute_length(this);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -599,12 +733,12 @@ notify_payload_t *notify_payload_create()
|
||||
* Described in header.
|
||||
*/
|
||||
notify_payload_t *notify_payload_create_from_protocol_and_type(
|
||||
protocol_id_t protocol_id, notify_type_t notify_type)
|
||||
payload_type_t type, protocol_id_t protocol, notify_type_t notify)
|
||||
{
|
||||
notify_payload_t *notify = notify_payload_create();
|
||||
notify_payload_t *this = notify_payload_create(type);
|
||||
|
||||
notify->set_notify_type(notify, notify_type);
|
||||
notify->set_protocol_id(notify, protocol_id);
|
||||
this->set_notify_type(this, notify);
|
||||
this->set_protocol_id(this, protocol);
|
||||
|
||||
return notify;
|
||||
return this;
|
||||
}
|
||||
|
||||
Regular → Executable
+50
-12
@@ -33,25 +33,36 @@ typedef struct notify_payload_t notify_payload_t;
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
/**
|
||||
* Notify payload length in bytes without any spi and notification data.
|
||||
*/
|
||||
#define NOTIFY_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Notify message types.
|
||||
*
|
||||
* See IKEv2 RFC 3.10.1.
|
||||
* Notify message types for IKEv2, and a subset for IKEv1.
|
||||
*/
|
||||
enum notify_type_t {
|
||||
/* notify error messages */
|
||||
UNSUPPORTED_CRITICAL_PAYLOAD = 1,
|
||||
/* IKEv1 alias */
|
||||
INVALID_PAYLOAD_TYPE = 1,
|
||||
INVALID_IKE_SPI = 4,
|
||||
INVALID_MAJOR_VERSION = 5,
|
||||
INVALID_SYNTAX = 7,
|
||||
/* IKEv1 alias */
|
||||
INVALID_EXCHANGE_TYPE = 7,
|
||||
INVALID_MESSAGE_ID = 9,
|
||||
INVALID_SPI = 11,
|
||||
/* IKEv1 only */
|
||||
ATTRIBUTES_NOT_SUPPORTED = 13,
|
||||
/* IKEv1 alias */
|
||||
NO_PROPOSAL_CHOSEN = 14,
|
||||
/* IKEv1 only */
|
||||
PAYLOAD_MALFORMED = 16,
|
||||
INVALID_KE_PAYLOAD = 17,
|
||||
/* IKEv1 alias */
|
||||
INVALID_KEY_INFORMATION = 17,
|
||||
/* IKEv1 only */
|
||||
INVALID_ID_INFORMATION = 18,
|
||||
INVALID_CERT_ENCODING = 19,
|
||||
INVALID_CERTIFICATE = 20,
|
||||
CERT_TYPE_UNSUPPORTED = 21,
|
||||
INVALID_CERT_AUTHORITY = 22,
|
||||
INVALID_HASH_INFORMATION = 23,
|
||||
AUTHENTICATION_FAILED = 24,
|
||||
SINGLE_PAIR_REQUIRED = 34,
|
||||
NO_ADDITIONAL_SAS = 35,
|
||||
@@ -132,6 +143,13 @@ enum notify_type_t {
|
||||
/* PACE - draft-kuegler-ipsecme-pace-ikev2 */
|
||||
PSK_PERSIST = 16425,
|
||||
PSK_CONFIRM = 16426,
|
||||
/* IKEv1 initial contact */
|
||||
INITIAL_CONTACT_IKEV1 = 24578,
|
||||
/* IKEv1 DPD */
|
||||
DPD_R_U_THERE = 36136,
|
||||
DPD_R_U_THERE_ACK = 36137,
|
||||
/* IKEv1 Cisco High Availability */
|
||||
UNITY_LOAD_BALANCE = 40501,
|
||||
/* BEET mode, not even a draft yet. private use */
|
||||
USE_BEET_MODE = 40961,
|
||||
/* IKE-ME, private use */
|
||||
@@ -213,6 +231,24 @@ struct notify_payload_t {
|
||||
*/
|
||||
void (*set_spi) (notify_payload_t *this, u_int32_t spi);
|
||||
|
||||
/**
|
||||
* Returns the currently set spi of this payload.
|
||||
*
|
||||
* This is only valid for notifys with protocol ISAKMP
|
||||
*
|
||||
* @return SPI value
|
||||
*/
|
||||
chunk_t (*get_spi_data) (notify_payload_t *this);
|
||||
|
||||
/**
|
||||
* Sets the spi of this payload.
|
||||
*
|
||||
* This is only valid for notifys with protocol ISAKMP
|
||||
*
|
||||
* @param spi SPI value
|
||||
*/
|
||||
void (*set_spi_data) (notify_payload_t *this, chunk_t spi);
|
||||
|
||||
/**
|
||||
* Returns the currently set notification data of payload.
|
||||
*
|
||||
@@ -241,18 +277,20 @@ struct notify_payload_t {
|
||||
/**
|
||||
* Creates an empty notify_payload_t object
|
||||
*
|
||||
* @param type payload type, NOTIFY or NOTIFY_V1
|
||||
* @return created notify_payload_t object
|
||||
*/
|
||||
notify_payload_t *notify_payload_create(void);
|
||||
notify_payload_t *notify_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates an notify_payload_t object of specific type for specific protocol id.
|
||||
*
|
||||
* @param protocol_id protocol id (IKE, AH or ESP)
|
||||
* @param type notify type (see notify_type_t)
|
||||
* @param type payload type, NOTIFY or NOTIFY_V1
|
||||
* @param protocol protocol id (IKE, AH or ESP)
|
||||
* @param notify type of notify
|
||||
* @return notify_payload_t object
|
||||
*/
|
||||
notify_payload_t *notify_payload_create_from_protocol_and_type(
|
||||
protocol_id_t protocol_id, notify_type_t type);
|
||||
payload_type_t type, protocol_id_t protocol, notify_type_t notify);
|
||||
|
||||
#endif /** NOTIFY_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <encoding/payloads/ike_header.h>
|
||||
#include <encoding/payloads/sa_payload.h>
|
||||
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
#include <encoding/payloads/id_payload.h>
|
||||
#include <encoding/payloads/ke_payload.h>
|
||||
@@ -34,13 +35,30 @@
|
||||
#include <encoding/payloads/cp_payload.h>
|
||||
#include <encoding/payloads/configuration_attribute.h>
|
||||
#include <encoding/payloads/eap_payload.h>
|
||||
#include <encoding/payloads/hash_payload.h>
|
||||
#include <encoding/payloads/unknown_payload.h>
|
||||
|
||||
|
||||
ENUM_BEGIN(payload_type_names, NO_PAYLOAD, NO_PAYLOAD,
|
||||
"NO_PAYLOAD");
|
||||
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION,
|
||||
GENERIC_SECURE_PASSWORD_METHOD, NO_PAYLOAD,
|
||||
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
|
||||
"SECURITY_ASSOCIATION_V1",
|
||||
"PROPOSAL_V1",
|
||||
"TRANSFORM_V1",
|
||||
"KEY_EXCHANGE_V1",
|
||||
"ID_V1",
|
||||
"CERTIFICATE_V1",
|
||||
"CERTIFICATE_REQUEST_V1",
|
||||
"HASH_V1",
|
||||
"SIGNATURE_V1",
|
||||
"NONCE_V1",
|
||||
"NOTIFY_V1",
|
||||
"DELETE_V1",
|
||||
"VENDOR_ID_V1",
|
||||
"CONFIGURATION_V1");
|
||||
ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
|
||||
"NAT_D_V1",
|
||||
"NAT_OA_V1");
|
||||
ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
|
||||
"SECURITY_ASSOCIATION",
|
||||
"KEY_EXCHANGE",
|
||||
"ID_INITIATOR",
|
||||
@@ -61,30 +79,56 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION,
|
||||
#ifdef ME
|
||||
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
|
||||
"ID_PEER");
|
||||
ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
|
||||
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, ID_PEER,
|
||||
"HEADER",
|
||||
"PROPOSAL_SUBSTRUCTURE",
|
||||
"PROPOSAL_SUBSTRUCTURE_V1",
|
||||
"TRANSFORM_SUBSTRUCTURE",
|
||||
"TRANSFORM_SUBSTRUCTURE_V1",
|
||||
"TRANSFORM_ATTRIBUTE",
|
||||
"TRANSFORM_ATTRIBUTE_V1",
|
||||
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
|
||||
"CONFIGURATION_ATTRIBUTE");
|
||||
"CONFIGURATION_ATTRIBUTE",
|
||||
"CONFIGURATION_ATTRIBUTE_V1",
|
||||
"ENCRYPTED_V1");
|
||||
#else
|
||||
ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE,
|
||||
GENERIC_SECURE_PASSWORD_METHOD,
|
||||
ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
|
||||
"HEADER",
|
||||
"PROPOSAL_SUBSTRUCTURE",
|
||||
"PROPOSAL_SUBSTRUCTURE_V1",
|
||||
"TRANSFORM_SUBSTRUCTURE",
|
||||
"TRANSFORM_SUBSTRUCTURE_V1",
|
||||
"TRANSFORM_ATTRIBUTE",
|
||||
"TRANSFORM_ATTRIBUTE_V1",
|
||||
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
|
||||
"CONFIGURATION_ATTRIBUTE");
|
||||
"CONFIGURATION_ATTRIBUTE",
|
||||
"CONFIGURATION_ATTRIBUTE_V1",
|
||||
"ENCRYPTED_V1");
|
||||
#endif /* ME */
|
||||
ENUM_END(payload_type_names, CONFIGURATION_ATTRIBUTE);
|
||||
ENUM_END(payload_type_names, ENCRYPTED_V1);
|
||||
|
||||
/* short forms of payload names */
|
||||
ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
|
||||
"--");
|
||||
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION,
|
||||
GENERIC_SECURE_PASSWORD_METHOD, NO_PAYLOAD,
|
||||
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
|
||||
"SA",
|
||||
"PROP",
|
||||
"TRANS",
|
||||
"KE",
|
||||
"ID",
|
||||
"CERT",
|
||||
"CERTREQ",
|
||||
"HASH",
|
||||
"SIG",
|
||||
"No",
|
||||
"N",
|
||||
"D",
|
||||
"V",
|
||||
"CP");
|
||||
ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
|
||||
"NAT-D",
|
||||
"NAT-OA");
|
||||
ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
|
||||
"SA",
|
||||
"KE",
|
||||
"IDi",
|
||||
@@ -106,24 +150,33 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION,
|
||||
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER,
|
||||
GENERIC_SECURE_PASSWORD_METHOD,
|
||||
"IDp");
|
||||
ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER,
|
||||
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, ID_PEER,
|
||||
"HDR",
|
||||
"PROP",
|
||||
"PROP",
|
||||
"TRANS",
|
||||
"TRANS",
|
||||
"TRANSATTR",
|
||||
"TRANSATTR",
|
||||
"TSSUB",
|
||||
"CPATTR");
|
||||
"CATTR",
|
||||
"CATTR",
|
||||
"E");
|
||||
#else
|
||||
ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE,
|
||||
GENERIC_SECURE_PASSWORD_METHOD,
|
||||
ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, GENERIC_SECURE_PASSWORD_METHOD,
|
||||
"HDR",
|
||||
"PROP",
|
||||
"PROP",
|
||||
"TRANS",
|
||||
"TRANS",
|
||||
"TRANSATTR",
|
||||
"TRANSATTR",
|
||||
"TSSUB",
|
||||
"CPATTR");
|
||||
"CATTR",
|
||||
"CATTR",
|
||||
"E");
|
||||
#endif /* ME */
|
||||
ENUM_END(payload_type_short_names, CONFIGURATION_ATTRIBUTE);
|
||||
ENUM_END(payload_type_short_names, ENCRYPTED_V1);
|
||||
|
||||
/*
|
||||
* see header
|
||||
@@ -135,29 +188,36 @@ payload_t *payload_create(payload_type_t type)
|
||||
case HEADER:
|
||||
return (payload_t*)ike_header_create();
|
||||
case SECURITY_ASSOCIATION:
|
||||
return (payload_t*)sa_payload_create();
|
||||
case SECURITY_ASSOCIATION_V1:
|
||||
return (payload_t*)sa_payload_create(type);
|
||||
case PROPOSAL_SUBSTRUCTURE:
|
||||
return (payload_t*)proposal_substructure_create();
|
||||
case PROPOSAL_SUBSTRUCTURE_V1:
|
||||
return (payload_t*)proposal_substructure_create(type);
|
||||
case TRANSFORM_SUBSTRUCTURE:
|
||||
return (payload_t*)transform_substructure_create();
|
||||
case TRANSFORM_SUBSTRUCTURE_V1:
|
||||
return (payload_t*)transform_substructure_create(type);
|
||||
case TRANSFORM_ATTRIBUTE:
|
||||
return (payload_t*)transform_attribute_create();
|
||||
case TRANSFORM_ATTRIBUTE_V1:
|
||||
return (payload_t*)transform_attribute_create(type);
|
||||
case NONCE:
|
||||
return (payload_t*)nonce_payload_create();
|
||||
case NONCE_V1:
|
||||
return (payload_t*)nonce_payload_create(type);
|
||||
case ID_INITIATOR:
|
||||
return (payload_t*)id_payload_create(ID_INITIATOR);
|
||||
case ID_RESPONDER:
|
||||
return (payload_t*)id_payload_create(ID_RESPONDER);
|
||||
case ID_V1:
|
||||
case NAT_OA_V1:
|
||||
#ifdef ME
|
||||
case ID_PEER:
|
||||
return (payload_t*)id_payload_create(ID_PEER);
|
||||
#endif /* ME */
|
||||
return (payload_t*)id_payload_create(type);
|
||||
case AUTHENTICATION:
|
||||
return (payload_t*)auth_payload_create();
|
||||
case CERTIFICATE:
|
||||
return (payload_t*)cert_payload_create();
|
||||
case CERTIFICATE_V1:
|
||||
return (payload_t*)cert_payload_create(type);
|
||||
case CERTIFICATE_REQUEST:
|
||||
return (payload_t*)certreq_payload_create();
|
||||
case CERTIFICATE_REQUEST_V1:
|
||||
return (payload_t*)certreq_payload_create(type);
|
||||
case TRAFFIC_SELECTOR_SUBSTRUCTURE:
|
||||
return (payload_t*)traffic_selector_substructure_create();
|
||||
case TRAFFIC_SELECTOR_INITIATOR:
|
||||
@@ -165,21 +225,32 @@ payload_t *payload_create(payload_type_t type)
|
||||
case TRAFFIC_SELECTOR_RESPONDER:
|
||||
return (payload_t*)ts_payload_create(FALSE);
|
||||
case KEY_EXCHANGE:
|
||||
return (payload_t*)ke_payload_create();
|
||||
case KEY_EXCHANGE_V1:
|
||||
return (payload_t*)ke_payload_create(type);
|
||||
case NOTIFY:
|
||||
return (payload_t*)notify_payload_create();
|
||||
case NOTIFY_V1:
|
||||
return (payload_t*)notify_payload_create(type);
|
||||
case DELETE:
|
||||
return (payload_t*)delete_payload_create(0);
|
||||
case DELETE_V1:
|
||||
return (payload_t*)delete_payload_create(type, 0);
|
||||
case VENDOR_ID:
|
||||
return (payload_t*)vendor_id_payload_create();
|
||||
case VENDOR_ID_V1:
|
||||
return (payload_t*)vendor_id_payload_create(type);
|
||||
case HASH_V1:
|
||||
case SIGNATURE_V1:
|
||||
case NAT_D_V1:
|
||||
return (payload_t*)hash_payload_create(type);
|
||||
case CONFIGURATION:
|
||||
return (payload_t*)cp_payload_create();
|
||||
case CONFIGURATION_V1:
|
||||
return (payload_t*)cp_payload_create(type);
|
||||
case CONFIGURATION_ATTRIBUTE:
|
||||
return (payload_t*)configuration_attribute_create();
|
||||
case CONFIGURATION_ATTRIBUTE_V1:
|
||||
return (payload_t*)configuration_attribute_create(type);
|
||||
case EXTENSIBLE_AUTHENTICATION:
|
||||
return (payload_t*)eap_payload_create();
|
||||
case ENCRYPTED:
|
||||
return (payload_t*)encryption_payload_create();
|
||||
case ENCRYPTED_V1:
|
||||
return (payload_t*)encryption_payload_create(type);
|
||||
default:
|
||||
return (payload_t*)unknown_payload_create(type);
|
||||
}
|
||||
@@ -190,8 +261,19 @@ payload_t *payload_create(payload_type_t type)
|
||||
*/
|
||||
bool payload_is_known(payload_type_t type)
|
||||
{
|
||||
if (type == HEADER ||
|
||||
(type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION))
|
||||
if (type == HEADER)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (type >= SECURITY_ASSOCIATION_V1 && type <= CONFIGURATION_V1)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (type >= NAT_D_V1 && type <= NAT_OA_V1)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -210,10 +292,9 @@ bool payload_is_known(payload_type_t type)
|
||||
void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip)
|
||||
{
|
||||
encoding_rule_t *rule;
|
||||
size_t count;
|
||||
int i;
|
||||
int i, count;
|
||||
|
||||
payload->get_encoding_rules(payload, &rule, &count);
|
||||
count = payload->get_encoding_rules(payload, &rule);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (rule[i].type == type && skip-- == 0)
|
||||
|
||||
@@ -29,20 +29,104 @@ typedef struct payload_t payload_t;
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/encodings.h>
|
||||
|
||||
/**
|
||||
* Domain of interpretation used by IPsec/IKEv1
|
||||
*/
|
||||
#define IKEV1_DOI_IPSEC 1
|
||||
|
||||
/**
|
||||
* Payload-Types of a IKEv2-Message.
|
||||
* Payload-Types of an IKE message.
|
||||
*
|
||||
* Header and substructures are also defined as
|
||||
* payload types with values from PRIVATE USE space.
|
||||
*/
|
||||
enum payload_type_t{
|
||||
enum payload_type_t {
|
||||
|
||||
/**
|
||||
* End of payload list in next_payload
|
||||
*/
|
||||
NO_PAYLOAD = 0,
|
||||
|
||||
/**
|
||||
* The security association (SA) payload containing proposals.
|
||||
*/
|
||||
SECURITY_ASSOCIATION_V1 = 1,
|
||||
|
||||
/**
|
||||
* The proposal payload, containing transforms.
|
||||
*/
|
||||
PROPOSAL_V1 = 2,
|
||||
|
||||
/**
|
||||
* The transform payload.
|
||||
*/
|
||||
TRANSFORM_V1 = 3,
|
||||
|
||||
/**
|
||||
* The key exchange (KE) payload containing diffie-hellman values.
|
||||
*/
|
||||
KEY_EXCHANGE_V1 = 4,
|
||||
|
||||
/**
|
||||
* ID payload.
|
||||
*/
|
||||
ID_V1 = 5,
|
||||
|
||||
/**
|
||||
* Certificate payload with certificates (CERT).
|
||||
*/
|
||||
CERTIFICATE_V1 = 6,
|
||||
|
||||
/**
|
||||
* Certificate request payload.
|
||||
*/
|
||||
CERTIFICATE_REQUEST_V1 = 7,
|
||||
|
||||
/**
|
||||
* Hash payload.
|
||||
*/
|
||||
HASH_V1 = 8,
|
||||
|
||||
/**
|
||||
* Signature payload
|
||||
*/
|
||||
SIGNATURE_V1 = 9,
|
||||
|
||||
/**
|
||||
* Nonce payload.
|
||||
*/
|
||||
NONCE_V1 = 10,
|
||||
|
||||
/**
|
||||
* Notification payload.
|
||||
*/
|
||||
NOTIFY_V1 = 11,
|
||||
|
||||
/**
|
||||
* Delete payload.
|
||||
*/
|
||||
DELETE_V1 = 12,
|
||||
|
||||
/**
|
||||
* Vendor id payload.
|
||||
*/
|
||||
VENDOR_ID_V1 = 13,
|
||||
|
||||
/**
|
||||
* Attribute payload (ISAKMP Mode Config, aka configuration payload.
|
||||
*/
|
||||
CONFIGURATION_V1 = 14,
|
||||
|
||||
/**
|
||||
* NAT discovery payload (NAT-D).
|
||||
*/
|
||||
NAT_D_V1 = 20,
|
||||
|
||||
/**
|
||||
* NAT original address payload (NAT-OA)
|
||||
*/
|
||||
NAT_OA_V1 = 21,
|
||||
|
||||
/**
|
||||
* The security association (SA) payload containing proposals.
|
||||
*/
|
||||
@@ -139,50 +223,60 @@ enum payload_type_t{
|
||||
/**
|
||||
* Header has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle IKEv2-Header like a payload.
|
||||
* This type and all the following are never sent over wire and are
|
||||
* used internally only.
|
||||
*/
|
||||
HEADER = 256,
|
||||
|
||||
/**
|
||||
* PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle a proposal substructure like a payload.
|
||||
* PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
|
||||
*/
|
||||
PROPOSAL_SUBSTRUCTURE = 257,
|
||||
PROPOSAL_SUBSTRUCTURE,
|
||||
|
||||
/**
|
||||
* TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle a transform substructure like a payload.
|
||||
* PROPOSAL_SUBSTRUCTURE_V1, IKEv1 proposals in a SA payload.
|
||||
*/
|
||||
TRANSFORM_SUBSTRUCTURE = 258,
|
||||
PROPOSAL_SUBSTRUCTURE_V1,
|
||||
|
||||
/**
|
||||
* TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle a transform attribute like a payload.
|
||||
* TRANSFORM_SUBSTRUCTURE, IKEv2 transforms in a proposal substructure.
|
||||
*/
|
||||
TRANSFORM_ATTRIBUTE = 259,
|
||||
TRANSFORM_SUBSTRUCTURE,
|
||||
|
||||
/**
|
||||
* TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle a transform selector like a payload.
|
||||
* TRANSFORM_SUBSTRUCTURE_V1, IKEv1 transforms in a proposal substructure.
|
||||
*/
|
||||
TRAFFIC_SELECTOR_SUBSTRUCTURE = 260,
|
||||
TRANSFORM_SUBSTRUCTURE_V1,
|
||||
|
||||
/**
|
||||
* CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space.
|
||||
*
|
||||
* This payload type is not sent over wire and just
|
||||
* used internally to handle a transform attribute like a payload.
|
||||
* TRANSFORM_ATTRIBUTE, IKEv2 attribute in a transform.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTE = 261,
|
||||
TRANSFORM_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* TRANSFORM_ATTRIBUTE_V1, IKEv1 attribute in a transform.
|
||||
*/
|
||||
TRANSFORM_ATTRIBUTE_V1,
|
||||
|
||||
/**
|
||||
* TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic selector in a TS payload.
|
||||
*/
|
||||
TRAFFIC_SELECTOR_SUBSTRUCTURE,
|
||||
|
||||
/**
|
||||
* CONFIGURATION_ATTRIBUTE, IKEv2 attribute in a configuration payload.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* CONFIGURATION_ATTRIBUTE_V1, IKEv1 attribute in a configuration payload.
|
||||
*/
|
||||
CONFIGURATION_ATTRIBUTE_V1,
|
||||
|
||||
/**
|
||||
* This is not really a payload, but rather the complete IKEv1 message.
|
||||
*/
|
||||
ENCRYPTED_V1,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -207,43 +301,50 @@ struct payload_t {
|
||||
/**
|
||||
* Get encoding rules for this payload.
|
||||
*
|
||||
* @param rules location to store pointer of first rule
|
||||
* @param rule_count location to store number of rules
|
||||
* @param rules location to store pointer to rules
|
||||
* @return number of rules
|
||||
*/
|
||||
void (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules, size_t *rule_count);
|
||||
int (*get_encoding_rules) (payload_t *this, encoding_rule_t **rules);
|
||||
|
||||
/**
|
||||
* Get non-variable header length for a variable length payload.
|
||||
*
|
||||
* @return fixed length of the payload
|
||||
*/
|
||||
int (*get_header_length)(payload_t *this);
|
||||
|
||||
/**
|
||||
* Get type of payload.
|
||||
*
|
||||
* @return type of this payload
|
||||
* @return type of this payload
|
||||
*/
|
||||
payload_type_t (*get_type) (payload_t *this);
|
||||
|
||||
/**
|
||||
* Get type of next payload or NO_PAYLOAD (0) if this is the last one.
|
||||
*
|
||||
* @return type of next payload
|
||||
* @return type of next payload
|
||||
*/
|
||||
payload_type_t (*get_next_type) (payload_t *this);
|
||||
|
||||
/**
|
||||
* Set type of next payload.
|
||||
*
|
||||
* @param type type of next payload
|
||||
* @param type type of next payload
|
||||
*/
|
||||
void (*set_next_type) (payload_t *this,payload_type_t type);
|
||||
|
||||
/**
|
||||
* Get length of payload.
|
||||
*
|
||||
* @return length of this payload
|
||||
* @return length of this payload
|
||||
*/
|
||||
size_t (*get_length) (payload_t *this);
|
||||
|
||||
/**
|
||||
* Verifies payload structure and makes consistence check.
|
||||
*
|
||||
* @return SUCCESS, FAILED if consistence not given
|
||||
* @return SUCCESS, FAILED if consistence not given
|
||||
*/
|
||||
status_t (*verify) (payload_t *this);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,17 +29,11 @@ typedef struct proposal_substructure_t proposal_substructure_t;
|
||||
#include <encoding/payloads/transform_substructure.h>
|
||||
#include <config/proposal.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
#include <kernel/kernel_ipsec.h>
|
||||
#include <sa/authenticator.h>
|
||||
|
||||
/**
|
||||
* Length of the proposal substructure header (without spi).
|
||||
*/
|
||||
#define PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2-PROPOSAL SUBSTRUCTURE.
|
||||
*
|
||||
* The PROPOSAL SUBSTRUCTURE format is described in RFC section 3.3.1.
|
||||
* Class representing an IKEv1/IKEv2 proposal substructure.
|
||||
*/
|
||||
struct proposal_substructure_t {
|
||||
|
||||
@@ -104,11 +98,11 @@ struct proposal_substructure_t {
|
||||
void (*set_spi) (proposal_substructure_t *this, chunk_t spi);
|
||||
|
||||
/**
|
||||
* Get a proposal_t from the propsal_substructure_t.
|
||||
* Get proposals contained in a propsal_substructure_t.
|
||||
*
|
||||
* @return proposal_t
|
||||
* @param list list to add created proposals to
|
||||
*/
|
||||
proposal_t * (*get_proposal) (proposal_substructure_t *this);
|
||||
void (*get_proposals) (proposal_substructure_t *this, linked_list_t *list);
|
||||
|
||||
/**
|
||||
* Create an enumerator over transform substructures.
|
||||
@@ -117,6 +111,35 @@ struct proposal_substructure_t {
|
||||
*/
|
||||
enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get the (shortest) lifetime of a proposal (IKEv1 only).
|
||||
*
|
||||
* @return lifetime, in seconds
|
||||
*/
|
||||
u_int32_t (*get_lifetime)(proposal_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get the (shortest) life duration of a proposal (IKEv1 only).
|
||||
*
|
||||
* @return life duration, in bytes
|
||||
*/
|
||||
u_int64_t (*get_lifebytes)(proposal_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get the first authentication method from the proposal (IKEv1 only).
|
||||
*
|
||||
* @return auth method, or AUTH_NONE
|
||||
*/
|
||||
auth_method_t (*get_auth_method)(proposal_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get the (first) encapsulation mode from a proposal (IKEv1 only).
|
||||
*
|
||||
* @param udp set to TRUE if UDP encapsulation used
|
||||
* @return ipsec encapsulation mode
|
||||
*/
|
||||
ipsec_mode_t (*get_encap_mode)(proposal_substructure_t *this, bool *udp);
|
||||
|
||||
/**
|
||||
* Destroys an proposal_substructure_t object.
|
||||
*/
|
||||
@@ -126,17 +149,49 @@ struct proposal_substructure_t {
|
||||
/**
|
||||
* Creates an empty proposal_substructure_t object
|
||||
*
|
||||
* @return proposal_substructure_t object
|
||||
* @param type PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
|
||||
* @return proposal_substructure_t object
|
||||
*/
|
||||
proposal_substructure_t *proposal_substructure_create(void);
|
||||
proposal_substructure_t *proposal_substructure_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a proposal_substructure_t from a proposal_t.
|
||||
* Creates an IKEv2 proposal_substructure_t from a proposal_t.
|
||||
*
|
||||
* @param proposal proposal to build a substruct out of it
|
||||
* @return proposal_substructure_t object
|
||||
* @param proposal proposal to build a substruct out of it
|
||||
* @return proposal_substructure_t PROPOSAL_SUBSTRUCTURE
|
||||
*/
|
||||
proposal_substructure_t *proposal_substructure_create_from_proposal(
|
||||
proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
|
||||
proposal_t *proposal);
|
||||
/**
|
||||
* Creates an IKEv1 proposal_substructure_t from a proposal_t.
|
||||
*
|
||||
* @param proposal proposal to build a substruct out of it
|
||||
* @param lifetime lifetime in seconds
|
||||
* @param lifebytes lifebytes, in bytes
|
||||
* @param auth authentication method to use, or AUTH_NONE
|
||||
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
|
||||
* @param udp TRUE to use UDP encapsulation
|
||||
*
|
||||
*
|
||||
* @return proposal_substructure_t object PROPOSAL_SUBSTRUCTURE_V1
|
||||
*/
|
||||
proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
|
||||
proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp);
|
||||
|
||||
/**
|
||||
* Creates an IKEv1 proposal_substructure_t from a list of proposal_t.
|
||||
*
|
||||
* @param proposals list of proposal_t to encode in a substructure
|
||||
* @param lifetime lifetime in seconds
|
||||
* @param lifebytes lifebytes, in bytes
|
||||
* @param auth authentication method to use, or AUTH_NONE
|
||||
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
|
||||
* @param udp TRUE to use UDP encapsulation
|
||||
* @return IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
|
||||
*/
|
||||
proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
|
||||
linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp);
|
||||
|
||||
#endif /** PROPOSAL_SUBSTRUCTURE_H_ @}*/
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <utils/linked_list.h>
|
||||
#include <daemon.h>
|
||||
|
||||
/* IKEv1 situation */
|
||||
#define SIT_IDENTITY_ONLY 1
|
||||
|
||||
typedef struct private_sa_payload_t private_sa_payload_t;
|
||||
|
||||
@@ -48,7 +50,7 @@ struct private_sa_payload_t {
|
||||
/**
|
||||
* Reserved bits
|
||||
*/
|
||||
bool reserved[7];
|
||||
bool reserved[8];
|
||||
|
||||
/**
|
||||
* Length of this payload.
|
||||
@@ -58,21 +60,75 @@ struct private_sa_payload_t {
|
||||
/**
|
||||
* Proposals in this payload are stored in a linked_list_t.
|
||||
*/
|
||||
linked_list_t * proposals;
|
||||
linked_list_t *proposals;
|
||||
|
||||
/**
|
||||
* Type of this payload, V1 or V2
|
||||
*/
|
||||
payload_type_t type;
|
||||
|
||||
/**
|
||||
* IKEv1 DOI
|
||||
*/
|
||||
u_int32_t doi;
|
||||
|
||||
/**
|
||||
* IKEv1 situation
|
||||
*/
|
||||
u_int32_t situation;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 rules for IKEv1 SA payload
|
||||
*/
|
||||
encoding_rule_t sa_payload_encodings[] = {
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_sa_payload_t, next_payload) },
|
||||
/* 8 reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[3]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[4]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[5]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[7]) },
|
||||
/* Length of the whole SA payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) },
|
||||
/* DOI*/
|
||||
{ U_INT_32, offsetof(private_sa_payload_t, doi) },
|
||||
/* Situation*/
|
||||
{ U_INT_32, offsetof(private_sa_payload_t, situation) },
|
||||
/* Proposals are stored in a proposal substructure list */
|
||||
{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1,
|
||||
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 ! RESERVED ! Payload Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! DOI !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! Situation !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ <Proposals> ~
|
||||
! !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoding rules for IKEv2 SA payload
|
||||
*/
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 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 */
|
||||
/* 7 Bit reserved bits */
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) },
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) },
|
||||
@@ -82,9 +138,9 @@ encoding_rule_t sa_payload_encodings[] = {
|
||||
{ RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) },
|
||||
/* 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) },
|
||||
/* Proposals are stored in a proposal substructure list */
|
||||
{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE,
|
||||
offsetof(private_sa_payload_t, proposals) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -102,11 +158,16 @@ encoding_rule_t sa_payload_encodings[] = {
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
int expected_number = 1, current_number;
|
||||
int expected_number = 0, current_number;
|
||||
status_t status = SUCCESS;
|
||||
enumerator_t *enumerator;
|
||||
proposal_substructure_t *substruct;
|
||||
|
||||
if (this->type == SECURITY_ASSOCIATION)
|
||||
{
|
||||
expected_number = 1;
|
||||
}
|
||||
|
||||
/* check proposal numbering */
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
while (enumerator->enumerate(enumerator, (void**)&substruct))
|
||||
@@ -131,17 +192,32 @@ METHOD(payload_t, verify, status_t,
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_sa_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = sa_payload_encodings;
|
||||
*rule_count = countof(sa_payload_encodings);
|
||||
if (this->type == SECURITY_ASSOCIATION_V1)
|
||||
{
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
if (this->type == SECURITY_ASSOCIATION_V1)
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
return SECURITY_ASSOCIATION;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -163,16 +239,15 @@ static void compute_length(private_sa_payload_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
payload_t *current;
|
||||
size_t length = SA_PAYLOAD_HEADER_LENGTH;
|
||||
|
||||
this->payload_length = get_header_length(this);
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
while (enumerator->enumerate(enumerator, (void **)¤t))
|
||||
{
|
||||
length += current->get_length(current);
|
||||
this->payload_length += current->get_length(current);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->payload_length = length;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_length, size_t,
|
||||
@@ -181,14 +256,16 @@ METHOD(payload_t, get_length, size_t,
|
||||
return this->payload_length;
|
||||
}
|
||||
|
||||
METHOD(sa_payload_t, add_proposal, void,
|
||||
private_sa_payload_t *this, proposal_t *proposal)
|
||||
/**
|
||||
* Create a transform substructure from a proposal, add to payload
|
||||
*/
|
||||
static void add_proposal_v2(private_sa_payload_t *this, proposal_t *proposal)
|
||||
{
|
||||
proposal_substructure_t *substruct, *last;
|
||||
u_int count;
|
||||
|
||||
substruct = proposal_substructure_create_from_proposal_v2(proposal);
|
||||
count = this->proposals->get_count(this->proposals);
|
||||
substruct = proposal_substructure_create_from_proposal(proposal);
|
||||
if (count > 0)
|
||||
{
|
||||
this->proposals->get_last(this->proposals, (void**)&last);
|
||||
@@ -215,8 +292,13 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
|
||||
int ignore_struct_number = 0;
|
||||
enumerator_t *enumerator;
|
||||
proposal_substructure_t *substruct;
|
||||
linked_list_t *list;
|
||||
proposal_t *proposal;
|
||||
linked_list_t *list;
|
||||
|
||||
if (this->type == SECURITY_ASSOCIATION_V1)
|
||||
{ /* IKEv1 proposals start with 0 */
|
||||
struct_number = ignore_struct_number = -1;
|
||||
}
|
||||
|
||||
list = linked_list_create();
|
||||
/* we do not support proposals split up to two proposal substructures, as
|
||||
@@ -233,18 +315,16 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
|
||||
if (ignore_struct_number < struct_number)
|
||||
{
|
||||
/* remove an already added, if first of series */
|
||||
list->remove_last(list, (void**)&proposal);
|
||||
proposal->destroy(proposal);
|
||||
if (list->remove_last(list, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
ignore_struct_number = struct_number;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
struct_number++;
|
||||
proposal = substruct->get_proposal(substruct);
|
||||
if (proposal)
|
||||
{
|
||||
list->insert_last(list, proposal);
|
||||
}
|
||||
substruct->get_proposals(substruct, list);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return list;
|
||||
@@ -256,18 +336,86 @@ METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
|
||||
return this->proposals->create_enumerator(this->proposals);
|
||||
}
|
||||
|
||||
METHOD(sa_payload_t, get_lifetime, u_int32_t,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
enumerator_t *enumerator;
|
||||
u_int32_t lifetime = 0;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
if (enumerator->enumerate(enumerator, &substruct))
|
||||
{
|
||||
lifetime = substruct->get_lifetime(substruct);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
METHOD(sa_payload_t, get_lifebytes, u_int64_t,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
enumerator_t *enumerator;
|
||||
u_int64_t lifebytes = 0;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
if (enumerator->enumerate(enumerator, &substruct))
|
||||
{
|
||||
lifebytes = substruct->get_lifebytes(substruct);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return lifebytes;
|
||||
}
|
||||
|
||||
METHOD(sa_payload_t, get_auth_method, auth_method_t,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
enumerator_t *enumerator;
|
||||
auth_method_t method = AUTH_NONE;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
if (enumerator->enumerate(enumerator, &substruct))
|
||||
{
|
||||
method = substruct->get_auth_method(substruct);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
|
||||
private_sa_payload_t *this, bool *udp)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
enumerator_t *enumerator;
|
||||
ipsec_mode_t mode = MODE_NONE;
|
||||
|
||||
enumerator = this->proposals->create_enumerator(this->proposals);
|
||||
if (enumerator->enumerate(enumerator, &substruct))
|
||||
{
|
||||
mode = substruct->get_encap_mode(substruct, udp);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, sa_payload_t, destroy, void,
|
||||
private_sa_payload_t *this)
|
||||
{
|
||||
this->proposals->destroy_offset(this->proposals,
|
||||
offsetof(proposal_substructure_t, destroy));
|
||||
offsetof(payload_t, destroy));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sa_payload_t *sa_payload_create()
|
||||
sa_payload_t *sa_payload_create(payload_type_t type)
|
||||
{
|
||||
private_sa_payload_t *this;
|
||||
|
||||
@@ -276,38 +424,48 @@ sa_payload_t *sa_payload_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
.get_type = _get_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add_proposal = _add_proposal,
|
||||
.get_proposals = _get_proposals,
|
||||
.create_substructure_enumerator = _create_substructure_enumerator,
|
||||
.get_lifetime = _get_lifetime,
|
||||
.get_lifebytes = _get_lifebytes,
|
||||
.get_auth_method = _get_auth_method,
|
||||
.get_encap_mode = _get_encap_mode,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = SA_PAYLOAD_HEADER_LENGTH,
|
||||
.proposals = linked_list_create(),
|
||||
.type = type,
|
||||
/* for IKEv1 only */
|
||||
.doi = IKEV1_DOI_IPSEC,
|
||||
.situation = SIT_IDENTITY_ONLY,
|
||||
);
|
||||
|
||||
compute_length(this);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
|
||||
sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
|
||||
{
|
||||
private_sa_payload_t *this;
|
||||
enumerator_t *enumerator;
|
||||
proposal_t *proposal;
|
||||
|
||||
this = (private_sa_payload_t*)sa_payload_create();
|
||||
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
|
||||
enumerator = proposals->create_enumerator(proposals);
|
||||
while (enumerator->enumerate(enumerator, &proposal))
|
||||
{
|
||||
add_proposal(this, proposal);
|
||||
add_proposal_v2(this, proposal);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
@@ -317,12 +475,57 @@ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal)
|
||||
sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
|
||||
{
|
||||
private_sa_payload_t *this;
|
||||
|
||||
this = (private_sa_payload_t*)sa_payload_create();
|
||||
add_proposal(this, proposal);
|
||||
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
|
||||
add_proposal_v2(this, proposal);
|
||||
|
||||
return &this->public;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
|
||||
u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
private_sa_payload_t *this;
|
||||
|
||||
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
|
||||
|
||||
/* IKEv1 encodes multiple proposals in a single substructure
|
||||
* TODO-IKEv1: Encode ESP+AH proposals in two different substructs */
|
||||
substruct = proposal_substructure_create_from_proposals_v1(proposals,
|
||||
lifetime, lifebytes, auth, mode, udp);
|
||||
substruct->set_is_last_proposal(substruct, TRUE);
|
||||
this->proposals->insert_last(this->proposals, substruct);
|
||||
compute_length(this);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
|
||||
u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp)
|
||||
{
|
||||
proposal_substructure_t *substruct;
|
||||
private_sa_payload_t *this;
|
||||
|
||||
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
|
||||
|
||||
substruct = proposal_substructure_create_from_proposal_v1(proposal,
|
||||
lifetime, lifebytes, auth, mode, udp);
|
||||
substruct->set_is_last_proposal(substruct, TRUE);
|
||||
this->proposals->insert_last(this->proposals, substruct);
|
||||
compute_length(this);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -28,14 +28,11 @@ typedef struct sa_payload_t sa_payload_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <encoding/payloads/proposal_substructure.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <kernel/kernel_ipsec.h>
|
||||
#include <sa/authenticator.h>
|
||||
|
||||
/**
|
||||
* SA_PAYLOAD length in bytes without any proposal substructure.
|
||||
*/
|
||||
#define SA_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2-SA Payload.
|
||||
* Class representing an IKEv1 or IKEv2 SA Payload.
|
||||
*
|
||||
* The SA Payload format is described in RFC section 3.3.
|
||||
*/
|
||||
@@ -54,11 +51,33 @@ struct sa_payload_t {
|
||||
linked_list_t *(*get_proposals) (sa_payload_t *this);
|
||||
|
||||
/**
|
||||
* Add a child proposal (AH/ESP) to the payload.
|
||||
* Get the (shortest) lifetime of a proposal (IKEv1 only).
|
||||
*
|
||||
* @param proposal child proposal to add to the payload
|
||||
* @return lifetime, in seconds
|
||||
*/
|
||||
void (*add_proposal) (sa_payload_t *this, proposal_t *proposal);
|
||||
u_int32_t (*get_lifetime)(sa_payload_t *this);
|
||||
|
||||
/**
|
||||
* Get the (shortest) life duration of a proposal (IKEv1 only).
|
||||
*
|
||||
* @return life duration, in bytes
|
||||
*/
|
||||
u_int64_t (*get_lifebytes)(sa_payload_t *this);
|
||||
|
||||
/**
|
||||
* Get the first authentication method from the proposal (IKEv1 only).
|
||||
*
|
||||
* @return auth method, or AUTH_NONE
|
||||
*/
|
||||
auth_method_t (*get_auth_method)(sa_payload_t *this);
|
||||
|
||||
/**
|
||||
* Get the (first) encapsulation mode from a proposal (IKEv1 only).
|
||||
*
|
||||
* @param udp set to TRUE if UDP encapsulation used
|
||||
* @return ipsec encapsulation mode
|
||||
*/
|
||||
ipsec_mode_t (*get_encap_mode)(sa_payload_t *this, bool *udp);
|
||||
|
||||
/**
|
||||
* Create an enumerator over all proposal substructures.
|
||||
@@ -76,27 +95,55 @@ struct sa_payload_t {
|
||||
/**
|
||||
* Creates an empty sa_payload_t object
|
||||
*
|
||||
* @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
|
||||
* @return created sa_payload_t object
|
||||
*/
|
||||
sa_payload_t *sa_payload_create(void);
|
||||
sa_payload_t *sa_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a sa_payload_t object from a list of proposals.
|
||||
* Creates an IKEv2 sa_payload_t object from a list of proposals.
|
||||
*
|
||||
* @param proposals list of proposals to build the payload from
|
||||
* @return sa_payload_t object
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals);
|
||||
sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals);
|
||||
|
||||
/**
|
||||
* Creates a sa_payload_t object from a single proposal.
|
||||
*
|
||||
* This is only for convenience. Use sa_payload_create_from_proposal_list
|
||||
* if you want to add more than one proposal.
|
||||
* Creates an IKEv2 sa_payload_t object from a single proposal.
|
||||
*
|
||||
* @param proposal proposal from which the payload should be built.
|
||||
* @return sa_payload_t object
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal);
|
||||
sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal);
|
||||
|
||||
/**
|
||||
* Creates an IKEv1 sa_payload_t object from a list of proposals.
|
||||
*
|
||||
* @param proposals list of proposals to build the payload from
|
||||
* @param lifetime lifetime in seconds
|
||||
* @param lifebytes lifebytes, in bytes
|
||||
* @param auth authentication method to use, or AUTH_NONE
|
||||
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
|
||||
* @param udp TRUE to use UDP encapsulation
|
||||
* @return sa_payload_t object
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
|
||||
u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp);
|
||||
|
||||
/**
|
||||
* Creates an IKEv1 sa_payload_t object from a single proposal.
|
||||
*
|
||||
* @param proposal proposal from which the payload should be built.
|
||||
* @param lifetime lifetime in seconds
|
||||
* @param lifebytes lifebytes, in bytes
|
||||
* @param auth authentication method to use, or AUTH_NONE
|
||||
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
|
||||
* @param udp TRUE to use UDP encapsulation
|
||||
* @return sa_payload_t object
|
||||
*/
|
||||
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
|
||||
u_int32_t lifetime, u_int64_t lifebytes,
|
||||
auth_method_t auth, ipsec_mode_t mode, bool udp);
|
||||
|
||||
#endif /** SA_PAYLOAD_H_ @}*/
|
||||
|
||||
@@ -74,7 +74,7 @@ struct private_traffic_selector_substructure_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_traffic_selector_substructure_t.
|
||||
*/
|
||||
encoding_rule_t traffic_selector_substructure_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next ts type*/
|
||||
{ TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
|
||||
/* 1 Byte IP protocol id*/
|
||||
@@ -148,12 +148,17 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_traffic_selector_substructure_t *this, encoding_rule_t **rules,
|
||||
size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_traffic_selector_substructure_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = traffic_selector_substructure_encodings;
|
||||
*rule_count = countof(traffic_selector_substructure_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_traffic_selector_substructure_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
@@ -208,6 +213,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -217,7 +223,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
|
||||
.get_traffic_selector = _get_traffic_selector,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
/* must be set to be valid */
|
||||
.ts_type = TS_IPV4_ADDR_RANGE,
|
||||
);
|
||||
@@ -239,7 +245,7 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
|
||||
this->end_port = ts->get_to_port(ts);
|
||||
this->starting_address = chunk_clone(ts->get_from_address(ts));
|
||||
this->ending_address = chunk_clone(ts->get_to_address(ts));
|
||||
this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
|
||||
this->payload_length = get_header_length(this) +
|
||||
this->ending_address.len + this->starting_address.len;
|
||||
|
||||
return &this->public;
|
||||
|
||||
@@ -29,11 +29,6 @@ typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
|
||||
#include <selectors/traffic_selector.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
|
||||
*/
|
||||
#define TRAFFIC_SELECTOR_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 TRAFFIC SELECTOR.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,44 @@
|
||||
#include <encoding/payloads/encodings.h>
|
||||
#include <library.h>
|
||||
|
||||
ENUM(tattr_ph1_names, TATTR_PH1_ENCRYPTION_ALGORITHM, TATTR_PH1_GROUP_ORDER,
|
||||
"ENCRYPTION_ALGORITHM",
|
||||
"HASH_ALGORITHM",
|
||||
"AUTH_METHOD",
|
||||
"GROUP",
|
||||
"GROUP_TYPE",
|
||||
"GROUP_PRIME",
|
||||
"GROUP_GENONE",
|
||||
"GROUP_GENTWO",
|
||||
"GROUP_CURVE_A",
|
||||
"GROUP_CURVE_B",
|
||||
"LIFE_TYPE",
|
||||
"LIFE_DURATION",
|
||||
"PRF",
|
||||
"KEY_LENGTH",
|
||||
"FIELD_SIZE",
|
||||
"GROUP_ORDER",
|
||||
);
|
||||
|
||||
ENUM(tattr_ph2_names, TATTR_PH2_SA_LIFE_TYPE, TATTR_PH2_EXT_SEQ_NUMBER,
|
||||
"SA_LIFE_TYPE",
|
||||
"SA_LIFE_DURATION",
|
||||
"GROUP",
|
||||
"ENCAP_MODE",
|
||||
"AUTH_ALGORITHM",
|
||||
"KEY_LENGTH",
|
||||
"KEY_ROUNDS",
|
||||
"COMP_DICT_SIZE",
|
||||
"COMP_PRIV_ALGORITHM",
|
||||
"ECN_TUNNEL",
|
||||
"EXT_SEQ_NUMBER",
|
||||
);
|
||||
|
||||
ENUM(tattr_ikev2_names, TATTR_IKEV2_KEY_LENGTH, TATTR_IKEV2_KEY_LENGTH,
|
||||
"KEY_LENGTH",
|
||||
);
|
||||
|
||||
|
||||
typedef struct private_transform_attribute_t private_transform_attribute_t;
|
||||
|
||||
/**
|
||||
@@ -57,22 +95,17 @@ struct private_transform_attribute_t {
|
||||
* Attribute value as chunk if attribute_format is 0 (FALSE).
|
||||
*/
|
||||
chunk_t attribute_value;
|
||||
|
||||
/**
|
||||
* Payload type, TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
|
||||
ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
|
||||
"ATTRIBUTE_UNDEFINED");
|
||||
ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
|
||||
"KEY_LENGTH");
|
||||
ENUM_END(transform_attribute_type_name, KEY_LENGTH);
|
||||
|
||||
/**
|
||||
* 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 rules for IKEv1/IKEv2 transform attributes
|
||||
*/
|
||||
encoding_rule_t transform_attribute_encodings[] = {
|
||||
static encoding_rule_t 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 */
|
||||
@@ -101,18 +134,23 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_transform_attribute_t *this, encoding_rule_t **rules,
|
||||
size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_transform_attribute_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = transform_attribute_encodings;
|
||||
*rule_count = countof(transform_attribute_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
return TRANSFORM_ATTRIBUTE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -136,31 +174,6 @@ METHOD(payload_t, get_length, size_t,
|
||||
return this->attribute_length_or_value + 4;
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, set_value_chunk, void,
|
||||
private_transform_attribute_t *this, chunk_t value)
|
||||
{
|
||||
chunk_free(&this->attribute_value);
|
||||
|
||||
if (value.len != 2)
|
||||
{
|
||||
this->attribute_value = chunk_clone(value);
|
||||
this->attribute_length_or_value = value.len;
|
||||
this->attribute_format = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&this->attribute_length_or_value, value.ptr, value.len);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, set_value, void,
|
||||
private_transform_attribute_t *this, u_int16_t value)
|
||||
{
|
||||
chunk_free(&this->attribute_value);
|
||||
this->attribute_length_or_value = value;
|
||||
this->attribute_format = TRUE;
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, get_value_chunk, chunk_t,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
@@ -171,16 +184,22 @@ METHOD(transform_attribute_t, get_value_chunk, chunk_t,
|
||||
return this->attribute_value;
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, get_value, u_int16_t,
|
||||
METHOD(transform_attribute_t, get_value, u_int64_t,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
return this->attribute_length_or_value;
|
||||
}
|
||||
u_int64_t value = 0;
|
||||
|
||||
METHOD(transform_attribute_t, set_attribute_type, void,
|
||||
private_transform_attribute_t *this, u_int16_t type)
|
||||
{
|
||||
this->attribute_type = type & 0x7FFF;
|
||||
if (this->attribute_format)
|
||||
{
|
||||
return this->attribute_length_or_value;
|
||||
}
|
||||
if (this->attribute_value.len > sizeof(value))
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
memcpy(((char*)&value) + sizeof(value) - this->attribute_value.len,
|
||||
this->attribute_value.ptr, this->attribute_value.len);
|
||||
return untoh64((char*)&value);
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
|
||||
@@ -189,24 +208,6 @@ METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
|
||||
return this->attribute_type;
|
||||
}
|
||||
|
||||
METHOD(transform_attribute_t, clone_, transform_attribute_t*,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
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 = chunk_clone(this->attribute_value);
|
||||
}
|
||||
return &new_clone->public;
|
||||
}
|
||||
|
||||
METHOD2(payload_t, transform_attribute_t, destroy, void,
|
||||
private_transform_attribute_t *this)
|
||||
{
|
||||
@@ -217,7 +218,7 @@ METHOD2(payload_t, transform_attribute_t, destroy, void,
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
transform_attribute_t *transform_attribute_create()
|
||||
transform_attribute_t *transform_attribute_create(payload_type_t type)
|
||||
{
|
||||
private_transform_attribute_t *this;
|
||||
|
||||
@@ -226,22 +227,20 @@ transform_attribute_t *transform_attribute_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
.get_type = _get_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.set_value_chunk = _set_value_chunk,
|
||||
.set_value = _set_value,
|
||||
.get_value_chunk = _get_value_chunk,
|
||||
.get_value = _get_value,
|
||||
.set_attribute_type = _set_attribute_type,
|
||||
.get_attribute_type = _get_attribute_type,
|
||||
.clone = _clone_,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.attribute_format = TRUE,
|
||||
.attribute_format = FALSE,
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -249,10 +248,33 @@ transform_attribute_t *transform_attribute_create()
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
|
||||
transform_attribute_t *transform_attribute_create_value(payload_type_t type,
|
||||
transform_attribute_type_t kind, u_int64_t value)
|
||||
{
|
||||
transform_attribute_t *attribute = transform_attribute_create();
|
||||
attribute->set_attribute_type(attribute, KEY_LENGTH);
|
||||
attribute->set_value(attribute, key_length);
|
||||
return attribute;
|
||||
private_transform_attribute_t *this;
|
||||
|
||||
this = (private_transform_attribute_t*)transform_attribute_create(type);
|
||||
|
||||
this->attribute_type = kind & 0x7FFF;
|
||||
|
||||
if (value <= UINT16_MAX)
|
||||
{
|
||||
this->attribute_length_or_value = value;
|
||||
this->attribute_format = TRUE;
|
||||
}
|
||||
else if (value <= UINT32_MAX)
|
||||
{
|
||||
u_int32_t val32;
|
||||
|
||||
val32 = htonl(value);
|
||||
this->attribute_value = chunk_clone(chunk_from_thing(val32));
|
||||
this->attribute_length_or_value = sizeof(val32);
|
||||
}
|
||||
else
|
||||
{
|
||||
htoun64(&value, value);
|
||||
this->attribute_value = chunk_clone(chunk_from_thing(value));
|
||||
this->attribute_length_or_value = sizeof(value);
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -28,26 +28,66 @@ typedef struct transform_attribute_t transform_attribute_t;
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
|
||||
/**
|
||||
* Type of the attribute, as in IKEv2 RFC 3.3.5.
|
||||
* Type of the attribute.
|
||||
*/
|
||||
enum transform_attribute_type_t {
|
||||
ATTRIBUTE_UNDEFINED = 16384,
|
||||
KEY_LENGTH = 14
|
||||
/** IKEv1 Phase 1 attributes */
|
||||
TATTR_PH1_ENCRYPTION_ALGORITHM = 1,
|
||||
TATTR_PH1_HASH_ALGORITHM = 2,
|
||||
TATTR_PH1_AUTH_METHOD = 3,
|
||||
TATTR_PH1_GROUP = 4,
|
||||
TATTR_PH1_GROUP_TYPE = 5,
|
||||
TATTR_PH1_GROUP_PRIME = 6,
|
||||
TATTR_PH1_GROUP_GENONE = 7,
|
||||
TATTR_PH1_GROUP_GENTWO = 8,
|
||||
TATTR_PH1_GROUP_CURVE_A = 9,
|
||||
TATTR_PH1_GROUP_CURVE_B = 10,
|
||||
TATTR_PH1_LIFE_TYPE = 11,
|
||||
TATTR_PH1_LIFE_DURATION = 12,
|
||||
TATTR_PH1_PRF = 13,
|
||||
TATTR_PH1_KEY_LENGTH = 14,
|
||||
TATTR_PH1_FIELD_SIZE = 15,
|
||||
TATTR_PH1_GROUP_ORDER = 16,
|
||||
/** IKEv1 Phase 2 attributes */
|
||||
TATTR_PH2_SA_LIFE_TYPE = 1,
|
||||
TATTR_PH2_SA_LIFE_DURATION = 2,
|
||||
TATTR_PH2_GROUP = 3,
|
||||
TATTR_PH2_ENCAP_MODE = 4,
|
||||
TATTR_PH2_AUTH_ALGORITHM = 5,
|
||||
TATTR_PH2_KEY_LENGTH = 6,
|
||||
TATTR_PH2_KEY_ROUNDS = 7,
|
||||
TATTR_PH2_COMP_DICT_SIZE = 8,
|
||||
TATTR_PH2_COMP_PRIV_ALGORITHM = 9,
|
||||
TATTR_PH2_ECN_TUNNEL = 10,
|
||||
TATTR_PH2_EXT_SEQ_NUMBER = 11,
|
||||
/* IKEv2 key length attribute */
|
||||
TATTR_IKEV2_KEY_LENGTH = 14,
|
||||
/* undefined, private use attribute */
|
||||
TATTR_UNDEFINED = 16384,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for transform_attribute_type_t.
|
||||
* Enum names for IKEv1 Phase 1 transform_attribute_type_t.
|
||||
*/
|
||||
extern enum_name_t *transform_attribute_type_names;
|
||||
extern enum_name_t *tattr_ph1_names;
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2- TRANSFORM Attribute.
|
||||
*
|
||||
* The TRANSFORM ATTRIBUTE format is described in RFC section 3.3.5.
|
||||
* Enum names for IKEv1 Phase 2 transform_attribute_type_t.
|
||||
*/
|
||||
extern enum_name_t *tattr_ph2_names;
|
||||
|
||||
/**
|
||||
* Enum names for IKEv2 transform_attribute_type_t.
|
||||
*/
|
||||
extern enum_name_t *tattr_ikev2_names;
|
||||
|
||||
|
||||
/**
|
||||
* Class representing an IKEv1/IKEv2 TRANSFORM Attribute.
|
||||
*/
|
||||
struct transform_attribute_t {
|
||||
|
||||
/**
|
||||
* The payload_t interface.
|
||||
*/
|
||||
@@ -58,7 +98,7 @@ struct transform_attribute_t {
|
||||
*
|
||||
* Returned data are not copied.
|
||||
*
|
||||
* @return chunk_t pointing to the value
|
||||
* @return chunk_t pointing to internal value
|
||||
*/
|
||||
chunk_t (*get_value_chunk) (transform_attribute_t *this);
|
||||
|
||||
@@ -69,30 +109,7 @@ struct transform_attribute_t {
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
u_int16_t (*get_value) (transform_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Sets the value of the attribute.
|
||||
*
|
||||
* Value is getting copied.
|
||||
*
|
||||
* @param value chunk_t pointing to the value to set
|
||||
*/
|
||||
void (*set_value_chunk) (transform_attribute_t *this, chunk_t value);
|
||||
|
||||
/**
|
||||
* Sets the value of the attribute.
|
||||
*
|
||||
* @param value value to set
|
||||
*/
|
||||
void (*set_value) (transform_attribute_t *this, u_int16_t value);
|
||||
|
||||
/**
|
||||
* Sets the type of the attribute.
|
||||
*
|
||||
* @param type type to set (most significant bit is set to zero)
|
||||
*/
|
||||
void (*set_attribute_type) (transform_attribute_t *this, u_int16_t type);
|
||||
u_int64_t (*get_value) (transform_attribute_t *this);
|
||||
|
||||
/**
|
||||
* get the type of the attribute.
|
||||
@@ -101,13 +118,6 @@ struct transform_attribute_t {
|
||||
*/
|
||||
u_int16_t (*get_attribute_type) (transform_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Clones an transform_attribute_t object.
|
||||
*
|
||||
* @return cloned transform_attribute_t object
|
||||
*/
|
||||
transform_attribute_t * (*clone) (transform_attribute_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an transform_attribute_t object.
|
||||
*/
|
||||
@@ -117,16 +127,20 @@ struct transform_attribute_t {
|
||||
/**
|
||||
* Creates an empty transform_attribute_t object.
|
||||
*
|
||||
* @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
|
||||
* @return transform_attribute_t object
|
||||
*/
|
||||
transform_attribute_t *transform_attribute_create(void);
|
||||
transform_attribute_t *transform_attribute_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates an transform_attribute_t of type KEY_LENGTH.
|
||||
* Creates a two byte value or a larger attribute for a given attribute kind.
|
||||
*
|
||||
* @param key_length key length in bytes
|
||||
* @param type TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
|
||||
* @param kind attribute kind
|
||||
* @param value fixed two byte value
|
||||
* @return transform_attribute_t object
|
||||
*/
|
||||
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length);
|
||||
transform_attribute_t *transform_attribute_create_value(payload_type_t type,
|
||||
transform_attribute_type_t kind, u_int64_t value);
|
||||
|
||||
#endif /** TRANSFORM_ATTRIBUTE_H_ @}*/
|
||||
|
||||
@@ -41,10 +41,11 @@ struct private_transform_substructure_t {
|
||||
* Next payload type.
|
||||
*/
|
||||
u_int8_t next_payload;
|
||||
|
||||
/**
|
||||
* Reserved bytes
|
||||
* Reserved byte
|
||||
*/
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t reserved[3];
|
||||
|
||||
/**
|
||||
* Length of this payload.
|
||||
@@ -52,43 +53,72 @@ struct private_transform_substructure_t {
|
||||
u_int16_t transform_length;
|
||||
|
||||
/**
|
||||
* Type of the transform.
|
||||
* Type or number, Type of the transform in IKEv2, number in IKEv2.
|
||||
*/
|
||||
u_int8_t transform_type;
|
||||
u_int8_t transform_ton;
|
||||
|
||||
/**
|
||||
* Transform ID.
|
||||
* Transform ID, as encoded in IKEv1.
|
||||
*/
|
||||
u_int16_t transform_id;
|
||||
u_int8_t transform_id_v1;
|
||||
|
||||
/**
|
||||
* Transform ID, as encoded in IKEv2.
|
||||
*/
|
||||
u_int16_t transform_id_v2;
|
||||
|
||||
/**
|
||||
* Transforms Attributes are stored in a linked_list_t.
|
||||
*/
|
||||
linked_list_t *attributes;
|
||||
|
||||
/**
|
||||
* Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 rules for TRANSFORM_SUBSTRUCTURE
|
||||
*/
|
||||
encoding_rule_t transform_substructure_encodings[] = {
|
||||
static encoding_rule_t encodings_v2[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
|
||||
/* 1 Reserved Byte */
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[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) },
|
||||
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
|
||||
/* transform type */
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, transform_ton) },
|
||||
/* transform identifier, as used by IKEv1 */
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
|
||||
/* transform identifier, as used by IKEv2 */
|
||||
{ U_INT_16, offsetof(private_transform_substructure_t, transform_id_v2) },
|
||||
/* Attributes in a transform attribute list */
|
||||
{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE,
|
||||
offsetof(private_transform_substructure_t, attributes) }
|
||||
};
|
||||
|
||||
/**
|
||||
* Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
|
||||
*/
|
||||
static encoding_rule_t encodings_v1[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
|
||||
/* 1 Reserved Byte */
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
|
||||
/* transform 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) }
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) },
|
||||
/* Length of the whole transform substructure*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)},
|
||||
/* transform number */
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, transform_ton)},
|
||||
/* transform identifier, as used by IKEv1 */
|
||||
{ U_INT_8, offsetof(private_transform_substructure_t, transform_id_v1) },
|
||||
/* transform identifier, as used by IKEv2 */
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) },
|
||||
{ RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[2]) },
|
||||
/* Attributes in a transform attribute list */
|
||||
{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1,
|
||||
offsetof(private_transform_substructure_t, attributes) }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -97,7 +127,7 @@ encoding_rule_t transform_substructure_encodings[] = {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! 0 (last) or 3 ! RESERVED ! Transform Length !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
!Transform Type ! RESERVED ! Transform ID !
|
||||
! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
! !
|
||||
~ Transform Attributes ~
|
||||
@@ -118,23 +148,6 @@ METHOD(payload_t, verify, status_t,
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
switch (this->transform_type)
|
||||
{
|
||||
case ENCRYPTION_ALGORITHM:
|
||||
case PSEUDO_RANDOM_FUNCTION:
|
||||
case INTEGRITY_ALGORITHM:
|
||||
case DIFFIE_HELLMAN_GROUP:
|
||||
case EXTENDED_SEQUENCE_NUMBERS:
|
||||
/* we don't check transform ID, we want to reply
|
||||
* cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
|
||||
break;
|
||||
default:
|
||||
{
|
||||
DBG1(DBG_ENC, "invalid transform type: %d", this->transform_type);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||
while (enumerator->enumerate(enumerator, &attribute))
|
||||
{
|
||||
@@ -151,18 +164,28 @@ METHOD(payload_t, verify, status_t,
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_transform_substructure_t *this, encoding_rule_t **rules,
|
||||
size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_transform_substructure_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = transform_substructure_encodings;
|
||||
*rule_count = countof(transform_substructure_encodings);
|
||||
if (this->type == TRANSFORM_SUBSTRUCTURE)
|
||||
{
|
||||
*rules = encodings_v2;
|
||||
return countof(encodings_v2);
|
||||
}
|
||||
*rules = encodings_v1;
|
||||
return countof(encodings_v1);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
return TRANSFORM_SUBSTRUCTURE;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -174,12 +197,12 @@ METHOD(payload_t, get_next_type, payload_type_t,
|
||||
/**
|
||||
* recompute the length of the payload.
|
||||
*/
|
||||
static void compute_length (private_transform_substructure_t *this)
|
||||
static void compute_length(private_transform_substructure_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
payload_t *attribute;
|
||||
|
||||
this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
|
||||
this->transform_length = get_header_length(this);
|
||||
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||
while (enumerator->enumerate(enumerator, &attribute))
|
||||
{
|
||||
@@ -194,6 +217,13 @@ METHOD(payload_t, get_length, size_t,
|
||||
return this->transform_length;
|
||||
}
|
||||
|
||||
METHOD(transform_substructure_t, add_transform_attribute, void,
|
||||
private_transform_substructure_t *this, transform_attribute_t *attribute)
|
||||
{
|
||||
this->attributes->insert_last(this->attributes, attribute);
|
||||
compute_length(this);
|
||||
}
|
||||
|
||||
METHOD(transform_substructure_t, set_is_last_transform, void,
|
||||
private_transform_substructure_t *this, bool is_last)
|
||||
{
|
||||
@@ -205,50 +235,40 @@ METHOD(payload_t, set_next_type, void,
|
||||
{
|
||||
}
|
||||
|
||||
METHOD(transform_substructure_t, get_transform_type, u_int8_t,
|
||||
METHOD(transform_substructure_t, get_transform_type_or_number, u_int8_t,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
return this->transform_type;
|
||||
return this->transform_ton;
|
||||
}
|
||||
|
||||
METHOD(transform_substructure_t, get_transform_id, u_int16_t,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
return this->transform_id;
|
||||
if (this->type == TRANSFORM_SUBSTRUCTURE)
|
||||
{
|
||||
return this->transform_id_v2;
|
||||
}
|
||||
return this->transform_id_v1;
|
||||
}
|
||||
|
||||
METHOD(transform_substructure_t, get_key_length, status_t,
|
||||
private_transform_substructure_t *this, u_int16_t *key_length)
|
||||
METHOD(transform_substructure_t, create_attribute_enumerator, enumerator_t*,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
transform_attribute_t *attribute;
|
||||
|
||||
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||
while (enumerator->enumerate(enumerator, &attribute))
|
||||
{
|
||||
if (attribute->get_attribute_type(attribute) == KEY_LENGTH)
|
||||
{
|
||||
*key_length = attribute->get_value(attribute);
|
||||
enumerator->destroy(enumerator);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return FAILED;
|
||||
return this->attributes->create_enumerator(this->attributes);
|
||||
}
|
||||
|
||||
METHOD2(payload_t, transform_substructure_t, destroy, void,
|
||||
private_transform_substructure_t *this)
|
||||
{
|
||||
this->attributes->destroy_offset(this->attributes,
|
||||
offsetof(transform_attribute_t, destroy));
|
||||
offsetof(payload_t, destroy));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
transform_substructure_t *transform_substructure_create()
|
||||
transform_substructure_t *transform_substructure_create(payload_type_t type)
|
||||
{
|
||||
private_transform_substructure_t *this;
|
||||
|
||||
@@ -257,21 +277,24 @@ transform_substructure_t *transform_substructure_create()
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
.get_type = _get_type,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.add_transform_attribute = _add_transform_attribute,
|
||||
.set_is_last_transform = _set_is_last_transform,
|
||||
.get_transform_type = _get_transform_type,
|
||||
.get_transform_type_or_number = _get_transform_type_or_number,
|
||||
.get_transform_id = _get_transform_id,
|
||||
.get_key_length = _get_key_length,
|
||||
.create_attribute_enumerator = _create_attribute_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH,
|
||||
.transform_length = get_header_length(this),
|
||||
.attributes = linked_list_create(),
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -279,20 +302,21 @@ transform_substructure_t *transform_substructure_create()
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
transform_substructure_t *transform_substructure_create_type(
|
||||
transform_type_t type, u_int16_t id, u_int16_t key_length)
|
||||
transform_substructure_t *transform_substructure_create_type(payload_type_t type,
|
||||
u_int8_t type_or_number, u_int16_t id)
|
||||
{
|
||||
private_transform_substructure_t *this;
|
||||
|
||||
this = (private_transform_substructure_t*)transform_substructure_create();
|
||||
this = (private_transform_substructure_t*)transform_substructure_create(type);
|
||||
|
||||
this->transform_type = type;
|
||||
this->transform_id = id;
|
||||
if (key_length)
|
||||
this->transform_ton = type_or_number;
|
||||
if (type == TRANSFORM_SUBSTRUCTURE)
|
||||
{
|
||||
this->attributes->insert_last(this->attributes,
|
||||
(void*)transform_attribute_create_key_length(key_length));
|
||||
compute_length(this);
|
||||
this->transform_id_v2 = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->transform_id_v1 = id;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -40,14 +40,7 @@ typedef struct transform_substructure_t transform_substructure_t;
|
||||
#define TRANSFORM_TYPE_VALUE 3
|
||||
|
||||
/**
|
||||
* Length of the transform substructure header in bytes.
|
||||
*/
|
||||
#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2- TRANSFORM SUBSTRUCTURE.
|
||||
*
|
||||
* The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2.
|
||||
* Class representing an IKEv1/IKEv2 transform substructure.
|
||||
*/
|
||||
struct transform_substructure_t {
|
||||
|
||||
@@ -75,11 +68,11 @@ struct transform_substructure_t {
|
||||
void (*set_is_last_transform) (transform_substructure_t *this, bool is_last);
|
||||
|
||||
/**
|
||||
* get transform type of the current transform.
|
||||
* Get transform type (IKEv2) or the transform number (IKEv1).
|
||||
*
|
||||
* @return Transform type of current transform substructure.
|
||||
*/
|
||||
u_int8_t (*get_transform_type) (transform_substructure_t *this);
|
||||
u_int8_t (*get_transform_type_or_number) (transform_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get transform id of the current transform.
|
||||
@@ -89,16 +82,11 @@ struct transform_substructure_t {
|
||||
u_int16_t (*get_transform_id) (transform_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Get transform id of the current transform.
|
||||
* Create an enumerator over transform attributes.
|
||||
*
|
||||
* @param key_length The key length is written to this location
|
||||
* @return
|
||||
* - SUCCESS if a key length attribute is contained
|
||||
* - FAILED if no key length attribute is part of this
|
||||
* transform or key length uses more then 16 bit!
|
||||
* @return enumerator over transform_attribute_t*
|
||||
*/
|
||||
status_t (*get_key_length) (transform_substructure_t *this,
|
||||
u_int16_t *key_length);
|
||||
enumerator_t* (*create_attribute_enumerator)(transform_substructure_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an transform_substructure_t object.
|
||||
@@ -109,19 +97,20 @@ struct transform_substructure_t {
|
||||
/**
|
||||
* Creates an empty transform_substructure_t object.
|
||||
*
|
||||
* @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
|
||||
* @return created transform_substructure_t object
|
||||
*/
|
||||
transform_substructure_t *transform_substructure_create(void);
|
||||
transform_substructure_t *transform_substructure_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates an empty transform_substructure_t object.
|
||||
*
|
||||
* @param type type of transform to create
|
||||
* @param id transform id specifc for the transform type
|
||||
* @param key_length key length for key length attribute, 0 to omit
|
||||
* @return transform_substructure_t object
|
||||
* @param type TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
|
||||
* @param type_or_number Type (IKEv2) or number (IKEv1) of transform
|
||||
* @param id transform id specifc for the transform type
|
||||
* @return transform_substructure_t object
|
||||
*/
|
||||
transform_substructure_t *transform_substructure_create_type(
|
||||
transform_type_t type, u_int16_t id, u_int16_t key_length);
|
||||
transform_substructure_t *transform_substructure_create_type(payload_type_t type,
|
||||
u_int8_t type_or_number, u_int16_t id);
|
||||
|
||||
#endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/
|
||||
|
||||
@@ -81,7 +81,7 @@ struct private_ts_payload_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_ts_payload_t.
|
||||
*/
|
||||
encoding_rule_t ts_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_ts_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -102,8 +102,9 @@ encoding_rule_t ts_payload_encodings[] = {
|
||||
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[0])},
|
||||
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[1])},
|
||||
{ RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[2])},
|
||||
/* some ts data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ TRAFFIC_SELECTORS,offsetof(private_ts_payload_t, substrs) }
|
||||
/* wrapped list of traffic selectors substructures */
|
||||
{ PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE,
|
||||
offsetof(private_ts_payload_t, substrs) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -145,11 +146,17 @@ METHOD(payload_t, verify, status_t,
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_ts_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = ts_payload_encodings;
|
||||
*rule_count = countof(ts_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_ts_payload_t *this)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
@@ -182,7 +189,7 @@ static void compute_length(private_ts_payload_t *this)
|
||||
enumerator_t *enumerator;
|
||||
payload_t *subst;
|
||||
|
||||
this->payload_length = TS_PAYLOAD_HEADER_LENGTH;
|
||||
this->payload_length = get_header_length(this);
|
||||
this->ts_num = 0;
|
||||
enumerator = this->substrs->create_enumerator(this->substrs);
|
||||
while (enumerator->enumerate(enumerator, &subst))
|
||||
@@ -250,6 +257,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -262,7 +270,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = TS_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.is_initiator = is_initiator,
|
||||
.substrs = linked_list_create(),
|
||||
);
|
||||
|
||||
@@ -30,11 +30,6 @@ typedef struct ts_payload_t ts_payload_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
#include <encoding/payloads/traffic_selector_substructure.h>
|
||||
|
||||
/**
|
||||
* Length of a TS payload without the Traffic selectors.
|
||||
*/
|
||||
#define TS_PAYLOAD_HEADER_LENGTH 8
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 TS payload.
|
||||
*
|
||||
|
||||
@@ -68,7 +68,7 @@ struct private_unknown_payload_t {
|
||||
* private_unknown_payload_t.
|
||||
*
|
||||
*/
|
||||
encoding_rule_t unknown_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_unknown_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -84,7 +84,7 @@ encoding_rule_t unknown_payload_encodings[] = {
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length) },
|
||||
/* some unknown data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) },
|
||||
{ CHUNK_DATA, offsetof(private_unknown_payload_t, data) },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -102,18 +102,20 @@ encoding_rule_t unknown_payload_encodings[] = {
|
||||
METHOD(payload_t, verify, status_t,
|
||||
private_unknown_payload_t *this)
|
||||
{
|
||||
if (this->payload_length != UNKNOWN_PAYLOAD_HEADER_LENGTH + this->data.len)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_unknown_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = unknown_payload_encodings;
|
||||
*rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_unknown_payload_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_payload_type, payload_type_t,
|
||||
@@ -171,6 +173,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -182,7 +185,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH,
|
||||
.payload_length = get_header_length(this),
|
||||
.type = type,
|
||||
);
|
||||
|
||||
@@ -201,7 +204,7 @@ unknown_payload_t *unknown_payload_create_data(payload_type_t type,
|
||||
this = (private_unknown_payload_t*)unknown_payload_create(type);
|
||||
this->data = data;
|
||||
this->critical = critical;
|
||||
this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH + data.len;
|
||||
this->payload_length = get_header_length(this) + data.len;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -27,11 +27,6 @@ typedef struct unknown_payload_t unknown_payload_t;
|
||||
#include <library.h>
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Header length of the unknown payload.
|
||||
*/
|
||||
#define UNKNOWN_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Payload which can't be processed further.
|
||||
*
|
||||
|
||||
@@ -55,6 +55,11 @@ struct private_vendor_id_payload_t {
|
||||
* The contained data.
|
||||
*/
|
||||
chunk_t data;
|
||||
|
||||
/**
|
||||
* Either a IKEv1 or a IKEv2 vendor ID payload
|
||||
*/
|
||||
payload_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -63,7 +68,7 @@ struct private_vendor_id_payload_t {
|
||||
* The defined offsets are the positions in a object of type
|
||||
* private_vendor_id_payload_t.
|
||||
*/
|
||||
encoding_rule_t vendor_id_payload_encodings[] = {
|
||||
static encoding_rule_t encodings[] = {
|
||||
/* 1 Byte next payload type, stored in the field next_payload */
|
||||
{ U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) },
|
||||
/* the critical bit */
|
||||
@@ -79,7 +84,7 @@ encoding_rule_t vendor_id_payload_encodings[] = {
|
||||
/* Length of the whole payload*/
|
||||
{ PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)},
|
||||
/* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */
|
||||
{ VID_DATA, offsetof(private_vendor_id_payload_t, data) }
|
||||
{ CHUNK_DATA, offsetof(private_vendor_id_payload_t, data) }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -100,18 +105,23 @@ METHOD(payload_t, verify, status_t,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_encoding_rules, void,
|
||||
private_vendor_id_payload_t *this, encoding_rule_t **rules,
|
||||
size_t *rule_count)
|
||||
METHOD(payload_t, get_encoding_rules, int,
|
||||
private_vendor_id_payload_t *this, encoding_rule_t **rules)
|
||||
{
|
||||
*rules = vendor_id_payload_encodings;
|
||||
*rule_count = countof(vendor_id_payload_encodings);
|
||||
*rules = encodings;
|
||||
return countof(encodings);
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_header_length, int,
|
||||
private_vendor_id_payload_t *this)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_type, payload_type_t,
|
||||
private_vendor_id_payload_t *this)
|
||||
{
|
||||
return VENDOR_ID;
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(payload_t, get_next_type, payload_type_t,
|
||||
@@ -148,7 +158,8 @@ METHOD2(payload_t, vendor_id_payload_t, destroy, void,
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
|
||||
vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
|
||||
chunk_t data)
|
||||
{
|
||||
private_vendor_id_payload_t *this;
|
||||
|
||||
@@ -157,6 +168,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
|
||||
.payload_interface = {
|
||||
.verify = _verify,
|
||||
.get_encoding_rules = _get_encoding_rules,
|
||||
.get_header_length = _get_header_length,
|
||||
.get_length = _get_length,
|
||||
.get_next_type = _get_next_type,
|
||||
.set_next_type = _set_next_type,
|
||||
@@ -167,8 +179,9 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.next_payload = NO_PAYLOAD,
|
||||
.payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + data.len,
|
||||
.payload_length = get_header_length(this) + data.len,
|
||||
.data = data,
|
||||
.type = type,
|
||||
);
|
||||
return &this->public;
|
||||
}
|
||||
@@ -176,7 +189,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data)
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
vendor_id_payload_t *vendor_id_payload_create()
|
||||
vendor_id_payload_t *vendor_id_payload_create(payload_type_t type)
|
||||
{
|
||||
return vendor_id_payload_create_data(chunk_empty);
|
||||
return vendor_id_payload_create_data(type, chunk_empty);
|
||||
}
|
||||
|
||||
@@ -28,12 +28,7 @@ typedef struct vendor_id_payload_t vendor_id_payload_t;
|
||||
#include <encoding/payloads/payload.h>
|
||||
|
||||
/**
|
||||
* Length of a VENDOR ID payload without the VID data in bytes.
|
||||
*/
|
||||
#define VENDOR_ID_PAYLOAD_HEADER_LENGTH 4
|
||||
|
||||
/**
|
||||
* Class representing an IKEv2 VENDOR ID payload.
|
||||
* Class representing an IKEv1/IKEv2 VENDOR ID payload.
|
||||
*
|
||||
* The VENDOR ID payload format is described in RFC section 3.12.
|
||||
*/
|
||||
@@ -58,18 +53,21 @@ struct vendor_id_payload_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an empty Vendor ID payload.
|
||||
* Creates an empty Vendor ID payload for IKEv1 or IKEv2.
|
||||
*
|
||||
* @@param type VENDOR_ID or VENDOR_ID_V1
|
||||
* @return vendor ID payload
|
||||
*/
|
||||
vendor_id_payload_t *vendor_id_payload_create();
|
||||
vendor_id_payload_t *vendor_id_payload_create(payload_type_t type);
|
||||
|
||||
/**
|
||||
* Creates a vendor ID payload using a chunk of data
|
||||
*
|
||||
* @param type VENDOR_ID or VENDOR_ID_V1
|
||||
* @param data data to use in vendor ID payload, gets owned by payload
|
||||
* @return vendor ID payload
|
||||
*/
|
||||
vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data);
|
||||
vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
|
||||
chunk_t data);
|
||||
|
||||
#endif /** VENDOR_ID_PAYLOAD_H_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user