From ec1ebb2377add71ef45c81d717aa9a83bd38b86c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Feb 2018 08:12:48 +0100 Subject: [PATCH 1/5] transform: Move internal identifiers out of private range Avoid any conflicts if implementations use transform types in the private range. Also removed the unused UNKNOWN_TRANSFORM_TYPE identifier. --- src/libstrongswan/crypto/transform.c | 20 +++++++++----------- src/libstrongswan/crypto/transform.h | 13 ++++++------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/libstrongswan/crypto/transform.c b/src/libstrongswan/crypto/transform.c index 808cb996e..2875fbb65 100644 --- a/src/libstrongswan/crypto/transform.c +++ b/src/libstrongswan/crypto/transform.c @@ -17,21 +17,20 @@ #include #include -ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, EXTENDED_OUTPUT_FUNCTION, - "UNDEFINED_TRANSFORM_TYPE", - "HASH_ALGORITHM", - "RANDOM_NUMBER_GENERATOR", - "AEAD_ALGORITHM", - "COMPRESSION_ALGORITHM", - "EXTENDED OUTPUT FUNCTION"); -ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, - EXTENDED_OUTPUT_FUNCTION, +ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, "ENCRYPTION_ALGORITHM", "PSEUDO_RANDOM_FUNCTION", "INTEGRITY_ALGORITHM", "DIFFIE_HELLMAN_GROUP", "EXTENDED_SEQUENCE_NUMBERS"); -ENUM_END(transform_type_names, EXTENDED_SEQUENCE_NUMBERS); +ENUM_NEXT(transform_type_names, HASH_ALGORITHM, EXTENDED_OUTPUT_FUNCTION, + EXTENDED_SEQUENCE_NUMBERS, + "HASH_ALGORITHM", + "RANDOM_NUMBER_GENERATOR", + "AEAD_ALGORITHM", + "COMPRESSION_ALGORITHM", + "EXTENDED OUTPUT FUNCTION"); +ENUM_END(transform_type_names, EXTENDED_OUTPUT_FUNCTION); ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, @@ -64,7 +63,6 @@ enum_name_t* transform_get_enum_names(transform_type_t type) return extended_sequence_numbers_names; case EXTENDED_OUTPUT_FUNCTION: return ext_out_function_names; - case UNDEFINED_TRANSFORM_TYPE: case COMPRESSION_ALGORITHM: break; } diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h index e043e605c..9181655e3 100644 --- a/src/libstrongswan/crypto/transform.h +++ b/src/libstrongswan/crypto/transform.h @@ -29,17 +29,16 @@ typedef enum transform_type_t transform_type_t; * Type of a transform, as in IKEv2 RFC 3.3.2. */ enum transform_type_t { - UNDEFINED_TRANSFORM_TYPE = 241, - HASH_ALGORITHM = 242, - RANDOM_NUMBER_GENERATOR = 243, - AEAD_ALGORITHM = 244, - COMPRESSION_ALGORITHM = 245, - EXTENDED_OUTPUT_FUNCTION = 246, ENCRYPTION_ALGORITHM = 1, PSEUDO_RANDOM_FUNCTION = 2, INTEGRITY_ALGORITHM = 3, DIFFIE_HELLMAN_GROUP = 4, - EXTENDED_SEQUENCE_NUMBERS = 5 + EXTENDED_SEQUENCE_NUMBERS = 5, + HASH_ALGORITHM = 256, + RANDOM_NUMBER_GENERATOR = 257, + AEAD_ALGORITHM = 258, + COMPRESSION_ALGORITHM = 259, + EXTENDED_OUTPUT_FUNCTION = 260, }; /** From cc55461c8d54dff66c89d754286b98524ba33957 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Feb 2018 08:36:33 +0100 Subject: [PATCH 2/5] proposal: Keep track of contained transform types --- src/libstrongswan/crypto/proposal/proposal.c | 86 +++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index bb0a02b59..be519c256 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -57,6 +57,11 @@ struct private_proposal_t { */ array_t *transforms; + /** + * Types of transforms contained, as transform_type_t + */ + array_t *types; + /** * senders SPI */ @@ -68,6 +73,57 @@ struct private_proposal_t { u_int number; }; +/** + * Sort transform types + */ +static int type_sort(const void *a, const void *b, void *user) +{ + const transform_type_t *ta = a, *tb = b; + return *ta - *tb; +} + +/** + * Find a transform type + */ +static int type_find(const void *a, const void *b) +{ + return type_sort(a, b, NULL); +} + +/** + * Check if the given transform type is already in the set + */ +static bool contains_type(private_proposal_t *this, transform_type_t type) +{ + return array_bsearch(this->types, &type, type_find, NULL) != -1; +} + +/** + * Add the given transform type to the set + */ +static void add_type(private_proposal_t *this, transform_type_t type) +{ + if (!contains_type(this, type)) + { + array_insert(this->types, ARRAY_TAIL, &type); + array_sort(this->types, type_sort, NULL); + } +} + +/** + * Remove the given transform type from the set + */ +static void remove_type(private_proposal_t *this, transform_type_t type) +{ + int i; + + i = array_bsearch(this->types, &type, type_find, NULL); + if (i >= 0) + { + array_remove(this->types, i, NULL); + } +} + /** * Struct used to store different kinds of algorithms. */ @@ -91,6 +147,7 @@ METHOD(proposal_t, add_algorithm, void, }; array_insert(this->transforms, ARRAY_TAIL, &entry); + add_type(this, type); } CALLBACK(alg_filter, bool, @@ -206,17 +263,29 @@ METHOD(proposal_t, strip_dh, void, { enumerator_t *enumerator; entry_t *entry; + bool found = FALSE; enumerator = array_create_enumerator(this->transforms); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->type == DIFFIE_HELLMAN_GROUP && - entry->alg != keep) + if (entry->type == DIFFIE_HELLMAN_GROUP) { - array_remove_at(this->transforms, enumerator); + if (entry->alg != keep) + { + array_remove_at(this->transforms, enumerator); + } + else + { + found = TRUE; + } } } enumerator->destroy(enumerator); + + if (keep == MODP_NONE || !found) + { + remove_type(this, DIFFIE_HELLMAN_GROUP); + } } /** @@ -427,6 +496,7 @@ METHOD(proposal_t, clone_, proposal_t*, private_proposal_t *clone; enumerator_t *enumerator; entry_t *entry; + transform_type_t *type; clone = (private_proposal_t*)proposal_create(this->protocol, 0); @@ -436,6 +506,12 @@ METHOD(proposal_t, clone_, proposal_t*, array_insert(clone->transforms, ARRAY_TAIL, entry); } enumerator->destroy(enumerator); + enumerator = array_create_enumerator(this->types); + while (enumerator->enumerate(enumerator, &type)) + { + array_insert(clone->types, ARRAY_TAIL, type); + } + enumerator->destroy(enumerator); clone->spi = this->spi; clone->number = this->number; @@ -479,6 +555,7 @@ static void remove_transform(private_proposal_t *this, transform_type_t type) } } e->destroy(e); + remove_type(this, type); } /** @@ -605,6 +682,7 @@ static bool check_proposal(private_proposal_t *this) } } e->destroy(e); + remove_type(this, ENCRYPTION_ALGORITHM); if (!get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL)) { @@ -730,6 +808,7 @@ METHOD(proposal_t, destroy, void, private_proposal_t *this) { array_destroy(this->transforms); + array_destroy(this->types); free(this); } @@ -760,6 +839,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number) .protocol = protocol, .number = number, .transforms = array_create(sizeof(entry_t), 0), + .types = array_create(sizeof(transform_type_t), 0), ); return &this->public; From 5eb094df1103cc7d527c1b6c280f5b5e259e8b69 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Feb 2018 08:43:07 +0100 Subject: [PATCH 3/5] proposal: Print all algorithms even those with currently unknown transform types --- src/libstrongswan/crypto/proposal/proposal.c | 71 +++++++++++++------ .../tests/suites/test_proposal.c | 22 ++++++ 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index be519c256..7e5486577 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -73,13 +73,31 @@ struct private_proposal_t { u_int number; }; +/** + * This is a hack to not change the previous order when printing proposals + */ +static transform_type_t type_for_sort(const void *type) +{ + const transform_type_t *t = type; + + switch (*t) + { + case PSEUDO_RANDOM_FUNCTION: + return INTEGRITY_ALGORITHM; + case INTEGRITY_ALGORITHM: + return PSEUDO_RANDOM_FUNCTION; + default: + return *t; + } +} + /** * Sort transform types */ static int type_sort(const void *a, const void *b, void *user) { - const transform_type_t *ta = a, *tb = b; - return *ta - *tb; + transform_type_t ta = type_for_sort(a), tb = type_for_sort(b); + return ta - tb; } /** @@ -724,30 +742,44 @@ static bool add_string_algo(private_proposal_t *this, const char *alg) } /** - * print all algorithms of a kind to buffer + * Print all algorithms of the given type */ static int print_alg(private_proposal_t *this, printf_hook_data_t *data, - u_int kind, void *names, bool *first) + transform_type_t type, bool *first) { enumerator_t *enumerator; size_t written = 0; - uint16_t alg, size; + entry_t *entry; + enum_name_t *names; - enumerator = create_enumerator(this, kind); - while (enumerator->enumerate(enumerator, &alg, &size)) + names = transform_get_enum_names(type); + + enumerator = array_create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &entry)) { + char *prefix = "/"; + + if (type != entry->type) + { + continue; + } if (*first) { - written += print_in_hook(data, "%N", names, alg); + prefix = ""; *first = FALSE; } + if (names) + { + written += print_in_hook(data, "%s%N", prefix, names, entry->alg); + } else { - written += print_in_hook(data, "/%N", names, alg); + written += print_in_hook(data, "%sUNKNOWN_%u_%u", prefix, + entry->type, entry->alg); } - if (size) + if (entry->key_size) { - written += print_in_hook(data, "_%u", size); + written += print_in_hook(data, "_%u", entry->key_size); } } enumerator->destroy(enumerator); @@ -763,6 +795,7 @@ int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, private_proposal_t *this = *((private_proposal_t**)(args[0])); linked_list_t *list = *((linked_list_t**)(args[0])); enumerator_t *enumerator; + transform_type_t *type; size_t written = 0; bool first = TRUE; @@ -791,16 +824,12 @@ int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, } written = print_in_hook(data, "%N:", protocol_id_names, this->protocol); - written += print_alg(this, data, ENCRYPTION_ALGORITHM, - encryption_algorithm_names, &first); - written += print_alg(this, data, INTEGRITY_ALGORITHM, - integrity_algorithm_names, &first); - written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION, - pseudo_random_function_names, &first); - written += print_alg(this, data, DIFFIE_HELLMAN_GROUP, - diffie_hellman_group_names, &first); - written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS, - extended_sequence_numbers_names, &first); + enumerator = array_create_enumerator(this->types); + while (enumerator->enumerate(enumerator, &type)) + { + written += print_alg(this, data, *type, &first); + } + enumerator->destroy(enumerator); return written; } diff --git a/src/libstrongswan/tests/suites/test_proposal.c b/src/libstrongswan/tests/suites/test_proposal.c index 1a2f97d5f..947c32159 100644 --- a/src/libstrongswan/tests/suites/test_proposal.c +++ b/src/libstrongswan/tests/suites/test_proposal.c @@ -194,6 +194,24 @@ START_TEST(test_promote_dh_group_not_contained) } END_TEST +START_TEST(test_unknown_transform_types_print) +{ + proposal_t *proposal; + + proposal = proposal_create(PROTO_IKE, 0); + proposal->add_algorithm(proposal, 242, 42, 128); + assert_proposal_eq(proposal, "IKE:UNKNOWN_242_42_128"); + proposal->destroy(proposal); + + proposal = proposal_create_from_string(PROTO_IKE, + "aes128-sha256-modp3072-ecp256"); + proposal->add_algorithm(proposal, 242, 42, 128); + proposal->add_algorithm(proposal, 243, 1, 0); + assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256/UNKNOWN_242_42_128/UNKNOWN_243_1"); + proposal->destroy(proposal); +} +END_TEST + Suite *proposal_suite_create() { Suite *s; @@ -216,5 +234,9 @@ Suite *proposal_suite_create() tcase_add_test(tc, test_promote_dh_group_not_contained); suite_add_tcase(s, tc); + tc = tcase_create("unknown transform types"); + tcase_add_test(tc, test_unknown_transform_types_print); + suite_add_tcase(s, tc); + return s; } From 76c7c951e11f7a4ed637c174c9f5b8dc22f2241a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Feb 2018 09:02:49 +0100 Subject: [PATCH 4/5] proposal: Make sure to consider all transform types when selecting proposals This way there will be a mismatch if one of the proposals contains transform types not contained in the other (the fix list of transform types used previously resulted in a match if unknown transform types were contained in one of the proposals). Merging the sets of types makes comparing proposals with optional transform types easier (e.g. DH for ESP with MODP_NONE). --- src/libstrongswan/crypto/proposal/proposal.c | 61 ++++++++++++++----- .../tests/suites/test_proposal.c | 59 +++++++++++++++++- 2 files changed, 103 insertions(+), 17 deletions(-) diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index 7e5486577..1fb6ee6d9 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -111,23 +111,49 @@ static int type_find(const void *a, const void *b) /** * Check if the given transform type is already in the set */ -static bool contains_type(private_proposal_t *this, transform_type_t type) +static bool contains_type(array_t *types, transform_type_t type) { - return array_bsearch(this->types, &type, type_find, NULL) != -1; + return array_bsearch(types, &type, type_find, NULL) != -1; } /** * Add the given transform type to the set */ -static void add_type(private_proposal_t *this, transform_type_t type) +static void add_type(array_t *types, transform_type_t type) { - if (!contains_type(this, type)) + if (!contains_type(types, type)) { - array_insert(this->types, ARRAY_TAIL, &type); - array_sort(this->types, type_sort, NULL); + array_insert(types, ARRAY_TAIL, &type); + array_sort(types, type_sort, NULL); } } +/** + * Merge two sets of transform types into a new array + */ +static array_t *merge_types(private_proposal_t *this, private_proposal_t *other) +{ + array_t *types; + transform_type_t type; + int i, count; + + count = max(array_count(this->types), array_count(other->types)); + types = array_create(sizeof(transform_type_t), count); + + for (i = 0; i < count; i++) + { + if (array_get(this->types, i, &type)) + { + add_type(types, type); + } + if (array_get(other->types, i, &type)) + { + add_type(types, type); + } + } + return types; +} + /** * Remove the given transform type from the set */ @@ -165,7 +191,7 @@ METHOD(proposal_t, add_algorithm, void, }; array_insert(this->transforms, ARRAY_TAIL, &entry); - add_type(this, type); + add_type(this->types, type); } CALLBACK(alg_filter, bool, @@ -397,6 +423,9 @@ METHOD(proposal_t, select_proposal, proposal_t*, bool private) { proposal_t *selected; + transform_type_t type; + array_t *types; + int i; DBG2(DBG_CFG, "selecting proposal:"); @@ -415,18 +444,20 @@ METHOD(proposal_t, select_proposal, proposal_t*, { selected = proposal_create(this->protocol, this->number); selected->set_spi(selected, this->spi); - } - if (!select_algo(this, other, selected, ENCRYPTION_ALGORITHM, private) || - !select_algo(this, other, selected, PSEUDO_RANDOM_FUNCTION, private) || - !select_algo(this, other, selected, INTEGRITY_ALGORITHM, private) || - !select_algo(this, other, selected, DIFFIE_HELLMAN_GROUP, private) || - !select_algo(this, other, selected, EXTENDED_SEQUENCE_NUMBERS, private)) + types = merge_types(this, (private_proposal_t*)other); + for (i = 0; i < array_count(types); i++) { - selected->destroy(selected); - return NULL; + array_get(types, i, &type); + if (!select_algo(this, other, selected, type, private)) + { + selected->destroy(selected); + array_destroy(types); + return NULL; + } } + array_destroy(types); DBG2(DBG_CFG, " proposal matches"); return selected; diff --git a/src/libstrongswan/tests/suites/test_proposal.c b/src/libstrongswan/tests/suites/test_proposal.c index 947c32159..9f8cc7e1f 100644 --- a/src/libstrongswan/tests/suites/test_proposal.c +++ b/src/libstrongswan/tests/suites/test_proposal.c @@ -204,14 +204,66 @@ START_TEST(test_unknown_transform_types_print) proposal->destroy(proposal); proposal = proposal_create_from_string(PROTO_IKE, - "aes128-sha256-modp3072-ecp256"); + "aes128-sha256-ecp256"); proposal->add_algorithm(proposal, 242, 42, 128); proposal->add_algorithm(proposal, 243, 1, 0); - assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256/UNKNOWN_242_42_128/UNKNOWN_243_1"); + assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128/UNKNOWN_243_1"); proposal->destroy(proposal); } END_TEST +START_TEST(test_unknown_transform_types_select_fail) +{ + proposal_t *self, *other, *selected; + + self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other->add_algorithm(other, 242, 42, 0); + + selected = self->select(self, other, TRUE, FALSE); + ck_assert(!selected); + other->destroy(other); + self->destroy(self); +} +END_TEST + +START_TEST(test_unknown_transform_types_select_fail_subtype) +{ + proposal_t *self, *other, *selected; + + self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + self->add_algorithm(self, 242, 8, 0); + other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other->add_algorithm(other, 242, 42, 0); + + selected = self->select(self, other, TRUE, FALSE); + ck_assert(!selected); + other->destroy(other); + self->destroy(self); +} +END_TEST + +START_TEST(test_unknown_transform_types_select_success) +{ + proposal_t *self, *other, *selected; + + self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + self->add_algorithm(self, 242, 42, 128); + other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other->add_algorithm(other, 242, 42, 128); + other->add_algorithm(other, 242, 1, 0); + + selected = self->select(self, other, TRUE, FALSE); + ck_assert(selected); + assert_proposal_eq(selected, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128"); + selected->destroy(selected); + other->destroy(other); + self->destroy(self); +} +END_TEST + + + Suite *proposal_suite_create() { Suite *s; @@ -236,6 +288,9 @@ Suite *proposal_suite_create() tc = tcase_create("unknown transform types"); tcase_add_test(tc, test_unknown_transform_types_print); + tcase_add_test(tc, test_unknown_transform_types_select_fail); + tcase_add_test(tc, test_unknown_transform_types_select_fail_subtype); + tcase_add_test(tc, test_unknown_transform_types_select_success); suite_add_tcase(s, tc); return s; From 6b8749ab18ac53eba2db81d7938e07dfcd9af4e0 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 23 Feb 2018 09:59:38 +0100 Subject: [PATCH 5/5] proposal: Compare algorithms of all transform types for equality --- src/libstrongswan/crypto/proposal/proposal.c | 23 ++++++++++++++----- .../tests/suites/test_proposal.c | 18 +++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index 1fb6ee6d9..c18915fd7 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -527,16 +527,27 @@ METHOD(proposal_t, get_number, u_int, METHOD(proposal_t, equals, bool, private_proposal_t *this, proposal_t *other) { + transform_type_t type; + array_t *types; + int i; + if (&this->public == other) { return TRUE; } - return ( - algo_list_equals(this, other, ENCRYPTION_ALGORITHM) && - algo_list_equals(this, other, INTEGRITY_ALGORITHM) && - algo_list_equals(this, other, PSEUDO_RANDOM_FUNCTION) && - algo_list_equals(this, other, DIFFIE_HELLMAN_GROUP) && - algo_list_equals(this, other, EXTENDED_SEQUENCE_NUMBERS)); + + types = merge_types(this, (private_proposal_t*)other); + for (i = 0; i < array_count(types); i++) + { + array_get(types, i, &type); + if (!algo_list_equals(this, other, type)) + { + array_destroy(types); + return FALSE; + } + } + array_destroy(types); + return TRUE; } METHOD(proposal_t, clone_, proposal_t*, diff --git a/src/libstrongswan/tests/suites/test_proposal.c b/src/libstrongswan/tests/suites/test_proposal.c index 9f8cc7e1f..4e235861c 100644 --- a/src/libstrongswan/tests/suites/test_proposal.c +++ b/src/libstrongswan/tests/suites/test_proposal.c @@ -212,6 +212,23 @@ START_TEST(test_unknown_transform_types_print) } END_TEST +START_TEST(test_unknown_transform_types_equals) +{ + proposal_t *self, *other; + + self = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other = proposal_create_from_string(PROTO_IKE, "aes128-sha256-ecp256"); + other->add_algorithm(other, 242, 42, 0); + ck_assert(!self->equals(self, other)); + ck_assert(!other->equals(other, self)); + self->add_algorithm(self, 242, 42, 0); + ck_assert(self->equals(self, other)); + ck_assert(other->equals(other, self)); + other->destroy(other); + self->destroy(self); +} +END_TEST + START_TEST(test_unknown_transform_types_select_fail) { proposal_t *self, *other, *selected; @@ -288,6 +305,7 @@ Suite *proposal_suite_create() tc = tcase_create("unknown transform types"); tcase_add_test(tc, test_unknown_transform_types_print); + tcase_add_test(tc, test_unknown_transform_types_equals); tcase_add_test(tc, test_unknown_transform_types_select_fail); tcase_add_test(tc, test_unknown_transform_types_select_fail_subtype); tcase_add_test(tc, test_unknown_transform_types_select_success);