Support IKEv1 proposal encodings having both lifebytes and a lifetime

This commit is contained in:
Martin Willi
2012-03-20 17:31:33 +01:00
parent b147679a2c
commit 927c1dd9d2
@@ -769,122 +769,113 @@ METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
return this->transforms->create_enumerator(this->transforms); 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 * Get an attribute from any transform, 0 if not found
*/ */
static u_int64_t get_attr(private_proposal_substructure_t *this, static u_int64_t get_attr(private_proposal_substructure_t *this,
transform_attribute_type_t type, transform_substructure_t **sel) transform_attribute_type_t type)
{ {
enumerator_t *transforms, *attributes;
transform_substructure_t *transform; transform_substructure_t *transform;
enumerator_t *enumerator; transform_attribute_t *attr;
u_int64_t value = 0;
enumerator = this->transforms->create_enumerator(this->transforms); transforms = this->transforms->create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &transform)) while (transforms->enumerate(transforms, &transform))
{ {
value = get_attr_tfrm(transform, type); attributes = transform->create_attribute_enumerator(transform);
if (value) while (attributes->enumerate(attributes, &attr))
{ {
if (sel) if (attr->get_attribute_type(attr) == type)
{ {
*sel = transform; attributes->destroy(attributes);
transforms->destroy(transforms);
return attr->get_value(attr);
} }
break;
} }
attributes->destroy(attributes);
} }
enumerator->destroy(enumerator); transforms->destroy(transforms);
return value; return 0;
}
/**
* Look up a lifetime duration of a given kind in all transforms
*/
static u_int64_t get_life_duration(private_proposal_substructure_t *this,
transform_attribute_type_t type_attr, ikev1_life_type_t type,
transform_attribute_type_t dur_attr)
{
enumerator_t *transforms, *attributes;
transform_substructure_t *transform;
transform_attribute_t *attr;
transforms = this->transforms->create_enumerator(this->transforms);
while (transforms->enumerate(transforms, &transform))
{
attributes = transform->create_attribute_enumerator(transform);
while (attributes->enumerate(attributes, &attr))
{
if (attr->get_attribute_type(attr) == type_attr &&
attr->get_value(attr) == type)
{ /* got type attribute, look for duration following next */
while (attributes->enumerate(attributes, &attr))
{
if (attr->get_attribute_type(attr) == dur_attr)
{
attributes->destroy(attributes);
transforms->destroy(transforms);
return attr->get_value(attr);
}
}
}
}
attributes->destroy(attributes);
}
transforms->destroy(transforms);
return 0;
} }
METHOD(proposal_substructure_t, get_lifetime, u_int32_t, METHOD(proposal_substructure_t, get_lifetime, u_int32_t,
private_proposal_substructure_t *this) private_proposal_substructure_t *this)
{ {
transform_substructure_t *transform; u_int32_t duration;
ikev1_life_type_t type;
switch (this->protocol_id) switch (this->protocol_id)
{ {
case PROTO_IKE: case PROTO_IKE:
type = get_attr(this, TATTR_PH1_LIFE_TYPE, &transform); return get_life_duration(this, TATTR_PH1_LIFE_TYPE,
if (type == IKEV1_LIFE_TYPE_SECONDS) IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
{
return get_attr_tfrm(transform, TATTR_PH1_LIFE_DURATION);
}
break;
case PROTO_ESP: case PROTO_ESP:
type = get_attr(this, TATTR_PH2_SA_LIFE_TYPE, &transform); duration = get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
if (type == IKEV1_LIFE_TYPE_SECONDS) IKEV1_LIFE_TYPE_SECONDS, TATTR_PH2_SA_LIFE_DURATION);
{ if (!duration)
return get_attr_tfrm(transform, TATTR_PH2_SA_LIFE_DURATION);
}
else if (type != IKEV1_LIFE_TYPE_KILOBYTES)
{ /* default to 8 hours, RFC 2407 */ { /* default to 8 hours, RFC 2407 */
return 28800; return 28800;
} }
break; return duration;
default: default:
break; return 0;
} }
return 0;
} }
METHOD(proposal_substructure_t, get_lifebytes, u_int64_t, METHOD(proposal_substructure_t, get_lifebytes, u_int64_t,
private_proposal_substructure_t *this) private_proposal_substructure_t *this)
{ {
transform_substructure_t *transform;
ikev1_life_type_t type;
switch (this->protocol_id) 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: case PROTO_ESP:
type = get_attr(this, TATTR_PH2_SA_LIFE_TYPE, &transform); return 1000 * get_life_duration(this, TATTR_PH2_SA_LIFE_TYPE,
if (type == IKEV1_LIFE_TYPE_KILOBYTES) IKEV1_LIFE_TYPE_KILOBYTES, TATTR_PH2_SA_LIFE_DURATION);
{ case PROTO_IKE:
return get_attr_tfrm(transform, TATTR_PH1_LIFE_DURATION);
}
break;
default: default:
break; return 0;
} }
return 0;
} }
METHOD(proposal_substructure_t, get_auth_method, auth_method_t, METHOD(proposal_substructure_t, get_auth_method, auth_method_t,
private_proposal_substructure_t *this) private_proposal_substructure_t *this)
{ {
switch (get_attr(this, TATTR_PH1_AUTH_METHOD, NULL)) switch (get_attr(this, TATTR_PH1_AUTH_METHOD))
{ {
case IKEV1_AUTH_PSK: case IKEV1_AUTH_PSK:
return AUTH_PSK; return AUTH_PSK;
@@ -908,7 +899,7 @@ METHOD(proposal_substructure_t, get_encap_mode, ipsec_mode_t,
private_proposal_substructure_t *this, bool *udp) private_proposal_substructure_t *this, bool *udp)
{ {
*udp = FALSE; *udp = FALSE;
switch (get_attr(this, TATTR_PH2_ENCAP_MODE, NULL)) switch (get_attr(this, TATTR_PH2_ENCAP_MODE))
{ {
case IKEV1_ENCAP_TRANSPORT: case IKEV1_ENCAP_TRANSPORT:
return MODE_TRANSPORT; return MODE_TRANSPORT;
@@ -1110,7 +1101,7 @@ static void set_from_proposal_v1_esp(private_proposal_substructure_t *this,
transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
TATTR_PH2_SA_LIFE_DURATION, lifetime)); TATTR_PH2_SA_LIFE_DURATION, lifetime));
} }
else if (lifebytes) if (lifebytes)
{ {
transform->add_transform_attribute(transform, transform->add_transform_attribute(transform,
transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1, transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,