Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
curl.36283
curl-CVE-2023-38039.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File curl-CVE-2023-38039.patch of Package curl.36283
From 3ee79c1674fd6f99e8efca52cd7510e08b766770 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg <daniel@haxx.se> Date: Wed, 2 Aug 2023 23:34:48 +0200 Subject: [PATCH] http: return error when receiving too large header set To avoid abuse. The limit is set to 300 KB for the accumulated size of all received HTTP headers for a single response. Incomplete research suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to 1MB. Closes #11582 --- lib/c-hyper.c | 12 +++++++----- lib/cf-h1-proxy.c | 4 +++- lib/http.c | 34 ++++++++++++++++++++++++++++++---- lib/http.h | 9 +++++++++ lib/pingpong.c | 4 +++- lib/urldata.h | 17 ++++++++--------- 6 files changed, 60 insertions(+), 20 deletions(-) Index: curl-8.0.1/lib/c-hyper.c =================================================================== --- curl-8.0.1.orig/lib/c-hyper.c +++ curl-8.0.1/lib/c-hyper.c @@ -174,8 +174,11 @@ static int hyper_each_header(void *userd } } - data->info.header_size += (curl_off_t)len; - data->req.headerbytecount += (curl_off_t)len; + result = Curl_bump_headersize(data, len, FALSE); + if(result) { + data->state.hresult = result; + return HYPER_ITER_BREAK; + } return HYPER_ITER_CONTINUE; } @@ -305,9 +308,8 @@ static CURLcode status_line(struct Curl_ if(result) return result; } - data->info.header_size += (curl_off_t)len; - data->req.headerbytecount += (curl_off_t)len; - return CURLE_OK; + result = Curl_bump_headersize(data, len, FALSE); + return result; } /* Index: curl-8.0.1/lib/http.c =================================================================== --- curl-8.0.1.orig/lib/http.c +++ curl-8.0.1/lib/http.c @@ -3760,6 +3760,29 @@ static CURLcode verify_header(struct Cur return CURLE_OK; } +CURLcode Curl_bump_headersize(struct Curl_easy *data, + size_t delta, + bool connect_only) +{ + size_t bad = 0; + if(delta < MAX_HTTP_RESP_HEADER_SIZE) { + if(!connect_only) + data->req.headerbytecount += (unsigned int)delta; + data->info.header_size += (unsigned int)delta; + if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE) + bad = data->info.header_size; + } + else + bad = data->info.header_size + delta; + if(bad) { + failf(data, "Too large response headers: %zu > %zu", + bad, MAX_HTTP_RESP_HEADER_SIZE); + return CURLE_RECV_ERROR; + } + return CURLE_OK; +} + + /* * Read any HTTP header lines from the server and pass them to the client app. */ @@ -4007,8 +4030,9 @@ CURLcode Curl_http_readwrite_headers(str if(result) return result; - data->info.header_size += (long)headerlen; - data->req.headerbytecount += (long)headerlen; + result = Curl_bump_headersize(data, headerlen, FALSE); + if(result) + return result; /* * When all the headers have been parsed, see if we should give @@ -4330,8 +4354,10 @@ CURLcode Curl_http_readwrite_headers(str if(result) return result; - data->info.header_size += Curl_dyn_len(&data->state.headerb); - data->req.headerbytecount += Curl_dyn_len(&data->state.headerb); + result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb), + FALSE); + if(result) + return result; Curl_dyn_reset(&data->state.headerb); } Index: curl-8.0.1/lib/http.h =================================================================== --- curl-8.0.1.orig/lib/http.h +++ curl-8.0.1/lib/http.h @@ -61,6 +61,10 @@ extern const struct Curl_handler Curl_ha #endif /* websockets */ +CURLcode Curl_bump_headersize(struct Curl_easy *data, + size_t delta, + bool connect_only); + /* Header specific functions */ bool Curl_compareheader(const char *headerline, /* line to check */ const char *header, /* header keyword _with_ colon */ @@ -176,6 +180,11 @@ CURLcode Curl_http_auth_act(struct Curl_ #define EXPECT_100_THRESHOLD (1024*1024) #endif +/* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers + combined that libcurl allows for a single HTTP response, any HTTP + version. This count includes CONNECT response headers. */ +#define MAX_HTTP_RESP_HEADER_SIZE (300*1024) + #endif /* CURL_DISABLE_HTTP */ #ifdef USE_NGHTTP3 Index: curl-8.0.1/lib/pingpong.c =================================================================== --- curl-8.0.1.orig/lib/pingpong.c +++ curl-8.0.1/lib/pingpong.c @@ -341,7 +341,9 @@ CURLcode Curl_pp_readresp(struct Curl_ea ssize_t clipamount = 0; bool restart = FALSE; - data->req.headerbytecount += (long)gotbytes; + result = Curl_bump_headersize(data, gotbytes, FALSE); + if(result) + return result; pp->nread_resp += gotbytes; for(i = 0; i < gotbytes; ptr++, i++) { Index: curl-8.0.1/lib/urldata.h =================================================================== --- curl-8.0.1.orig/lib/urldata.h +++ curl-8.0.1/lib/urldata.h @@ -619,17 +619,16 @@ struct SingleRequest { curl_off_t bytecount; /* total number of bytes read */ curl_off_t writebytecount; /* number of bytes written */ - curl_off_t headerbytecount; /* only count received headers */ - curl_off_t deductheadercount; /* this amount of bytes doesn't count when we - check if anything has been transferred at - the end of a connection. We use this - counter to make only a 100 reply (without a - following second response code) result in a - CURLE_GOT_NOTHING error code */ - curl_off_t pendingheader; /* this many bytes left to send is actually header and not body */ struct curltime start; /* transfer started at this time */ + unsigned int headerbytecount; /* only count received headers */ + unsigned int deductheadercount; /* this amount of bytes doesn't count when + we check if anything has been transferred + at the end of a connection. We use this + counter to make only a 100 reply (without + a following second response code) result + in a CURLE_GOT_NOTHING error code */ enum { HEADER_NORMAL, /* no bad header at all */ HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest @@ -1076,7 +1075,6 @@ struct PureInfo { int httpversion; /* the http version number X.Y = X*10+Y */ time_t filetime; /* If requested, this is might get set. Set to -1 if the time was unretrievable. */ - curl_off_t header_size; /* size of read header(s) in bytes */ curl_off_t request_size; /* the amount of bytes sent in the request(s) */ unsigned long proxyauthavail; /* what proxy auth types were announced */ unsigned long httpauthavail; /* what host auth types were announced */ @@ -1084,6 +1082,7 @@ struct PureInfo { char *contenttype; /* the content type of the object */ char *wouldredirect; /* URL this would've been redirected to if asked to */ curl_off_t retry_after; /* info from Retry-After: header */ + unsigned int header_size; /* size of read header(s) in bytes */ /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' and, 'conn_local_port' are copied over from the connectdata struct in Index: curl-8.0.1/lib/http_proxy.c =================================================================== --- curl-8.0.1.orig/lib/http_proxy.c +++ curl-8.0.1/lib/http_proxy.c @@ -586,7 +586,9 @@ static CURLcode recv_CONNECT_resp(struct return result; } - data->info.header_size += (long)perline; + result = Curl_bump_headersize(data, perline, TRUE); + if(result) + return result; /* Newlines are CRLF, so the CR is ignored as the line isn't really terminated until the LF comes. Treat a following CR
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor