quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

http.c (152451B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "curl_setup.h"
     26 
     27 #ifndef CURL_DISABLE_HTTP
     28 
     29 #ifdef HAVE_NETINET_IN_H
     30 #include <netinet/in.h>
     31 #endif
     32 
     33 #ifdef HAVE_NETDB_H
     34 #include <netdb.h>
     35 #endif
     36 #ifdef HAVE_ARPA_INET_H
     37 #include <arpa/inet.h>
     38 #endif
     39 #ifdef HAVE_NET_IF_H
     40 #include <net/if.h>
     41 #endif
     42 #ifdef HAVE_SYS_IOCTL_H
     43 #include <sys/ioctl.h>
     44 #endif
     45 
     46 #ifdef HAVE_SYS_PARAM_H
     47 #include <sys/param.h>
     48 #endif
     49 
     50 #include "urldata.h"
     51 #include <curl/curl.h>
     52 #include "transfer.h"
     53 #include "sendf.h"
     54 #include "formdata.h"
     55 #include "mime.h"
     56 #include "progress.h"
     57 #include "curlx/base64.h"
     58 #include "cookie.h"
     59 #include "vauth/vauth.h"
     60 #include "vtls/vtls.h"
     61 #include "vquic/vquic.h"
     62 #include "http_digest.h"
     63 #include "http_ntlm.h"
     64 #include "http_negotiate.h"
     65 #include "http_aws_sigv4.h"
     66 #include "url.h"
     67 #include "urlapi-int.h"
     68 #include "share.h"
     69 #include "hostip.h"
     70 #include "dynhds.h"
     71 #include "http.h"
     72 #include "headers.h"
     73 #include "select.h"
     74 #include "parsedate.h" /* for the week day and month names */
     75 #include "multiif.h"
     76 #include "strcase.h"
     77 #include "content_encoding.h"
     78 #include "http_proxy.h"
     79 #include "curlx/warnless.h"
     80 #include "http2.h"
     81 #include "cfilters.h"
     82 #include "connect.h"
     83 #include "strdup.h"
     84 #include "altsvc.h"
     85 #include "hsts.h"
     86 #include "ws.h"
     87 #include "curl_ctype.h"
     88 #include "curlx/strparse.h"
     89 
     90 /* The last 3 #include files should be in this order */
     91 #include "curl_printf.h"
     92 #include "curl_memory.h"
     93 #include "memdebug.h"
     94 
     95 /*
     96  * Forward declarations.
     97  */
     98 
     99 static bool http_should_fail(struct Curl_easy *data, int httpcode);
    100 static bool http_exp100_is_waiting(struct Curl_easy *data);
    101 static CURLcode http_exp100_add_reader(struct Curl_easy *data);
    102 static void http_exp100_send_anyway(struct Curl_easy *data);
    103 static bool http_exp100_is_selected(struct Curl_easy *data);
    104 static void http_exp100_got100(struct Curl_easy *data);
    105 static CURLcode http_firstwrite(struct Curl_easy *data);
    106 static CURLcode http_header(struct Curl_easy *data,
    107                             const char *hd, size_t hdlen);
    108 static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn);
    109 static CURLcode http_range(struct Curl_easy *data,
    110                            Curl_HttpReq httpreq);
    111 static CURLcode http_req_complete(struct Curl_easy *data,
    112                                   struct dynbuf *r, int httpversion,
    113                                   Curl_HttpReq httpreq);
    114 static CURLcode http_req_set_reader(struct Curl_easy *data,
    115                                     Curl_HttpReq httpreq, int httpversion,
    116                                     const char **tep);
    117 static CURLcode http_size(struct Curl_easy *data);
    118 static CURLcode http_statusline(struct Curl_easy *data,
    119                                 struct connectdata *conn);
    120 static CURLcode http_target(struct Curl_easy *data, struct connectdata *conn,
    121                             struct dynbuf *req);
    122 static CURLcode http_useragent(struct Curl_easy *data);
    123 #ifdef HAVE_LIBZ
    124 static CURLcode http_transferencode(struct Curl_easy *data);
    125 #endif
    126 
    127 
    128 /*
    129  * HTTP handler interface.
    130  */
    131 const struct Curl_handler Curl_handler_http = {
    132   "http",                               /* scheme */
    133   Curl_http_setup_conn,                 /* setup_connection */
    134   Curl_http,                            /* do_it */
    135   Curl_http_done,                       /* done */
    136   ZERO_NULL,                            /* do_more */
    137   Curl_http_connect,                    /* connect_it */
    138   ZERO_NULL,                            /* connecting */
    139   ZERO_NULL,                            /* doing */
    140   ZERO_NULL,                            /* proto_getsock */
    141   Curl_http_getsock_do,                 /* doing_getsock */
    142   ZERO_NULL,                            /* domore_getsock */
    143   ZERO_NULL,                            /* perform_getsock */
    144   ZERO_NULL,                            /* disconnect */
    145   Curl_http_write_resp,                 /* write_resp */
    146   Curl_http_write_resp_hd,              /* write_resp_hd */
    147   ZERO_NULL,                            /* connection_check */
    148   ZERO_NULL,                            /* attach connection */
    149   Curl_http_follow,                     /* follow */
    150   PORT_HTTP,                            /* defport */
    151   CURLPROTO_HTTP,                       /* protocol */
    152   CURLPROTO_HTTP,                       /* family */
    153   PROTOPT_CREDSPERREQUEST |             /* flags */
    154   PROTOPT_USERPWDCTRL
    155 };
    156 
    157 #ifdef USE_SSL
    158 /*
    159  * HTTPS handler interface.
    160  */
    161 const struct Curl_handler Curl_handler_https = {
    162   "https",                              /* scheme */
    163   Curl_http_setup_conn,                 /* setup_connection */
    164   Curl_http,                            /* do_it */
    165   Curl_http_done,                       /* done */
    166   ZERO_NULL,                            /* do_more */
    167   Curl_http_connect,                    /* connect_it */
    168   NULL,                                 /* connecting */
    169   ZERO_NULL,                            /* doing */
    170   NULL,                                 /* proto_getsock */
    171   Curl_http_getsock_do,                 /* doing_getsock */
    172   ZERO_NULL,                            /* domore_getsock */
    173   ZERO_NULL,                            /* perform_getsock */
    174   ZERO_NULL,                            /* disconnect */
    175   Curl_http_write_resp,                 /* write_resp */
    176   Curl_http_write_resp_hd,              /* write_resp_hd */
    177   ZERO_NULL,                            /* connection_check */
    178   ZERO_NULL,                            /* attach connection */
    179   Curl_http_follow,                     /* follow */
    180   PORT_HTTPS,                           /* defport */
    181   CURLPROTO_HTTPS,                      /* protocol */
    182   CURLPROTO_HTTP,                       /* family */
    183   PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
    184   PROTOPT_USERPWDCTRL
    185 };
    186 
    187 #endif
    188 
    189 void Curl_http_neg_init(struct Curl_easy *data, struct http_negotiation *neg)
    190 {
    191   memset(neg, 0, sizeof(*neg));
    192   neg->accept_09 = data->set.http09_allowed;
    193   switch(data->set.httpwant) {
    194   case CURL_HTTP_VERSION_1_0:
    195     neg->wanted = neg->allowed = (CURL_HTTP_V1x);
    196     neg->only_10 = TRUE;
    197     break;
    198   case CURL_HTTP_VERSION_1_1:
    199     neg->wanted = neg->allowed = (CURL_HTTP_V1x);
    200     break;
    201   case CURL_HTTP_VERSION_2_0:
    202     neg->wanted = neg->allowed = (CURL_HTTP_V1x | CURL_HTTP_V2x);
    203     neg->h2_upgrade = TRUE;
    204     break;
    205   case CURL_HTTP_VERSION_2TLS:
    206     neg->wanted = neg->allowed = (CURL_HTTP_V1x | CURL_HTTP_V2x);
    207     break;
    208   case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
    209     neg->wanted = neg->allowed = (CURL_HTTP_V2x);
    210     data->state.http_neg.h2_prior_knowledge = TRUE;
    211     break;
    212   case CURL_HTTP_VERSION_3:
    213     neg->wanted = (CURL_HTTP_V1x | CURL_HTTP_V2x | CURL_HTTP_V3x);
    214     neg->allowed = neg->wanted;
    215     break;
    216   case CURL_HTTP_VERSION_3ONLY:
    217     neg->wanted = neg->allowed = (CURL_HTTP_V3x);
    218     break;
    219   case CURL_HTTP_VERSION_NONE:
    220   default:
    221     neg->wanted = (CURL_HTTP_V1x | CURL_HTTP_V2x);
    222     neg->allowed = (CURL_HTTP_V1x | CURL_HTTP_V2x | CURL_HTTP_V3x);
    223     break;
    224   }
    225 }
    226 
    227 CURLcode Curl_http_setup_conn(struct Curl_easy *data,
    228                               struct connectdata *conn)
    229 {
    230   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
    231      during this request */
    232   connkeep(conn, "HTTP default");
    233   if(data->state.http_neg.wanted == CURL_HTTP_V3x) {
    234     /* only HTTP/3, needs to work */
    235     CURLcode result = Curl_conn_may_http3(data, conn, conn->transport_wanted);
    236     if(result)
    237       return result;
    238   }
    239   return CURLE_OK;
    240 }
    241 
    242 #ifndef CURL_DISABLE_PROXY
    243 /*
    244  * checkProxyHeaders() checks the linked list of custom proxy headers
    245  * if proxy headers are not available, then it will lookup into http header
    246  * link list
    247  *
    248  * It takes a connectdata struct as input to see if this is a proxy request or
    249  * not, as it then might check a different header list. Provide the header
    250  * prefix without colon!
    251  */
    252 char *Curl_checkProxyheaders(struct Curl_easy *data,
    253                              const struct connectdata *conn,
    254                              const char *thisheader,
    255                              const size_t thislen)
    256 {
    257   struct curl_slist *head;
    258 
    259   for(head = (conn->bits.proxy && data->set.sep_headers) ?
    260         data->set.proxyheaders : data->set.headers;
    261       head; head = head->next) {
    262     if(curl_strnequal(head->data, thisheader, thislen) &&
    263        Curl_headersep(head->data[thislen]))
    264       return head->data;
    265   }
    266 
    267   return NULL;
    268 }
    269 #else
    270 /* disabled */
    271 #define Curl_checkProxyheaders(x,y,z,a) NULL
    272 #endif
    273 
    274 /*
    275  * Strip off leading and trailing whitespace from the value in the given HTTP
    276  * header line and return a strdup()ed copy. Returns NULL in case of
    277  * allocation failure or bad input. Returns an empty string if the header
    278  * value consists entirely of whitespace.
    279  *
    280  * If the header is provided as "name;", ending with a semicolon, it must
    281  * return a blank string.
    282  */
    283 char *Curl_copy_header_value(const char *header)
    284 {
    285   struct Curl_str out;
    286 
    287   /* find the end of the header name */
    288   if(!curlx_str_cspn(&header, &out, ";:") &&
    289      (!curlx_str_single(&header, ':') || !curlx_str_single(&header, ';'))) {
    290     curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
    291     curlx_str_trimblanks(&out);
    292 
    293     return Curl_memdup0(curlx_str(&out), curlx_strlen(&out));
    294   }
    295   /* bad input */
    296   return NULL;
    297 }
    298 
    299 #ifndef CURL_DISABLE_HTTP_AUTH
    300 
    301 #ifndef CURL_DISABLE_BASIC_AUTH
    302 /*
    303  * http_output_basic() sets up an Authorization: header (or the proxy version)
    304  * for HTTP Basic authentication.
    305  *
    306  * Returns CURLcode.
    307  */
    308 static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
    309 {
    310   size_t size = 0;
    311   char *authorization = NULL;
    312   char **userp;
    313   const char *user;
    314   const char *pwd;
    315   CURLcode result;
    316   char *out;
    317 
    318   /* credentials are unique per transfer for HTTP, do not use the ones for the
    319      connection */
    320   if(proxy) {
    321 #ifndef CURL_DISABLE_PROXY
    322     userp = &data->state.aptr.proxyuserpwd;
    323     user = data->state.aptr.proxyuser;
    324     pwd = data->state.aptr.proxypasswd;
    325 #else
    326     return CURLE_NOT_BUILT_IN;
    327 #endif
    328   }
    329   else {
    330     userp = &data->state.aptr.userpwd;
    331     user = data->state.aptr.user;
    332     pwd = data->state.aptr.passwd;
    333   }
    334 
    335   out = aprintf("%s:%s", user ? user : "", pwd ? pwd : "");
    336   if(!out)
    337     return CURLE_OUT_OF_MEMORY;
    338 
    339   result = curlx_base64_encode(out, strlen(out), &authorization, &size);
    340   if(result)
    341     goto fail;
    342 
    343   if(!authorization) {
    344     result = CURLE_REMOTE_ACCESS_DENIED;
    345     goto fail;
    346   }
    347 
    348   free(*userp);
    349   *userp = aprintf("%sAuthorization: Basic %s\r\n",
    350                    proxy ? "Proxy-" : "",
    351                    authorization);
    352   free(authorization);
    353   if(!*userp) {
    354     result = CURLE_OUT_OF_MEMORY;
    355     goto fail;
    356   }
    357 
    358 fail:
    359   free(out);
    360   return result;
    361 }
    362 
    363 #endif
    364 
    365 #ifndef CURL_DISABLE_BEARER_AUTH
    366 /*
    367  * http_output_bearer() sets up an Authorization: header
    368  * for HTTP Bearer authentication.
    369  *
    370  * Returns CURLcode.
    371  */
    372 static CURLcode http_output_bearer(struct Curl_easy *data)
    373 {
    374   char **userp;
    375   CURLcode result = CURLE_OK;
    376 
    377   userp = &data->state.aptr.userpwd;
    378   free(*userp);
    379   *userp = aprintf("Authorization: Bearer %s\r\n",
    380                    data->set.str[STRING_BEARER]);
    381 
    382   if(!*userp) {
    383     result = CURLE_OUT_OF_MEMORY;
    384     goto fail;
    385   }
    386 
    387 fail:
    388   return result;
    389 }
    390 
    391 #endif
    392 
    393 #endif
    394 
    395 /* pickoneauth() selects the most favourable authentication method from the
    396  * ones available and the ones we want.
    397  *
    398  * return TRUE if one was picked
    399  */
    400 static bool pickoneauth(struct auth *pick, unsigned long mask)
    401 {
    402   bool picked;
    403   /* only deal with authentication we want */
    404   unsigned long avail = pick->avail & pick->want & mask;
    405   picked = TRUE;
    406 
    407   /* The order of these checks is highly relevant, as this will be the order
    408      of preference in case of the existence of multiple accepted types. */
    409   if(avail & CURLAUTH_NEGOTIATE)
    410     pick->picked = CURLAUTH_NEGOTIATE;
    411 #ifndef CURL_DISABLE_BEARER_AUTH
    412   else if(avail & CURLAUTH_BEARER)
    413     pick->picked = CURLAUTH_BEARER;
    414 #endif
    415 #ifndef CURL_DISABLE_DIGEST_AUTH
    416   else if(avail & CURLAUTH_DIGEST)
    417     pick->picked = CURLAUTH_DIGEST;
    418 #endif
    419   else if(avail & CURLAUTH_NTLM)
    420     pick->picked = CURLAUTH_NTLM;
    421 #ifndef CURL_DISABLE_BASIC_AUTH
    422   else if(avail & CURLAUTH_BASIC)
    423     pick->picked = CURLAUTH_BASIC;
    424 #endif
    425 #ifndef CURL_DISABLE_AWS
    426   else if(avail & CURLAUTH_AWS_SIGV4)
    427     pick->picked = CURLAUTH_AWS_SIGV4;
    428 #endif
    429   else {
    430     pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
    431     picked = FALSE;
    432   }
    433   pick->avail = CURLAUTH_NONE; /* clear it here */
    434 
    435   return picked;
    436 }
    437 
    438 /*
    439  * http_perhapsrewind()
    440  *
    441  * The current request needs to be done again - maybe due to a follow
    442  * or authentication negotiation. Check if:
    443  * 1) a rewind of the data sent to the server is necessary
    444  * 2) the current transfer should continue or be stopped early
    445  */
    446 static CURLcode http_perhapsrewind(struct Curl_easy *data,
    447                                    struct connectdata *conn)
    448 {
    449   curl_off_t bytessent = data->req.writebytecount;
    450   curl_off_t expectsend = Curl_creader_total_length(data);
    451   curl_off_t upload_remain = (expectsend >= 0) ? (expectsend - bytessent) : -1;
    452   bool little_upload_remains = (upload_remain >= 0 && upload_remain < 2000);
    453   bool needs_rewind = Curl_creader_needs_rewind(data);
    454   /* By default, we would like to abort the transfer when little or unknown
    455    * amount remains. This may be overridden by authentications further
    456    * below! */
    457   bool abort_upload = (!data->req.upload_done && !little_upload_remains);
    458   const char *ongoing_auth = NULL;
    459 
    460   /* We need a rewind before uploading client read data again. The
    461    * checks below just influence of the upload is to be continued
    462    * or aborted early.
    463    * This depends on how much remains to be sent and in what state
    464    * the authentication is. Some auth schemes such as NTLM do not work
    465    * for a new connection. */
    466   if(needs_rewind) {
    467     infof(data, "Need to rewind upload for next request");
    468     Curl_creader_set_rewind(data, TRUE);
    469   }
    470 
    471   if(conn->bits.close)
    472     /* If we already decided to close this connection, we cannot veto. */
    473     return CURLE_OK;
    474 
    475   if(abort_upload) {
    476     /* We'd like to abort the upload - but should we? */
    477 #if defined(USE_NTLM)
    478     if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
    479        (data->state.authhost.picked == CURLAUTH_NTLM)) {
    480       ongoing_auth = "NTLM";
    481       if((conn->http_ntlm_state != NTLMSTATE_NONE) ||
    482          (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
    483         /* The NTLM-negotiation has started, keep on sending.
    484          * Need to do further work on same connection */
    485         abort_upload = FALSE;
    486       }
    487     }
    488 #endif
    489 #if defined(USE_SPNEGO)
    490     /* There is still data left to send */
    491     if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
    492        (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
    493       ongoing_auth = "NEGOTIATE";
    494       if((conn->http_negotiate_state != GSS_AUTHNONE) ||
    495          (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
    496         /* The NEGOTIATE-negotiation has started, keep on sending.
    497          * Need to do further work on same connection */
    498         abort_upload = FALSE;
    499       }
    500     }
    501 #endif
    502   }
    503 
    504   if(abort_upload) {
    505     if(upload_remain >= 0)
    506       infof(data, "%s%sclose instead of sending %" FMT_OFF_T " more bytes",
    507             ongoing_auth ? ongoing_auth : "",
    508             ongoing_auth ? " send, " : "",
    509             upload_remain);
    510     else
    511       infof(data, "%s%sclose instead of sending unknown amount "
    512             "of more bytes",
    513             ongoing_auth ? ongoing_auth : "",
    514             ongoing_auth ? " send, " : "");
    515     /* We decided to abort the ongoing transfer */
    516     streamclose(conn, "Mid-auth HTTP and much data left to send");
    517     data->req.size = 0; /* do not download any more than 0 bytes */
    518   }
    519   return CURLE_OK;
    520 }
    521 
    522 /*
    523  * Curl_http_auth_act() gets called when all HTTP headers have been received
    524  * and it checks what authentication methods that are available and decides
    525  * which one (if any) to use. It will set 'newurl' if an auth method was
    526  * picked.
    527  */
    528 
    529 CURLcode Curl_http_auth_act(struct Curl_easy *data)
    530 {
    531   struct connectdata *conn = data->conn;
    532   bool pickhost = FALSE;
    533   bool pickproxy = FALSE;
    534   CURLcode result = CURLE_OK;
    535   unsigned long authmask = ~0ul;
    536 
    537   if(!data->set.str[STRING_BEARER])
    538     authmask &= (unsigned long)~CURLAUTH_BEARER;
    539 
    540   if(100 <= data->req.httpcode && data->req.httpcode <= 199)
    541     /* this is a transient response code, ignore */
    542     return CURLE_OK;
    543 
    544   if(data->state.authproblem)
    545     return data->set.http_fail_on_error ? CURLE_HTTP_RETURNED_ERROR : CURLE_OK;
    546 
    547   if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
    548      ((data->req.httpcode == 401) ||
    549       (data->req.authneg && data->req.httpcode < 300))) {
    550     pickhost = pickoneauth(&data->state.authhost, authmask);
    551     if(!pickhost)
    552       data->state.authproblem = TRUE;
    553     else
    554       data->info.httpauthpicked = data->state.authhost.picked;
    555     if(data->state.authhost.picked == CURLAUTH_NTLM &&
    556        (data->req.httpversion_sent > 11)) {
    557       infof(data, "Forcing HTTP/1.1 for NTLM");
    558       connclose(conn, "Force HTTP/1.1 connection");
    559       data->state.http_neg.wanted = CURL_HTTP_V1x;
    560       data->state.http_neg.allowed = CURL_HTTP_V1x;
    561     }
    562   }
    563 #ifndef CURL_DISABLE_PROXY
    564   if(conn->bits.proxy_user_passwd &&
    565      ((data->req.httpcode == 407) ||
    566       (data->req.authneg && data->req.httpcode < 300))) {
    567     pickproxy = pickoneauth(&data->state.authproxy,
    568                             authmask & ~CURLAUTH_BEARER);
    569     if(!pickproxy)
    570       data->state.authproblem = TRUE;
    571     else
    572       data->info.proxyauthpicked = data->state.authproxy.picked;
    573 
    574   }
    575 #endif
    576 
    577   if(pickhost || pickproxy) {
    578     result = http_perhapsrewind(data, conn);
    579     if(result)
    580       return result;
    581 
    582     /* In case this is GSS auth, the newurl field is already allocated so
    583        we must make sure to free it before allocating a new one. As figured
    584        out in bug #2284386 */
    585     free(data->req.newurl);
    586     data->req.newurl = strdup(data->state.url); /* clone URL */
    587     if(!data->req.newurl)
    588       return CURLE_OUT_OF_MEMORY;
    589   }
    590   else if((data->req.httpcode < 300) &&
    591           (!data->state.authhost.done) &&
    592           data->req.authneg) {
    593     /* no (known) authentication available,
    594        authentication is not "done" yet and
    595        no authentication seems to be required and
    596        we did not try HEAD or GET */
    597     if((data->state.httpreq != HTTPREQ_GET) &&
    598        (data->state.httpreq != HTTPREQ_HEAD)) {
    599       data->req.newurl = strdup(data->state.url); /* clone URL */
    600       if(!data->req.newurl)
    601         return CURLE_OUT_OF_MEMORY;
    602       data->state.authhost.done = TRUE;
    603     }
    604   }
    605   if(http_should_fail(data, data->req.httpcode)) {
    606     failf(data, "The requested URL returned error: %d",
    607           data->req.httpcode);
    608     result = CURLE_HTTP_RETURNED_ERROR;
    609   }
    610 
    611   return result;
    612 }
    613 
    614 #ifndef CURL_DISABLE_HTTP_AUTH
    615 /*
    616  * Output the correct authentication header depending on the auth type
    617  * and whether or not it is to a proxy.
    618  */
    619 static CURLcode
    620 output_auth_headers(struct Curl_easy *data,
    621                     struct connectdata *conn,
    622                     struct auth *authstatus,
    623                     const char *request,
    624                     const char *path,
    625                     bool proxy)
    626 {
    627   const char *auth = NULL;
    628   CURLcode result = CURLE_OK;
    629   (void)conn;
    630 
    631 #ifdef CURL_DISABLE_DIGEST_AUTH
    632   (void)request;
    633   (void)path;
    634 #endif
    635 #ifndef CURL_DISABLE_AWS
    636   if((authstatus->picked == CURLAUTH_AWS_SIGV4) && !proxy) {
    637     /* this method is never for proxy */
    638     auth = "AWS_SIGV4";
    639     result = Curl_output_aws_sigv4(data);
    640     if(result)
    641       return result;
    642   }
    643   else
    644 #endif
    645 #ifdef USE_SPNEGO
    646   if(authstatus->picked == CURLAUTH_NEGOTIATE) {
    647     auth = "Negotiate";
    648     result = Curl_output_negotiate(data, conn, proxy);
    649     if(result)
    650       return result;
    651   }
    652   else
    653 #endif
    654 #ifdef USE_NTLM
    655   if(authstatus->picked == CURLAUTH_NTLM) {
    656     auth = "NTLM";
    657     result = Curl_output_ntlm(data, proxy);
    658     if(result)
    659       return result;
    660   }
    661   else
    662 #endif
    663 #ifndef CURL_DISABLE_DIGEST_AUTH
    664   if(authstatus->picked == CURLAUTH_DIGEST) {
    665     auth = "Digest";
    666     result = Curl_output_digest(data,
    667                                 proxy,
    668                                 (const unsigned char *)request,
    669                                 (const unsigned char *)path);
    670     if(result)
    671       return result;
    672   }
    673   else
    674 #endif
    675 #ifndef CURL_DISABLE_BASIC_AUTH
    676   if(authstatus->picked == CURLAUTH_BASIC) {
    677     /* Basic */
    678     if(
    679 #ifndef CURL_DISABLE_PROXY
    680       (proxy && conn->bits.proxy_user_passwd &&
    681        !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
    682 #endif
    683       (!proxy && data->state.aptr.user &&
    684        !Curl_checkheaders(data, STRCONST("Authorization")))) {
    685       auth = "Basic";
    686       result = http_output_basic(data, proxy);
    687       if(result)
    688         return result;
    689     }
    690 
    691     /* NOTE: this function should set 'done' TRUE, as the other auth
    692        functions work that way */
    693     authstatus->done = TRUE;
    694   }
    695 #endif
    696 #ifndef CURL_DISABLE_BEARER_AUTH
    697   if(authstatus->picked == CURLAUTH_BEARER) {
    698     /* Bearer */
    699     if((!proxy && data->set.str[STRING_BEARER] &&
    700         !Curl_checkheaders(data, STRCONST("Authorization")))) {
    701       auth = "Bearer";
    702       result = http_output_bearer(data);
    703       if(result)
    704         return result;
    705     }
    706 
    707     /* NOTE: this function should set 'done' TRUE, as the other auth
    708        functions work that way */
    709     authstatus->done = TRUE;
    710   }
    711 #endif
    712 
    713   if(auth) {
    714 #ifndef CURL_DISABLE_PROXY
    715     infof(data, "%s auth using %s with user '%s'",
    716           proxy ? "Proxy" : "Server", auth,
    717           proxy ? (data->state.aptr.proxyuser ?
    718                    data->state.aptr.proxyuser : "") :
    719           (data->state.aptr.user ?
    720            data->state.aptr.user : ""));
    721 #else
    722     (void)proxy;
    723     infof(data, "Server auth using %s with user '%s'",
    724           auth, data->state.aptr.user ?
    725           data->state.aptr.user : "");
    726 #endif
    727     authstatus->multipass = !authstatus->done;
    728   }
    729   else
    730     authstatus->multipass = FALSE;
    731 
    732   return result;
    733 }
    734 
    735 /**
    736  * Curl_http_output_auth() setups the authentication headers for the
    737  * host/proxy and the correct authentication
    738  * method. data->state.authdone is set to TRUE when authentication is
    739  * done.
    740  *
    741  * @param conn all information about the current connection
    742  * @param request pointer to the request keyword
    743  * @param path pointer to the requested path; should include query part
    744  * @param proxytunnel boolean if this is the request setting up a "proxy
    745  * tunnel"
    746  *
    747  * @returns CURLcode
    748  */
    749 CURLcode
    750 Curl_http_output_auth(struct Curl_easy *data,
    751                       struct connectdata *conn,
    752                       const char *request,
    753                       Curl_HttpReq httpreq,
    754                       const char *path,
    755                       bool proxytunnel) /* TRUE if this is the request setting
    756                                            up the proxy tunnel */
    757 {
    758   CURLcode result = CURLE_OK;
    759   struct auth *authhost;
    760   struct auth *authproxy;
    761 
    762   DEBUGASSERT(data);
    763 
    764   authhost = &data->state.authhost;
    765   authproxy = &data->state.authproxy;
    766 
    767   if(
    768 #ifndef CURL_DISABLE_PROXY
    769     (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
    770 #endif
    771     data->state.aptr.user ||
    772 #ifdef USE_SPNEGO
    773     authhost->want & CURLAUTH_NEGOTIATE ||
    774     authproxy->want & CURLAUTH_NEGOTIATE ||
    775 #endif
    776     data->set.str[STRING_BEARER])
    777     /* continue please */;
    778   else {
    779     authhost->done = TRUE;
    780     authproxy->done = TRUE;
    781     return CURLE_OK; /* no authentication with no user or password */
    782   }
    783 
    784   if(authhost->want && !authhost->picked)
    785     /* The app has selected one or more methods, but none has been picked
    786        so far by a server round-trip. Then we set the picked one to the
    787        want one, and if this is one single bit it will be used instantly. */
    788     authhost->picked = authhost->want;
    789 
    790   if(authproxy->want && !authproxy->picked)
    791     /* The app has selected one or more methods, but none has been picked so
    792        far by a proxy round-trip. Then we set the picked one to the want one,
    793        and if this is one single bit it will be used instantly. */
    794     authproxy->picked = authproxy->want;
    795 
    796 #ifndef CURL_DISABLE_PROXY
    797   /* Send proxy authentication header if needed */
    798   if(conn->bits.httpproxy &&
    799      (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
    800     result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
    801     if(result)
    802       return result;
    803   }
    804   else
    805 #else
    806   (void)proxytunnel;
    807 #endif /* CURL_DISABLE_PROXY */
    808     /* we have no proxy so let's pretend we are done authenticating
    809        with it */
    810     authproxy->done = TRUE;
    811 
    812   /* To prevent the user+password to get sent to other than the original host
    813      due to a location-follow */
    814   if(Curl_auth_allowed_to_host(data)
    815 #ifndef CURL_DISABLE_NETRC
    816      || conn->bits.netrc
    817 #endif
    818     )
    819     result = output_auth_headers(data, conn, authhost, request, path, FALSE);
    820   else
    821     authhost->done = TRUE;
    822 
    823   if(((authhost->multipass && !authhost->done) ||
    824       (authproxy->multipass && !authproxy->done)) &&
    825      (httpreq != HTTPREQ_GET) &&
    826      (httpreq != HTTPREQ_HEAD)) {
    827     /* Auth is required and we are not authenticated yet. Make a PUT or POST
    828        with content-length zero as a "probe". */
    829     data->req.authneg = TRUE;
    830   }
    831   else
    832     data->req.authneg = FALSE;
    833 
    834   return result;
    835 }
    836 
    837 #else
    838 /* when disabled */
    839 CURLcode
    840 Curl_http_output_auth(struct Curl_easy *data,
    841                       struct connectdata *conn,
    842                       const char *request,
    843                       Curl_HttpReq httpreq,
    844                       const char *path,
    845                       bool proxytunnel)
    846 {
    847   (void)data;
    848   (void)conn;
    849   (void)request;
    850   (void)httpreq;
    851   (void)path;
    852   (void)proxytunnel;
    853   return CURLE_OK;
    854 }
    855 #endif
    856 
    857 #if defined(USE_SPNEGO) || defined(USE_NTLM) || \
    858   !defined(CURL_DISABLE_DIGEST_AUTH) || \
    859   !defined(CURL_DISABLE_BASIC_AUTH) || \
    860   !defined(CURL_DISABLE_BEARER_AUTH)
    861 static bool authcmp(const char *auth, const char *line)
    862 {
    863   /* the auth string must not have an alnum following */
    864   size_t n = strlen(auth);
    865   return curl_strnequal(auth, line, n) && !ISALNUM(line[n]);
    866 }
    867 #endif
    868 
    869 #ifdef USE_SPNEGO
    870 static CURLcode auth_spnego(struct Curl_easy *data,
    871                             bool proxy,
    872                             const char *auth,
    873                             struct auth *authp,
    874                             unsigned long *availp)
    875 {
    876   if((authp->avail & CURLAUTH_NEGOTIATE) || Curl_auth_is_spnego_supported()) {
    877     *availp |= CURLAUTH_NEGOTIATE;
    878     authp->avail |= CURLAUTH_NEGOTIATE;
    879 
    880     if(authp->picked == CURLAUTH_NEGOTIATE) {
    881       struct connectdata *conn = data->conn;
    882       CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
    883       curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
    884         &conn->http_negotiate_state;
    885       if(!result) {
    886         free(data->req.newurl);
    887         data->req.newurl = strdup(data->state.url);
    888         if(!data->req.newurl)
    889           return CURLE_OUT_OF_MEMORY;
    890         data->state.authproblem = FALSE;
    891         /* we received a GSS auth token and we dealt with it fine */
    892         *negstate = GSS_AUTHRECV;
    893       }
    894       else
    895         data->state.authproblem = TRUE;
    896     }
    897   }
    898   return CURLE_OK;
    899 }
    900 #endif
    901 
    902 #ifdef USE_NTLM
    903 static CURLcode auth_ntlm(struct Curl_easy *data,
    904                           bool proxy,
    905                           const char *auth,
    906                           struct auth *authp,
    907                           unsigned long *availp)
    908 {
    909   /* NTLM support requires the SSL crypto libs */
    910   if((authp->avail & CURLAUTH_NTLM) || Curl_auth_is_ntlm_supported()) {
    911     *availp |= CURLAUTH_NTLM;
    912     authp->avail |= CURLAUTH_NTLM;
    913 
    914     if(authp->picked == CURLAUTH_NTLM) {
    915       /* NTLM authentication is picked and activated */
    916       CURLcode result = Curl_input_ntlm(data, proxy, auth);
    917       if(!result)
    918         data->state.authproblem = FALSE;
    919       else {
    920         infof(data, "NTLM authentication problem, ignoring.");
    921         data->state.authproblem = TRUE;
    922       }
    923     }
    924   }
    925   return CURLE_OK;
    926 }
    927 #endif
    928 
    929 #ifndef CURL_DISABLE_DIGEST_AUTH
    930 static CURLcode auth_digest(struct Curl_easy *data,
    931                             bool proxy,
    932                             const char *auth,
    933                             struct auth *authp,
    934                             unsigned long *availp)
    935 {
    936   if(authp->avail & CURLAUTH_DIGEST)
    937     infof(data, "Ignoring duplicate digest auth header.");
    938   else if(Curl_auth_is_digest_supported()) {
    939     CURLcode result;
    940 
    941     *availp |= CURLAUTH_DIGEST;
    942     authp->avail |= CURLAUTH_DIGEST;
    943 
    944     /* We call this function on input Digest headers even if Digest
    945      * authentication is not activated yet, as we need to store the
    946      * incoming data from this header in case we are going to use
    947      * Digest */
    948     result = Curl_input_digest(data, proxy, auth);
    949     if(result) {
    950       infof(data, "Digest authentication problem, ignoring.");
    951       data->state.authproblem = TRUE;
    952     }
    953   }
    954   return CURLE_OK;
    955 }
    956 #endif
    957 
    958 #ifndef CURL_DISABLE_BASIC_AUTH
    959 static CURLcode auth_basic(struct Curl_easy *data,
    960                            struct auth *authp,
    961                            unsigned long *availp)
    962 {
    963   *availp |= CURLAUTH_BASIC;
    964   authp->avail |= CURLAUTH_BASIC;
    965   if(authp->picked == CURLAUTH_BASIC) {
    966     /* We asked for Basic authentication but got a 40X back
    967        anyway, which basically means our name+password is not
    968        valid. */
    969     authp->avail = CURLAUTH_NONE;
    970     infof(data, "Basic authentication problem, ignoring.");
    971     data->state.authproblem = TRUE;
    972   }
    973   return CURLE_OK;
    974 }
    975 #endif
    976 
    977 #ifndef CURL_DISABLE_BEARER_AUTH
    978 static CURLcode auth_bearer(struct Curl_easy *data,
    979                             struct auth *authp,
    980                             unsigned long *availp)
    981 {
    982   *availp |= CURLAUTH_BEARER;
    983   authp->avail |= CURLAUTH_BEARER;
    984   if(authp->picked == CURLAUTH_BEARER) {
    985     /* We asked for Bearer authentication but got a 40X back
    986        anyway, which basically means our token is not valid. */
    987     authp->avail = CURLAUTH_NONE;
    988     infof(data, "Bearer authentication problem, ignoring.");
    989     data->state.authproblem = TRUE;
    990   }
    991   return CURLE_OK;
    992 }
    993 #endif
    994 
    995 /*
    996  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
    997  * headers. They are dealt with both in the transfer.c main loop and in the
    998  * proxy CONNECT loop.
    999  *
   1000  * The 'auth' line ends with a null byte without CR or LF present.
   1001  */
   1002 CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
   1003                               const char *auth) /* the first non-space */
   1004 {
   1005   /*
   1006    * This resource requires authentication
   1007    */
   1008 #if defined(USE_SPNEGO) ||                      \
   1009   defined(USE_NTLM) ||                          \
   1010   !defined(CURL_DISABLE_DIGEST_AUTH) ||         \
   1011   !defined(CURL_DISABLE_BASIC_AUTH) ||          \
   1012   !defined(CURL_DISABLE_BEARER_AUTH)
   1013 
   1014   unsigned long *availp;
   1015   struct auth *authp;
   1016   CURLcode result = CURLE_OK;
   1017   DEBUGASSERT(auth);
   1018   DEBUGASSERT(data);
   1019 
   1020   if(proxy) {
   1021     availp = &data->info.proxyauthavail;
   1022     authp = &data->state.authproxy;
   1023   }
   1024   else {
   1025     availp = &data->info.httpauthavail;
   1026     authp = &data->state.authhost;
   1027   }
   1028 
   1029   /*
   1030    * Here we check if we want the specific single authentication (using ==) and
   1031    * if we do, we initiate usage of it.
   1032    *
   1033    * If the provided authentication is wanted as one out of several accepted
   1034    * types (using &), we OR this authentication type to the authavail
   1035    * variable.
   1036    *
   1037    * Note:
   1038    *
   1039    * ->picked is first set to the 'want' value (one or more bits) before the
   1040    * request is sent, and then it is again set _after_ all response 401/407
   1041    * headers have been received but then only to a single preferred method
   1042    * (bit).
   1043    */
   1044 
   1045   while(*auth) {
   1046 #ifdef USE_SPNEGO
   1047     if(authcmp("Negotiate", auth))
   1048       result = auth_spnego(data, proxy, auth, authp, availp);
   1049 #endif
   1050 #ifdef USE_NTLM
   1051     if(!result && authcmp("NTLM", auth))
   1052       result = auth_ntlm(data, proxy, auth, authp, availp);
   1053 #endif
   1054 #ifndef CURL_DISABLE_DIGEST_AUTH
   1055     if(!result && authcmp("Digest", auth))
   1056       result = auth_digest(data, proxy, auth, authp, availp);
   1057 #endif
   1058 #ifndef CURL_DISABLE_BASIC_AUTH
   1059     if(!result && authcmp("Basic", auth))
   1060       result = auth_basic(data, authp, availp);
   1061 #endif
   1062 #ifndef CURL_DISABLE_BEARER_AUTH
   1063     if(authcmp("Bearer", auth))
   1064       result = auth_bearer(data, authp, availp);
   1065 #endif
   1066 
   1067     if(result)
   1068       break;
   1069 
   1070     /* there may be multiple methods on one line, so keep reading */
   1071     auth = strchr(auth, ',');
   1072     if(auth) /* if we are on a comma, skip it */
   1073       auth++;
   1074     else
   1075       break;
   1076     curlx_str_passblanks(&auth);
   1077   }
   1078   return result;
   1079 #else
   1080   (void) proxy;
   1081   /* nothing to do when disabled */
   1082   return CURLE_OK;
   1083 #endif
   1084 }
   1085 
   1086 /**
   1087  * http_should_fail() determines whether an HTTP response code has gotten us
   1088  * into an error state or not.
   1089  *
   1090  * @retval FALSE communications should continue
   1091  *
   1092  * @retval TRUE communications should not continue
   1093  */
   1094 static bool http_should_fail(struct Curl_easy *data, int httpcode)
   1095 {
   1096   DEBUGASSERT(data);
   1097   DEBUGASSERT(data->conn);
   1098 
   1099   /*
   1100   ** If we have not been asked to fail on error,
   1101   ** do not fail.
   1102   */
   1103   if(!data->set.http_fail_on_error)
   1104     return FALSE;
   1105 
   1106   /*
   1107   ** Any code < 400 is never terminal.
   1108   */
   1109   if(httpcode < 400)
   1110     return FALSE;
   1111 
   1112   /*
   1113   ** A 416 response to a resume request is presumably because the file is
   1114   ** already completely downloaded and thus not actually a fail.
   1115   */
   1116   if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
   1117      httpcode == 416)
   1118     return FALSE;
   1119 
   1120   /*
   1121   ** Any code >= 400 that is not 401 or 407 is always
   1122   ** a terminal error
   1123   */
   1124   if((httpcode != 401) && (httpcode != 407))
   1125     return TRUE;
   1126 
   1127   /*
   1128   ** All we have left to deal with is 401 and 407
   1129   */
   1130   DEBUGASSERT((httpcode == 401) || (httpcode == 407));
   1131 
   1132   /*
   1133   ** Examine the current authentication state to see if this is an error. The
   1134   ** idea is for this function to get called after processing all the headers
   1135   ** in a response message. So, if we have been to asked to authenticate a
   1136   ** particular stage, and we have done it, we are OK. If we are already
   1137   ** completely authenticated, it is not OK to get another 401 or 407.
   1138   **
   1139   ** It is possible for authentication to go stale such that the client needs
   1140   ** to reauthenticate. Once that info is available, use it here.
   1141   */
   1142 
   1143   /*
   1144   ** Either we are not authenticating, or we are supposed to be authenticating
   1145   ** something else. This is an error.
   1146   */
   1147   if((httpcode == 401) && !data->state.aptr.user)
   1148     return TRUE;
   1149 #ifndef CURL_DISABLE_PROXY
   1150   if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
   1151     return TRUE;
   1152 #endif
   1153 
   1154   return data->state.authproblem;
   1155 }
   1156 
   1157 static void http_switch_to_get(struct Curl_easy *data, int code)
   1158 {
   1159   const char *req = data->set.str[STRING_CUSTOMREQUEST];
   1160   if((req || data->state.httpreq != HTTPREQ_GET) &&
   1161      (data->set.http_follow_mode == CURLFOLLOW_OBEYCODE)) {
   1162     infof(data, "Switch to GET because of %d response", code);
   1163     data->state.http_ignorecustom = TRUE;
   1164   }
   1165   else if(req && (data->set.http_follow_mode != CURLFOLLOW_FIRSTONLY))
   1166     infof(data, "Stick to %s instead of GET", req);
   1167 
   1168   data->state.httpreq = HTTPREQ_GET;
   1169   Curl_creader_set_rewind(data, FALSE);
   1170 }
   1171 
   1172 CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
   1173                           followtype type)
   1174 {
   1175   bool disallowport = FALSE;
   1176   bool reachedmax = FALSE;
   1177   char *follow_url = NULL;
   1178   CURLUcode uc;
   1179   CURLcode rewind_result;
   1180   bool switch_to_get = FALSE;
   1181 
   1182   DEBUGASSERT(type != FOLLOW_NONE);
   1183 
   1184   if(type != FOLLOW_FAKE)
   1185     data->state.requests++; /* count all real follows */
   1186   if(type == FOLLOW_REDIR) {
   1187     if((data->set.maxredirs != -1) &&
   1188        (data->state.followlocation >= data->set.maxredirs)) {
   1189       reachedmax = TRUE;
   1190       type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
   1191                              to URL */
   1192     }
   1193     else {
   1194       data->state.followlocation++; /* count redirect-followings, including
   1195                                        auth reloads */
   1196 
   1197       if(data->set.http_auto_referer) {
   1198         CURLU *u;
   1199         char *referer = NULL;
   1200 
   1201         /* We are asked to automatically set the previous URL as the referer
   1202            when we get the next URL. We pick the ->url field, which may or may
   1203            not be 100% correct */
   1204 
   1205         if(data->state.referer_alloc) {
   1206           Curl_safefree(data->state.referer);
   1207           data->state.referer_alloc = FALSE;
   1208         }
   1209 
   1210         /* Make a copy of the URL without credentials and fragment */
   1211         u = curl_url();
   1212         if(!u)
   1213           return CURLE_OUT_OF_MEMORY;
   1214 
   1215         uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
   1216         if(!uc)
   1217           uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
   1218         if(!uc)
   1219           uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
   1220         if(!uc)
   1221           uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
   1222         if(!uc)
   1223           uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
   1224 
   1225         curl_url_cleanup(u);
   1226 
   1227         if(uc || !referer)
   1228           return CURLE_OUT_OF_MEMORY;
   1229 
   1230         data->state.referer = referer;
   1231         data->state.referer_alloc = TRUE; /* yes, free this later */
   1232       }
   1233     }
   1234   }
   1235 
   1236   if((type != FOLLOW_RETRY) &&
   1237      (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
   1238      Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
   1239     /* If this is not redirect due to a 401 or 407 response and an absolute
   1240        URL: do not allow a custom port number */
   1241     disallowport = TRUE;
   1242   }
   1243 
   1244   DEBUGASSERT(data->state.uh);
   1245   uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, (unsigned int)
   1246                     ((type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
   1247                      ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
   1248                      CURLU_ALLOW_SPACE |
   1249                      (data->set.path_as_is ? CURLU_PATH_AS_IS : 0)));
   1250   if(uc) {
   1251     if(type != FOLLOW_FAKE) {
   1252       failf(data, "The redirect target URL could not be parsed: %s",
   1253             curl_url_strerror(uc));
   1254       return Curl_uc_to_curlcode(uc);
   1255     }
   1256 
   1257     /* the URL could not be parsed for some reason, but since this is FAKE
   1258        mode, just duplicate the field as-is */
   1259     follow_url = strdup(newurl);
   1260     if(!follow_url)
   1261       return CURLE_OUT_OF_MEMORY;
   1262   }
   1263   else {
   1264     uc = curl_url_get(data->state.uh, CURLUPART_URL, &follow_url, 0);
   1265     if(uc)
   1266       return Curl_uc_to_curlcode(uc);
   1267 
   1268     /* Clear auth if this redirects to a different port number or protocol,
   1269        unless permitted */
   1270     if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
   1271       char *portnum;
   1272       int port;
   1273       bool clear = FALSE;
   1274 
   1275       if(data->set.use_port && data->state.allow_port)
   1276         /* a custom port is used */
   1277         port = (int)data->set.use_port;
   1278       else {
   1279         uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
   1280                           CURLU_DEFAULT_PORT);
   1281         if(uc) {
   1282           free(follow_url);
   1283           return Curl_uc_to_curlcode(uc);
   1284         }
   1285         port = atoi(portnum);
   1286         free(portnum);
   1287       }
   1288       if(port != data->info.conn_remote_port) {
   1289         infof(data, "Clear auth, redirects to port from %u to %u",
   1290               data->info.conn_remote_port, port);
   1291         clear = TRUE;
   1292       }
   1293       else {
   1294         char *scheme;
   1295         const struct Curl_handler *p;
   1296         uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
   1297         if(uc) {
   1298           free(follow_url);
   1299           return Curl_uc_to_curlcode(uc);
   1300         }
   1301 
   1302         p = Curl_get_scheme_handler(scheme);
   1303         if(p && (p->protocol != data->info.conn_protocol)) {
   1304           infof(data, "Clear auth, redirects scheme from %s to %s",
   1305                 data->info.conn_scheme, scheme);
   1306           clear = TRUE;
   1307         }
   1308         free(scheme);
   1309       }
   1310       if(clear) {
   1311         Curl_safefree(data->state.aptr.user);
   1312         Curl_safefree(data->state.aptr.passwd);
   1313       }
   1314     }
   1315   }
   1316   DEBUGASSERT(follow_url);
   1317 
   1318   if(type == FOLLOW_FAKE) {
   1319     /* we are only figuring out the new URL if we would have followed locations
   1320        but now we are done so we can get out! */
   1321     data->info.wouldredirect = follow_url;
   1322 
   1323     if(reachedmax) {
   1324       failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
   1325       return CURLE_TOO_MANY_REDIRECTS;
   1326     }
   1327     return CURLE_OK;
   1328   }
   1329 
   1330   if(disallowport)
   1331     data->state.allow_port = FALSE;
   1332 
   1333   if(data->state.url_alloc)
   1334     Curl_safefree(data->state.url);
   1335 
   1336   data->state.url = follow_url;
   1337   data->state.url_alloc = TRUE;
   1338   rewind_result = Curl_req_soft_reset(&data->req, data);
   1339   infof(data, "Issue another request to this URL: '%s'", data->state.url);
   1340   if((data->set.http_follow_mode == CURLFOLLOW_FIRSTONLY) &&
   1341      data->set.str[STRING_CUSTOMREQUEST] &&
   1342      !data->state.http_ignorecustom) {
   1343     data->state.http_ignorecustom = TRUE;
   1344     infof(data, "Drop custom request method for next request");
   1345   }
   1346 
   1347   /*
   1348    * We get here when the HTTP code is 300-399 (and 401). We need to perform
   1349    * differently based on exactly what return code there was.
   1350    *
   1351    * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
   1352    * an HTTP (proxy-) authentication scheme other than Basic.
   1353    */
   1354   switch(data->info.httpcode) {
   1355     /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
   1356        Authorization: XXXX header in the HTTP request code snippet */
   1357     /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
   1358        Proxy-Authorization: XXXX header in the HTTP request code snippet */
   1359     /* 300 - Multiple Choices */
   1360     /* 306 - Not used */
   1361     /* 307 - Temporary Redirect */
   1362   default:  /* for all above (and the unknown ones) */
   1363     /* Some codes are explicitly mentioned since I have checked RFC2616 and
   1364      * they seem to be OK to POST to.
   1365      */
   1366     break;
   1367   case 301: /* Moved Permanently */
   1368     /* (quote from RFC7231, section 6.4.2)
   1369      *
   1370      * Note: For historical reasons, a user agent MAY change the request
   1371      * method from POST to GET for the subsequent request. If this
   1372      * behavior is undesired, the 307 (Temporary Redirect) status code
   1373      * can be used instead.
   1374      *
   1375      * ----
   1376      *
   1377      * Many webservers expect this, so these servers often answers to a POST
   1378      * request with an error page. To be sure that libcurl gets the page that
   1379      * most user agents would get, libcurl has to force GET.
   1380      *
   1381      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
   1382      * can be overridden with CURLOPT_POSTREDIR.
   1383      */
   1384     if((data->state.httpreq == HTTPREQ_POST
   1385         || data->state.httpreq == HTTPREQ_POST_FORM
   1386         || data->state.httpreq == HTTPREQ_POST_MIME)
   1387        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
   1388       http_switch_to_get(data, 301);
   1389       switch_to_get = TRUE;
   1390     }
   1391     break;
   1392   case 302: /* Found */
   1393     /* (quote from RFC7231, section 6.4.3)
   1394      *
   1395      * Note: For historical reasons, a user agent MAY change the request
   1396      * method from POST to GET for the subsequent request. If this
   1397      * behavior is undesired, the 307 (Temporary Redirect) status code
   1398      * can be used instead.
   1399      *
   1400      * ----
   1401      *
   1402      * Many webservers expect this, so these servers often answers to a POST
   1403      * request with an error page. To be sure that libcurl gets the page that
   1404      * most user agents would get, libcurl has to force GET.
   1405      *
   1406      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
   1407      * can be overridden with CURLOPT_POSTREDIR.
   1408      */
   1409     if((data->state.httpreq == HTTPREQ_POST
   1410         || data->state.httpreq == HTTPREQ_POST_FORM
   1411         || data->state.httpreq == HTTPREQ_POST_MIME)
   1412        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
   1413       http_switch_to_get(data, 302);
   1414       switch_to_get = TRUE;
   1415     }
   1416     break;
   1417 
   1418   case 303: /* See Other */
   1419     /* 'See Other' location is not the resource but a substitute for the
   1420      * resource. In this case we switch the method to GET/HEAD, unless the
   1421      * method is POST and the user specified to keep it as POST.
   1422      * https://github.com/curl/curl/issues/5237#issuecomment-614641049
   1423      */
   1424     if(data->state.httpreq != HTTPREQ_GET &&
   1425        ((data->state.httpreq != HTTPREQ_POST &&
   1426          data->state.httpreq != HTTPREQ_POST_FORM &&
   1427          data->state.httpreq != HTTPREQ_POST_MIME) ||
   1428         !(data->set.keep_post & CURL_REDIR_POST_303))) {
   1429       http_switch_to_get(data, 303);
   1430       switch_to_get = TRUE;
   1431     }
   1432     break;
   1433   case 304: /* Not Modified */
   1434     /* 304 means we did a conditional request and it was "Not modified".
   1435      * We should not get any Location: header in this response!
   1436      */
   1437     break;
   1438   case 305: /* Use Proxy */
   1439     /* (quote from RFC2616, section 10.3.6):
   1440      * "The requested resource MUST be accessed through the proxy given
   1441      * by the Location field. The Location field gives the URI of the
   1442      * proxy. The recipient is expected to repeat this single request
   1443      * via the proxy. 305 responses MUST only be generated by origin
   1444      * servers."
   1445      */
   1446     break;
   1447   }
   1448 
   1449   /* When rewind of upload data failed and we are not switching to GET,
   1450    * we need to fail the follow, as we cannot send the data again. */
   1451   if(rewind_result && !switch_to_get)
   1452     return rewind_result;
   1453 
   1454   Curl_pgrsTime(data, TIMER_REDIRECT);
   1455   Curl_pgrsResetTransferSizes(data);
   1456 
   1457   return CURLE_OK;
   1458 }
   1459 
   1460 /*
   1461  * Curl_compareheader()
   1462  *
   1463  * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
   1464  * Pass headers WITH the colon.
   1465  */
   1466 bool
   1467 Curl_compareheader(const char *headerline, /* line to check */
   1468                    const char *header,  /* header keyword _with_ colon */
   1469                    const size_t hlen,   /* len of the keyword in bytes */
   1470                    const char *content, /* content string to find */
   1471                    const size_t clen)   /* len of the content in bytes */
   1472 {
   1473   /* RFC2616, section 4.2 says: "Each header field consists of a name followed
   1474    * by a colon (":") and the field value. Field names are case-insensitive.
   1475    * The field value MAY be preceded by any amount of LWS, though a single SP
   1476    * is preferred." */
   1477 
   1478   const char *p;
   1479   struct Curl_str val;
   1480   DEBUGASSERT(hlen);
   1481   DEBUGASSERT(clen);
   1482   DEBUGASSERT(header);
   1483   DEBUGASSERT(content);
   1484 
   1485   if(!curl_strnequal(headerline, header, hlen))
   1486     return FALSE; /* does not start with header */
   1487 
   1488   /* pass the header */
   1489   p = &headerline[hlen];
   1490 
   1491   if(curlx_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE))
   1492     return FALSE;
   1493   curlx_str_trimblanks(&val);
   1494 
   1495   /* find the content string in the rest of the line */
   1496   if(curlx_strlen(&val) >= clen) {
   1497     size_t len;
   1498     p = curlx_str(&val);
   1499     for(len = curlx_strlen(&val); len >= curlx_strlen(&val); len--, p++) {
   1500       if(curl_strnequal(p, content, clen))
   1501         return TRUE; /* match! */
   1502     }
   1503   }
   1504   return FALSE; /* no match */
   1505 }
   1506 
   1507 /*
   1508  * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
   1509  * the generic Curl_connect().
   1510  */
   1511 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
   1512 {
   1513   struct connectdata *conn = data->conn;
   1514 
   1515   /* We default to persistent connections. We set this already in this connect
   1516      function to make the reuse checks properly be able to check this bit. */
   1517   connkeep(conn, "HTTP default");
   1518 
   1519   return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
   1520 }
   1521 
   1522 /* this returns the socket to wait for in the DO and DOING state for the multi
   1523    interface and then we are always _sending_ a request and thus we wait for
   1524    the single socket to become writable only */
   1525 int Curl_http_getsock_do(struct Curl_easy *data,
   1526                          struct connectdata *conn,
   1527                          curl_socket_t *socks)
   1528 {
   1529   /* write mode */
   1530   (void)conn;
   1531   socks[0] = Curl_conn_get_socket(data, FIRSTSOCKET);
   1532   return GETSOCK_WRITESOCK(0);
   1533 }
   1534 
   1535 /*
   1536  * Curl_http_done() gets called after a single HTTP request has been
   1537  * performed.
   1538  */
   1539 
   1540 CURLcode Curl_http_done(struct Curl_easy *data,
   1541                         CURLcode status, bool premature)
   1542 {
   1543   struct connectdata *conn = data->conn;
   1544 
   1545   /* Clear multipass flag. If authentication is not done yet, then it will get
   1546    * a chance to be set back to true when we output the next auth header */
   1547   data->state.authhost.multipass = FALSE;
   1548   data->state.authproxy.multipass = FALSE;
   1549 
   1550   curlx_dyn_reset(&data->state.headerb);
   1551 
   1552   if(status)
   1553     return status;
   1554 
   1555   if(!premature && /* this check is pointless when DONE is called before the
   1556                       entire operation is complete */
   1557      !conn->bits.retry &&
   1558      !data->set.connect_only &&
   1559      (data->req.bytecount +
   1560       data->req.headerbytecount -
   1561       data->req.deductheadercount) <= 0) {
   1562     /* If this connection is not simply closed to be retried, AND nothing was
   1563        read from the HTTP server (that counts), this cannot be right so we
   1564        return an error here */
   1565     failf(data, "Empty reply from server");
   1566     /* Mark it as closed to avoid the "left intact" message */
   1567     streamclose(conn, "Empty reply from server");
   1568     return CURLE_GOT_NOTHING;
   1569   }
   1570 
   1571   return CURLE_OK;
   1572 }
   1573 
   1574 /* Determine if we may use HTTP 1.1 for this request. */
   1575 static bool http_may_use_1_1(const struct Curl_easy *data)
   1576 {
   1577   const struct connectdata *conn = data->conn;
   1578   /* We have seen a previous response for *this* transfer with 1.0,
   1579    * on another connection or the same one. */
   1580   if(data->state.http_neg.rcvd_min == 10)
   1581     return FALSE;
   1582   /* We have seen a previous response on *this* connection with 1.0. */
   1583   if(conn && conn->httpversion_seen == 10)
   1584     return FALSE;
   1585   /* We want 1.0 and have seen no previous response on *this* connection
   1586      with a higher version (maybe no response at all yet). */
   1587   if((data->state.http_neg.only_10) &&
   1588      (!conn || conn->httpversion_seen <= 10))
   1589     return FALSE;
   1590   /* We are not restricted to use 1.0 only. */
   1591   return !data->state.http_neg.only_10;
   1592 }
   1593 
   1594 static unsigned char http_request_version(struct Curl_easy *data)
   1595 {
   1596   unsigned char v = Curl_conn_http_version(data, data->conn);
   1597   if(!v) {
   1598     /* No specific HTTP connection filter installed. */
   1599     v = http_may_use_1_1(data) ? 11 : 10;
   1600   }
   1601   return v;
   1602 }
   1603 
   1604 static const char *get_http_string(int httpversion)
   1605 {
   1606   switch(httpversion) {
   1607     case 30:
   1608       return "3";
   1609     case 20:
   1610       return "2";
   1611     case 11:
   1612       return "1.1";
   1613     default:
   1614       return "1.0";
   1615   }
   1616 }
   1617 
   1618 CURLcode Curl_add_custom_headers(struct Curl_easy *data,
   1619                                  bool is_connect, int httpversion,
   1620                                  struct dynbuf *req)
   1621 {
   1622   struct curl_slist *h[2];
   1623   struct curl_slist *headers;
   1624   int numlists = 1; /* by default */
   1625   int i;
   1626 
   1627 #ifndef CURL_DISABLE_PROXY
   1628   enum Curl_proxy_use proxy;
   1629 
   1630   if(is_connect)
   1631     proxy = HEADER_CONNECT;
   1632   else
   1633     proxy = data->conn->bits.httpproxy && !data->conn->bits.tunnel_proxy ?
   1634       HEADER_PROXY : HEADER_SERVER;
   1635 
   1636   switch(proxy) {
   1637   case HEADER_SERVER:
   1638     h[0] = data->set.headers;
   1639     break;
   1640   case HEADER_PROXY:
   1641     h[0] = data->set.headers;
   1642     if(data->set.sep_headers) {
   1643       h[1] = data->set.proxyheaders;
   1644       numlists++;
   1645     }
   1646     break;
   1647   case HEADER_CONNECT:
   1648     if(data->set.sep_headers)
   1649       h[0] = data->set.proxyheaders;
   1650     else
   1651       h[0] = data->set.headers;
   1652     break;
   1653   }
   1654 #else
   1655   (void)is_connect;
   1656   h[0] = data->set.headers;
   1657 #endif
   1658 
   1659   /* loop through one or two lists */
   1660   for(i = 0; i < numlists; i++) {
   1661     for(headers = h[i]; headers; headers = headers->next) {
   1662       CURLcode result = CURLE_OK;
   1663       bool blankheader = FALSE;
   1664       struct Curl_str name;
   1665       const char *p = headers->data;
   1666       const char *origp = p;
   1667 
   1668       /* explicitly asked to send header without content is done by a header
   1669          that ends with a semicolon, but there must be no colon present in the
   1670          name */
   1671       if(!curlx_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ';') &&
   1672          !curlx_str_single(&p, ';') &&
   1673          !curlx_str_single(&p, '\0') &&
   1674          !memchr(curlx_str(&name), ':', curlx_strlen(&name)))
   1675         blankheader = TRUE;
   1676       else {
   1677         p = origp;
   1678         if(!curlx_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ':') &&
   1679            !curlx_str_single(&p, ':')) {
   1680           struct Curl_str val;
   1681           curlx_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE);
   1682           curlx_str_trimblanks(&val);
   1683           if(!curlx_strlen(&val))
   1684             /* no content, don't send this */
   1685             continue;
   1686         }
   1687         else
   1688           /* no colon */
   1689           continue;
   1690       }
   1691 
   1692       /* only send this if the contents was non-blank or done special */
   1693 
   1694       if(data->state.aptr.host &&
   1695          /* a Host: header was sent already, do not pass on any custom
   1696             Host: header as that will produce *two* in the same
   1697             request! */
   1698          curlx_str_casecompare(&name, "Host"))
   1699         ;
   1700       else if(data->state.httpreq == HTTPREQ_POST_FORM &&
   1701               /* this header (extended by formdata.c) is sent later */
   1702               curlx_str_casecompare(&name, "Content-Type"))
   1703         ;
   1704       else if(data->state.httpreq == HTTPREQ_POST_MIME &&
   1705               /* this header is sent later */
   1706               curlx_str_casecompare(&name, "Content-Type"))
   1707         ;
   1708       else if(data->req.authneg &&
   1709               /* while doing auth neg, do not allow the custom length since
   1710                  we will force length zero then */
   1711               curlx_str_casecompare(&name, "Content-Length"))
   1712         ;
   1713       else if(data->state.aptr.te &&
   1714               /* when asking for Transfer-Encoding, do not pass on a custom
   1715                  Connection: */
   1716               curlx_str_casecompare(&name, "Connection"))
   1717         ;
   1718       else if((httpversion >= 20) &&
   1719               curlx_str_casecompare(&name, "Transfer-Encoding"))
   1720         /* HTTP/2 does not support chunked requests */
   1721         ;
   1722       else if((curlx_str_casecompare(&name, "Authorization") ||
   1723                curlx_str_casecompare(&name, "Cookie")) &&
   1724               /* be careful of sending this potentially sensitive header to
   1725                  other hosts */
   1726               !Curl_auth_allowed_to_host(data))
   1727         ;
   1728       else if(blankheader)
   1729         result = curlx_dyn_addf(req, "%.*s:\r\n", (int)curlx_strlen(&name),
   1730                                 curlx_str(&name));
   1731       else
   1732         result = curlx_dyn_addf(req, "%s\r\n", origp);
   1733 
   1734       if(result)
   1735         return result;
   1736     }
   1737   }
   1738 
   1739   return CURLE_OK;
   1740 }
   1741 
   1742 #ifndef CURL_DISABLE_PARSEDATE
   1743 CURLcode Curl_add_timecondition(struct Curl_easy *data,
   1744                                 struct dynbuf *req)
   1745 {
   1746   const struct tm *tm;
   1747   struct tm keeptime;
   1748   CURLcode result;
   1749   char datestr[80];
   1750   const char *condp;
   1751   size_t len;
   1752 
   1753   if(data->set.timecondition == CURL_TIMECOND_NONE)
   1754     /* no condition was asked for */
   1755     return CURLE_OK;
   1756 
   1757   result = Curl_gmtime(data->set.timevalue, &keeptime);
   1758   if(result) {
   1759     failf(data, "Invalid TIMEVALUE");
   1760     return result;
   1761   }
   1762   tm = &keeptime;
   1763 
   1764   switch(data->set.timecondition) {
   1765   default:
   1766     DEBUGF(infof(data, "invalid time condition"));
   1767     return CURLE_BAD_FUNCTION_ARGUMENT;
   1768 
   1769   case CURL_TIMECOND_IFMODSINCE:
   1770     condp = "If-Modified-Since";
   1771     len = 17;
   1772     break;
   1773   case CURL_TIMECOND_IFUNMODSINCE:
   1774     condp = "If-Unmodified-Since";
   1775     len = 19;
   1776     break;
   1777   case CURL_TIMECOND_LASTMOD:
   1778     condp = "Last-Modified";
   1779     len = 13;
   1780     break;
   1781   }
   1782 
   1783   if(Curl_checkheaders(data, condp, len)) {
   1784     /* A custom header was specified; it will be sent instead. */
   1785     return CURLE_OK;
   1786   }
   1787 
   1788   /* The If-Modified-Since header family should have their times set in
   1789    * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
   1790    * represented in Greenwich Mean Time (GMT), without exception. For the
   1791    * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
   1792    * Time)." (see page 20 of RFC2616).
   1793    */
   1794 
   1795   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
   1796   msnprintf(datestr, sizeof(datestr),
   1797             "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
   1798             condp,
   1799             Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
   1800             tm->tm_mday,
   1801             Curl_month[tm->tm_mon],
   1802             tm->tm_year + 1900,
   1803             tm->tm_hour,
   1804             tm->tm_min,
   1805             tm->tm_sec);
   1806 
   1807   result = curlx_dyn_add(req, datestr);
   1808   return result;
   1809 }
   1810 #else
   1811 /* disabled */
   1812 CURLcode Curl_add_timecondition(struct Curl_easy *data,
   1813                                 struct dynbuf *req)
   1814 {
   1815   (void)data;
   1816   (void)req;
   1817   return CURLE_OK;
   1818 }
   1819 #endif
   1820 
   1821 void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
   1822                       const char **method, Curl_HttpReq *reqp)
   1823 {
   1824   Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq;
   1825   const char *request;
   1826   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
   1827      data->state.upload)
   1828     httpreq = HTTPREQ_PUT;
   1829 
   1830   /* Now set the 'request' pointer to the proper request string */
   1831   if(data->set.str[STRING_CUSTOMREQUEST] &&
   1832      !data->state.http_ignorecustom) {
   1833     request = data->set.str[STRING_CUSTOMREQUEST];
   1834   }
   1835   else {
   1836     if(data->req.no_body)
   1837       request = "HEAD";
   1838     else {
   1839       DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
   1840       switch(httpreq) {
   1841       case HTTPREQ_POST:
   1842       case HTTPREQ_POST_FORM:
   1843       case HTTPREQ_POST_MIME:
   1844         request = "POST";
   1845         break;
   1846       case HTTPREQ_PUT:
   1847         request = "PUT";
   1848         break;
   1849       default: /* this should never happen */
   1850       case HTTPREQ_GET:
   1851         request = "GET";
   1852         break;
   1853       case HTTPREQ_HEAD:
   1854         request = "HEAD";
   1855         break;
   1856       }
   1857     }
   1858   }
   1859   *method = request;
   1860   *reqp = httpreq;
   1861 }
   1862 
   1863 static CURLcode http_useragent(struct Curl_easy *data)
   1864 {
   1865   /* The User-Agent string might have been allocated in url.c already, because
   1866      it might have been used in the proxy connect, but if we have got a header
   1867      with the user-agent string specified, we erase the previously made string
   1868      here. */
   1869   if(Curl_checkheaders(data, STRCONST("User-Agent"))) {
   1870     free(data->state.aptr.uagent);
   1871     data->state.aptr.uagent = NULL;
   1872   }
   1873   return CURLE_OK;
   1874 }
   1875 
   1876 
   1877 static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn)
   1878 {
   1879   const char *ptr;
   1880   struct dynamically_allocated_data *aptr = &data->state.aptr;
   1881   if(!data->state.this_is_a_follow) {
   1882     /* Free to avoid leaking memory on multiple requests */
   1883     free(data->state.first_host);
   1884 
   1885     data->state.first_host = strdup(conn->host.name);
   1886     if(!data->state.first_host)
   1887       return CURLE_OUT_OF_MEMORY;
   1888 
   1889     data->state.first_remote_port = conn->remote_port;
   1890     data->state.first_remote_protocol = conn->handler->protocol;
   1891   }
   1892   Curl_safefree(aptr->host);
   1893 
   1894   ptr = Curl_checkheaders(data, STRCONST("Host"));
   1895   if(ptr && (!data->state.this_is_a_follow ||
   1896              curl_strequal(data->state.first_host, conn->host.name))) {
   1897 #if !defined(CURL_DISABLE_COOKIES)
   1898     /* If we have a given custom Host: header, we extract the hostname in
   1899        order to possibly use it for cookie reasons later on. We only allow the
   1900        custom Host: header if this is NOT a redirect, as setting Host: in the
   1901        redirected request is being out on thin ice. Except if the hostname
   1902        is the same as the first one! */
   1903     char *cookiehost = Curl_copy_header_value(ptr);
   1904     if(!cookiehost)
   1905       return CURLE_OUT_OF_MEMORY;
   1906     if(!*cookiehost)
   1907       /* ignore empty data */
   1908       free(cookiehost);
   1909     else {
   1910       /* If the host begins with '[', we start searching for the port after
   1911          the bracket has been closed */
   1912       if(*cookiehost == '[') {
   1913         char *closingbracket;
   1914         /* since the 'cookiehost' is an allocated memory area that will be
   1915            freed later we cannot simply increment the pointer */
   1916         memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
   1917         closingbracket = strchr(cookiehost, ']');
   1918         if(closingbracket)
   1919           *closingbracket = 0;
   1920       }
   1921       else {
   1922         int startsearch = 0;
   1923         char *colon = strchr(cookiehost + startsearch, ':');
   1924         if(colon)
   1925           *colon = 0; /* The host must not include an embedded port number */
   1926       }
   1927       free(aptr->cookiehost);
   1928       aptr->cookiehost = cookiehost;
   1929     }
   1930 #endif
   1931 
   1932     if(!curl_strequal("Host:", ptr)) {
   1933       aptr->host = aprintf("Host:%s\r\n", &ptr[5]);
   1934       if(!aptr->host)
   1935         return CURLE_OUT_OF_MEMORY;
   1936     }
   1937   }
   1938   else {
   1939     /* When building Host: headers, we must put the hostname within
   1940        [brackets] if the hostname is a plain IPv6-address. RFC2732-style. */
   1941     const char *host = conn->host.name;
   1942 
   1943     if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) &&
   1944         (conn->remote_port == PORT_HTTPS)) ||
   1945        ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) &&
   1946         (conn->remote_port == PORT_HTTP)) )
   1947       /* if(HTTPS on port 443) OR (HTTP on port 80) then do not include
   1948          the port number in the host string */
   1949       aptr->host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip ? "[" : "",
   1950                            host, conn->bits.ipv6_ip ? "]" : "");
   1951     else
   1952       aptr->host = aprintf("Host: %s%s%s:%d\r\n",
   1953                            conn->bits.ipv6_ip ? "[" : "",
   1954                            host, conn->bits.ipv6_ip ? "]" : "",
   1955                            conn->remote_port);
   1956 
   1957     if(!aptr->host)
   1958       /* without Host: we cannot make a nice request */
   1959       return CURLE_OUT_OF_MEMORY;
   1960   }
   1961   return CURLE_OK;
   1962 }
   1963 
   1964 /*
   1965  * Append the request-target to the HTTP request
   1966  */
   1967 static CURLcode http_target(struct Curl_easy *data,
   1968                             struct connectdata *conn,
   1969                             struct dynbuf *r)
   1970 {
   1971   CURLcode result = CURLE_OK;
   1972   const char *path = data->state.up.path;
   1973   const char *query = data->state.up.query;
   1974 
   1975   if(data->set.str[STRING_TARGET]) {
   1976     path = data->set.str[STRING_TARGET];
   1977     query = NULL;
   1978   }
   1979 
   1980 #ifndef CURL_DISABLE_PROXY
   1981   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
   1982     /* Using a proxy but does not tunnel through it */
   1983 
   1984     /* The path sent to the proxy is in fact the entire URL. But if the remote
   1985        host is a IDN-name, we must make sure that the request we produce only
   1986        uses the encoded hostname! */
   1987 
   1988     /* and no fragment part */
   1989     CURLUcode uc;
   1990     char *url;
   1991     CURLU *h = curl_url_dup(data->state.uh);
   1992     if(!h)
   1993       return CURLE_OUT_OF_MEMORY;
   1994 
   1995     if(conn->host.dispname != conn->host.name) {
   1996       uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
   1997       if(uc) {
   1998         curl_url_cleanup(h);
   1999         return CURLE_OUT_OF_MEMORY;
   2000       }
   2001     }
   2002     uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
   2003     if(uc) {
   2004       curl_url_cleanup(h);
   2005       return CURLE_OUT_OF_MEMORY;
   2006     }
   2007 
   2008     if(curl_strequal("http", data->state.up.scheme)) {
   2009       /* when getting HTTP, we do not want the userinfo the URL */
   2010       uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
   2011       if(uc) {
   2012         curl_url_cleanup(h);
   2013         return CURLE_OUT_OF_MEMORY;
   2014       }
   2015       uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
   2016       if(uc) {
   2017         curl_url_cleanup(h);
   2018         return CURLE_OUT_OF_MEMORY;
   2019       }
   2020     }
   2021     /* Extract the URL to use in the request. */
   2022     uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
   2023     if(uc) {
   2024       curl_url_cleanup(h);
   2025       return CURLE_OUT_OF_MEMORY;
   2026     }
   2027 
   2028     curl_url_cleanup(h);
   2029 
   2030     /* target or URL */
   2031     result = curlx_dyn_add(r, data->set.str[STRING_TARGET] ?
   2032       data->set.str[STRING_TARGET] : url);
   2033     free(url);
   2034     if(result)
   2035       return result;
   2036 
   2037     if(curl_strequal("ftp", data->state.up.scheme)) {
   2038       if(data->set.proxy_transfer_mode) {
   2039         /* when doing ftp, append ;type=<a|i> if not present */
   2040         char *type = strstr(path, ";type=");
   2041         if(type && type[6] && type[7] == 0) {
   2042           switch(Curl_raw_toupper(type[6])) {
   2043           case 'A':
   2044           case 'D':
   2045           case 'I':
   2046             break;
   2047           default:
   2048             type = NULL;
   2049           }
   2050         }
   2051         if(!type) {
   2052           result = curlx_dyn_addf(r, ";type=%c",
   2053                                   data->state.prefer_ascii ? 'a' : 'i');
   2054           if(result)
   2055             return result;
   2056         }
   2057       }
   2058     }
   2059   }
   2060 
   2061   else
   2062 #else
   2063     (void)conn; /* not used in disabled-proxy builds */
   2064 #endif
   2065   {
   2066     result = curlx_dyn_add(r, path);
   2067     if(result)
   2068       return result;
   2069     if(query)
   2070       result = curlx_dyn_addf(r, "?%s", query);
   2071   }
   2072 
   2073   return result;
   2074 }
   2075 
   2076 #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   2077 static CURLcode set_post_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
   2078 {
   2079   CURLcode result;
   2080 
   2081   switch(httpreq) {
   2082 #ifndef CURL_DISABLE_MIME
   2083   case HTTPREQ_POST_MIME:
   2084     data->state.mimepost = &data->set.mimepost;
   2085     break;
   2086 #endif
   2087 #ifndef CURL_DISABLE_FORM_API
   2088   case HTTPREQ_POST_FORM:
   2089     /* Convert the form structure into a mime structure, then keep
   2090        the conversion */
   2091     if(!data->state.formp) {
   2092       data->state.formp = calloc(1, sizeof(curl_mimepart));
   2093       if(!data->state.formp)
   2094         return CURLE_OUT_OF_MEMORY;
   2095       Curl_mime_cleanpart(data->state.formp);
   2096       result = Curl_getformdata(data, data->state.formp, data->set.httppost,
   2097                                 data->state.fread_func);
   2098       if(result) {
   2099         Curl_safefree(data->state.formp);
   2100         return result;
   2101       }
   2102       data->state.mimepost = data->state.formp;
   2103     }
   2104     break;
   2105 #endif
   2106   default:
   2107     data->state.mimepost = NULL;
   2108     break;
   2109   }
   2110 
   2111   switch(httpreq) {
   2112   case HTTPREQ_POST_FORM:
   2113   case HTTPREQ_POST_MIME:
   2114     /* This is form posting using mime data. */
   2115 #ifndef CURL_DISABLE_MIME
   2116     if(data->state.mimepost) {
   2117       const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
   2118 
   2119       /* Read and seek body only. */
   2120       data->state.mimepost->flags |= MIME_BODY_ONLY;
   2121 
   2122       /* Prepare the mime structure headers & set content type. */
   2123 
   2124       if(cthdr)
   2125         for(cthdr += 13; *cthdr == ' '; cthdr++)
   2126           ;
   2127       else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
   2128         cthdr = "multipart/form-data";
   2129 
   2130       curl_mime_headers(data->state.mimepost, data->set.headers, 0);
   2131       result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
   2132                                          NULL, MIMESTRATEGY_FORM);
   2133       if(result)
   2134         return result;
   2135       curl_mime_headers(data->state.mimepost, NULL, 0);
   2136       result = Curl_creader_set_mime(data, data->state.mimepost);
   2137       if(result)
   2138         return result;
   2139     }
   2140     else
   2141 #endif
   2142     {
   2143       result = Curl_creader_set_null(data);
   2144     }
   2145     data->state.infilesize = Curl_creader_total_length(data);
   2146     return result;
   2147 
   2148   default:
   2149     return Curl_creader_set_null(data);
   2150   }
   2151   /* never reached */
   2152 }
   2153 #endif
   2154 
   2155 static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
   2156 {
   2157   CURLcode result = CURLE_OK;
   2158   curl_off_t postsize = data->state.infilesize;
   2159 
   2160   DEBUGASSERT(data->conn);
   2161 
   2162   if(data->req.authneg) {
   2163     return Curl_creader_set_null(data);
   2164   }
   2165 
   2166   switch(httpreq) {
   2167   case HTTPREQ_PUT: /* Let's PUT the data to the server! */
   2168     return postsize ? Curl_creader_set_fread(data, postsize) :
   2169       Curl_creader_set_null(data);
   2170 
   2171 #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   2172   case HTTPREQ_POST_FORM:
   2173   case HTTPREQ_POST_MIME:
   2174     return set_post_reader(data, httpreq);
   2175 #endif
   2176 
   2177   case HTTPREQ_POST:
   2178     /* this is the simple POST, using x-www-form-urlencoded style */
   2179     /* the size of the post body */
   2180     if(!postsize) {
   2181       result = Curl_creader_set_null(data);
   2182     }
   2183     else if(data->set.postfields) {
   2184       if(postsize > 0)
   2185         result = Curl_creader_set_buf(data, data->set.postfields,
   2186                                       (size_t)postsize);
   2187       else
   2188         result = Curl_creader_set_null(data);
   2189     }
   2190     else {
   2191       /* we read the bytes from the callback. In case "chunked" encoding
   2192        * is forced by the application, we disregard `postsize`. This is
   2193        * a backward compatibility decision to earlier versions where
   2194        * chunking disregarded this. See issue #13229. */
   2195       bool chunked = FALSE;
   2196       char *ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
   2197       if(ptr) {
   2198         /* Some kind of TE is requested, check if 'chunked' is chosen */
   2199         chunked = Curl_compareheader(ptr, STRCONST("Transfer-Encoding:"),
   2200                                      STRCONST("chunked"));
   2201       }
   2202       result = Curl_creader_set_fread(data, chunked ? -1 : postsize);
   2203     }
   2204     return result;
   2205 
   2206   default:
   2207     /* HTTP GET/HEAD download, has no body, needs no Content-Length */
   2208     data->state.infilesize = 0;
   2209     return Curl_creader_set_null(data);
   2210   }
   2211   /* not reached */
   2212 }
   2213 
   2214 static CURLcode http_resume(struct Curl_easy *data, Curl_HttpReq httpreq)
   2215 {
   2216   if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
   2217      data->state.resume_from) {
   2218     /**********************************************************************
   2219      * Resuming upload in HTTP means that we PUT or POST and that we have
   2220      * got a resume_from value set. The resume value has already created
   2221      * a Range: header that will be passed along. We need to "fast forward"
   2222      * the file the given number of bytes and decrease the assume upload
   2223      * file size before we continue this venture in the dark lands of HTTP.
   2224      * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
   2225      *********************************************************************/
   2226 
   2227     if(data->state.resume_from < 0) {
   2228       /*
   2229        * This is meant to get the size of the present remote-file by itself.
   2230        * We do not support this now. Bail out!
   2231        */
   2232       data->state.resume_from = 0;
   2233     }
   2234 
   2235     if(data->state.resume_from && !data->req.authneg) {
   2236       /* only act on the first request */
   2237       CURLcode result;
   2238       result = Curl_creader_resume_from(data, data->state.resume_from);
   2239       if(result) {
   2240         failf(data, "Unable to resume from offset %" FMT_OFF_T,
   2241               data->state.resume_from);
   2242         return result;
   2243       }
   2244     }
   2245   }
   2246   return CURLE_OK;
   2247 }
   2248 
   2249 static CURLcode http_req_set_reader(struct Curl_easy *data,
   2250                                     Curl_HttpReq httpreq, int httpversion,
   2251                                     const char **tep)
   2252 {
   2253   CURLcode result = CURLE_OK;
   2254   const char *ptr;
   2255 
   2256   result = set_reader(data, httpreq);
   2257   if(result)
   2258     return result;
   2259 
   2260   result = http_resume(data, httpreq);
   2261   if(result)
   2262     return result;
   2263 
   2264   ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
   2265   if(ptr) {
   2266     /* Some kind of TE is requested, check if 'chunked' is chosen */
   2267     data->req.upload_chunky =
   2268       Curl_compareheader(ptr,
   2269                          STRCONST("Transfer-Encoding:"), STRCONST("chunked"));
   2270     if(data->req.upload_chunky && (httpversion >= 20)) {
   2271       infof(data, "suppressing chunked transfer encoding on connection "
   2272             "using HTTP version 2 or higher");
   2273       data->req.upload_chunky = FALSE;
   2274     }
   2275   }
   2276   else {
   2277     curl_off_t req_clen = Curl_creader_total_length(data);
   2278 
   2279     if(req_clen < 0) {
   2280       /* indeterminate request content length */
   2281       if(httpversion > 10) {
   2282         /* On HTTP/1.1, enable chunked, on HTTP/2 and later we do not
   2283          * need it */
   2284         data->req.upload_chunky = (httpversion < 20);
   2285       }
   2286       else {
   2287         failf(data, "Chunky upload is not supported by HTTP 1.0");
   2288         return CURLE_UPLOAD_FAILED;
   2289       }
   2290     }
   2291     else {
   2292       /* else, no chunky upload */
   2293       data->req.upload_chunky = FALSE;
   2294     }
   2295 
   2296     if(data->req.upload_chunky)
   2297       *tep = "Transfer-Encoding: chunked\r\n";
   2298   }
   2299   return result;
   2300 }
   2301 
   2302 static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
   2303                           int httpversion, bool *announced_exp100)
   2304 {
   2305   CURLcode result;
   2306   char *ptr;
   2307 
   2308   *announced_exp100 = FALSE;
   2309   /* Avoid Expect: 100-continue if Upgrade: is used */
   2310   if(data->req.upgr101 != UPGR101_INIT)
   2311     return CURLE_OK;
   2312 
   2313   /* For really small puts we do not use Expect: headers at all, and for
   2314      the somewhat bigger ones we allow the app to disable it. Just make
   2315      sure that the expect100header is always set to the preferred value
   2316      here. */
   2317   ptr = Curl_checkheaders(data, STRCONST("Expect"));
   2318   if(ptr) {
   2319     *announced_exp100 =
   2320       Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
   2321   }
   2322   else if(!data->state.disableexpect && (httpversion == 11)) {
   2323     /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
   2324        Expect: 100-continue to the headers which actually speeds up post
   2325        operations (as there is one packet coming back from the web server) */
   2326     curl_off_t client_len = Curl_creader_client_length(data);
   2327     if(client_len > EXPECT_100_THRESHOLD || client_len < 0) {
   2328       result = curlx_dyn_addn(r, STRCONST("Expect: 100-continue\r\n"));
   2329       if(result)
   2330         return result;
   2331       *announced_exp100 = TRUE;
   2332     }
   2333   }
   2334   return CURLE_OK;
   2335 }
   2336 
   2337 static CURLcode http_req_complete(struct Curl_easy *data,
   2338                                   struct dynbuf *r, int httpversion,
   2339                                   Curl_HttpReq httpreq)
   2340 {
   2341   CURLcode result = CURLE_OK;
   2342   curl_off_t req_clen;
   2343   bool announced_exp100 = FALSE;
   2344 
   2345   DEBUGASSERT(data->conn);
   2346   if(data->req.upload_chunky) {
   2347     result = Curl_httpchunk_add_reader(data);
   2348     if(result)
   2349       return result;
   2350   }
   2351 
   2352   /* Get the request body length that has been set up */
   2353   req_clen = Curl_creader_total_length(data);
   2354   switch(httpreq) {
   2355   case HTTPREQ_PUT:
   2356   case HTTPREQ_POST:
   2357 #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   2358   case HTTPREQ_POST_FORM:
   2359   case HTTPREQ_POST_MIME:
   2360 #endif
   2361     /* We only set Content-Length and allow a custom Content-Length if
   2362        we do not upload data chunked, as RFC2616 forbids us to set both
   2363        kinds of headers (Transfer-Encoding: chunked and Content-Length).
   2364        We do not override a custom "Content-Length" header, but during
   2365        authentication negotiation that header is suppressed.
   2366      */
   2367     if(req_clen >= 0 && !data->req.upload_chunky &&
   2368        (data->req.authneg ||
   2369         !Curl_checkheaders(data, STRCONST("Content-Length")))) {
   2370       /* we allow replacing this header if not during auth negotiation,
   2371          although it is not very wise to actually set your own */
   2372       result = curlx_dyn_addf(r, "Content-Length: %" FMT_OFF_T "\r\n",
   2373                               req_clen);
   2374     }
   2375     if(result)
   2376       goto out;
   2377 
   2378 #ifndef CURL_DISABLE_MIME
   2379     /* Output mime-generated headers. */
   2380     if(data->state.mimepost &&
   2381        ((httpreq == HTTPREQ_POST_FORM) || (httpreq == HTTPREQ_POST_MIME))) {
   2382       struct curl_slist *hdr;
   2383 
   2384       for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
   2385         result = curlx_dyn_addf(r, "%s\r\n", hdr->data);
   2386         if(result)
   2387           goto out;
   2388       }
   2389     }
   2390 #endif
   2391     if(httpreq == HTTPREQ_POST) {
   2392       if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
   2393         result = curlx_dyn_addn(r, STRCONST("Content-Type: application/"
   2394                                             "x-www-form-urlencoded\r\n"));
   2395         if(result)
   2396           goto out;
   2397       }
   2398     }
   2399     result = addexpect(data, r, httpversion, &announced_exp100);
   2400     if(result)
   2401       goto out;
   2402     break;
   2403   default:
   2404     break;
   2405   }
   2406 
   2407   /* end of headers */
   2408   result = curlx_dyn_addn(r, STRCONST("\r\n"));
   2409   if(!result) {
   2410     Curl_pgrsSetUploadSize(data, req_clen);
   2411     if(announced_exp100)
   2412       result = http_exp100_add_reader(data);
   2413   }
   2414 
   2415 out:
   2416   if(!result) {
   2417     /* setup variables for the upcoming transfer */
   2418     Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
   2419   }
   2420   return result;
   2421 }
   2422 
   2423 #if !defined(CURL_DISABLE_COOKIES)
   2424 
   2425 static CURLcode http_cookies(struct Curl_easy *data,
   2426                              struct connectdata *conn,
   2427                              struct dynbuf *r)
   2428 {
   2429   CURLcode result = CURLE_OK;
   2430   char *addcookies = NULL;
   2431   bool linecap = FALSE;
   2432   if(data->set.str[STRING_COOKIE] &&
   2433      !Curl_checkheaders(data, STRCONST("Cookie")))
   2434     addcookies = data->set.str[STRING_COOKIE];
   2435 
   2436   if(data->cookies || addcookies) {
   2437     struct Curl_llist list;
   2438     int count = 0;
   2439     int rc = 1;
   2440 
   2441     if(data->cookies && data->state.cookie_engine) {
   2442       const char *host = data->state.aptr.cookiehost ?
   2443         data->state.aptr.cookiehost : conn->host.name;
   2444       const bool secure_context =
   2445         conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
   2446         curl_strequal("localhost", host) ||
   2447         !strcmp(host, "127.0.0.1") ||
   2448         !strcmp(host, "::1");
   2449       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   2450       rc = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
   2451                                secure_context, &list);
   2452       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   2453     }
   2454     if(!rc) {
   2455       struct Curl_llist_node *n;
   2456       size_t clen = 8; /* hold the size of the generated Cookie: header */
   2457 
   2458       /* loop through all cookies that matched */
   2459       for(n = Curl_llist_head(&list); n; n = Curl_node_next(n)) {
   2460         struct Cookie *co = Curl_node_elem(n);
   2461         if(co->value) {
   2462           size_t add;
   2463           if(!count) {
   2464             result = curlx_dyn_addn(r, STRCONST("Cookie: "));
   2465             if(result)
   2466               break;
   2467           }
   2468           add = strlen(co->name) + strlen(co->value) + 1;
   2469           if(clen + add >= MAX_COOKIE_HEADER_LEN) {
   2470             infof(data, "Restricted outgoing cookies due to header size, "
   2471                   "'%s' not sent", co->name);
   2472             linecap = TRUE;
   2473             break;
   2474           }
   2475           result = curlx_dyn_addf(r, "%s%s=%s", count ? "; " : "",
   2476                                   co->name, co->value);
   2477           if(result)
   2478             break;
   2479           clen += add + (count ? 2 : 0);
   2480           count++;
   2481         }
   2482       }
   2483       Curl_llist_destroy(&list, NULL);
   2484     }
   2485     if(addcookies && !result && !linecap) {
   2486       if(!count)
   2487         result = curlx_dyn_addn(r, STRCONST("Cookie: "));
   2488       if(!result) {
   2489         result = curlx_dyn_addf(r, "%s%s", count ? "; " : "", addcookies);
   2490         count++;
   2491       }
   2492     }
   2493     if(count && !result)
   2494       result = curlx_dyn_addn(r, STRCONST("\r\n"));
   2495 
   2496     if(result)
   2497       return result;
   2498   }
   2499   return result;
   2500 }
   2501 #else
   2502 #define http_cookies(a,b,c) CURLE_OK
   2503 #endif
   2504 
   2505 static CURLcode http_range(struct Curl_easy *data,
   2506                            Curl_HttpReq httpreq)
   2507 {
   2508   if(data->state.use_range) {
   2509     /*
   2510      * A range is selected. We use different headers whether we are downloading
   2511      * or uploading and we always let customized headers override our internal
   2512      * ones if any such are specified.
   2513      */
   2514     if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
   2515        !Curl_checkheaders(data, STRCONST("Range"))) {
   2516       /* if a line like this was already allocated, free the previous one */
   2517       free(data->state.aptr.rangeline);
   2518       data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
   2519                                            data->state.range);
   2520     }
   2521     else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
   2522             !Curl_checkheaders(data, STRCONST("Content-Range"))) {
   2523       curl_off_t req_clen = Curl_creader_total_length(data);
   2524       /* if a line like this was already allocated, free the previous one */
   2525       free(data->state.aptr.rangeline);
   2526 
   2527       if(data->set.set_resume_from < 0) {
   2528         /* Upload resume was asked for, but we do not know the size of the
   2529            remote part so we tell the server (and act accordingly) that we
   2530            upload the whole file (again) */
   2531         data->state.aptr.rangeline =
   2532           aprintf("Content-Range: bytes 0-%" FMT_OFF_T "/%" FMT_OFF_T "\r\n",
   2533                   req_clen - 1, req_clen);
   2534 
   2535       }
   2536       else if(data->state.resume_from) {
   2537         /* This is because "resume" was selected */
   2538         /* Not sure if we want to send this header during authentication
   2539          * negotiation, but test1084 checks for it. In which case we have a
   2540          * "null" client reader installed that gives an unexpected length. */
   2541         curl_off_t total_len = data->req.authneg ?
   2542                                data->state.infilesize :
   2543                                (data->state.resume_from + req_clen);
   2544         data->state.aptr.rangeline =
   2545           aprintf("Content-Range: bytes %s%" FMT_OFF_T "/%" FMT_OFF_T "\r\n",
   2546                   data->state.range, total_len-1, total_len);
   2547       }
   2548       else {
   2549         /* Range was selected and then we just pass the incoming range and
   2550            append total size */
   2551         data->state.aptr.rangeline =
   2552           aprintf("Content-Range: bytes %s/%" FMT_OFF_T "\r\n",
   2553                   data->state.range, req_clen);
   2554       }
   2555       if(!data->state.aptr.rangeline)
   2556         return CURLE_OUT_OF_MEMORY;
   2557     }
   2558   }
   2559   return CURLE_OK;
   2560 }
   2561 
   2562 static CURLcode http_firstwrite(struct Curl_easy *data)
   2563 {
   2564   struct connectdata *conn = data->conn;
   2565   struct SingleRequest *k = &data->req;
   2566 
   2567   if(data->req.newurl) {
   2568     if(conn->bits.close) {
   2569       /* Abort after the headers if "follow Location" is set
   2570          and we are set to close anyway. */
   2571       k->keepon &= ~KEEP_RECV;
   2572       k->done = TRUE;
   2573       return CURLE_OK;
   2574     }
   2575     /* We have a new URL to load, but since we want to be able to reuse this
   2576        connection properly, we read the full response in "ignore more" */
   2577     k->ignorebody = TRUE;
   2578     infof(data, "Ignoring the response-body");
   2579   }
   2580   if(data->state.resume_from && !k->content_range &&
   2581      (data->state.httpreq == HTTPREQ_GET) &&
   2582      !k->ignorebody) {
   2583 
   2584     if(k->size == data->state.resume_from) {
   2585       /* The resume point is at the end of file, consider this fine even if it
   2586          does not allow resume from here. */
   2587       infof(data, "The entire document is already downloaded");
   2588       streamclose(conn, "already downloaded");
   2589       /* Abort download */
   2590       k->keepon &= ~KEEP_RECV;
   2591       k->done = TRUE;
   2592       return CURLE_OK;
   2593     }
   2594 
   2595     /* we wanted to resume a download, although the server does not seem to
   2596      * support this and we did this with a GET (if it was not a GET we did a
   2597      * POST or PUT resume) */
   2598     failf(data, "HTTP server does not seem to support "
   2599           "byte ranges. Cannot resume.");
   2600     return CURLE_RANGE_ERROR;
   2601   }
   2602 
   2603   if(data->set.timecondition && !data->state.range) {
   2604     /* A time condition has been set AND no ranges have been requested. This
   2605        seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
   2606        action for an HTTP/1.1 client */
   2607 
   2608     if(!Curl_meets_timecondition(data, k->timeofdoc)) {
   2609       k->done = TRUE;
   2610       /* We are simulating an HTTP 304 from server so we return
   2611          what should have been returned from the server */
   2612       data->info.httpcode = 304;
   2613       infof(data, "Simulate an HTTP 304 response");
   2614       /* we abort the transfer before it is completed == we ruin the
   2615          reuse ability. Close the connection */
   2616       streamclose(conn, "Simulated 304 handling");
   2617       return CURLE_OK;
   2618     }
   2619   } /* we have a time condition */
   2620 
   2621   return CURLE_OK;
   2622 }
   2623 
   2624 #ifdef HAVE_LIBZ
   2625 static CURLcode http_transferencode(struct Curl_easy *data)
   2626 {
   2627   if(!Curl_checkheaders(data, STRCONST("TE")) &&
   2628      data->set.http_transfer_encoding) {
   2629     /* When we are to insert a TE: header in the request, we must also insert
   2630        TE in a Connection: header, so we need to merge the custom provided
   2631        Connection: header and prevent the original to get sent. Note that if
   2632        the user has inserted his/her own TE: header we do not do this magic
   2633        but then assume that the user will handle it all! */
   2634     char *cptr = Curl_checkheaders(data, STRCONST("Connection"));
   2635 #define TE_HEADER "TE: gzip\r\n"
   2636 
   2637     Curl_safefree(data->state.aptr.te);
   2638 
   2639     if(cptr) {
   2640       cptr = Curl_copy_header_value(cptr);
   2641       if(!cptr)
   2642         return CURLE_OUT_OF_MEMORY;
   2643     }
   2644 
   2645     /* Create the (updated) Connection: header */
   2646     data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
   2647                                 cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
   2648 
   2649     free(cptr);
   2650     if(!data->state.aptr.te)
   2651       return CURLE_OUT_OF_MEMORY;
   2652   }
   2653   return CURLE_OK;
   2654 }
   2655 #endif
   2656 
   2657 /*
   2658  * Curl_http() gets called from the generic multi_do() function when an HTTP
   2659  * request is to be performed. This creates and sends a properly constructed
   2660  * HTTP request.
   2661  */
   2662 CURLcode Curl_http(struct Curl_easy *data, bool *done)
   2663 {
   2664   struct connectdata *conn = data->conn;
   2665   CURLcode result = CURLE_OK;
   2666   Curl_HttpReq httpreq;
   2667   const char *te = ""; /* transfer-encoding */
   2668   const char *request;
   2669   const char *httpstring;
   2670   struct dynbuf req;
   2671   char *altused = NULL;
   2672   const char *p_accept;      /* Accept: string */
   2673   unsigned char httpversion;
   2674 
   2675   /* Always consider the DO phase done after this function call, even if there
   2676      may be parts of the request that are not yet sent, since we can deal with
   2677      the rest of the request in the PERFORM phase. */
   2678   *done = TRUE;
   2679 
   2680   switch(conn->alpn) {
   2681   case CURL_HTTP_VERSION_3:
   2682     DEBUGASSERT(Curl_conn_http_version(data, conn) == 30);
   2683     break;
   2684   case CURL_HTTP_VERSION_2:
   2685 #ifndef CURL_DISABLE_PROXY
   2686     if((Curl_conn_http_version(data, conn) != 20) &&
   2687        conn->bits.proxy && !conn->bits.tunnel_proxy
   2688       ) {
   2689       result = Curl_http2_switch(data);
   2690       if(result)
   2691         goto fail;
   2692     }
   2693     else
   2694 #endif
   2695       DEBUGASSERT(Curl_conn_http_version(data, conn) == 20);
   2696     break;
   2697   case CURL_HTTP_VERSION_1_1:
   2698     /* continue with HTTP/1.x when explicitly requested */
   2699     break;
   2700   default:
   2701     /* Check if user wants to use HTTP/2 with clear TCP */
   2702     if(Curl_http2_may_switch(data)) {
   2703       DEBUGF(infof(data, "HTTP/2 over clean TCP"));
   2704       result = Curl_http2_switch(data);
   2705       if(result)
   2706         goto fail;
   2707     }
   2708     break;
   2709   }
   2710 
   2711   /* Add collecting of headers written to client. For a new connection,
   2712    * we might have done that already, but reuse
   2713    * or multiplex needs it here as well. */
   2714   result = Curl_headers_init(data);
   2715   if(result)
   2716     goto fail;
   2717 
   2718   result = http_host(data, conn);
   2719   if(result)
   2720     goto fail;
   2721 
   2722   result = http_useragent(data);
   2723   if(result)
   2724     goto fail;
   2725 
   2726   Curl_http_method(data, conn, &request, &httpreq);
   2727 
   2728   /* setup the authentication headers */
   2729   {
   2730     char *pq = NULL;
   2731     if(data->state.up.query) {
   2732       pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
   2733       if(!pq)
   2734         return CURLE_OUT_OF_MEMORY;
   2735     }
   2736     result = Curl_http_output_auth(data, conn, request, httpreq,
   2737                                    (pq ? pq : data->state.up.path), FALSE);
   2738     free(pq);
   2739     if(result)
   2740       goto fail;
   2741   }
   2742 
   2743   Curl_safefree(data->state.aptr.ref);
   2744   if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
   2745     data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
   2746     if(!data->state.aptr.ref)
   2747       return CURLE_OUT_OF_MEMORY;
   2748   }
   2749 
   2750   if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
   2751      data->set.str[STRING_ENCODING]) {
   2752     free(data->state.aptr.accept_encoding);
   2753     data->state.aptr.accept_encoding =
   2754       aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
   2755     if(!data->state.aptr.accept_encoding)
   2756       return CURLE_OUT_OF_MEMORY;
   2757   }
   2758   else
   2759     Curl_safefree(data->state.aptr.accept_encoding);
   2760 
   2761 #ifdef HAVE_LIBZ
   2762   /* we only consider transfer-encoding magic if libz support is built-in */
   2763   result = http_transferencode(data);
   2764   if(result)
   2765     goto fail;
   2766 #endif
   2767 
   2768   httpversion = http_request_version(data);
   2769   httpstring = get_http_string(httpversion);
   2770 
   2771   result = http_req_set_reader(data, httpreq, httpversion, &te);
   2772   if(result)
   2773     goto fail;
   2774 
   2775   p_accept = Curl_checkheaders(data,
   2776                                STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
   2777 
   2778   result = http_range(data, httpreq);
   2779   if(result)
   2780     goto fail;
   2781 
   2782   /* initialize a dynamic send-buffer */
   2783   curlx_dyn_init(&req, DYN_HTTP_REQUEST);
   2784 
   2785   /* make sure the header buffer is reset - if there are leftovers from a
   2786      previous transfer */
   2787   curlx_dyn_reset(&data->state.headerb);
   2788 
   2789   /* add the main request stuff */
   2790   /* GET/HEAD/POST/PUT */
   2791   result = curlx_dyn_addf(&req, "%s ", request);
   2792   if(!result)
   2793     result = http_target(data, conn, &req);
   2794   if(result) {
   2795     curlx_dyn_free(&req);
   2796     goto fail;
   2797   }
   2798 
   2799 #ifndef CURL_DISABLE_ALTSVC
   2800   if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
   2801     altused = aprintf("Alt-Used: %s:%d\r\n",
   2802                       conn->conn_to_host.name, conn->conn_to_port);
   2803     if(!altused) {
   2804       curlx_dyn_free(&req);
   2805       return CURLE_OUT_OF_MEMORY;
   2806     }
   2807   }
   2808 #endif
   2809   result =
   2810     curlx_dyn_addf(&req,
   2811                    " HTTP/%s\r\n" /* HTTP version */
   2812                    "%s" /* host */
   2813                    "%s" /* proxyuserpwd */
   2814                    "%s" /* userpwd */
   2815                    "%s" /* range */
   2816                    "%s" /* user agent */
   2817                    "%s" /* accept */
   2818                    "%s" /* TE: */
   2819                    "%s" /* accept-encoding */
   2820                    "%s" /* referer */
   2821                    "%s" /* Proxy-Connection */
   2822                    "%s" /* transfer-encoding */
   2823                    "%s",/* Alt-Used */
   2824 
   2825                    httpstring,
   2826                    (data->state.aptr.host ? data->state.aptr.host : ""),
   2827 #ifndef CURL_DISABLE_PROXY
   2828                    data->state.aptr.proxyuserpwd ?
   2829                    data->state.aptr.proxyuserpwd : "",
   2830 #else
   2831                    "",
   2832 #endif
   2833                    data->state.aptr.userpwd ? data->state.aptr.userpwd : "",
   2834                    (data->state.use_range && data->state.aptr.rangeline) ?
   2835                    data->state.aptr.rangeline : "",
   2836                    (data->set.str[STRING_USERAGENT] &&
   2837                     *data->set.str[STRING_USERAGENT] &&
   2838                     data->state.aptr.uagent) ?
   2839                    data->state.aptr.uagent : "",
   2840                    p_accept ? p_accept : "",
   2841                    data->state.aptr.te ? data->state.aptr.te : "",
   2842                    (data->set.str[STRING_ENCODING] &&
   2843                     *data->set.str[STRING_ENCODING] &&
   2844                     data->state.aptr.accept_encoding) ?
   2845                    data->state.aptr.accept_encoding : "",
   2846                    (data->state.referer && data->state.aptr.ref) ?
   2847                    data->state.aptr.ref : "" /* Referer: <data> */,
   2848 #ifndef CURL_DISABLE_PROXY
   2849                    (conn->bits.httpproxy &&
   2850                     !conn->bits.tunnel_proxy &&
   2851                     !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
   2852                     !Curl_checkProxyheaders(data, conn,
   2853                                             STRCONST("Proxy-Connection"))) ?
   2854                    "Proxy-Connection: Keep-Alive\r\n":"",
   2855 #else
   2856                    "",
   2857 #endif
   2858                    te,
   2859                    altused ? altused : ""
   2860       );
   2861 
   2862   /* clear userpwd and proxyuserpwd to avoid reusing old credentials
   2863    * from reused connections */
   2864   Curl_safefree(data->state.aptr.userpwd);
   2865 #ifndef CURL_DISABLE_PROXY
   2866   Curl_safefree(data->state.aptr.proxyuserpwd);
   2867 #endif
   2868   free(altused);
   2869 
   2870   if(result) {
   2871     curlx_dyn_free(&req);
   2872     goto fail;
   2873   }
   2874 
   2875   if(!Curl_conn_is_ssl(conn, FIRSTSOCKET) && (httpversion < 20) &&
   2876      (data->state.http_neg.wanted & CURL_HTTP_V2x) &&
   2877      data->state.http_neg.h2_upgrade) {
   2878     /* append HTTP2 upgrade magic stuff to the HTTP request if it is not done
   2879        over SSL */
   2880     result = Curl_http2_request_upgrade(&req, data);
   2881     if(result) {
   2882       curlx_dyn_free(&req);
   2883       return result;
   2884     }
   2885   }
   2886 
   2887   result = http_cookies(data, conn, &req);
   2888 #ifndef CURL_DISABLE_WEBSOCKETS
   2889   if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
   2890     result = Curl_ws_request(data, &req);
   2891 #endif
   2892   if(!result)
   2893     result = Curl_add_timecondition(data, &req);
   2894   if(!result)
   2895     result = Curl_add_custom_headers(data, FALSE, httpversion, &req);
   2896 
   2897   if(!result) {
   2898     /* req_send takes ownership of the 'req' memory on success */
   2899     result = http_req_complete(data, &req, httpversion, httpreq);
   2900     if(!result)
   2901       result = Curl_req_send(data, &req, httpversion);
   2902   }
   2903   curlx_dyn_free(&req);
   2904   if(result)
   2905     goto fail;
   2906 
   2907   if((httpversion >= 20) && data->req.upload_chunky)
   2908     /* upload_chunky was set above to set up the request in a chunky fashion,
   2909        but is disabled here again to avoid that the chunked encoded version is
   2910        actually used when sending the request body over h2 */
   2911     data->req.upload_chunky = FALSE;
   2912 fail:
   2913   if(CURLE_TOO_LARGE == result)
   2914     failf(data, "HTTP request too large");
   2915   return result;
   2916 }
   2917 
   2918 typedef enum {
   2919   STATUS_UNKNOWN, /* not enough data to tell yet */
   2920   STATUS_DONE, /* a status line was read */
   2921   STATUS_BAD /* not a status line */
   2922 } statusline;
   2923 
   2924 
   2925 /* Check a string for a prefix. Check no more than 'len' bytes */
   2926 static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
   2927 {
   2928   size_t ch = CURLMIN(strlen(prefix), len);
   2929   return curl_strnequal(prefix, buffer, ch);
   2930 }
   2931 
   2932 /*
   2933  * checkhttpprefix()
   2934  *
   2935  * Returns TRUE if member of the list matches prefix of string
   2936  */
   2937 static statusline
   2938 checkhttpprefix(struct Curl_easy *data,
   2939                 const char *s, size_t len)
   2940 {
   2941   struct curl_slist *head = data->set.http200aliases;
   2942   statusline rc = STATUS_BAD;
   2943   statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
   2944 
   2945   while(head) {
   2946     if(checkprefixmax(head->data, s, len)) {
   2947       rc = onmatch;
   2948       break;
   2949     }
   2950     head = head->next;
   2951   }
   2952 
   2953   if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
   2954     rc = onmatch;
   2955 
   2956   return rc;
   2957 }
   2958 
   2959 #ifndef CURL_DISABLE_RTSP
   2960 static statusline
   2961 checkrtspprefix(struct Curl_easy *data,
   2962                 const char *s, size_t len)
   2963 {
   2964   statusline result = STATUS_BAD;
   2965   statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
   2966   (void)data; /* unused */
   2967   if(checkprefixmax("RTSP/", s, len))
   2968     result = onmatch;
   2969 
   2970   return result;
   2971 }
   2972 #endif /* CURL_DISABLE_RTSP */
   2973 
   2974 static statusline
   2975 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
   2976                  const char *s, size_t len)
   2977 {
   2978 #ifndef CURL_DISABLE_RTSP
   2979   if(conn->handler->protocol & CURLPROTO_RTSP)
   2980     return checkrtspprefix(data, s, len);
   2981 #else
   2982   (void)conn;
   2983 #endif /* CURL_DISABLE_RTSP */
   2984 
   2985   return checkhttpprefix(data, s, len);
   2986 }
   2987 
   2988 /* HTTP header has field name `n` (a string constant) */
   2989 #define HD_IS(hd, hdlen, n) \
   2990   (((hdlen) >= (sizeof(n)-1)) && curl_strnequal((n), (hd), (sizeof(n)-1)))
   2991 
   2992 #define HD_VAL(hd, hdlen, n) \
   2993   ((((hdlen) >= (sizeof(n)-1)) && \
   2994     curl_strnequal((n), (hd), (sizeof(n)-1)))? (hd + (sizeof(n)-1)) : NULL)
   2995 
   2996 /* HTTP header has field name `n` (a string constant) and contains `v`
   2997  * (a string constant) in its value(s) */
   2998 #define HD_IS_AND_SAYS(hd, hdlen, n, v) \
   2999   (HD_IS(hd, hdlen, n) && \
   3000    ((hdlen) > ((sizeof(n)-1) + (sizeof(v)-1))) && \
   3001    Curl_compareheader(hd, STRCONST(n), STRCONST(v)))
   3002 
   3003 /*
   3004  * http_header_a() parses a single response header starting with A.
   3005  */
   3006 static CURLcode http_header_a(struct Curl_easy *data,
   3007                               const char *hd, size_t hdlen)
   3008 {
   3009 #ifndef CURL_DISABLE_ALTSVC
   3010   const char *v;
   3011   struct connectdata *conn = data->conn;
   3012   v = (data->asi &&
   3013        (Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ||
   3014 #ifdef DEBUGBUILD
   3015         /* allow debug builds to circumvent the HTTPS restriction */
   3016         getenv("CURL_ALTSVC_HTTP")
   3017 #else
   3018         0
   3019 #endif
   3020          )) ? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
   3021   if(v) {
   3022     /* the ALPN of the current request */
   3023     struct SingleRequest *k = &data->req;
   3024     enum alpnid id = (k->httpversion == 30) ? ALPN_h3 :
   3025       (k->httpversion == 20) ? ALPN_h2 : ALPN_h1;
   3026     return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
   3027                              curlx_uitous((unsigned int)conn->remote_port));
   3028   }
   3029 #else
   3030   (void)data;
   3031   (void)hd;
   3032   (void)hdlen;
   3033 #endif
   3034   return CURLE_OK;
   3035 }
   3036 
   3037 /*
   3038  * http_header_c() parses a single response header starting with C.
   3039  */
   3040 static CURLcode http_header_c(struct Curl_easy *data,
   3041                               const char *hd, size_t hdlen)
   3042 {
   3043   struct connectdata *conn = data->conn;
   3044   struct SingleRequest *k = &data->req;
   3045   const char *v;
   3046 
   3047   /* Check for Content-Length: header lines to get size */
   3048   v = (!k->http_bodyless && !data->set.ignorecl) ?
   3049     HD_VAL(hd, hdlen, "Content-Length:") : NULL;
   3050   if(v) {
   3051     curl_off_t contentlength;
   3052     int offt = curlx_str_numblanks(&v, &contentlength);
   3053 
   3054     if(offt == STRE_OK) {
   3055       k->size = contentlength;
   3056       k->maxdownload = k->size;
   3057     }
   3058     else if(offt == STRE_OVERFLOW) {
   3059       /* out of range */
   3060       if(data->set.max_filesize) {
   3061         failf(data, "Maximum file size exceeded");
   3062         return CURLE_FILESIZE_EXCEEDED;
   3063       }
   3064       streamclose(conn, "overflow content-length");
   3065       infof(data, "Overflow Content-Length: value");
   3066     }
   3067     else {
   3068       /* negative or just rubbish - bad HTTP */
   3069       failf(data, "Invalid Content-Length: value");
   3070       return CURLE_WEIRD_SERVER_REPLY;
   3071     }
   3072     return CURLE_OK;
   3073   }
   3074   v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ?
   3075     HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
   3076   if(v) {
   3077     /*
   3078      * Process Content-Encoding. Look for the values: identity,
   3079      * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
   3080      * x-compress are the same as gzip and compress. (Sec 3.5 RFC
   3081      * 2616). zlib cannot handle compress. However, errors are
   3082      * handled further down when the response body is processed
   3083      */
   3084     return Curl_build_unencoding_stack(data, v, FALSE);
   3085   }
   3086   /* check for Content-Type: header lines to get the MIME-type */
   3087   v = HD_VAL(hd, hdlen, "Content-Type:");
   3088   if(v) {
   3089     char *contenttype = Curl_copy_header_value(hd);
   3090     if(!contenttype)
   3091       return CURLE_OUT_OF_MEMORY;
   3092     if(!*contenttype)
   3093       /* ignore empty data */
   3094       free(contenttype);
   3095     else {
   3096       free(data->info.contenttype);
   3097       data->info.contenttype = contenttype;
   3098     }
   3099     return CURLE_OK;
   3100   }
   3101   if(HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) {
   3102     /*
   3103      * [RFC 2616, section 8.1.2.1]
   3104      * "Connection: close" is HTTP/1.1 language and means that
   3105      * the connection will close when this request has been
   3106      * served.
   3107      */
   3108     streamclose(conn, "Connection: close used");
   3109     return CURLE_OK;
   3110   }
   3111   if((k->httpversion == 10) &&
   3112      HD_IS_AND_SAYS(hd, hdlen, "Connection:", "keep-alive")) {
   3113     /*
   3114      * An HTTP/1.0 reply with the 'Connection: keep-alive' line
   3115      * tells us the connection will be kept alive for our
   3116      * pleasure. Default action for 1.0 is to close.
   3117      *
   3118      * [RFC2068, section 19.7.1] */
   3119     connkeep(conn, "Connection keep-alive");
   3120     infof(data, "HTTP/1.0 connection set to keep alive");
   3121     return CURLE_OK;
   3122   }
   3123   v = !k->http_bodyless ? HD_VAL(hd, hdlen, "Content-Range:") : NULL;
   3124   if(v) {
   3125     /* Content-Range: bytes [num]-
   3126        Content-Range: bytes: [num]-
   3127        Content-Range: [num]-
   3128        Content-Range: [asterisk]/[total]
   3129 
   3130        The second format was added since Sun's webserver
   3131        JavaWebServer/1.1.1 obviously sends the header this way!
   3132        The third added since some servers use that!
   3133        The fourth means the requested range was unsatisfied.
   3134     */
   3135 
   3136     const char *ptr = v;
   3137 
   3138     /* Move forward until first digit or asterisk */
   3139     while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
   3140       ptr++;
   3141 
   3142     /* if it truly stopped on a digit */
   3143     if(ISDIGIT(*ptr)) {
   3144       if(!curlx_str_number(&ptr, &k->offset, CURL_OFF_T_MAX) &&
   3145          (data->state.resume_from == k->offset))
   3146         /* we asked for a resume and we got it */
   3147         k->content_range = TRUE;
   3148     }
   3149     else if(k->httpcode < 300)
   3150       data->state.resume_from = 0; /* get everything */
   3151   }
   3152   return CURLE_OK;
   3153 }
   3154 
   3155 /*
   3156  * http_header_l() parses a single response header starting with L.
   3157  */
   3158 static CURLcode http_header_l(struct Curl_easy *data,
   3159                               const char *hd, size_t hdlen)
   3160 {
   3161   struct connectdata *conn = data->conn;
   3162   struct SingleRequest *k = &data->req;
   3163   const char *v = (!k->http_bodyless &&
   3164                    (data->set.timecondition || data->set.get_filetime)) ?
   3165     HD_VAL(hd, hdlen, "Last-Modified:") : NULL;
   3166   if(v) {
   3167     k->timeofdoc = Curl_getdate_capped(v);
   3168     if(data->set.get_filetime)
   3169       data->info.filetime = k->timeofdoc;
   3170     return CURLE_OK;
   3171   }
   3172   if((k->httpcode >= 300 && k->httpcode < 400) &&
   3173      HD_IS(hd, hdlen, "Location:") &&
   3174      !data->req.location) {
   3175     /* this is the URL that the server advises us to use instead */
   3176     char *location = Curl_copy_header_value(hd);
   3177     if(!location)
   3178       return CURLE_OUT_OF_MEMORY;
   3179     if(!*location)
   3180       /* ignore empty data */
   3181       free(location);
   3182     else {
   3183       data->req.location = location;
   3184 
   3185       if(data->set.http_follow_mode) {
   3186         CURLcode result;
   3187         DEBUGASSERT(!data->req.newurl);
   3188         data->req.newurl = strdup(data->req.location); /* clone */
   3189         if(!data->req.newurl)
   3190           return CURLE_OUT_OF_MEMORY;
   3191 
   3192         /* some cases of POST and PUT etc needs to rewind the data
   3193            stream at this point */
   3194         result = http_perhapsrewind(data, conn);
   3195         if(result)
   3196           return result;
   3197 
   3198         /* mark the next request as a followed location: */
   3199         data->state.this_is_a_follow = TRUE;
   3200       }
   3201     }
   3202   }
   3203   return CURLE_OK;
   3204 }
   3205 
   3206 /*
   3207  * http_header_p() parses a single response header starting with P.
   3208  */
   3209 static CURLcode http_header_p(struct Curl_easy *data,
   3210                               const char *hd, size_t hdlen)
   3211 {
   3212   struct SingleRequest *k = &data->req;
   3213 
   3214 #ifndef CURL_DISABLE_PROXY
   3215   const char *v = HD_VAL(hd, hdlen, "Proxy-Connection:");
   3216   if(v) {
   3217     struct connectdata *conn = data->conn;
   3218     if((k->httpversion == 10) && conn->bits.httpproxy &&
   3219        HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "keep-alive")) {
   3220       /*
   3221        * When an HTTP/1.0 reply comes when using a proxy, the
   3222        * 'Proxy-Connection: keep-alive' line tells us the
   3223        * connection will be kept alive for our pleasure.
   3224        * Default action for 1.0 is to close.
   3225        */
   3226       connkeep(conn, "Proxy-Connection keep-alive"); /* do not close */
   3227       infof(data, "HTTP/1.0 proxy connection set to keep alive");
   3228     }
   3229     else if((k->httpversion == 11) && conn->bits.httpproxy &&
   3230             HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "close")) {
   3231       /*
   3232        * We get an HTTP/1.1 response from a proxy and it says it will
   3233        * close down after this transfer.
   3234        */
   3235       connclose(conn, "Proxy-Connection: asked to close after done");
   3236       infof(data, "HTTP/1.1 proxy connection set close");
   3237     }
   3238     return CURLE_OK;
   3239   }
   3240 #endif
   3241   if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) {
   3242     char *auth = Curl_copy_header_value(hd);
   3243     CURLcode result;
   3244     if(!auth)
   3245       return CURLE_OUT_OF_MEMORY;
   3246     result = Curl_http_input_auth(data, TRUE, auth);
   3247     free(auth);
   3248     return result;
   3249   }
   3250 #ifdef USE_SPNEGO
   3251   if(HD_IS(hd, hdlen, "Persistent-Auth:")) {
   3252     struct connectdata *conn = data->conn;
   3253     struct negotiatedata *negdata = Curl_auth_nego_get(conn, FALSE);
   3254     struct auth *authp = &data->state.authhost;
   3255     if(!negdata)
   3256       return CURLE_OUT_OF_MEMORY;
   3257     if(authp->picked == CURLAUTH_NEGOTIATE) {
   3258       char *persistentauth = Curl_copy_header_value(hd);
   3259       if(!persistentauth)
   3260         return CURLE_OUT_OF_MEMORY;
   3261       negdata->noauthpersist = !!checkprefix("false", persistentauth);
   3262       negdata->havenoauthpersist = TRUE;
   3263       infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
   3264             negdata->noauthpersist, persistentauth);
   3265       free(persistentauth);
   3266     }
   3267   }
   3268 #endif
   3269   return CURLE_OK;
   3270 }
   3271 
   3272 /*
   3273  * http_header_r() parses a single response header starting with R.
   3274  */
   3275 static CURLcode http_header_r(struct Curl_easy *data,
   3276                               const char *hd, size_t hdlen)
   3277 {
   3278   const char *v = HD_VAL(hd, hdlen, "Retry-After:");
   3279   if(v) {
   3280     /* Retry-After = HTTP-date / delay-seconds */
   3281     curl_off_t retry_after = 0; /* zero for unknown or "now" */
   3282     time_t date;
   3283     curlx_str_passblanks(&v);
   3284 
   3285     /* try it as a date first, because a date can otherwise start with and
   3286        get treated as a number */
   3287     date = Curl_getdate_capped(v);
   3288 
   3289     if((time_t)-1 != date) {
   3290       time_t current = time(NULL);
   3291       if(date >= current)
   3292         /* convert date to number of seconds into the future */
   3293         retry_after = date - current;
   3294     }
   3295     else
   3296       /* Try it as a decimal number, ignore errors */
   3297       (void)curlx_str_number(&v, &retry_after, CURL_OFF_T_MAX);
   3298     /* limit to 6 hours max. this is not documented so that it can be changed
   3299        in the future if necessary. */
   3300     if(retry_after > 21600)
   3301       retry_after = 21600;
   3302     data->info.retry_after = retry_after;
   3303   }
   3304   return CURLE_OK;
   3305 }
   3306 
   3307 /*
   3308  * http_header_s() parses a single response header starting with S.
   3309  */
   3310 static CURLcode http_header_s(struct Curl_easy *data,
   3311                               const char *hd, size_t hdlen)
   3312 {
   3313 #if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_HSTS)
   3314   struct connectdata *conn = data->conn;
   3315   const char *v;
   3316 #else
   3317   (void)data;
   3318   (void)hd;
   3319   (void)hdlen;
   3320 #endif
   3321 
   3322 #if !defined(CURL_DISABLE_COOKIES)
   3323   v = (data->cookies && data->state.cookie_engine) ?
   3324     HD_VAL(hd, hdlen, "Set-Cookie:") : NULL;
   3325   if(v) {
   3326     /* If there is a custom-set Host: name, use it here, or else use
   3327      * real peer hostname. */
   3328     const char *host = data->state.aptr.cookiehost ?
   3329       data->state.aptr.cookiehost : conn->host.name;
   3330     const bool secure_context =
   3331       conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
   3332       curl_strequal("localhost", host) ||
   3333       !strcmp(host, "127.0.0.1") ||
   3334       !strcmp(host, "::1");
   3335 
   3336     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
   3337                     CURL_LOCK_ACCESS_SINGLE);
   3338     Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host,
   3339                     data->state.up.path, secure_context);
   3340     Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   3341     return CURLE_OK;
   3342   }
   3343 #endif
   3344 #ifndef CURL_DISABLE_HSTS
   3345   /* If enabled, the header is incoming and this is over HTTPS */
   3346   v = (data->hsts &&
   3347        (Curl_conn_is_ssl(conn, FIRSTSOCKET) ||
   3348 #ifdef DEBUGBUILD
   3349         /* allow debug builds to circumvent the HTTPS restriction */
   3350         getenv("CURL_HSTS_HTTP")
   3351 #else
   3352         0
   3353 #endif
   3354          )
   3355     ) ? HD_VAL(hd, hdlen, "Strict-Transport-Security:") : NULL;
   3356   if(v) {
   3357     CURLcode check =
   3358       Curl_hsts_parse(data->hsts, conn->host.name, v);
   3359     if(check)
   3360       infof(data, "Illegal STS header skipped");
   3361 #ifdef DEBUGBUILD
   3362     else
   3363       infof(data, "Parsed STS header fine (%zu entries)",
   3364             Curl_llist_count(&data->hsts->list));
   3365 #endif
   3366   }
   3367 #endif
   3368 
   3369   return CURLE_OK;
   3370 }
   3371 
   3372 /*
   3373  * http_header_t() parses a single response header starting with T.
   3374  */
   3375 static CURLcode http_header_t(struct Curl_easy *data,
   3376                               const char *hd, size_t hdlen)
   3377 {
   3378   struct connectdata *conn = data->conn;
   3379   struct SingleRequest *k = &data->req;
   3380 
   3381   /* RFC 9112, ch. 6.1
   3382    * "Transfer-Encoding MAY be sent in a response to a HEAD request or
   3383    *  in a 304 (Not Modified) response (Section 15.4.5 of [HTTP]) to a
   3384    *  GET request, neither of which includes a message body, to indicate
   3385    *  that the origin server would have applied a transfer coding to the
   3386    *  message body if the request had been an unconditional GET."
   3387    *
   3388    * Read: in these cases the 'Transfer-Encoding' does not apply
   3389    * to any data following the response headers. Do not add any decoders.
   3390    */
   3391   const char *v = (!k->http_bodyless &&
   3392                    (data->state.httpreq != HTTPREQ_HEAD) &&
   3393                    (k->httpcode != 304)) ?
   3394     HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
   3395   if(v) {
   3396     /* One or more encodings. We check for chunked and/or a compression
   3397        algorithm. */
   3398     CURLcode result = Curl_build_unencoding_stack(data, v, TRUE);
   3399     if(result)
   3400       return result;
   3401     if(!k->chunk && data->set.http_transfer_encoding) {
   3402       /* if this is not chunked, only close can signal the end of this
   3403        * transfer as Content-Length is said not to be trusted for
   3404        * transfer-encoding! */
   3405       connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
   3406       k->ignore_cl = TRUE;
   3407     }
   3408     return CURLE_OK;
   3409   }
   3410   v = HD_VAL(hd, hdlen, "Trailer:");
   3411   if(v) {
   3412     data->req.resp_trailer = TRUE;
   3413     return CURLE_OK;
   3414   }
   3415   return CURLE_OK;
   3416 }
   3417 
   3418 /*
   3419  * http_header_w() parses a single response header starting with W.
   3420  */
   3421 static CURLcode http_header_w(struct Curl_easy *data,
   3422                               const char *hd, size_t hdlen)
   3423 {
   3424   struct SingleRequest *k = &data->req;
   3425   CURLcode result = CURLE_OK;
   3426 
   3427   if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) {
   3428     char *auth = Curl_copy_header_value(hd);
   3429     if(!auth)
   3430       return CURLE_OUT_OF_MEMORY;
   3431     result = Curl_http_input_auth(data, FALSE, auth);
   3432     free(auth);
   3433   }
   3434   return result;
   3435 }
   3436 
   3437 /*
   3438  * http_header() parses a single response header.
   3439  */
   3440 static CURLcode http_header(struct Curl_easy *data,
   3441                             const char *hd, size_t hdlen)
   3442 {
   3443   CURLcode result = CURLE_OK;
   3444 
   3445   switch(hd[0]) {
   3446   case 'a':
   3447   case 'A':
   3448     result = http_header_a(data, hd, hdlen);
   3449     break;
   3450   case 'c':
   3451   case 'C':
   3452     result = http_header_c(data, hd, hdlen);
   3453     break;
   3454   case 'l':
   3455   case 'L':
   3456     result = http_header_l(data, hd, hdlen);
   3457     break;
   3458   case 'p':
   3459   case 'P':
   3460     result = http_header_p(data, hd, hdlen);
   3461     break;
   3462   case 'r':
   3463   case 'R':
   3464     result = http_header_r(data, hd, hdlen);
   3465     break;
   3466   case 's':
   3467   case 'S':
   3468     result = http_header_s(data, hd, hdlen);
   3469     break;
   3470   case 't':
   3471   case 'T':
   3472     result = http_header_t(data, hd, hdlen);
   3473     break;
   3474   case 'w':
   3475   case 'W':
   3476     result = http_header_w(data, hd, hdlen);
   3477     break;
   3478   }
   3479 
   3480   if(!result) {
   3481     struct connectdata *conn = data->conn;
   3482     if(conn->handler->protocol & CURLPROTO_RTSP)
   3483       result = Curl_rtsp_parseheader(data, hd);
   3484   }
   3485   return result;
   3486 }
   3487 
   3488 /*
   3489  * Called after the first HTTP response line (the status line) has been
   3490  * received and parsed.
   3491  */
   3492 static CURLcode http_statusline(struct Curl_easy *data,
   3493                                 struct connectdata *conn)
   3494 {
   3495   struct SingleRequest *k = &data->req;
   3496 
   3497   switch(k->httpversion) {
   3498   case 10:
   3499   case 11:
   3500 #ifdef USE_HTTP2
   3501   case 20:
   3502 #endif
   3503 #ifdef USE_HTTP3
   3504   case 30:
   3505 #endif
   3506     /* no major version switch mid-connection */
   3507     if(k->httpversion_sent &&
   3508        (k->httpversion/10 != k->httpversion_sent/10)) {
   3509       failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)",
   3510             k->httpversion_sent/10, k->httpversion/10);
   3511       return CURLE_WEIRD_SERVER_REPLY;
   3512     }
   3513     break;
   3514   default:
   3515     failf(data, "Unsupported HTTP version (%u.%d) in response",
   3516           k->httpversion/10, k->httpversion%10);
   3517     return CURLE_UNSUPPORTED_PROTOCOL;
   3518   }
   3519 
   3520   data->info.httpcode = k->httpcode;
   3521   data->info.httpversion = k->httpversion;
   3522   conn->httpversion_seen = (unsigned char)k->httpversion;
   3523 
   3524   if(!data->state.http_neg.rcvd_min ||
   3525      data->state.http_neg.rcvd_min > k->httpversion)
   3526     /* store the lowest server version we encounter */
   3527     data->state.http_neg.rcvd_min = (unsigned char)k->httpversion;
   3528 
   3529   /*
   3530    * This code executes as part of processing the header. As a
   3531    * result, it is not totally clear how to interpret the
   3532    * response code yet as that depends on what other headers may
   3533    * be present. 401 and 407 may be errors, but may be OK
   3534    * depending on how authentication is working. Other codes
   3535    * are definitely errors, so give up here.
   3536    */
   3537   if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
   3538      k->httpcode == 416) {
   3539     /* "Requested Range Not Satisfiable", just proceed and
   3540        pretend this is no error */
   3541     k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
   3542   }
   3543 
   3544   if(k->httpversion == 10) {
   3545     /* Default action for HTTP/1.0 must be to close, unless
   3546        we get one of those fancy headers that tell us the
   3547        server keeps it open for us! */
   3548     infof(data, "HTTP 1.0, assume close after body");
   3549     connclose(conn, "HTTP/1.0 close after body");
   3550   }
   3551   else if(k->httpversion == 20 ||
   3552           (k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
   3553     DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
   3554   }
   3555 
   3556   k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
   3557   switch(k->httpcode) {
   3558   case 304:
   3559     /* (quote from RFC2616, section 10.3.5): The 304 response
   3560      * MUST NOT contain a message-body, and thus is always
   3561      * terminated by the first empty line after the header
   3562      * fields.  */
   3563     if(data->set.timecondition)
   3564       data->info.timecond = TRUE;
   3565     FALLTHROUGH();
   3566   case 204:
   3567     /* (quote from RFC2616, section 10.2.5): The server has
   3568      * fulfilled the request but does not need to return an
   3569      * entity-body ... The 204 response MUST NOT include a
   3570      * message-body, and thus is always terminated by the first
   3571      * empty line after the header fields. */
   3572     k->size = 0;
   3573     k->maxdownload = 0;
   3574     k->http_bodyless = TRUE;
   3575     break;
   3576   default:
   3577     break;
   3578   }
   3579   return CURLE_OK;
   3580 }
   3581 
   3582 /* Content-Length must be ignored if any Transfer-Encoding is present in the
   3583    response. Refer to RFC 7230 section 3.3.3 and RFC2616 section 4.4. This is
   3584    figured out here after all headers have been received but before the final
   3585    call to the user's header callback, so that a valid content length can be
   3586    retrieved by the user in the final call. */
   3587 static CURLcode http_size(struct Curl_easy *data)
   3588 {
   3589   struct SingleRequest *k = &data->req;
   3590   if(data->req.ignore_cl || k->chunk) {
   3591     k->size = k->maxdownload = -1;
   3592   }
   3593   else if(k->size != -1) {
   3594     if(data->set.max_filesize &&
   3595        !k->ignorebody &&
   3596        (k->size > data->set.max_filesize)) {
   3597       failf(data, "Maximum file size exceeded");
   3598       return CURLE_FILESIZE_EXCEEDED;
   3599     }
   3600     if(k->ignorebody)
   3601       infof(data, "setting size while ignoring");
   3602     Curl_pgrsSetDownloadSize(data, k->size);
   3603     k->maxdownload = k->size;
   3604   }
   3605   return CURLE_OK;
   3606 }
   3607 
   3608 static CURLcode verify_header(struct Curl_easy *data,
   3609                               const char *hd, size_t hdlen)
   3610 {
   3611   struct SingleRequest *k = &data->req;
   3612   char *ptr = memchr(hd, 0x00, hdlen);
   3613   if(ptr) {
   3614     /* this is bad, bail out */
   3615     failf(data, "Nul byte in header");
   3616     return CURLE_WEIRD_SERVER_REPLY;
   3617   }
   3618   if(k->headerline < 2)
   3619     /* the first "header" is the status-line and it has no colon */
   3620     return CURLE_OK;
   3621   if(((hd[0] == ' ') || (hd[0] == '\t')) && k->headerline > 2)
   3622     /* line folding, cannot happen on line 2 */
   3623     ;
   3624   else {
   3625     ptr = memchr(hd, ':', hdlen);
   3626     if(!ptr) {
   3627       /* this is bad, bail out */
   3628       failf(data, "Header without colon");
   3629       return CURLE_WEIRD_SERVER_REPLY;
   3630     }
   3631   }
   3632   return CURLE_OK;
   3633 }
   3634 
   3635 CURLcode Curl_bump_headersize(struct Curl_easy *data,
   3636                               size_t delta,
   3637                               bool connect_only)
   3638 {
   3639   size_t bad = 0;
   3640   unsigned int max = MAX_HTTP_RESP_HEADER_SIZE;
   3641   if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
   3642     data->info.header_size += (unsigned int)delta;
   3643     data->req.allheadercount += (unsigned int)delta;
   3644     if(!connect_only)
   3645       data->req.headerbytecount += (unsigned int)delta;
   3646     if(data->req.allheadercount > max)
   3647       bad = data->req.allheadercount;
   3648     else if(data->info.header_size > (max * 20)) {
   3649       bad = data->info.header_size;
   3650       max *= 20;
   3651     }
   3652   }
   3653   else
   3654     bad = data->req.allheadercount + delta;
   3655   if(bad) {
   3656     failf(data, "Too large response headers: %zu > %u", bad, max);
   3657     return CURLE_RECV_ERROR;
   3658   }
   3659   return CURLE_OK;
   3660 }
   3661 
   3662 static CURLcode http_write_header(struct Curl_easy *data,
   3663                                   const char *hd, size_t hdlen)
   3664 {
   3665   CURLcode result;
   3666   int writetype;
   3667 
   3668   /* now, only output this if the header AND body are requested:
   3669    */
   3670   Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen);
   3671 
   3672   writetype = CLIENTWRITE_HEADER |
   3673     ((data->req.httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
   3674 
   3675   result = Curl_client_write(data, writetype, hd, hdlen);
   3676   if(result)
   3677     return result;
   3678 
   3679   result = Curl_bump_headersize(data, hdlen, FALSE);
   3680   if(result)
   3681     return result;
   3682 
   3683   data->req.deductheadercount = (100 <= data->req.httpcode &&
   3684                                  199 >= data->req.httpcode) ?
   3685     data->req.headerbytecount : 0;
   3686   return result;
   3687 }
   3688 
   3689 static CURLcode http_on_response(struct Curl_easy *data,
   3690                                  const char *last_hd, size_t last_hd_len,
   3691                                  const char *buf, size_t blen,
   3692                                  size_t *pconsumed)
   3693 {
   3694   struct connectdata *conn = data->conn;
   3695   CURLcode result = CURLE_OK;
   3696   struct SingleRequest *k = &data->req;
   3697 
   3698   (void)buf; /* not used without HTTP2 enabled */
   3699   *pconsumed = 0;
   3700 
   3701   if(k->upgr101 == UPGR101_RECEIVED) {
   3702     /* supposedly upgraded to http2 now */
   3703     if(data->req.httpversion != 20)
   3704       infof(data, "Lying server, not serving HTTP/2");
   3705   }
   3706 
   3707   if(k->httpcode < 200 && last_hd) {
   3708     /* Intermediate responses might trigger processing of more
   3709      * responses, write the last header to the client before
   3710      * proceeding. */
   3711     result = http_write_header(data, last_hd, last_hd_len);
   3712     last_hd = NULL; /* handled it */
   3713     if(result)
   3714       goto out;
   3715   }
   3716 
   3717   if(k->httpcode < 100) {
   3718     failf(data, "Unsupported response code in HTTP response");
   3719     result = CURLE_UNSUPPORTED_PROTOCOL;
   3720     goto out;
   3721   }
   3722   else if(k->httpcode < 200) {
   3723     /* "A user agent MAY ignore unexpected 1xx status responses."
   3724      * By default, we expect to get more responses after this one. */
   3725     k->header = TRUE;
   3726     k->headerline = 0; /* restart the header line counter */
   3727 
   3728     switch(k->httpcode) {
   3729     case 100:
   3730       /*
   3731        * We have made an HTTP PUT or POST and this is 1.1-lingo
   3732        * that tells us that the server is OK with this and ready
   3733        * to receive the data.
   3734        */
   3735       http_exp100_got100(data);
   3736       break;
   3737     case 101:
   3738       /* Switching Protocols only allowed from HTTP/1.1 */
   3739       if(k->httpversion_sent != 11) {
   3740         /* invalid for other HTTP versions */
   3741         failf(data, "unexpected 101 response code");
   3742         result = CURLE_WEIRD_SERVER_REPLY;
   3743         goto out;
   3744       }
   3745       if(k->upgr101 == UPGR101_H2) {
   3746         /* Switching to HTTP/2, where we will get more responses */
   3747         infof(data, "Received 101, Switching to HTTP/2");
   3748         k->upgr101 = UPGR101_RECEIVED;
   3749         data->conn->bits.asks_multiplex = FALSE;
   3750         /* We expect more response from HTTP/2 later */
   3751         k->header = TRUE;
   3752         k->headerline = 0; /* restart the header line counter */
   3753         k->httpversion_sent = 20; /* It's an HTTP/2 request now */
   3754         /* Any remaining `buf` bytes are already HTTP/2 and passed to
   3755          * be processed. */
   3756         result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
   3757         if(result)
   3758           goto out;
   3759         *pconsumed += blen;
   3760       }
   3761 #ifndef CURL_DISABLE_WEBSOCKETS
   3762       else if(k->upgr101 == UPGR101_WS) {
   3763         /* verify the response. Any passed `buf` bytes are already in
   3764          * WebSockets format and taken in by the protocol handler. */
   3765         result = Curl_ws_accept(data, buf, blen);
   3766         if(result)
   3767           goto out;
   3768         *pconsumed += blen; /* ws accept handled the data */
   3769         k->header = FALSE; /* we will not get more responses */
   3770         if(data->set.connect_only)
   3771           k->keepon &= ~KEEP_RECV; /* read no more content */
   3772       }
   3773 #endif
   3774       else {
   3775         /* We silently accept this as the final response. What are we
   3776          * switching to if we did not ask for an Upgrade? Maybe the
   3777          * application provided an `Upgrade: xxx` header? */
   3778         k->header = FALSE;
   3779       }
   3780       break;
   3781     default:
   3782       /* The server may send us other 1xx responses, like informative
   3783        * 103. This have no influence on request processing and we expect
   3784        * to receive a final response eventually. */
   3785       break;
   3786     }
   3787     goto out;
   3788   }
   3789 
   3790   /* k->httpcode >= 200, final response */
   3791   k->header = FALSE;
   3792 
   3793   if(k->upgr101 == UPGR101_H2) {
   3794     /* A requested upgrade was denied, poke the multi handle to possibly
   3795        allow a pending pipewait to continue */
   3796     data->conn->bits.asks_multiplex = FALSE;
   3797     Curl_multi_connchanged(data->multi);
   3798   }
   3799 
   3800   if((k->size == -1) && !k->chunk && !conn->bits.close &&
   3801      (k->httpversion == 11) &&
   3802      !(conn->handler->protocol & CURLPROTO_RTSP) &&
   3803      data->state.httpreq != HTTPREQ_HEAD) {
   3804     /* On HTTP 1.1, when connection is not to get closed, but no
   3805        Content-Length nor Transfer-Encoding chunked have been
   3806        received, according to RFC2616 section 4.4 point 5, we
   3807        assume that the server will close the connection to
   3808        signal the end of the document. */
   3809     infof(data, "no chunk, no close, no size. Assume close to "
   3810           "signal end");
   3811     streamclose(conn, "HTTP: No end-of-message indicator");
   3812   }
   3813 
   3814   /* At this point we have some idea about the fate of the connection.
   3815      If we are closing the connection it may result auth failure. */
   3816 #if defined(USE_NTLM)
   3817   if(conn->bits.close &&
   3818      (((data->req.httpcode == 401) &&
   3819        (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
   3820       ((data->req.httpcode == 407) &&
   3821        (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
   3822     infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
   3823     data->state.authproblem = TRUE;
   3824   }
   3825 #endif
   3826 #if defined(USE_SPNEGO)
   3827   if(conn->bits.close &&
   3828     (((data->req.httpcode == 401) &&
   3829       (conn->http_negotiate_state == GSS_AUTHRECV)) ||
   3830      ((data->req.httpcode == 407) &&
   3831       (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
   3832     infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
   3833     data->state.authproblem = TRUE;
   3834   }
   3835   if((conn->http_negotiate_state == GSS_AUTHDONE) &&
   3836      (data->req.httpcode != 401)) {
   3837     conn->http_negotiate_state = GSS_AUTHSUCC;
   3838   }
   3839   if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
   3840      (data->req.httpcode != 407)) {
   3841     conn->proxy_negotiate_state = GSS_AUTHSUCC;
   3842   }
   3843 #endif
   3844 
   3845 #ifndef CURL_DISABLE_WEBSOCKETS
   3846   /* All >=200 HTTP status codes are errors when wanting WebSockets */
   3847   if(data->req.upgr101 == UPGR101_WS) {
   3848     failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
   3849     result = CURLE_HTTP_RETURNED_ERROR;
   3850     goto out;
   3851   }
   3852 #endif
   3853 
   3854   /* Check if this response means the transfer errored. */
   3855   if(http_should_fail(data, data->req.httpcode)) {
   3856     failf(data, "The requested URL returned error: %d",
   3857           k->httpcode);
   3858     result = CURLE_HTTP_RETURNED_ERROR;
   3859     goto out;
   3860   }
   3861 
   3862   /* Curl_http_auth_act() checks what authentication methods
   3863    * that are available and decides which one (if any) to
   3864    * use. It will set 'newurl' if an auth method was picked. */
   3865   result = Curl_http_auth_act(data);
   3866   if(result)
   3867     goto out;
   3868 
   3869   if(k->httpcode >= 300) {
   3870     if((!data->req.authneg) && !conn->bits.close &&
   3871        !Curl_creader_will_rewind(data)) {
   3872       /*
   3873        * General treatment of errors when about to send data. Including :
   3874        * "417 Expectation Failed", while waiting for 100-continue.
   3875        *
   3876        * The check for close above is done simply because of something
   3877        * else has already deemed the connection to get closed then
   3878        * something else should've considered the big picture and we
   3879        * avoid this check.
   3880        *
   3881        */
   3882 
   3883       switch(data->state.httpreq) {
   3884       case HTTPREQ_PUT:
   3885       case HTTPREQ_POST:
   3886       case HTTPREQ_POST_FORM:
   3887       case HTTPREQ_POST_MIME:
   3888         /* We got an error response. If this happened before the whole
   3889          * request body has been sent we stop sending and mark the
   3890          * connection for closure after we have read the entire response.
   3891          */
   3892         if(!Curl_req_done_sending(data)) {
   3893           if((k->httpcode == 417) && http_exp100_is_selected(data)) {
   3894             /* 417 Expectation Failed - try again without the Expect
   3895                header */
   3896             if(!k->writebytecount && http_exp100_is_waiting(data)) {
   3897               infof(data, "Got HTTP failure 417 while waiting for a 100");
   3898             }
   3899             else {
   3900               infof(data, "Got HTTP failure 417 while sending data");
   3901               streamclose(conn,
   3902                           "Stop sending data before everything sent");
   3903               result = http_perhapsrewind(data, conn);
   3904               if(result)
   3905                 goto out;
   3906             }
   3907             data->state.disableexpect = TRUE;
   3908             DEBUGASSERT(!data->req.newurl);
   3909             data->req.newurl = strdup(data->state.url);
   3910             Curl_req_abort_sending(data);
   3911           }
   3912           else if(data->set.http_keep_sending_on_error) {
   3913             infof(data, "HTTP error before end of send, keep sending");
   3914             http_exp100_send_anyway(data);
   3915           }
   3916           else {
   3917             infof(data, "HTTP error before end of send, stop sending");
   3918             streamclose(conn, "Stop sending data before everything sent");
   3919             result = Curl_req_abort_sending(data);
   3920             if(result)
   3921               goto out;
   3922           }
   3923         }
   3924         break;
   3925 
   3926       default: /* default label present to avoid compiler warnings */
   3927         break;
   3928       }
   3929     }
   3930 
   3931     if(Curl_creader_will_rewind(data) && !Curl_req_done_sending(data)) {
   3932       /* We rewind before next send, continue sending now */
   3933       infof(data, "Keep sending data to get tossed away");
   3934       k->keepon |= KEEP_SEND;
   3935     }
   3936 
   3937   }
   3938 
   3939   /* If we requested a "no body", this is a good time to get
   3940    * out and return home.
   3941    */
   3942   if(data->req.no_body)
   3943     k->download_done = TRUE;
   3944 
   3945   /* If max download size is *zero* (nothing) we already have
   3946      nothing and can safely return ok now!  But for HTTP/2, we would
   3947      like to call http2_handle_stream_close to properly close a
   3948      stream. In order to do this, we keep reading until we
   3949      close the stream. */
   3950   if((0 == k->maxdownload) && (k->httpversion_sent < 20))
   3951     k->download_done = TRUE;
   3952 
   3953   /* final response without error, prepare to receive the body */
   3954   result = http_firstwrite(data);
   3955 
   3956   if(!result)
   3957     /* This is the last response that we get for the current request.
   3958      * Check on the body size and determine if the response is complete.
   3959      */
   3960     result = http_size(data);
   3961 
   3962 out:
   3963   if(last_hd) {
   3964     /* if not written yet, write it now */
   3965     result = Curl_1st_err(
   3966       result, http_write_header(data, last_hd, last_hd_len));
   3967   }
   3968   return result;
   3969 }
   3970 
   3971 static CURLcode http_rw_hd(struct Curl_easy *data,
   3972                            const char *hd, size_t hdlen,
   3973                            const char *buf_remain, size_t blen,
   3974                            size_t *pconsumed)
   3975 {
   3976   CURLcode result = CURLE_OK;
   3977   struct SingleRequest *k = &data->req;
   3978   int writetype;
   3979 
   3980   *pconsumed = 0;
   3981   if((0x0a == *hd) || (0x0d == *hd)) {
   3982     /* Empty header line means end of headers! */
   3983     struct dynbuf last_header;
   3984     size_t consumed;
   3985 
   3986     curlx_dyn_init(&last_header, hdlen + 1);
   3987     result = curlx_dyn_addn(&last_header, hd, hdlen);
   3988     if(result)
   3989       return result;
   3990 
   3991     /* analyze the response to find out what to do. */
   3992     /* Caveat: we clear anything in the header brigade, because a
   3993      * response might switch HTTP version which may call use recursively.
   3994      * Not nice, but that is currently the way of things. */
   3995     curlx_dyn_reset(&data->state.headerb);
   3996     result = http_on_response(data, curlx_dyn_ptr(&last_header),
   3997                               curlx_dyn_len(&last_header),
   3998                               buf_remain, blen, &consumed);
   3999     *pconsumed += consumed;
   4000     curlx_dyn_free(&last_header);
   4001     return result;
   4002   }
   4003 
   4004   /*
   4005    * Checks for special headers coming up.
   4006    */
   4007 
   4008   writetype = CLIENTWRITE_HEADER;
   4009   if(!k->headerline++) {
   4010     /* This is the first header, it MUST be the error code line
   4011        or else we consider this to be the body right away! */
   4012     bool fine_statusline = FALSE;
   4013 
   4014     k->httpversion = 0; /* Do not know yet */
   4015     if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
   4016       /*
   4017        * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
   4018        *
   4019        * The response code is always a three-digit number in HTTP as the spec
   4020        * says. We allow any three-digit number here, but we cannot make
   4021        * guarantees on future behaviors since it is not within the protocol.
   4022        */
   4023       const char *p = hd;
   4024 
   4025       curlx_str_passblanks(&p);
   4026       if(!strncmp(p, "HTTP/", 5)) {
   4027         p += 5;
   4028         switch(*p) {
   4029         case '1':
   4030           p++;
   4031           if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
   4032             if(ISBLANK(p[2])) {
   4033               k->httpversion = (unsigned char)(10 + (p[1] - '0'));
   4034               p += 3;
   4035               if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
   4036                 k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
   4037                   (p[2] - '0');
   4038                 /* RFC 9112 requires a single space following the status code,
   4039                    but the browsers don't so let's not insist */
   4040                 fine_statusline = TRUE;
   4041               }
   4042             }
   4043           }
   4044           if(!fine_statusline) {
   4045             failf(data, "Unsupported HTTP/1 subversion in response");
   4046             return CURLE_UNSUPPORTED_PROTOCOL;
   4047           }
   4048           break;
   4049         case '2':
   4050         case '3':
   4051           if(!ISBLANK(p[1]))
   4052             break;
   4053           k->httpversion = (unsigned char)((*p - '0') * 10);
   4054           p += 2;
   4055           if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
   4056             k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
   4057               (p[2] - '0');
   4058             p += 3;
   4059             if(!ISBLANK(*p))
   4060               break;
   4061             fine_statusline = TRUE;
   4062           }
   4063           break;
   4064         default: /* unsupported */
   4065           failf(data, "Unsupported HTTP version in response");
   4066           return CURLE_UNSUPPORTED_PROTOCOL;
   4067         }
   4068       }
   4069 
   4070       if(!fine_statusline) {
   4071         /* If user has set option HTTP200ALIASES,
   4072            compare header line against list of aliases
   4073         */
   4074         statusline check = checkhttpprefix(data, hd, hdlen);
   4075         if(check == STATUS_DONE) {
   4076           fine_statusline = TRUE;
   4077           k->httpcode = 200;
   4078           k->httpversion = 10;
   4079         }
   4080       }
   4081     }
   4082     else if(data->conn->handler->protocol & CURLPROTO_RTSP) {
   4083       const char *p = hd;
   4084       struct Curl_str ver;
   4085       curl_off_t status;
   4086       /* we set the max string a little excessive to forgive some leading
   4087          spaces */
   4088       if(!curlx_str_until(&p, &ver, 32, ' ') &&
   4089          !curlx_str_single(&p, ' ') &&
   4090          !curlx_str_number(&p, &status, 999)) {
   4091         curlx_str_trimblanks(&ver);
   4092         if(curlx_str_cmp(&ver, "RTSP/1.0")) {
   4093           k->httpcode = (int)status;
   4094           fine_statusline = TRUE;
   4095           k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
   4096         }
   4097       }
   4098       if(!fine_statusline)
   4099         return CURLE_WEIRD_SERVER_REPLY;
   4100     }
   4101 
   4102     if(fine_statusline) {
   4103       result = http_statusline(data, data->conn);
   4104       if(result)
   4105         return result;
   4106       writetype |= CLIENTWRITE_STATUS;
   4107     }
   4108     else {
   4109       k->header = FALSE;   /* this is not a header line */
   4110       return CURLE_WEIRD_SERVER_REPLY;
   4111     }
   4112   }
   4113 
   4114   result = verify_header(data, hd, hdlen);
   4115   if(result)
   4116     return result;
   4117 
   4118   result = http_header(data, hd, hdlen);
   4119   if(result)
   4120     return result;
   4121 
   4122   /*
   4123    * Taken in one (more) header. Write it to the client.
   4124    */
   4125   Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen);
   4126 
   4127   if(k->httpcode/100 == 1)
   4128     writetype |= CLIENTWRITE_1XX;
   4129   result = Curl_client_write(data, writetype, hd, hdlen);
   4130   if(result)
   4131     return result;
   4132 
   4133   result = Curl_bump_headersize(data, hdlen, FALSE);
   4134   if(result)
   4135     return result;
   4136 
   4137   return CURLE_OK;
   4138 }
   4139 
   4140 /*
   4141  * Read any HTTP header lines from the server and pass them to the client app.
   4142  */
   4143 static CURLcode http_parse_headers(struct Curl_easy *data,
   4144                                    const char *buf, size_t blen,
   4145                                    size_t *pconsumed)
   4146 {
   4147   struct connectdata *conn = data->conn;
   4148   CURLcode result = CURLE_OK;
   4149   struct SingleRequest *k = &data->req;
   4150   char *end_ptr;
   4151   bool leftover_body = FALSE;
   4152 
   4153   /* header line within buffer loop */
   4154   *pconsumed = 0;
   4155   while(blen && k->header) {
   4156     size_t consumed;
   4157 
   4158     end_ptr = memchr(buf, '\n', blen);
   4159     if(!end_ptr) {
   4160       /* Not a complete header line within buffer, append the data to
   4161          the end of the headerbuff. */
   4162       result = curlx_dyn_addn(&data->state.headerb, buf, blen);
   4163       if(result)
   4164         return result;
   4165       *pconsumed += blen;
   4166 
   4167       if(!k->headerline) {
   4168         /* check if this looks like a protocol header */
   4169         statusline st =
   4170           checkprotoprefix(data, conn,
   4171                            curlx_dyn_ptr(&data->state.headerb),
   4172                            curlx_dyn_len(&data->state.headerb));
   4173 
   4174         if(st == STATUS_BAD) {
   4175           /* this is not the beginning of a protocol first header line.
   4176            * Cannot be 0.9 if version was detected or connection was reused. */
   4177           k->header = FALSE;
   4178           streamclose(conn, "bad HTTP: No end-of-message indicator");
   4179           if((k->httpversion >= 10) || conn->bits.reuse) {
   4180             failf(data, "Invalid status line");
   4181             return CURLE_WEIRD_SERVER_REPLY;
   4182           }
   4183           if(!data->state.http_neg.accept_09) {
   4184             failf(data, "Received HTTP/0.9 when not allowed");
   4185             return CURLE_UNSUPPORTED_PROTOCOL;
   4186           }
   4187           leftover_body = TRUE;
   4188           goto out;
   4189         }
   4190       }
   4191       goto out; /* read more and try again */
   4192     }
   4193 
   4194     /* decrease the size of the remaining (supposed) header line */
   4195     consumed = (end_ptr - buf) + 1;
   4196     result = curlx_dyn_addn(&data->state.headerb, buf, consumed);
   4197     if(result)
   4198       return result;
   4199     blen -= consumed;
   4200     buf += consumed;
   4201     *pconsumed += consumed;
   4202 
   4203     /****
   4204      * We now have a FULL header line in 'headerb'.
   4205      *****/
   4206 
   4207     if(!k->headerline) {
   4208       /* the first read header */
   4209       statusline st = checkprotoprefix(data, conn,
   4210                                        curlx_dyn_ptr(&data->state.headerb),
   4211                                        curlx_dyn_len(&data->state.headerb));
   4212       if(st == STATUS_BAD) {
   4213         streamclose(conn, "bad HTTP: No end-of-message indicator");
   4214         /* this is not the beginning of a protocol first header line.
   4215          * Cannot be 0.9 if version was detected or connection was reused. */
   4216         if((k->httpversion >= 10) || conn->bits.reuse) {
   4217           failf(data, "Invalid status line");
   4218           return CURLE_WEIRD_SERVER_REPLY;
   4219         }
   4220         if(!data->state.http_neg.accept_09) {
   4221           failf(data, "Received HTTP/0.9 when not allowed");
   4222           return CURLE_UNSUPPORTED_PROTOCOL;
   4223         }
   4224         k->header = FALSE;
   4225         leftover_body = TRUE;
   4226         goto out;
   4227       }
   4228     }
   4229 
   4230     result = http_rw_hd(data, curlx_dyn_ptr(&data->state.headerb),
   4231                         curlx_dyn_len(&data->state.headerb),
   4232                         buf, blen, &consumed);
   4233     /* We are done with this line. We reset because response
   4234      * processing might switch to HTTP/2 and that might call us
   4235      * directly again. */
   4236     curlx_dyn_reset(&data->state.headerb);
   4237     if(consumed) {
   4238       blen -= consumed;
   4239       buf += consumed;
   4240       *pconsumed += consumed;
   4241     }
   4242     if(result)
   4243       return result;
   4244   }
   4245 
   4246   /* We might have reached the end of the header part here, but
   4247      there might be a non-header part left in the end of the read
   4248      buffer. */
   4249 out:
   4250   if(!k->header && !leftover_body) {
   4251     curlx_dyn_free(&data->state.headerb);
   4252   }
   4253   return CURLE_OK;
   4254 }
   4255 
   4256 CURLcode Curl_http_write_resp_hd(struct Curl_easy *data,
   4257                                  const char *hd, size_t hdlen,
   4258                                  bool is_eos)
   4259 {
   4260   CURLcode result;
   4261   size_t consumed;
   4262   char tmp = 0;
   4263 
   4264   result = http_rw_hd(data, hd, hdlen, &tmp, 0, &consumed);
   4265   if(!result && is_eos) {
   4266     result = Curl_client_write(data, (CLIENTWRITE_BODY|CLIENTWRITE_EOS),
   4267                                &tmp, 0);
   4268   }
   4269   return result;
   4270 }
   4271 
   4272 /*
   4273  * HTTP protocol `write_resp` implementation. Will parse headers
   4274  * when not done yet and otherwise return without consuming data.
   4275  */
   4276 CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
   4277                                   const char *buf, size_t blen,
   4278                                   size_t *pconsumed)
   4279 {
   4280   if(!data->req.header) {
   4281     *pconsumed = 0;
   4282     return CURLE_OK;
   4283   }
   4284   else {
   4285     CURLcode result;
   4286 
   4287     result = http_parse_headers(data, buf, blen, pconsumed);
   4288     if(!result && !data->req.header) {
   4289       if(!data->req.no_body && curlx_dyn_len(&data->state.headerb)) {
   4290         /* leftover from parsing something that turned out not
   4291          * to be a header, only happens if we allow for
   4292          * HTTP/0.9 like responses */
   4293         result = Curl_client_write(data, CLIENTWRITE_BODY,
   4294                                    curlx_dyn_ptr(&data->state.headerb),
   4295                                    curlx_dyn_len(&data->state.headerb));
   4296       }
   4297       curlx_dyn_free(&data->state.headerb);
   4298     }
   4299     return result;
   4300   }
   4301 }
   4302 
   4303 CURLcode Curl_http_write_resp(struct Curl_easy *data,
   4304                               const char *buf, size_t blen,
   4305                               bool is_eos)
   4306 {
   4307   CURLcode result;
   4308   size_t consumed;
   4309   int flags;
   4310 
   4311   result = Curl_http_write_resp_hds(data, buf, blen, &consumed);
   4312   if(result || data->req.done)
   4313     goto out;
   4314 
   4315   DEBUGASSERT(consumed <= blen);
   4316   blen -= consumed;
   4317   buf += consumed;
   4318   /* either all was consumed in header parsing, or we have data left
   4319    * and are done with headers, e.g. it is BODY data */
   4320   DEBUGASSERT(!blen || !data->req.header);
   4321   if(!data->req.header && (blen || is_eos)) {
   4322     /* BODY data after header been parsed, write and consume */
   4323     flags = CLIENTWRITE_BODY;
   4324     if(is_eos)
   4325       flags |= CLIENTWRITE_EOS;
   4326     result = Curl_client_write(data, flags, buf, blen);
   4327   }
   4328 out:
   4329   return result;
   4330 }
   4331 
   4332 /* Decode HTTP status code string. */
   4333 CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
   4334 {
   4335   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
   4336   int status = 0;
   4337   int i;
   4338 
   4339   if(len != 3)
   4340     goto out;
   4341 
   4342   for(i = 0; i < 3; ++i) {
   4343     char c = s[i];
   4344 
   4345     if(c < '0' || c > '9')
   4346       goto out;
   4347 
   4348     status *= 10;
   4349     status += c - '0';
   4350   }
   4351   result = CURLE_OK;
   4352 out:
   4353   *pstatus = result ? -1 : status;
   4354   return result;
   4355 }
   4356 
   4357 CURLcode Curl_http_req_make(struct httpreq **preq,
   4358                             const char *method, size_t m_len,
   4359                             const char *scheme, size_t s_len,
   4360                             const char *authority, size_t a_len,
   4361                             const char *path, size_t p_len)
   4362 {
   4363   struct httpreq *req;
   4364   CURLcode result = CURLE_OUT_OF_MEMORY;
   4365 
   4366   DEBUGASSERT(method && m_len);
   4367 
   4368   req = calloc(1, sizeof(*req) + m_len);
   4369   if(!req)
   4370     goto out;
   4371   memcpy(req->method, method, m_len);
   4372   if(scheme) {
   4373     req->scheme = Curl_memdup0(scheme, s_len);
   4374     if(!req->scheme)
   4375       goto out;
   4376   }
   4377   if(authority) {
   4378     req->authority = Curl_memdup0(authority, a_len);
   4379     if(!req->authority)
   4380       goto out;
   4381   }
   4382   if(path) {
   4383     req->path = Curl_memdup0(path, p_len);
   4384     if(!req->path)
   4385       goto out;
   4386   }
   4387   Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
   4388   Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
   4389   result = CURLE_OK;
   4390 
   4391 out:
   4392   if(result && req)
   4393     Curl_http_req_free(req);
   4394   *preq = result ? NULL : req;
   4395   return result;
   4396 }
   4397 
   4398 static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url)
   4399 {
   4400   char *user, *pass, *host, *port;
   4401   struct dynbuf buf;
   4402   CURLUcode uc;
   4403   CURLcode result = CURLE_URL_MALFORMAT;
   4404 
   4405   user = pass = host = port = NULL;
   4406   curlx_dyn_init(&buf, DYN_HTTP_REQUEST);
   4407 
   4408   uc = curl_url_get(url, CURLUPART_HOST, &host, 0);
   4409   if(uc && uc != CURLUE_NO_HOST)
   4410     goto out;
   4411   if(!host) {
   4412     req->authority = NULL;
   4413     result = CURLE_OK;
   4414     goto out;
   4415   }
   4416 
   4417   uc = curl_url_get(url, CURLUPART_PORT, &port, CURLU_NO_DEFAULT_PORT);
   4418   if(uc && uc != CURLUE_NO_PORT)
   4419     goto out;
   4420   uc = curl_url_get(url, CURLUPART_USER, &user, 0);
   4421   if(uc && uc != CURLUE_NO_USER)
   4422     goto out;
   4423   if(user) {
   4424     uc = curl_url_get(url, CURLUPART_PASSWORD, &pass, 0);
   4425     if(uc && uc != CURLUE_NO_PASSWORD)
   4426       goto out;
   4427   }
   4428 
   4429   if(user) {
   4430     result = curlx_dyn_add(&buf, user);
   4431     if(result)
   4432       goto out;
   4433     if(pass) {
   4434       result = curlx_dyn_addf(&buf, ":%s", pass);
   4435       if(result)
   4436         goto out;
   4437     }
   4438     result = curlx_dyn_add(&buf, "@");
   4439     if(result)
   4440       goto out;
   4441   }
   4442   result = curlx_dyn_add(&buf, host);
   4443   if(result)
   4444     goto out;
   4445   if(port) {
   4446     result = curlx_dyn_addf(&buf, ":%s", port);
   4447     if(result)
   4448       goto out;
   4449   }
   4450   req->authority = strdup(curlx_dyn_ptr(&buf));
   4451   if(!req->authority)
   4452     goto out;
   4453   result = CURLE_OK;
   4454 
   4455 out:
   4456   free(user);
   4457   free(pass);
   4458   free(host);
   4459   free(port);
   4460   curlx_dyn_free(&buf);
   4461   return result;
   4462 }
   4463 
   4464 static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
   4465 {
   4466   char *path, *query;
   4467   struct dynbuf buf;
   4468   CURLUcode uc;
   4469   CURLcode result = CURLE_URL_MALFORMAT;
   4470 
   4471   path = query = NULL;
   4472   curlx_dyn_init(&buf, DYN_HTTP_REQUEST);
   4473 
   4474   uc = curl_url_get(url, CURLUPART_PATH, &path, CURLU_PATH_AS_IS);
   4475   if(uc)
   4476     goto out;
   4477   uc = curl_url_get(url, CURLUPART_QUERY, &query, 0);
   4478   if(uc && uc != CURLUE_NO_QUERY)
   4479     goto out;
   4480 
   4481   if(!path && !query) {
   4482     req->path = NULL;
   4483   }
   4484   else if(path && !query) {
   4485     req->path = path;
   4486     path = NULL;
   4487   }
   4488   else {
   4489     if(path) {
   4490       result = curlx_dyn_add(&buf, path);
   4491       if(result)
   4492         goto out;
   4493     }
   4494     if(query) {
   4495       result = curlx_dyn_addf(&buf, "?%s", query);
   4496       if(result)
   4497         goto out;
   4498     }
   4499     req->path = strdup(curlx_dyn_ptr(&buf));
   4500     if(!req->path)
   4501       goto out;
   4502   }
   4503   result = CURLE_OK;
   4504 
   4505 out:
   4506   free(path);
   4507   free(query);
   4508   curlx_dyn_free(&buf);
   4509   return result;
   4510 }
   4511 
   4512 CURLcode Curl_http_req_make2(struct httpreq **preq,
   4513                              const char *method, size_t m_len,
   4514                              CURLU *url, const char *scheme_default)
   4515 {
   4516   struct httpreq *req;
   4517   CURLcode result = CURLE_OUT_OF_MEMORY;
   4518   CURLUcode uc;
   4519 
   4520   DEBUGASSERT(method && m_len);
   4521 
   4522   req = calloc(1, sizeof(*req) + m_len);
   4523   if(!req)
   4524     goto out;
   4525   memcpy(req->method, method, m_len);
   4526 
   4527   uc = curl_url_get(url, CURLUPART_SCHEME, &req->scheme, 0);
   4528   if(uc && uc != CURLUE_NO_SCHEME)
   4529     goto out;
   4530   if(!req->scheme && scheme_default) {
   4531     req->scheme = strdup(scheme_default);
   4532     if(!req->scheme)
   4533       goto out;
   4534   }
   4535 
   4536   result = req_assign_url_authority(req, url);
   4537   if(result)
   4538     goto out;
   4539   result = req_assign_url_path(req, url);
   4540   if(result)
   4541     goto out;
   4542 
   4543   Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
   4544   Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
   4545   result = CURLE_OK;
   4546 
   4547 out:
   4548   if(result && req)
   4549     Curl_http_req_free(req);
   4550   *preq = result ? NULL : req;
   4551   return result;
   4552 }
   4553 
   4554 void Curl_http_req_free(struct httpreq *req)
   4555 {
   4556   if(req) {
   4557     free(req->scheme);
   4558     free(req->authority);
   4559     free(req->path);
   4560     Curl_dynhds_free(&req->headers);
   4561     Curl_dynhds_free(&req->trailers);
   4562     free(req);
   4563   }
   4564 }
   4565 
   4566 struct name_const {
   4567   const char *name;
   4568   size_t namelen;
   4569 };
   4570 
   4571 /* keep them sorted by length! */
   4572 static struct name_const H2_NON_FIELD[] = {
   4573   { STRCONST("Host") },
   4574   { STRCONST("Upgrade") },
   4575   { STRCONST("Connection") },
   4576   { STRCONST("Keep-Alive") },
   4577   { STRCONST("Proxy-Connection") },
   4578   { STRCONST("Transfer-Encoding") },
   4579 };
   4580 
   4581 static bool h2_permissible_field(struct dynhds_entry *e)
   4582 {
   4583   size_t i;
   4584   for(i = 0; i < CURL_ARRAYSIZE(H2_NON_FIELD); ++i) {
   4585     if(e->namelen < H2_NON_FIELD[i].namelen)
   4586       return TRUE;
   4587     if(e->namelen == H2_NON_FIELD[i].namelen &&
   4588        curl_strequal(H2_NON_FIELD[i].name, e->name))
   4589       return FALSE;
   4590   }
   4591   return TRUE;
   4592 }
   4593 
   4594 static bool http_TE_has_token(const char *fvalue, const char *token)
   4595 {
   4596   while(*fvalue) {
   4597     struct Curl_str name;
   4598 
   4599     /* skip to first token */
   4600     while(ISBLANK(*fvalue) || *fvalue == ',')
   4601       fvalue++;
   4602     if(curlx_str_cspn(&fvalue, &name, " \t\r;,"))
   4603       return FALSE;
   4604     if(curlx_str_casecompare(&name, token))
   4605       return TRUE;
   4606 
   4607     /* skip any remainder after token, e.g. parameters with quoted strings */
   4608     while(*fvalue && *fvalue != ',') {
   4609       if(*fvalue == '"') {
   4610         struct Curl_str qw;
   4611         /* if we do not cleanly find a quoted word here, the header value
   4612          * does not follow HTTP syntax and we reject */
   4613         if(curlx_str_quotedword(&fvalue, &qw, CURL_MAX_HTTP_HEADER))
   4614           return FALSE;
   4615       }
   4616       else
   4617         fvalue++;
   4618     }
   4619   }
   4620   return FALSE;
   4621 }
   4622 
   4623 CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
   4624                              struct httpreq *req, struct Curl_easy *data)
   4625 {
   4626   const char *scheme = NULL, *authority = NULL;
   4627   struct dynhds_entry *e;
   4628   size_t i;
   4629   CURLcode result;
   4630 
   4631   DEBUGASSERT(req);
   4632   DEBUGASSERT(h2_headers);
   4633 
   4634   if(req->scheme) {
   4635     scheme = req->scheme;
   4636   }
   4637   else if(strcmp("CONNECT", req->method)) {
   4638     scheme = Curl_checkheaders(data, STRCONST(HTTP_PSEUDO_SCHEME));
   4639     if(scheme) {
   4640       scheme += sizeof(HTTP_PSEUDO_SCHEME);
   4641       curlx_str_passblanks(&scheme);
   4642       infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
   4643     }
   4644     else {
   4645       scheme = Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ?
   4646         "https" : "http";
   4647     }
   4648   }
   4649 
   4650   if(req->authority) {
   4651     authority = req->authority;
   4652   }
   4653   else {
   4654     e = Curl_dynhds_get(&req->headers, STRCONST("Host"));
   4655     if(e)
   4656       authority = e->value;
   4657   }
   4658 
   4659   Curl_dynhds_reset(h2_headers);
   4660   Curl_dynhds_set_opts(h2_headers, DYNHDS_OPT_LOWERCASE);
   4661   result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_METHOD),
   4662                            req->method, strlen(req->method));
   4663   if(!result && scheme) {
   4664     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_SCHEME),
   4665                              scheme, strlen(scheme));
   4666   }
   4667   if(!result && authority) {
   4668     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_AUTHORITY),
   4669                              authority, strlen(authority));
   4670   }
   4671   if(!result && req->path) {
   4672     result = Curl_dynhds_add(h2_headers, STRCONST(HTTP_PSEUDO_PATH),
   4673                              req->path, strlen(req->path));
   4674   }
   4675   for(i = 0; !result && i < Curl_dynhds_count(&req->headers); ++i) {
   4676     e = Curl_dynhds_getn(&req->headers, i);
   4677     /* "TE" is special in that it is only permissible when it
   4678      * has only value "trailers". RFC 9113 ch. 8.2.2 */
   4679     if(e->namelen == 2 && curl_strequal("TE", e->name)) {
   4680       if(http_TE_has_token(e->value, "trailers"))
   4681         result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
   4682                                  "trailers", sizeof("trailers") - 1);
   4683     }
   4684     else if(h2_permissible_field(e)) {
   4685       result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
   4686                                e->value, e->valuelen);
   4687     }
   4688   }
   4689 
   4690   return result;
   4691 }
   4692 
   4693 CURLcode Curl_http_resp_make(struct http_resp **presp,
   4694                              int status,
   4695                              const char *description)
   4696 {
   4697   struct http_resp *resp;
   4698   CURLcode result = CURLE_OUT_OF_MEMORY;
   4699 
   4700   resp = calloc(1, sizeof(*resp));
   4701   if(!resp)
   4702     goto out;
   4703 
   4704   resp->status = status;
   4705   if(description) {
   4706     resp->description = strdup(description);
   4707     if(!resp->description)
   4708       goto out;
   4709   }
   4710   Curl_dynhds_init(&resp->headers, 0, DYN_HTTP_REQUEST);
   4711   Curl_dynhds_init(&resp->trailers, 0, DYN_HTTP_REQUEST);
   4712   result = CURLE_OK;
   4713 
   4714 out:
   4715   if(result && resp)
   4716     Curl_http_resp_free(resp);
   4717   *presp = result ? NULL : resp;
   4718   return result;
   4719 }
   4720 
   4721 void Curl_http_resp_free(struct http_resp *resp)
   4722 {
   4723   if(resp) {
   4724     free(resp->description);
   4725     Curl_dynhds_free(&resp->headers);
   4726     Curl_dynhds_free(&resp->trailers);
   4727     if(resp->prev)
   4728       Curl_http_resp_free(resp->prev);
   4729     free(resp);
   4730   }
   4731 }
   4732 
   4733 struct cr_exp100_ctx {
   4734   struct Curl_creader super;
   4735   struct curltime start; /* time started waiting */
   4736   enum expect100 state;
   4737 };
   4738 
   4739 /* Expect: 100-continue client reader, blocking uploads */
   4740 
   4741 static void http_exp100_continue(struct Curl_easy *data,
   4742                                  struct Curl_creader *reader)
   4743 {
   4744   struct cr_exp100_ctx *ctx = reader->ctx;
   4745   if(ctx->state > EXP100_SEND_DATA) {
   4746     ctx->state = EXP100_SEND_DATA;
   4747     data->req.keepon |= KEEP_SEND;
   4748     data->req.keepon &= ~KEEP_SEND_TIMED;
   4749     Curl_expire_done(data, EXPIRE_100_TIMEOUT);
   4750   }
   4751 }
   4752 
   4753 static CURLcode cr_exp100_read(struct Curl_easy *data,
   4754                                struct Curl_creader *reader,
   4755                                char *buf, size_t blen,
   4756                                size_t *nread, bool *eos)
   4757 {
   4758   struct cr_exp100_ctx *ctx = reader->ctx;
   4759   timediff_t ms;
   4760 
   4761   switch(ctx->state) {
   4762   case EXP100_SENDING_REQUEST:
   4763     if(!Curl_req_sendbuf_empty(data)) {
   4764       /* The initial request data has not been fully sent yet. Do
   4765        * not start the timer yet. */
   4766       DEBUGF(infof(data, "cr_exp100_read, request not full sent yet"));
   4767       *nread = 0;
   4768       *eos = FALSE;
   4769       return CURLE_OK;
   4770     }
   4771     /* We are now waiting for a reply from the server or
   4772      * a timeout on our side IFF the request has been fully sent. */
   4773     DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, "
   4774            "timeout %ldms", data->set.expect_100_timeout));
   4775     ctx->state = EXP100_AWAITING_CONTINUE;
   4776     ctx->start = curlx_now();
   4777     Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
   4778     data->req.keepon &= ~KEEP_SEND;
   4779     data->req.keepon |= KEEP_SEND_TIMED;
   4780     *nread = 0;
   4781     *eos = FALSE;
   4782     return CURLE_OK;
   4783   case EXP100_FAILED:
   4784     DEBUGF(infof(data, "cr_exp100_read, expectation failed, error"));
   4785     *nread = 0;
   4786     *eos = FALSE;
   4787     return CURLE_READ_ERROR;
   4788   case EXP100_AWAITING_CONTINUE:
   4789     ms = curlx_timediff(curlx_now(), ctx->start);
   4790     if(ms < data->set.expect_100_timeout) {
   4791       DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired"));
   4792       data->req.keepon &= ~KEEP_SEND;
   4793       data->req.keepon |= KEEP_SEND_TIMED;
   4794       *nread = 0;
   4795       *eos = FALSE;
   4796       return CURLE_OK;
   4797     }
   4798     /* we have waited long enough, continue anyway */
   4799     http_exp100_continue(data, reader);
   4800     infof(data, "Done waiting for 100-continue");
   4801     FALLTHROUGH();
   4802   default:
   4803     DEBUGF(infof(data, "cr_exp100_read, pass through"));
   4804     return Curl_creader_read(data, reader->next, buf, blen, nread, eos);
   4805   }
   4806 }
   4807 
   4808 static void cr_exp100_done(struct Curl_easy *data,
   4809                            struct Curl_creader *reader, int premature)
   4810 {
   4811   struct cr_exp100_ctx *ctx = reader->ctx;
   4812   ctx->state = premature ? EXP100_FAILED : EXP100_SEND_DATA;
   4813   data->req.keepon &= ~KEEP_SEND_TIMED;
   4814   Curl_expire_done(data, EXPIRE_100_TIMEOUT);
   4815 }
   4816 
   4817 static const struct Curl_crtype cr_exp100 = {
   4818   "cr-exp100",
   4819   Curl_creader_def_init,
   4820   cr_exp100_read,
   4821   Curl_creader_def_close,
   4822   Curl_creader_def_needs_rewind,
   4823   Curl_creader_def_total_length,
   4824   Curl_creader_def_resume_from,
   4825   Curl_creader_def_rewind,
   4826   Curl_creader_def_unpause,
   4827   Curl_creader_def_is_paused,
   4828   cr_exp100_done,
   4829   sizeof(struct cr_exp100_ctx)
   4830 };
   4831 
   4832 static CURLcode http_exp100_add_reader(struct Curl_easy *data)
   4833 {
   4834   struct Curl_creader *reader = NULL;
   4835   CURLcode result;
   4836 
   4837   result = Curl_creader_create(&reader, data, &cr_exp100,
   4838                                CURL_CR_PROTOCOL);
   4839   if(!result)
   4840     result = Curl_creader_add(data, reader);
   4841   if(!result) {
   4842     struct cr_exp100_ctx *ctx = reader->ctx;
   4843     ctx->state = EXP100_SENDING_REQUEST;
   4844   }
   4845 
   4846   if(result && reader)
   4847     Curl_creader_free(data, reader);
   4848   return result;
   4849 }
   4850 
   4851 static void http_exp100_got100(struct Curl_easy *data)
   4852 {
   4853   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
   4854   if(r)
   4855     http_exp100_continue(data, r);
   4856 }
   4857 
   4858 static bool http_exp100_is_waiting(struct Curl_easy *data)
   4859 {
   4860   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
   4861   if(r) {
   4862     struct cr_exp100_ctx *ctx = r->ctx;
   4863     return ctx->state == EXP100_AWAITING_CONTINUE;
   4864   }
   4865   return FALSE;
   4866 }
   4867 
   4868 static void http_exp100_send_anyway(struct Curl_easy *data)
   4869 {
   4870   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
   4871   if(r)
   4872     http_exp100_continue(data, r);
   4873 }
   4874 
   4875 static bool http_exp100_is_selected(struct Curl_easy *data)
   4876 {
   4877   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
   4878   return !!r;
   4879 }
   4880 
   4881 #endif /* CURL_DISABLE_HTTP */