comparison mupdf-source/thirdparty/curl/lib/http.c @ 2:b50eed0cc0ef upstream

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