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