forked from puppetlabs/puppet-runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request puppetlabs#810 from span786/PUP-12030-puppet-agent…
…s-packaged-curl-is-vulnerable-to-cve-2024-2004-and-cve-2024-2398 (PA-6291): Applied curl patches to curl 7.88.1
- Loading branch information
Showing
3 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
setopt: Fix disabling all protocols | ||
|
||
When disabling all protocols without enabling any, the resulting | ||
set of allowed protocols remained the default set. Clearing the | ||
allowed set before inspecting the passed value from --proto make | ||
the set empty even in the errorpath of no protocols enabled. | ||
|
||
Co-authored-by: Dan Fandrich <[email protected]> | ||
Reported-by: Dan Fandrich <[email protected]> | ||
Reviewed-by: Daniel Stenberg <[email protected]> | ||
Closes: #13004 | ||
--- | ||
diff --git a/lib/setopt.c b/lib/setopt.c | ||
index 604693ad9..d6b62c5c9 100644 | ||
--- a/lib/setopt.c | ||
+++ b/lib/setopt.c | ||
@@ -150,6 +150,12 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) | ||
|
||
static CURLcode protocol2num(const char *str, curl_prot_t *val) | ||
{ | ||
+ /* | ||
+ * We are asked to cherry-pick protocols, so play it safe and disallow all | ||
+ * protocols to start with, and re-add the wanted ones back in. | ||
+ */ | ||
+ *val = 0; | ||
+ | ||
if(!str) | ||
return CURLE_BAD_FUNCTION_ARGUMENT; | ||
|
||
@@ -158,8 +164,6 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) | ||
return CURLE_OK; | ||
} | ||
|
||
- *val = 0; | ||
- | ||
do { | ||
const char *token = str; | ||
size_t tlen; | ||
@@ -2668,22 +2672,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) | ||
break; | ||
|
||
case CURLOPT_PROTOCOLS_STR: { | ||
- curl_prot_t prot; | ||
argptr = va_arg(param, char *); | ||
- result = protocol2num(argptr, &prot); | ||
+ result = protocol2num(argptr, &data->set.allowed_protocols); | ||
if(result) | ||
return result; | ||
- data->set.allowed_protocols = prot; | ||
break; | ||
} | ||
|
||
case CURLOPT_REDIR_PROTOCOLS_STR: { | ||
- curl_prot_t prot; | ||
argptr = va_arg(param, char *); | ||
- result = protocol2num(argptr, &prot); | ||
+ result = protocol2num(argptr, &data->set.redir_protocols); | ||
if(result) | ||
return result; | ||
- data->set.redir_protocols = prot; | ||
break; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
http2: push headers better cleanup | ||
|
||
provide common cleanup method for push headers | ||
|
||
Co-authored-by: Stefan Eissing <@[email protected]> | ||
Reviewed-by: Daniel Stenberg <[email protected]> | ||
|
||
Closes #13054 | ||
--- | ||
diff --git a/lib/http2.c b/lib/http2.c | ||
index bdb5e7378..f2c02da7c 100644 | ||
--- a/lib/http2.c | ||
+++ b/lib/http2.c | ||
@@ -144,6 +144,161 @@ static void cf_h2_ctx_free(struct cf_h2_ctx *ctx) | ||
} | ||
} | ||
|
||
+static CURLcode h2_progress_egress(struct Curl_cfilter *cf, | ||
+ struct Curl_easy *data); | ||
+ | ||
+/** | ||
+ * All about the H2 internals of a stream | ||
+ */ | ||
+struct h2_stream_ctx { | ||
+ int32_t id; /* HTTP/2 protocol identifier for stream */ | ||
+ struct bufq recvbuf; /* response buffer */ | ||
+ struct bufq sendbuf; /* request buffer */ | ||
+ struct h1_req_parser h1; /* parsing the request */ | ||
+ struct dynhds resp_trailers; /* response trailer fields */ | ||
+ size_t resp_hds_len; /* amount of response header bytes in recvbuf */ | ||
+ size_t upload_blocked_len; | ||
+ curl_off_t upload_left; /* number of request bytes left to upload */ | ||
+ curl_off_t nrcvd_data; /* number of DATA bytes received */ | ||
+ | ||
+ char **push_headers; /* allocated array */ | ||
+ size_t push_headers_used; /* number of entries filled in */ | ||
+ size_t push_headers_alloc; /* number of entries allocated */ | ||
+ | ||
+ int status_code; /* HTTP response status code */ | ||
+ uint32_t error; /* stream error code */ | ||
+ uint32_t local_window_size; /* the local recv window size */ | ||
+ bool resp_hds_complete; /* we have a complete, final response */ | ||
+ bool closed; /* TRUE on stream close */ | ||
+ bool reset; /* TRUE on stream reset */ | ||
+ bool close_handled; /* TRUE if stream closure is handled by libcurl */ | ||
+ bool bodystarted; | ||
+ bool send_closed; /* transfer is done sending, we might have still | ||
+ buffered data in stream->sendbuf to upload. */ | ||
+}; | ||
+ | ||
+#define H2_STREAM_CTX(d) ((struct h2_stream_ctx *)(((d) && \ | ||
+ (d)->req.p.http)? \ | ||
+ ((struct HTTP *)(d)->req.p.http)->h2_ctx \ | ||
+ : NULL)) | ||
+#define H2_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h2_ctx | ||
+#define H2_STREAM_ID(d) (H2_STREAM_CTX(d)? \ | ||
+ H2_STREAM_CTX(d)->id : -2) | ||
+ | ||
+/* | ||
+ * Mark this transfer to get "drained". | ||
+ */ | ||
+static void drain_stream(struct Curl_cfilter *cf, | ||
+ struct Curl_easy *data, | ||
+ struct h2_stream_ctx *stream) | ||
+{ | ||
+ unsigned char bits; | ||
+ | ||
+ (void)cf; | ||
+ bits = CURL_CSELECT_IN; | ||
+ if(!stream->send_closed && | ||
+ (stream->upload_left || stream->upload_blocked_len)) | ||
+ bits |= CURL_CSELECT_OUT; | ||
+ if(data->state.select_bits != bits) { | ||
+ CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x", | ||
+ stream->id, bits); | ||
+ data->state.select_bits = bits; | ||
+ Curl_expire(data, 0, EXPIRE_RUN_NOW); | ||
+ } | ||
+} | ||
+ | ||
+static CURLcode http2_data_setup(struct Curl_cfilter *cf, | ||
+ struct Curl_easy *data, | ||
+ struct h2_stream_ctx **pstream) | ||
+{ | ||
+ struct cf_h2_ctx *ctx = cf->ctx; | ||
+ struct h2_stream_ctx *stream; | ||
+ | ||
+ (void)cf; | ||
+ DEBUGASSERT(data); | ||
+ if(!data->req.p.http) { | ||
+ failf(data, "initialization failure, transfer not http initialized"); | ||
+ return CURLE_FAILED_INIT; | ||
+ } | ||
+ stream = H2_STREAM_CTX(data); | ||
+ if(stream) { | ||
+ *pstream = stream; | ||
+ return CURLE_OK; | ||
+ } | ||
+ | ||
+ stream = calloc(1, sizeof(*stream)); | ||
+ if(!stream) | ||
+ return CURLE_OUT_OF_MEMORY; | ||
+ | ||
+ stream->id = -1; | ||
+ Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp, | ||
+ H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE); | ||
+ Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); | ||
+ Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST); | ||
+ stream->resp_hds_len = 0; | ||
+ stream->bodystarted = FALSE; | ||
+ stream->status_code = -1; | ||
+ stream->closed = FALSE; | ||
+ stream->close_handled = FALSE; | ||
+ stream->error = NGHTTP2_NO_ERROR; | ||
+ stream->local_window_size = H2_STREAM_WINDOW_SIZE; | ||
+ stream->upload_left = 0; | ||
+ stream->nrcvd_data = 0; | ||
+ | ||
+ H2_STREAM_LCTX(data) = stream; | ||
+ *pstream = stream; | ||
+ return CURLE_OK; | ||
+} | ||
+ | ||
+static void free_push_headers(struct h2_stream_ctx *stream) | ||
+{ | ||
+ size_t i; | ||
+ for(i = 0; i<stream->push_headers_used; i++) | ||
+ free(stream->push_headers[i]); | ||
+ Curl_safefree(stream->push_headers); | ||
+ stream->push_headers_used = 0; | ||
+} | ||
+ | ||
+static void http2_data_done(struct Curl_cfilter *cf, | ||
+ struct Curl_easy *data, bool premature) | ||
+{ | ||
+ struct cf_h2_ctx *ctx = cf->ctx; | ||
+ struct h2_stream_ctx *stream = H2_STREAM_CTX(data); | ||
+ | ||
+ DEBUGASSERT(ctx); | ||
+ (void)premature; | ||
+ if(!stream) | ||
+ return; | ||
+ | ||
+ if(ctx->h2) { | ||
+ bool flush_egress = FALSE; | ||
+ /* returns error if stream not known, which is fine here */ | ||
+ (void)nghttp2_session_set_stream_user_data(ctx->h2, stream->id, NULL); | ||
+ | ||
+ if(!stream->closed && stream->id > 0) { | ||
+ /* RST_STREAM */ | ||
+ CURL_TRC_CF(data, cf, "[%d] premature DATA_DONE, RST stream", | ||
+ stream->id); | ||
+ stream->closed = TRUE; | ||
+ stream->reset = TRUE; | ||
+ stream->send_closed = TRUE; | ||
+ nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE, | ||
+ stream->id, NGHTTP2_STREAM_CLOSED); | ||
+ flush_egress = TRUE; | ||
+ } | ||
+ | ||
+ if(flush_egress) | ||
+ nghttp2_session_send(ctx->h2); | ||
+ } | ||
+ | ||
+ Curl_bufq_free(&stream->sendbuf); | ||
+ Curl_h1_req_parse_free(&stream->h1); | ||
+ Curl_dynhds_free(&stream->resp_trailers); | ||
+ free_push_headers(stream); | ||
+ free(stream); | ||
+ H2_STREAM_LCTX(data) = NULL; | ||
+} | ||
+ | ||
static int h2_client_new(struct Curl_cfilter *cf, | ||
nghttp2_session_callbacks *cbs) | ||
{ | ||
@@ -702,6 +857,7 @@ static int push_promise(struct Curl_cfilter *cf, | ||
struct HTTP *newstream; | ||
struct curl_pushheaders heads; | ||
CURLMcode rc; | ||
+ CURLcode result; | ||
size_t i; | ||
/* clone the parent */ | ||
struct Curl_easy *newhandle = h2_duphandle(cf, data); | ||
@@ -738,11 +894,7 @@ static int push_promise(struct Curl_cfilter *cf, | ||
Curl_set_in_callback(data, false); | ||
|
||
/* free the headers again */ | ||
- for(i = 0; i<stream->push_headers_used; i++) | ||
- free(stream->push_headers[i]); | ||
- free(stream->push_headers); | ||
- stream->push_headers = NULL; | ||
- stream->push_headers_used = 0; | ||
+ free_push_headers(stream); | ||
|
||
if(rv) { | ||
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT)); | ||
@@ -1198,14 +1350,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, | ||
if(stream->push_headers_alloc > 1000) { | ||
/* this is beyond crazy many headers, bail out */ | ||
failf(data_s, "Too many PUSH_PROMISE headers"); | ||
- Curl_safefree(stream->push_headers); | ||
+ free_push_headers(stream); | ||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; | ||
} | ||
stream->push_headers_alloc *= 2; | ||
- headp = Curl_saferealloc(stream->push_headers, | ||
- stream->push_headers_alloc * sizeof(char *)); | ||
+ headp = realloc(stream->push_headers, | ||
+ stream->push_headers_alloc * sizeof(char *)); | ||
if(!headp) { | ||
- stream->push_headers = NULL; | ||
+ free_push_headers(stream); | ||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; | ||
} | ||
stream->push_headers = headp; |