1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #ifndef CURL_DISABLE_HTTP
26 
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NET_IF_H
38 #include <net/if.h>
39 #endif
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 
44 #ifdef HAVE_SYS_PARAM_H
45 #include <sys/param.h>
46 #endif
47 
48 #ifdef USE_HYPER
49 #include <hyper.h>
50 #endif
51 
52 #include "urldata.h"
53 #include <curl/curl.h>
54 #include "transfer.h"
55 #include "sendf.h"
56 #include "formdata.h"
57 #include "mime.h"
58 #include "progress.h"
59 #include "curl_base64.h"
60 #include "cookie.h"
61 #include "vauth/vauth.h"
62 #include "vtls/vtls.h"
63 #include "http_digest.h"
64 #include "http_ntlm.h"
65 #include "curl_ntlm_wb.h"
66 #include "http_negotiate.h"
67 #include "http_aws_sigv4.h"
68 #include "url.h"
69 #include "share.h"
70 #include "hostip.h"
71 #include "http.h"
72 #include "select.h"
73 #include "parsedate.h" /* for the week day and month names */
74 #include "strtoofft.h"
75 #include "multiif.h"
76 #include "strcase.h"
77 #include "content_encoding.h"
78 #include "http_proxy.h"
79 #include "warnless.h"
80 #include "non-ascii.h"
81 #include "http2.h"
82 #include "connect.h"
83 #include "strdup.h"
84 #include "altsvc.h"
85 #include "hsts.h"
86 #include "c-hyper.h"
87 
88 /* The last 3 #include files should be in this order */
89 #include "curl_printf.h"
90 #include "curl_memory.h"
91 #include "memdebug.h"
92 
93 /*
94  * Forward declarations.
95  */
96 
97 static int http_getsock_do(struct Curl_easy *data,
98                            struct connectdata *conn,
99                            curl_socket_t *socks);
100 static bool http_should_fail(struct Curl_easy *data);
101 
102 #ifndef CURL_DISABLE_PROXY
103 static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
104 #endif
105 
106 #ifdef USE_SSL
107 static CURLcode https_connecting(struct Curl_easy *data, bool *done);
108 static int https_getsock(struct Curl_easy *data,
109                          struct connectdata *conn,
110                          curl_socket_t *socks);
111 #else
112 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
113 #endif
114 static CURLcode http_setup_conn(struct Curl_easy *data,
115                                 struct connectdata *conn);
116 
117 /*
118  * HTTP handler interface.
119  */
120 const struct Curl_handler Curl_handler_http = {
121   "HTTP",                               /* scheme */
122   http_setup_conn,                      /* setup_connection */
123   Curl_http,                            /* do_it */
124   Curl_http_done,                       /* done */
125   ZERO_NULL,                            /* do_more */
126   Curl_http_connect,                    /* connect_it */
127   ZERO_NULL,                            /* connecting */
128   ZERO_NULL,                            /* doing */
129   ZERO_NULL,                            /* proto_getsock */
130   http_getsock_do,                      /* doing_getsock */
131   ZERO_NULL,                            /* domore_getsock */
132   ZERO_NULL,                            /* perform_getsock */
133   ZERO_NULL,                            /* disconnect */
134   ZERO_NULL,                            /* readwrite */
135   ZERO_NULL,                            /* connection_check */
136   ZERO_NULL,                            /* attach connection */
137   PORT_HTTP,                            /* defport */
138   CURLPROTO_HTTP,                       /* protocol */
139   CURLPROTO_HTTP,                       /* family */
140   PROTOPT_CREDSPERREQUEST |             /* flags */
141   PROTOPT_USERPWDCTRL
142 };
143 
144 #ifdef USE_SSL
145 /*
146  * HTTPS handler interface.
147  */
148 const struct Curl_handler Curl_handler_https = {
149   "HTTPS",                              /* scheme */
150   http_setup_conn,                      /* setup_connection */
151   Curl_http,                            /* do_it */
152   Curl_http_done,                       /* done */
153   ZERO_NULL,                            /* do_more */
154   Curl_http_connect,                    /* connect_it */
155   https_connecting,                     /* connecting */
156   ZERO_NULL,                            /* doing */
157   https_getsock,                        /* proto_getsock */
158   http_getsock_do,                      /* doing_getsock */
159   ZERO_NULL,                            /* domore_getsock */
160   ZERO_NULL,                            /* perform_getsock */
161   ZERO_NULL,                            /* disconnect */
162   ZERO_NULL,                            /* readwrite */
163   ZERO_NULL,                            /* connection_check */
164   ZERO_NULL,                            /* attach connection */
165   PORT_HTTPS,                           /* defport */
166   CURLPROTO_HTTPS,                      /* protocol */
167   CURLPROTO_HTTP,                       /* family */
168   PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
169   PROTOPT_USERPWDCTRL
170 };
171 #endif
172 
http_setup_conn(struct Curl_easy * data,struct connectdata * conn)173 static CURLcode http_setup_conn(struct Curl_easy *data,
174                                 struct connectdata *conn)
175 {
176   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
177      during this request */
178   struct HTTP *http;
179   DEBUGASSERT(data->req.p.http == NULL);
180 
181   http = calloc(1, sizeof(struct HTTP));
182   if(!http)
183     return CURLE_OUT_OF_MEMORY;
184 
185   Curl_mime_initpart(&http->form, data);
186   data->req.p.http = http;
187 
188   if(data->state.httpwant == CURL_HTTP_VERSION_3) {
189     if(conn->handler->flags & PROTOPT_SSL)
190       /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
191          the QUIC dance. */
192       conn->transport = TRNSPRT_QUIC;
193     else {
194       failf(data, "HTTP/3 requested for non-HTTPS URL");
195       return CURLE_URL_MALFORMAT;
196     }
197   }
198   else {
199     if(!CONN_INUSE(conn))
200       /* if not already multi-using, setup connection details */
201       Curl_http2_setup_conn(conn);
202     Curl_http2_setup_req(data);
203   }
204   return CURLE_OK;
205 }
206 
207 #ifndef CURL_DISABLE_PROXY
208 /*
209  * checkProxyHeaders() checks the linked list of custom proxy headers
210  * if proxy headers are not available, then it will lookup into http header
211  * link list
212  *
213  * It takes a connectdata struct as input to see if this is a proxy request or
214  * not, as it then might check a different header list. Provide the header
215  * prefix without colon!
216  */
Curl_checkProxyheaders(struct Curl_easy * data,const struct connectdata * conn,const char * thisheader)217 char *Curl_checkProxyheaders(struct Curl_easy *data,
218                              const struct connectdata *conn,
219                              const char *thisheader)
220 {
221   struct curl_slist *head;
222   size_t thislen = strlen(thisheader);
223 
224   for(head = (conn->bits.proxy && data->set.sep_headers) ?
225         data->set.proxyheaders : data->set.headers;
226       head; head = head->next) {
227     if(strncasecompare(head->data, thisheader, thislen) &&
228        Curl_headersep(head->data[thislen]))
229       return head->data;
230   }
231 
232   return NULL;
233 }
234 #else
235 /* disabled */
236 #define Curl_checkProxyheaders(x,y,z) NULL
237 #endif
238 
239 /*
240  * Strip off leading and trailing whitespace from the value in the
241  * given HTTP header line and return a strdupped copy. Returns NULL in
242  * case of allocation failure. Returns an empty string if the header value
243  * consists entirely of whitespace.
244  */
Curl_copy_header_value(const char * header)245 char *Curl_copy_header_value(const char *header)
246 {
247   const char *start;
248   const char *end;
249   char *value;
250   size_t len;
251 
252   /* Find the end of the header name */
253   while(*header && (*header != ':'))
254     ++header;
255 
256   if(*header)
257     /* Skip over colon */
258     ++header;
259 
260   /* Find the first non-space letter */
261   start = header;
262   while(*start && ISSPACE(*start))
263     start++;
264 
265   /* data is in the host encoding so
266      use '\r' and '\n' instead of 0x0d and 0x0a */
267   end = strchr(start, '\r');
268   if(!end)
269     end = strchr(start, '\n');
270   if(!end)
271     end = strchr(start, '\0');
272   if(!end)
273     return NULL;
274 
275   /* skip all trailing space letters */
276   while((end > start) && ISSPACE(*end))
277     end--;
278 
279   /* get length of the type */
280   len = end - start + 1;
281 
282   value = malloc(len + 1);
283   if(!value)
284     return NULL;
285 
286   memcpy(value, start, len);
287   value[len] = 0; /* null-terminate */
288 
289   return value;
290 }
291 
292 #ifndef CURL_DISABLE_HTTP_AUTH
293 /*
294  * http_output_basic() sets up an Authorization: header (or the proxy version)
295  * for HTTP Basic authentication.
296  *
297  * Returns CURLcode.
298  */
http_output_basic(struct Curl_easy * data,bool proxy)299 static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
300 {
301   size_t size = 0;
302   char *authorization = NULL;
303   char **userp;
304   const char *user;
305   const char *pwd;
306   CURLcode result;
307   char *out;
308 
309   /* credentials are unique per transfer for HTTP, do not use the ones for the
310      connection */
311   if(proxy) {
312 #ifndef CURL_DISABLE_PROXY
313     userp = &data->state.aptr.proxyuserpwd;
314     user = data->state.aptr.proxyuser;
315     pwd = data->state.aptr.proxypasswd;
316 #else
317     return CURLE_NOT_BUILT_IN;
318 #endif
319   }
320   else {
321     userp = &data->state.aptr.userpwd;
322     user = data->state.aptr.user;
323     pwd = data->state.aptr.passwd;
324   }
325 
326   out = aprintf("%s:%s", user, pwd ? pwd : "");
327   if(!out)
328     return CURLE_OUT_OF_MEMORY;
329 
330   result = Curl_base64_encode(data, out, strlen(out), &authorization, &size);
331   if(result)
332     goto fail;
333 
334   if(!authorization) {
335     result = CURLE_REMOTE_ACCESS_DENIED;
336     goto fail;
337   }
338 
339   free(*userp);
340   *userp = aprintf("%sAuthorization: Basic %s\r\n",
341                    proxy ? "Proxy-" : "",
342                    authorization);
343   free(authorization);
344   if(!*userp) {
345     result = CURLE_OUT_OF_MEMORY;
346     goto fail;
347   }
348 
349   fail:
350   free(out);
351   return result;
352 }
353 
354 /*
355  * http_output_bearer() sets up an Authorization: header
356  * for HTTP Bearer authentication.
357  *
358  * Returns CURLcode.
359  */
http_output_bearer(struct Curl_easy * data)360 static CURLcode http_output_bearer(struct Curl_easy *data)
361 {
362   char **userp;
363   CURLcode result = CURLE_OK;
364 
365   userp = &data->state.aptr.userpwd;
366   free(*userp);
367   *userp = aprintf("Authorization: Bearer %s\r\n",
368                    data->set.str[STRING_BEARER]);
369 
370   if(!*userp) {
371     result = CURLE_OUT_OF_MEMORY;
372     goto fail;
373   }
374 
375   fail:
376   return result;
377 }
378 
379 #endif
380 
381 /* pickoneauth() selects the most favourable authentication method from the
382  * ones available and the ones we want.
383  *
384  * return TRUE if one was picked
385  */
pickoneauth(struct auth * pick,unsigned long mask)386 static bool pickoneauth(struct auth *pick, unsigned long mask)
387 {
388   bool picked;
389   /* only deal with authentication we want */
390   unsigned long avail = pick->avail & pick->want & mask;
391   picked = TRUE;
392 
393   /* The order of these checks is highly relevant, as this will be the order
394      of preference in case of the existence of multiple accepted types. */
395   if(avail & CURLAUTH_NEGOTIATE)
396     pick->picked = CURLAUTH_NEGOTIATE;
397   else if(avail & CURLAUTH_BEARER)
398     pick->picked = CURLAUTH_BEARER;
399   else if(avail & CURLAUTH_DIGEST)
400     pick->picked = CURLAUTH_DIGEST;
401   else if(avail & CURLAUTH_NTLM)
402     pick->picked = CURLAUTH_NTLM;
403   else if(avail & CURLAUTH_NTLM_WB)
404     pick->picked = CURLAUTH_NTLM_WB;
405   else if(avail & CURLAUTH_BASIC)
406     pick->picked = CURLAUTH_BASIC;
407   else if(avail & CURLAUTH_AWS_SIGV4)
408     pick->picked = CURLAUTH_AWS_SIGV4;
409   else {
410     pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
411     picked = FALSE;
412   }
413   pick->avail = CURLAUTH_NONE; /* clear it here */
414 
415   return picked;
416 }
417 
418 /*
419  * http_perhapsrewind()
420  *
421  * If we are doing POST or PUT {
422  *   If we have more data to send {
423  *     If we are doing NTLM {
424  *       Keep sending since we must not disconnect
425  *     }
426  *     else {
427  *       If there is more than just a little data left to send, close
428  *       the current connection by force.
429  *     }
430  *   }
431  *   If we have sent any data {
432  *     If we don't have track of all the data {
433  *       call app to tell it to rewind
434  *     }
435  *     else {
436  *       rewind internally so that the operation can restart fine
437  *     }
438  *   }
439  * }
440  */
http_perhapsrewind(struct Curl_easy * data,struct connectdata * conn)441 static CURLcode http_perhapsrewind(struct Curl_easy *data,
442                                    struct connectdata *conn)
443 {
444   struct HTTP *http = data->req.p.http;
445   curl_off_t bytessent;
446   curl_off_t expectsend = -1; /* default is unknown */
447 
448   if(!http)
449     /* If this is still NULL, we have not reach very far and we can safely
450        skip this rewinding stuff */
451     return CURLE_OK;
452 
453   switch(data->state.httpreq) {
454   case HTTPREQ_GET:
455   case HTTPREQ_HEAD:
456     return CURLE_OK;
457   default:
458     break;
459   }
460 
461   bytessent = data->req.writebytecount;
462 
463   if(conn->bits.authneg) {
464     /* This is a state where we are known to be negotiating and we don't send
465        any data then. */
466     expectsend = 0;
467   }
468   else if(!conn->bits.protoconnstart) {
469     /* HTTP CONNECT in progress: there is no body */
470     expectsend = 0;
471   }
472   else {
473     /* figure out how much data we are expected to send */
474     switch(data->state.httpreq) {
475     case HTTPREQ_POST:
476     case HTTPREQ_PUT:
477       if(data->state.infilesize != -1)
478         expectsend = data->state.infilesize;
479       break;
480     case HTTPREQ_POST_FORM:
481     case HTTPREQ_POST_MIME:
482       expectsend = http->postsize;
483       break;
484     default:
485       break;
486     }
487   }
488 
489   conn->bits.rewindaftersend = FALSE; /* default */
490 
491   if((expectsend == -1) || (expectsend > bytessent)) {
492 #if defined(USE_NTLM)
493     /* There is still data left to send */
494     if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
495        (data->state.authhost.picked == CURLAUTH_NTLM) ||
496        (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
497        (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
498       if(((expectsend - bytessent) < 2000) ||
499          (conn->http_ntlm_state != NTLMSTATE_NONE) ||
500          (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
501         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
502            data left to send, keep on sending. */
503 
504         /* rewind data when completely done sending! */
505         if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
506           conn->bits.rewindaftersend = TRUE;
507           infof(data, "Rewind stream after send");
508         }
509 
510         return CURLE_OK;
511       }
512 
513       if(conn->bits.close)
514         /* this is already marked to get closed */
515         return CURLE_OK;
516 
517       infof(data, "NTLM send, close instead of sending %"
518             CURL_FORMAT_CURL_OFF_T " bytes",
519             (curl_off_t)(expectsend - bytessent));
520     }
521 #endif
522 #if defined(USE_SPNEGO)
523     /* There is still data left to send */
524     if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
525        (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
526       if(((expectsend - bytessent) < 2000) ||
527          (conn->http_negotiate_state != GSS_AUTHNONE) ||
528          (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
529         /* The NEGOTIATE-negotiation has started *OR*
530         there is just a little (<2K) data left to send, keep on sending. */
531 
532         /* rewind data when completely done sending! */
533         if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
534           conn->bits.rewindaftersend = TRUE;
535           infof(data, "Rewind stream after send");
536         }
537 
538         return CURLE_OK;
539       }
540 
541       if(conn->bits.close)
542         /* this is already marked to get closed */
543         return CURLE_OK;
544 
545       infof(data, "NEGOTIATE send, close instead of sending %"
546         CURL_FORMAT_CURL_OFF_T " bytes",
547         (curl_off_t)(expectsend - bytessent));
548     }
549 #endif
550 
551     /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
552     streamclose(conn, "Mid-auth HTTP and much data left to send");
553     data->req.size = 0; /* don't download any more than 0 bytes */
554 
555     /* There still is data left to send, but this connection is marked for
556        closure so we can safely do the rewind right now */
557   }
558 
559   if(bytessent)
560     /* we rewind now at once since if we already sent something */
561     return Curl_readrewind(data);
562 
563   return CURLE_OK;
564 }
565 
566 /*
567  * Curl_http_auth_act() gets called when all HTTP headers have been received
568  * and it checks what authentication methods that are available and decides
569  * which one (if any) to use. It will set 'newurl' if an auth method was
570  * picked.
571  */
572 
Curl_http_auth_act(struct Curl_easy * data)573 CURLcode Curl_http_auth_act(struct Curl_easy *data)
574 {
575   struct connectdata *conn = data->conn;
576   bool pickhost = FALSE;
577   bool pickproxy = FALSE;
578   CURLcode result = CURLE_OK;
579   unsigned long authmask = ~0ul;
580 
581   if(!data->set.str[STRING_BEARER])
582     authmask &= (unsigned long)~CURLAUTH_BEARER;
583 
584   if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
585     /* this is a transient response code, ignore */
586     return CURLE_OK;
587 
588   if(data->state.authproblem)
589     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
590 
591   if((conn->bits.user_passwd || data->set.str[STRING_BEARER]) &&
592      ((data->req.httpcode == 401) ||
593       (conn->bits.authneg && data->req.httpcode < 300))) {
594     pickhost = pickoneauth(&data->state.authhost, authmask);
595     if(!pickhost)
596       data->state.authproblem = TRUE;
597     if(data->state.authhost.picked == CURLAUTH_NTLM &&
598        conn->httpversion > 11) {
599       infof(data, "Forcing HTTP/1.1 for NTLM");
600       connclose(conn, "Force HTTP/1.1 connection");
601       data->state.httpwant = CURL_HTTP_VERSION_1_1;
602     }
603   }
604 #ifndef CURL_DISABLE_PROXY
605   if(conn->bits.proxy_user_passwd &&
606      ((data->req.httpcode == 407) ||
607       (conn->bits.authneg && data->req.httpcode < 300))) {
608     pickproxy = pickoneauth(&data->state.authproxy,
609                             authmask & ~CURLAUTH_BEARER);
610     if(!pickproxy)
611       data->state.authproblem = TRUE;
612   }
613 #endif
614 
615   if(pickhost || pickproxy) {
616     if((data->state.httpreq != HTTPREQ_GET) &&
617        (data->state.httpreq != HTTPREQ_HEAD) &&
618        !conn->bits.rewindaftersend) {
619       result = http_perhapsrewind(data, conn);
620       if(result)
621         return result;
622     }
623     /* In case this is GSS auth, the newurl field is already allocated so
624        we must make sure to free it before allocating a new one. As figured
625        out in bug #2284386 */
626     Curl_safefree(data->req.newurl);
627     data->req.newurl = strdup(data->state.url); /* clone URL */
628     if(!data->req.newurl)
629       return CURLE_OUT_OF_MEMORY;
630   }
631   else if((data->req.httpcode < 300) &&
632           (!data->state.authhost.done) &&
633           conn->bits.authneg) {
634     /* no (known) authentication available,
635        authentication is not "done" yet and
636        no authentication seems to be required and
637        we didn't try HEAD or GET */
638     if((data->state.httpreq != HTTPREQ_GET) &&
639        (data->state.httpreq != HTTPREQ_HEAD)) {
640       data->req.newurl = strdup(data->state.url); /* clone URL */
641       if(!data->req.newurl)
642         return CURLE_OUT_OF_MEMORY;
643       data->state.authhost.done = TRUE;
644     }
645   }
646   if(http_should_fail(data)) {
647     failf(data, "The requested URL returned error: %d",
648           data->req.httpcode);
649     result = CURLE_HTTP_RETURNED_ERROR;
650   }
651 
652   return result;
653 }
654 
655 #ifndef CURL_DISABLE_HTTP_AUTH
656 /*
657  * Output the correct authentication header depending on the auth type
658  * and whether or not it is to a proxy.
659  */
660 static CURLcode
output_auth_headers(struct Curl_easy * data,struct connectdata * conn,struct auth * authstatus,const char * request,const char * path,bool proxy)661 output_auth_headers(struct Curl_easy *data,
662                     struct connectdata *conn,
663                     struct auth *authstatus,
664                     const char *request,
665                     const char *path,
666                     bool proxy)
667 {
668   const char *auth = NULL;
669   CURLcode result = CURLE_OK;
670 
671 #ifdef CURL_DISABLE_CRYPTO_AUTH
672   (void)request;
673   (void)path;
674 #endif
675 #ifndef CURL_DISABLE_CRYPTO_AUTH
676   if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
677     auth = "AWS_SIGV4";
678     result = Curl_output_aws_sigv4(data, proxy);
679     if(result)
680       return result;
681   }
682   else
683 #endif
684 #ifdef USE_SPNEGO
685   if(authstatus->picked == CURLAUTH_NEGOTIATE) {
686     auth = "Negotiate";
687     result = Curl_output_negotiate(data, conn, proxy);
688     if(result)
689       return result;
690   }
691   else
692 #endif
693 #ifdef USE_NTLM
694   if(authstatus->picked == CURLAUTH_NTLM) {
695     auth = "NTLM";
696     result = Curl_output_ntlm(data, proxy);
697     if(result)
698       return result;
699   }
700   else
701 #endif
702 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
703   if(authstatus->picked == CURLAUTH_NTLM_WB) {
704     auth = "NTLM_WB";
705     result = Curl_output_ntlm_wb(data, conn, proxy);
706     if(result)
707       return result;
708   }
709   else
710 #endif
711 #ifndef CURL_DISABLE_CRYPTO_AUTH
712   if(authstatus->picked == CURLAUTH_DIGEST) {
713     auth = "Digest";
714     result = Curl_output_digest(data,
715                                 proxy,
716                                 (const unsigned char *)request,
717                                 (const unsigned char *)path);
718     if(result)
719       return result;
720   }
721   else
722 #endif
723   if(authstatus->picked == CURLAUTH_BASIC) {
724     /* Basic */
725     if(
726 #ifndef CURL_DISABLE_PROXY
727       (proxy && conn->bits.proxy_user_passwd &&
728        !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) ||
729 #endif
730       (!proxy && conn->bits.user_passwd &&
731        !Curl_checkheaders(data, "Authorization"))) {
732       auth = "Basic";
733       result = http_output_basic(data, proxy);
734       if(result)
735         return result;
736     }
737 
738     /* NOTE: this function should set 'done' TRUE, as the other auth
739        functions work that way */
740     authstatus->done = TRUE;
741   }
742   if(authstatus->picked == CURLAUTH_BEARER) {
743     /* Bearer */
744     if((!proxy && data->set.str[STRING_BEARER] &&
745         !Curl_checkheaders(data, "Authorization"))) {
746       auth = "Bearer";
747       result = http_output_bearer(data);
748       if(result)
749         return result;
750     }
751 
752     /* NOTE: this function should set 'done' TRUE, as the other auth
753        functions work that way */
754     authstatus->done = TRUE;
755   }
756 
757   if(auth) {
758 #ifndef CURL_DISABLE_PROXY
759     infof(data, "%s auth using %s with user '%s'",
760           proxy ? "Proxy" : "Server", auth,
761           proxy ? (data->state.aptr.proxyuser ?
762                    data->state.aptr.proxyuser : "") :
763           (data->state.aptr.user ?
764            data->state.aptr.user : ""));
765 #else
766     infof(data, "Server auth using %s with user '%s'",
767           auth, data->state.aptr.user ?
768           data->state.aptr.user : "");
769 #endif
770     authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
771   }
772   else
773     authstatus->multipass = FALSE;
774 
775   return CURLE_OK;
776 }
777 
778 /**
779  * Curl_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   DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP));
2906   if(data->req.ignore_cl) {
2907     k->size = k->maxdownload = -1;
2908   }
2909   else if(k->size != -1) {
2910     /* We wait until after all headers have been received to set this so that
2911        we know for sure Content-Length is valid. */
2912     if(data->set.max_filesize &&
2913        k->size > data->set.max_filesize) {
2914       failf(data, "Maximum file size exceeded");
2915       return CURLE_FILESIZE_EXCEEDED;
2916     }
2917     Curl_pgrsSetDownloadSize(data, k->size);
2918   }
2919 
2920   if(data->req.newurl) {
2921     if(conn->bits.close) {
2922       /* Abort after the headers if "follow Location" is set
2923          and we're set to close anyway. */
2924       k->keepon &= ~KEEP_RECV;
2925       *done = TRUE;
2926       return CURLE_OK;
2927     }
2928     /* We have a new url to load, but since we want to be able to re-use this
2929        connection properly, we read the full response in "ignore more" */
2930     k->ignorebody = TRUE;
2931     infof(data, "Ignoring the response-body");
2932   }
2933   if(data->state.resume_from && !k->content_range &&
2934      (data->state.httpreq == HTTPREQ_GET) &&
2935      !k->ignorebody) {
2936 
2937     if(k->size == data->state.resume_from) {
2938       /* The resume point is at the end of file, consider this fine even if it
2939          doesn't allow resume from here. */
2940       infof(data, "The entire document is already downloaded");
2941       connclose(conn, "already downloaded");
2942       /* Abort download */
2943       k->keepon &= ~KEEP_RECV;
2944       *done = TRUE;
2945       return CURLE_OK;
2946     }
2947 
2948     /* we wanted to resume a download, although the server doesn't seem to
2949      * support this and we did this with a GET (if it wasn't a GET we did a
2950      * POST or PUT resume) */
2951     failf(data, "HTTP server doesn't seem to support "
2952           "byte ranges. Cannot resume.");
2953     return CURLE_RANGE_ERROR;
2954   }
2955 
2956   if(data->set.timecondition && !data->state.range) {
2957     /* A time condition has been set AND no ranges have been requested. This
2958        seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
2959        action for a HTTP/1.1 client */
2960 
2961     if(!Curl_meets_timecondition(data, k->timeofdoc)) {
2962       *done = TRUE;
2963       /* We're simulating a http 304 from server so we return
2964          what should have been returned from the server */
2965       data->info.httpcode = 304;
2966       infof(data, "Simulate a HTTP 304 response!");
2967       /* we abort the transfer before it is completed == we ruin the
2968          re-use ability. Close the connection */
2969       connclose(conn, "Simulated 304 handling");
2970       return CURLE_OK;
2971     }
2972   } /* we have a time condition */
2973 
2974   return CURLE_OK;
2975 }
2976 
2977 #ifdef HAVE_LIBZ
Curl_transferencode(struct Curl_easy * data)2978 CURLcode Curl_transferencode(struct Curl_easy *data)
2979 {
2980   if(!Curl_checkheaders(data, "TE") &&
2981      data->set.http_transfer_encoding) {
2982     /* When we are to insert a TE: header in the request, we must also insert
2983        TE in a Connection: header, so we need to merge the custom provided
2984        Connection: header and prevent the original to get sent. Note that if
2985        the user has inserted his/her own TE: header we don't do this magic
2986        but then assume that the user will handle it all! */
2987     char *cptr = Curl_checkheaders(data, "Connection");
2988 #define TE_HEADER "TE: gzip\r\n"
2989 
2990     Curl_safefree(data->state.aptr.te);
2991 
2992     if(cptr) {
2993       cptr = Curl_copy_header_value(cptr);
2994       if(!cptr)
2995         return CURLE_OUT_OF_MEMORY;
2996     }
2997 
2998     /* Create the (updated) Connection: header */
2999     data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
3000                                 cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
3001 
3002     free(cptr);
3003     if(!data->state.aptr.te)
3004       return CURLE_OUT_OF_MEMORY;
3005   }
3006   return CURLE_OK;
3007 }
3008 #endif
3009 
3010 #ifndef USE_HYPER
3011 /*
3012  * Curl_http() gets called from the generic multi_do() function when a HTTP
3013  * request is to be performed. This creates and sends a properly constructed
3014  * HTTP request.
3015  */
Curl_http(struct Curl_easy * data,bool * done)3016 CURLcode Curl_http(struct Curl_easy *data, bool *done)
3017 {
3018   struct connectdata *conn = data->conn;
3019   CURLcode result = CURLE_OK;
3020   struct HTTP *http;
3021   Curl_HttpReq httpreq;
3022   const char *te = ""; /* transfer-encoding */
3023   const char *request;
3024   const char *httpstring;
3025   struct dynbuf req;
3026   char *altused = NULL;
3027   const char *p_accept;      /* Accept: string */
3028 
3029   /* Always consider the DO phase done after this function call, even if there
3030      may be parts of the request that are not yet sent, since we can deal with
3031      the rest of the request in the PERFORM phase. */
3032   *done = TRUE;
3033 
3034   if(conn->transport != TRNSPRT_QUIC) {
3035     if(conn->httpversion < 20) { /* unless the connection is re-used and
3036                                     already http2 */
3037       switch(conn->negnpn) {
3038       case CURL_HTTP_VERSION_2:
3039         conn->httpversion = 20; /* we know we're on HTTP/2 now */
3040 
3041         result = Curl_http2_switched(data, NULL, 0);
3042         if(result)
3043           return result;
3044         break;
3045       case CURL_HTTP_VERSION_1_1:
3046         /* continue with HTTP/1.1 when explicitly requested */
3047         break;
3048       default:
3049         /* Check if user wants to use HTTP/2 with clear TCP*/
3050 #ifdef USE_NGHTTP2
3051         if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
3052 #ifndef CURL_DISABLE_PROXY
3053           if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
3054             /* We don't support HTTP/2 proxies yet. Also it's debatable
3055                whether or not this setting should apply to HTTP/2 proxies. */
3056             infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
3057             break;
3058           }
3059 #endif
3060           DEBUGF(infof(data, "HTTP/2 over clean TCP"));
3061           conn->httpversion = 20;
3062 
3063           result = Curl_http2_switched(data, NULL, 0);
3064           if(result)
3065             return result;
3066         }
3067 #endif
3068         break;
3069       }
3070     }
3071     else {
3072       /* prepare for a http2 request */
3073       result = Curl_http2_setup(data, conn);
3074       if(result)
3075         return result;
3076     }
3077   }
3078   http = data->req.p.http;
3079   DEBUGASSERT(http);
3080 
3081   result = Curl_http_host(data, conn);
3082   if(result)
3083     return result;
3084 
3085   result = Curl_http_useragent(data);
3086   if(result)
3087     return result;
3088 
3089   Curl_http_method(data, conn, &request, &httpreq);
3090 
3091   /* setup the authentication headers */
3092   {
3093     char *pq = NULL;
3094     if(data->state.up.query) {
3095       pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
3096       if(!pq)
3097         return CURLE_OUT_OF_MEMORY;
3098     }
3099     result = Curl_http_output_auth(data, conn, request, httpreq,
3100                                    (pq ? pq : data->state.up.path), FALSE);
3101     free(pq);
3102     if(result)
3103       return result;
3104   }
3105 
3106   Curl_safefree(data->state.aptr.ref);
3107   if(data->state.referer && !Curl_checkheaders(data, "Referer")) {
3108     data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
3109     if(!data->state.aptr.ref)
3110       return CURLE_OUT_OF_MEMORY;
3111   }
3112 
3113   if(!Curl_checkheaders(data, "Accept-Encoding") &&
3114      data->set.str[STRING_ENCODING]) {
3115     Curl_safefree(data->state.aptr.accept_encoding);
3116     data->state.aptr.accept_encoding =
3117       aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
3118     if(!data->state.aptr.accept_encoding)
3119       return CURLE_OUT_OF_MEMORY;
3120   }
3121   else
3122     Curl_safefree(data->state.aptr.accept_encoding);
3123 
3124 #ifdef HAVE_LIBZ
3125   /* we only consider transfer-encoding magic if libz support is built-in */
3126   result = Curl_transferencode(data);
3127   if(result)
3128     return result;
3129 #endif
3130 
3131   result = Curl_http_body(data, conn, httpreq, &te);
3132   if(result)
3133     return result;
3134 
3135   p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
3136 
3137   result = Curl_http_resume(data, conn, httpreq);
3138   if(result)
3139     return result;
3140 
3141   result = Curl_http_range(data, httpreq);
3142   if(result)
3143     return result;
3144 
3145   httpstring = get_http_string(data, conn);
3146 
3147   /* initialize a dynamic send-buffer */
3148   Curl_dyn_init(&req, DYN_HTTP_REQUEST);
3149 
3150   /* make sure the header buffer is reset - if there are leftovers from a
3151      previous transfer */
3152   Curl_dyn_reset(&data->state.headerb);
3153 
3154   /* add the main request stuff */
3155   /* GET/HEAD/POST/PUT */
3156   result = Curl_dyn_addf(&req, "%s ", request);
3157   if(!result)
3158     result = Curl_http_target(data, conn, &req);
3159   if(result) {
3160     Curl_dyn_free(&req);
3161     return result;
3162   }
3163 
3164 #ifndef CURL_DISABLE_ALTSVC
3165   if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) {
3166     altused = aprintf("Alt-Used: %s:%d\r\n",
3167                       conn->conn_to_host.name, conn->conn_to_port);
3168     if(!altused) {
3169       Curl_dyn_free(&req);
3170       return CURLE_OUT_OF_MEMORY;
3171     }
3172   }
3173 #endif
3174   result =
3175     Curl_dyn_addf(&req,
3176                   " HTTP/%s\r\n" /* HTTP version */
3177                   "%s" /* host */
3178                   "%s" /* proxyuserpwd */
3179                   "%s" /* userpwd */
3180                   "%s" /* range */
3181                   "%s" /* user agent */
3182                   "%s" /* accept */
3183                   "%s" /* TE: */
3184                   "%s" /* accept-encoding */
3185                   "%s" /* referer */
3186                   "%s" /* Proxy-Connection */
3187                   "%s" /* transfer-encoding */
3188                   "%s",/* Alt-Used */
3189 
3190                   httpstring,
3191                   (data->state.aptr.host?data->state.aptr.host:""),
3192                   data->state.aptr.proxyuserpwd?
3193                   data->state.aptr.proxyuserpwd:"",
3194                   data->state.aptr.userpwd?data->state.aptr.userpwd:"",
3195                   (data->state.use_range && data->state.aptr.rangeline)?
3196                   data->state.aptr.rangeline:"",
3197                   (data->set.str[STRING_USERAGENT] &&
3198                    *data->set.str[STRING_USERAGENT] &&
3199                    data->state.aptr.uagent)?
3200                   data->state.aptr.uagent:"",
3201                   p_accept?p_accept:"",
3202                   data->state.aptr.te?data->state.aptr.te:"",
3203                   (data->set.str[STRING_ENCODING] &&
3204                    *data->set.str[STRING_ENCODING] &&
3205                    data->state.aptr.accept_encoding)?
3206                   data->state.aptr.accept_encoding:"",
3207                   (data->state.referer && data->state.aptr.ref)?
3208                   data->state.aptr.ref:"" /* Referer: <data> */,
3209 #ifndef CURL_DISABLE_PROXY
3210                   (conn->bits.httpproxy &&
3211                    !conn->bits.tunnel_proxy &&
3212                    !Curl_checkheaders(data, "Proxy-Connection") &&
3213                    !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))?
3214                   "Proxy-Connection: Keep-Alive\r\n":"",
3215 #else
3216                   "",
3217 #endif
3218                   te,
3219                   altused ? altused : ""
3220       );
3221 
3222   /* clear userpwd and proxyuserpwd to avoid re-using old credentials
3223    * from re-used connections */
3224   Curl_safefree(data->state.aptr.userpwd);
3225   Curl_safefree(data->state.aptr.proxyuserpwd);
3226   free(altused);
3227 
3228   if(result) {
3229     Curl_dyn_free(&req);
3230     return result;
3231   }
3232 
3233   if(!(conn->handler->flags&PROTOPT_SSL) &&
3234      conn->httpversion != 20 &&
3235      (data->state.httpwant == CURL_HTTP_VERSION_2)) {
3236     /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
3237        over SSL */
3238     result = Curl_http2_request_upgrade(&req, data);
3239     if(result) {
3240       Curl_dyn_free(&req);
3241       return result;
3242     }
3243   }
3244 
3245   result = Curl_http_cookies(data, conn, &req);
3246   if(!result)
3247     result = Curl_add_timecondition(data, &req);
3248   if(!result)
3249     result = Curl_add_custom_headers(data, FALSE, &req);
3250 
3251   if(!result) {
3252     http->postdata = NULL;  /* nothing to post at this point */
3253     if((httpreq == HTTPREQ_GET) ||
3254        (httpreq == HTTPREQ_HEAD))
3255       Curl_pgrsSetUploadSize(data, 0); /* nothing */
3256 
3257     /* bodysend takes ownership of the 'req' memory on success */
3258     result = Curl_http_bodysend(data, conn, &req, httpreq);
3259   }
3260   if(result) {
3261     Curl_dyn_free(&req);
3262     return result;
3263   }
3264 
3265   if((http->postsize > -1) &&
3266      (http->postsize <= data->req.writebytecount) &&
3267      (http->sending != HTTPSEND_REQUEST))
3268     data->req.upload_done = TRUE;
3269 
3270   if(data->req.writebytecount) {
3271     /* if a request-body has been sent off, we make sure this progress is noted
3272        properly */
3273     Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
3274     if(Curl_pgrsUpdate(data))
3275       result = CURLE_ABORTED_BY_CALLBACK;
3276 
3277     if(!http->postsize) {
3278       /* already sent the entire request body, mark the "upload" as
3279          complete */
3280       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
3281             " out of %" CURL_FORMAT_CURL_OFF_T " bytes",
3282             data->req.writebytecount, http->postsize);
3283       data->req.upload_done = TRUE;
3284       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
3285       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
3286       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3287     }
3288   }
3289 
3290   if((conn->httpversion == 20) && data->req.upload_chunky)
3291     /* upload_chunky was set above to set up the request in a chunky fashion,
3292        but is disabled here again to avoid that the chunked encoded version is
3293        actually used when sending the request body over h2 */
3294     data->req.upload_chunky = FALSE;
3295   return result;
3296 }
3297 
3298 #endif /* USE_HYPER */
3299 
3300 typedef enum {
3301   STATUS_UNKNOWN, /* not enough data to tell yet */
3302   STATUS_DONE, /* a status line was read */
3303   STATUS_BAD /* not a status line */
3304 } statusline;
3305 
3306 
3307 /* Check a string for a prefix. Check no more than 'len' bytes */
checkprefixmax(const char * prefix,const char * buffer,size_t len)3308 static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
3309 {
3310   size_t ch = CURLMIN(strlen(prefix), len);
3311   return curl_strnequal(prefix, buffer, ch);
3312 }
3313 
3314 /*
3315  * checkhttpprefix()
3316  *
3317  * Returns TRUE if member of the list matches prefix of string
3318  */
3319 static statusline
checkhttpprefix(struct Curl_easy * data,const char * s,size_t len)3320 checkhttpprefix(struct Curl_easy *data,
3321                 const char *s, size_t len)
3322 {
3323   struct curl_slist *head = data->set.http200aliases;
3324   statusline rc = STATUS_BAD;
3325   statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3326 #ifdef CURL_DOES_CONVERSIONS
3327   /* convert from the network encoding using a scratch area */
3328   char *scratch = strdup(s);
3329   if(NULL == scratch) {
3330     failf(data, "Failed to allocate memory for conversion!");
3331     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3332   }
3333   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
3334     /* Curl_convert_from_network calls failf if unsuccessful */
3335     free(scratch);
3336     return FALSE; /* can't return CURLE_foobar so return FALSE */
3337   }
3338   s = scratch;
3339 #endif /* CURL_DOES_CONVERSIONS */
3340 
3341   while(head) {
3342     if(checkprefixmax(head->data, s, len)) {
3343       rc = onmatch;
3344       break;
3345     }
3346     head = head->next;
3347   }
3348 
3349   if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
3350     rc = onmatch;
3351 
3352 #ifdef CURL_DOES_CONVERSIONS
3353   free(scratch);
3354 #endif /* CURL_DOES_CONVERSIONS */
3355   return rc;
3356 }
3357 
3358 #ifndef CURL_DISABLE_RTSP
3359 static statusline
checkrtspprefix(struct Curl_easy * data,const char * s,size_t len)3360 checkrtspprefix(struct Curl_easy *data,
3361                 const char *s, size_t len)
3362 {
3363   statusline result = STATUS_BAD;
3364   statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3365 
3366 #ifdef CURL_DOES_CONVERSIONS
3367   /* convert from the network encoding using a scratch area */
3368   char *scratch = strdup(s);
3369   if(NULL == scratch) {
3370     failf(data, "Failed to allocate memory for conversion!");
3371     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
3372   }
3373   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
3374     /* Curl_convert_from_network calls failf if unsuccessful */
3375     result = FALSE; /* can't return CURLE_foobar so return FALSE */
3376   }
3377   else if(checkprefixmax("RTSP/", scratch, len))
3378     result = onmatch;
3379   free(scratch);
3380 #else
3381   (void)data; /* unused */
3382   if(checkprefixmax("RTSP/", s, len))
3383     result = onmatch;
3384 #endif /* CURL_DOES_CONVERSIONS */
3385 
3386   return result;
3387 }
3388 #endif /* CURL_DISABLE_RTSP */
3389 
3390 static statusline
checkprotoprefix(struct Curl_easy * data,struct connectdata * conn,const char * s,size_t len)3391 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
3392                  const char *s, size_t len)
3393 {
3394 #ifndef CURL_DISABLE_RTSP
3395   if(conn->handler->protocol & CURLPROTO_RTSP)
3396     return checkrtspprefix(data, s, len);
3397 #else
3398   (void)conn;
3399 #endif /* CURL_DISABLE_RTSP */
3400 
3401   return checkhttpprefix(data, s, len);
3402 }
3403 
3404 /*
3405  * Curl_http_header() parses a single response header.
3406  */
Curl_http_header(struct Curl_easy * data,struct connectdata * conn,char * headp)3407 CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
3408                           char *headp)
3409 {
3410   CURLcode result;
3411   struct SingleRequest *k = &data->req;
3412   /* Check for Content-Length: header lines to get size */
3413   if(!k->http_bodyless &&
3414      !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
3415     curl_off_t contentlength;
3416     CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"),
3417                                     NULL, 10, &contentlength);
3418 
3419     if(offt == CURL_OFFT_OK) {
3420       k->size = contentlength;
3421       k->maxdownload = k->size;
3422     }
3423     else if(offt == CURL_OFFT_FLOW) {
3424       /* out of range */
3425       if(data->set.max_filesize) {
3426         failf(data, "Maximum file size exceeded");
3427         return CURLE_FILESIZE_EXCEEDED;
3428       }
3429       streamclose(conn, "overflow content-length");
3430       infof(data, "Overflow Content-Length: value!");
3431     }
3432     else {
3433       /* negative or just rubbish - bad HTTP */
3434       failf(data, "Invalid Content-Length: value");
3435       return CURLE_WEIRD_SERVER_REPLY;
3436     }
3437   }
3438   /* check for Content-Type: header lines to get the MIME-type */
3439   else if(checkprefix("Content-Type:", headp)) {
3440     char *contenttype = Curl_copy_header_value(headp);
3441     if(!contenttype)
3442       return CURLE_OUT_OF_MEMORY;
3443     if(!*contenttype)
3444       /* ignore empty data */
3445       free(contenttype);
3446     else {
3447       Curl_safefree(data->info.contenttype);
3448       data->info.contenttype = contenttype;
3449     }
3450   }
3451 #ifndef CURL_DISABLE_PROXY
3452   else if((conn->httpversion == 10) &&
3453           conn->bits.httpproxy &&
3454           Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
3455     /*
3456      * When a HTTP/1.0 reply comes when using a proxy, the
3457      * 'Proxy-Connection: keep-alive' line tells us the
3458      * connection will be kept alive for our pleasure.
3459      * Default action for 1.0 is to close.
3460      */
3461     connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
3462     infof(data, "HTTP/1.0 proxy connection set to keep alive!");
3463   }
3464   else if((conn->httpversion == 11) &&
3465           conn->bits.httpproxy &&
3466           Curl_compareheader(headp, "Proxy-Connection:", "close")) {
3467     /*
3468      * We get a HTTP/1.1 response from a proxy and it says it'll
3469      * close down after this transfer.
3470      */
3471     connclose(conn, "Proxy-Connection: asked to close after done");
3472     infof(data, "HTTP/1.1 proxy connection set close!");
3473   }
3474 #endif
3475   else if((conn->httpversion == 10) &&
3476           Curl_compareheader(headp, "Connection:", "keep-alive")) {
3477     /*
3478      * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3479      * tells us the connection will be kept alive for our
3480      * pleasure.  Default action for 1.0 is to close.
3481      *
3482      * [RFC2068, section 19.7.1] */
3483     connkeep(conn, "Connection keep-alive");
3484     infof(data, "HTTP/1.0 connection set to keep alive!");
3485   }
3486   else if(Curl_compareheader(headp, "Connection:", "close")) {
3487     /*
3488      * [RFC 2616, section 8.1.2.1]
3489      * "Connection: close" is HTTP/1.1 language and means that
3490      * the connection will close when this request has been
3491      * served.
3492      */
3493     streamclose(conn, "Connection: close used");
3494   }
3495   else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
3496     /* One or more encodings. We check for chunked and/or a compression
3497        algorithm. */
3498     /*
3499      * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3500      * means that the server will send a series of "chunks". Each
3501      * chunk starts with line with info (including size of the
3502      * coming block) (terminated with CRLF), then a block of data
3503      * with the previously mentioned size. There can be any amount
3504      * of chunks, and a chunk-data set to zero signals the
3505      * end-of-chunks. */
3506 
3507     result = Curl_build_unencoding_stack(data,
3508                                          headp + strlen("Transfer-Encoding:"),
3509                                          TRUE);
3510     if(result)
3511       return result;
3512     if(!k->chunk) {
3513       /* if this isn't chunked, only close can signal the end of this transfer
3514          as Content-Length is said not to be trusted for transfer-encoding! */
3515       connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
3516       k->ignore_cl = TRUE;
3517     }
3518   }
3519   else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
3520           data->set.str[STRING_ENCODING]) {
3521     /*
3522      * Process Content-Encoding. Look for the values: identity,
3523      * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3524      * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3525      * 2616). zlib cannot handle compress.  However, errors are
3526      * handled further down when the response body is processed
3527      */
3528     result = Curl_build_unencoding_stack(data,
3529                                          headp + strlen("Content-Encoding:"),
3530                                          FALSE);
3531     if(result)
3532       return result;
3533   }
3534   else if(checkprefix("Retry-After:", headp)) {
3535     /* Retry-After = HTTP-date / delay-seconds */
3536     curl_off_t retry_after = 0; /* zero for unknown or "now" */
3537     time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
3538     if(-1 == date) {
3539       /* not a date, try it as a decimal number */
3540       (void)curlx_strtoofft(headp + strlen("Retry-After:"),
3541                             NULL, 10, &retry_after);
3542     }
3543     else
3544       /* convert date to number of seconds into the future */
3545       retry_after = date - time(NULL);
3546     data->info.retry_after = retry_after; /* store it */
3547   }
3548   else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
3549     /* Content-Range: bytes [num]-
3550        Content-Range: bytes: [num]-
3551        Content-Range: [num]-
3552        Content-Range: [asterisk]/[total]
3553 
3554        The second format was added since Sun's webserver
3555        JavaWebServer/1.1.1 obviously sends the header this way!
3556        The third added since some servers use that!
3557        The forth means the requested range was unsatisfied.
3558     */
3559 
3560     char *ptr = headp + strlen("Content-Range:");
3561 
3562     /* Move forward until first digit or asterisk */
3563     while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
3564       ptr++;
3565 
3566     /* if it truly stopped on a digit */
3567     if(ISDIGIT(*ptr)) {
3568       if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
3569         if(data->state.resume_from == k->offset)
3570           /* we asked for a resume and we got it */
3571           k->content_range = TRUE;
3572       }
3573     }
3574     else
3575       data->state.resume_from = 0; /* get everything */
3576   }
3577 #if !defined(CURL_DISABLE_COOKIES)
3578   else if(data->cookies && data->state.cookie_engine &&
3579           checkprefix("Set-Cookie:", headp)) {
3580     /* If there is a custom-set Host: name, use it here, or else use real peer
3581        host name. */
3582     const char *host = data->state.aptr.cookiehost?
3583       data->state.aptr.cookiehost:conn->host.name;
3584     const bool secure_context =
3585       conn->handler->protocol&CURLPROTO_HTTPS ||
3586       strcasecompare("localhost", host) ||
3587       !strcmp(host, "127.0.0.1") ||
3588       !strcmp(host, "[::1]") ? TRUE : FALSE;
3589 
3590     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3591                     CURL_LOCK_ACCESS_SINGLE);
3592     Curl_cookie_add(data, data->cookies, TRUE, FALSE,
3593                     headp + strlen("Set-Cookie:"), host,
3594                     data->state.up.path, secure_context);
3595     Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3596   }
3597 #endif
3598   else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
3599           (data->set.timecondition || data->set.get_filetime) ) {
3600     k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
3601     if(data->set.get_filetime)
3602       data->info.filetime = k->timeofdoc;
3603   }
3604   else if((checkprefix("WWW-Authenticate:", headp) &&
3605            (401 == k->httpcode)) ||
3606           (checkprefix("Proxy-authenticate:", headp) &&
3607            (407 == k->httpcode))) {
3608 
3609     bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3610     char *auth = Curl_copy_header_value(headp);
3611     if(!auth)
3612       return CURLE_OUT_OF_MEMORY;
3613 
3614     result = Curl_http_input_auth(data, proxy, auth);
3615 
3616     free(auth);
3617 
3618     if(result)
3619       return result;
3620   }
3621 #ifdef USE_SPNEGO
3622   else if(checkprefix("Persistent-Auth:", headp)) {
3623     struct negotiatedata *negdata = &conn->negotiate;
3624     struct auth *authp = &data->state.authhost;
3625     if(authp->picked == CURLAUTH_NEGOTIATE) {
3626       char *persistentauth = Curl_copy_header_value(headp);
3627       if(!persistentauth)
3628         return CURLE_OUT_OF_MEMORY;
3629       negdata->noauthpersist = checkprefix("false", persistentauth)?
3630         TRUE:FALSE;
3631       negdata->havenoauthpersist = TRUE;
3632       infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
3633             negdata->noauthpersist, persistentauth);
3634       free(persistentauth);
3635     }
3636   }
3637 #endif
3638   else if((k->httpcode >= 300 && k->httpcode < 400) &&
3639           checkprefix("Location:", headp) &&
3640           !data->req.location) {
3641     /* this is the URL that the server advises us to use instead */
3642     char *location = Curl_copy_header_value(headp);
3643     if(!location)
3644       return CURLE_OUT_OF_MEMORY;
3645     if(!*location)
3646       /* ignore empty data */
3647       free(location);
3648     else {
3649       data->req.location = location;
3650 
3651       if(data->set.http_follow_location) {
3652         DEBUGASSERT(!data->req.newurl);
3653         data->req.newurl = strdup(data->req.location); /* clone */
3654         if(!data->req.newurl)
3655           return CURLE_OUT_OF_MEMORY;
3656 
3657         /* some cases of POST and PUT etc needs to rewind the data
3658            stream at this point */
3659         result = http_perhapsrewind(data, conn);
3660         if(result)
3661           return result;
3662       }
3663     }
3664   }
3665 
3666 #ifndef CURL_DISABLE_HSTS
3667   /* If enabled, the header is incoming and this is over HTTPS */
3668   else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
3669           (conn->handler->flags & PROTOPT_SSL)) {
3670     CURLcode check =
3671       Curl_hsts_parse(data->hsts, data->state.up.hostname,
3672                       headp + strlen("Strict-Transport-Security:"));
3673     if(check)
3674       infof(data, "Illegal STS header skipped");
3675 #ifdef DEBUGBUILD
3676     else
3677       infof(data, "Parsed STS header fine (%zu entries)",
3678             data->hsts->list.size);
3679 #endif
3680   }
3681 #endif
3682 #ifndef CURL_DISABLE_ALTSVC
3683   /* If enabled, the header is incoming and this is over HTTPS */
3684   else if(data->asi && checkprefix("Alt-Svc:", headp) &&
3685           ((conn->handler->flags & PROTOPT_SSL) ||
3686 #ifdef CURLDEBUG
3687            /* allow debug builds to circumvent the HTTPS restriction */
3688            getenv("CURL_ALTSVC_HTTP")
3689 #else
3690            0
3691 #endif
3692             )) {
3693     /* the ALPN of the current request */
3694     enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
3695     result = Curl_altsvc_parse(data, data->asi,
3696                                headp + strlen("Alt-Svc:"),
3697                                id, conn->host.name,
3698                                curlx_uitous(conn->remote_port));
3699     if(result)
3700       return result;
3701   }
3702 #endif
3703   else if(conn->handler->protocol & CURLPROTO_RTSP) {
3704     result = Curl_rtsp_parseheader(data, headp);
3705     if(result)
3706       return result;
3707   }
3708   return CURLE_OK;
3709 }
3710 
3711 /*
3712  * Called after the first HTTP response line (the status line) has been
3713  * received and parsed.
3714  */
3715 
Curl_http_statusline(struct Curl_easy * data,struct connectdata * conn)3716 CURLcode Curl_http_statusline(struct Curl_easy *data,
3717                               struct connectdata *conn)
3718 {
3719   struct SingleRequest *k = &data->req;
3720   data->info.httpcode = k->httpcode;
3721 
3722   data->info.httpversion = conn->httpversion;
3723   if(!data->state.httpversion ||
3724      data->state.httpversion > conn->httpversion)
3725     /* store the lowest server version we encounter */
3726     data->state.httpversion = conn->httpversion;
3727 
3728   /*
3729    * This code executes as part of processing the header.  As a
3730    * result, it's not totally clear how to interpret the
3731    * response code yet as that depends on what other headers may
3732    * be present.  401 and 407 may be errors, but may be OK
3733    * depending on how authentication is working.  Other codes
3734    * are definitely errors, so give up here.
3735    */
3736   if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
3737      k->httpcode == 416) {
3738     /* "Requested Range Not Satisfiable", just proceed and
3739        pretend this is no error */
3740     k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
3741   }
3742 
3743   if(conn->httpversion == 10) {
3744     /* Default action for HTTP/1.0 must be to close, unless
3745        we get one of those fancy headers that tell us the
3746        server keeps it open for us! */
3747     infof(data, "HTTP 1.0, assume close after body");
3748     connclose(conn, "HTTP/1.0 close after body");
3749   }
3750   else if(conn->httpversion == 20 ||
3751           (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
3752     DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
3753     /* HTTP/2 cannot avoid multiplexing since it is a core functionality
3754        of the protocol */
3755     conn->bundle->multiuse = BUNDLE_MULTIPLEX;
3756   }
3757   else if(conn->httpversion >= 11 &&
3758           !conn->bits.close) {
3759     /* If HTTP version is >= 1.1 and connection is persistent */
3760     DEBUGF(infof(data,
3761                  "HTTP 1.1 or later with persistent connection"));
3762   }
3763 
3764   k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
3765   switch(k->httpcode) {
3766   case 304:
3767     /* (quote from RFC2616, section 10.3.5): The 304 response
3768      * MUST NOT contain a message-body, and thus is always
3769      * terminated by the first empty line after the header
3770      * fields.  */
3771     if(data->set.timecondition)
3772       data->info.timecond = TRUE;
3773     /* FALLTHROUGH */
3774   case 204:
3775     /* (quote from RFC2616, section 10.2.5): The server has
3776      * fulfilled the request but does not need to return an
3777      * entity-body ... The 204 response MUST NOT include a
3778      * message-body, and thus is always terminated by the first
3779      * empty line after the header fields. */
3780     k->size = 0;
3781     k->maxdownload = 0;
3782     k->http_bodyless = TRUE;
3783     break;
3784   default:
3785     break;
3786   }
3787   return CURLE_OK;
3788 }
3789 
3790 /*
3791  * Read any HTTP header lines from the server and pass them to the client app.
3792  */
Curl_http_readwrite_headers(struct Curl_easy * data,struct connectdata * conn,ssize_t * nread,bool * stop_reading)3793 CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
3794                                      struct connectdata *conn,
3795                                      ssize_t *nread,
3796                                      bool *stop_reading)
3797 {
3798   CURLcode result;
3799   struct SingleRequest *k = &data->req;
3800   ssize_t onread = *nread;
3801   char *ostr = k->str;
3802   char *headp;
3803   char *str_start;
3804   char *end_ptr;
3805 
3806   /* header line within buffer loop */
3807   do {
3808     size_t rest_length;
3809     size_t full_length;
3810     int writetype;
3811 
3812     /* str_start is start of line within buf */
3813     str_start = k->str;
3814 
3815     /* data is in network encoding so use 0x0a instead of '\n' */
3816     end_ptr = memchr(str_start, 0x0a, *nread);
3817 
3818     if(!end_ptr) {
3819       /* Not a complete header line within buffer, append the data to
3820          the end of the headerbuff. */
3821       result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
3822       if(result)
3823         return result;
3824 
3825       if(!k->headerline) {
3826         /* check if this looks like a protocol header */
3827         statusline st =
3828           checkprotoprefix(data, conn,
3829                            Curl_dyn_ptr(&data->state.headerb),
3830                            Curl_dyn_len(&data->state.headerb));
3831 
3832         if(st == STATUS_BAD) {
3833           /* this is not the beginning of a protocol first header line */
3834           k->header = FALSE;
3835           k->badheader = HEADER_ALLBAD;
3836           streamclose(conn, "bad HTTP: No end-of-message indicator");
3837           if(!data->set.http09_allowed) {
3838             failf(data, "Received HTTP/0.9 when not allowed");
3839             return CURLE_UNSUPPORTED_PROTOCOL;
3840           }
3841           break;
3842         }
3843       }
3844 
3845       break; /* read more and try again */
3846     }
3847 
3848     /* decrease the size of the remaining (supposed) header line */
3849     rest_length = (end_ptr - k->str) + 1;
3850     *nread -= (ssize_t)rest_length;
3851 
3852     k->str = end_ptr + 1; /* move past new line */
3853 
3854     full_length = k->str - str_start;
3855 
3856     result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
3857     if(result)
3858       return result;
3859 
3860     /****
3861      * We now have a FULL header line in 'headerb'.
3862      *****/
3863 
3864     if(!k->headerline) {
3865       /* the first read header */
3866       statusline st = checkprotoprefix(data, conn,
3867                                        Curl_dyn_ptr(&data->state.headerb),
3868                                        Curl_dyn_len(&data->state.headerb));
3869       if(st == STATUS_BAD) {
3870         streamclose(conn, "bad HTTP: No end-of-message indicator");
3871         /* this is not the beginning of a protocol first header line */
3872         if(!data->set.http09_allowed) {
3873           failf(data, "Received HTTP/0.9 when not allowed");
3874           return CURLE_UNSUPPORTED_PROTOCOL;
3875         }
3876         k->header = FALSE;
3877         if(*nread)
3878           /* since there's more, this is a partial bad header */
3879           k->badheader = HEADER_PARTHEADER;
3880         else {
3881           /* this was all we read so it's all a bad header */
3882           k->badheader = HEADER_ALLBAD;
3883           *nread = onread;
3884           k->str = ostr;
3885           return CURLE_OK;
3886         }
3887         break;
3888       }
3889     }
3890 
3891     /* headers are in network encoding so use 0x0a and 0x0d instead of '\n'
3892        and '\r' */
3893     headp = Curl_dyn_ptr(&data->state.headerb);
3894     if((0x0a == *headp) || (0x0d == *headp)) {
3895       size_t headerlen;
3896       /* Zero-length header line means end of headers! */
3897 
3898 #ifdef CURL_DOES_CONVERSIONS
3899       if(0x0d == *headp) {
3900         *headp = '\r'; /* replace with CR in host encoding */
3901         headp++;       /* pass the CR byte */
3902       }
3903       if(0x0a == *headp) {
3904         *headp = '\n'; /* replace with LF in host encoding */
3905         headp++;       /* pass the LF byte */
3906       }
3907 #else
3908       if('\r' == *headp)
3909         headp++; /* pass the \r byte */
3910       if('\n' == *headp)
3911         headp++; /* pass the \n byte */
3912 #endif /* CURL_DOES_CONVERSIONS */
3913 
3914       if(100 <= k->httpcode && 199 >= k->httpcode) {
3915         /* "A user agent MAY ignore unexpected 1xx status responses." */
3916         switch(k->httpcode) {
3917         case 100:
3918           /*
3919            * We have made a HTTP PUT or POST and this is 1.1-lingo
3920            * that tells us that the server is OK with this and ready
3921            * to receive the data.
3922            * However, we'll get more headers now so we must get
3923            * back into the header-parsing state!
3924            */
3925           k->header = TRUE;
3926           k->headerline = 0; /* restart the header line counter */
3927 
3928           /* if we did wait for this do enable write now! */
3929           if(k->exp100 > EXP100_SEND_DATA) {
3930             k->exp100 = EXP100_SEND_DATA;
3931             k->keepon |= KEEP_SEND;
3932             Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3933           }
3934           break;
3935         case 101:
3936           /* Switching Protocols */
3937           if(k->upgr101 == UPGR101_REQUESTED) {
3938             /* Switching to HTTP/2 */
3939             infof(data, "Received 101");
3940             k->upgr101 = UPGR101_RECEIVED;
3941 
3942             /* we'll get more headers (HTTP/2 response) */
3943             k->header = TRUE;
3944             k->headerline = 0; /* restart the header line counter */
3945 
3946             /* switch to http2 now. The bytes after response headers
3947                are also processed here, otherwise they are lost. */
3948             result = Curl_http2_switched(data, k->str, *nread);
3949             if(result)
3950               return result;
3951             *nread = 0;
3952           }
3953           else {
3954             /* Switching to another protocol (e.g. WebSocket) */
3955             k->header = FALSE; /* no more header to parse! */
3956           }
3957           break;
3958         default:
3959           /* the status code 1xx indicates a provisional response, so
3960              we'll get another set of headers */
3961           k->header = TRUE;
3962           k->headerline = 0; /* restart the header line counter */
3963           break;
3964         }
3965       }
3966       else {
3967         k->header = FALSE; /* no more header to parse! */
3968 
3969         if((k->size == -1) && !k->chunk && !conn->bits.close &&
3970            (conn->httpversion == 11) &&
3971            !(conn->handler->protocol & CURLPROTO_RTSP) &&
3972            data->state.httpreq != HTTPREQ_HEAD) {
3973           /* On HTTP 1.1, when connection is not to get closed, but no
3974              Content-Length nor Transfer-Encoding chunked have been
3975              received, according to RFC2616 section 4.4 point 5, we
3976              assume that the server will close the connection to
3977              signal the end of the document. */
3978           infof(data, "no chunk, no close, no size. Assume close to "
3979                 "signal end");
3980           streamclose(conn, "HTTP: No end-of-message indicator");
3981         }
3982       }
3983 
3984       /* At this point we have some idea about the fate of the connection.
3985          If we are closing the connection it may result auth failure. */
3986 #if defined(USE_NTLM)
3987       if(conn->bits.close &&
3988          (((data->req.httpcode == 401) &&
3989            (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
3990           ((data->req.httpcode == 407) &&
3991            (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
3992         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
3993         data->state.authproblem = TRUE;
3994       }
3995 #endif
3996 #if defined(USE_SPNEGO)
3997       if(conn->bits.close &&
3998         (((data->req.httpcode == 401) &&
3999           (conn->http_negotiate_state == GSS_AUTHRECV)) ||
4000          ((data->req.httpcode == 407) &&
4001           (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
4002         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
4003         data->state.authproblem = TRUE;
4004       }
4005       if((conn->http_negotiate_state == GSS_AUTHDONE) &&
4006          (data->req.httpcode != 401)) {
4007         conn->http_negotiate_state = GSS_AUTHSUCC;
4008       }
4009       if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
4010          (data->req.httpcode != 407)) {
4011         conn->proxy_negotiate_state = GSS_AUTHSUCC;
4012       }
4013 #endif
4014 
4015       /* now, only output this if the header AND body are requested:
4016        */
4017       writetype = CLIENTWRITE_HEADER;
4018       if(data->set.include_header)
4019         writetype |= CLIENTWRITE_BODY;
4020 
4021       headerlen = Curl_dyn_len(&data->state.headerb);
4022       result = Curl_client_write(data, writetype,
4023                                  Curl_dyn_ptr(&data->state.headerb),
4024                                  headerlen);
4025       if(result)
4026         return result;
4027 
4028       data->info.header_size += (long)headerlen;
4029       data->req.headerbytecount += (long)headerlen;
4030 
4031       /*
4032        * When all the headers have been parsed, see if we should give
4033        * up and return an error.
4034        */
4035       if(http_should_fail(data)) {
4036         failf(data, "The requested URL returned error: %d",
4037               k->httpcode);
4038         return CURLE_HTTP_RETURNED_ERROR;
4039       }
4040 
4041       data->req.deductheadercount =
4042         (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
4043 
4044       /* Curl_http_auth_act() checks what authentication methods
4045        * that are available and decides which one (if any) to
4046        * use. It will set 'newurl' if an auth method was picked. */
4047       result = Curl_http_auth_act(data);
4048 
4049       if(result)
4050         return result;
4051 
4052       if(k->httpcode >= 300) {
4053         if((!conn->bits.authneg) && !conn->bits.close &&
4054            !conn->bits.rewindaftersend) {
4055           /*
4056            * General treatment of errors when about to send data. Including :
4057            * "417 Expectation Failed", while waiting for 100-continue.
4058            *
4059            * The check for close above is done simply because of something
4060            * else has already deemed the connection to get closed then
4061            * something else should've considered the big picture and we
4062            * avoid this check.
4063            *
4064            * rewindaftersend indicates that something has told libcurl to
4065            * continue sending even if it gets discarded
4066            */
4067 
4068           switch(data->state.httpreq) {
4069           case HTTPREQ_PUT:
4070           case HTTPREQ_POST:
4071           case HTTPREQ_POST_FORM:
4072           case HTTPREQ_POST_MIME:
4073             /* We got an error response. If this happened before the whole
4074              * request body has been sent we stop sending and mark the
4075              * connection for closure after we've read the entire response.
4076              */
4077             Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4078             if(!k->upload_done) {
4079               if((k->httpcode == 417) && data->state.expect100header) {
4080                 /* 417 Expectation Failed - try again without the Expect
4081                    header */
4082                 infof(data, "Got 417 while waiting for a 100");
4083                 data->state.disableexpect = TRUE;
4084                 DEBUGASSERT(!data->req.newurl);
4085                 data->req.newurl = strdup(data->state.url);
4086                 Curl_done_sending(data, k);
4087               }
4088               else if(data->set.http_keep_sending_on_error) {
4089                 infof(data, "HTTP error before end of send, keep sending");
4090                 if(k->exp100 > EXP100_SEND_DATA) {
4091                   k->exp100 = EXP100_SEND_DATA;
4092                   k->keepon |= KEEP_SEND;
4093                 }
4094               }
4095               else {
4096                 infof(data, "HTTP error before end of send, stop sending");
4097                 streamclose(conn, "Stop sending data before everything sent");
4098                 result = Curl_done_sending(data, k);
4099                 if(result)
4100                   return result;
4101                 k->upload_done = TRUE;
4102                 if(data->state.expect100header)
4103                   k->exp100 = EXP100_FAILED;
4104               }
4105             }
4106             break;
4107 
4108           default: /* default label present to avoid compiler warnings */
4109             break;
4110           }
4111         }
4112 
4113         if(conn->bits.rewindaftersend) {
4114           /* We rewind after a complete send, so thus we continue
4115              sending now */
4116           infof(data, "Keep sending data to get tossed away!");
4117           k->keepon |= KEEP_SEND;
4118         }
4119       }
4120 
4121       if(!k->header) {
4122         /*
4123          * really end-of-headers.
4124          *
4125          * If we requested a "no body", this is a good time to get
4126          * out and return home.
4127          */
4128         if(data->set.opt_no_body)
4129           *stop_reading = TRUE;
4130 #ifndef CURL_DISABLE_RTSP
4131         else if((conn->handler->protocol & CURLPROTO_RTSP) &&
4132                 (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
4133                 (k->size <= -1))
4134           /* Respect section 4.4 of rfc2326: If the Content-Length header is
4135              absent, a length 0 must be assumed.  It will prevent libcurl from
4136              hanging on DESCRIBE request that got refused for whatever
4137              reason */
4138           *stop_reading = TRUE;
4139 #endif
4140         else {
4141           /* If we know the expected size of this document, we set the
4142              maximum download size to the size of the expected
4143              document or else, we won't know when to stop reading!
4144 
4145              Note that we set the download maximum even if we read a
4146              "Connection: close" header, to make sure that
4147              "Content-Length: 0" still prevents us from attempting to
4148              read the (missing) response-body.
4149           */
4150           /* According to RFC2616 section 4.4, we MUST ignore
4151              Content-Length: headers if we are now receiving data
4152              using chunked Transfer-Encoding.
4153           */
4154           if(k->chunk)
4155             k->maxdownload = k->size = -1;
4156         }
4157         if(-1 != k->size) {
4158           /* We do this operation even if no_body is true, since this
4159              data might be retrieved later with curl_easy_getinfo()
4160              and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
4161 
4162           Curl_pgrsSetDownloadSize(data, k->size);
4163           k->maxdownload = k->size;
4164         }
4165 
4166         /* If max download size is *zero* (nothing) we already have
4167            nothing and can safely return ok now!  But for HTTP/2, we'd
4168            like to call http2_handle_stream_close to properly close a
4169            stream.  In order to do this, we keep reading until we
4170            close the stream. */
4171         if(0 == k->maxdownload
4172 #if defined(USE_NGHTTP2)
4173            && !((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
4174                 conn->httpversion == 20)
4175 #endif
4176            )
4177           *stop_reading = TRUE;
4178 
4179         if(*stop_reading) {
4180           /* we make sure that this socket isn't read more now */
4181           k->keepon &= ~KEEP_RECV;
4182         }
4183 
4184         Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
4185         break; /* exit header line loop */
4186       }
4187 
4188       /* We continue reading headers, reset the line-based header */
4189       Curl_dyn_reset(&data->state.headerb);
4190       continue;
4191     }
4192 
4193     /*
4194      * Checks for special headers coming up.
4195      */
4196 
4197     if(!k->headerline++) {
4198       /* This is the first header, it MUST be the error code line
4199          or else we consider this to be the body right away! */
4200       int httpversion_major;
4201       int rtspversion_major;
4202       int nc = 0;
4203 #ifdef CURL_DOES_CONVERSIONS
4204 #define HEADER1 scratch
4205 #define SCRATCHSIZE 21
4206       CURLcode res;
4207       char scratch[SCRATCHSIZE + 1]; /* "HTTP/major.minor 123" */
4208       /* We can't really convert this yet because we don't know if it's the
4209          1st header line or the body.  So we do a partial conversion into a
4210          scratch area, leaving the data at 'headp' as-is.
4211       */
4212       strncpy(&scratch[0], headp, SCRATCHSIZE);
4213       scratch[SCRATCHSIZE] = 0; /* null terminate */
4214       res = Curl_convert_from_network(data,
4215                                       &scratch[0],
4216                                       SCRATCHSIZE);
4217       if(res)
4218         /* Curl_convert_from_network calls failf if unsuccessful */
4219         return res;
4220 #else
4221 #define HEADER1 headp /* no conversion needed, just use headp */
4222 #endif /* CURL_DOES_CONVERSIONS */
4223 
4224       if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
4225         /*
4226          * https://tools.ietf.org/html/rfc7230#section-3.1.2
4227          *
4228          * The response code is always a three-digit number in HTTP as the spec
4229          * says. We allow any three-digit number here, but we cannot make
4230          * guarantees on future behaviors since it isn't within the protocol.
4231          */
4232         char separator;
4233         char twoorthree[2];
4234         int httpversion = 0;
4235         char digit4 = 0;
4236         nc = sscanf(HEADER1,
4237                     " HTTP/%1d.%1d%c%3d%c",
4238                     &httpversion_major,
4239                     &httpversion,
4240                     &separator,
4241                     &k->httpcode,
4242                     &digit4);
4243 
4244         if(nc == 1 && httpversion_major >= 2 &&
4245            2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
4246           conn->httpversion = 0;
4247           nc = 4;
4248           separator = ' ';
4249         }
4250 
4251         /* There can only be a 4th response code digit stored in 'digit4' if
4252            all the other fields were parsed and stored first, so nc is 5 when
4253            digit4 a digit */
4254         else if(ISDIGIT(digit4)) {
4255           failf(data, "Unsupported response code in HTTP response");
4256           return CURLE_UNSUPPORTED_PROTOCOL;
4257         }
4258 
4259         if((nc >= 4) && (' ' == separator)) {
4260           httpversion += 10 * httpversion_major;
4261           switch(httpversion) {
4262           case 10:
4263           case 11:
4264 #if defined(USE_NGHTTP2) || defined(USE_HYPER)
4265           case 20:
4266 #endif
4267 #if defined(ENABLE_QUIC)
4268           case 30:
4269 #endif
4270             conn->httpversion = (unsigned char)httpversion;
4271             break;
4272           default:
4273             failf(data, "Unsupported HTTP version (%u.%d) in response",
4274                   httpversion/10, httpversion%10);
4275             return CURLE_UNSUPPORTED_PROTOCOL;
4276           }
4277 
4278           if(k->upgr101 == UPGR101_RECEIVED) {
4279             /* supposedly upgraded to http2 now */
4280             if(conn->httpversion != 20)
4281               infof(data, "Lying server, not serving HTTP/2");
4282           }
4283           if(conn->httpversion < 20) {
4284             conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
4285             infof(data, "Mark bundle as not supporting multiuse");
4286           }
4287         }
4288         else if(!nc) {
4289           /* this is the real world, not a Nirvana
4290              NCSA 1.5.x returns this crap when asked for HTTP/1.1
4291           */
4292           nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
4293           conn->httpversion = 10;
4294 
4295           /* If user has set option HTTP200ALIASES,
4296              compare header line against list of aliases
4297           */
4298           if(!nc) {
4299             statusline check =
4300               checkhttpprefix(data,
4301                               Curl_dyn_ptr(&data->state.headerb),
4302                               Curl_dyn_len(&data->state.headerb));
4303             if(check == STATUS_DONE) {
4304               nc = 1;
4305               k->httpcode = 200;
4306               conn->httpversion = 10;
4307             }
4308           }
4309         }
4310         else {
4311           failf(data, "Unsupported HTTP version in response");
4312           return CURLE_UNSUPPORTED_PROTOCOL;
4313         }
4314       }
4315       else if(conn->handler->protocol & CURLPROTO_RTSP) {
4316         char separator;
4317         int rtspversion;
4318         nc = sscanf(HEADER1,
4319                     " RTSP/%1d.%1d%c%3d",
4320                     &rtspversion_major,
4321                     &rtspversion,
4322                     &separator,
4323                     &k->httpcode);
4324         if((nc == 4) && (' ' == separator)) {
4325           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
4326         }
4327         else {
4328           nc = 0;
4329         }
4330       }
4331 
4332       if(nc) {
4333         result = Curl_http_statusline(data, conn);
4334         if(result)
4335           return result;
4336       }
4337       else {
4338         k->header = FALSE;   /* this is not a header line */
4339         break;
4340       }
4341     }
4342 
4343     result = Curl_convert_from_network(data, headp, strlen(headp));
4344     /* Curl_convert_from_network calls failf if unsuccessful */
4345     if(result)
4346       return result;
4347 
4348     result = Curl_http_header(data, conn, headp);
4349     if(result)
4350       return result;
4351 
4352     /*
4353      * End of header-checks. Write them to the client.
4354      */
4355 
4356     writetype = CLIENTWRITE_HEADER;
4357     if(data->set.include_header)
4358       writetype |= CLIENTWRITE_BODY;
4359 
4360     Curl_debug(data, CURLINFO_HEADER_IN, headp,
4361                Curl_dyn_len(&data->state.headerb));
4362 
4363     result = Curl_client_write(data, writetype, headp,
4364                                Curl_dyn_len(&data->state.headerb));
4365     if(result)
4366       return result;
4367 
4368     data->info.header_size += Curl_dyn_len(&data->state.headerb);
4369     data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);
4370 
4371     Curl_dyn_reset(&data->state.headerb);
4372   }
4373   while(*k->str); /* header line within buffer */
4374 
4375   /* We might have reached the end of the header part here, but
4376      there might be a non-header part left in the end of the read
4377      buffer. */
4378 
4379   return CURLE_OK;
4380 }
4381 
4382 #endif /* CURL_DISABLE_HTTP */
4383