Implemented IKEv1 attribute encoding in SA payload
This commit is contained in:
@@ -754,6 +754,157 @@ 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
|
||||||
|
*/
|
||||||
|
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,
|
METHOD2(payload_t, proposal_substructure_t, destroy, void,
|
||||||
private_proposal_substructure_t *this)
|
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,
|
.create_substructure_enumerator = _create_substructure_enumerator,
|
||||||
.set_spi = _set_spi,
|
.set_spi = _set_spi,
|
||||||
.get_spi = _get_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,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.next_payload = NO_PAYLOAD,
|
.next_payload = NO_PAYLOAD,
|
||||||
|
|||||||
@@ -111,6 +111,35 @@ struct proposal_substructure_t {
|
|||||||
*/
|
*/
|
||||||
enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this);
|
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.
|
* Destroys an proposal_substructure_t object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -339,26 +339,69 @@ METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
|
|||||||
METHOD(sa_payload_t, get_lifetime, u_int32_t,
|
METHOD(sa_payload_t, get_lifetime, u_int32_t,
|
||||||
private_sa_payload_t *this)
|
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,
|
METHOD(sa_payload_t, get_lifebytes, u_int64_t,
|
||||||
private_sa_payload_t *this)
|
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,
|
METHOD(sa_payload_t, get_auth_method, auth_method_t,
|
||||||
private_sa_payload_t *this)
|
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,
|
METHOD(sa_payload_t, get_encap_mode, ipsec_mode_t,
|
||||||
private_sa_payload_t *this, bool *udp)
|
private_sa_payload_t *this, bool *udp)
|
||||||
{
|
{
|
||||||
*udp = FALSE;
|
proposal_substructure_t *substruct;
|
||||||
return MODE_NONE;
|
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,
|
METHOD2(payload_t, sa_payload_t, destroy, void,
|
||||||
|
|||||||
@@ -209,10 +209,22 @@ METHOD(transform_attribute_t, get_value_chunk, chunk_t,
|
|||||||
return this->attribute_value;
|
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)
|
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,
|
METHOD(transform_attribute_t, set_attribute_type, void,
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ struct transform_attribute_t {
|
|||||||
*
|
*
|
||||||
* @return value
|
* @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.
|
* Sets the value of the attribute.
|
||||||
|
|||||||
Reference in New Issue
Block a user