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