aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2010-08-12 23:56:44 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2010-08-12 23:58:54 +0200
commit1327839da8e92c101dbe160d6e82d83b5ed6e788 (patch)
tree87136a6eae9a99ae5b58eb8f8fac3297ccc3a7ee
parent123a84d3dba9c5e88f101aab222db44e25db5a4a (diff)
downloadstrongswan-1327839da8e92c101dbe160d6e82d83b5ed6e788.tar.bz2
strongswan-1327839da8e92c101dbe160d6e82d83b5ed6e788.tar.xz
added generic TLS application data handler and specific EAP-TTLS instantiation
-rw-r--r--src/libcharon/plugins/eap_tls/eap_tls.c3
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.am3
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls.c13
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.c96
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.h46
-rw-r--r--src/libtls/Makefile.am2
-rw-r--r--src/libtls/tls.c13
-rw-r--r--src/libtls/tls.h6
-rw-r--r--src/libtls/tls_application.h64
-rw-r--r--src/libtls/tls_fragmentation.c96
-rw-r--r--src/libtls/tls_fragmentation.h5
-rw-r--r--src/libtls/tls_handshake.h7
-rw-r--r--src/libtls/tls_peer.c7
-rw-r--r--src/libtls/tls_server.c7
14 files changed, 335 insertions, 33 deletions
diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c
index a2407e51d..e4f12d7f6 100644
--- a/src/libcharon/plugins/eap_tls/eap_tls.c
+++ b/src/libcharon/plugins/eap_tls/eap_tls.c
@@ -433,7 +433,8 @@ static eap_tls_t *eap_tls_create(identification_t *server,
.is_server = is_server,
);
/* MSK PRF ASCII constant label according to EAP-TLS RFC 5216 */
- this->tls = tls_create(is_server, server, peer, "client EAP encryption");
+ this->tls = tls_create(is_server, server, peer, "client EAP encryption",
+ NULL);
return &this->public;
}
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am
index fdd4606d0..47be97908 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.am
+++ b/src/libcharon/plugins/eap_ttls/Makefile.am
@@ -12,6 +12,7 @@ libstrongswan_eap_ttls_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
endif
libstrongswan_eap_ttls_la_SOURCES = \
- eap_ttls_plugin.h eap_ttls_plugin.c eap_ttls.h eap_ttls.c
+ eap_ttls_plugin.h eap_ttls_plugin.c eap_ttls.h eap_ttls.c \
+ eap_ttls_peer.h eap_ttls_peer.c
libstrongswan_eap_ttls_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c
index 1139a3f3d..04ae13854 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c
@@ -14,6 +14,7 @@
*/
#include "eap_ttls.h"
+#include "eap_ttls_peer.h"
#include <tls.h>
@@ -423,7 +424,8 @@ METHOD(eap_method_t, destroy, void,
* Generic private constructor
*/
static eap_ttls_t *eap_ttls_create(identification_t *server,
- identification_t *peer, bool is_server)
+ identification_t *peer, bool is_server,
+ tls_application_t *application)
{
private_eap_ttls_t *this;
@@ -439,19 +441,20 @@ static eap_ttls_t *eap_ttls_create(identification_t *server,
.is_server = is_server,
);
/* MSK PRF ASCII constant label according to EAP-TTLS RFC 5281 */
- this->tls = tls_create(is_server, server, peer, "ttls keying material");
-
+ this->tls = tls_create(is_server, server, peer, "ttls keying material",
+ application);
return &this->public;
}
eap_ttls_t *eap_ttls_create_server(identification_t *server,
identification_t *peer)
{
- return eap_ttls_create(server, peer, TRUE);
+ return eap_ttls_create(server, peer, TRUE, NULL);
}
eap_ttls_t *eap_ttls_create_peer(identification_t *server,
identification_t *peer)
{
- return eap_ttls_create(server, peer, FALSE);
+ return eap_ttls_create(server, peer, FALSE,
+ &eap_ttls_peer_create(peer)->application);
}
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
new file mode 100644
index 000000000..0e4d70fa8
--- /dev/null
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_ttls_peer.h"
+
+#include <debug.h>
+
+#define AVP_EAP_MESSAGE 79
+
+typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t;
+
+/**
+ * Private data of an eap_ttls_peer_t object.
+ */
+struct private_eap_ttls_peer_t {
+
+ /**
+ * Public eap_ttls_peer_t interface.
+ */
+ eap_ttls_peer_t public;
+
+ /**
+ * Peer identity
+ */
+ identification_t *peer;
+
+ /**
+ * EAP-TTLS state information
+ */
+ bool start_phase2;
+};
+
+
+METHOD(tls_application_t, process, status_t,
+ private_eap_ttls_peer_t *this, tls_reader_t *reader)
+{
+ return NEED_MORE;
+}
+
+METHOD(tls_application_t, build, status_t,
+ private_eap_ttls_peer_t *this, tls_writer_t *writer)
+{
+ if (this->start_phase2)
+ {
+ chunk_t data = chunk_from_chars(
+ 0x02, 0x00, 0x00, 10, 0x01, 'c', 'a', 'r', 'o', 'l', 0x00, 0x00);
+ u_int8_t avp_flags = 0x40;
+ u_int32_t avp_len;
+
+ avp_len = 8 + data.len - 2;
+ writer->write_uint32(writer, AVP_EAP_MESSAGE);
+ writer->write_uint8(writer, avp_flags);
+ writer->write_uint24(writer, avp_len);
+ writer->write_data(writer, data);
+ this->start_phase2 = FALSE;
+ }
+ return INVALID_STATE;
+}
+
+METHOD(tls_application_t, destroy, void,
+ private_eap_ttls_peer_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_ttls_peer_t *eap_ttls_peer_create(identification_t *peer)
+{
+ private_eap_ttls_peer_t *this;
+
+ INIT(this,
+ .public.application = {
+ .process = _process,
+ .build = _build,
+ .destroy = _destroy,
+ },
+ .peer = peer,
+ .start_phase2 = TRUE,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h
new file mode 100644
index 000000000..0338f2631
--- /dev/null
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tls_peer tls_peer
+ * @{ @ingroup libtls
+ */
+
+#ifndef EAP_TTLS_PEER_H_
+#define EAP_TTLS_PEER_H_
+
+typedef struct eap_ttls_peer_t eap_ttls_peer_t;
+
+#include "tls_application.h"
+
+#include <library.h>
+
+/**
+ * TLS application data handler as peer.
+ */
+struct eap_ttls_peer_t {
+
+ /**
+ * Implements the TLS application data handler.
+ */
+ tls_application_t application;
+};
+
+/**
+ * Create an eap_ttls_peer instance.
+ */
+eap_ttls_peer_t *eap_ttls_peer_create(identification_t *peer);
+
+#endif /** EAP_TTLS_PEER_H_ @}*/
diff --git a/src/libtls/Makefile.am b/src/libtls/Makefile.am
index d61cd8477..5e112f601 100644
--- a/src/libtls/Makefile.am
+++ b/src/libtls/Makefile.am
@@ -12,4 +12,4 @@ libtls_la_SOURCES = \
tls_writer.h tls_writer.c \
tls_peer.h tls_peer.c \
tls_server.h tls_server.c \
- tls_handshake.h tls.h tls.c
+ tls_handshake.h tls_application.h tls.h tls.c
diff --git a/src/libtls/tls.c b/src/libtls/tls.c
index f8f7e848e..24f442ca9 100644
--- a/src/libtls/tls.c
+++ b/src/libtls/tls.c
@@ -110,6 +110,11 @@ struct private_tls_t {
* TLS handshake protocol handler
*/
tls_handshake_t *handshake;
+
+ /**
+ * TLS application data handler
+ */
+ tls_application_t *application;
};
METHOD(tls_t, process, status_t,
@@ -164,6 +169,7 @@ METHOD(tls_t, destroy, void,
this->handshake->destroy(this->handshake);
this->peer->destroy(this->peer);
this->server->destroy(this->server);
+ DESTROY_IF(this->application);
free(this);
}
@@ -172,7 +178,8 @@ METHOD(tls_t, destroy, void,
* See header
*/
tls_t *tls_create(bool is_server, identification_t *server,
- identification_t *peer, char *msk_label)
+ identification_t *peer, char *msk_label,
+ tls_application_t *application)
{
private_tls_t *this;
@@ -191,6 +198,7 @@ tls_t *tls_create(bool is_server, identification_t *server,
.version = TLS_1_2,
.server = server->clone(server),
.peer = peer->clone(peer),
+ .application = application,
);
this->crypto = tls_crypto_create(&this->public, msk_label);
@@ -204,7 +212,8 @@ tls_t *tls_create(bool is_server, identification_t *server,
this->handshake = &tls_peer_create(&this->public, this->crypto,
this->peer, this->server)->handshake;
}
- this->fragmentation = tls_fragmentation_create(this->handshake);
+ this->fragmentation = tls_fragmentation_create(this->handshake,
+ this->application);
this->compression = tls_compression_create(this->fragmentation);
this->protection = tls_protection_create(&this->public, this->compression);
this->crypto->set_protection(this->crypto, this->protection);
diff --git a/src/libtls/tls.h b/src/libtls/tls.h
index 923c87ae1..ea66b7661 100644
--- a/src/libtls/tls.h
+++ b/src/libtls/tls.h
@@ -33,6 +33,8 @@ typedef struct tls_t tls_t;
#include <library.h>
+#include "tls_application.h"
+
/**
* TLS/SSL version numbers
*/
@@ -163,9 +165,11 @@ struct tls_t {
* @param server server identity
* @param peer peer identity
* @param msk_label ASCII string constant used as seed for MSK PRF
+ * @param application higher layer application or NULL if none
* @return TLS stack
*/
tls_t *tls_create(bool is_server, identification_t *server,
- identification_t *peer, char *msk_label);
+ identification_t *peer, char *msk_label,
+ tls_application_t *application);
#endif /** TLS_H_ @}*/
diff --git a/src/libtls/tls_application.h b/src/libtls/tls_application.h
new file mode 100644
index 000000000..dacd10ef7
--- /dev/null
+++ b/src/libtls/tls_application.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tls_handshake tls_handshake
+ * @{ @ingroup libtls
+ */
+
+#ifndef TLS_APPLICATION_H_
+#define TLS_APPLICATION_H_
+
+typedef struct tls_application_t tls_application_t;
+
+#include "tls.h"
+#include "tls_reader.h"
+#include "tls_writer.h"
+
+/**
+ * TLS application data interface.
+ */
+struct tls_application_t {
+
+ /**
+ * Process received TLS application data.
+ *
+ * @param reader TLS data buffer
+ * @return
+ * - SUCCESS if application completed
+ * - FAILED if application data processing failed
+ * - NEED_MORE if another invocation of process/build needed
+ */
+ status_t (*process)(tls_application_t *this, tls_reader_t *reader);
+
+ /**
+ * Build TLS application data to send out.
+ *
+ * @param writer TLS data buffer to write to
+ * @return
+ * - SUCCESS if application completed
+ * - FAILED if application data build failed
+ * - NEED_MORE if more data ready for delivery
+ * - INVALID_STATE if more input to process() required
+ */
+ status_t (*build)(tls_application_t *this, tls_writer_t *writer);
+
+ /**
+ * Destroy a tls_application_t.
+ */
+ void (*destroy)(tls_application_t *this);
+};
+
+#endif /** TLS_APPLICATION_H_ @}*/
diff --git a/src/libtls/tls_fragmentation.c b/src/libtls/tls_fragmentation.c
index f95fe4f2e..835a3c9f5 100644
--- a/src/libtls/tls_fragmentation.c
+++ b/src/libtls/tls_fragmentation.c
@@ -55,6 +55,11 @@ struct private_tls_fragmentation_t {
* Handshake output buffer
*/
chunk_t output;
+
+ /**
+ * Upper layer application data protocol
+ */
+ tls_application_t *application;
};
/**
@@ -133,6 +138,33 @@ static status_t process_handshake(private_tls_fragmentation_t *this,
return NEED_MORE;
}
+/**
+ * Process TLS application data
+ */
+static status_t process_application(private_tls_fragmentation_t *this,
+ tls_reader_t *reader)
+{
+ while (reader->remaining(reader))
+ {
+ u_int32_t len;
+ chunk_t data;
+
+ if (reader->remaining(reader) > MAX_TLS_FRAGMENT_LEN)
+ {
+ DBG1(DBG_IKE, "TLS fragment has invalid length");
+ return FAILED;
+ }
+
+ len = reader->remaining(reader);
+ if (!reader->read_data(reader, len, &data))
+ {
+ return FAILED;
+ }
+ DBG1(DBG_IKE, "received TLS application data: %B", &data);
+ }
+ return NEED_MORE;
+}
+
METHOD(tls_fragmentation_t, process, status_t,
private_tls_fragmentation_t *this, tls_content_type_t type, chunk_t data)
{
@@ -158,8 +190,7 @@ METHOD(tls_fragmentation_t, process, status_t,
status = process_handshake(this, reader);
break;
case TLS_APPLICATION_DATA:
- /* skip application data */
- status = NEED_MORE;
+ status = process_application(this, reader);
break;
default:
DBG1(DBG_IKE, "received unknown TLS content type %d, ignored", type);
@@ -175,7 +206,7 @@ METHOD(tls_fragmentation_t, build, status_t,
{
tls_handshake_type_t hs_type;
tls_writer_t *writer, *msg;
- status_t status;
+ status_t status = INVALID_STATE;
if (this->handshake->cipherspec_changed(this->handshake))
{
@@ -187,27 +218,47 @@ METHOD(tls_fragmentation_t, build, status_t,
if (!this->output.len)
{
msg = tls_writer_create(64);
- do
+
+ if (this->handshake->finished(this->handshake))
{
- writer = tls_writer_create(64);
- status = this->handshake->build(this->handshake, &hs_type, writer);
- switch (status)
+ if (this->application)
{
- case NEED_MORE:
- DBG2(DBG_IKE, "sending TLS %N message",
- tls_handshake_type_names, hs_type);
- msg->write_uint8(msg, hs_type);
- msg->write_data24(msg, writer->get_buf(writer));
- break;
- case INVALID_STATE:
+ status = this->application->build(this->application, msg);
+ if (status == INVALID_STATE)
+ {
this->output = chunk_clone(msg->get_buf(msg));
- break;
- default:
- break;
+ if (this->output.len)
+ {
+ DBG2(DBG_IKE, "sending TLS application data: %B",
+ &this->output);
+ }
+ }
+ }
+ }
+ else
+ {
+ do
+ {
+ writer = tls_writer_create(64);
+ status = this->handshake->build(this->handshake, &hs_type, writer);
+ switch (status)
+ {
+ case NEED_MORE:
+ DBG2(DBG_IKE, "sending TLS %N message",
+ tls_handshake_type_names, hs_type);
+ msg->write_uint8(msg, hs_type);
+ msg->write_data24(msg, writer->get_buf(writer));
+ break;
+ case INVALID_STATE:
+ this->output = chunk_clone(msg->get_buf(msg));
+ break;
+ default:
+ break;
+ }
+ writer->destroy(writer);
}
- writer->destroy(writer);
+ while (status == NEED_MORE);
}
- while (status == NEED_MORE);
msg->destroy(msg);
if (status != INVALID_STATE)
@@ -218,7 +269,8 @@ METHOD(tls_fragmentation_t, build, status_t,
if (this->output.len)
{
- *type = TLS_HANDSHAKE;
+ *type = this->handshake->finished(this->handshake) ?
+ TLS_APPLICATION_DATA : TLS_HANDSHAKE;
if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
{
*data = this->output;
@@ -243,7 +295,8 @@ METHOD(tls_fragmentation_t, destroy, void,
/**
* See header
*/
-tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake)
+tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
+ tls_application_t *application)
{
private_tls_fragmentation_t *this;
@@ -254,6 +307,7 @@ tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake)
.destroy = _destroy,
},
.handshake = handshake,
+ .application = application,
);
return &this->public;
diff --git a/src/libtls/tls_fragmentation.h b/src/libtls/tls_fragmentation.h
index e141a334b..6adbc36d0 100644
--- a/src/libtls/tls_fragmentation.h
+++ b/src/libtls/tls_fragmentation.h
@@ -27,6 +27,7 @@ typedef struct tls_fragmentation_t tls_fragmentation_t;
#include "tls.h"
#include "tls_handshake.h"
+#include "tls_handshake.h"
/**
* TLS record protocol fragmentation layer.
@@ -70,8 +71,10 @@ struct tls_fragmentation_t {
* Create a tls_fragmentation instance.
*
* @param handshake upper layer handshake protocol
+ * @param application upper layer application data or NULL
* @return TLS fragmentation layer.
*/
-tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake);
+tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
+ tls_application_t *application);
#endif /** TLS_FRAGMENTATION_H_ @}*/
diff --git a/src/libtls/tls_handshake.h b/src/libtls/tls_handshake.h
index c0798625e..3aab3c527 100644
--- a/src/libtls/tls_handshake.h
+++ b/src/libtls/tls_handshake.h
@@ -74,6 +74,13 @@ struct tls_handshake_t {
bool (*change_cipherspec)(tls_handshake_t *this);
/**
+ * Check if the finished message was decoded successfully.
+ *
+ * @return TRUE if finished message was decoded successfully
+ */
+ bool (*finished)(tls_handshake_t *this);
+
+ /**
* Destroy a tls_handshake_t.
*/
void (*destroy)(tls_handshake_t *this);
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index 221b629a5..79f97ae40 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -621,6 +621,12 @@ METHOD(tls_handshake_t, change_cipherspec, bool,
return FALSE;
}
+METHOD(tls_handshake_t, finished, bool,
+ private_tls_peer_t *this)
+{
+ return this->state == STATE_COMPLETE;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_peer_t *this)
{
@@ -644,6 +650,7 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto,
.build = _build,
.cipherspec_changed = _cipherspec_changed,
.change_cipherspec = _change_cipherspec,
+ .finished = _finished,
.destroy = _destroy,
},
.state = STATE_INIT,
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index 8d2c961ea..673b20145 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -583,6 +583,12 @@ METHOD(tls_handshake_t, change_cipherspec, bool,
return FALSE;
}
+METHOD(tls_handshake_t, finished, bool,
+ private_tls_server_t *this)
+{
+ return this->state == STATE_FINISHED_SENT;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_server_t *this)
{
@@ -606,6 +612,7 @@ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
.build = _build,
.cipherspec_changed = _cipherspec_changed,
.change_cipherspec = _change_cipherspec,
+ .finished = _finished,
.destroy = _destroy,
},
.tls = tls,