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