VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/http.c@ 99040

最後變更 在這個檔案從99040是 98326,由 vboxsync 提交於 2 年 前

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette