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