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 */