diff --git a/Source/charon/generator.c b/Source/charon/generator.c index f4d3ad8e6..8737157db 100644 --- a/Source/charon/generator.c +++ b/Source/charon/generator.c @@ -30,8 +30,10 @@ #include "types.h" #include "utils/allocator.h" +#include "utils/linked_list.h" #include "utils/logger_manager.h" #include "payloads/payload.h" +#include "payloads/transform_substructure.h" extern logger_manager_t *global_logger_manager; @@ -138,6 +140,21 @@ struct private_generator_s { status_t (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes); + /** + * Writes a specific amount of byte into the buffer at a specific offset. + * + * @warning buffer size is not check to hold the data if offset is to large. + * + * @param this calling private_generator_t object + * @param bytes pointer to bytes to write + * @param number_of_bytes number of bytes to write into buffer + * @param offset offset to write the data into + * @return + * - SUCCESSFUL if succeeded + * - OUT_OF_RES otherwise + */ + status_t (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset); + /** * Buffer used to generate the data into. */ @@ -163,6 +180,11 @@ struct private_generator_s { */ void * data_struct; + /* + * Last payload length position offset in the buffer + */ + u_int32_t last_payload_length_position_offset; + /* * Attribute format of the last generated transform attribute * @@ -461,6 +483,26 @@ static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes,si return status; } +/** + * Implements private_generator_t's write_bytes_to_buffer_at_offset function. + * See #private_generator_s.write_bytes_to_buffer_at_offset. + * TODO automatic buffer increasing! + */ +static status_t write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset) +{ + u_int8_t *read_position = (u_int8_t *) bytes; + int i; + u_int8_t *write_position = this->buffer + offset; + + for (i = 0; i < number_of_bytes; i++) + { + *(write_position) = *(read_position); + read_position++; + write_position++; + } + return SUCCESS; +} + /** * Implements generator_t's write_chunk function. * See #generator_s.write_chunk. @@ -534,6 +576,7 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload) } case PAYLOAD_LENGTH: /* payload length is generated like an U_INT_16 */ + this->last_payload_length_position_offset = (this->out_position - this->buffer); status = this->generate_u_int_type(this,U_INT_16,rules[i].offset); break; @@ -543,7 +586,53 @@ static status_t generate_payload (private_generator_t *this,payload_t *payload) break; case SPI_SIZE: /* currently not implemented */ + break; + case TRANSFORM_ATTRIBUTES: + { + this->logger->log(this->logger,CONTROL_MORE,"Generate Transform attributes"); + /* before iterative generate the transforms, store the current length position */ + u_int32_t transform_length_position_offset = this->last_payload_length_position_offset; + + u_int16_t length_of_transform = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + u_int16_t int16_val; + linked_list_t *transform_attributes =*((linked_list_t **)(this->data_struct + rules[i].offset)); + + linked_list_iterator_t *iterator; + /* create forward iterator */ + status = transform_attributes->create_iterator(transform_attributes,&iterator,TRUE); + if (status != SUCCESS) + { + return status; + } + while (iterator->has_next(iterator)) + { + payload_t *current_attribute; + u_int32_t before_generate_position_offset; + u_int32_t after_generate_position_offset; + status = iterator->current(iterator,(void **)¤t_attribute); + if (status != SUCCESS) + { + iterator->destroy(iterator); + return status; + } + + before_generate_position_offset = (this->out_position - this->buffer); + this->public.generate_payload(&(this->public),current_attribute); + after_generate_position_offset = (this->out_position - this->buffer); + + /* increase size of transform */ + length_of_transform += (after_generate_position_offset - before_generate_position_offset); + } + iterator->destroy(iterator); + + this->logger->log(this->logger,CONTROL_MORE,"Length of Transform is %d, offset is %d",length_of_transform,transform_length_position_offset); + + int16_val = htons(length_of_transform); + this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset); + + break; + } case ATTRIBUTE_FORMAT: { this->logger->log(this->logger,CONTROL_MORE,"Generate Attribute Format flag"); @@ -632,6 +721,7 @@ generator_t * generator_create() this->generate_from_chunk = generate_from_chunk; this->make_space_available = make_space_available; this->write_bytes_to_buffer = write_bytes_to_buffer; + this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset; /* allocate memory for buffer */ @@ -647,6 +737,7 @@ generator_t * generator_create() this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE; this->data_struct = NULL; this->current_bit = 0; + this->last_payload_length_position_offset = 0; this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL); return &(this->public); } diff --git a/Source/charon/payloads/transform_substructure.c b/Source/charon/payloads/transform_substructure.c index 6a302fb60..9313ff5d6 100644 --- a/Source/charon/payloads/transform_substructure.c +++ b/Source/charon/payloads/transform_substructure.c @@ -65,12 +65,12 @@ struct private_transform_substructure_s { /** * Transform ID */ - u_int8_t transform_id; + u_int16_t transform_id; /** * Transforms Attributes are stored in a linked_list_t */ - linked_list_t * attributes; + linked_list_t *attributes; }; @@ -93,7 +93,7 @@ encoding_rule_t transform_substructure_encodings[] = { /* Reserved Byte is skipped */ { RESERVED_BYTE, 0 }, /* tranform ID is a number of 8 bit */ - { U_INT_8, offsetof(private_transform_substructure_t, transform_id) }, + { 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) } @@ -158,6 +158,21 @@ static payload_type_t get_next_type(private_transform_substructure_t *this) */ static size_t get_length(private_transform_substructure_t *this) { + linked_list_iterator_t *iterator; + status_t status; + size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + status = this->attributes->create_iterator(this->attributes,&iterator,TRUE); + if (status != SUCCESS) + return length; + while (iterator->has_next(iterator)) + { + payload_t * current_attribute; + iterator->current(iterator,(void **) ¤t_attribute); + length += current_attribute->get_length(current_attribute); + } + + this->transform_length = length; + return this->transform_length; } @@ -177,8 +192,66 @@ static status_t create_transform_attribute_iterator (private_transform_substruct static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute) { return (this->attributes->insert_last(this->attributes,(void *) attribute)); + this->transform_length += ((payload_t *)this->attributes)->get_length(((payload_t *)this->attributes)); + return SUCCESS; } +/** + * Implements transform_substructure_t's set_is_last_transform function. + * See #transform_substructure_s.set_is_last_transform for description. + */ +static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last) +{ + this->next_payload = (is_last) ? 0 : TRANSFORM_TYPE_VALUE; + return SUCCESS; +} + +/** + * Implements transform_substructure_t's get_is_last_transform function. + * See #transform_substructure_s.get_is_last_transform for description. + */ +static bool get_is_last_transform (private_transform_substructure_t *this) +{ + return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE); +} + +/** + * Implements transform_substructure_t's set_transform_type function. + * See #transform_substructure_s.set_transform_type for description. + */ +static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type) +{ + this->transform_type = type; + return SUCCESS; +} + +/** + * Implements transform_substructure_t's get_transform_type function. + * See #transform_substructure_s.get_transform_type for description. + */ +static u_int8_t get_transform_type (private_transform_substructure_t *this) +{ + return this->transform_type; +} + +/** + * Implements transform_substructure_t's set_transform_id function. + * See #transform_substructure_s.set_transform_id for description. + */ +static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id) +{ + this->transform_id = id; + return SUCCESS; +} + +/** + * Implements transform_substructure_t's get_transform_id function. + * See #transform_substructure_s.get_transform_id for description. + */ +static u_int16_t get_transform_id (private_transform_substructure_t *this) +{ + return this->transform_id; +} /* * Described in header @@ -198,11 +271,17 @@ transform_substructure_t *transform_substructure_create() this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy; this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator; this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute; + this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform; + this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform; + this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type; + this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type; + this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id; + this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id; this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy; /* set default values of the fields */ this->next_payload = NO_PAYLOAD; - this->transform_length = 0; + this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; this->transform_id = 0; this->transform_type = 0; diff --git a/Source/charon/payloads/transform_substructure.h b/Source/charon/payloads/transform_substructure.h index 0454ad60a..ba4988073 100644 --- a/Source/charon/payloads/transform_substructure.h +++ b/Source/charon/payloads/transform_substructure.h @@ -30,6 +30,16 @@ #include "../utils/linked_list.h" #include "transform_attribute.h" +/** + * IKEv1 Value for a transform payload + */ +#define TRANSFORM_TYPE_VALUE 3 + +/** + * Length of the transform substructure header in bytes + */ +#define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8 + /** * Object representing an IKEv2- TRANSFORM SUBSTRUCTURE * @@ -48,6 +58,9 @@ struct transform_substructure_s { * @brief Creates an iterator of stored transform_attribute_t objects. * * @warning The created iterator has to get destroyed by the caller! + * + * @warning When deleting an transform attribute, the length of this transform substructure + * has to be refreshed with get_length! * * @param this calling transform_substructure_t object * @param iterator the created iterator is stored at the pointed pointer @@ -71,6 +84,60 @@ struct transform_substructure_s { */ status_t (*add_transform_attribute) (transform_substructure_t *this,transform_attribute_t *attribute); + /** + * @brief Sets the next_payload field of this substructure + * + * If this is the last transform, next payload field is set to 0, + * otherwise to 3 (payload type of transform in IKEv1) + * + * @param this calling transform_substructure_t object + * @param is_last When TRUE, next payload field is set to 0, otherwise to 3 + * @return - SUCCESS + */ + status_t (*set_is_last_transform) (transform_substructure_t *this, bool is_last); + + /** + * @brief Checks if this is the last transform. + * + * @param this calling transform_substructure_t object + * @return TRUE if this is the last Transform, FALSE otherwise + */ + bool (*get_is_last_transform) (transform_substructure_t *this); + + /** + * @brief Sets transform type of the current transform substructure. + * + * @param this calling transform_substructure_t object + * @param type type value to set + * @return - SUCCESS + */ + status_t (*set_transform_type) (transform_substructure_t *this,u_int8_t type); + + /** + * @brief get transform type of the current transform. + * + * @param this calling transform_substructure_t object + * @return Transform type of current transform substructure. + */ + u_int8_t (*get_transform_type) (transform_substructure_t *this); + + /** + * @brief Sets transform id of the current transform substructure. + * + * @param this calling transform_substructure_t object + * @param id transform id to set + * @return - SUCCESS + */ + status_t (*set_transform_id) (transform_substructure_t *this,u_int16_t id); + + /** + * @brief get transform id of the current transform. + * + * @param this calling transform_substructure_t object + * @return Transform id of current transform substructure. + */ + u_int16_t (*get_transform_id) (transform_substructure_t *this); + /** * @brief Destroys an transform_substructure_t object. * diff --git a/Source/charon/testcases/generator_test.c b/Source/charon/testcases/generator_test.c index 038dc26d5..5ec4bcae1 100644 --- a/Source/charon/testcases/generator_test.c +++ b/Source/charon/testcases/generator_test.c @@ -32,6 +32,7 @@ #include "../payloads/encodings.h" #include "../payloads/ike_header.h" #include "../payloads/transform_attribute.h" +#include "../payloads/transform_substructure.h" /* * Described in Header @@ -138,7 +139,7 @@ void test_generator_with_transform_attribute(tester_t *tester) chunk_t generated_data; logger_t *logger; - logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"header payload"); + logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"transform_attribute payload"); /* test empty attribute */ @@ -226,3 +227,84 @@ void test_generator_with_transform_attribute(tester_t *tester) global_logger_manager->destroy_logger(global_logger_manager,logger); } + + + +/* + * Described in header + */ +void test_generator_with_transform_substructure(tester_t *tester) +{ + generator_t *generator; + transform_attribute_t *attribute1, *attribute2; + transform_substructure_t *transform; + chunk_t data; + status_t status; + chunk_t generated_data; + logger_t *logger; + + logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"transform substr."); + + /* create generator */ + generator = generator_create(); + tester->assert_true(tester,(generator != NULL), "generator create check"); + + /* create attribute 1 */ + attribute1 = transform_attribute_create(); + char *stringval = "abcd"; + data.ptr = (void *) stringval; + data.len = 4; + status = attribute1->set_value(attribute1,data); + tester->assert_true(tester,(status == SUCCESS),"set_value call check"); + status = attribute1->set_attribute_type(attribute1,0); + tester->assert_true(tester,(status == SUCCESS),"set_attribute_type call check"); + logger->log(logger,CONTROL,"attribute1 created"); + + /* create attribute 2 */ + attribute2 = transform_attribute_create(); + stringval = "efgh"; + data.ptr = (void *) stringval; + data.len = 4; + status = attribute2->set_value(attribute2,data); + tester->assert_true(tester,(status == SUCCESS),"set_value call check"); + status = attribute2->set_attribute_type(attribute2,0); + tester->assert_true(tester,(status == SUCCESS),"set_attribute_type call check"); + logger->log(logger,CONTROL,"attribute2 created"); + + /* create transform */ + transform = transform_substructure_create(); + tester->assert_true(tester,(transform != NULL), "transform create check"); + status = transform->add_transform_attribute(transform,attribute1); + tester->assert_true(tester,(status == SUCCESS),"add_transform_attribute call check"); + status = transform->add_transform_attribute(transform,attribute2); + tester->assert_true(tester,(status == SUCCESS),"add_transform_attribute call check"); + status = transform->set_transform_type(transform,5); /* hex 5 */ + tester->assert_true(tester,(status == SUCCESS),"set_transform_type call check"); + status = transform->set_transform_id(transform,65000); /* hex FDE8 */ + tester->assert_true(tester,(status == SUCCESS),"set_transform_id call check"); + + + logger->log(logger,CONTROL,"transform created"); + + status = generator->generate_payload(generator,(payload_t *)transform); + tester->assert_true(tester,(status == SUCCESS),"generate_payload call check"); + tester->assert_true(tester,(generator->write_to_chunk(generator,&generated_data) == SUCCESS),"write_to_chunk call check"); + logger->log_chunk(logger,RAW,"generated transform",&generated_data); + + u_int8_t expected_generation3[] = { + 0x00,0x00,0x00,0x18, + 0x05,0x00,0xFD,0xE8, + 0x00,0x00,0x00,0x04, + 0x61,0x62,0x63,0x64, + 0x00,0x00,0x00,0x04, + 0x65,0x66,0x67,0x68, + }; + tester->assert_true(tester,(memcmp(expected_generation3,generated_data.ptr,sizeof(expected_generation3)) == 0), "compare generated data"); + + allocator_free_chunk(generated_data); + tester->assert_true(tester,(transform->destroy(transform) == SUCCESS), "transform destroy call check"); + tester->assert_true(tester,(generator->destroy(generator) == SUCCESS), "generator destroy call check"); + + + global_logger_manager->destroy_logger(global_logger_manager,logger); +} diff --git a/Source/charon/testcases/generator_test.h b/Source/charon/testcases/generator_test.h index ac574f450..7031dae93 100644 --- a/Source/charon/testcases/generator_test.h +++ b/Source/charon/testcases/generator_test.h @@ -41,4 +41,14 @@ void test_generator_with_header_payload(tester_t *tester); */ void test_generator_with_transform_attribute(tester_t *tester); + +/** + * @brief Test function used to test the generator with transform substructure payload + * + * + * @param tester associated tester object + */ +void test_generator_with_transform_substructure(tester_t *tester); + + #endif /*GENERATOR_TEST_H_*/ diff --git a/Source/charon/testcases/testcases.c b/Source/charon/testcases/testcases.c index ac5ca5eb2..10f036d7e 100644 --- a/Source/charon/testcases/testcases.c +++ b/Source/charon/testcases/testcases.c @@ -43,7 +43,7 @@ #include "ike_sa_test.h" #include "ike_sa_manager_test.h" #include "generator_test.h" -#include "parser_test.h" +//#include "parser_test.h" #include "packet_test.h" @@ -121,15 +121,25 @@ test_t ike_sa_test = {test_ike_sa,"IKE_SA"}; */ test_t ike_sa_manager_test = {test_ike_sa_manager, "IKE_SA-Manager"}; +/** + * Test 1 for generator_t + */ +test_t generator_test1 = {test_generator_with_header_payload,"Generator: header payload"}; /** * Test 2 for generator_t */ -test_t generator_test2 = {test_generator_with_header_payload,"Generator: header payload"}; +test_t generator_test2 = {test_generator_with_transform_attribute,"Generator: transform attribute"}; + +/** + * Test 3 for generator_t + */ +test_t generator_test3 = {test_generator_with_transform_substructure,"Generator: transform substructure"}; + /** * Test 2 for generator_t */ -test_t parser_test = {test_parser_with_header_payload, "Parser: header payload"}; +//test_t parser_test = {test_parser_with_header_payload, "Parser: header payload"}; /** @@ -182,13 +192,15 @@ logger_manager_t *global_logger_manager; &receiver_test, &ike_sa_id_test, &ike_sa_test, + &generator_test1, &generator_test2, - &parser_test, + &generator_test3, +// &parser_test, &ike_sa_manager_test, &packet_test, NULL }; - global_logger_manager = logger_manager_create(CONTROL); + global_logger_manager = logger_manager_create(ALL); global_socket = socket_create(4600); @@ -200,8 +212,8 @@ logger_manager_t *global_logger_manager; tester_t *tester = tester_create(test_output, FALSE); - tester->perform_tests(tester,all_tests); - //tester->perform_test(tester,&parser_test); + //tester->perform_tests(tester,all_tests); + tester->perform_test(tester,&generator_test3); tester->destroy(tester);