From 3f3ddee0665176040b3eaf89a912a922726ecb18 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 5 Jan 2023 09:38:11 +0100 Subject: [PATCH] http_proxy: do not assign data->req.p.http use local copy Avoid the tricky reusing of the data->req.p.http pointer for http proxy tunneling. Fixes #10194 Closes #10234 --- lib/http.c | 32 ++++++++++++++++++-------------- lib/http.h | 3 +++ lib/http_proxy.c | 25 +++++++------------------ lib/rtsp.c | 2 +- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/lib/http.c b/lib/http.c index 10c62bf564..a33251e5d3 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1248,8 +1248,8 @@ static size_t readmoredata(char *buffer, size_t nitems, void *userp) { - struct Curl_easy *data = (struct Curl_easy *)userp; - struct HTTP *http = data->req.p.http; + struct HTTP *http = (struct HTTP *)userp; + struct Curl_easy *data = http->backup.data; size_t fullsize = size * nitems; if(!http->postsize) @@ -1301,6 +1301,7 @@ static size_t readmoredata(char *buffer, */ CURLcode Curl_buffer_send(struct dynbuf *in, struct Curl_easy *data, + struct HTTP *http, /* add the number of sent bytes to this counter */ curl_off_t *bytes_written, @@ -1313,7 +1314,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, char *ptr; size_t size; struct connectdata *conn = data->conn; - struct HTTP *http = data->req.p.http; size_t sendsize; curl_socket_t sockfd; size_t headersize; @@ -1448,10 +1448,11 @@ CURLcode Curl_buffer_send(struct dynbuf *in, http->backup.fread_in = data->state.in; http->backup.postdata = http->postdata; http->backup.postsize = http->postsize; + http->backup.data = data; /* set the new pointers for the request-sending */ data->state.fread_func = (curl_read_callback)readmoredata; - data->state.in = (void *)data; + data->state.in = (void *)http; http->postdata = ptr; http->postsize = (curl_off_t)size; @@ -1460,7 +1461,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, http->send_buffer = *in; /* copy the whole struct */ http->sending = HTTPSEND_REQUEST; - return CURLE_OK; } http->sending = HTTPSEND_BODY; @@ -2342,7 +2342,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, curl_off_t included_body = 0; #else /* from this point down, this function should not be used */ -#define Curl_buffer_send(a,b,c,d,e) CURLE_OK +#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK #endif CURLcode result = CURLE_OK; struct HTTP *http = data->req.p.http; @@ -2386,7 +2386,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, Curl_pgrsSetUploadSize(data, http->postsize); /* this sends the buffer and frees all the buffer resources */ - result = Curl_buffer_send(r, data, &data->info.request_size, 0, + result = Curl_buffer_send(r, data, data->req.p.http, + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending PUT request"); @@ -2407,7 +2408,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, if(result) return result; - result = Curl_buffer_send(r, data, &data->info.request_size, 0, + result = Curl_buffer_send(r, data, data->req.p.http, + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); @@ -2478,7 +2480,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, http->sending = HTTPSEND_BODY; /* this sends the buffer and frees all the buffer resources */ - result = Curl_buffer_send(r, data, &data->info.request_size, 0, + result = Curl_buffer_send(r, data, data->req.p.http, + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending POST request"); @@ -2595,11 +2598,10 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, else { /* A huge POST coming up, do data separate from the request */ http->postdata = data->set.postfields; - http->sending = HTTPSEND_BODY; - + http->backup.data = data; data->state.fread_func = (curl_read_callback)readmoredata; - data->state.in = (void *)data; + data->state.in = (void *)http; /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); @@ -2638,7 +2640,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, } } /* issue the request */ - result = Curl_buffer_send(r, data, &data->info.request_size, included_body, + result = Curl_buffer_send(r, data, data->req.p.http, + &data->info.request_size, included_body, FIRSTSOCKET); if(result) @@ -2654,7 +2657,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, return result; /* issue the request */ - result = Curl_buffer_send(r, data, &data->info.request_size, 0, + result = Curl_buffer_send(r, data, data->req.p.http, + &data->info.request_size, 0, FIRSTSOCKET); if(result) failf(data, "Failed sending HTTP request"); diff --git a/lib/http.h b/lib/http.h index 8739290d97..99ec7169e7 100644 --- a/lib/http.h +++ b/lib/http.h @@ -74,8 +74,10 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, const struct connectdata *conn, const char *thisheader, const size_t thislen); +struct HTTP; /* see below */ CURLcode Curl_buffer_send(struct dynbuf *in, struct Curl_easy *data, + struct HTTP *http, curl_off_t *bytes_written, curl_off_t included_body_bytes, int socketindex); @@ -198,6 +200,7 @@ struct HTTP { void *fread_in; /* backup storage for fread_in pointer */ const char *postdata; curl_off_t postsize; + struct Curl_easy *data; } backup; enum { diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 4c05c66c81..1afea5491b 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -74,8 +74,7 @@ struct tunnel_state { int sockindex; const char *hostname; int remote_port; - struct HTTP http_proxy; - struct HTTP *prot_save; + struct HTTP CONNECT; struct dynbuf rcvbuf; struct dynbuf req; size_t nsend; @@ -160,17 +159,6 @@ static CURLcode tunnel_init(struct tunnel_state **pts, Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS); Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST); - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want [protocol] through HTTP and we have - * to change the member temporarily for connecting to the HTTP - * proxy. After Curl_proxyCONNECT we have to set back the member to the - * original pointer - * - * This function might be called several times in the multi interface case - * if the proxy's CONNECT response is not instant. - */ - ts->prot_save = data->req.p.http; - data->req.p.http = &ts->http_proxy; *pts = ts; connkeep(conn, "HTTP proxy CONNECT"); return tunnel_reinit(ts, conn, data); @@ -227,7 +215,6 @@ static void tunnel_go_state(struct Curl_cfilter *cf, Curl_dyn_reset(&ts->rcvbuf); Curl_dyn_reset(&ts->req); /* restore the protocol pointer */ - data->req.p.http = ts->prot_save; data->info.httpcode = 0; /* clear it as it might've been used for the proxy */ /* If a proxy-authorization header was used for the proxy, then we should @@ -355,7 +342,8 @@ static CURLcode start_CONNECT(struct Curl_easy *data, goto out; /* Send the connect request to the proxy */ - result = Curl_buffer_send(&ts->req, data, &data->info.request_size, 0, + result = Curl_buffer_send(&ts->req, data, &ts->CONNECT, + &data->info.request_size, 0, ts->sockindex); ts->headerlines = 0; @@ -373,7 +361,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, bool *done) { struct SingleRequest *k = &data->req; - struct HTTP *http = data->req.p.http; + struct HTTP *http = &ts->CONNECT; CURLcode result = CURLE_OK; if(http->sending != HTTPSEND_REQUEST) @@ -394,7 +382,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, result = Curl_write(data, conn->writesockfd, /* socket to send to */ k->upload_fromhere, /* buffer pointer */ - ts->nsend, /* buffer size */ + ts->nsend, /* buffer size */ &bytes_written); /* actually sent */ if(result) goto out; @@ -1158,8 +1146,9 @@ static int http_proxy_cf_get_select_socks(struct Curl_cfilter *cf, wait for the socket to become readable to be able to get the response headers or if we're still sending the request, wait for write. */ - if(ts->http_proxy.sending == HTTPSEND_REQUEST) + if(ts->CONNECT.sending == HTTPSEND_REQUEST) { return GETSOCK_WRITESOCK(0); + } return GETSOCK_READSOCK(0); } return GETSOCK_WRITESOCK(0); diff --git a/lib/rtsp.c b/lib/rtsp.c index 3069f3f996..9d27929e84 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -563,7 +563,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) } /* issue the request */ - result = Curl_buffer_send(&req_buffer, data, + result = Curl_buffer_send(&req_buffer, data, data->req.p.http, &data->info.request_size, 0, FIRSTSOCKET); if(result) { failf(data, "Failed sending RTSP request");