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