1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #ifndef CURL_DISABLE_HTTP
26 
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NET_IF_H
38 #include <net/if.h>
39 #endif
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 
44 #ifdef HAVE_SYS_PARAM_H
45 #include <sys/param.h>
46 #endif
47 
48 #include "urldata.h"
49 #include <curl/curl.h>
50 #include "transfer.h"
51 #include "sendf.h"
52 #include "formdata.h"
53 #include "mime.h"
54 #include "progress.h"
55 #include "curl_base64.h"
56 #include "cookie.h"
57 #include "vauth/vauth.h"
58 #include "vtls/vtls.h"
59 #include "http_digest.h"
60 #include "http_ntlm.h"
61 #include "curl_ntlm_wb.h"
62 #include "http_negotiate.h"
63 #include "url.h"
64 #include "share.h"
65 #include "hostip.h"
66 #include "http.h"
67 #include "select.h"
68 #include "parsedate.h" /* for the week day and month names */
69 #include "strtoofft.h"
70 #include "multiif.h"
71 #include "strcase.h"
72 #include "content_encoding.h"
73 #include "http_proxy.h"
74 #include "warnless.h"
75 #include "non-ascii.h"
76 #include "http2.h"
77 #include "connect.h"
78 #include "strdup.h"
79 #include "altsvc.h"
80 
81 /* The last 3 #include files should be in this order */
82 #include "curl_printf.h"
83 #include "curl_memory.h"
84 #include "memdebug.h"
85 
86 /*
87  * Forward declarations.
88  */
89 
90 static int http_getsock_do(struct connectdata *conn,
91                            curl_socket_t *socks);
92 static int http_should_fail(struct connectdata *conn);
93 
94 #ifndef CURL_DISABLE_PROXY
95 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
96 #endif
97 
98 #ifdef USE_SSL
99 static CURLcode https_connecting(struct connectdata *conn, bool *done);
100 static int https_getsock(struct connectdata *conn,
101                          curl_socket_t *socks);
102 #else
103 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
104 #endif
105 static CURLcode http_setup_conn(struct connectdata *conn);
106 
107 /*
108  * HTTP handler interface.
109  */
110 const struct Curl_handler Curl_handler_http = {
111   "HTTP",                               /* scheme */
112   http_setup_conn,                      /* setup_connection */
113   Curl_http,                            /* do_it */
114   Curl_http_done,                       /* done */
115   ZERO_NULL,                            /* do_more */
116   Curl_http_connect,                    /* connect_it */
117   ZERO_NULL,                            /* connecting */
118   ZERO_NULL,                            /* doing */
119   ZERO_NULL,                            /* proto_getsock */
120   http_getsock_do,                      /* doing_getsock */
121   ZERO_NULL,                            /* domore_getsock */
122   ZERO_NULL,                            /* perform_getsock */
123   ZERO_NULL,                            /* disconnect */
124   ZERO_NULL,                            /* readwrite */
125   ZERO_NULL,                            /* connection_check */
126   PORT_HTTP,                            /* defport */
127   CURLPROTO_HTTP,                       /* protocol */
128   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)
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(data, premature);
1621   Curl_quic_done(data, premature);
1622 
1623   Curl_mime_cleanpart(&http->form);
1624 
1625   if(status)
1626     return status;
1627 
1628   if(!premature && /* this check is pointless when DONE is called before the
1629                       entire operation is complete */
1630      !conn->bits.retry &&
1631      !data->set.connect_only &&
1632      (data->req.bytecount +
1633       data->req.headerbytecount -
1634       data->req.deductheadercount) <= 0) {
1635     /* If this connection isn't simply closed to be retried, AND nothing was
1636        read from the HTTP server (that counts), this can't be right so we
1637        return an error here */
1638     failf(data, "Empty reply from server");
1639     return CURLE_GOT_NOTHING;
1640   }
1641 
1642   return CURLE_OK;
1643 }
1644 
1645 /*
1646  * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1647  * to avoid it include:
1648  *
1649  * - if the user specifically requested HTTP 1.0
1650  * - if the server we are connected to only supports 1.0
1651  * - if any server previously contacted to handle this request only supports
1652  * 1.0.
1653  */
use_http_1_1plus(const struct Curl_easy * data,const struct connectdata * conn)1654 static bool use_http_1_1plus(const struct Curl_easy *data,
1655                              const struct connectdata *conn)
1656 {
1657   if((data->state.httpversion == 10) || (conn->httpversion == 10))
1658     return FALSE;
1659   if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
1660      (conn->httpversion <= 10))
1661     return FALSE;
1662   return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
1663           (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
1664 }
1665 
get_http_string(const struct Curl_easy * data,const struct connectdata * conn)1666 static const char *get_http_string(const struct Curl_easy *data,
1667                                    const struct connectdata *conn)
1668 {
1669 #ifdef ENABLE_QUIC
1670   if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
1671      (conn->httpversion == 30))
1672     return "3";
1673 #endif
1674 
1675 #ifdef USE_NGHTTP2
1676   if(conn->proto.httpc.h2)
1677     return "2";
1678 #endif
1679 
1680   if(use_http_1_1plus(data, conn))
1681     return "1.1";
1682 
1683   return "1.0";
1684 }
1685 
1686 /* check and possibly add an Expect: header */
expect100(struct Curl_easy * data,struct connectdata * conn,Curl_send_buffer * req_buffer)1687 static CURLcode expect100(struct Curl_easy *data,
1688                           struct connectdata *conn,
1689                           Curl_send_buffer *req_buffer)
1690 {
1691   CURLcode result = CURLE_OK;
1692   data->state.expect100header = FALSE; /* default to false unless it is set
1693                                           to TRUE below */
1694   if(use_http_1_1plus(data, conn) &&
1695      (conn->httpversion < 20)) {
1696     /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
1697        Expect: 100-continue to the headers which actually speeds up post
1698        operations (as there is one packet coming back from the web server) */
1699     const char *ptr = Curl_checkheaders(conn, "Expect");
1700     if(ptr) {
1701       data->state.expect100header =
1702         Curl_compareheader(ptr, "Expect:", "100-continue");
1703     }
1704     else {
1705       result = Curl_add_bufferf(&req_buffer,
1706                                 "Expect: 100-continue\r\n");
1707       if(!result)
1708         data->state.expect100header = TRUE;
1709     }
1710   }
1711 
1712   return result;
1713 }
1714 
1715 enum proxy_use {
1716   HEADER_SERVER,  /* direct to server */
1717   HEADER_PROXY,   /* regular request to proxy */
1718   HEADER_CONNECT  /* sending CONNECT to a proxy */
1719 };
1720 
1721 /* used to compile the provided trailers into one buffer
1722    will return an error code if one of the headers is
1723    not formatted correctly */
Curl_http_compile_trailers(struct curl_slist * trailers,Curl_send_buffer ** buffer,struct Curl_easy * handle)1724 CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
1725                                     Curl_send_buffer **buffer,
1726                                     struct Curl_easy *handle)
1727 {
1728   char *ptr = NULL;
1729   CURLcode result = CURLE_OK;
1730   const char *endofline_native = NULL;
1731   const char *endofline_network = NULL;
1732 
1733   if(
1734 #ifdef CURL_DO_LINEEND_CONV
1735      (handle->set.prefer_ascii) ||
1736 #endif
1737      (handle->set.crlf)) {
1738     /* \n will become \r\n later on */
1739     endofline_native  = "\n";
1740     endofline_network = "\x0a";
1741   }
1742   else {
1743     endofline_native  = "\r\n";
1744     endofline_network = "\x0d\x0a";
1745   }
1746 
1747   while(trailers) {
1748     /* only add correctly formatted trailers */
1749     ptr = strchr(trailers->data, ':');
1750     if(ptr && *(ptr + 1) == ' ') {
1751       result = Curl_add_bufferf(buffer, "%s%s", trailers->data,
1752                                 endofline_native);
1753       if(result)
1754         return result;
1755     }
1756     else
1757       infof(handle, "Malformatted trailing header ! Skipping trailer.");
1758     trailers = trailers->next;
1759   }
1760   result = Curl_add_buffer(buffer, endofline_network,
1761                            strlen(endofline_network));
1762   return result;
1763 }
1764 
Curl_add_custom_headers(struct connectdata * conn,bool is_connect,Curl_send_buffer * req_buffer)1765 CURLcode Curl_add_custom_headers(struct connectdata *conn,
1766                                  bool is_connect,
1767                                  Curl_send_buffer *req_buffer)
1768 {
1769   char *ptr;
1770   struct curl_slist *h[2];
1771   struct curl_slist *headers;
1772   int numlists = 1; /* by default */
1773   struct Curl_easy *data = conn->data;
1774   int i;
1775 
1776   enum proxy_use proxy;
1777 
1778   if(is_connect)
1779     proxy = HEADER_CONNECT;
1780   else
1781     proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
1782       HEADER_PROXY:HEADER_SERVER;
1783 
1784   switch(proxy) {
1785   case HEADER_SERVER:
1786     h[0] = data->set.headers;
1787     break;
1788   case HEADER_PROXY:
1789     h[0] = data->set.headers;
1790     if(data->set.sep_headers) {
1791       h[1] = data->set.proxyheaders;
1792       numlists++;
1793     }
1794     break;
1795   case HEADER_CONNECT:
1796     if(data->set.sep_headers)
1797       h[0] = data->set.proxyheaders;
1798     else
1799       h[0] = data->set.headers;
1800     break;
1801   }
1802 
1803   /* loop through one or two lists */
1804   for(i = 0; i < numlists; i++) {
1805     headers = h[i];
1806 
1807     while(headers) {
1808       char *semicolonp = NULL;
1809       ptr = strchr(headers->data, ':');
1810       if(!ptr) {
1811         char *optr;
1812         /* no colon, semicolon? */
1813         ptr = strchr(headers->data, ';');
1814         if(ptr) {
1815           optr = ptr;
1816           ptr++; /* pass the semicolon */
1817           while(*ptr && ISSPACE(*ptr))
1818             ptr++;
1819 
1820           if(*ptr) {
1821             /* this may be used for something else in the future */
1822             optr = NULL;
1823           }
1824           else {
1825             if(*(--ptr) == ';') {
1826               /* copy the source */
1827               semicolonp = strdup(headers->data);
1828               if(!semicolonp) {
1829                 Curl_add_buffer_free(&req_buffer);
1830                 return CURLE_OUT_OF_MEMORY;
1831               }
1832               /* put a colon where the semicolon is */
1833               semicolonp[ptr - headers->data] = ':';
1834               /* point at the colon */
1835               optr = &semicolonp [ptr - headers->data];
1836             }
1837           }
1838           ptr = optr;
1839         }
1840       }
1841       if(ptr) {
1842         /* we require a colon for this to be a true header */
1843 
1844         ptr++; /* pass the colon */
1845         while(*ptr && ISSPACE(*ptr))
1846           ptr++;
1847 
1848         if(*ptr || semicolonp) {
1849           /* only send this if the contents was non-blank or done special */
1850           CURLcode result = CURLE_OK;
1851           char *compare = semicolonp ? semicolonp : headers->data;
1852 
1853           if(conn->allocptr.host &&
1854              /* a Host: header was sent already, don't pass on any custom Host:
1855                 header as that will produce *two* in the same request! */
1856              checkprefix("Host:", compare))
1857             ;
1858           else if(data->set.httpreq == HTTPREQ_POST_FORM &&
1859                   /* this header (extended by formdata.c) is sent later */
1860                   checkprefix("Content-Type:", compare))
1861             ;
1862           else if(data->set.httpreq == HTTPREQ_POST_MIME &&
1863                   /* this header is sent later */
1864                   checkprefix("Content-Type:", compare))
1865             ;
1866           else if(conn->bits.authneg &&
1867                   /* while doing auth neg, don't allow the custom length since
1868                      we will force length zero then */
1869                   checkprefix("Content-Length:", compare))
1870             ;
1871           else if(conn->allocptr.te &&
1872                   /* when asking for Transfer-Encoding, don't pass on a custom
1873                      Connection: */
1874                   checkprefix("Connection:", compare))
1875             ;
1876           else if((conn->httpversion >= 20) &&
1877                   checkprefix("Transfer-Encoding:", compare))
1878             /* HTTP/2 doesn't support chunked requests */
1879             ;
1880           else if((checkprefix("Authorization:", compare) ||
1881                    checkprefix("Cookie:", compare)) &&
1882                   /* be careful of sending this potentially sensitive header to
1883                      other hosts */
1884                   (data->state.this_is_a_follow &&
1885                    data->state.first_host &&
1886                    !data->set.allow_auth_to_other_hosts &&
1887                    !strcasecompare(data->state.first_host, conn->host.name)))
1888             ;
1889           else {
1890             result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare);
1891           }
1892           if(semicolonp)
1893             free(semicolonp);
1894           if(result)
1895             return result;
1896         }
1897       }
1898       headers = headers->next;
1899     }
1900   }
1901 
1902   return CURLE_OK;
1903 }
1904 
1905 #ifndef CURL_DISABLE_PARSEDATE
Curl_add_timecondition(const struct connectdata * conn,Curl_send_buffer * req_buffer)1906 CURLcode Curl_add_timecondition(const struct connectdata *conn,
1907                                 Curl_send_buffer *req_buffer)
1908 {
1909   struct Curl_easy *data = conn->data;
1910   const struct tm *tm;
1911   struct tm keeptime;
1912   CURLcode result;
1913   char datestr[80];
1914   const char *condp;
1915 
1916   if(data->set.timecondition == CURL_TIMECOND_NONE)
1917     /* no condition was asked for */
1918     return CURLE_OK;
1919 
1920   result = Curl_gmtime(data->set.timevalue, &keeptime);
1921   if(result) {
1922     failf(data, "Invalid TIMEVALUE");
1923     return result;
1924   }
1925   tm = &keeptime;
1926 
1927   switch(data->set.timecondition) {
1928   default:
1929     return CURLE_BAD_FUNCTION_ARGUMENT;
1930 
1931   case CURL_TIMECOND_IFMODSINCE:
1932     condp = "If-Modified-Since";
1933     break;
1934   case CURL_TIMECOND_IFUNMODSINCE:
1935     condp = "If-Unmodified-Since";
1936     break;
1937   case CURL_TIMECOND_LASTMOD:
1938     condp = "Last-Modified";
1939     break;
1940   }
1941 
1942   if(Curl_checkheaders(conn, condp)) {
1943     /* A custom header was specified; it will be sent instead. */
1944     return CURLE_OK;
1945   }
1946 
1947   /* The If-Modified-Since header family should have their times set in
1948    * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1949    * represented in Greenwich Mean Time (GMT), without exception. For the
1950    * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1951    * Time)." (see page 20 of RFC2616).
1952    */
1953 
1954   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
1955   msnprintf(datestr, sizeof(datestr),
1956             "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
1957             condp,
1958             Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
1959             tm->tm_mday,
1960             Curl_month[tm->tm_mon],
1961             tm->tm_year + 1900,
1962             tm->tm_hour,
1963             tm->tm_min,
1964             tm->tm_sec);
1965 
1966   result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
1967 
1968   return result;
1969 }
1970 #else
1971 /* disabled */
Curl_add_timecondition(const struct connectdata * conn,Curl_send_buffer * req_buffer)1972 CURLcode Curl_add_timecondition(const struct connectdata *conn,
1973                                 Curl_send_buffer *req_buffer)
1974 {
1975   (void)conn;
1976   (void)req_buffer;
1977   return CURLE_OK;
1978 }
1979 #endif
1980 
1981 /*
1982  * Curl_http() gets called from the generic multi_do() function when a HTTP
1983  * request is to be performed. This creates and sends a properly constructed
1984  * HTTP request.
1985  */
Curl_http(struct connectdata * conn,bool * done)1986 CURLcode Curl_http(struct connectdata *conn, bool *done)
1987 {
1988   struct Curl_easy *data = conn->data;
1989   CURLcode result = CURLE_OK;
1990   struct HTTP *http;
1991   const char *path = data->state.up.path;
1992   const char *query = data->state.up.query;
1993   bool paste_ftp_userpwd = FALSE;
1994   char ftp_typecode[sizeof("/;type=?")] = "";
1995   const char *host = conn->host.name;
1996   const char *te = ""; /* transfer-encoding */
1997   const char *ptr;
1998   const char *request;
1999   Curl_HttpReq httpreq = data->set.httpreq;
2000 #if !defined(CURL_DISABLE_COOKIES)
2001   char *addcookies = NULL;
2002 #endif
2003   curl_off_t included_body = 0;
2004   const char *httpstring;
2005   Curl_send_buffer *req_buffer;
2006   curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
2007   char *altused = NULL;
2008 
2009   /* Always consider the DO phase done after this function call, even if there
2010      may be parts of the request that is not yet sent, since we can deal with
2011      the rest of the request in the PERFORM phase. */
2012   *done = TRUE;
2013 
2014   if(conn->transport != TRNSPRT_QUIC) {
2015     if(conn->httpversion < 20) { /* unless the connection is re-used and
2016                                     already http2 */
2017       switch(conn->negnpn) {
2018       case CURL_HTTP_VERSION_2:
2019         conn->httpversion = 20; /* we know we're on HTTP/2 now */
2020 
2021         result = Curl_http2_switched(conn, NULL, 0);
2022         if(result)
2023           return result;
2024         break;
2025       case CURL_HTTP_VERSION_1_1:
2026         /* continue with HTTP/1.1 when explicitly requested */
2027         break;
2028       default:
2029         /* Check if user wants to use HTTP/2 with clear TCP*/
2030 #ifdef USE_NGHTTP2
2031         if(conn->data->set.httpversion ==
2032            CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
2033           if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2034             /* We don't support HTTP/2 proxies yet. Also it's debatable
2035                whether or not this setting should apply to HTTP/2 proxies. */
2036             infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
2037             break;
2038           }
2039 
2040           DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
2041           conn->httpversion = 20;
2042 
2043           result = Curl_http2_switched(conn, NULL, 0);
2044           if(result)
2045             return result;
2046         }
2047 #endif
2048         break;
2049       }
2050     }
2051     else {
2052       /* prepare for a http2 request */
2053       result = Curl_http2_setup(conn);
2054       if(result)
2055         return result;
2056     }
2057   }
2058   http = data->req.protop;
2059   DEBUGASSERT(http);
2060 
2061   if(!data->state.this_is_a_follow) {
2062     /* Free to avoid leaking memory on multiple requests*/
2063     free(data->state.first_host);
2064 
2065     data->state.first_host = strdup(conn->host.name);
2066     if(!data->state.first_host)
2067       return CURLE_OUT_OF_MEMORY;
2068 
2069     data->state.first_remote_port = conn->remote_port;
2070   }
2071 
2072   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
2073      data->set.upload) {
2074     httpreq = HTTPREQ_PUT;
2075   }
2076 
2077   /* Now set the 'request' pointer to the proper request string */
2078   if(data->set.str[STRING_CUSTOMREQUEST])
2079     request = data->set.str[STRING_CUSTOMREQUEST];
2080   else {
2081     if(data->set.opt_no_body)
2082       request = "HEAD";
2083     else {
2084       DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
2085       switch(httpreq) {
2086       case HTTPREQ_POST:
2087       case HTTPREQ_POST_FORM:
2088       case HTTPREQ_POST_MIME:
2089         request = "POST";
2090         break;
2091       case HTTPREQ_PUT:
2092         request = "PUT";
2093         break;
2094       case HTTPREQ_OPTIONS:
2095         request = "OPTIONS";
2096         break;
2097       default: /* this should never happen */
2098       case HTTPREQ_GET:
2099         request = "GET";
2100         break;
2101       case HTTPREQ_HEAD:
2102         request = "HEAD";
2103         break;
2104       }
2105     }
2106   }
2107 
2108   /* The User-Agent string might have been allocated in url.c already, because
2109      it might have been used in the proxy connect, but if we have got a header
2110      with the user-agent string specified, we erase the previously made string
2111      here. */
2112   if(Curl_checkheaders(conn, "User-Agent")) {
2113     free(conn->allocptr.uagent);
2114     conn->allocptr.uagent = NULL;
2115   }
2116 
2117   /* setup the authentication headers */
2118   {
2119     char *pq = NULL;
2120     if(query && *query) {
2121       pq = aprintf("%s?%s", path, query);
2122       if(!pq)
2123         return CURLE_OUT_OF_MEMORY;
2124     }
2125     result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
2126     free(pq);
2127     if(result)
2128       return result;
2129   }
2130 
2131   if(((data->state.authhost.multipass && !data->state.authhost.done)
2132       || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
2133      (httpreq != HTTPREQ_GET) &&
2134      (httpreq != HTTPREQ_HEAD)) {
2135     /* Auth is required and we are not authenticated yet. Make a PUT or POST
2136        with content-length zero as a "probe". */
2137     conn->bits.authneg = TRUE;
2138   }
2139   else
2140     conn->bits.authneg = FALSE;
2141 
2142   Curl_safefree(conn->allocptr.ref);
2143   if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
2144     conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
2145     if(!conn->allocptr.ref)
2146       return CURLE_OUT_OF_MEMORY;
2147   }
2148   else
2149     conn->allocptr.ref = NULL;
2150 
2151 #if !defined(CURL_DISABLE_COOKIES)
2152   if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
2153     addcookies = data->set.str[STRING_COOKIE];
2154 #endif
2155 
2156   if(!Curl_checkheaders(conn, "Accept-Encoding") &&
2157      data->set.str[STRING_ENCODING]) {
2158     Curl_safefree(conn->allocptr.accept_encoding);
2159     conn->allocptr.accept_encoding =
2160       aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
2161     if(!conn->allocptr.accept_encoding)
2162       return CURLE_OUT_OF_MEMORY;
2163   }
2164   else {
2165     Curl_safefree(conn->allocptr.accept_encoding);
2166     conn->allocptr.accept_encoding = NULL;
2167   }
2168 
2169 #ifdef HAVE_LIBZ
2170   /* we only consider transfer-encoding magic if libz support is built-in */
2171 
2172   if(!Curl_checkheaders(conn, "TE") &&
2173      data->set.http_transfer_encoding) {
2174     /* When we are to insert a TE: header in the request, we must also insert
2175        TE in a Connection: header, so we need to merge the custom provided
2176        Connection: header and prevent the original to get sent. Note that if
2177        the user has inserted his/hers own TE: header we don't do this magic
2178        but then assume that the user will handle it all! */
2179     char *cptr = Curl_checkheaders(conn, "Connection");
2180 #define TE_HEADER "TE: gzip\r\n"
2181 
2182     Curl_safefree(conn->allocptr.te);
2183 
2184     if(cptr) {
2185       cptr = Curl_copy_header_value(cptr);
2186       if(!cptr)
2187         return CURLE_OUT_OF_MEMORY;
2188     }
2189 
2190     /* Create the (updated) Connection: header */
2191     conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
2192                                 cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
2193 
2194     free(cptr);
2195     if(!conn->allocptr.te)
2196       return CURLE_OUT_OF_MEMORY;
2197   }
2198 #endif
2199 
2200   switch(httpreq) {
2201   case HTTPREQ_POST_MIME:
2202     http->sendit = &data->set.mimepost;
2203     break;
2204   case HTTPREQ_POST_FORM:
2205     /* Convert the form structure into a mime structure. */
2206     Curl_mime_cleanpart(&http->form);
2207     result = Curl_getformdata(data, &http->form, data->set.httppost,
2208                               data->state.fread_func);
2209     if(result)
2210       return result;
2211     http->sendit = &http->form;
2212     break;
2213   default:
2214     http->sendit = NULL;
2215   }
2216 
2217 #ifndef CURL_DISABLE_MIME
2218   if(http->sendit) {
2219     const char *cthdr = Curl_checkheaders(conn, "Content-Type");
2220 
2221     /* Read and seek body only. */
2222     http->sendit->flags |= MIME_BODY_ONLY;
2223 
2224     /* Prepare the mime structure headers & set content type. */
2225 
2226     if(cthdr)
2227       for(cthdr += 13; *cthdr == ' '; cthdr++)
2228         ;
2229     else if(http->sendit->kind == MIMEKIND_MULTIPART)
2230       cthdr = "multipart/form-data";
2231 
2232     curl_mime_headers(http->sendit, data->set.headers, 0);
2233     result = Curl_mime_prepare_headers(http->sendit, cthdr,
2234                                        NULL, MIMESTRATEGY_FORM);
2235     curl_mime_headers(http->sendit, NULL, 0);
2236     if(!result)
2237       result = Curl_mime_rewind(http->sendit);
2238     if(result)
2239       return result;
2240     http->postsize = Curl_mime_size(http->sendit);
2241   }
2242 #endif
2243 
2244   ptr = Curl_checkheaders(conn, "Transfer-Encoding");
2245   if(ptr) {
2246     /* Some kind of TE is requested, check if 'chunked' is chosen */
2247     data->req.upload_chunky =
2248       Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
2249   }
2250   else {
2251     if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
2252        (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
2253          http->postsize < 0) ||
2254         ((data->set.upload || httpreq == HTTPREQ_POST) &&
2255          data->state.infilesize == -1))) {
2256       if(conn->bits.authneg)
2257         /* don't enable chunked during auth neg */
2258         ;
2259       else if(use_http_1_1plus(data, conn)) {
2260         if(conn->httpversion < 20)
2261           /* HTTP, upload, unknown file size and not HTTP 1.0 */
2262           data->req.upload_chunky = TRUE;
2263       }
2264       else {
2265         failf(data, "Chunky upload is not supported by HTTP 1.0");
2266         return CURLE_UPLOAD_FAILED;
2267       }
2268     }
2269     else {
2270       /* else, no chunky upload */
2271       data->req.upload_chunky = FALSE;
2272     }
2273 
2274     if(data->req.upload_chunky)
2275       te = "Transfer-Encoding: chunked\r\n";
2276   }
2277 
2278   Curl_safefree(conn->allocptr.host);
2279 
2280   ptr = Curl_checkheaders(conn, "Host");
2281   if(ptr && (!data->state.this_is_a_follow ||
2282              strcasecompare(data->state.first_host, conn->host.name))) {
2283 #if !defined(CURL_DISABLE_COOKIES)
2284     /* If we have a given custom Host: header, we extract the host name in
2285        order to possibly use it for cookie reasons later on. We only allow the
2286        custom Host: header if this is NOT a redirect, as setting Host: in the
2287        redirected request is being out on thin ice. Except if the host name
2288        is the same as the first one! */
2289     char *cookiehost = Curl_copy_header_value(ptr);
2290     if(!cookiehost)
2291       return CURLE_OUT_OF_MEMORY;
2292     if(!*cookiehost)
2293       /* ignore empty data */
2294       free(cookiehost);
2295     else {
2296       /* If the host begins with '[', we start searching for the port after
2297          the bracket has been closed */
2298       if(*cookiehost == '[') {
2299         char *closingbracket;
2300         /* since the 'cookiehost' is an allocated memory area that will be
2301            freed later we cannot simply increment the pointer */
2302         memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
2303         closingbracket = strchr(cookiehost, ']');
2304         if(closingbracket)
2305           *closingbracket = 0;
2306       }
2307       else {
2308         int startsearch = 0;
2309         char *colon = strchr(cookiehost + startsearch, ':');
2310         if(colon)
2311           *colon = 0; /* The host must not include an embedded port number */
2312       }
2313       Curl_safefree(conn->allocptr.cookiehost);
2314       conn->allocptr.cookiehost = cookiehost;
2315     }
2316 #endif
2317 
2318     if(strcmp("Host:", ptr)) {
2319       conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
2320       if(!conn->allocptr.host)
2321         return CURLE_OUT_OF_MEMORY;
2322     }
2323     else
2324       /* when clearing the header */
2325       conn->allocptr.host = NULL;
2326   }
2327   else {
2328     /* When building Host: headers, we must put the host name within
2329        [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
2330 
2331     if(((conn->given->protocol&CURLPROTO_HTTPS) &&
2332         (conn->remote_port == PORT_HTTPS)) ||
2333        ((conn->given->protocol&CURLPROTO_HTTP) &&
2334         (conn->remote_port == PORT_HTTP)) )
2335       /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
2336          the port number in the host string */
2337       conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
2338                                     conn->bits.ipv6_ip?"[":"",
2339                                     host,
2340                                     conn->bits.ipv6_ip?"]":"");
2341     else
2342       conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
2343                                     conn->bits.ipv6_ip?"[":"",
2344                                     host,
2345                                     conn->bits.ipv6_ip?"]":"",
2346                                     conn->remote_port);
2347 
2348     if(!conn->allocptr.host)
2349       /* without Host: we can't make a nice request */
2350       return CURLE_OUT_OF_MEMORY;
2351   }
2352 
2353 #ifndef CURL_DISABLE_PROXY
2354   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2355     /* Using a proxy but does not tunnel through it */
2356 
2357     /* The path sent to the proxy is in fact the entire URL. But if the remote
2358        host is a IDN-name, we must make sure that the request we produce only
2359        uses the encoded host name! */
2360 
2361     /* and no fragment part */
2362     CURLUcode uc;
2363     CURLU *h = curl_url_dup(data->state.uh);
2364     if(!h)
2365       return CURLE_OUT_OF_MEMORY;
2366 
2367     if(conn->host.dispname != conn->host.name) {
2368       uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
2369       if(uc) {
2370         curl_url_cleanup(h);
2371         return CURLE_OUT_OF_MEMORY;
2372       }
2373     }
2374     uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
2375     if(uc) {
2376       curl_url_cleanup(h);
2377       return CURLE_OUT_OF_MEMORY;
2378     }
2379 
2380     if(strcasecompare("http", data->state.up.scheme)) {
2381       /* when getting HTTP, we don't want the userinfo the URL */
2382       uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
2383       if(uc) {
2384         curl_url_cleanup(h);
2385         return CURLE_OUT_OF_MEMORY;
2386       }
2387       uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
2388       if(uc) {
2389         curl_url_cleanup(h);
2390         return CURLE_OUT_OF_MEMORY;
2391       }
2392     }
2393     /* Extract the the URL to use in the request. Store in STRING_TEMP_URL for
2394        clean-up reasons if the function returns before the free() further
2395        down. */
2396     uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0);
2397     if(uc) {
2398       curl_url_cleanup(h);
2399       return CURLE_OUT_OF_MEMORY;
2400     }
2401 
2402     curl_url_cleanup(h);
2403 
2404     if(strcasecompare("ftp", data->state.up.scheme)) {
2405       if(data->set.proxy_transfer_mode) {
2406         /* when doing ftp, append ;type=<a|i> if not present */
2407         char *type = strstr(path, ";type=");
2408         if(type && type[6] && type[7] == 0) {
2409           switch(Curl_raw_toupper(type[6])) {
2410           case 'A':
2411           case 'D':
2412           case 'I':
2413             break;
2414           default:
2415             type = NULL;
2416           }
2417         }
2418         if(!type) {
2419           char *p = ftp_typecode;
2420           /* avoid sending invalid URLs like ftp://example.com;type=i if the
2421            * user specified ftp://example.com without the slash */
2422           if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
2423             *p++ = '/';
2424           }
2425           msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
2426                     data->set.prefer_ascii ? 'a' : 'i');
2427         }
2428       }
2429       if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
2430         paste_ftp_userpwd = TRUE;
2431     }
2432   }
2433 #endif /* CURL_DISABLE_PROXY */
2434 
2435   http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
2436 
2437   if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
2438      data->state.resume_from) {
2439     /**********************************************************************
2440      * Resuming upload in HTTP means that we PUT or POST and that we have
2441      * got a resume_from value set. The resume value has already created
2442      * a Range: header that will be passed along. We need to "fast forward"
2443      * the file the given number of bytes and decrease the assume upload
2444      * file size before we continue this venture in the dark lands of HTTP.
2445      * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
2446      *********************************************************************/
2447 
2448     if(data->state.resume_from < 0) {
2449       /*
2450        * This is meant to get the size of the present remote-file by itself.
2451        * We don't support this now. Bail out!
2452        */
2453       data->state.resume_from = 0;
2454     }
2455 
2456     if(data->state.resume_from && !data->state.this_is_a_follow) {
2457       /* do we still game? */
2458 
2459       /* Now, let's read off the proper amount of bytes from the
2460          input. */
2461       int seekerr = CURL_SEEKFUNC_CANTSEEK;
2462       if(conn->seek_func) {
2463         Curl_set_in_callback(data, true);
2464         seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2465                                   SEEK_SET);
2466         Curl_set_in_callback(data, false);
2467       }
2468 
2469       if(seekerr != CURL_SEEKFUNC_OK) {
2470         curl_off_t passed = 0;
2471 
2472         if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2473           failf(data, "Could not seek stream");
2474           return CURLE_READ_ERROR;
2475         }
2476         /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2477         do {
2478           size_t readthisamountnow =
2479             (data->state.resume_from - passed > data->set.buffer_size) ?
2480             (size_t)data->set.buffer_size :
2481             curlx_sotouz(data->state.resume_from - passed);
2482 
2483           size_t actuallyread =
2484             data->state.fread_func(data->state.buffer, 1, readthisamountnow,
2485                                    data->state.in);
2486 
2487           passed += actuallyread;
2488           if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2489             /* this checks for greater-than only to make sure that the
2490                CURL_READFUNC_ABORT return code still aborts */
2491             failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2492                   " bytes from the input", passed);
2493             return CURLE_READ_ERROR;
2494           }
2495         } while(passed < data->state.resume_from);
2496       }
2497 
2498       /* now, decrease the size of the read */
2499       if(data->state.infilesize>0) {
2500         data->state.infilesize -= data->state.resume_from;
2501 
2502         if(data->state.infilesize <= 0) {
2503           failf(data, "File already completely uploaded");
2504           return CURLE_PARTIAL_FILE;
2505         }
2506       }
2507       /* we've passed, proceed as normal */
2508     }
2509   }
2510   if(data->state.use_range) {
2511     /*
2512      * A range is selected. We use different headers whether we're downloading
2513      * or uploading and we always let customized headers override our internal
2514      * ones if any such are specified.
2515      */
2516     if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2517        !Curl_checkheaders(conn, "Range")) {
2518       /* if a line like this was already allocated, free the previous one */
2519       free(conn->allocptr.rangeline);
2520       conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
2521                                          data->state.range);
2522     }
2523     else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
2524             !Curl_checkheaders(conn, "Content-Range")) {
2525 
2526       /* if a line like this was already allocated, free the previous one */
2527       free(conn->allocptr.rangeline);
2528 
2529       if(data->set.set_resume_from < 0) {
2530         /* Upload resume was asked for, but we don't know the size of the
2531            remote part so we tell the server (and act accordingly) that we
2532            upload the whole file (again) */
2533         conn->allocptr.rangeline =
2534           aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
2535                   "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2536                   data->state.infilesize - 1, data->state.infilesize);
2537 
2538       }
2539       else if(data->state.resume_from) {
2540         /* This is because "resume" was selected */
2541         curl_off_t total_expected_size =
2542           data->state.resume_from + data->state.infilesize;
2543         conn->allocptr.rangeline =
2544           aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
2545                   "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2546                   data->state.range, total_expected_size-1,
2547                   total_expected_size);
2548       }
2549       else {
2550         /* Range was selected and then we just pass the incoming range and
2551            append total size */
2552         conn->allocptr.rangeline =
2553           aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2554                   data->state.range, data->state.infilesize);
2555       }
2556       if(!conn->allocptr.rangeline)
2557         return CURLE_OUT_OF_MEMORY;
2558     }
2559   }
2560 
2561   httpstring = get_http_string(data, conn);
2562 
2563   /* initialize a dynamic send-buffer */
2564   req_buffer = Curl_add_buffer_init();
2565 
2566   if(!req_buffer)
2567     return CURLE_OUT_OF_MEMORY;
2568 
2569   /* add the main request stuff */
2570   /* GET/HEAD/POST/PUT */
2571   result = Curl_add_bufferf(&req_buffer, "%s ", request);
2572   if(result)
2573     return result;
2574 
2575   if(data->set.str[STRING_TARGET]) {
2576     path = data->set.str[STRING_TARGET];
2577     query = NULL;
2578   }
2579 
2580 #ifndef CURL_DISABLE_PROXY
2581   /* url */
2582   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2583     char *url = data->set.str[STRING_TEMP_URL];
2584     result = Curl_add_buffer(&req_buffer, url, strlen(url));
2585     Curl_safefree(data->set.str[STRING_TEMP_URL]);
2586   }
2587   else
2588 #endif
2589   if(paste_ftp_userpwd)
2590     result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
2591                               conn->user, conn->passwd,
2592                               path + sizeof("ftp://") - 1);
2593   else {
2594     result = Curl_add_buffer(&req_buffer, path, strlen(path));
2595     if(result)
2596       return result;
2597     if(query)
2598       result = Curl_add_bufferf(&req_buffer, "?%s", query);
2599   }
2600   if(result)
2601     return result;
2602 
2603 #ifdef USE_ALTSVC
2604   if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) {
2605     altused = aprintf("Alt-Used: %s:%d\r\n",
2606                       conn->conn_to_host.name, conn->conn_to_port);
2607     if(!altused)
2608       return CURLE_OUT_OF_MEMORY;
2609   }
2610 #endif
2611   result =
2612     Curl_add_bufferf(&req_buffer,
2613                      "%s" /* ftp typecode (;type=x) */
2614                      " HTTP/%s\r\n" /* HTTP version */
2615                      "%s" /* host */
2616                      "%s" /* proxyuserpwd */
2617                      "%s" /* userpwd */
2618                      "%s" /* range */
2619                      "%s" /* user agent */
2620                      "%s" /* accept */
2621                      "%s" /* TE: */
2622                      "%s" /* accept-encoding */
2623                      "%s" /* referer */
2624                      "%s" /* Proxy-Connection */
2625                      "%s" /* transfer-encoding */
2626                      "%s",/* Alt-Used */
2627 
2628                      ftp_typecode,
2629                      httpstring,
2630                      (conn->allocptr.host?conn->allocptr.host:""),
2631                      conn->allocptr.proxyuserpwd?
2632                      conn->allocptr.proxyuserpwd:"",
2633                      conn->allocptr.userpwd?conn->allocptr.userpwd:"",
2634                      (data->state.use_range && conn->allocptr.rangeline)?
2635                      conn->allocptr.rangeline:"",
2636                      (data->set.str[STRING_USERAGENT] &&
2637                       *data->set.str[STRING_USERAGENT] &&
2638                       conn->allocptr.uagent)?
2639                      conn->allocptr.uagent:"",
2640                      http->p_accept?http->p_accept:"",
2641                      conn->allocptr.te?conn->allocptr.te:"",
2642                      (data->set.str[STRING_ENCODING] &&
2643                       *data->set.str[STRING_ENCODING] &&
2644                       conn->allocptr.accept_encoding)?
2645                      conn->allocptr.accept_encoding:"",
2646                      (data->change.referer && conn->allocptr.ref)?
2647                      conn->allocptr.ref:"" /* Referer: <data> */,
2648                      (conn->bits.httpproxy &&
2649                       !conn->bits.tunnel_proxy &&
2650                       !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
2651                      "Proxy-Connection: Keep-Alive\r\n":"",
2652                      te,
2653                      altused ? altused : ""
2654       );
2655 
2656   /* clear userpwd and proxyuserpwd to avoid re-using old credentials
2657    * from re-used connections */
2658   Curl_safefree(conn->allocptr.userpwd);
2659   Curl_safefree(conn->allocptr.proxyuserpwd);
2660   free(altused);
2661 
2662   if(result)
2663     return result;
2664 
2665   if(!(conn->handler->flags&PROTOPT_SSL) &&
2666      conn->httpversion != 20 &&
2667      (data->set.httpversion == CURL_HTTP_VERSION_2)) {
2668     /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
2669        over SSL */
2670     result = Curl_http2_request_upgrade(req_buffer, conn);
2671     if(result)
2672       return result;
2673   }
2674 
2675 #if !defined(CURL_DISABLE_COOKIES)
2676   if(data->cookies || addcookies) {
2677     struct Cookie *co = NULL; /* no cookies from start */
2678     int count = 0;
2679 
2680     if(data->cookies && data->state.cookie_engine) {
2681       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2682       co = Curl_cookie_getlist(data->cookies,
2683                                conn->allocptr.cookiehost?
2684                                conn->allocptr.cookiehost:host,
2685                                data->state.up.path,
2686                                (conn->handler->protocol&CURLPROTO_HTTPS)?
2687                                TRUE:FALSE);
2688       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2689     }
2690     if(co) {
2691       struct Cookie *store = co;
2692       /* now loop through all cookies that matched */
2693       while(co) {
2694         if(co->value) {
2695           if(0 == count) {
2696             result = Curl_add_bufferf(&req_buffer, "Cookie: ");
2697             if(result)
2698               break;
2699           }
2700           result = Curl_add_bufferf(&req_buffer,
2701                                     "%s%s=%s", count?"; ":"",
2702                                     co->name, co->value);
2703           if(result)
2704             break;
2705           count++;
2706         }
2707         co = co->next; /* next cookie please */
2708       }
2709       Curl_cookie_freelist(store);
2710     }
2711     if(addcookies && !result) {
2712       if(!count)
2713         result = Curl_add_bufferf(&req_buffer, "Cookie: ");
2714       if(!result) {
2715         result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"",
2716                                   addcookies);
2717         count++;
2718       }
2719     }
2720     if(count && !result)
2721       result = Curl_add_buffer(&req_buffer, "\r\n", 2);
2722 
2723     if(result)
2724       return result;
2725   }
2726 #endif
2727 
2728   result = Curl_add_timecondition(conn, req_buffer);
2729   if(result)
2730     return result;
2731 
2732   result = Curl_add_custom_headers(conn, FALSE, req_buffer);
2733   if(result)
2734     return result;
2735 
2736   http->postdata = NULL;  /* nothing to post at this point */
2737   Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
2738 
2739   /* If 'authdone' is FALSE, we must not set the write socket index to the
2740      Curl_transfer() call below, as we're not ready to actually upload any
2741      data yet. */
2742 
2743   switch(httpreq) {
2744 
2745   case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2746 
2747     if(conn->bits.authneg)
2748       postsize = 0;
2749     else
2750       postsize = data->state.infilesize;
2751 
2752     if((postsize != -1) && !data->req.upload_chunky &&
2753        (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
2754       /* only add Content-Length if not uploading chunked */
2755       result = Curl_add_bufferf(&req_buffer,
2756                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2757                                 "\r\n", postsize);
2758       if(result)
2759         return result;
2760     }
2761 
2762     if(postsize != 0) {
2763       result = expect100(data, conn, req_buffer);
2764       if(result)
2765         return result;
2766     }
2767 
2768     result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */
2769     if(result)
2770       return result;
2771 
2772     /* set the upload size to the progress meter */
2773     Curl_pgrsSetUploadSize(data, postsize);
2774 
2775     /* this sends the buffer and frees all the buffer resources */
2776     result = Curl_add_buffer_send(&req_buffer, conn,
2777                                   &data->info.request_size, 0, FIRSTSOCKET);
2778     if(result)
2779       failf(data, "Failed sending PUT request");
2780     else
2781       /* prepare for transfer */
2782       Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2783                           postsize?FIRSTSOCKET:-1);
2784     if(result)
2785       return result;
2786     break;
2787 
2788   case HTTPREQ_POST_FORM:
2789   case HTTPREQ_POST_MIME:
2790     /* This is form posting using mime data. */
2791     if(conn->bits.authneg) {
2792       /* nothing to post! */
2793       result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n");
2794       if(result)
2795         return result;
2796 
2797       result = Curl_add_buffer_send(&req_buffer, conn,
2798                                     &data->info.request_size, 0, FIRSTSOCKET);
2799       if(result)
2800         failf(data, "Failed sending POST request");
2801       else
2802         /* setup variables for the upcoming transfer */
2803         Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
2804       break;
2805     }
2806 
2807     data->state.infilesize = postsize = http->postsize;
2808 
2809     /* We only set Content-Length and allow a custom Content-Length if
2810        we don't upload data chunked, as RFC2616 forbids us to set both
2811        kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2812     if(postsize != -1 && !data->req.upload_chunky &&
2813        (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
2814       /* we allow replacing this header if not during auth negotiation,
2815          although it isn't very wise to actually set your own */
2816       result = Curl_add_bufferf(&req_buffer,
2817                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2818                                 "\r\n", postsize);
2819       if(result)
2820         return result;
2821     }
2822 
2823 #ifndef CURL_DISABLE_MIME
2824     /* Output mime-generated headers. */
2825     {
2826       struct curl_slist *hdr;
2827 
2828       for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
2829         result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data);
2830         if(result)
2831           return result;
2832       }
2833     }
2834 #endif
2835 
2836     /* For really small posts we don't use Expect: headers at all, and for
2837        the somewhat bigger ones we allow the app to disable it. Just make
2838        sure that the expect100header is always set to the preferred value
2839        here. */
2840     ptr = Curl_checkheaders(conn, "Expect");
2841     if(ptr) {
2842       data->state.expect100header =
2843         Curl_compareheader(ptr, "Expect:", "100-continue");
2844     }
2845     else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
2846       result = expect100(data, conn, req_buffer);
2847       if(result)
2848         return result;
2849     }
2850     else
2851       data->state.expect100header = FALSE;
2852 
2853     /* make the request end in a true CRLF */
2854     result = Curl_add_buffer(&req_buffer, "\r\n", 2);
2855     if(result)
2856       return result;
2857 
2858     /* set the upload size to the progress meter */
2859     Curl_pgrsSetUploadSize(data, postsize);
2860 
2861     /* Read from mime structure. */
2862     data->state.fread_func = (curl_read_callback) Curl_mime_read;
2863     data->state.in = (void *) http->sendit;
2864     http->sending = HTTPSEND_BODY;
2865 
2866     /* this sends the buffer and frees all the buffer resources */
2867     result = Curl_add_buffer_send(&req_buffer, conn,
2868                                   &data->info.request_size, 0, FIRSTSOCKET);
2869     if(result)
2870       failf(data, "Failed sending POST request");
2871     else
2872       /* prepare for transfer */
2873       Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2874                           postsize?FIRSTSOCKET:-1);
2875     if(result)
2876       return result;
2877 
2878     break;
2879 
2880   case HTTPREQ_POST:
2881     /* this is the simple POST, using x-www-form-urlencoded style */
2882 
2883     if(conn->bits.authneg)
2884       postsize = 0;
2885     else
2886       /* the size of the post body */
2887       postsize = data->state.infilesize;
2888 
2889     /* We only set Content-Length and allow a custom Content-Length if
2890        we don't upload data chunked, as RFC2616 forbids us to set both
2891        kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2892     if((postsize != -1) && !data->req.upload_chunky &&
2893        (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
2894       /* we allow replacing this header if not during auth negotiation,
2895          although it isn't very wise to actually set your own */
2896       result = Curl_add_bufferf(&req_buffer,
2897                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2898                                 "\r\n", postsize);
2899       if(result)
2900         return result;
2901     }
2902 
2903     if(!Curl_checkheaders(conn, "Content-Type")) {
2904       result = Curl_add_bufferf(&req_buffer,
2905                                 "Content-Type: application/"
2906                                 "x-www-form-urlencoded\r\n");
2907       if(result)
2908         return result;
2909     }
2910 
2911     /* For really small posts we don't use Expect: headers at all, and for
2912        the somewhat bigger ones we allow the app to disable it. Just make
2913        sure that the expect100header is always set to the preferred value
2914        here. */
2915     ptr = Curl_checkheaders(conn, "Expect");
2916     if(ptr) {
2917       data->state.expect100header =
2918         Curl_compareheader(ptr, "Expect:", "100-continue");
2919     }
2920     else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
2921       result = expect100(data, conn, req_buffer);
2922       if(result)
2923         return result;
2924     }
2925     else
2926       data->state.expect100header = FALSE;
2927 
2928     if(data->set.postfields) {
2929 
2930       /* In HTTP2, we send request body in DATA frame regardless of
2931          its size. */
2932       if(conn->httpversion != 20 &&
2933          !data->state.expect100header &&
2934          (postsize < MAX_INITIAL_POST_SIZE)) {
2935         /* if we don't use expect: 100  AND
2936            postsize is less than MAX_INITIAL_POST_SIZE
2937 
2938            then append the post data to the HTTP request header. This limit
2939            is no magic limit but only set to prevent really huge POSTs to
2940            get the data duplicated with malloc() and family. */
2941 
2942         result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
2943         if(result)
2944           return result;
2945 
2946         if(!data->req.upload_chunky) {
2947           /* We're not sending it 'chunked', append it to the request
2948              already now to reduce the number if send() calls */
2949           result = Curl_add_buffer(&req_buffer, data->set.postfields,
2950                                    (size_t)postsize);
2951           included_body = postsize;
2952         }
2953         else {
2954           if(postsize) {
2955             /* Append the POST data chunky-style */
2956             result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize);
2957             if(!result) {
2958               result = Curl_add_buffer(&req_buffer, data->set.postfields,
2959                                        (size_t)postsize);
2960               if(!result)
2961                 result = Curl_add_buffer(&req_buffer, "\r\n", 2);
2962               included_body = postsize + 2;
2963             }
2964           }
2965           if(!result)
2966             result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
2967           /* 0  CR  LF  CR  LF */
2968           included_body += 5;
2969         }
2970         if(result)
2971           return result;
2972         /* Make sure the progress information is accurate */
2973         Curl_pgrsSetUploadSize(data, postsize);
2974       }
2975       else {
2976         /* A huge POST coming up, do data separate from the request */
2977         http->postsize = postsize;
2978         http->postdata = data->set.postfields;
2979 
2980         http->sending = HTTPSEND_BODY;
2981 
2982         data->state.fread_func = (curl_read_callback)readmoredata;
2983         data->state.in = (void *)conn;
2984 
2985         /* set the upload size to the progress meter */
2986         Curl_pgrsSetUploadSize(data, http->postsize);
2987 
2988         result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
2989         if(result)
2990           return result;
2991       }
2992     }
2993     else {
2994       result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
2995       if(result)
2996         return result;
2997 
2998       if(data->req.upload_chunky && conn->bits.authneg) {
2999         /* Chunky upload is selected and we're negotiating auth still, send
3000            end-of-data only */
3001         result = Curl_add_buffer(&req_buffer,
3002                                  "\x30\x0d\x0a\x0d\x0a", 5);
3003         /* 0  CR  LF  CR  LF */
3004         if(result)
3005           return result;
3006       }
3007 
3008       else if(data->state.infilesize) {
3009         /* set the upload size to the progress meter */
3010         Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
3011 
3012         /* set the pointer to mark that we will send the post body using the
3013            read callback, but only if we're not in authenticate
3014            negotiation  */
3015         if(!conn->bits.authneg) {
3016           http->postdata = (char *)&http->postdata;
3017           http->postsize = postsize;
3018         }
3019       }
3020     }
3021     /* issue the request */
3022     result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size,
3023                                   (size_t)included_body, FIRSTSOCKET);
3024 
3025     if(result)
3026       failf(data, "Failed sending HTTP POST request");
3027     else
3028       Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
3029                           http->postdata?FIRSTSOCKET:-1);
3030     break;
3031 
3032   default:
3033     result = Curl_add_buffer(&req_buffer, "\r\n", 2);
3034     if(result)
3035       return result;
3036 
3037     /* issue the request */
3038     result = Curl_add_buffer_send(&req_buffer, conn,
3039                                   &data->info.request_size, 0, FIRSTSOCKET);
3040 
3041     if(result)
3042       failf(data, "Failed sending HTTP request");
3043     else
3044       /* HTTP GET/HEAD download: */
3045       Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
3046   }
3047   if(result)
3048     return result;
3049 
3050   if(data->req.writebytecount) {
3051     /* if a request-body has been sent off, we make sure this progress is noted
3052        properly */
3053     Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
3054     if(Curl_pgrsUpdate(conn))
3055       result = CURLE_ABORTED_BY_CALLBACK;
3056 
3057     if(data->req.writebytecount >= postsize) {
3058       /* already sent the entire request body, mark the "upload" as
3059          complete */
3060       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
3061             " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
3062             data->req.writebytecount, postsize);
3063       data->req.upload_done = TRUE;
3064       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
3065       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
3066       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3067     }
3068   }
3069 
3070   if((conn->httpversion == 20) && data->req.upload_chunky)
3071     /* upload_chunky was set above to set up the request in a chunky fashion,
3072        but is disabled here again to avoid that the chunked encoded version is
3073        actually used when sending the request body over h2 */
3074     data->req.upload_chunky = FALSE;
3075   return result;
3076 }
3077 
3078 typedef enum {
3079   STATUS_UNKNOWN, /* not enough data to tell yet */
3080   STATUS_DONE, /* a status line was read */
3081   STATUS_BAD /* not a status line */
3082 } statusline;
3083 
3084 
3085 /* Check a string for a prefix. Check no more than 'len' bytes */
checkprefixmax(const char * prefix,const char * buffer,size_t len)3086 static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
3087 {
3088   size_t ch = CURLMIN(strlen(prefix), len);
3089   return curl_strnequal(prefix, buffer, ch);
3090 }
3091 
3092 /*
3093  * checkhttpprefix()
3094  *
3095  * Returns TRUE if member of the list matches prefix of string
3096  */
3097 static statusline
checkhttpprefix(struct Curl_easy * data,const char * s,size_t len)3098 checkhttpprefix(struct Curl_easy *data,
3099                 const char *s, size_t len)
3100 {
3101   struct curl_slist *head = data->set.http200aliases;
3102   statusline rc = STATUS_BAD;
3103   statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3104 #ifdef CURL_DOES_CONVERSIONS
3105   /* convert from the network encoding using a scratch area */
3106   char *scratch = strdup(s);
3107   if(NULL == scratch) {
3108     failf(data, "Failed to allocate memory for conversion!");
3109     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3110   }
3111   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
3112     /* Curl_convert_from_network calls failf if unsuccessful */
3113     free(scratch);
3114     return FALSE; /* can't return CURLE_foobar so return FALSE */
3115   }
3116   s = scratch;
3117 #endif /* CURL_DOES_CONVERSIONS */
3118 
3119   while(head) {
3120     if(checkprefixmax(head->data, s, len)) {
3121       rc = onmatch;
3122       break;
3123     }
3124     head = head->next;
3125   }
3126 
3127   if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
3128     rc = onmatch;
3129 
3130 #ifdef CURL_DOES_CONVERSIONS
3131   free(scratch);
3132 #endif /* CURL_DOES_CONVERSIONS */
3133   return rc;
3134 }
3135 
3136 #ifndef CURL_DISABLE_RTSP
3137 static statusline
checkrtspprefix(struct Curl_easy * data,const char * s,size_t len)3138 checkrtspprefix(struct Curl_easy *data,
3139                 const char *s, size_t len)
3140 {
3141   statusline result = STATUS_BAD;
3142   statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3143 
3144 #ifdef CURL_DOES_CONVERSIONS
3145   /* convert from the network encoding using a scratch area */
3146   char *scratch = strdup(s);
3147   if(NULL == scratch) {
3148     failf(data, "Failed to allocate memory for conversion!");
3149     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3150   }
3151   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
3152     /* Curl_convert_from_network calls failf if unsuccessful */
3153     result = FALSE; /* can't return CURLE_foobar so return FALSE */
3154   }
3155   else if(checkprefixmax("RTSP/", scratch, len))
3156     result = onmatch;
3157   free(scratch);
3158 #else
3159   (void)data; /* unused */
3160   if(checkprefixmax("RTSP/", s, len))
3161     result = onmatch;
3162 #endif /* CURL_DOES_CONVERSIONS */
3163 
3164   return result;
3165 }
3166 #endif /* CURL_DISABLE_RTSP */
3167 
3168 static statusline
checkprotoprefix(struct Curl_easy * data,struct connectdata * conn,const char * s,size_t len)3169 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
3170                  const char *s, size_t len)
3171 {
3172 #ifndef CURL_DISABLE_RTSP
3173   if(conn->handler->protocol & CURLPROTO_RTSP)
3174     return checkrtspprefix(data, s, len);
3175 #else
3176   (void)conn;
3177 #endif /* CURL_DISABLE_RTSP */
3178 
3179   return checkhttpprefix(data, s, len);
3180 }
3181 
3182 /*
3183  * header_append() copies a chunk of data to the end of the already received
3184  * header. We make sure that the full string fit in the allocated header
3185  * buffer, or else we enlarge it.
3186  */
header_append(struct Curl_easy * data,struct SingleRequest * k,size_t length)3187 static CURLcode header_append(struct Curl_easy *data,
3188                               struct SingleRequest *k,
3189                               size_t length)
3190 {
3191   /* length is at most the size of a full read buffer, for which the upper
3192      bound is CURL_MAX_READ_SIZE. There is thus no chance of overflow in this
3193      calculation. */
3194   size_t newsize = k->hbuflen + length;
3195   if(newsize > CURL_MAX_HTTP_HEADER) {
3196     /* The reason to have a max limit for this is to avoid the risk of a bad
3197        server feeding libcurl with a never-ending header that will cause
3198        reallocs infinitely */
3199     failf(data, "Rejected %zu bytes header (max is %d)!", newsize,
3200           CURL_MAX_HTTP_HEADER);
3201     return CURLE_OUT_OF_MEMORY;
3202   }
3203   if(newsize >= data->state.headersize) {
3204     /* We enlarge the header buffer as it is too small */
3205     char *newbuff;
3206     size_t hbufp_index;
3207 
3208     newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2);
3209     hbufp_index = k->hbufp - data->state.headerbuff;
3210     newbuff = realloc(data->state.headerbuff, newsize);
3211     if(!newbuff) {
3212       failf(data, "Failed to alloc memory for big header!");
3213       return CURLE_OUT_OF_MEMORY;
3214     }
3215     data->state.headersize = newsize;
3216     data->state.headerbuff = newbuff;
3217     k->hbufp = data->state.headerbuff + hbufp_index;
3218   }
3219   memcpy(k->hbufp, k->str_start, length);
3220   k->hbufp += length;
3221   k->hbuflen += length;
3222   *k->hbufp = 0;
3223 
3224   return CURLE_OK;
3225 }
3226 
print_http_error(struct Curl_easy * data)3227 static void print_http_error(struct Curl_easy *data)
3228 {
3229   struct SingleRequest *k = &data->req;
3230   char *beg = k->p;
3231 
3232   /* make sure that data->req.p points to the HTTP status line */
3233   if(!strncmp(beg, "HTTP", 4)) {
3234 
3235     /* skip to HTTP status code */
3236     beg = strchr(beg, ' ');
3237     if(beg && *++beg) {
3238 
3239       /* find trailing CR */
3240       char end_char = '\r';
3241       char *end = strchr(beg, end_char);
3242       if(!end) {
3243         /* try to find LF (workaround for non-compliant HTTP servers) */
3244         end_char = '\n';
3245         end = strchr(beg, end_char);
3246       }
3247 
3248       if(end) {
3249         /* temporarily replace CR or LF by NUL and print the error message */
3250         *end = '\0';
3251         failf(data, "The requested URL returned error: %s", beg);
3252 
3253         /* restore the previously replaced CR or LF */
3254         *end = end_char;
3255         return;
3256       }
3257     }
3258   }
3259 
3260   /* fall-back to printing the HTTP status code only */
3261   failf(data, "The requested URL returned error: %d", k->httpcode);
3262 }
3263 
3264 /*
3265  * Read any HTTP header lines from the server and pass them to the client app.
3266  */
Curl_http_readwrite_headers(struct Curl_easy * data,struct connectdata * conn,ssize_t * nread,bool * stop_reading)3267 CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
3268                                        struct connectdata *conn,
3269                                        ssize_t *nread,
3270                                        bool *stop_reading)
3271 {
3272   CURLcode result;
3273   struct SingleRequest *k = &data->req;
3274   ssize_t onread = *nread;
3275   char *ostr = k->str;
3276 
3277   /* header line within buffer loop */
3278   do {
3279     size_t rest_length;
3280     size_t full_length;
3281     int writetype;
3282 
3283     /* str_start is start of line within buf */
3284     k->str_start = k->str;
3285 
3286     /* data is in network encoding so use 0x0a instead of '\n' */
3287     k->end_ptr = memchr(k->str_start, 0x0a, *nread);
3288 
3289     if(!k->end_ptr) {
3290       /* Not a complete header line within buffer, append the data to
3291          the end of the headerbuff. */
3292       result = header_append(data, k, *nread);
3293       if(result)
3294         return result;
3295 
3296       if(!k->headerline) {
3297         /* check if this looks like a protocol header */
3298         statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
3299                                          k->hbuflen);
3300         if(st == STATUS_BAD) {
3301           /* this is not the beginning of a protocol first header line */
3302           k->header = FALSE;
3303           k->badheader = HEADER_ALLBAD;
3304           streamclose(conn, "bad HTTP: No end-of-message indicator");
3305           if(!data->set.http09_allowed) {
3306             failf(data, "Received HTTP/0.9 when not allowed\n");
3307             return CURLE_UNSUPPORTED_PROTOCOL;
3308           }
3309           break;
3310         }
3311       }
3312 
3313       break; /* read more and try again */
3314     }
3315 
3316     /* decrease the size of the remaining (supposed) header line */
3317     rest_length = (k->end_ptr - k->str) + 1;
3318     *nread -= (ssize_t)rest_length;
3319 
3320     k->str = k->end_ptr + 1; /* move past new line */
3321 
3322     full_length = k->str - k->str_start;
3323 
3324     result = header_append(data, k, full_length);
3325     if(result)
3326       return result;
3327 
3328     k->end_ptr = k->hbufp;
3329     k->p = data->state.headerbuff;
3330 
3331     /****
3332      * We now have a FULL header line that p points to
3333      *****/
3334 
3335     if(!k->headerline) {
3336       /* the first read header */
3337       statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
3338                                        k->hbuflen);
3339       if(st == STATUS_BAD) {
3340         streamclose(conn, "bad HTTP: No end-of-message indicator");
3341         /* this is not the beginning of a protocol first header line */
3342         if(!data->set.http09_allowed) {
3343           failf(data, "Received HTTP/0.9 when not allowed\n");
3344           return CURLE_UNSUPPORTED_PROTOCOL;
3345         }
3346         k->header = FALSE;
3347         if(*nread)
3348           /* since there's more, this is a partial bad header */
3349           k->badheader = HEADER_PARTHEADER;
3350         else {
3351           /* this was all we read so it's all a bad header */
3352           k->badheader = HEADER_ALLBAD;
3353           *nread = onread;
3354           k->str = ostr;
3355           return CURLE_OK;
3356         }
3357         break;
3358       }
3359     }
3360 
3361     /* headers are in network encoding so
3362        use 0x0a and 0x0d instead of '\n' and '\r' */
3363     if((0x0a == *k->p) || (0x0d == *k->p)) {
3364       size_t headerlen;
3365       /* Zero-length header line means end of headers! */
3366 
3367 #ifdef CURL_DOES_CONVERSIONS
3368       if(0x0d == *k->p) {
3369         *k->p = '\r'; /* replace with CR in host encoding */
3370         k->p++;       /* pass the CR byte */
3371       }
3372       if(0x0a == *k->p) {
3373         *k->p = '\n'; /* replace with LF in host encoding */
3374         k->p++;       /* pass the LF byte */
3375       }
3376 #else
3377       if('\r' == *k->p)
3378         k->p++; /* pass the \r byte */
3379       if('\n' == *k->p)
3380         k->p++; /* pass the \n byte */
3381 #endif /* CURL_DOES_CONVERSIONS */
3382 
3383       if(100 <= k->httpcode && 199 >= k->httpcode) {
3384         /* "A user agent MAY ignore unexpected 1xx status responses." */
3385         switch(k->httpcode) {
3386         case 100:
3387           /*
3388            * We have made a HTTP PUT or POST and this is 1.1-lingo
3389            * that tells us that the server is OK with this and ready
3390            * to receive the data.
3391            * However, we'll get more headers now so we must get
3392            * back into the header-parsing state!
3393            */
3394           k->header = TRUE;
3395           k->headerline = 0; /* restart the header line counter */
3396 
3397           /* if we did wait for this do enable write now! */
3398           if(k->exp100 > EXP100_SEND_DATA) {
3399             k->exp100 = EXP100_SEND_DATA;
3400             k->keepon |= KEEP_SEND;
3401             Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3402           }
3403           break;
3404         case 101:
3405           /* Switching Protocols */
3406           if(k->upgr101 == UPGR101_REQUESTED) {
3407             /* Switching to HTTP/2 */
3408             infof(data, "Received 101\n");
3409             k->upgr101 = UPGR101_RECEIVED;
3410 
3411             /* we'll get more headers (HTTP/2 response) */
3412             k->header = TRUE;
3413             k->headerline = 0; /* restart the header line counter */
3414 
3415             /* switch to http2 now. The bytes after response headers
3416                are also processed here, otherwise they are lost. */
3417             result = Curl_http2_switched(conn, k->str, *nread);
3418             if(result)
3419               return result;
3420             *nread = 0;
3421           }
3422           else {
3423             /* Switching to another protocol (e.g. WebSocket) */
3424             k->header = FALSE; /* no more header to parse! */
3425           }
3426           break;
3427         default:
3428           /* the status code 1xx indicates a provisional response, so
3429              we'll get another set of headers */
3430           k->header = TRUE;
3431           k->headerline = 0; /* restart the header line counter */
3432           break;
3433         }
3434       }
3435       else {
3436         k->header = FALSE; /* no more header to parse! */
3437 
3438         if((k->size == -1) && !k->chunk && !conn->bits.close &&
3439            (conn->httpversion == 11) &&
3440            !(conn->handler->protocol & CURLPROTO_RTSP) &&
3441            data->set.httpreq != HTTPREQ_HEAD) {
3442           /* On HTTP 1.1, when connection is not to get closed, but no
3443              Content-Length nor Transfer-Encoding chunked have been
3444              received, according to RFC2616 section 4.4 point 5, we
3445              assume that the server will close the connection to
3446              signal the end of the document. */
3447           infof(data, "no chunk, no close, no size. Assume close to "
3448                 "signal end\n");
3449           streamclose(conn, "HTTP: No end-of-message indicator");
3450         }
3451       }
3452 
3453       /* At this point we have some idea about the fate of the connection.
3454          If we are closing the connection it may result auth failure. */
3455 #if defined(USE_NTLM)
3456       if(conn->bits.close &&
3457          (((data->req.httpcode == 401) &&
3458            (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
3459           ((data->req.httpcode == 407) &&
3460            (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
3461         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
3462         data->state.authproblem = TRUE;
3463       }
3464 #endif
3465 #if defined(USE_SPNEGO)
3466       if(conn->bits.close &&
3467         (((data->req.httpcode == 401) &&
3468           (conn->http_negotiate_state == GSS_AUTHRECV)) ||
3469          ((data->req.httpcode == 407) &&
3470           (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
3471         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
3472         data->state.authproblem = TRUE;
3473       }
3474       if((conn->http_negotiate_state == GSS_AUTHDONE) &&
3475          (data->req.httpcode != 401)) {
3476         conn->http_negotiate_state = GSS_AUTHSUCC;
3477       }
3478       if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
3479          (data->req.httpcode != 407)) {
3480         conn->proxy_negotiate_state = GSS_AUTHSUCC;
3481       }
3482 #endif
3483       /*
3484        * When all the headers have been parsed, see if we should give
3485        * up and return an error.
3486        */
3487       if(http_should_fail(conn)) {
3488         failf(data, "The requested URL returned error: %d",
3489               k->httpcode);
3490         return CURLE_HTTP_RETURNED_ERROR;
3491       }
3492 
3493       /* now, only output this if the header AND body are requested:
3494        */
3495       writetype = CLIENTWRITE_HEADER;
3496       if(data->set.include_header)
3497         writetype |= CLIENTWRITE_BODY;
3498 
3499       headerlen = k->p - data->state.headerbuff;
3500 
3501       result = Curl_client_write(conn, writetype,
3502                                  data->state.headerbuff,
3503                                  headerlen);
3504       if(result)
3505         return result;
3506 
3507       data->info.header_size += (long)headerlen;
3508       data->req.headerbytecount += (long)headerlen;
3509 
3510       data->req.deductheadercount =
3511         (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
3512 
3513       /* Curl_http_auth_act() checks what authentication methods
3514        * that are available and decides which one (if any) to
3515        * use. It will set 'newurl' if an auth method was picked. */
3516       result = Curl_http_auth_act(conn);
3517 
3518       if(result)
3519         return result;
3520 
3521       if(k->httpcode >= 300) {
3522         if((!conn->bits.authneg) && !conn->bits.close &&
3523            !conn->bits.rewindaftersend) {
3524           /*
3525            * General treatment of errors when about to send data. Including :
3526            * "417 Expectation Failed", while waiting for 100-continue.
3527            *
3528            * The check for close above is done simply because of something
3529            * else has already deemed the connection to get closed then
3530            * something else should've considered the big picture and we
3531            * avoid this check.
3532            *
3533            * rewindaftersend indicates that something has told libcurl to
3534            * continue sending even if it gets discarded
3535            */
3536 
3537           switch(data->set.httpreq) {
3538           case HTTPREQ_PUT:
3539           case HTTPREQ_POST:
3540           case HTTPREQ_POST_FORM:
3541           case HTTPREQ_POST_MIME:
3542             /* We got an error response. If this happened before the whole
3543              * request body has been sent we stop sending and mark the
3544              * connection for closure after we've read the entire response.
3545              */
3546             Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3547             if(!k->upload_done) {
3548               if(data->set.http_keep_sending_on_error) {
3549                 infof(data, "HTTP error before end of send, keep sending\n");
3550                 if(k->exp100 > EXP100_SEND_DATA) {
3551                   k->exp100 = EXP100_SEND_DATA;
3552                   k->keepon |= KEEP_SEND;
3553                 }
3554               }
3555               else {
3556                 infof(data, "HTTP error before end of send, stop sending\n");
3557                 streamclose(conn, "Stop sending data before everything sent");
3558                 result = Curl_done_sending(conn, k);
3559                 if(result)
3560                   return result;
3561                 k->upload_done = TRUE;
3562                 if(data->state.expect100header)
3563                   k->exp100 = EXP100_FAILED;
3564               }
3565             }
3566             break;
3567 
3568           default: /* default label present to avoid compiler warnings */
3569             break;
3570           }
3571         }
3572 
3573         if(conn->bits.rewindaftersend) {
3574           /* We rewind after a complete send, so thus we continue
3575              sending now */
3576           infof(data, "Keep sending data to get tossed away!\n");
3577           k->keepon |= KEEP_SEND;
3578         }
3579       }
3580 
3581       if(!k->header) {
3582         /*
3583          * really end-of-headers.
3584          *
3585          * If we requested a "no body", this is a good time to get
3586          * out and return home.
3587          */
3588         if(data->set.opt_no_body)
3589           *stop_reading = TRUE;
3590 #ifndef CURL_DISABLE_RTSP
3591         else if((conn->handler->protocol & CURLPROTO_RTSP) &&
3592                 (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
3593                 (k->size <= -1))
3594           /* Respect section 4.4 of rfc2326: If the Content-Length header is
3595              absent, a length 0 must be assumed.  It will prevent libcurl from
3596              hanging on DESCRIBE request that got refused for whatever
3597              reason */
3598           *stop_reading = TRUE;
3599 #endif
3600         else {
3601           /* If we know the expected size of this document, we set the
3602              maximum download size to the size of the expected
3603              document or else, we won't know when to stop reading!
3604 
3605              Note that we set the download maximum even if we read a
3606              "Connection: close" header, to make sure that
3607              "Content-Length: 0" still prevents us from attempting to
3608              read the (missing) response-body.
3609           */
3610           /* According to RFC2616 section 4.4, we MUST ignore
3611              Content-Length: headers if we are now receiving data
3612              using chunked Transfer-Encoding.
3613           */
3614           if(k->chunk)
3615             k->maxdownload = k->size = -1;
3616         }
3617         if(-1 != k->size) {
3618           /* We do this operation even if no_body is true, since this
3619              data might be retrieved later with curl_easy_getinfo()
3620              and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
3621 
3622           Curl_pgrsSetDownloadSize(data, k->size);
3623           k->maxdownload = k->size;
3624         }
3625 
3626         /* If max download size is *zero* (nothing) we already have
3627            nothing and can safely return ok now!  But for HTTP/2, we'd
3628            like to call http2_handle_stream_close to properly close a
3629            stream.  In order to do this, we keep reading until we
3630            close the stream. */
3631         if(0 == k->maxdownload
3632 #if defined(USE_NGHTTP2)
3633            && !((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
3634                 conn->httpversion == 20)
3635 #endif
3636            )
3637           *stop_reading = TRUE;
3638 
3639         if(*stop_reading) {
3640           /* we make sure that this socket isn't read more now */
3641           k->keepon &= ~KEEP_RECV;
3642         }
3643 
3644         if(data->set.verbose)
3645           Curl_debug(data, CURLINFO_HEADER_IN,
3646                      k->str_start, headerlen);
3647         break;          /* exit header line loop */
3648       }
3649 
3650       /* We continue reading headers, so reset the line-based
3651          header parsing variables hbufp && hbuflen */
3652       k->hbufp = data->state.headerbuff;
3653       k->hbuflen = 0;
3654       continue;
3655     }
3656 
3657     /*
3658      * Checks for special headers coming up.
3659      */
3660 
3661     if(!k->headerline++) {
3662       /* This is the first header, it MUST be the error code line
3663          or else we consider this to be the body right away! */
3664       int httpversion_major;
3665       int rtspversion_major;
3666       int nc = 0;
3667 #ifdef CURL_DOES_CONVERSIONS
3668 #define HEADER1 scratch
3669 #define SCRATCHSIZE 21
3670       CURLcode res;
3671       char scratch[SCRATCHSIZE + 1]; /* "HTTP/major.minor 123" */
3672       /* We can't really convert this yet because we
3673          don't know if it's the 1st header line or the body.
3674          So we do a partial conversion into a scratch area,
3675          leaving the data at k->p as-is.
3676       */
3677       strncpy(&scratch[0], k->p, SCRATCHSIZE);
3678       scratch[SCRATCHSIZE] = 0; /* null terminate */
3679       res = Curl_convert_from_network(data,
3680                                       &scratch[0],
3681                                       SCRATCHSIZE);
3682       if(res)
3683         /* Curl_convert_from_network calls failf if unsuccessful */
3684         return res;
3685 #else
3686 #define HEADER1 k->p /* no conversion needed, just use k->p */
3687 #endif /* CURL_DOES_CONVERSIONS */
3688 
3689       if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
3690         /*
3691          * https://tools.ietf.org/html/rfc7230#section-3.1.2
3692          *
3693          * The response code is always a three-digit number in HTTP as the spec
3694          * says. We try to allow any number here, but we cannot make
3695          * guarantees on future behaviors since it isn't within the protocol.
3696          */
3697         char separator;
3698         char twoorthree[2];
3699         nc = sscanf(HEADER1,
3700                     " HTTP/%1d.%1d%c%3d",
3701                     &httpversion_major,
3702                     &conn->httpversion,
3703                     &separator,
3704                     &k->httpcode);
3705 
3706         if(nc == 1 && httpversion_major >= 2 &&
3707            2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
3708           conn->httpversion = 0;
3709           nc = 4;
3710           separator = ' ';
3711         }
3712 
3713         if((nc == 4) && (' ' == separator)) {
3714           conn->httpversion += 10 * httpversion_major;
3715 
3716           if(k->upgr101 == UPGR101_RECEIVED) {
3717             /* supposedly upgraded to http2 now */
3718             if(conn->httpversion != 20)
3719               infof(data, "Lying server, not serving HTTP/2\n");
3720           }
3721           if(conn->httpversion < 20) {
3722             conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
3723             infof(data, "Mark bundle as not supporting multiuse\n");
3724           }
3725         }
3726         else if(!nc) {
3727           /* this is the real world, not a Nirvana
3728              NCSA 1.5.x returns this crap when asked for HTTP/1.1
3729           */
3730           nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
3731           conn->httpversion = 10;
3732 
3733           /* If user has set option HTTP200ALIASES,
3734              compare header line against list of aliases
3735           */
3736           if(!nc) {
3737             if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) {
3738               nc = 1;
3739               k->httpcode = 200;
3740               conn->httpversion = 10;
3741             }
3742           }
3743         }
3744         else {
3745           failf(data, "Unsupported HTTP version in response");
3746           return CURLE_UNSUPPORTED_PROTOCOL;
3747         }
3748       }
3749       else if(conn->handler->protocol & CURLPROTO_RTSP) {
3750         char separator;
3751         nc = sscanf(HEADER1,
3752                     " RTSP/%1d.%1d%c%3d",
3753                     &rtspversion_major,
3754                     &conn->rtspversion,
3755                     &separator,
3756                     &k->httpcode);
3757         if((nc == 4) && (' ' == separator)) {
3758           conn->rtspversion += 10 * rtspversion_major;
3759           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
3760         }
3761         else {
3762           nc = 0;
3763         }
3764       }
3765 
3766       if(nc) {
3767         data->info.httpcode = k->httpcode;
3768 
3769         data->info.httpversion = conn->httpversion;
3770         if(!data->state.httpversion ||
3771            data->state.httpversion > conn->httpversion)
3772           /* store the lowest server version we encounter */
3773           data->state.httpversion = conn->httpversion;
3774 
3775         /*
3776          * This code executes as part of processing the header.  As a
3777          * result, it's not totally clear how to interpret the
3778          * response code yet as that depends on what other headers may
3779          * be present.  401 and 407 may be errors, but may be OK
3780          * depending on how authentication is working.  Other codes
3781          * are definitely errors, so give up here.
3782          */
3783         if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET &&
3784              k->httpcode == 416) {
3785           /* "Requested Range Not Satisfiable", just proceed and
3786              pretend this is no error */
3787           k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
3788         }
3789         else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
3790            ((k->httpcode != 401) || !conn->bits.user_passwd) &&
3791            ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
3792           /* serious error, go home! */
3793           print_http_error(data);
3794           return CURLE_HTTP_RETURNED_ERROR;
3795         }
3796 
3797         if(conn->httpversion == 10) {
3798           /* Default action for HTTP/1.0 must be to close, unless
3799              we get one of those fancy headers that tell us the
3800              server keeps it open for us! */
3801           infof(data, "HTTP 1.0, assume close after body\n");
3802           connclose(conn, "HTTP/1.0 close after body");
3803         }
3804         else if(conn->httpversion == 20 ||
3805                 (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
3806           DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
3807 
3808           /* HTTP/2 cannot blacklist multiplexing since it is a core
3809              functionality of the protocol */
3810           conn->bundle->multiuse = BUNDLE_MULTIPLEX;
3811         }
3812         else if(conn->httpversion >= 11 &&
3813                 !conn->bits.close) {
3814           /* If HTTP version is >= 1.1 and connection is persistent */
3815           DEBUGF(infof(data,
3816                        "HTTP 1.1 or later with persistent connection\n"));
3817         }
3818 
3819         k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
3820         switch(k->httpcode) {
3821         case 304:
3822           /* (quote from RFC2616, section 10.3.5): The 304 response
3823            * MUST NOT contain a message-body, and thus is always
3824            * terminated by the first empty line after the header
3825            * fields.  */
3826           if(data->set.timecondition)
3827             data->info.timecond = TRUE;
3828           /* FALLTHROUGH */
3829         case 204:
3830           /* (quote from RFC2616, section 10.2.5): The server has
3831            * fulfilled the request but does not need to return an
3832            * entity-body ... The 204 response MUST NOT include a
3833            * message-body, and thus is always terminated by the first
3834            * empty line after the header fields. */
3835           k->size = 0;
3836           k->maxdownload = 0;
3837           k->http_bodyless = TRUE;
3838           break;
3839         default:
3840           break;
3841         }
3842       }
3843       else {
3844         k->header = FALSE;   /* this is not a header line */
3845         break;
3846       }
3847     }
3848 
3849     result = Curl_convert_from_network(data, k->p, strlen(k->p));
3850     /* Curl_convert_from_network calls failf if unsuccessful */
3851     if(result)
3852       return result;
3853 
3854     /* Check for Content-Length: header lines to get size */
3855     if(!k->http_bodyless &&
3856        !data->set.ignorecl && checkprefix("Content-Length:", k->p)) {
3857       curl_off_t contentlength;
3858       CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength);
3859 
3860       if(offt == CURL_OFFT_OK) {
3861         if(data->set.max_filesize &&
3862            contentlength > data->set.max_filesize) {
3863           failf(data, "Maximum file size exceeded");
3864           return CURLE_FILESIZE_EXCEEDED;
3865         }
3866         k->size = contentlength;
3867         k->maxdownload = k->size;
3868         /* we set the progress download size already at this point
3869            just to make it easier for apps/callbacks to extract this
3870            info as soon as possible */
3871         Curl_pgrsSetDownloadSize(data, k->size);
3872       }
3873       else if(offt == CURL_OFFT_FLOW) {
3874         /* out of range */
3875         if(data->set.max_filesize) {
3876           failf(data, "Maximum file size exceeded");
3877           return CURLE_FILESIZE_EXCEEDED;
3878         }
3879         streamclose(conn, "overflow content-length");
3880         infof(data, "Overflow Content-Length: value!\n");
3881       }
3882       else {
3883         /* negative or just rubbish - bad HTTP */
3884         failf(data, "Invalid Content-Length: value");
3885         return CURLE_WEIRD_SERVER_REPLY;
3886       }
3887     }
3888     /* check for Content-Type: header lines to get the MIME-type */
3889     else if(checkprefix("Content-Type:", k->p)) {
3890       char *contenttype = Curl_copy_header_value(k->p);
3891       if(!contenttype)
3892         return CURLE_OUT_OF_MEMORY;
3893       if(!*contenttype)
3894         /* ignore empty data */
3895         free(contenttype);
3896       else {
3897         Curl_safefree(data->info.contenttype);
3898         data->info.contenttype = contenttype;
3899       }
3900     }
3901     else if((conn->httpversion == 10) &&
3902             conn->bits.httpproxy &&
3903             Curl_compareheader(k->p,
3904                                "Proxy-Connection:", "keep-alive")) {
3905       /*
3906        * When a HTTP/1.0 reply comes when using a proxy, the
3907        * 'Proxy-Connection: keep-alive' line tells us the
3908        * connection will be kept alive for our pleasure.
3909        * Default action for 1.0 is to close.
3910        */
3911       connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
3912       infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
3913     }
3914     else if((conn->httpversion == 11) &&
3915             conn->bits.httpproxy &&
3916             Curl_compareheader(k->p,
3917                                "Proxy-Connection:", "close")) {
3918       /*
3919        * We get a HTTP/1.1 response from a proxy and it says it'll
3920        * close down after this transfer.
3921        */
3922       connclose(conn, "Proxy-Connection: asked to close after done");
3923       infof(data, "HTTP/1.1 proxy connection set close!\n");
3924     }
3925     else if((conn->httpversion == 10) &&
3926             Curl_compareheader(k->p, "Connection:", "keep-alive")) {
3927       /*
3928        * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3929        * tells us the connection will be kept alive for our
3930        * pleasure.  Default action for 1.0 is to close.
3931        *
3932        * [RFC2068, section 19.7.1] */
3933       connkeep(conn, "Connection keep-alive");
3934       infof(data, "HTTP/1.0 connection set to keep alive!\n");
3935     }
3936     else if(Curl_compareheader(k->p, "Connection:", "close")) {
3937       /*
3938        * [RFC 2616, section 8.1.2.1]
3939        * "Connection: close" is HTTP/1.1 language and means that
3940        * the connection will close when this request has been
3941        * served.
3942        */
3943       streamclose(conn, "Connection: close used");
3944     }
3945     else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", k->p)) {
3946       /* One or more encodings. We check for chunked and/or a compression
3947          algorithm. */
3948       /*
3949        * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3950        * means that the server will send a series of "chunks". Each
3951        * chunk starts with line with info (including size of the
3952        * coming block) (terminated with CRLF), then a block of data
3953        * with the previously mentioned size. There can be any amount
3954        * of chunks, and a chunk-data set to zero signals the
3955        * end-of-chunks. */
3956 
3957       result = Curl_build_unencoding_stack(conn, k->p + 18, TRUE);
3958       if(result)
3959         return result;
3960     }
3961     else if(!k->http_bodyless && checkprefix("Content-Encoding:", k->p) &&
3962             data->set.str[STRING_ENCODING]) {
3963       /*
3964        * Process Content-Encoding. Look for the values: identity,
3965        * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3966        * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3967        * 2616). zlib cannot handle compress.  However, errors are
3968        * handled further down when the response body is processed
3969        */
3970       result = Curl_build_unencoding_stack(conn, k->p + 17, FALSE);
3971       if(result)
3972         return result;
3973     }
3974     else if(checkprefix("Retry-After:", k->p)) {
3975       /* Retry-After = HTTP-date / delay-seconds */
3976       curl_off_t retry_after = 0; /* zero for unknown or "now" */
3977       time_t date = Curl_getdate_capped(&k->p[12]);
3978       if(-1 == date) {
3979         /* not a date, try it as a decimal number */
3980         (void)curlx_strtoofft(&k->p[12], NULL, 10, &retry_after);
3981       }
3982       else
3983         /* convert date to number of seconds into the future */
3984         retry_after = date - time(NULL);
3985       data->info.retry_after = retry_after; /* store it */
3986     }
3987     else if(!k->http_bodyless && checkprefix("Content-Range:", k->p)) {
3988       /* Content-Range: bytes [num]-
3989          Content-Range: bytes: [num]-
3990          Content-Range: [num]-
3991          Content-Range: [asterisk]/[total]
3992 
3993          The second format was added since Sun's webserver
3994          JavaWebServer/1.1.1 obviously sends the header this way!
3995          The third added since some servers use that!
3996          The forth means the requested range was unsatisfied.
3997       */
3998 
3999       char *ptr = k->p + 14;
4000 
4001       /* Move forward until first digit or asterisk */
4002       while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
4003         ptr++;
4004 
4005       /* if it truly stopped on a digit */
4006       if(ISDIGIT(*ptr)) {
4007         if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
4008           if(data->state.resume_from == k->offset)
4009             /* we asked for a resume and we got it */
4010             k->content_range = TRUE;
4011         }
4012       }
4013       else
4014         data->state.resume_from = 0; /* get everything */
4015     }
4016 #if !defined(CURL_DISABLE_COOKIES)
4017     else if(data->cookies && data->state.cookie_engine &&
4018             checkprefix("Set-Cookie:", k->p)) {
4019       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
4020                       CURL_LOCK_ACCESS_SINGLE);
4021       Curl_cookie_add(data,
4022                       data->cookies, TRUE, FALSE, k->p + 11,
4023                       /* If there is a custom-set Host: name, use it
4024                          here, or else use real peer host name. */
4025                       conn->allocptr.cookiehost?
4026                       conn->allocptr.cookiehost:conn->host.name,
4027                       data->state.up.path,
4028                       (conn->handler->protocol&CURLPROTO_HTTPS)?
4029                       TRUE:FALSE);
4030       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
4031     }
4032 #endif
4033     else if(!k->http_bodyless && checkprefix("Last-Modified:", k->p) &&
4034             (data->set.timecondition || data->set.get_filetime) ) {
4035       k->timeofdoc = Curl_getdate_capped(k->p + strlen("Last-Modified:"));
4036       if(data->set.get_filetime)
4037         data->info.filetime = k->timeofdoc;
4038     }
4039     else if((checkprefix("WWW-Authenticate:", k->p) &&
4040              (401 == k->httpcode)) ||
4041             (checkprefix("Proxy-authenticate:", k->p) &&
4042              (407 == k->httpcode))) {
4043 
4044       bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
4045       char *auth = Curl_copy_header_value(k->p);
4046       if(!auth)
4047         return CURLE_OUT_OF_MEMORY;
4048 
4049       result = Curl_http_input_auth(conn, proxy, auth);
4050 
4051       free(auth);
4052 
4053       if(result)
4054         return result;
4055     }
4056 #ifdef USE_SPNEGO
4057     else if(checkprefix("Persistent-Auth", k->p)) {
4058       struct negotiatedata *negdata = &conn->negotiate;
4059       struct auth *authp = &data->state.authhost;
4060       if(authp->picked == CURLAUTH_NEGOTIATE) {
4061         char *persistentauth = Curl_copy_header_value(k->p);
4062         if(!persistentauth)
4063           return CURLE_OUT_OF_MEMORY;
4064         negdata->noauthpersist = checkprefix("false", persistentauth)?
4065           TRUE:FALSE;
4066         negdata->havenoauthpersist = TRUE;
4067         infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
4068           negdata->noauthpersist, persistentauth);
4069         free(persistentauth);
4070       }
4071     }
4072 #endif
4073     else if((k->httpcode >= 300 && k->httpcode < 400) &&
4074             checkprefix("Location:", k->p) &&
4075             !data->req.location) {
4076       /* this is the URL that the server advises us to use instead */
4077       char *location = Curl_copy_header_value(k->p);
4078       if(!location)
4079         return CURLE_OUT_OF_MEMORY;
4080       if(!*location)
4081         /* ignore empty data */
4082         free(location);
4083       else {
4084         data->req.location = location;
4085 
4086         if(data->set.http_follow_location) {
4087           DEBUGASSERT(!data->req.newurl);
4088           data->req.newurl = strdup(data->req.location); /* clone */
4089           if(!data->req.newurl)
4090             return CURLE_OUT_OF_MEMORY;
4091 
4092           /* some cases of POST and PUT etc needs to rewind the data
4093              stream at this point */
4094           result = http_perhapsrewind(conn);
4095           if(result)
4096             return result;
4097         }
4098       }
4099     }
4100 #ifdef USE_ALTSVC
4101     /* If enabled, the header is incoming and this is over HTTPS */
4102     else if(data->asi && checkprefix("Alt-Svc:", k->p) &&
4103             ((conn->handler->flags & PROTOPT_SSL) ||
4104 #ifdef CURLDEBUG
4105              /* allow debug builds to circumvent the HTTPS restriction */
4106              getenv("CURL_ALTSVC_HTTP")
4107 #else
4108              0
4109 #endif
4110               )) {
4111       /* the ALPN of the current request */
4112       enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
4113       result = Curl_altsvc_parse(data, data->asi,
4114                                  &k->p[ strlen("Alt-Svc:") ],
4115                                  id, conn->host.name,
4116                                  curlx_uitous(conn->remote_port));
4117       if(result)
4118         return result;
4119     }
4120 #endif
4121     else if(conn->handler->protocol & CURLPROTO_RTSP) {
4122       result = Curl_rtsp_parseheader(conn, k->p);
4123       if(result)
4124         return result;
4125     }
4126 
4127     /*
4128      * End of header-checks. Write them to the client.
4129      */
4130 
4131     writetype = CLIENTWRITE_HEADER;
4132     if(data->set.include_header)
4133       writetype |= CLIENTWRITE_BODY;
4134 
4135     if(data->set.verbose)
4136       Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen);
4137 
4138     result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
4139     if(result)
4140       return result;
4141 
4142     data->info.header_size += (long)k->hbuflen;
4143     data->req.headerbytecount += (long)k->hbuflen;
4144 
4145     /* reset hbufp pointer && hbuflen */
4146     k->hbufp = data->state.headerbuff;
4147     k->hbuflen = 0;
4148   }
4149   while(*k->str); /* header line within buffer */
4150 
4151   /* We might have reached the end of the header part here, but
4152      there might be a non-header part left in the end of the read
4153      buffer. */
4154 
4155   return CURLE_OK;
4156 }
4157 
4158 #endif /* CURL_DISABLE_HTTP */
4159