From: Daniel Stenberg Date: Tue, 3 Dec 2024 12:24:38 +0000 (+0100) Subject: http_proxy: move dynhds_add_custom here from http.c X-Git-Tag: curl-8_11_1~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=381b275314a695cb1156f3c3a1523387438f2f76;p=thirdparty%2Fcurl.git http_proxy: move dynhds_add_custom here from http.c ... and make it static. As it is not used anywhere else. Closes #15672 --- diff --git a/lib/http.c b/lib/http.c index a94edd61c2..35e7085515 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1229,163 +1229,6 @@ static const char *get_http_string(const struct Curl_easy *data, } #endif -enum proxy_use { - HEADER_SERVER, /* direct to server */ - HEADER_PROXY, /* regular request to proxy */ - HEADER_CONNECT /* sending CONNECT to a proxy */ -}; - -static bool hd_name_eq(const char *n1, size_t n1len, - const char *n2, size_t n2len) -{ - if(n1len == n2len) { - return strncasecompare(n1, n2, n1len); - } - return FALSE; -} - -CURLcode Curl_dynhds_add_custom(struct Curl_easy *data, - bool is_connect, - struct dynhds *hds) -{ - struct connectdata *conn = data->conn; - char *ptr; - struct curl_slist *h[2]; - struct curl_slist *headers; - int numlists = 1; /* by default */ - int i; - -#ifndef CURL_DISABLE_PROXY - enum proxy_use proxy; - - if(is_connect) - proxy = HEADER_CONNECT; - else - proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ? - HEADER_PROXY : HEADER_SERVER; - - switch(proxy) { - case HEADER_SERVER: - h[0] = data->set.headers; - break; - case HEADER_PROXY: - h[0] = data->set.headers; - if(data->set.sep_headers) { - h[1] = data->set.proxyheaders; - numlists++; - } - break; - case HEADER_CONNECT: - if(data->set.sep_headers) - h[0] = data->set.proxyheaders; - else - h[0] = data->set.headers; - break; - } -#else - (void)is_connect; - h[0] = data->set.headers; -#endif - - /* loop through one or two lists */ - for(i = 0; i < numlists; i++) { - for(headers = h[i]; headers; headers = headers->next) { - const char *name, *value; - size_t namelen, valuelen; - - /* There are 2 quirks in place for custom headers: - * 1. setting only 'name:' to suppress a header from being sent - * 2. setting only 'name;' to send an empty (illegal) header - */ - ptr = strchr(headers->data, ':'); - if(ptr) { - name = headers->data; - namelen = ptr - headers->data; - ptr++; /* pass the colon */ - while(*ptr && ISSPACE(*ptr)) - ptr++; - if(*ptr) { - value = ptr; - valuelen = strlen(value); - } - else { - /* quirk #1, suppress this header */ - continue; - } - } - else { - ptr = strchr(headers->data, ';'); - - if(!ptr) { - /* neither : nor ; in provided header value. We seem - * to ignore this silently */ - continue; - } - - name = headers->data; - namelen = ptr - headers->data; - ptr++; /* pass the semicolon */ - while(*ptr && ISSPACE(*ptr)) - ptr++; - if(!*ptr) { - /* quirk #2, send an empty header */ - value = ""; - valuelen = 0; - } - else { - /* this may be used for something else in the future, - * ignore this for now */ - continue; - } - } - - DEBUGASSERT(name && value); - if(data->state.aptr.host && - /* a Host: header was sent already, do not pass on any custom Host: - header as that will produce *two* in the same request! */ - hd_name_eq(name, namelen, STRCONST("Host:"))) - ; - else if(data->state.httpreq == HTTPREQ_POST_FORM && - /* this header (extended by formdata.c) is sent later */ - hd_name_eq(name, namelen, STRCONST("Content-Type:"))) - ; - else if(data->state.httpreq == HTTPREQ_POST_MIME && - /* this header is sent later */ - hd_name_eq(name, namelen, STRCONST("Content-Type:"))) - ; - else if(data->req.authneg && - /* while doing auth neg, do not allow the custom length since - we will force length zero then */ - hd_name_eq(name, namelen, STRCONST("Content-Length:"))) - ; - else if(data->state.aptr.te && - /* when asking for Transfer-Encoding, do not pass on a custom - Connection: */ - hd_name_eq(name, namelen, STRCONST("Connection:"))) - ; - else if((conn->httpversion >= 20) && - hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:"))) - /* HTTP/2 does not support chunked requests */ - ; - else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) || - hd_name_eq(name, namelen, STRCONST("Cookie:"))) && - /* be careful of sending this potentially sensitive header to - other hosts */ - !Curl_auth_allowed_to_host(data)) - ; - else { - CURLcode result; - - result = Curl_dynhds_add(hds, name, namelen, value, valuelen); - if(result) - return result; - } - } - } - - return CURLE_OK; -} - CURLcode Curl_add_custom_headers(struct Curl_easy *data, bool is_connect, #ifndef USE_HYPER @@ -1403,7 +1246,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, int i; #ifndef CURL_DISABLE_PROXY - enum proxy_use proxy; + enum Curl_proxy_use proxy; if(is_connect) proxy = HEADER_CONNECT; diff --git a/lib/http.h b/lib/http.h index bb5974d94d..7056e8a8ed 100644 --- a/lib/http.h +++ b/lib/http.h @@ -89,9 +89,6 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, void *headers #endif ); -CURLcode Curl_dynhds_add_custom(struct Curl_easy *data, - bool is_connect, - struct dynhds *hds); void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, const char **method, Curl_HttpReq *); diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 1ec08d0d09..b1dbe98427 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -45,12 +45,155 @@ #include "vtls/vtls.h" #include "transfer.h" #include "multiif.h" +#include "vauth/vauth.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" +static bool hd_name_eq(const char *n1, size_t n1len, + const char *n2, size_t n2len) +{ + return (n1len == n2len) ? strncasecompare(n1, n2, n1len) : FALSE; +} + +static CURLcode dynhds_add_custom(struct Curl_easy *data, + bool is_connect, + struct dynhds *hds) +{ + struct connectdata *conn = data->conn; + char *ptr; + struct curl_slist *h[2]; + struct curl_slist *headers; + int numlists = 1; /* by default */ + int i; + + enum Curl_proxy_use proxy; + + if(is_connect) + proxy = HEADER_CONNECT; + else + proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ? + HEADER_PROXY : HEADER_SERVER; + + switch(proxy) { + case HEADER_SERVER: + h[0] = data->set.headers; + break; + case HEADER_PROXY: + h[0] = data->set.headers; + if(data->set.sep_headers) { + h[1] = data->set.proxyheaders; + numlists++; + } + break; + case HEADER_CONNECT: + if(data->set.sep_headers) + h[0] = data->set.proxyheaders; + else + h[0] = data->set.headers; + break; + } + + /* loop through one or two lists */ + for(i = 0; i < numlists; i++) { + for(headers = h[i]; headers; headers = headers->next) { + const char *name, *value; + size_t namelen, valuelen; + + /* There are 2 quirks in place for custom headers: + * 1. setting only 'name:' to suppress a header from being sent + * 2. setting only 'name;' to send an empty (illegal) header + */ + ptr = strchr(headers->data, ':'); + if(ptr) { + name = headers->data; + namelen = ptr - headers->data; + ptr++; /* pass the colon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + if(*ptr) { + value = ptr; + valuelen = strlen(value); + } + else { + /* quirk #1, suppress this header */ + continue; + } + } + else { + ptr = strchr(headers->data, ';'); + + if(!ptr) { + /* neither : nor ; in provided header value. We seem + * to ignore this silently */ + continue; + } + + name = headers->data; + namelen = ptr - headers->data; + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + if(!*ptr) { + /* quirk #2, send an empty header */ + value = ""; + valuelen = 0; + } + else { + /* this may be used for something else in the future, + * ignore this for now */ + continue; + } + } + + DEBUGASSERT(name && value); + if(data->state.aptr.host && + /* a Host: header was sent already, do not pass on any custom Host: + header as that will produce *two* in the same request! */ + hd_name_eq(name, namelen, STRCONST("Host:"))) + ; + else if(data->state.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + hd_name_eq(name, namelen, STRCONST("Content-Type:"))) + ; + else if(data->state.httpreq == HTTPREQ_POST_MIME && + /* this header is sent later */ + hd_name_eq(name, namelen, STRCONST("Content-Type:"))) + ; + else if(data->req.authneg && + /* while doing auth neg, do not allow the custom length since + we will force length zero then */ + hd_name_eq(name, namelen, STRCONST("Content-Length:"))) + ; + else if(data->state.aptr.te && + /* when asking for Transfer-Encoding, do not pass on a custom + Connection: */ + hd_name_eq(name, namelen, STRCONST("Connection:"))) + ; + else if((conn->httpversion >= 20) && + hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:"))) + /* HTTP/2 does not support chunked requests */ + ; + else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) || + hd_name_eq(name, namelen, STRCONST("Cookie:"))) && + /* be careful of sending this potentially sensitive header to + other hosts */ + !Curl_auth_allowed_to_host(data)) + ; + else { + CURLcode result; + + result = Curl_dynhds_add(hds, name, namelen, value, valuelen); + if(result) + return result; + } + } + } + + return CURLE_OK; +} CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, const char **phostname, @@ -146,7 +289,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, goto out; } - result = Curl_dynhds_add_custom(data, TRUE, &req->headers); + result = dynhds_add_custom(data, TRUE, &req->headers); out: if(result && req) { diff --git a/lib/http_proxy.h b/lib/http_proxy.h index 2b5f7ae706..2e91ff2037 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -30,6 +30,12 @@ #include "urldata.h" +enum Curl_proxy_use { + HEADER_SERVER, /* direct to server */ + HEADER_PROXY, /* regular request to proxy */ + HEADER_CONNECT /* sending CONNECT to a proxy */ +}; + CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, const char **phostname, int *pport, bool *pipv6_ip);