diff options
Diffstat (limited to 'src/charon/encoding')
-rw-r--r-- | src/charon/encoding/message.c | 8 | ||||
-rw-r--r-- | src/charon/encoding/payloads/notify_payload.c | 76 | ||||
-rw-r--r-- | src/charon/encoding/payloads/notify_payload.h | 37 | ||||
-rw-r--r-- | src/charon/encoding/payloads/proposal_substructure.c | 59 | ||||
-rw-r--r-- | src/charon/encoding/payloads/proposal_substructure.h | 25 | ||||
-rw-r--r-- | src/charon/encoding/payloads/sa_payload.c | 64 |
6 files changed, 152 insertions, 117 deletions
diff --git a/src/charon/encoding/message.c b/src/charon/encoding/message.c index 8a7998e66..db6d6ea5d 100644 --- a/src/charon/encoding/message.c +++ b/src/charon/encoding/message.c @@ -187,7 +187,7 @@ static payload_rule_t informational_r_payload_rules[] = { /** * Message rule for CREATE_CHILD_SA from initiator. */ -static payload_rule_t create_child_sa_r_payload_rules[] = { +static payload_rule_t create_child_sa_i_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, {NONCE,1,1,TRUE,FALSE}, @@ -200,7 +200,7 @@ static payload_rule_t create_child_sa_r_payload_rules[] = { /** * Message rule for CREATE_CHILD_SA from responder. */ -static payload_rule_t create_child_sa_i_payload_rules[] = { +static payload_rule_t create_child_sa_r_payload_rules[] = { {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE}, {SECURITY_ASSOCIATION,1,1,TRUE,FALSE}, {NONCE,1,1,TRUE,FALSE}, @@ -220,7 +220,9 @@ static message_rule_t message_rules[] = { {IKE_AUTH,TRUE,TRUE,(sizeof(ike_auth_i_payload_rules)/sizeof(payload_rule_t)),ike_auth_i_payload_rules}, {IKE_AUTH,FALSE,TRUE,(sizeof(ike_auth_r_payload_rules)/sizeof(payload_rule_t)),ike_auth_r_payload_rules}, {INFORMATIONAL,TRUE,TRUE,(sizeof(informational_i_payload_rules)/sizeof(payload_rule_t)),informational_i_payload_rules}, - {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules} + {INFORMATIONAL,FALSE,TRUE,(sizeof(informational_r_payload_rules)/sizeof(payload_rule_t)),informational_r_payload_rules}, + {CREATE_CHILD_SA,TRUE,TRUE,(sizeof(create_child_sa_i_payload_rules)/sizeof(payload_rule_t)),create_child_sa_i_payload_rules}, + {CREATE_CHILD_SA,FALSE,TRUE,(sizeof(create_child_sa_r_payload_rules)/sizeof(payload_rule_t)),create_child_sa_r_payload_rules}, }; diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c index a4062cf42..a09e33778 100644 --- a/src/charon/encoding/payloads/notify_payload.c +++ b/src/charon/encoding/payloads/notify_payload.c @@ -173,12 +173,25 @@ encoding_rule_t notify_payload_encodings[] = { */ static status_t verify(private_notify_payload_t *this) { - if (this->protocol_id > 3) + switch (this->protocol_id) { - /* reserved for future use */ - return FAILED; + case PROTO_IKE: + if (this->spi.len != 8) + { + return FAILED; + } + break; + case PROTO_AH: + case PROTO_ESP: + if (this->spi.len != 4) + { + return FAILED; + } + break; + default: + return FAILED; } - + /* TODO: Check all kinds of notify */ if (this->notify_message_type == INVALID_KE_PAYLOAD) @@ -265,9 +278,7 @@ static void compute_length (private_notify_payload_t *this) { length += this->spi.len; } - this->payload_length = length; - } /** @@ -289,7 +300,7 @@ static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id /** * Implementation of notify_payload_t.get_notify_message_type. */ -static u_int16_t get_notify_message_type(private_notify_payload_t *this) +static notify_message_type_t get_notify_message_type(private_notify_payload_t *this) { return this->notify_message_type; } @@ -305,32 +316,42 @@ static void set_notify_message_type(private_notify_payload_t *this, u_int16_t no /** * Implementation of notify_payload_t.get_spi. */ -static chunk_t get_spi(private_notify_payload_t *this) +static u_int64_t get_spi(private_notify_payload_t *this) { - return (this->spi); + switch (this->protocol_id) + { + case PROTO_IKE: + return *((u_int64_t*)this->spi.ptr); + case PROTO_AH: + case PROTO_ESP: + return *((u_int32_t*)this->spi.ptr); + default: + return 0; + } } /** * Implementation of notify_payload_t.set_spi. */ -static void set_spi(private_notify_payload_t *this, chunk_t spi) +static void set_spi(private_notify_payload_t *this, u_int64_t spi) { - /* destroy existing data first */ - if (this->spi.ptr != NULL) + chunk_free(&this->spi); + switch (this->protocol_id) { - /* free existing value */ - free(this->spi.ptr); - this->spi.ptr = NULL; - this->spi.len = 0; - + case PROTO_IKE: + this->spi = chunk_alloc(8); + *((u_int64_t*)this->spi.ptr) = spi; + break; + case PROTO_AH: + case PROTO_ESP: + this->spi = chunk_alloc(4); + *((u_int32_t*)this->spi.ptr) = spi; + break; + default: + break; } - - this->spi.ptr = clalloc(spi.ptr,spi.len); - - this->spi.len = spi.len; - this->spi_size = spi.len; + this->spi_size = this->spi.len; this->compute_length(this); - } /** @@ -376,7 +397,6 @@ static status_t destroy(private_notify_payload_t *this) { free(this->spi.ptr); } - free(this); return SUCCESS; } @@ -400,10 +420,10 @@ notify_payload_t *notify_payload_create() /* public functions */ this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id; this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id; - this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type; - this->public.set_notify_message_type = (void (*) (notify_payload_t *,u_int16_t)) set_notify_message_type; - this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi; - this->public.set_spi = (void (*) (notify_payload_t *,chunk_t)) set_spi; + this->public.get_notify_message_type = (notify_message_type_t (*) (notify_payload_t *)) get_notify_message_type; + this->public.set_notify_message_type = (void (*) (notify_payload_t *,notify_message_type_t)) set_notify_message_type; + this->public.get_spi = (u_int64_t (*) (notify_payload_t *)) get_spi; + this->public.set_spi = (void (*) (notify_payload_t *,u_int64_t)) set_spi; this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data; this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data; this->public.destroy = (void (*) (notify_payload_t *)) destroy; diff --git a/src/charon/encoding/payloads/notify_payload.h b/src/charon/encoding/payloads/notify_payload.h index ab86a6d53..ef425f314 100644 --- a/src/charon/encoding/payloads/notify_payload.h +++ b/src/charon/encoding/payloads/notify_payload.h @@ -64,7 +64,8 @@ enum notify_message_type_t { INVALID_SELECTORS = 39, INITIAL_CONTACT = 16384, - SET_WINDOW_SIZE = 16385 + SET_WINDOW_SIZE = 16385, + REKEY_SA = 16393, }; /** @@ -107,46 +108,42 @@ struct notify_payload_t { /** * @brief Sets the protocol id of this payload. * - * @param this calling notify_payload_t object - * @param protocol_id protocol id to set + * @param this calling notify_payload_t object + * @param protocol_id protocol id to set */ void (*set_protocol_id) (notify_payload_t *this, u_int8_t protocol_id); /** * @brief Gets the notify message type of this payload. * - * @param this calling notify_payload_t object - * @return notify message type of this payload + * @param this calling notify_payload_t object + * @return notify message type of this payload */ - u_int16_t (*get_notify_message_type) (notify_payload_t *this); + notify_message_type_t (*get_notify_message_type) (notify_payload_t *this); /** * @brief Sets notify message type of this payload. * - * @param this calling notify_payload_t object - * @param notify_message_type notify message type to set + * @param this calling notify_payload_t object + * @param type notify message type to set */ - void (*set_notify_message_type) (notify_payload_t *this, u_int16_t notify_message_type); + void (*set_notify_message_type) (notify_payload_t *this, notify_message_type_t type); /** * @brief Returns the currently set spi of this payload. - * - * @warning Returned data are not copied. - * + * * @param this calling notify_payload_t object - * @return chunk_t pointing to the value + * @return SPI value */ - chunk_t (*get_spi) (notify_payload_t *this); + u_int64_t (*get_spi) (notify_payload_t *this); /** * @brief Sets the spi of this payload. - * - * @warning Value is getting copied. * - * @param this calling notify_payload_t object - * @param spi chunk_t pointing to the value to set + * @param this calling notify_payload_t object + * @param spi SPI value */ - void (*set_spi) (notify_payload_t *this, chunk_t spi); + void (*set_spi) (notify_payload_t *this, u_int64_t spi); /** * @brief Returns the currently set notification data of payload. @@ -163,7 +160,7 @@ struct notify_payload_t { * * @warning Value is getting copied. * - * @param this calling notify_payload_t object + * @param this calling notify_payload_t object * @param notification_data chunk_t pointing to the value to set */ void (*set_notification_data) (notify_payload_t *this, chunk_t notification_data); diff --git a/src/charon/encoding/payloads/proposal_substructure.c b/src/charon/encoding/payloads/proposal_substructure.c index cb3c695b2..f72fbb1c2 100644 --- a/src/charon/encoding/payloads/proposal_substructure.c +++ b/src/charon/encoding/payloads/proposal_substructure.c @@ -61,7 +61,7 @@ struct private_proposal_substructure_t { /** * Proposal number. */ - u_int8_t proposal_number; + u_int8_t proposal_number; /** * Protocol ID. @@ -404,14 +404,17 @@ static size_t get_spi_size (private_proposal_substructure_t *this) } /** - * Implementation of proposal_substructure_t.add_to_proposal. + * Implementation of proposal_substructure_t.get_proposal. */ -void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal) +proposal_t* get_proposal(private_proposal_substructure_t *this) { - iterator_t *iterator = this->transforms->create_iterator(this->transforms, TRUE); - u_int32_t spi; + iterator_t *iterator; + proposal_t *proposal; + u_int64_t spi; + proposal = proposal_create(this->protocol_id); + iterator = this->transforms->create_iterator(this->transforms, TRUE); while (iterator->has_next(iterator)) { transform_substructure_t *transform; @@ -425,13 +428,24 @@ void add_to_proposal(private_proposal_substructure_t *this, proposal_t *proposal transform_id = transform->get_transform_id(transform); transform->get_key_length(transform, &key_length); - proposal->add_algorithm(proposal, this->protocol_id, transform_type, transform_id, key_length); + proposal->add_algorithm(proposal, transform_type, transform_id, key_length); } iterator->destroy(iterator); - spi = *((u_int32_t*)this->spi.ptr); + switch (this->spi.len) + { + case 4: + spi = *((u_int32_t*)this->spi.ptr); + break; + case 8: + spi = *((u_int64_t*)this->spi.ptr); + break; + default: + spi = 0; + } + proposal->set_spi(proposal, spi); - proposal->set_spi(proposal, this->protocol_id, spi); + return proposal; } /** @@ -527,7 +541,7 @@ proposal_substructure_t *proposal_substructure_create() this->public.get_protocol_id = (u_int8_t (*) (proposal_substructure_t *)) get_protocol_id; this->public.get_info_for_transform_type = (status_t (*) (proposal_substructure_t *,transform_type_t,u_int16_t *, u_int16_t *))get_info_for_transform_type; this->public.set_is_last_proposal = (void (*) (proposal_substructure_t *,bool)) set_is_last_proposal; - this->public.add_to_proposal = (void (*) (proposal_substructure_t*,proposal_t*))add_to_proposal; + this->public.get_proposal = (proposal_t* (*) (proposal_substructure_t*))get_proposal; this->public.set_spi = (void (*) (proposal_substructure_t *,chunk_t))set_spi; this->public.get_spi = (chunk_t (*) (proposal_substructure_t *)) get_spi; this->public.get_transform_count = (size_t (*) (proposal_substructure_t *)) get_transform_count; @@ -556,7 +570,7 @@ proposal_substructure_t *proposal_substructure_create() /* * Described in header. */ -proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto) +proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal) { private_proposal_substructure_t *this = (private_proposal_substructure_t*)proposal_substructure_create(); iterator_t *iterator; @@ -564,7 +578,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * transform_substructure_t *transform; /* encryption algorithm is only availble in ESP */ - iterator = proposal->create_algorithm_iterator(proposal, proto, ENCRYPTION_ALGORITHM); + iterator = proposal->create_algorithm_iterator(proposal, ENCRYPTION_ALGORITHM); while (iterator->has_next(iterator)) { iterator->current(iterator, (void**)&algo); @@ -574,7 +588,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * iterator->destroy(iterator); /* integrity algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, proto, INTEGRITY_ALGORITHM); + iterator = proposal->create_algorithm_iterator(proposal, INTEGRITY_ALGORITHM); while (iterator->has_next(iterator)) { algorithm_t *algo; @@ -585,7 +599,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * iterator->destroy(iterator); /* prf algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, proto, PSEUDO_RANDOM_FUNCTION); + iterator = proposal->create_algorithm_iterator(proposal, PSEUDO_RANDOM_FUNCTION); while (iterator->has_next(iterator)) { algorithm_t *algo; @@ -596,7 +610,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * iterator->destroy(iterator); /* dh groups */ - iterator = proposal->create_algorithm_iterator(proposal, proto, DIFFIE_HELLMAN_GROUP); + iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); while (iterator->has_next(iterator)) { algorithm_t *algo; @@ -607,7 +621,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * iterator->destroy(iterator); /* extended sequence numbers */ - iterator = proposal->create_algorithm_iterator(proposal, proto, EXTENDED_SEQUENCE_NUMBERS); + iterator = proposal->create_algorithm_iterator(proposal, EXTENDED_SEQUENCE_NUMBERS); while (iterator->has_next(iterator)) { algorithm_t *algo; @@ -618,12 +632,19 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * iterator->destroy(iterator); /* take over general infos */ - this->spi_size = proto == PROTO_IKE ? 8 : 4; + this->spi_size = proposal->get_protocol(proposal) == PROTO_IKE ? 8 : 4; this->spi.len = this->spi_size; this->spi.ptr = malloc(this->spi_size); - *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal, proto); - this->proposal_number = proposal->get_number(proposal); - this->protocol_id = proto; + if (this->spi_size == 8) + { + *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal); + } + else + { + *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal); + } + this->proposal_number = 0; + this->protocol_id = proposal->get_protocol(proposal); return &(this->public); } diff --git a/src/charon/encoding/payloads/proposal_substructure.h b/src/charon/encoding/payloads/proposal_substructure.h index a59f9532f..5b935f0cd 100644 --- a/src/charon/encoding/payloads/proposal_substructure.h +++ b/src/charon/encoding/payloads/proposal_substructure.h @@ -174,16 +174,12 @@ struct proposal_substructure_t { void (*set_spi) (proposal_substructure_t *this, chunk_t spi); /** - * @brief Add this proposal_substructure to a proposal. - * - * Since a proposal_t may contain the data of multiple - * proposal_sbustructure_t's, it may be necessary to call - * the function multiple times with the same proposal. + * @brief Get a proposal_t from the propsal_substructure_t. * * @param this calling proposal_substructure_t object - * @param proposal proposal where the data should be added + * @return proposal_t */ - void (*add_to_proposal) (proposal_substructure_t *this, proposal_t *proposal); + proposal_t * (*get_proposal) (proposal_substructure_t *this); /** * @brief Clones an proposal_substructure_t object. @@ -211,21 +207,14 @@ struct proposal_substructure_t { proposal_substructure_t *proposal_substructure_create(void); /** - * @brief Creates a proposal substructure from a proposal. - * - * Since a child proposal may contain data for both AH and ESP, - * the protocol must be specified. If the proposal does not contain - * data for proto, NULL is returned. Call twice, once with AH, once - * with ESP, with the same proposal to build the two substructures - * for it. - * + * @brief Creates a proposal_substructure_t from a proposal_t. + * * @param proposal proposal to build a substruct out of it - * @param proto for which protocol the substructure should be built - * @return proposal_substructure_t object, or NULL + * @return proposal_substructure_t object * * @ingroup payloads */ -proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal, protocol_id_t proto); +proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal); #endif /*PROPOSAL_SUBSTRUCTURE_H_*/ diff --git a/src/charon/encoding/payloads/sa_payload.c b/src/charon/encoding/payloads/sa_payload.c index 345264b4d..a54e406a3 100644 --- a/src/charon/encoding/payloads/sa_payload.c +++ b/src/charon/encoding/payloads/sa_payload.c @@ -232,18 +232,20 @@ static iterator_t *create_proposal_substructure_iterator (private_sa_payload_t * /** * Implementation of sa_payload_t.add_proposal_substructure. */ -static void add_proposal_substructure (private_sa_payload_t *this,proposal_substructure_t *proposal) +static void add_proposal_substructure(private_sa_payload_t *this,proposal_substructure_t *proposal) { status_t status; - if (this->proposals->get_count(this->proposals) > 0) + u_int proposal_count = this->proposals->get_count(this->proposals); + + if (proposal_count > 0) { proposal_substructure_t *last_proposal; status = this->proposals->get_last(this->proposals,(void **) &last_proposal); /* last transform is now not anymore last one */ - last_proposal->set_is_last_proposal(last_proposal,FALSE); + last_proposal->set_is_last_proposal(last_proposal, FALSE); } - proposal->set_is_last_proposal(proposal,TRUE); - + proposal->set_is_last_proposal(proposal, TRUE); + proposal->set_proposal_number(proposal, proposal_count + 1); this->proposals->insert_last(this->proposals,(void *) proposal); this->compute_length(this); } @@ -254,19 +256,9 @@ static void add_proposal_substructure (private_sa_payload_t *this,proposal_subst static void add_proposal(private_sa_payload_t *this, proposal_t *proposal) { proposal_substructure_t *substructure; - protocol_id_t proto[2]; - u_int i; - /* build the substructures for every protocol */ - proposal->get_protocols(proposal, proto); - for (i = 0; i<2; i++) - { - if (proto[i] != PROTO_NONE) - { - substructure = proposal_substructure_create_from_proposal(proposal, proto[i]); - add_proposal_substructure(this, substructure); - } - } + substructure = proposal_substructure_create_from_proposal(proposal); + add_proposal_substructure(this, substructure); } /** @@ -274,30 +266,44 @@ static void add_proposal(private_sa_payload_t *this, proposal_t *proposal) */ static linked_list_t *get_proposals(private_sa_payload_t *this) { - int proposal_struct_number = 0; + int struct_number = 0; + int ignore_struct_number = 0; iterator_t *iterator; - proposal_t *proposal; linked_list_t *proposal_list; /* this list will hold our proposals */ proposal_list = linked_list_create(); - /* iterate over structures, one OR MORE structures will result in a proposal */ - iterator = this->proposals->create_iterator(this->proposals,TRUE); + /* we do not support proposals split up to two proposal substructures, as + * AH+ESP bundles are not supported in RFC4301 anymore. + * To handle such structures safely, we just skip proposals with multiple + * protocols. + */ + iterator = this->proposals->create_iterator(this->proposals, TRUE); while (iterator->has_next(iterator)) { + proposal_t *proposal; proposal_substructure_t *proposal_struct; - iterator->current(iterator,(void **)&(proposal_struct)); - if (proposal_struct->get_proposal_number(proposal_struct) > proposal_struct_number) + iterator->current(iterator, (void **)&proposal_struct); + /* check if a proposal has a single protocol */ + if (proposal_struct->get_proposal_number(proposal_struct) == struct_number) + { + if (ignore_struct_number < struct_number) + { + /* remova an already added, if first of series */ + proposal_list->remove_last(proposal_list, (void**)proposal); + proposal->destroy(proposal); + ignore_struct_number = struct_number; + } + continue; + } + struct_number++; + proposal = proposal_struct->get_proposal(proposal_struct); + if (proposal) { - /* here starts a new proposal, create a new one and add it to the list */ - proposal_struct_number = proposal_struct->get_proposal_number(proposal_struct); - proposal = proposal_create(proposal_struct_number); proposal_list->insert_last(proposal_list, proposal); } - /* proposal_substructure_t does the dirty work and builds up the proposal */ - proposal_struct->add_to_proposal(proposal_struct, proposal); } iterator->destroy(iterator); return proposal_list; @@ -354,7 +360,7 @@ sa_payload_t *sa_payload_create() this->payload_length = SA_PAYLOAD_HEADER_LENGTH; this->proposals = linked_list_create(); - return (&(this->public)); + return &this->public; } /* |