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
This commit is contained in:
Daniel Stenberg 2023-01-05 09:38:11 +01:00
parent 446267c555
commit 3f3ddee066
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 29 additions and 33 deletions

View File

@ -1248,8 +1248,8 @@ static size_t readmoredata(char *buffer,
size_t nitems, size_t nitems,
void *userp) void *userp)
{ {
struct Curl_easy *data = (struct Curl_easy *)userp; struct HTTP *http = (struct HTTP *)userp;
struct HTTP *http = data->req.p.http; struct Curl_easy *data = http->backup.data;
size_t fullsize = size * nitems; size_t fullsize = size * nitems;
if(!http->postsize) if(!http->postsize)
@ -1301,6 +1301,7 @@ static size_t readmoredata(char *buffer,
*/ */
CURLcode Curl_buffer_send(struct dynbuf *in, CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data, struct Curl_easy *data,
struct HTTP *http,
/* add the number of sent bytes to this /* add the number of sent bytes to this
counter */ counter */
curl_off_t *bytes_written, curl_off_t *bytes_written,
@ -1313,7 +1314,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
char *ptr; char *ptr;
size_t size; size_t size;
struct connectdata *conn = data->conn; struct connectdata *conn = data->conn;
struct HTTP *http = data->req.p.http;
size_t sendsize; size_t sendsize;
curl_socket_t sockfd; curl_socket_t sockfd;
size_t headersize; size_t headersize;
@ -1448,10 +1448,11 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
http->backup.fread_in = data->state.in; http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata; http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize; http->backup.postsize = http->postsize;
http->backup.data = data;
/* set the new pointers for the request-sending */ /* set the new pointers for the request-sending */
data->state.fread_func = (curl_read_callback)readmoredata; data->state.fread_func = (curl_read_callback)readmoredata;
data->state.in = (void *)data; data->state.in = (void *)http;
http->postdata = ptr; http->postdata = ptr;
http->postsize = (curl_off_t)size; 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->send_buffer = *in; /* copy the whole struct */
http->sending = HTTPSEND_REQUEST; http->sending = HTTPSEND_REQUEST;
return CURLE_OK; return CURLE_OK;
} }
http->sending = HTTPSEND_BODY; 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; curl_off_t included_body = 0;
#else #else
/* from this point down, this function should not be used */ /* 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 #endif
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct HTTP *http = data->req.p.http; 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); Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */ /* 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); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending PUT request"); failf(data, "Failed sending PUT request");
@ -2407,7 +2408,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
if(result) if(result)
return 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); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); 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; http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */ /* 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); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending POST request"); failf(data, "Failed sending POST request");
@ -2595,11 +2598,10 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
else { else {
/* A huge POST coming up, do data separate from the request */ /* A huge POST coming up, do data separate from the request */
http->postdata = data->set.postfields; http->postdata = data->set.postfields;
http->sending = HTTPSEND_BODY; http->sending = HTTPSEND_BODY;
http->backup.data = data;
data->state.fread_func = (curl_read_callback)readmoredata; 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 */ /* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
@ -2638,7 +2640,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
} }
} }
/* issue the request */ /* 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); FIRSTSOCKET);
if(result) if(result)
@ -2654,7 +2657,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result; return result;
/* issue the request */ /* 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); FIRSTSOCKET);
if(result) if(result)
failf(data, "Failed sending HTTP request"); failf(data, "Failed sending HTTP request");

View File

@ -74,8 +74,10 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
const struct connectdata *conn, const struct connectdata *conn,
const char *thisheader, const char *thisheader,
const size_t thislen); const size_t thislen);
struct HTTP; /* see below */
CURLcode Curl_buffer_send(struct dynbuf *in, CURLcode Curl_buffer_send(struct dynbuf *in,
struct Curl_easy *data, struct Curl_easy *data,
struct HTTP *http,
curl_off_t *bytes_written, curl_off_t *bytes_written,
curl_off_t included_body_bytes, curl_off_t included_body_bytes,
int socketindex); int socketindex);
@ -198,6 +200,7 @@ struct HTTP {
void *fread_in; /* backup storage for fread_in pointer */ void *fread_in; /* backup storage for fread_in pointer */
const char *postdata; const char *postdata;
curl_off_t postsize; curl_off_t postsize;
struct Curl_easy *data;
} backup; } backup;
enum { enum {

View File

@ -74,8 +74,7 @@ struct tunnel_state {
int sockindex; int sockindex;
const char *hostname; const char *hostname;
int remote_port; int remote_port;
struct HTTP http_proxy; struct HTTP CONNECT;
struct HTTP *prot_save;
struct dynbuf rcvbuf; struct dynbuf rcvbuf;
struct dynbuf req; struct dynbuf req;
size_t nsend; 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->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST); 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; *pts = ts;
connkeep(conn, "HTTP proxy CONNECT"); connkeep(conn, "HTTP proxy CONNECT");
return tunnel_reinit(ts, conn, data); 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->rcvbuf);
Curl_dyn_reset(&ts->req); Curl_dyn_reset(&ts->req);
/* restore the protocol pointer */ /* 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 data->info.httpcode = 0; /* clear it as it might've been used for the
proxy */ proxy */
/* If a proxy-authorization header was used for the proxy, then we should /* 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; goto out;
/* Send the connect request to the proxy */ /* 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->sockindex);
ts->headerlines = 0; ts->headerlines = 0;
@ -373,7 +361,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data,
bool *done) bool *done)
{ {
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
struct HTTP *http = data->req.p.http; struct HTTP *http = &ts->CONNECT;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(http->sending != HTTPSEND_REQUEST) if(http->sending != HTTPSEND_REQUEST)
@ -394,7 +382,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data,
result = Curl_write(data, result = Curl_write(data,
conn->writesockfd, /* socket to send to */ conn->writesockfd, /* socket to send to */
k->upload_fromhere, /* buffer pointer */ k->upload_fromhere, /* buffer pointer */
ts->nsend, /* buffer size */ ts->nsend, /* buffer size */
&bytes_written); /* actually sent */ &bytes_written); /* actually sent */
if(result) if(result)
goto out; 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 wait for the socket to become readable to be able to get the
response headers or if we're still sending the request, wait response headers or if we're still sending the request, wait
for write. */ for write. */
if(ts->http_proxy.sending == HTTPSEND_REQUEST) if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
return GETSOCK_WRITESOCK(0); return GETSOCK_WRITESOCK(0);
}
return GETSOCK_READSOCK(0); return GETSOCK_READSOCK(0);
} }
return GETSOCK_WRITESOCK(0); return GETSOCK_WRITESOCK(0);

View File

@ -563,7 +563,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
} }
/* issue the request */ /* 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); &data->info.request_size, 0, FIRSTSOCKET);
if(result) { if(result) {
failf(data, "Failed sending RTSP request"); failf(data, "Failed sending RTSP request");