summaryrefslogtreecommitdiff
path: root/Libraries/LibTLS
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-05-30 19:53:07 +0430
committerAndreas Kling <kling@serenityos.org>2020-05-30 18:26:13 +0200
commitd54d2892a9bbf46adc3430871fb74502917f9ec3 (patch)
tree9904e43d8c8d9c6648a14195612390ba67f74c75 /Libraries/LibTLS
parente5e8e8ab96c1489bb193236b9485e39d7b34b2a5 (diff)
downloadserenity-d54d2892a9bbf46adc3430871fb74502917f9ec3.zip
LibTLS: Avoid busy-wait between ClientHello and ServerHello
This commit also adds a timeout timer to cancel the connection if the server does not respond to the hello request in 10 seconds.
Diffstat (limited to 'Libraries/LibTLS')
-rw-r--r--Libraries/LibTLS/ClientHandshake.cpp10
-rw-r--r--Libraries/LibTLS/Handshake.cpp7
-rw-r--r--Libraries/LibTLS/Record.cpp4
-rw-r--r--Libraries/LibTLS/Socket.cpp36
-rw-r--r--Libraries/LibTLS/TLSv12.h10
5 files changed, 52 insertions, 15 deletions
diff --git a/Libraries/LibTLS/ClientHandshake.cpp b/Libraries/LibTLS/ClientHandshake.cpp
index dcf20543d9..28d27215dc 100644
--- a/Libraries/LibTLS/ClientHandshake.cpp
+++ b/Libraries/LibTLS/ClientHandshake.cpp
@@ -238,6 +238,16 @@ ssize_t TLSv12::handle_finished(const ByteBuffer& buffer, WritePacketStage& writ
#endif
m_context.connection_status = ConnectionStatus::Established;
+ if (m_handshake_timeout_timer) {
+ // Disable the handshake timeout timer as handshake has been established.
+ m_handshake_timeout_timer->stop();
+ m_handshake_timeout_timer->remove_from_parent();
+ m_handshake_timeout_timer = nullptr;
+ }
+
+ if (on_tls_ready_to_write)
+ on_tls_ready_to_write(*this);
+
return handle_message(buffer);
}
diff --git a/Libraries/LibTLS/Handshake.cpp b/Libraries/LibTLS/Handshake.cpp
index e209f11d8a..99165fec5b 100644
--- a/Libraries/LibTLS/Handshake.cpp
+++ b/Libraries/LibTLS/Handshake.cpp
@@ -167,4 +167,11 @@ ByteBuffer TLSv12::build_finished()
return packet;
}
+void TLSv12::alert(AlertLevel level, AlertDescription code)
+{
+ auto the_alert = build_alert(level == AlertLevel::Critical, (u8)code);
+ write_packet(the_alert);
+ flush();
+}
+
}
diff --git a/Libraries/LibTLS/Record.cpp b/Libraries/LibTLS/Record.cpp
index ee62426423..19fb65f440 100644
--- a/Libraries/LibTLS/Record.cpp
+++ b/Libraries/LibTLS/Record.cpp
@@ -311,9 +311,7 @@ ssize_t TLSv12::handle_message(const ByteBuffer& buffer)
if (code == 0) {
// close notify
res += 2;
- auto closure_alert = build_alert(true, (u8)AlertDescription::CloseNotify);
- write_packet(closure_alert);
- flush();
+ alert(AlertLevel::Critical, AlertDescription::CloseNotify);
m_context.connection_finished = true;
}
m_context.error_code = (Error)code;
diff --git a/Libraries/LibTLS/Socket.cpp b/Libraries/LibTLS/Socket.cpp
index 62d95d43d0..b5f4fcf3ca 100644
--- a/Libraries/LibTLS/Socket.cpp
+++ b/Libraries/LibTLS/Socket.cpp
@@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <LibCore/DateTime.h>
#include <LibCore/Timer.h>
#include <LibCrypto/ASN1/DER.h>
#include <LibCrypto/PK/Code/EMSA_PSS.h>
@@ -110,14 +111,32 @@ bool TLSv12::common_connect(const struct sockaddr* saddr, socklen_t length)
}
}
- auto packet = build_hello();
- write_packet(packet);
-
Core::Socket::on_connected = [this] {
Core::Socket::on_ready_to_read = [this] {
read_from_socket();
};
- write_into_socket();
+
+ auto packet = build_hello();
+ write_packet(packet);
+
+ deferred_invoke([&](auto&) {
+ m_handshake_timeout_timer = Core::Timer::create_single_shot(
+ m_max_wait_time_for_handshake_in_seconds * 1000, [&] {
+ // The server did not respond fast enough,
+ // time the connection out.
+ alert(AlertLevel::Critical, AlertDescription::UserCanceled);
+ m_context.connection_finished = true;
+ m_context.tls_buffer.clear();
+ m_context.error_code = Error::TimedOut;
+ m_context.critical_error = (u8)Error::TimedOut;
+ check_connection_state(false); // Notify the client.
+ },
+ this);
+ write_into_socket();
+ m_handshake_timeout_timer->start();
+ });
+ m_has_scheduled_write_flush = true;
+
if (on_tls_connected)
on_tls_connected();
};
@@ -138,7 +157,7 @@ void TLSv12::read_from_socket()
if (!check_connection_state(true))
return;
- flush();
+
consume(Core::Socket::read(4096));
}
@@ -152,13 +171,10 @@ void TLSv12::write_into_socket()
return;
flush();
- if (!is_established()) {
- deferred_invoke([this](auto&) { write_into_socket(); });
- m_has_scheduled_write_flush = true;
+ if (!is_established())
return;
- }
- if (is_established() && !m_context.application_buffer.size()) // hey client, you still have stuff to read...
+ if (!m_context.application_buffer.size()) // hey client, you still have stuff to read...
if (on_tls_ready_to_write)
on_tls_ready_to_write(*this);
}
diff --git a/Libraries/LibTLS/TLSv12.h b/Libraries/LibTLS/TLSv12.h
index 6a104092eb..ab9ca33ff5 100644
--- a/Libraries/LibTLS/TLSv12.h
+++ b/Libraries/LibTLS/TLSv12.h
@@ -142,6 +142,7 @@ enum class Error : i8 {
FeatureNotSupported = -17,
DecryptionFailed = -20,
NeedMoreData = -21,
+ TimedOut = -22,
};
enum class AlertLevel : u8 {
@@ -293,6 +294,8 @@ struct Context {
StringView negotiated_alpn;
size_t send_retries { 0 };
+
+ time_t handshake_initiation_timestamp { 0 };
};
class TLSv12 : public Core::Socket {
@@ -335,7 +338,7 @@ public:
ByteBuffer read(size_t max_size);
bool write(const ByteBuffer& buffer);
- void alert(bool critical, u8 code);
+ void alert(AlertLevel, AlertDescription);
bool can_read_line() const { return m_context.application_buffer.size() && memchr(m_context.application_buffer.data(), '\n', m_context.application_buffer.size()); }
bool can_read() const { return m_context.application_buffer.size() > 0; }
@@ -467,7 +470,10 @@ private:
OwnPtr<Crypto::Cipher::AESCipher::CBCMode> m_aes_local;
OwnPtr<Crypto::Cipher::AESCipher::CBCMode> m_aes_remote;
- bool m_has_scheduled_write_flush = false;
+ bool m_has_scheduled_write_flush { false };
+ i32 m_max_wait_time_for_handshake_in_seconds { 10 };
+
+ RefPtr<Core::Timer> m_handshake_timeout_timer;
};
namespace Constants {