source: EcnlProtoTool/trunk/curl-7.57.0/lib/http.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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