diff options
-rw-r--r-- | src/conftest/hooks/custom_proposal.c | 3 | ||||
-rw-r--r-- | src/conftest/hooks/pretend_auth.c | 3 | ||||
-rw-r--r-- | src/conftest/hooks/set_proposal_number.c | 2 | ||||
-rw-r--r-- | src/libcharon/encoding/parser.c | 12 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encodings.h | 5 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/payload.c | 3 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/payload.h | 12 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/sa_payload.c | 125 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/sa_payload.h | 20 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/child_create.c | 6 | ||||
-rw-r--r-- | src/libcharon/sa/tasks/ike_init.c | 6 |
11 files changed, 160 insertions, 37 deletions
diff --git a/src/conftest/hooks/custom_proposal.c b/src/conftest/hooks/custom_proposal.c index e4acd841f..9522335b1 100644 --- a/src/conftest/hooks/custom_proposal.c +++ b/src/conftest/hooks/custom_proposal.c @@ -145,7 +145,8 @@ METHOD(listener_t, message, bool, proposal->get_protocol(proposal), proposal->get_spi(proposal)); DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props); - new = sa_payload_create_from_proposal_list(new_props); + new = sa_payload_create_from_proposal_list( + SECURITY_ASSOCIATION, new_props); message->add_payload(message, (payload_t*)new); new_props->destroy_offset(new_props, offsetof(proposal_t, destroy)); } diff --git a/src/conftest/hooks/pretend_auth.c b/src/conftest/hooks/pretend_auth.c index 4b7168cac..dd6ab9959 100644 --- a/src/conftest/hooks/pretend_auth.c +++ b/src/conftest/hooks/pretend_auth.c @@ -294,7 +294,8 @@ static void process_auth_response(private_pretend_auth_t *this, if (this->proposal) { message->add_payload(message, (payload_t*) - sa_payload_create_from_proposal(this->proposal)); + sa_payload_create_from_proposal(SECURITY_ASSOCIATION, + this->proposal)); } if (this->tsi) { diff --git a/src/conftest/hooks/set_proposal_number.c b/src/conftest/hooks/set_proposal_number.c index a59d96b6d..32b0155cb 100644 --- a/src/conftest/hooks/set_proposal_number.c +++ b/src/conftest/hooks/set_proposal_number.c @@ -121,7 +121,7 @@ METHOD(listener_t, message, bool, } enumerator->destroy(enumerator); } - sa = sa_payload_create_from_proposal_list(updated); + sa = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION, updated); list->destroy_offset(list, offsetof(proposal_t, destroy)); updated->destroy_offset(updated, offsetof(proposal_t, destroy)); message->add_payload(message, (payload_t*)sa); diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c index 6309a5c3f..09b52168f 100644 --- a/src/libcharon/encoding/parser.c +++ b/src/libcharon/encoding/parser.c @@ -496,6 +496,18 @@ METHOD(parser_t, parse_payload, status_t, } break; } + case PROPOSALS_V1: + { + if (payload_length < SA_PAYLOAD_V1_HEADER_LENGTH || + !parse_list(this, rule_number, output + rule->offset, + PROPOSAL_SUBSTRUCTURE_V1, + payload_length - SA_PAYLOAD_V1_HEADER_LENGTH)) + { + pld->destroy(pld); + return PARSE_ERROR; + } + break; + } case TRANSFORMS: { if (payload_length < diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h index 52af4a984..80df979cc 100644 --- a/src/libcharon/encoding/payloads/encodings.h +++ b/src/libcharon/encoding/payloads/encodings.h @@ -220,6 +220,11 @@ enum encoding_type_t { PROPOSALS, /** + * Same as PROPOSALS, but for IKEv1 in a SECURITY_ASSOCIATION_V1 + */ + PROPOSALS_V1, + + /** * Representating one or more transform substructures. * * The offset points to a linked_list_t pointer. diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index 78451c5b4..14617b4e3 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -156,7 +156,8 @@ 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 TRANSFORM_SUBSTRUCTURE: diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h index 021383a1d..ff1ae73a3 100644 --- a/src/libcharon/encoding/payloads/payload.h +++ b/src/libcharon/encoding/payloads/payload.h @@ -29,6 +29,10 @@ 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 an IKE message. @@ -243,6 +247,14 @@ enum payload_type_t { * used internally to handle a transform attribute like a payload. */ CONFIGURATION_ATTRIBUTE = 261, + + /** + * 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_V1 = 262, }; /** diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c index 89464ac3d..af3012623 100644 --- a/src/libcharon/encoding/payloads/sa_payload.c +++ b/src/libcharon/encoding/payloads/sa_payload.c @@ -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, + offset points to a linked_list_t pointer */ + { PROPOSALS_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]) }, @@ -144,14 +200,22 @@ METHOD(payload_t, verify, status_t, METHOD(payload_t, get_encoding_rules, void, private_sa_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { - *rules = sa_payload_encodings; - *rule_count = countof(sa_payload_encodings); + if (this->type == SECURITY_ASSOCIATION_V1) + { + *rules = encodings_v1; + *rule_count = countof(encodings_v1); + } + else + { + *rules = encodings_v2; + *rule_count = countof(encodings_v2); + } } 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, @@ -175,6 +239,11 @@ static void compute_length(private_sa_payload_t *this) payload_t *current; size_t length = SA_PAYLOAD_HEADER_LENGTH; + if (this->type == SECURITY_ASSOCIATION_V1) + { + length = SA_PAYLOAD_V1_HEADER_LENGTH; + } + enumerator = this->proposals->create_enumerator(this->proposals); while (enumerator->enumerate(enumerator, (void **)¤t)) { @@ -270,14 +339,14 @@ 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; @@ -298,41 +367,49 @@ sa_payload_t *sa_payload_create() .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_proposal_list(payload_type_t type, + linked_list_t *proposals) { - private_sa_payload_t *this; + sa_payload_t *this; enumerator_t *enumerator; proposal_t *proposal; - this = (private_sa_payload_t*)sa_payload_create(); + this = sa_payload_create(type); enumerator = proposals->create_enumerator(proposals); while (enumerator->enumerate(enumerator, &proposal)) { - add_proposal(this, proposal); + this->add_proposal(this, proposal); } enumerator->destroy(enumerator); - return &this->public; + return this; } /* * Described in header. */ -sa_payload_t *sa_payload_create_from_proposal(proposal_t *proposal) +sa_payload_t *sa_payload_create_from_proposal(payload_type_t type, + proposal_t *proposal) { - private_sa_payload_t *this; + sa_payload_t *this; - this = (private_sa_payload_t*)sa_payload_create(); - add_proposal(this, proposal); + this = sa_payload_create(type); + this->add_proposal(this, proposal); - return &this->public; + return this; } diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h index cc8c481c8..11fc774e5 100644 --- a/src/libcharon/encoding/payloads/sa_payload.h +++ b/src/libcharon/encoding/payloads/sa_payload.h @@ -30,12 +30,17 @@ typedef struct sa_payload_t sa_payload_t; #include <utils/linked_list.h> /** - * SA_PAYLOAD length in bytes without any proposal substructure. + * SECURITY_ASSOCIATION length in bytes without any proposal substructure. */ #define SA_PAYLOAD_HEADER_LENGTH 4 /** - * Class representing an IKEv2-SA Payload. + * SECURITY_ASSOCIATION_V1 length in bytes without any proposal substructure. + */ +#define SA_PAYLOAD_V1_HEADER_LENGTH 12 + +/** + * Class representing an IKEv1 or IKEv2 SA Payload. * * The SA Payload format is described in RFC section 3.3. */ @@ -76,17 +81,20 @@ 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. * + * @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1 * @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_proposal_list(payload_type_t type, + linked_list_t *proposals); /** * Creates a sa_payload_t object from a single proposal. @@ -94,9 +102,11 @@ sa_payload_t *sa_payload_create_from_proposal_list(linked_list_t *proposals); * This is only for convenience. Use sa_payload_create_from_proposal_list * if you want to add more than one proposal. * + * @param type SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1 * @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(payload_type_t type, + proposal_t *proposal); #endif /** SA_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c index 67c29d31f..fdc5b520e 100644 --- a/src/libcharon/sa/tasks/child_create.c +++ b/src/libcharon/sa/tasks/child_create.c @@ -526,11 +526,13 @@ static void build_payloads(private_child_create_t *this, message_t *message) /* add SA payload */ if (this->initiator) { - sa_payload = sa_payload_create_from_proposal_list(this->proposals); + sa_payload = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION, + this->proposals); } else { - sa_payload = sa_payload_create_from_proposal(this->proposal); + sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION, + this->proposal); } message->add_payload(message, (payload_t*)sa_payload); diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c index b8e66c7e6..911e0c2aa 100644 --- a/src/libcharon/sa/tasks/ike_init.c +++ b/src/libcharon/sa/tasks/ike_init.c @@ -132,7 +132,8 @@ static void build_payloads(private_ike_init_t *this, message_t *message) enumerator->destroy(enumerator); } - sa_payload = sa_payload_create_from_proposal_list(proposal_list); + sa_payload = sa_payload_create_from_proposal_list(SECURITY_ASSOCIATION, + proposal_list); proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy)); } else @@ -142,7 +143,8 @@ static void build_payloads(private_ike_init_t *this, message_t *message) /* include SPI of new IKE_SA when we are rekeying */ this->proposal->set_spi(this->proposal, id->get_responder_spi(id)); } - sa_payload = sa_payload_create_from_proposal(this->proposal); + sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION, + this->proposal); } message->add_payload(message, (payload_t*)sa_payload); |