From 2ef11339c720d06215f44555de020ea5ebdfd641 Mon Sep 17 00:00:00 2001 From: Jan Hutter Date: Wed, 30 Nov 2005 17:21:33 +0000 Subject: [PATCH] created class init_config_t encapsulating configuration issues of IKE_SA_INIT phase --- Source/charon/config/Makefile.config | 4 + Source/charon/config/init_config.c | 210 +++++++++++++++++++++++++++++ Source/charon/config/init_config.h | 165 +++++++++++++++++++++++ Source/charon/testcases/Makefile.testcases | 4 +- Source/charon/testcases/init_config_test.c | 128 ++++++++++++++++++ Source/charon/testcases/init_config_test.h | 38 ++++++ Source/charon/testcases/testcases.c | 7 +- 7 files changed, 553 insertions(+), 3 deletions(-) create mode 100644 Source/charon/testcases/init_config_test.c create mode 100644 Source/charon/testcases/init_config_test.h diff --git a/Source/charon/config/Makefile.config b/Source/charon/config/Makefile.config index 977a272..1333a24 100644 --- a/Source/charon/config/Makefile.config +++ b/Source/charon/config/Makefile.config @@ -18,3 +18,7 @@ CONFIG_DIR= $(MAIN_DIR)config/ OBJS+= $(BUILD_DIR)configuration_manager.o $(BUILD_DIR)configuration_manager.o : $(CONFIG_DIR)configuration_manager.c $(CONFIG_DIR)configuration_manager.h $(CC) $(CFLAGS) -c -o $@ $< + +OBJS+= $(BUILD_DIR)init_config.o +$(BUILD_DIR)init_config.o : $(CONFIG_DIR)init_config.c $(CONFIG_DIR)init_config.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/Source/charon/config/init_config.c b/Source/charon/config/init_config.c index e69de29..495feb7 100644 --- a/Source/charon/config/init_config.c +++ b/Source/charon/config/init_config.c @@ -0,0 +1,210 @@ +/** + * @file init_config.c + * + * @brief Implementation of init_config_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 "init_config.h" + +#include +#include + +typedef struct private_init_config_t private_init_config_t; + +/** + * Private data of an init_config_t object + */ +struct private_init_config_t { + + /** + * Public part + */ + init_config_t public; + + /** + * Host information of my host. + */ + host_t *my_host; + + /** + * Host information of other host. + */ + host_t *other_host; + + /** + * Supported proposals + */ + linked_list_t *proposals; +}; + +/** + * Implementation of init_config_t.get_my_host. + */ +static host_t * get_my_host (private_init_config_t *this) +{ + return this->my_host->clone(this->my_host); +} + +/** + * Implementation of init_config_t.get_other_host. + */ +static host_t * get_other_host (private_init_config_t *this) +{ + return this->other_host->clone(this->other_host); +} + +/** + * Implementation of init_config_t.get_dh_group_number. + */ +static diffie_hellman_group_t get_dh_group_number (private_init_config_t *this,size_t priority) +{ + ike_proposal_t *ike_proposal; + + if ((this->proposals->get_count(this->proposals) == 0) || (this->proposals->get_count(this->proposals) < priority)) + { + return MODP_UNDEFINED; + } + + this->proposals->get_at_position(this->proposals,(priority -1),(void **) &ike_proposal); + + return (ike_proposal->diffie_hellman_group); +} + +/** + * Implementation of init_config_t.get_proposals. + */ +static size_t get_proposals (private_init_config_t *this,ike_proposal_t **proposals) +{ + iterator_t *iterator; + ike_proposal_t *current_proposal; + int i = 0; + ike_proposal_t *proposal_array; + + proposal_array = allocator_alloc(this->proposals->get_count(this->proposals) * sizeof(ike_proposal_t)); + + iterator = this->proposals->create_iterator(this->proposals,TRUE); + + while (iterator->has_next(iterator)) + { + iterator->current(iterator,(void **) ¤t_proposal); + proposal_array[i] = (*current_proposal); + i++; + } + iterator->destroy(iterator); + + *proposals = proposal_array; + return this->proposals->get_count(this->proposals); +} + +/** + * Implementation of init_config_t.select_proposal. + */ +static status_t select_proposal (private_init_config_t *this, ike_proposal_t *proposals, size_t proposal_count, ike_proposal_t *selected_proposal) +{ + iterator_t * my_iterator; + int i; + ike_proposal_t *my_current_proposal; + + my_iterator = this->proposals->create_iterator(this->proposals,TRUE); + + + for (i = 0; i < proposal_count; i++) + { + my_iterator->reset(my_iterator); + while (my_iterator->has_next(my_iterator)) + { + my_iterator->current(my_iterator,(void **) &my_current_proposal); + + if (memcmp(my_current_proposal,&proposals[i],sizeof(ike_proposal_t)) == 0) + { + /* found a matching proposal */ + *selected_proposal = *my_current_proposal; + my_iterator->destroy(my_iterator); + return SUCCESS; + } + } + } + + my_iterator->destroy(my_iterator); + return NOT_FOUND; +} + +/** + * Implementation of init_config_t.destroy. + */ +static void add_proposal (private_init_config_t *this,size_t priority, ike_proposal_t proposal) +{ + ike_proposal_t * new_proposal = allocator_alloc(sizeof(ike_proposal_t)); + + *new_proposal = proposal; + + + if (priority > this->proposals->get_count(this->proposals)) + { + this->proposals->insert_last(this->proposals,new_proposal); + return; + } + + this->proposals->insert_at_position(this->proposals,(priority - 1),new_proposal); +} + +/** + * Implementation of init_config_t.destroy. + */ +static void destroy (private_init_config_t *this) +{ + ike_proposal_t *proposal; + + while (this->proposals->get_count(this->proposals) > 0) + { + this->proposals->remove_first(this->proposals,(void **) &proposal); + allocator_free(proposal); + } + this->proposals->destroy(this->proposals); + + this->my_host->destroy(this->my_host); + this->other_host->destroy(this->other_host); + + allocator_free(this); +} + +/** + * Described in header. + */ +init_config_t * init_config_create(char * my_ip, char *other_ip, u_int16_t my_port, u_int16_t other_port) +{ + private_init_config_t *this = allocator_alloc_thing(private_init_config_t); + + /* public functions */ + this->public.get_my_host = (host_t*(*)(init_config_t*))get_my_host; + this->public.get_other_host = (host_t*(*)(init_config_t*))get_other_host; + this->public.get_dh_group_number = (diffie_hellman_group_t (*)(init_config_t*,size_t))get_dh_group_number; + this->public.get_proposals = (size_t(*)(init_config_t*,ike_proposal_t**))get_proposals; + this->public.select_proposal = (status_t(*)(init_config_t*,ike_proposal_t*,size_t,ike_proposal_t*))select_proposal; + this->public.add_proposal = (void(*)(init_config_t*, size_t, ike_proposal_t)) add_proposal; + this->public.destroy = (void(*)(init_config_t*))destroy; + + /* private variables */ + this->my_host = host_create(AF_INET,my_ip, my_port); + this->other_host = host_create(AF_INET,other_ip, other_port); + + this->proposals = linked_list_create(); + + return (&this->public); +} diff --git a/Source/charon/config/init_config.h b/Source/charon/config/init_config.h index 4cf9860..876ead8 100644 --- a/Source/charon/config/init_config.h +++ b/Source/charon/config/init_config.h @@ -1,4 +1,169 @@ +/** + * @file init_config.h + * + * @brief Interface of init_config_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + #ifndef _INIT_CONFIG_H_ #define _INIT_CONFIG_H_ +#include +#include +#include +#include + +typedef struct ike_proposal_t ike_proposal_t; + +/** + * Represents a Proposal used in IKE_SA_INIT phase. + */ +struct ike_proposal_t { + /** + * Encryption algorithm. + * */ + encryption_algorithm_t encryption_algorithm; + + /** + * Key length of encryption algorithm in bytes. + */ + u_int16_t encryption_algorithm_key_length; + + /** + * Integrity algorithm. + */ + integrity_algorithm_t integrity_algorithm; + + /** + * Key length of integrity algorithm + */ + u_int16_t integrity_algorithm_key_length; + + /** + * Pseudo random function (prf). + */ + pseudo_random_function_t pseudo_random_function; + + /** + * Key length of prf. + */ + u_int16_t pseudo_random_function_key_length; + + /** + * Diffie hellman group + */ + diffie_hellman_group_t diffie_hellman_group; +}; + +typedef struct init_config_t init_config_t; + +/** + * Represents a configuration class holding all needed informations for IKE_SA_INIT phase. + * + * @ingroup config + * + */ +struct init_config_t { + + /** + * Get my host information as host_t object. + * + * @warning Object is getting cloned and has to get destroyed by caller. + * + * @param this calling object + * @return host information as host_t object + */ + host_t * (*get_my_host) (init_config_t *this); + + /** + * Get other host information as host_t object. + * + * @warning Object is getting cloned and has to get destroyed by caller. + * + * @param this calling object + * @return host information as host_t object + */ + host_t * (*get_other_host) (init_config_t *this); + + /** + * Get the diffie hellman group to use as initiator with given priority. + * + * + * @param this calling object + * @param priority priority of dh group number (starting at 1) + * @return diffie hellman group number for given priority or + * MODP_UNDEFINED for not supported priorities + */ + diffie_hellman_group_t (*get_dh_group_number) (init_config_t *this,size_t priority); + + /** + * Returns a list of all supported ike_proposals of type ike_proposal_t *. + * + * @warning array of ike_proposal_t has to get destroyed by the caller + * + * @param this calling object + * @param proposals first proposal in a array + * @return number of proposals in array + */ + size_t (*get_proposals) (init_config_t *this,ike_proposal_t **proposals); + + /** + * Adds a proposal with given priority to the current stored proposals + * + * If allready a proposal with given priority is stored the other one is + * moved one priority back. If priority is higher then all other stored + * proposals, it is inserted as last one. + * + * @param this calling object + * @param priority priority of adding proposal + * @param proposal proposal to add + */ + void (*add_proposal) (init_config_t *this,size_t priority, ike_proposal_t proposal); + + /** + * Select a proposed from suggested proposals. + * + * + * @param this calling object + * @param suggested_proposals first proposal in a array + * @param proposal_count number of suggested proposals in array + * @param selected_proposal the ike_proposal_t pointing to is set + * @return + * - SUCCESS if a proposal was selected + * - NOT_FOUND if none of suggested proposals is supported + */ + status_t (*select_proposal) (init_config_t *this, ike_proposal_t *proposals, size_t proposal_count, ike_proposal_t *selected_proposal); + + /** + * Destroys a init_config_t object. + * + * @param this calling object + */ + void (*destroy) (init_config_t *this); +}; + +/** + * Creates a init_config_t object. + * + * @return pointer to created init_config_t object. + * + * @ingroup config + */ +init_config_t * init_config_create(char * my_ip, char *other_ip, u_int16_t my_port, u_int16_t other_port); + #endif //_INIT_CONFIG_H_ diff --git a/Source/charon/testcases/Makefile.testcases b/Source/charon/testcases/Makefile.testcases index abee371..d6027cb 100644 --- a/Source/charon/testcases/Makefile.testcases +++ b/Source/charon/testcases/Makefile.testcases @@ -108,4 +108,6 @@ TEST_OBJS+= $(BUILD_DIR)encryption_payload_test.o $(BUILD_DIR)encryption_payload_test.o : $(TESTCASES_DIR)encryption_payload_test.c $(TESTCASES_DIR)encryption_payload_test.h $(CC) $(CFLAGS) -c -o $@ $< - +TEST_OBJS+= $(BUILD_DIR)init_config_test.o +$(BUILD_DIR)init_config_test.o : $(TESTCASES_DIR)init_config_test.c $(TESTCASES_DIR)init_config_test.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/Source/charon/testcases/init_config_test.c b/Source/charon/testcases/init_config_test.c new file mode 100644 index 0000000..6f69a59 --- /dev/null +++ b/Source/charon/testcases/init_config_test.c @@ -0,0 +1,128 @@ +/** + * @file init_config_test.c + * + * @brief Tests for the init_config_t class. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 "init_config_test.h" + +#include +#include + + +/** + * Described in header. + */ +void test_init_config(tester_t *tester) +{ + init_config_t *init_config = init_config_create("192.168.0.1","192.168.0.2",500,500); + ike_proposal_t prop1, prop2, prop3, prop4, selected_one; + ike_proposal_t *proposal_list; + size_t proposal_count; + status_t status; + + prop1.encryption_algorithm = ENCR_AES_CBC; + prop1.encryption_algorithm_key_length = 20; + prop1.integrity_algorithm = AUTH_HMAC_SHA1_96; + prop1.integrity_algorithm_key_length = 20; + prop1.pseudo_random_function = PRF_HMAC_SHA1; + prop1.pseudo_random_function_key_length = 20; + prop1.diffie_hellman_group = MODP_2048_BIT; + + prop2 = prop1; + prop2.pseudo_random_function = PRF_HMAC_MD5; + prop2.diffie_hellman_group = MODP_1024_BIT; + + prop3 = prop1; + prop3.encryption_algorithm = ENCR_DES; + prop3.diffie_hellman_group = MODP_768_BIT; + + prop4 = prop1; + + prop4.encryption_algorithm = ENCR_3DES; + prop4.pseudo_random_function = PRF_HMAC_TIGER; + + init_config->add_proposal(init_config,1,prop1); + init_config->add_proposal(init_config,1,prop2); + init_config->add_proposal(init_config,3,prop3); + init_config->add_proposal(init_config,2,prop4); + + proposal_count = init_config->get_proposals(init_config,&proposal_list); + + tester->assert_true(tester,(proposal_count == 4), "proposal count check "); + + tester->assert_true(tester,(proposal_list[0].encryption_algorithm == ENCR_AES_CBC), "encryption algorithm check 1"); + tester->assert_true(tester,(proposal_list[0].pseudo_random_function == PRF_HMAC_MD5), "prf check 1"); + + tester->assert_true(tester,(proposal_list[1].encryption_algorithm == ENCR_3DES), "encryption algorithm check 2"); + tester->assert_true(tester,(proposal_list[1].pseudo_random_function == PRF_HMAC_TIGER), "prf check 2"); + + tester->assert_true(tester,(proposal_list[2].encryption_algorithm == ENCR_AES_CBC), "encryption algorithm check 3"); + tester->assert_true(tester,(proposal_list[2].pseudo_random_function == PRF_HMAC_SHA1), "prf check 3"); + + tester->assert_true(tester,(proposal_list[3].encryption_algorithm == ENCR_DES), "encryption algorithm check 4"); + tester->assert_true(tester,(proposal_list[3].pseudo_random_function == PRF_HMAC_SHA1), "prf check 4"); + + + + /* going to check proposals */ + status = init_config->select_proposal(init_config,proposal_list,proposal_count,&selected_one); + tester->assert_true(tester,(status == SUCCESS), "select proposal call check 1"); + + tester->assert_true(tester,(selected_one.encryption_algorithm == ENCR_AES_CBC), "encryption algorithm check"); + tester->assert_true(tester,(selected_one.pseudo_random_function == PRF_HMAC_MD5), "prf check"); + + proposal_list[0].encryption_algorithm = ENCR_DES_IV32; + + status = init_config->select_proposal(init_config,proposal_list,proposal_count,&selected_one); + tester->assert_true(tester,(status == SUCCESS), "select proposal call check 2"); + + tester->assert_true(tester,(selected_one.encryption_algorithm == ENCR_3DES), "encryption algorithm check"); + tester->assert_true(tester,(selected_one.pseudo_random_function == PRF_HMAC_TIGER), "prf check"); + + proposal_list[1].pseudo_random_function = PRF_AES128_CBC; + + status = init_config->select_proposal(init_config,proposal_list,proposal_count,&selected_one); + tester->assert_true(tester,(status == SUCCESS), "select proposal call check 3"); + + tester->assert_true(tester,(selected_one.encryption_algorithm == ENCR_AES_CBC), "encryption algorithm check"); + tester->assert_true(tester,(selected_one.pseudo_random_function == PRF_HMAC_SHA1), "prf check"); + + proposal_list[2].pseudo_random_function = PRF_AES128_CBC; + + status = init_config->select_proposal(init_config,proposal_list,proposal_count,&selected_one); + tester->assert_true(tester,(status == SUCCESS), "select proposal call check 4"); + + tester->assert_true(tester,(selected_one.encryption_algorithm == ENCR_DES), "encryption algorithm check"); + tester->assert_true(tester,(selected_one.pseudo_random_function == PRF_HMAC_SHA1), "prf check"); + + proposal_list[3].pseudo_random_function = PRF_AES128_CBC; + + status = init_config->select_proposal(init_config,proposal_list,proposal_count,&selected_one); + tester->assert_true(tester,(status == NOT_FOUND), "select proposal call check 5"); + + tester->assert_true(tester,(init_config->get_dh_group_number(init_config,1) == MODP_1024_BIT), "get DH group number call check 1"); + tester->assert_true(tester,(init_config->get_dh_group_number(init_config,2) == MODP_2048_BIT), "get DH group number call check 2"); + tester->assert_true(tester,(init_config->get_dh_group_number(init_config,3) == MODP_2048_BIT), "get DH group number call check 3"); + tester->assert_true(tester,(init_config->get_dh_group_number(init_config,4) == MODP_768_BIT), "get DH group number call check 4"); + + allocator_free(proposal_list); + + init_config->destroy(init_config); +} diff --git a/Source/charon/testcases/init_config_test.h b/Source/charon/testcases/init_config_test.h new file mode 100644 index 0000000..c1b6f1d --- /dev/null +++ b/Source/charon/testcases/init_config_test.h @@ -0,0 +1,38 @@ +/** + * @file init_config_test.h + * + * @brief Tests for the init_config_t class. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#ifndef _INIT_CONFIG_TEST_H_ +#define _INIT_CONFIG_TEST_H_ + +#include + +/** + * @brief Test function used to test the init_config_t functionality. + * + * @param tester associated tester_t object + * + * @ingroup testcases + */ +void test_init_config(tester_t *tester); + +#endif //_INIT_CONFIG_TEST_H_ diff --git a/Source/charon/testcases/testcases.c b/Source/charon/testcases/testcases.c index 23a6e0a..45aa477 100644 --- a/Source/charon/testcases/testcases.c +++ b/Source/charon/testcases/testcases.c @@ -56,6 +56,7 @@ #include #include #include +#include /* output for test messages */ extern FILE * stderr; @@ -104,6 +105,7 @@ test_t aes_cbc_crypter_test = {test_aes_cbc_crypter, "AES CBC"}; test_t hmac_signer_test1 = {test_hmac_md5_signer, "HMAC MD5 signer test"}; test_t hmac_signer_test2 = {test_hmac_sha1_signer, "HMAC SHA1 signer test"}; test_t encryption_payload_test = {test_encryption_payload, "encryption payload test"}; +test_t init_config_test = {test_init_config, "init_config_t test"}; daemon_t* charon; @@ -197,6 +199,7 @@ int main() &hmac_signer_test1, &hmac_signer_test2, &encryption_payload_test, + &init_config_test, NULL }; @@ -207,8 +210,8 @@ int main() tester_t *tester = tester_create(test_output, FALSE); - tester->perform_tests(tester,all_tests); - //tester->perform_test(tester,&encryption_payload_test); + //tester->perform_tests(tester,all_tests); + tester->perform_test(tester,&init_config_test); tester->destroy(tester); -- 2.7.4