2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-29 12:49:49 +00:00

[http] Treat any unexpected connection close as an error

iPXE currently checks that the server has not closed the connection
mid-stream (i.e. in the middle of a chunked transfer, or before the
specified Content-Length has been received), but does not check that
the server got as far as starting to send data.  Consequently, if the
server closes the connection before any data is transferred (e.g. if
the server gives up waiting while iPXE performs the validation steps
for TLS), then iPXE will treat this as a successful transfer of a
zero-length file.

Fix by checking the RX connection state, and forcing an error if the
server has closed the connection at an unexpected point.

Originally-fixed-by: Marin Hannache <mareo@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2012-08-15 16:29:22 +01:00
parent c7eea31ed8
commit 501527daab

View File

@ -60,9 +60,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
#define EINFO_EIO_CONTENT_LENGTH \
__einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
#define EIO_CHUNK __einfo_error ( EINFO_EIO_CHUNK )
#define EINFO_EIO_CHUNK \
__einfo_uniqify ( EINFO_EIO, 0x03, "Terminated mid-chunk" )
#define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE )
#define EINFO_EINVAL_RESPONSE \
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" )
@ -111,7 +108,14 @@ enum http_rx_state {
HTTP_RX_RESPONSE = 0,
HTTP_RX_HEADER,
HTTP_RX_CHUNK_LEN,
/* In HTTP_RX_DATA, it is acceptable for the server to close
* the connection (unless we are in the middle of a chunked
* transfer).
*/
HTTP_RX_DATA,
/* In the following states, it is acceptable for the server to
* close the connection.
*/
HTTP_RX_TRAILER,
HTTP_RX_IDLE,
HTTP_RX_DEAD,
@ -251,10 +255,14 @@ static int http_socket_open ( struct http_request *http ) {
static void http_done ( struct http_request *http ) {
int rc;
/* If we are in the middle of a chunked transfer, force an error */
if ( http->chunked ) {
DBGC ( http, "HTTP %p terminated mid-chunk\n", http );
http_close ( http, -EIO_CHUNK );
/* If we are not at an appropriate stage of the protocol
* (including being in the middle of a chunked transfer),
* force an error.
*/
if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) {
DBGC ( http, "HTTP %p connection closed unexpectedly\n",
http );
http_close ( http, -ECONNRESET );
return;
}