summaryrefslogtreecommitdiff
path: root/src/libtls
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtls')
-rw-r--r--src/libtls/Makefile.in5
-rw-r--r--src/libtls/tests/Makefile.in5
-rw-r--r--src/libtls/tls.c9
-rw-r--r--src/libtls/tls.h7
-rw-r--r--src/libtls/tls_eap.c7
-rw-r--r--src/libtls/tls_eap.h7
-rw-r--r--src/libtls/tls_fragmentation.c35
-rw-r--r--src/libtls/tls_fragmentation.h4
-rw-r--r--src/libtls/tls_handshake.h7
-rw-r--r--src/libtls/tls_peer.c40
-rw-r--r--src/libtls/tls_protection.c11
-rw-r--r--src/libtls/tls_server.c23
-rw-r--r--src/libtls/tls_socket.c15
13 files changed, 148 insertions, 27 deletions
diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in
index 426d8bcb3..e6c23d970 100644
--- a/src/libtls/Makefile.in
+++ b/src/libtls/Makefile.in
@@ -278,6 +278,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -338,10 +339,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -415,6 +418,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtls/tests/Makefile.in b/src/libtls/tests/Makefile.in
index 2e44fb4a5..7d5b3771c 100644
--- a/src/libtls/tests/Makefile.in
+++ b/src/libtls/tests/Makefile.in
@@ -223,6 +223,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -283,10 +284,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -360,6 +363,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtls/tls.c b/src/libtls/tls.c
index 6a8d5030c..08a06f5ef 100644
--- a/src/libtls/tls.c
+++ b/src/libtls/tls.c
@@ -415,6 +415,12 @@ METHOD(tls_t, get_eap_msk, chunk_t,
return this->crypto->get_eap_msk(this->crypto);
}
+METHOD(tls_t, get_auth, auth_cfg_t*,
+ private_tls_t *this)
+{
+ return this->handshake->get_auth(this->handshake);
+}
+
METHOD(tls_t, destroy, void,
private_tls_t *this)
{
@@ -465,6 +471,7 @@ tls_t *tls_create(bool is_server, identification_t *server,
.get_purpose = _get_purpose,
.is_complete = _is_complete,
.get_eap_msk = _get_eap_msk,
+ .get_auth = _get_auth,
.destroy = _destroy,
},
.is_server = is_server,
@@ -487,7 +494,7 @@ tls_t *tls_create(bool is_server, identification_t *server,
this->alert, peer, server)->handshake;
}
this->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
- this->application);
+ this->application, purpose);
this->compression = tls_compression_create(this->fragmentation, this->alert);
this->protection = tls_protection_create(this->compression, this->alert);
this->crypto->set_protection(this->crypto, this->protection);
diff --git a/src/libtls/tls.h b/src/libtls/tls.h
index fc1d9b9fd..f3dc198cf 100644
--- a/src/libtls/tls.h
+++ b/src/libtls/tls.h
@@ -252,6 +252,13 @@ struct tls_t {
chunk_t (*get_eap_msk)(tls_t *this);
/**
+ * Get the authentication details after completing the handshake.
+ *
+ * @return authentication details, internal data
+ */
+ auth_cfg_t* (*get_auth)(tls_t *this);
+
+ /**
* Destroy a tls_t.
*/
void (*destroy)(tls_t *this);
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index ebe5bc3a8..12d5aed53 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -426,6 +426,12 @@ METHOD(tls_eap_t, set_identifier, void,
this->identifier = identifier;
}
+METHOD(tls_eap_t, get_auth, auth_cfg_t*,
+ private_tls_eap_t *this)
+{
+ return this->tls->get_auth(this->tls);
+}
+
METHOD(tls_eap_t, destroy, void,
private_tls_eap_t *this)
{
@@ -453,6 +459,7 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
.get_msk = _get_msk,
.get_identifier = _get_identifier,
.set_identifier = _set_identifier,
+ .get_auth = _get_auth,
.destroy = _destroy,
},
.type = type,
diff --git a/src/libtls/tls_eap.h b/src/libtls/tls_eap.h
index f3fbba078..df41fc4d7 100644
--- a/src/libtls/tls_eap.h
+++ b/src/libtls/tls_eap.h
@@ -77,6 +77,13 @@ struct tls_eap_t {
void (*set_identifier) (tls_eap_t *this, uint8_t identifier);
/**
+ * Get the authentication details after completing the handshake.
+ *
+ * @return authentication details, internal data
+ */
+ auth_cfg_t* (*get_auth)(tls_eap_t *this);
+
+ /**
* Destroy a tls_eap_t.
*/
void (*destroy)(tls_eap_t *this);
diff --git a/src/libtls/tls_fragmentation.c b/src/libtls/tls_fragmentation.c
index 6e4347e3c..a97ca1eaa 100644
--- a/src/libtls/tls_fragmentation.c
+++ b/src/libtls/tls_fragmentation.c
@@ -96,9 +96,32 @@ struct private_tls_fragmentation_t {
* Upper layer application data protocol
*/
tls_application_t *application;
+
+ /**
+ * Type of context this TLS instance runs in
+ */
+ tls_purpose_t purpose;
};
/**
+ * Check if we should send a close notify once the application finishes
+ */
+static bool send_close_notify(private_tls_fragmentation_t *this)
+{
+ switch (this->purpose)
+ {
+ case TLS_PURPOSE_EAP_TLS:
+ case TLS_PURPOSE_EAP_TTLS:
+ case TLS_PURPOSE_EAP_PEAP:
+ /* not for TLS-in-EAP, as we indicate completion with EAP-SUCCCESS.
+ * Windows does not like close notifies, and hangs/disconnects. */
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+/**
* Process a TLS alert
*/
static status_t process_alert(private_tls_fragmentation_t *this,
@@ -223,6 +246,10 @@ static status_t process_application(private_tls_fragmentation_t *this,
continue;
case SUCCESS:
this->application_finished = TRUE;
+ if (!send_close_notify(this))
+ {
+ return SUCCESS;
+ }
/* FALL */
case FAILED:
default:
@@ -368,6 +395,10 @@ static status_t build_application(private_tls_fragmentation_t *this)
break;
case SUCCESS:
this->application_finished = TRUE;
+ if (!send_close_notify(this))
+ {
+ break;
+ }
/* FALL */
case FAILED:
default:
@@ -463,7 +494,8 @@ METHOD(tls_fragmentation_t, destroy, void,
* See header
*/
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
- tls_alert_t *alert, tls_application_t *application)
+ tls_alert_t *alert, tls_application_t *application,
+ tls_purpose_t purpose)
{
private_tls_fragmentation_t *this;
@@ -478,6 +510,7 @@ tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
.alert = alert,
.state = ALERT_NONE,
.application = application,
+ .purpose = purpose,
);
return &this->public;
diff --git a/src/libtls/tls_fragmentation.h b/src/libtls/tls_fragmentation.h
index f650e7be8..a49f27b20 100644
--- a/src/libtls/tls_fragmentation.h
+++ b/src/libtls/tls_fragmentation.h
@@ -80,9 +80,11 @@ struct tls_fragmentation_t {
* @param handshake upper layer handshake protocol
* @param alert TLS alert handler
* @param application upper layer application data or NULL
+ * @param purpose type of context this TLS stack is running in
* @return TLS fragmentation layer
*/
tls_fragmentation_t *tls_fragmentation_create(tls_handshake_t *handshake,
- tls_alert_t *alert, tls_application_t *application);
+ tls_alert_t *alert, tls_application_t *application,
+ tls_purpose_t purpose);
#endif /** TLS_FRAGMENTATION_H_ @}*/
diff --git a/src/libtls/tls_handshake.h b/src/libtls/tls_handshake.h
index 7fa660c58..7edb49ba0 100644
--- a/src/libtls/tls_handshake.h
+++ b/src/libtls/tls_handshake.h
@@ -98,6 +98,13 @@ struct tls_handshake_t {
identification_t* (*get_server_id)(tls_handshake_t *this);
/**
+ * Get the peers authentication information after completing the handshake.
+ *
+ * @return authentication data, internal data
+ */
+ auth_cfg_t* (*get_auth)(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 a95b40f55..e6be36b7b 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -312,7 +312,7 @@ static status_t process_certificate(private_tls_peer_t *this,
static public_key_t *find_public_key(private_tls_peer_t *this)
{
public_key_t *public = NULL, *current;
- certificate_t *cert;
+ certificate_t *cert, *found;
enumerator_t *enumerator;
auth_cfg_t *auth;
@@ -323,8 +323,13 @@ static public_key_t *find_public_key(private_tls_peer_t *this)
KEY_ANY, cert->get_subject(cert), this->server_auth);
while (enumerator->enumerate(enumerator, &current, &auth))
{
- public = current->get_ref(current);
- break;
+ found = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (found && cert->equals(cert, found))
+ {
+ public = current->get_ref(current);
+ this->server_auth->merge(this->server_auth, auth, FALSE);
+ break;
+ }
}
enumerator->destroy(enumerator);
}
@@ -379,7 +384,12 @@ static status_t process_modp_key_exchange(private_tls_peer_t *this,
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->dh->set_other_public_value(this->dh, pub);
+ if (!this->dh->set_other_public_value(this->dh, pub))
+ {
+ DBG1(DBG_TLS, "applying DH public value failed");
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
this->state = STATE_KEY_EXCHANGE_RECEIVED;
return NEED_MORE;
@@ -489,7 +499,12 @@ static status_t process_ec_key_exchange(private_tls_peer_t *this,
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1));
+ if (!this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1)))
+ {
+ DBG1(DBG_TLS, "applying DH public value failed");
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
this->state = STATE_KEY_EXCHANGE_RECEIVED;
return NEED_MORE;
@@ -968,7 +983,7 @@ static status_t send_key_exchange_dhe(private_tls_peer_t *this,
{
chunk_t premaster, pub;
- if (this->dh->get_shared_secret(this->dh, &premaster) != SUCCESS)
+ if (!this->dh->get_shared_secret(this->dh, &premaster))
{
DBG1(DBG_TLS, "calculating premaster from DH failed");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
@@ -985,7 +1000,11 @@ static status_t send_key_exchange_dhe(private_tls_peer_t *this,
}
chunk_clear(&premaster);
- this->dh->get_my_public_value(this->dh, &pub);
+ if (!this->dh->get_my_public_value(this->dh, &pub))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
if (this->dh->get_dh_group(this->dh) == MODP_CUSTOM)
{
writer->write_data16(writer, pub);
@@ -1153,6 +1172,12 @@ METHOD(tls_handshake_t, get_server_id, identification_t*,
return this->server;
}
+METHOD(tls_handshake_t, get_auth, auth_cfg_t*,
+ private_tls_peer_t *this)
+{
+ return this->server_auth;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_peer_t *this)
{
@@ -1186,6 +1211,7 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert
.finished = _finished,
.get_peer_id = _get_peer_id,
.get_server_id = _get_server_id,
+ .get_auth = _get_auth,
.destroy = _destroy,
},
},
diff --git a/src/libtls/tls_protection.c b/src/libtls/tls_protection.c
index b016db21f..e73fedc5d 100644
--- a/src/libtls/tls_protection.c
+++ b/src/libtls/tls_protection.c
@@ -101,14 +101,13 @@ METHOD(tls_protection_t, build, status_t,
status_t status;
status = this->compression->build(this->compression, type, data);
- if (*type == TLS_CHANGE_CIPHER_SPEC)
- {
- this->seq_out = 0;
- return status;
- }
-
if (status == NEED_MORE)
{
+ if (*type == TLS_CHANGE_CIPHER_SPEC)
+ {
+ this->seq_out = 0;
+ return status;
+ }
if (this->aead_out)
{
if (!this->aead_out->encrypt(this->aead_out, this->version,
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index aeb5a714f..b1a214f7f 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -494,8 +494,13 @@ static status_t process_key_exchange_dhe(private_tls_server_t *this,
}
pub = chunk_skip(pub, 1);
}
- this->dh->set_other_public_value(this->dh, pub);
- if (this->dh->get_shared_secret(this->dh, &premaster) != SUCCESS)
+ if (!this->dh->set_other_public_value(this->dh, pub))
+ {
+ DBG1(DBG_TLS, "applying DH public value failed");
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
+ if (!this->dh->get_shared_secret(this->dh, &premaster))
{
DBG1(DBG_TLS, "calculating premaster from DH failed");
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
@@ -551,6 +556,7 @@ static status_t process_cert_verify(private_tls_server_t *this,
sig->destroy(sig);
if (verified)
{
+ this->peer_auth->merge(this->peer_auth, auth, FALSE);
break;
}
DBG1(DBG_TLS, "signature verification failed, trying another key");
@@ -914,7 +920,11 @@ static status_t send_server_key_exchange(private_tls_server_t *this,
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
return NEED_MORE;
}
- this->dh->get_my_public_value(this->dh, &chunk);
+ if (!this->dh->get_my_public_value(this->dh, &chunk))
+ {
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
+ }
if (params)
{
writer->write_data16(writer, chunk);
@@ -1073,6 +1083,12 @@ METHOD(tls_handshake_t, get_server_id, identification_t*,
return this->server;
}
+METHOD(tls_handshake_t, get_auth, auth_cfg_t*,
+ private_tls_server_t *this)
+{
+ return this->peer_auth;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_server_t *this)
{
@@ -1107,6 +1123,7 @@ tls_server_t *tls_server_create(tls_t *tls,
.finished = _finished,
.get_peer_id = _get_peer_id,
.get_server_id = _get_server_id,
+ .get_auth = _get_auth,
.destroy = _destroy,
},
},
diff --git a/src/libtls/tls_socket.c b/src/libtls/tls_socket.c
index 648771e75..2ccd97571 100644
--- a/src/libtls/tls_socket.c
+++ b/src/libtls/tls_socket.c
@@ -291,25 +291,24 @@ METHOD(tls_socket_t, splice, bool,
private_tls_socket_t *this, int rfd, int wfd)
{
char buf[PLAIN_BUF_SIZE], *pos;
- fd_set set;
ssize_t in, out;
bool old, plain_eof = FALSE, crypto_eof = FALSE;
+ struct pollfd pfd[] = {
+ { .fd = this->fd, .events = POLLIN, },
+ { .fd = rfd, .events = POLLIN, },
+ };
while (!plain_eof && !crypto_eof)
{
- FD_ZERO(&set);
- FD_SET(rfd, &set);
- FD_SET(this->fd, &set);
-
old = thread_cancelability(TRUE);
- in = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL);
+ in = poll(pfd, countof(pfd), -1);
thread_cancelability(old);
if (in == -1)
{
DBG1(DBG_TLS, "TLS select error: %s", strerror(errno));
return FALSE;
}
- while (!plain_eof && FD_ISSET(this->fd, &set))
+ while (!plain_eof && pfd[0].revents & (POLLIN | POLLHUP | POLLNVAL))
{
in = read_(this, buf, sizeof(buf), FALSE);
switch (in)
@@ -342,7 +341,7 @@ METHOD(tls_socket_t, splice, bool,
}
break;
}
- if (!crypto_eof && FD_ISSET(rfd, &set))
+ if (!crypto_eof && pfd[1].revents & (POLLIN | POLLHUP | POLLNVAL))
{
in = read(rfd, buf, sizeof(buf));
switch (in)