mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibTLS+LibHTTP: Tolerate improperly closed TLS sockets
Some really cursed servers simply drop the TCP socket on the floor when they're trying to close an HTTP connection going through a TLS socket. This commit makes LibTLS tolerate these silly servers, and LibHTTP accept their idea of "EOF == connection closed". Fixes loading wpt.live/acid/acid3/test.html. Note that this means TLSv12::on_ready_to_read can fire with an empty buffer signifying EOF; one test refused this behaviour, and has been changed in this commit.
This commit is contained in:
parent
2d90317c20
commit
06386ab2b5
Notes:
sideshowbarker
2024-07-19 16:49:21 +09:00
Author: https://github.com/alimpfard 🔰 Commit: https://github.com/SerenityOS/serenity/commit/06386ab2b5b Pull-request: https://github.com/SerenityOS/serenity/pull/23981
3 changed files with 32 additions and 8 deletions
|
@ -61,11 +61,7 @@ TEST_CASE(test_TLS_hello_handshake)
|
|||
auto tls = TRY_OR_FAIL(TLS::TLSv12::connect(DEFAULT_SERVER, port, move(options)));
|
||||
ByteBuffer contents;
|
||||
tls->on_ready_to_read = [&] {
|
||||
auto read_bytes = TRY_OR_FAIL(tls->read_some(contents.must_get_bytes_for_writing(4 * KiB)));
|
||||
if (read_bytes.is_empty()) {
|
||||
FAIL("No data received");
|
||||
loop.quit(1);
|
||||
}
|
||||
(void)TRY_OR_FAIL(tls->read_some(contents.must_get_bytes_for_writing(4 * KiB)));
|
||||
loop.quit(0);
|
||||
};
|
||||
|
||||
|
|
|
@ -223,8 +223,20 @@ void Job::on_socket_connected()
|
|||
}
|
||||
|
||||
if (m_socket->is_eof()) {
|
||||
dbgln_if(JOB_DEBUG, "Read failure: Actually EOF!");
|
||||
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
||||
// Some servers really like terminating connections by simply closing them (even TLS ones)
|
||||
// to signal end-of-data, if there's no:
|
||||
// - connection
|
||||
// - content-size
|
||||
// - transfer-encoding: chunked
|
||||
// header, simply treat EOF as a termination signal.
|
||||
if (m_headers.contains("connection"sv) || m_content_length.has_value() || m_current_chunk_total_size.has_value()) {
|
||||
dbgln_if(JOB_DEBUG, "Read failure: Actually EOF!");
|
||||
deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
||||
return;
|
||||
}
|
||||
|
||||
finish_up();
|
||||
return;
|
||||
}
|
||||
|
||||
while (m_state == State::InStatus) {
|
||||
|
|
|
@ -174,6 +174,16 @@ ErrorOr<void> TLSv12::read_from_socket()
|
|||
consume(read_bytes);
|
||||
} while (!read_bytes.is_empty() && !m_context.critical_error);
|
||||
|
||||
if (read_bytes.is_empty()) {
|
||||
// read_some() returned an empty span, this is either an EOF (from improper closure)
|
||||
// or some sort of weird even that is showing itself as an EOF.
|
||||
// To guard against servers closing the connection weirdly or just improperly, make sure
|
||||
// to check the connection state here and send the appropriate notifications.
|
||||
stream.close();
|
||||
|
||||
check_connection_state(true);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -204,6 +214,11 @@ bool TLSv12::check_connection_state(bool read)
|
|||
m_context.connection_finished = true;
|
||||
m_context.connection_status = ConnectionStatus::Disconnected;
|
||||
close();
|
||||
m_context.has_invoked_finish_or_error_callback = true;
|
||||
if (on_ready_to_read)
|
||||
on_ready_to_read(); // Notify the client about the weird event.
|
||||
if (on_tls_finished)
|
||||
on_tls_finished();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -291,7 +306,8 @@ ErrorOr<bool> TLSv12::flush()
|
|||
|
||||
void TLSv12::close()
|
||||
{
|
||||
alert(AlertLevel::FATAL, AlertDescription::CLOSE_NOTIFY);
|
||||
if (underlying_stream().is_open())
|
||||
alert(AlertLevel::FATAL, AlertDescription::CLOSE_NOTIFY);
|
||||
// bye bye.
|
||||
m_context.connection_status = ConnectionStatus::Disconnected;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue