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