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:
Martin Willi
2012-05-02 11:12:31 +02:00
297 changed files with 22065 additions and 5546 deletions
+104 -48
View File
@@ -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;
}
+8
View File
@@ -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_ @}*/
File diff suppressed because it is too large Load Diff
+32 -31
View File
@@ -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
View File
@@ -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",
+15 -8
View File
@@ -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.
+40 -18
View File
@@ -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;
}
+12 -15
View File
@@ -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_ @}*/
+109 -35
View File
@@ -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);
}
+22 -13
View File
@@ -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_ @}*/
+121 -22
View File
@@ -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_ @}*/
+15 -7
View File
@@ -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.
+2 -18
View File
@@ -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",
);
+16 -183
View File
@@ -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_ @}*/
+273 -31
View File
@@ -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;
}
+32 -16
View File
@@ -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_ @}*/
+155 -44
View File
@@ -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;
}
+112 -27
View File
@@ -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_ @}*/
+60 -16
View File
@@ -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;
}
+14 -18
View File
@@ -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_ @}*/
+43 -11
View File
@@ -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_ @}*/
+209 -75
View File
@@ -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;
}
+50 -12
View File
@@ -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_ @}*/
+120 -39
View File
@@ -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)
+138 -37
View File
@@ -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_ @}*/
+245 -42
View File
@@ -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 **)&current))
{
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;
}
+64 -17
View File
@@ -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_ @}*/
+17 -9
View File
@@ -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_ @}*/