source: UsbWattMeter/trunk/curl-7.47.1/lib/http.c

Last change on this file was 167, checked in by coas-nagasima, 8 years ago

MIMEにSJISを設定

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