diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-05-24 13:31:53 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-05-24 15:32:28 +0200 |
commit | 647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad (patch) | |
tree | 4313bcdd0c89211bbf0a4b9f99d3d1341aaeb466 /src | |
parent | 7a75cae8566dbf1a42f12c9e7521aa59866f240d (diff) | |
download | strongswan-647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad.tar.bz2 strongswan-647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad.tar.xz |
Added support for IKEv1 IPComp proposals in SA payload.
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/encoding/payloads/sa_payload.c | 81 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/sa_payload.h | 19 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/aggressive_mode.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/main_mode.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_mode.c | 4 |
5 files changed, 98 insertions, 14 deletions
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c index 18b1dc7b6..4fb1bc63a 100644 --- a/src/libcharon/encoding/payloads/sa_payload.c +++ b/src/libcharon/encoding/payloads/sa_payload.c @@ -336,6 +336,60 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*, return list; } +METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*, + private_sa_payload_t *this, u_int16_t *cpi) +{ + int current_proposal = -1, unsupported_proposal = -1; + enumerator_t *enumerator; + proposal_substructure_t *substruct, *esp = NULL, *ipcomp = NULL; + linked_list_t *list; + + /* we currently only support the combination ESP+IPComp, find the first */ + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &substruct)) + { + u_int8_t proposal_number = substruct->get_proposal_number(substruct); + u_int8_t protocol_id = substruct->get_protocol_id(substruct); + + if (proposal_number == unsupported_proposal) + { + continue; + } + if (protocol_id != PROTO_ESP && protocol_id != PROTO_IPCOMP) + { /* unsupported combination */ + esp = ipcomp = NULL; + unsupported_proposal = current_proposal; + continue; + } + if (proposal_number != current_proposal) + { /* start of a new proposal */ + if (esp && ipcomp) + { /* previous proposal is valid */ + break; + } + esp = ipcomp = NULL; + current_proposal = proposal_number; + } + switch (protocol_id) + { + case PROTO_ESP: + esp = substruct; + break; + case PROTO_IPCOMP: + ipcomp = substruct; + break; + } + } + enumerator->destroy(enumerator); + + list = linked_list_create(); + if (esp && ipcomp && ipcomp->get_cpi(ipcomp, cpi)) + { + esp->get_proposals(esp, list); + } + return list; +} + METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*, private_sa_payload_t *this) { @@ -438,6 +492,7 @@ sa_payload_t *sa_payload_create(payload_type_t type) .destroy = _destroy, }, .get_proposals = _get_proposals, + .get_ipcomp_proposals = _get_ipcomp_proposals, .create_substructure_enumerator = _create_substructure_enumerator, .get_lifetime = _get_lifetime, .get_lifebytes = _get_lifebytes, @@ -497,7 +552,8 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal) */ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes, - auth_method_t auth, ipsec_mode_t mode, bool udp) + auth_method_t auth, ipsec_mode_t mode, bool udp, + u_int16_t cpi) { proposal_substructure_t *substruct; private_sa_payload_t *this; @@ -505,11 +561,18 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals, this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1); /* IKEv1 encodes multiple proposals in a single substructure - * TODO-IKEv1: Encode ESP+AH proposals in two different substructs */ + * TODO-IKEv1: Encode ESP+AH proposals in two substructs with same num */ substruct = proposal_substructure_create_from_proposals_v1(proposals, lifetime, lifebytes, auth, mode, udp); - substruct->set_is_last_proposal(substruct, TRUE); this->proposals->insert_last(this->proposals, substruct); + substruct->set_is_last_proposal(substruct, FALSE); + if (cpi) + { + substruct = proposal_substructure_create_for_ipcomp_v1(lifetime, + lifebytes, cpi, substruct->get_proposal_number(substruct)); + this->proposals->insert_last(this->proposals, substruct); + } + substruct->set_is_last_proposal(substruct, TRUE); compute_length(this); return &this->public; @@ -520,7 +583,8 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals, */ sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes, - auth_method_t auth, ipsec_mode_t mode, bool udp) + auth_method_t auth, ipsec_mode_t mode, bool udp, + u_int16_t cpi) { proposal_substructure_t *substruct; private_sa_payload_t *this; @@ -529,8 +593,15 @@ sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal, substruct = proposal_substructure_create_from_proposal_v1(proposal, lifetime, lifebytes, auth, mode, udp); - substruct->set_is_last_proposal(substruct, TRUE); this->proposals->insert_last(this->proposals, substruct); + substruct->set_is_last_proposal(substruct, FALSE); + if (cpi) + { + substruct = proposal_substructure_create_for_ipcomp_v1(lifetime, + lifebytes, cpi, substruct->get_proposal_number(substruct)); + this->proposals->insert_last(this->proposals, substruct); + } + substruct->set_is_last_proposal(substruct, TRUE); compute_length(this); return &this->public; diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h index 6dfbd5180..9a88cccd5 100644 --- a/src/libcharon/encoding/payloads/sa_payload.h +++ b/src/libcharon/encoding/payloads/sa_payload.h @@ -46,11 +46,20 @@ struct sa_payload_t { /** * Gets the proposals in this payload as a list. * - * @return a list containing proposal_t s + * @return a list containing proposal_ts */ linked_list_t *(*get_proposals) (sa_payload_t *this); /** + * Gets the proposals from the first proposal in this payload with IPComp + * enabled (IKEv1 only). + * + * @param cpi the CPI of the first IPComp (sub)proposal + * @return a list containing proposal_ts + */ + linked_list_t *(*get_ipcomp_proposals) (sa_payload_t *this, u_int16_t *cpi); + + /** * Get the (shortest) lifetime of a proposal (IKEv1 only). * * @return lifetime, in seconds @@ -125,11 +134,13 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal); * @param auth authentication method to use, or AUTH_NONE * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL * @param udp TRUE to use UDP encapsulation + * @param cpi CPI in case IPComp should be used * @return sa_payload_t object */ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes, - auth_method_t auth, ipsec_mode_t mode, bool udp); + auth_method_t auth, ipsec_mode_t mode, bool udp, + u_int16_t cpi); /** * Creates an IKEv1 sa_payload_t object from a single proposal. @@ -140,10 +151,12 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals, * @param auth authentication method to use, or AUTH_NONE * @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL * @param udp TRUE to use UDP encapsulation + * @param cpi CPI in case IPComp should be used * @return sa_payload_t object */ sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal, u_int32_t lifetime, u_int64_t lifebytes, - auth_method_t auth, ipsec_mode_t mode, bool udp); + auth_method_t auth, ipsec_mode_t mode, bool udp, + u_int16_t cpi); #endif /** SA_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c index 664fce918..db27ae12f 100644 --- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c +++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c @@ -235,7 +235,7 @@ METHOD(task_t, build_i, status_t, this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg); proposals = this->ike_cfg->get_proposals(this->ike_cfg); sa_payload = sa_payload_create_from_proposals_v1(proposals, - this->lifetime, 0, this->method, MODE_NONE, FALSE); + this->lifetime, 0, this->method, MODE_NONE, FALSE, 0); proposals->destroy_offset(proposals, offsetof(proposal_t, destroy)); message->add_payload(message, &sa_payload->payload_interface); @@ -480,7 +480,7 @@ METHOD(task_t, build_r, status_t, identification_t *id; sa_payload = sa_payload_create_from_proposal_v1(this->proposal, - this->lifetime, 0, this->method, MODE_NONE, FALSE); + this->lifetime, 0, this->method, MODE_NONE, FALSE, 0); message->add_payload(message, &sa_payload->payload_interface); if (!this->ph1->add_nonce_ke(this->ph1, message)) diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index ce047df16..23c90ba6b 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -241,7 +241,7 @@ METHOD(task_t, build_i, status_t, this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg); proposals = this->ike_cfg->get_proposals(this->ike_cfg); sa_payload = sa_payload_create_from_proposals_v1(proposals, - this->lifetime, 0, this->method, MODE_NONE, FALSE); + this->lifetime, 0, this->method, MODE_NONE, FALSE, 0); proposals->destroy_offset(proposals, offsetof(proposal_t, destroy)); message->add_payload(message, &sa_payload->payload_interface); @@ -455,7 +455,7 @@ METHOD(task_t, build_r, status_t, sa_payload_t *sa_payload; sa_payload = sa_payload_create_from_proposal_v1(this->proposal, - this->lifetime, 0, this->method, MODE_NONE, FALSE); + this->lifetime, 0, this->method, MODE_NONE, FALSE, 0); message->add_payload(message, &sa_payload->payload_interface); return NEED_MORE; diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index cc3ac6720..6fa0752b0 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -654,7 +654,7 @@ METHOD(task_t, build_i, status_t, get_lifetimes(this); sa_payload = sa_payload_create_from_proposals_v1(list, this->lifetime, this->lifebytes, AUTH_NONE, - this->mode, this->udp); + this->mode, this->udp, 0); list->destroy_offset(list, offsetof(proposal_t, destroy)); message->add_payload(message, &sa_payload->payload_interface); @@ -933,7 +933,7 @@ METHOD(task_t, build_r, status_t, sa_payload = sa_payload_create_from_proposal_v1(this->proposal, this->lifetime, this->lifebytes, AUTH_NONE, - this->mode, this->udp); + this->mode, this->udp, 0); message->add_payload(message, &sa_payload->payload_interface); if (!add_nonce(this, &this->nonce_r, message)) |