aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2010-09-09 11:13:48 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2010-09-09 11:15:08 +0200
commit20ad62026e8177a20f7089c9d428283fa71435a0 (patch)
treeae21f1e3c51c6c44ed2b3fa6697560c90b889d43 /src/libcharon
parentb1baa908463fef13bf604b9bee421b3540be5068 (diff)
downloadstrongswan-20ad62026e8177a20f7089c9d428283fa71435a0.tar.bz2
strongswan-20ad62026e8177a20f7089c9d428283fa71435a0.tar.xz
support non EAP-TTLS conformant RADIUS-type attribute segmentation
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.c92
1 files changed, 79 insertions, 13 deletions
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
index 11e6cd0f3..10d08ca2a 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
@@ -64,31 +64,96 @@ struct private_eap_ttls_peer_t {
eap_ttls_avp_t *avp;
};
+/**
+ * EAP packet format
+ */
+typedef struct __attribute__((packed)) {
+ u_int8_t code;
+ u_int8_t identifier;
+ u_int16_t length;
+ u_int8_t type;
+ u_int8_t data;
+} eap_packet_t;
+
+#define MAX_RADIUS_ATTRIBUTE_SIZE 253
+
METHOD(tls_application_t, process, status_t,
private_eap_ttls_peer_t *this, tls_reader_t *reader)
{
- chunk_t data = chunk_empty;
+ chunk_t avp_data = chunk_empty;
+ chunk_t eap_data = chunk_empty;
status_t status;
payload_t *payload;
eap_payload_t *in;
+ eap_packet_t *pkt;
eap_code_t code;
eap_type_t type, received_type;
u_int32_t vendor, received_vendor;
+ u_int16_t eap_len;
+ size_t eap_pos = 0;
+ bool concatenated = FALSE;
- status = this->avp->process(this->avp, reader, &data);
- switch (status)
+ do
{
- case SUCCESS:
- break;
- case NEED_MORE:
- DBG1(DBG_IKE, "need more AVP data");
- return NEED_MORE;
- case FAILED:
- default:
+ status = this->avp->process(this->avp, reader, &avp_data);
+ switch (status)
+ {
+ case SUCCESS:
+ break;
+ case NEED_MORE:
+ DBG1(DBG_IKE, "need more AVP data");
+ return NEED_MORE;
+ case FAILED:
+ default:
+ return FAILED;
+ }
+
+ if (eap_data.len == 0)
+ {
+ if (avp_data.len < 4)
+ {
+ DBG1(DBG_IKE, "AVP size to small to contain EAP header");
+ chunk_free(&avp_data);
+ return FAILED;
+ }
+ pkt = (eap_packet_t*)avp_data.ptr;
+ eap_len = untoh16(&pkt->length);
+
+ if (eap_len <= avp_data.len)
+ {
+ /* standard: EAP packet contained in a single AVP */
+ eap_data = avp_data;
+ break;
+ }
+ else if (avp_data.len == MAX_RADIUS_ATTRIBUTE_SIZE)
+ {
+ /* non-standard: EAP packet segmented into multiple AVPs */
+ eap_data = chunk_alloc(eap_len);
+ concatenated = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "non-radius segmentation of EAP packet into AVPs");
+ chunk_free(&avp_data);
+ return FAILED;
+ }
+ }
+
+ if (avp_data.len > eap_data.len - eap_pos)
+ {
+ DBG1(DBG_IKE, "AVP size to large to fit into EAP packet");
+ chunk_free(&avp_data);
+ chunk_free(&eap_data);
return FAILED;
+ }
+ memcpy(eap_data.ptr + eap_pos, avp_data.ptr, avp_data.len);
+ eap_pos += avp_data.len;
+ chunk_free(&avp_data);
}
- in = eap_payload_create_data(data);
- chunk_free(&data);
+ while (eap_pos < eap_data.len);
+
+ in = eap_payload_create_data(eap_data);
+ chunk_free(&eap_data);
payload = (payload_t*)in;
if (payload->verify(payload) != SUCCESS)
@@ -98,7 +163,8 @@ METHOD(tls_application_t, process, status_t,
}
code = in->get_code(in);
received_type = in->get_type(in, &received_vendor);
- DBG1(DBG_IKE, "received tunneled EAP-TTLS AVP [EAP/%N/%N]",
+ DBG1(DBG_IKE, "received tunneled EAP-TTLS AVP%s [EAP/%N/%N]",
+ concatenated ? "s" : "",
eap_code_short_names, code,
eap_type_short_names, received_type);
if (code != EAP_REQUEST)