mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 13:57:35 +00:00
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.
This commit is contained in:
parent
e5e8e8ab96
commit
d54d2892a9
5 changed files with 52 additions and 15 deletions
|
@ -238,6 +238,16 @@ ssize_t TLSv12::handle_finished(const ByteBuffer& buffer, WritePacketStage& writ
|
||||||
#endif
|
#endif
|
||||||
m_context.connection_status = ConnectionStatus::Established;
|
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);
|
return handle_message(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,4 +167,11 @@ ByteBuffer TLSv12::build_finished()
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TLSv12::alert(AlertLevel level, AlertDescription code)
|
||||||
|
{
|
||||||
|
auto the_alert = build_alert(level == AlertLevel::Critical, (u8)code);
|
||||||
|
write_packet(the_alert);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,9 +311,7 @@ ssize_t TLSv12::handle_message(const ByteBuffer& buffer)
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
// close notify
|
// close notify
|
||||||
res += 2;
|
res += 2;
|
||||||
auto closure_alert = build_alert(true, (u8)AlertDescription::CloseNotify);
|
alert(AlertLevel::Critical, AlertDescription::CloseNotify);
|
||||||
write_packet(closure_alert);
|
|
||||||
flush();
|
|
||||||
m_context.connection_finished = true;
|
m_context.connection_finished = true;
|
||||||
}
|
}
|
||||||
m_context.error_code = (Error)code;
|
m_context.error_code = (Error)code;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibCore/DateTime.h>
|
||||||
#include <LibCore/Timer.h>
|
#include <LibCore/Timer.h>
|
||||||
#include <LibCrypto/ASN1/DER.h>
|
#include <LibCrypto/ASN1/DER.h>
|
||||||
#include <LibCrypto/PK/Code/EMSA_PSS.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_connected = [this] {
|
||||||
Core::Socket::on_ready_to_read = [this] {
|
Core::Socket::on_ready_to_read = [this] {
|
||||||
read_from_socket();
|
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)
|
if (on_tls_connected)
|
||||||
on_tls_connected();
|
on_tls_connected();
|
||||||
};
|
};
|
||||||
|
@ -138,7 +157,7 @@ void TLSv12::read_from_socket()
|
||||||
|
|
||||||
if (!check_connection_state(true))
|
if (!check_connection_state(true))
|
||||||
return;
|
return;
|
||||||
flush();
|
|
||||||
consume(Core::Socket::read(4096));
|
consume(Core::Socket::read(4096));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +171,10 @@ void TLSv12::write_into_socket()
|
||||||
return;
|
return;
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
if (!is_established()) {
|
if (!is_established())
|
||||||
deferred_invoke([this](auto&) { write_into_socket(); });
|
|
||||||
m_has_scheduled_write_flush = true;
|
|
||||||
return;
|
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)
|
if (on_tls_ready_to_write)
|
||||||
on_tls_ready_to_write(*this);
|
on_tls_ready_to_write(*this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,7 @@ enum class Error : i8 {
|
||||||
FeatureNotSupported = -17,
|
FeatureNotSupported = -17,
|
||||||
DecryptionFailed = -20,
|
DecryptionFailed = -20,
|
||||||
NeedMoreData = -21,
|
NeedMoreData = -21,
|
||||||
|
TimedOut = -22,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AlertLevel : u8 {
|
enum class AlertLevel : u8 {
|
||||||
|
@ -293,6 +294,8 @@ struct Context {
|
||||||
StringView negotiated_alpn;
|
StringView negotiated_alpn;
|
||||||
|
|
||||||
size_t send_retries { 0 };
|
size_t send_retries { 0 };
|
||||||
|
|
||||||
|
time_t handshake_initiation_timestamp { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class TLSv12 : public Core::Socket {
|
class TLSv12 : public Core::Socket {
|
||||||
|
@ -335,7 +338,7 @@ public:
|
||||||
ByteBuffer read(size_t max_size);
|
ByteBuffer read(size_t max_size);
|
||||||
|
|
||||||
bool write(const ByteBuffer& buffer);
|
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_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; }
|
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_local;
|
||||||
OwnPtr<Crypto::Cipher::AESCipher::CBCMode> m_aes_remote;
|
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 {
|
namespace Constants {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue