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