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