diff options
Diffstat (limited to 'src/libcharon/encoding')
5 files changed, 247 insertions, 8 deletions
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c index 11d684f5e..ca19ba700 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.c +++ b/src/libcharon/encoding/payloads/proposal_substructure.c @@ -754,6 +754,157 @@ METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*, return this->transforms->create_enumerator(this->transforms); } +/** + * Get an attribute from a selected transform + */ +static u_int64_t get_attr_tfrm(transform_substructure_t *transform, + transform_attribute_type_t type) +{ + enumerator_t *enumerator; + transform_attribute_t *attr; + u_int64_t value = 0; + + enumerator = transform->create_attribute_enumerator(transform); + while (enumerator->enumerate(enumerator, &attr)) + { + if (attr->get_attribute_type(attr) == type) + { + value = attr->get_value(attr); + break; + } + } + enumerator->destroy(enumerator); + return value; +} + + +/** + * Get an attribute from any transform, 0 if not found + */ +static u_int64_t get_attr(private_proposal_substructure_t *this, + transform_attribute_type_t type, transform_substructure_t **sel) +{ + transform_substructure_t *transform; + enumerator_t *enumerator; + u_int64_t value = 0; + + enumerator = this->transforms->create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &transform)) + { + value = get_attr_tfrm(transform, type); + if (value) + { + if (sel) + { + *sel = transform; + } + break; + } + } + enumerator->destroy(enumerator); + return value; +} + +METHOD(proposal_substructure_t, get_lifetime, u_int32_t, + private_proposal_substructure_t *this) +{ + transform_substructure_t *transform; + transform_attribute_type_t type; + + switch (this->protocol_id) + { + case PROTO_IKE: + type = get_attr(this, TATTR_PH1_LIFE_TYPE, &transform); + if (type == IKEV1_LIFE_TYPE_SECONDS) + { + return get_attr_tfrm(transform, TATTR_PH1_LIFE_DURATION); + } + break; + case PROTO_ESP: + type = get_attr(this, TATTR_PH2_SA_LIFE_TYPE, &transform); + if (type == IKEV1_LIFE_TYPE_SECONDS) + { + return get_attr_tfrm(transform, TATTR_PH2_SA_LIFE_DURATION); + } + else if (type != IKEV1_LIFE_TYPE_KILOBYTES) + { /* default to 8 hours, RFC 2407 */ + return 28800; + } + break; + default: + break; + } + return 0; +} + +METHOD(proposal_substructure_t, get_lifebytes, u_int64_t, + private_proposal_substructure_t *this) +{ + transform_substructure_t *transform; + transform_attribute_type_t type; + + switch (this->protocol_id) + { + case PROTO_IKE: + type = get_attr(this, TATTR_PH1_LIFE_TYPE, &transform); + if (type == IKEV1_LIFE_TYPE_KILOBYTES) + { + return get_attr_tfrm(transform, TATTR_PH1_LIFE_DURATION); + } + break; + case PROTO_ESP: + type = get_attr(this, TATTR_PH2_SA_LIFE_TYPE, &transform); + if (type == IKEV1_LIFE_TYPE_KILOBYTES) + { + return get_attr_tfrm(transform, TATTR_PH1_LIFE_DURATION); + } + break; + default: + break; + } + return 0; + +} + +METHOD(proposal_substructure_t, get_auth_method, auth_method_t, + private_proposal_substructure_t *this) +{ + switch (get_attr(this, TATTR_PH1_AUTH_METHOD, NULL)) + { + case IKEV1_AUTH_PSK: + return AUTH_PSK; + case IKEV1_AUTH_RSA_SIG: + return AUTH_RSA; + case IKEV1_AUTH_DSS_SIG: + return AUTH_DSS; + default: + /* TODO-IKEv1: XAUTH, ECDSA sigs */ + return AUTH_NONE; + } +} + +METHOD(proposal_substructure_t, get_encap_mode, ipsec_mode_t, + private_proposal_substructure_t *this, bool *udp) +{ + *udp = FALSE; + switch (get_attr(this, TATTR_PH2_ENCAP_MODE, NULL)) + { + case IKEV1_ENCAP_TRANSPORT: + return MODE_TRANSPORT; + case IKEV1_ENCAP_TUNNEL: + return MODE_TRANSPORT; + case IKEV1_ENCAP_UDP_TRANSPORT: + *udp = TRUE; + return MODE_TRANSPORT; + case IKEV1_ENCAP_UDP_TUNNEL: + *udp = TRUE; + return MODE_TUNNEL; + default: + /* default to TUNNEL, RFC 2407 says implementation specific */ + return MODE_TUNNEL; + } +} + METHOD2(payload_t, proposal_substructure_t, destroy, void, private_proposal_substructure_t *this) { @@ -791,6 +942,10 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type) .create_substructure_enumerator = _create_substructure_enumerator, .set_spi = _set_spi, .get_spi = _get_spi, + .get_lifetime = _get_lifetime, + .get_lifebytes = _get_lifebytes, + .get_auth_method = _get_auth_method, + .get_encap_mode = _get_encap_mode, .destroy = _destroy, }, .next_payload = NO_PAYLOAD, diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h index de06f916f..03b26e127 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.h +++ b/src/libcharon/encoding/payloads/proposal_substructure.h @@ -112,6 +112,35 @@ struct proposal_substructure_t { enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this); /** + * Get the (shortest) lifetime of a proposal (IKEv1 only). + * + * @return lifetime, in seconds + */ + u_int32_t (*get_lifetime)(proposal_substructure_t *this); + + /** + * Get the (shortest) life duration of a proposal (IKEv1 only). + * + * @return life duration, in bytes + */ + u_int64_t (*get_lifebytes)(proposal_substructure_t *this); + + /** + * Get the first authentication method from the proposal (IKEv1 only). + * + * @return auth method, or AUTH_NONE + */ + auth_method_t (*get_auth_method)(proposal_substructure_t *this); + + /** + * Get the (first) encapsulation mode from a proposal (IKEv1 only). + * + * @param udp set to TRUE if UDP encapsulation used + * @return ipsec encapsulation mode + */ + ipsec_mode_t (*get_encap_mode)(proposal_substructure_t *this, bool *udp); + + /** * Destroys an proposal_substructure_t object. */ void (*destroy) (proposal_substructure_t *this); diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c index 5f739c94a..254916c55 100644 --- a/src/libcharon/encoding/payloads/sa_payload.c +++ b/src/libcharon/encoding/payloads/sa_payload.c @@ -339,26 +339,69 @@ METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*, METHOD(sa_payload_t, get_lifetime, u_int32_t, private_sa_payload_t *this) { - return 0; + proposal_substructure_t *substruct; + enumerator_t *enumerator; + u_int32_t lifetime = 0; + + enumerator = this->proposals->create_enumerator(this->proposals); + if (enumerator->enumerate(enumerator, &substruct)) + { + lifetime = substruct->get_lifetime(substruct); + } + enumerator->destroy(enumerator); + + return lifetime; } METHOD(sa_payload_t, get_lifebytes, u_int64_t, private_sa_payload_t *this) { - return 0; + proposal_substructure_t *substruct; + enumerator_t *enumerator; + u_int64_t lifebytes = 0; + + enumerator = this->proposals->create_enumerator(this->proposals); + if (enumerator->enumerate(enumerator, &substruct)) + { + lifebytes = substruct->get_lifebytes(substruct); + } + enumerator->destroy(enumerator); + + return lifebytes; } METHOD(sa_payload_t, get_auth_method, auth_method_t, private_sa_payload_t *this) { - return AUTH_NONE; + proposal_substructure_t *substruct; + enumerator_t *enumerator; + auth_method_t method = AUTH_NONE; + + enumerator = this->proposals->create_enumerator(this->proposals); + if (enumerator->enumerate(enumerator, &substruct)) + { + method = substruct->get_auth_method(substruct); + } + enumerator->destroy(enumerator); + + return method; } METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t, private_sa_payload_t *this, bool *udp) { - *udp = FALSE; - return MODE_NONE; + proposal_substructure_t *substruct; + enumerator_t *enumerator; + ipsec_mode_t mode = MODE_NONE; + + enumerator = this->proposals->create_enumerator(this->proposals); + if (enumerator->enumerate(enumerator, &substruct)) + { + mode = substruct->get_encap_mode(substruct, udp); + } + enumerator->destroy(enumerator); + + return mode; } METHOD2(payload_t, sa_payload_t, destroy, void, diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c index 7e8a9c7c7..0be39316a 100644 --- a/src/libcharon/encoding/payloads/transform_attribute.c +++ b/src/libcharon/encoding/payloads/transform_attribute.c @@ -209,10 +209,22 @@ METHOD(transform_attribute_t, get_value_chunk, chunk_t, return this->attribute_value; } -METHOD(transform_attribute_t, get_value, u_int16_t, +METHOD(transform_attribute_t, get_value, u_int64_t, private_transform_attribute_t *this) { - return this->attribute_length_or_value; + u_int64_t value = 0; + + if (this->attribute_format) + { + return this->attribute_length_or_value; + } + if (this->attribute_value.len > sizeof(value)) + { + return UINT64_MAX; + } + memcpy(((char*)&value) + sizeof(value) - this->attribute_value.len, + this->attribute_value.ptr, this->attribute_value.len); + return be64toh(value); } METHOD(transform_attribute_t, set_attribute_type, void, diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h index 52e5d8412..7eed40b3e 100644 --- a/src/libcharon/encoding/payloads/transform_attribute.h +++ b/src/libcharon/encoding/payloads/transform_attribute.h @@ -109,7 +109,7 @@ struct transform_attribute_t { * * @return value */ - u_int16_t (*get_value) (transform_attribute_t *this); + u_int64_t (*get_value) (transform_attribute_t *this); /** * Sets the value of the attribute. |