aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/encoding
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/encoding')
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c155
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.h29
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c53
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.c16
-rw-r--r--src/libcharon/encoding/payloads/transform_attribute.h2
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.