diff options
Diffstat (limited to 'src/libtls')
-rw-r--r-- | src/libtls/Makefile.in | 5 | ||||
-rw-r--r-- | src/libtls/tests/Makefile.in | 5 | ||||
-rw-r--r-- | src/libtls/tls.c | 9 | ||||
-rw-r--r-- | src/libtls/tls.h | 7 | ||||
-rw-r--r-- | src/libtls/tls_eap.c | 7 | ||||
-rw-r--r-- | src/libtls/tls_eap.h | 7 | ||||
-rw-r--r-- | src/libtls/tls_fragmentation.c | 35 | ||||
-rw-r--r-- | src/libtls/tls_fragmentation.h | 4 | ||||
-rw-r--r-- | src/libtls/tls_handshake.h | 7 | ||||
-rw-r--r-- | src/libtls/tls_peer.c | 40 | ||||
-rw-r--r-- | src/libtls/tls_protection.c | 11 | ||||
-rw-r--r-- | src/libtls/tls_server.c | 23 | ||||
-rw-r--r-- | src/libtls/tls_socket.c | 15 |
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, ¤t, &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) |