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