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