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