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