mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +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)));
|
auto tls = TRY_OR_FAIL(TLS::TLSv12::connect(DEFAULT_SERVER, port, move(options)));
|
||||||
ByteBuffer contents;
|
ByteBuffer contents;
|
||||||
tls->on_ready_to_read = [&] {
|
tls->on_ready_to_read = [&] {
|
||||||
auto read_bytes = TRY_OR_FAIL(tls->read_some(contents.must_get_bytes_for_writing(4 * KiB)));
|
(void)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);
|
|
||||||
}
|
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -223,8 +223,20 @@ void Job::on_socket_connected()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_socket->is_eof()) {
|
if (m_socket->is_eof()) {
|
||||||
dbgln_if(JOB_DEBUG, "Read failure: Actually EOF!");
|
// Some servers really like terminating connections by simply closing them (even TLS ones)
|
||||||
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
// 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) {
|
while (m_state == State::InStatus) {
|
||||||
|
|
|
@ -174,6 +174,16 @@ ErrorOr<void> TLSv12::read_from_socket()
|
||||||
consume(read_bytes);
|
consume(read_bytes);
|
||||||
} while (!read_bytes.is_empty() && !m_context.critical_error);
|
} 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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +214,11 @@ bool TLSv12::check_connection_state(bool read)
|
||||||
m_context.connection_finished = true;
|
m_context.connection_finished = true;
|
||||||
m_context.connection_status = ConnectionStatus::Disconnected;
|
m_context.connection_status = ConnectionStatus::Disconnected;
|
||||||
close();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +306,8 @@ ErrorOr<bool> TLSv12::flush()
|
||||||
|
|
||||||
void TLSv12::close()
|
void TLSv12::close()
|
||||||
{
|
{
|
||||||
alert(AlertLevel::FATAL, AlertDescription::CLOSE_NOTIFY);
|
if (underlying_stream().is_open())
|
||||||
|
alert(AlertLevel::FATAL, AlertDescription::CLOSE_NOTIFY);
|
||||||
// bye bye.
|
// bye bye.
|
||||||
m_context.connection_status = ConnectionStatus::Disconnected;
|
m_context.connection_status = ConnectionStatus::Disconnected;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue