Fix error handling in SSL shutdown operations in examples

This commit is contained in:
Mohammad Nejati
2024-05-28 09:31:17 +00:00
committed by Mohammad Nejati
parent 0afa15e8cb
commit 9bf2184b33
5 changed files with 93 additions and 45 deletions

View File

@@ -192,16 +192,25 @@ public:
void void
on_shutdown(beast::error_code ec) on_shutdown(beast::error_code ec)
{ {
if(ec == net::error::eof) // ssl::error::stream_truncated, also known as an SSL "short read",
{ // indicates the peer closed the connection without performing the
// Rationale: // required closing handshake (for example, Google does this to
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error // improve performance). Generally this can be a security issue,
ec = {}; // but if your communication protocol is self-terminated (as
} // it is with both HTTP and WebSocket) then you may simply
if(ec) // ignore the lack of close_notify.
return fail(ec, "shutdown"); //
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
// If we get here then the connection is closed gracefully if(ec != net::ssl::error::stream_truncated)
return fail(ec, "shutdown");
} }
}; };

View File

@@ -184,16 +184,25 @@ public:
void void
on_shutdown(beast::error_code ec) on_shutdown(beast::error_code ec)
{ {
if(ec == net::error::eof) // ssl::error::stream_truncated, also known as an SSL "short read",
{ // indicates the peer closed the connection without performing the
// Rationale: // required closing handshake (for example, Google does this to
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error // improve performance). Generally this can be a security issue,
ec = {}; // but if your communication protocol is self-terminated (as
} // it is with both HTTP and WebSocket) then you may simply
if(ec) // ignore the lack of close_notify.
return fail(ec, "shutdown"); //
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
// If we get here then the connection is closed gracefully if(ec != net::ssl::error::stream_truncated)
return fail(ec, "shutdown");
} }
}; };

View File

@@ -109,16 +109,26 @@ do_session(
// Gracefully close the stream - do not threat every error as an exception! // Gracefully close the stream - do not threat every error as an exception!
auto [ec] = co_await stream.async_shutdown(net::as_tuple(net::use_awaitable)); auto [ec] = co_await stream.async_shutdown(net::as_tuple(net::use_awaitable));
if (ec == net::error::eof)
{
// Rationale:
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
ec = {};
}
if (ec)
throw boost::system::system_error(ec, "shutdown");
// If we get here then the connection is closed gracefully // ssl::error::stream_truncated, also known as an SSL "short read",
// indicates the peer closed the connection without performing the
// required closing handshake (for example, Google does this to
// improve performance). Generally this can be a security issue,
// but if your communication protocol is self-terminated (as
// it is with both HTTP and WebSocket) then you may simply
// ignore the lack of close_notify.
//
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
if(ec != net::ssl::error::stream_truncated)
throw boost::system::system_error(ec, "shutdown");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -118,16 +118,26 @@ do_session(
// Gracefully close the stream // Gracefully close the stream
stream.async_shutdown(yield[ec]); stream.async_shutdown(yield[ec]);
if(ec == net::error::eof)
{
// Rationale:
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
ec = {};
}
if(ec)
return fail(ec, "shutdown");
// If we get here then the connection is closed gracefully // ssl::error::stream_truncated, also known as an SSL "short read",
// indicates the peer closed the connection without performing the
// required closing handshake (for example, Google does this to
// improve performance). Generally this can be a security issue,
// but if your communication protocol is self-terminated (as
// it is with both HTTP and WebSocket) then you may simply
// ignore the lack of close_notify.
//
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
if(ec != net::ssl::error::stream_truncated)
return fail(ec, "shutdown");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -108,16 +108,26 @@ int main(int argc, char** argv)
// Gracefully close the stream // Gracefully close the stream
beast::error_code ec; beast::error_code ec;
stream.shutdown(ec); stream.shutdown(ec);
if(ec == net::error::eof)
{
// Rationale:
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
ec = {};
}
if(ec)
throw beast::system_error{ec};
// If we get here then the connection is closed gracefully // ssl::error::stream_truncated, also known as an SSL "short read",
// indicates the peer closed the connection without performing the
// required closing handshake (for example, Google does this to
// improve performance). Generally this can be a security issue,
// but if your communication protocol is self-terminated (as
// it is with both HTTP and WebSocket) then you may simply
// ignore the lack of close_notify.
//
// https://github.com/boostorg/beast/issues/38
//
// https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
//
// When a short read would cut off the end of an HTTP message,
// Beast returns the error beast::http::error::partial_message.
// Therefore, if we see a short read here, it has occurred
// after the message has been completed, so it is safe to ignore it.
if(ec != net::ssl::error::stream_truncated)
throw beast::system_error{ec};
} }
catch(std::exception const& e) catch(std::exception const& e)
{ {