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