• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 #include "curl_setup.h"
26 #include "strtoofft.h"
27 
28 #ifdef HAVE_NETINET_IN_H
29 #include <netinet/in.h>
30 #endif
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 #include <signal.h>
44 
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
47 #endif
48 
49 #ifdef HAVE_SYS_SELECT_H
50 #include <sys/select.h>
51 #elif defined(HAVE_UNISTD_H)
52 #include <unistd.h>
53 #endif
54 
55 #ifndef HAVE_SOCKET
56 #error "We can't compile without socket() support!"
57 #endif
58 
59 #include "urldata.h"
60 #include <curl/curl.h>
61 #include "netrc.h"
62 
63 #include "content_encoding.h"
64 #include "hostip.h"
65 #include "cfilters.h"
66 #include "transfer.h"
67 #include "sendf.h"
68 #include "speedcheck.h"
69 #include "progress.h"
70 #include "http.h"
71 #include "url.h"
72 #include "getinfo.h"
73 #include "vtls/vtls.h"
74 #include "vquic/vquic.h"
75 #include "select.h"
76 #include "multiif.h"
77 #include "connect.h"
78 #include "http2.h"
79 #include "mime.h"
80 #include "strcase.h"
81 #include "urlapi-int.h"
82 #include "hsts.h"
83 #include "setopt.h"
84 #include "headers.h"
85 
86 /* The last 3 #include files should be in this order */
87 #include "curl_printf.h"
88 #include "curl_memory.h"
89 #include "memdebug.h"
90 
91 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
92     !defined(CURL_DISABLE_IMAP)
93 /*
94  * checkheaders() checks the linked list of custom headers for a
95  * particular header (prefix). Provide the prefix without colon!
96  *
97  * Returns a pointer to the first matching header or NULL if none matched.
98  */
Curl_checkheaders(const struct Curl_easy * data,const char * thisheader,const size_t thislen)99 char *Curl_checkheaders(const struct Curl_easy *data,
100                         const char *thisheader,
101                         const size_t thislen)
102 {
103   struct curl_slist *head;
104   DEBUGASSERT(thislen);
105   DEBUGASSERT(thisheader[thislen-1] != ':');
106 
107   for(head = data->set.headers; head; head = head->next) {
108     if(strncasecompare(head->data, thisheader, thislen) &&
109        Curl_headersep(head->data[thislen]) )
110       return head->data;
111   }
112 
113   return NULL;
114 }
115 #endif
116 
Curl_get_upload_buffer(struct Curl_easy * data)117 CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
118 {
119   if(!data->state.ulbuf) {
120     data->state.ulbuf = malloc(data->set.upload_buffer_size);
121     if(!data->state.ulbuf)
122       return CURLE_OUT_OF_MEMORY;
123   }
124   return CURLE_OK;
125 }
126 
127 #ifndef CURL_DISABLE_HTTP
128 /*
129  * This function will be called to loop through the trailers buffer
130  * until no more data is available for sending.
131  */
trailers_read(char * buffer,size_t size,size_t nitems,void * raw)132 static size_t trailers_read(char *buffer, size_t size, size_t nitems,
133                             void *raw)
134 {
135   struct Curl_easy *data = (struct Curl_easy *)raw;
136   struct dynbuf *trailers_buf = &data->state.trailers_buf;
137   size_t bytes_left = Curl_dyn_len(trailers_buf) -
138     data->state.trailers_bytes_sent;
139   size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
140   if(to_copy) {
141     memcpy(buffer,
142            Curl_dyn_ptr(trailers_buf) + data->state.trailers_bytes_sent,
143            to_copy);
144     data->state.trailers_bytes_sent += to_copy;
145   }
146   return to_copy;
147 }
148 
trailers_left(void * raw)149 static size_t trailers_left(void *raw)
150 {
151   struct Curl_easy *data = (struct Curl_easy *)raw;
152   struct dynbuf *trailers_buf = &data->state.trailers_buf;
153   return Curl_dyn_len(trailers_buf) - data->state.trailers_bytes_sent;
154 }
155 #endif
156 
157 /*
158  * This function will call the read callback to fill our buffer with data
159  * to upload.
160  */
Curl_fillreadbuffer(struct Curl_easy * data,size_t bytes,size_t * nreadp)161 CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
162                              size_t *nreadp)
163 {
164   size_t buffersize = bytes;
165   size_t nread;
166   curl_read_callback readfunc = NULL;
167   void *extra_data = NULL;
168   int eof_index = 0;
169 
170 #ifndef CURL_DISABLE_HTTP
171   if(data->state.trailers_state == TRAILERS_INITIALIZED) {
172     struct curl_slist *trailers = NULL;
173     CURLcode result;
174     int trailers_ret_code;
175 
176     /* at this point we already verified that the callback exists
177        so we compile and store the trailers buffer, then proceed */
178     infof(data,
179           "Moving trailers state machine from initialized to sending.");
180     data->state.trailers_state = TRAILERS_SENDING;
181     Curl_dyn_init(&data->state.trailers_buf, DYN_TRAILERS);
182 
183     data->state.trailers_bytes_sent = 0;
184     Curl_set_in_callback(data, true);
185     trailers_ret_code = data->set.trailer_callback(&trailers,
186                                                    data->set.trailer_data);
187     Curl_set_in_callback(data, false);
188     if(trailers_ret_code == CURL_TRAILERFUNC_OK) {
189       result = Curl_http_compile_trailers(trailers, &data->state.trailers_buf,
190                                           data);
191     }
192     else {
193       failf(data, "operation aborted by trailing headers callback");
194       *nreadp = 0;
195       result = CURLE_ABORTED_BY_CALLBACK;
196     }
197     if(result) {
198       Curl_dyn_free(&data->state.trailers_buf);
199       curl_slist_free_all(trailers);
200       return result;
201     }
202     infof(data, "Successfully compiled trailers.");
203     curl_slist_free_all(trailers);
204   }
205 #endif
206 
207 #ifndef CURL_DISABLE_HTTP
208   /* if we are transmitting trailing data, we don't need to write
209      a chunk size so we skip this */
210   if(data->req.upload_chunky &&
211      data->state.trailers_state == TRAILERS_NONE) {
212     /* if chunked Transfer-Encoding */
213     buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
214     data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
215   }
216 
217   if(data->state.trailers_state == TRAILERS_SENDING) {
218     /* if we're here then that means that we already sent the last empty chunk
219        but we didn't send a final CR LF, so we sent 0 CR LF. We then start
220        pulling trailing data until we have no more at which point we
221        simply return to the previous point in the state machine as if
222        nothing happened.
223        */
224     readfunc = trailers_read;
225     extra_data = (void *)data;
226     eof_index = 1;
227   }
228   else
229 #endif
230   {
231     readfunc = data->state.fread_func;
232     extra_data = data->state.in;
233   }
234 
235   if(!data->req.fread_eof[eof_index]) {
236     Curl_set_in_callback(data, true);
237     nread = readfunc(data->req.upload_fromhere, 1, buffersize, extra_data);
238     Curl_set_in_callback(data, false);
239     /* make sure the callback is not called again after EOF */
240     data->req.fread_eof[eof_index] = !nread;
241   }
242   else
243     nread = 0;
244 
245   if(nread == CURL_READFUNC_ABORT) {
246     failf(data, "operation aborted by callback");
247     *nreadp = 0;
248     return CURLE_ABORTED_BY_CALLBACK;
249   }
250   if(nread == CURL_READFUNC_PAUSE) {
251     struct SingleRequest *k = &data->req;
252 
253     if(data->conn->handler->flags & PROTOPT_NONETWORK) {
254       /* protocols that work without network cannot be paused. This is
255          actually only FILE:// just now, and it can't pause since the transfer
256          isn't done using the "normal" procedure. */
257       failf(data, "Read callback asked for PAUSE when not supported");
258       return CURLE_READ_ERROR;
259     }
260 
261     /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
262     k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
263     if(data->req.upload_chunky) {
264         /* Back out the preallocation done above */
265       data->req.upload_fromhere -= (8 + 2);
266     }
267     *nreadp = 0;
268 
269     return CURLE_OK; /* nothing was read */
270   }
271   else if(nread > buffersize) {
272     /* the read function returned a too large value */
273     *nreadp = 0;
274     failf(data, "read function returned funny value");
275     return CURLE_READ_ERROR;
276   }
277 
278 #ifndef CURL_DISABLE_HTTP
279   if(!data->req.forbidchunk && data->req.upload_chunky) {
280     /* if chunked Transfer-Encoding
281      *    build chunk:
282      *
283      *        <HEX SIZE> CRLF
284      *        <DATA> CRLF
285      */
286     /* On non-ASCII platforms the <DATA> may or may not be
287        translated based on state.prefer_ascii while the protocol
288        portion must always be translated to the network encoding.
289        To further complicate matters, line end conversion might be
290        done later on, so we need to prevent CRLFs from becoming
291        CRCRLFs if that's the case.  To do this we use bare LFs
292        here, knowing they'll become CRLFs later on.
293      */
294 
295     bool added_crlf = FALSE;
296     int hexlen = 0;
297     const char *endofline_native;
298     const char *endofline_network;
299 
300     if(
301 #ifdef CURL_DO_LINEEND_CONV
302        (data->state.prefer_ascii) ||
303 #endif
304        (data->set.crlf)) {
305       /* \n will become \r\n later on */
306       endofline_native  = "\n";
307       endofline_network = "\x0a";
308     }
309     else {
310       endofline_native  = "\r\n";
311       endofline_network = "\x0d\x0a";
312     }
313 
314     /* if we're not handling trailing data, proceed as usual */
315     if(data->state.trailers_state != TRAILERS_SENDING) {
316       char hexbuffer[11] = "";
317       hexlen = msnprintf(hexbuffer, sizeof(hexbuffer),
318                          "%zx%s", nread, endofline_native);
319 
320       /* move buffer pointer */
321       data->req.upload_fromhere -= hexlen;
322       nread += hexlen;
323 
324       /* copy the prefix to the buffer, leaving out the NUL */
325       memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
326 
327       /* always append ASCII CRLF to the data unless
328          we have a valid trailer callback */
329       if((nread-hexlen) == 0 &&
330           data->set.trailer_callback != NULL &&
331           data->state.trailers_state == TRAILERS_NONE) {
332         data->state.trailers_state = TRAILERS_INITIALIZED;
333       }
334       else {
335         memcpy(data->req.upload_fromhere + nread,
336                endofline_network,
337                strlen(endofline_network));
338         added_crlf = TRUE;
339       }
340     }
341 
342     if(data->state.trailers_state == TRAILERS_SENDING &&
343        !trailers_left(data)) {
344       Curl_dyn_free(&data->state.trailers_buf);
345       data->state.trailers_state = TRAILERS_DONE;
346       data->set.trailer_data = NULL;
347       data->set.trailer_callback = NULL;
348       /* mark the transfer as done */
349       data->req.upload_done = TRUE;
350       infof(data, "Signaling end of chunked upload after trailers.");
351     }
352     else
353       if((nread - hexlen) == 0 &&
354          data->state.trailers_state != TRAILERS_INITIALIZED) {
355         /* mark this as done once this chunk is transferred */
356         data->req.upload_done = TRUE;
357         infof(data,
358               "Signaling end of chunked upload via terminating chunk.");
359       }
360 
361     if(added_crlf)
362       nread += strlen(endofline_network); /* for the added end of line */
363   }
364 #endif
365 
366   *nreadp = nread;
367 
368   return CURLE_OK;
369 }
370 
data_pending(struct Curl_easy * data)371 static int data_pending(struct Curl_easy *data)
372 {
373   struct connectdata *conn = data->conn;
374 
375   if(conn->handler->protocol&PROTO_FAMILY_FTP)
376     return Curl_conn_data_pending(data, SECONDARYSOCKET);
377 
378   /* in the case of libssh2, we can never be really sure that we have emptied
379      its internal buffers so we MUST always try until we get EAGAIN back */
380   return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
381     Curl_conn_data_pending(data, FIRSTSOCKET);
382 }
383 
384 /*
385  * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
386  * remote document with the time provided by CURLOPT_TIMEVAL
387  */
Curl_meets_timecondition(struct Curl_easy * data,time_t timeofdoc)388 bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
389 {
390   if((timeofdoc == 0) || (data->set.timevalue == 0))
391     return TRUE;
392 
393   switch(data->set.timecondition) {
394   case CURL_TIMECOND_IFMODSINCE:
395   default:
396     if(timeofdoc <= data->set.timevalue) {
397       infof(data,
398             "The requested document is not new enough");
399       data->info.timecond = TRUE;
400       return FALSE;
401     }
402     break;
403   case CURL_TIMECOND_IFUNMODSINCE:
404     if(timeofdoc >= data->set.timevalue) {
405       infof(data,
406             "The requested document is not old enough");
407       data->info.timecond = TRUE;
408       return FALSE;
409     }
410     break;
411   }
412 
413   return TRUE;
414 }
415 
416 /**
417  * Receive raw response data for the transfer.
418  * @param data         the transfer
419  * @param buf          buffer to keep response data received
420  * @param blen         length of `buf`
421  * @param eos_reliable if EOS detection in underlying connection is reliable
422  * @param err error    code in case of -1 return
423  * @return number of bytes read or -1 for error
424  */
Curl_xfer_recv_resp(struct Curl_easy * data,char * buf,size_t blen,bool eos_reliable,CURLcode * err)425 static ssize_t Curl_xfer_recv_resp(struct Curl_easy *data,
426                                    char *buf, size_t blen,
427                                    bool eos_reliable,
428                                    CURLcode *err)
429 {
430   ssize_t nread;
431 
432   DEBUGASSERT(blen > 0);
433   /* If we are reading BODY data and the connection does NOT handle EOF
434    * and we know the size of the BODY data, limit the read amount */
435   if(!eos_reliable && !data->req.header && data->req.size != -1) {
436     curl_off_t totalleft = data->req.size - data->req.bytecount;
437     if(totalleft <= 0)
438       blen = 0;
439     else if(totalleft < (curl_off_t)blen)
440       blen = (size_t)totalleft;
441   }
442 
443   if(!blen) {
444     /* want nothing - continue as if read nothing. */
445     DEBUGF(infof(data, "readwrite_data: we're done"));
446     *err = CURLE_OK;
447     return 0;
448   }
449 
450   *err = Curl_read(data, data->conn->sockfd, buf, blen, &nread);
451   if(*err)
452     return -1;
453   DEBUGASSERT(nread >= 0);
454   *err = CURLE_OK;
455   return nread;
456 }
457 
458 /*
459  * Go ahead and do a read if we have a readable socket or if
460  * the stream was rewound (in which case we have data in a
461  * buffer)
462  */
readwrite_data(struct Curl_easy * data,struct SingleRequest * k,int * didwhat,bool * done)463 static CURLcode readwrite_data(struct Curl_easy *data,
464                                struct SingleRequest *k,
465                                int *didwhat, bool *done)
466 {
467   struct connectdata *conn = data->conn;
468   CURLcode result = CURLE_OK;
469   char *buf;
470   size_t blen;
471   int maxloops = 10;
472   curl_off_t total_received = 0;
473   bool is_multiplex = FALSE;
474 
475   DEBUGASSERT(data->state.buffer);
476   *done = FALSE;
477 
478   /* This is where we loop until we have read everything there is to
479      read or we get a CURLE_AGAIN */
480   do {
481     bool is_eos = FALSE;
482     size_t bytestoread;
483     ssize_t nread;
484 
485     if(!is_multiplex) {
486       /* Multiplexed connection have inherent handling of EOF and we do not
487        * have to carefully restrict the amount we try to read.
488        * Multiplexed changes only in one direction. */
489       is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
490     }
491 
492     buf = data->state.buffer;
493     bytestoread = data->set.buffer_size;
494 
495     /* Observe any imposed speed limit */
496     if(bytestoread && data->set.max_recv_speed) {
497       curl_off_t net_limit = data->set.max_recv_speed - total_received;
498       if(net_limit <= 0)
499         break;
500       if((size_t)net_limit < bytestoread)
501         bytestoread = (size_t)net_limit;
502     }
503 
504     nread = Curl_xfer_recv_resp(data, buf, bytestoread,
505                                 is_multiplex, &result);
506     if(nread < 0) {
507       if(CURLE_AGAIN == result) {
508         result = CURLE_OK;
509         break; /* get out of loop */
510       }
511       goto out; /* real error */
512     }
513 
514     /* We only get a 0-length read on EndOfStream */
515     blen = (size_t)nread;
516     is_eos = (blen == 0);
517     *didwhat |= KEEP_RECV;
518 
519     if(!blen) {
520       /* if we receive 0 or less here, either the data transfer is done or the
521          server closed the connection and we bail out from this! */
522       if(is_multiplex)
523         DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
524       else
525         DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
526       if(k->eos_written) { /* already did write this to client, leave */
527         k->keepon = 0; /* stop sending as well */
528         break;
529       }
530     }
531     total_received += blen;
532 
533     result = Curl_xfer_write_resp(data, buf, blen, is_eos, done);
534     if(result || *done)
535       goto out;
536 
537     /* if we are done, we stop receiving. On multiplexed connections,
538      * we should read the EOS. Which may arrive as meta data after
539      * the bytes. Not taking it in might lead to RST of streams. */
540     if((!is_multiplex && data->req.download_done) || is_eos) {
541       data->req.keepon &= ~KEEP_RECV;
542     }
543     /* if we are PAUSEd or stopped receiving, leave the loop */
544     if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV))
545       break;
546 
547   } while(maxloops-- && data_pending(data));
548 
549   if(maxloops <= 0) {
550     /* did not read until EAGAIN, mark read-again-please */
551     data->state.select_bits = CURL_CSELECT_IN;
552     if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
553       data->state.select_bits |= CURL_CSELECT_OUT;
554   }
555 
556   if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
557      (conn->bits.close || is_multiplex)) {
558     /* When we've read the entire thing and the close bit is set, the server
559        may now close the connection. If there's now any kind of sending going
560        on from our side, we need to stop that immediately. */
561     infof(data, "we are done reading and this is set to close, stop send");
562     k->keepon &= ~KEEP_SEND; /* no writing anymore either */
563     k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */
564   }
565 
566 out:
567   if(result)
568     DEBUGF(infof(data, "readwrite_data() -> %d", result));
569   return result;
570 }
571 
Curl_done_sending(struct Curl_easy * data,struct SingleRequest * k)572 CURLcode Curl_done_sending(struct Curl_easy *data,
573                            struct SingleRequest *k)
574 {
575   k->keepon &= ~KEEP_SEND; /* we're done writing */
576 
577   /* These functions should be moved into the handler struct! */
578   Curl_conn_ev_data_done_send(data);
579 
580   return CURLE_OK;
581 }
582 
583 #if defined(_WIN32) && defined(USE_WINSOCK)
584 #ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
585 #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
586 #endif
587 
win_update_buffer_size(curl_socket_t sockfd)588 static void win_update_buffer_size(curl_socket_t sockfd)
589 {
590   int result;
591   ULONG ideal;
592   DWORD ideallen;
593   result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
594                     &ideal, sizeof(ideal), &ideallen, 0, 0);
595   if(result == 0) {
596     setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
597                (const char *)&ideal, sizeof(ideal));
598   }
599 }
600 #else
601 #define win_update_buffer_size(x)
602 #endif
603 
604 #define curl_upload_refill_watermark(data) \
605         ((ssize_t)((data)->set.upload_buffer_size >> 5))
606 
607 /*
608  * Send data to upload to the server, when the socket is writable.
609  */
readwrite_upload(struct Curl_easy * data,struct connectdata * conn,int * didwhat)610 static CURLcode readwrite_upload(struct Curl_easy *data,
611                                  struct connectdata *conn,
612                                  int *didwhat)
613 {
614   ssize_t i, si;
615   ssize_t bytes_written;
616   CURLcode result;
617   ssize_t nread; /* number of bytes read */
618   bool sending_http_headers = FALSE;
619   struct SingleRequest *k = &data->req;
620 
621   *didwhat |= KEEP_SEND;
622 
623   do {
624     curl_off_t nbody;
625     ssize_t offset = 0;
626 
627     if(0 != k->upload_present &&
628        k->upload_present < curl_upload_refill_watermark(data) &&
629        !k->upload_chunky &&/*(variable sized chunked header; append not safe)*/
630        !k->upload_done &&  /*!(k->upload_done once k->upload_present sent)*/
631        !(k->writebytecount + k->upload_present - k->pendingheader ==
632          data->state.infilesize)) {
633       offset = k->upload_present;
634     }
635 
636     /* only read more data if there's no upload data already
637        present in the upload buffer, or if appending to upload buffer */
638     if(0 == k->upload_present || offset) {
639       result = Curl_get_upload_buffer(data);
640       if(result)
641         return result;
642       if(offset && k->upload_fromhere != data->state.ulbuf)
643         memmove(data->state.ulbuf, k->upload_fromhere, offset);
644       /* init the "upload from here" pointer */
645       k->upload_fromhere = data->state.ulbuf;
646 
647       if(!k->upload_done) {
648         /* HTTP pollution, this should be written nicer to become more
649            protocol agnostic. */
650         size_t fillcount;
651         struct HTTP *http = k->p.http;
652 
653         if((k->exp100 == EXP100_SENDING_REQUEST) &&
654            (http->sending == HTTPSEND_BODY)) {
655           /* If this call is to send body data, we must take some action:
656              We have sent off the full HTTP 1.1 request, and we shall now
657              go into the Expect: 100 state and await such a header */
658           k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
659           k->keepon &= ~KEEP_SEND;         /* disable writing */
660           k->start100 = Curl_now();       /* timeout count starts now */
661           *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
662           /* set a timeout for the multi interface */
663           Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
664           break;
665         }
666 
667         if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
668           if(http->sending == HTTPSEND_REQUEST)
669             /* We're sending the HTTP request headers, not the data.
670                Remember that so we don't change the line endings. */
671             sending_http_headers = TRUE;
672           else
673             sending_http_headers = FALSE;
674         }
675 
676         k->upload_fromhere += offset;
677         result = Curl_fillreadbuffer(data, data->set.upload_buffer_size-offset,
678                                      &fillcount);
679         k->upload_fromhere -= offset;
680         if(result)
681           return result;
682 
683         nread = offset + fillcount;
684       }
685       else
686         nread = 0; /* we're done uploading/reading */
687 
688       if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
689         /* this is a paused transfer */
690         break;
691       }
692       if(nread <= 0) {
693         result = Curl_done_sending(data, k);
694         if(result)
695           return result;
696         break;
697       }
698 
699       /* store number of bytes available for upload */
700       k->upload_present = nread;
701 
702       /* convert LF to CRLF if so asked */
703       if((!sending_http_headers) && (
704 #ifdef CURL_DO_LINEEND_CONV
705          /* always convert if we're FTPing in ASCII mode */
706          (data->state.prefer_ascii) ||
707 #endif
708          (data->set.crlf))) {
709         /* Do we need to allocate a scratch buffer? */
710         if(!data->state.scratch) {
711           data->state.scratch = malloc(2 * data->set.upload_buffer_size);
712           if(!data->state.scratch) {
713             failf(data, "Failed to alloc scratch buffer");
714 
715             return CURLE_OUT_OF_MEMORY;
716           }
717         }
718 
719         /*
720          * ASCII/EBCDIC Note: This is presumably a text (not binary)
721          * transfer so the data should already be in ASCII.
722          * That means the hex values for ASCII CR (0x0d) & LF (0x0a)
723          * must be used instead of the escape sequences \r & \n.
724          */
725         if(offset)
726           memcpy(data->state.scratch, k->upload_fromhere, offset);
727         for(i = offset, si = offset; i < nread; i++, si++) {
728           if(k->upload_fromhere[i] == 0x0a) {
729             data->state.scratch[si++] = 0x0d;
730             data->state.scratch[si] = 0x0a;
731             if(!data->set.crlf) {
732               /* we're here only because FTP is in ASCII mode...
733                  bump infilesize for the LF we just added */
734               if(data->state.infilesize != -1)
735                 data->state.infilesize++;
736             }
737           }
738           else
739             data->state.scratch[si] = k->upload_fromhere[i];
740         }
741 
742         if(si != nread) {
743           /* only perform the special operation if we really did replace
744              anything */
745           nread = si;
746 
747           /* upload from the new (replaced) buffer instead */
748           k->upload_fromhere = data->state.scratch;
749 
750           /* set the new amount too */
751           k->upload_present = nread;
752         }
753       }
754 
755 #ifndef CURL_DISABLE_SMTP
756       if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
757         result = Curl_smtp_escape_eob(data, nread, offset);
758         if(result)
759           return result;
760       }
761 #endif /* CURL_DISABLE_SMTP */
762     } /* if 0 == k->upload_present or appended to upload buffer */
763     else {
764       /* We have a partial buffer left from a previous "round". Use
765          that instead of reading more data */
766     }
767 
768     /* write to socket (send away data) */
769     result = Curl_write(data,
770                         conn->writesockfd,  /* socket to send to */
771                         k->upload_fromhere, /* buffer pointer */
772                         k->upload_present,  /* buffer size */
773                         &bytes_written);    /* actually sent */
774     if(result)
775       return result;
776 
777 #if defined(_WIN32) && defined(USE_WINSOCK)
778     {
779       struct curltime n = Curl_now();
780       if(Curl_timediff(n, k->last_sndbuf_update) > 1000) {
781         win_update_buffer_size(conn->writesockfd);
782         k->last_sndbuf_update = n;
783       }
784     }
785 #endif
786 
787     if(k->pendingheader) {
788       /* parts of what was sent was header */
789       curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
790       /* show the data before we change the pointer upload_fromhere */
791       Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
792       k->pendingheader -= n;
793       nbody = bytes_written - n; /* size of the written body part */
794     }
795     else
796       nbody = bytes_written;
797 
798     if(nbody) {
799       /* show the data before we change the pointer upload_fromhere */
800       Curl_debug(data, CURLINFO_DATA_OUT,
801                  &k->upload_fromhere[bytes_written - nbody],
802                  (size_t)nbody);
803 
804       k->writebytecount += nbody;
805       Curl_pgrsSetUploadCounter(data, k->writebytecount);
806     }
807 
808     if((!k->upload_chunky || k->forbidchunk) &&
809        (k->writebytecount == data->state.infilesize)) {
810       /* we have sent all data we were supposed to */
811       k->upload_done = TRUE;
812       infof(data, "We are completely uploaded and fine");
813     }
814 
815     if(k->upload_present != bytes_written) {
816       /* we only wrote a part of the buffer (if anything), deal with it! */
817 
818       /* store the amount of bytes left in the buffer to write */
819       k->upload_present -= bytes_written;
820 
821       /* advance the pointer where to find the buffer when the next send
822          is to happen */
823       k->upload_fromhere += bytes_written;
824     }
825     else {
826       /* we've uploaded that buffer now */
827       result = Curl_get_upload_buffer(data);
828       if(result)
829         return result;
830       k->upload_fromhere = data->state.ulbuf;
831       k->upload_present = 0; /* no more bytes left */
832 
833       if(k->upload_done) {
834         result = Curl_done_sending(data, k);
835         if(result)
836           return result;
837       }
838     }
839 
840 
841   } while(0); /* just to break out from! */
842 
843   return CURLE_OK;
844 }
845 
select_bits_paused(struct Curl_easy * data,int select_bits)846 static int select_bits_paused(struct Curl_easy *data, int select_bits)
847 {
848   /* See issue #11982: we really need to be careful not to progress
849    * a transfer direction when that direction is paused. Not all parts
850    * of our state machine are handling PAUSED transfers correctly. So, we
851    * do not want to go there.
852    * NOTE: we are only interested in PAUSE, not HOLD. */
853 
854   /* if there is data in a direction not paused, return false */
855   if(((select_bits & CURL_CSELECT_IN) &&
856       !(data->req.keepon & KEEP_RECV_PAUSE)) ||
857      ((select_bits & CURL_CSELECT_OUT) &&
858       !(data->req.keepon & KEEP_SEND_PAUSE)))
859     return FALSE;
860 
861   return (data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE));
862 }
863 
864 /*
865  * Curl_readwrite() is the low-level function to be called when data is to
866  * be read and written to/from the connection.
867  */
Curl_readwrite(struct Curl_easy * data,bool * done)868 CURLcode Curl_readwrite(struct Curl_easy *data,
869                         bool *done)
870 {
871   struct connectdata *conn = data->conn;
872   struct SingleRequest *k = &data->req;
873   CURLcode result;
874   struct curltime now;
875   int didwhat = 0;
876   int select_bits;
877 
878   if(data->state.select_bits) {
879     if(select_bits_paused(data, data->state.select_bits)) {
880       /* leave the bits unchanged, so they'll tell us what to do when
881        * this transfer gets unpaused. */
882       DEBUGF(infof(data, "readwrite, select_bits, early return on PAUSED"));
883       result = CURLE_OK;
884       goto out;
885     }
886     select_bits = data->state.select_bits;
887     data->state.select_bits = 0;
888   }
889   else {
890     curl_socket_t fd_read;
891     curl_socket_t fd_write;
892     /* only use the proper socket if the *_HOLD bit is not set simultaneously
893        as then we are in rate limiting state in that transfer direction */
894     if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
895       fd_read = conn->sockfd;
896     else
897       fd_read = CURL_SOCKET_BAD;
898 
899     if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
900       fd_write = conn->writesockfd;
901     else
902       fd_write = CURL_SOCKET_BAD;
903 
904     select_bits = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
905   }
906 
907   if(select_bits == CURL_CSELECT_ERR) {
908     failf(data, "select/poll returned error");
909     result = CURLE_SEND_ERROR;
910     goto out;
911   }
912 
913 #ifdef USE_HYPER
914   if(conn->datastream) {
915     result = conn->datastream(data, conn, &didwhat, done, select_bits);
916     if(result || *done)
917       goto out;
918   }
919   else {
920 #endif
921   /* We go ahead and do a read if we have a readable socket or if
922      the stream was rewound (in which case we have data in a
923      buffer) */
924   if((k->keepon & KEEP_RECV) && (select_bits & CURL_CSELECT_IN)) {
925     result = readwrite_data(data, k, &didwhat, done);
926     if(result || *done)
927       goto out;
928   }
929 
930   /* If we still have writing to do, we check if we have a writable socket. */
931   if((k->keepon & KEEP_SEND) && (select_bits & CURL_CSELECT_OUT)) {
932     /* write */
933 
934     result = readwrite_upload(data, conn, &didwhat);
935     if(result)
936       goto out;
937   }
938 #ifdef USE_HYPER
939   }
940 #endif
941 
942   now = Curl_now();
943   if(!didwhat) {
944     /* no read no write, this is a timeout? */
945     if(k->exp100 == EXP100_AWAITING_CONTINUE) {
946       /* This should allow some time for the header to arrive, but only a
947          very short time as otherwise it'll be too much wasted time too
948          often. */
949 
950       /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
951 
952          Therefore, when a client sends this header field to an origin server
953          (possibly via a proxy) from which it has never seen a 100 (Continue)
954          status, the client SHOULD NOT wait for an indefinite period before
955          sending the request body.
956 
957       */
958 
959       timediff_t ms = Curl_timediff(now, k->start100);
960       if(ms >= data->set.expect_100_timeout) {
961         /* we've waited long enough, continue anyway */
962         k->exp100 = EXP100_SEND_DATA;
963         k->keepon |= KEEP_SEND;
964         Curl_expire_done(data, EXPIRE_100_TIMEOUT);
965         infof(data, "Done waiting for 100-continue");
966       }
967     }
968 
969     result = Curl_conn_ev_data_idle(data);
970     if(result)
971       goto out;
972   }
973 
974   if(Curl_pgrsUpdate(data))
975     result = CURLE_ABORTED_BY_CALLBACK;
976   else
977     result = Curl_speedcheck(data, now);
978   if(result)
979     goto out;
980 
981   if(k->keepon) {
982     if(0 > Curl_timeleft(data, &now, FALSE)) {
983       if(k->size != -1) {
984         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
985               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
986               CURL_FORMAT_CURL_OFF_T " bytes received",
987               Curl_timediff(now, data->progress.t_startsingle),
988               k->bytecount, k->size);
989       }
990       else {
991         failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
992               " milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received",
993               Curl_timediff(now, data->progress.t_startsingle),
994               k->bytecount);
995       }
996       result = CURLE_OPERATION_TIMEDOUT;
997       goto out;
998     }
999   }
1000   else {
1001     /*
1002      * The transfer has been performed. Just make some general checks before
1003      * returning.
1004      */
1005 
1006     if(!(data->req.no_body) && (k->size != -1) &&
1007        (k->bytecount != k->size) &&
1008 #ifdef CURL_DO_LINEEND_CONV
1009        /* Most FTP servers don't adjust their file SIZE response for CRLFs,
1010           so we'll check to see if the discrepancy can be explained
1011           by the number of CRLFs we've changed to LFs.
1012        */
1013        (k->bytecount != (k->size + data->state.crlf_conversions)) &&
1014 #endif /* CURL_DO_LINEEND_CONV */
1015        !k->newurl) {
1016       failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
1017             " bytes remaining to read", k->size - k->bytecount);
1018       result = CURLE_PARTIAL_FILE;
1019       goto out;
1020     }
1021     if(Curl_pgrsUpdate(data)) {
1022       result = CURLE_ABORTED_BY_CALLBACK;
1023       goto out;
1024     }
1025   }
1026 
1027   /* Now update the "done" boolean we return */
1028   *done = (0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS))) ? TRUE : FALSE;
1029 out:
1030   if(result)
1031     DEBUGF(infof(data, "Curl_readwrite() -> %d", result));
1032   return result;
1033 }
1034 
1035 /* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
1036    which means this gets called once for each subsequent redirect etc */
Curl_init_CONNECT(struct Curl_easy * data)1037 void Curl_init_CONNECT(struct Curl_easy *data)
1038 {
1039   data->state.fread_func = data->set.fread_func_set;
1040   data->state.in = data->set.in_set;
1041   data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
1042 }
1043 
1044 /*
1045  * Curl_pretransfer() is called immediately before a transfer starts, and only
1046  * once for one transfer no matter if it has redirects or do multi-pass
1047  * authentication etc.
1048  */
Curl_pretransfer(struct Curl_easy * data)1049 CURLcode Curl_pretransfer(struct Curl_easy *data)
1050 {
1051   CURLcode result;
1052 
1053   if(!data->state.url && !data->set.uh) {
1054     /* we can't do anything without URL */
1055     failf(data, "No URL set");
1056     return CURLE_URL_MALFORMAT;
1057   }
1058 
1059   /* since the URL may have been redirected in a previous use of this handle */
1060   if(data->state.url_alloc) {
1061     /* the already set URL is allocated, free it first! */
1062     Curl_safefree(data->state.url);
1063     data->state.url_alloc = FALSE;
1064   }
1065 
1066   if(!data->state.url && data->set.uh) {
1067     CURLUcode uc;
1068     free(data->set.str[STRING_SET_URL]);
1069     uc = curl_url_get(data->set.uh,
1070                       CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
1071     if(uc) {
1072       failf(data, "No URL set");
1073       return CURLE_URL_MALFORMAT;
1074     }
1075   }
1076 
1077   if(data->set.postfields && data->set.set_resume_from) {
1078     /* we can't */
1079     failf(data, "cannot mix POSTFIELDS with RESUME_FROM");
1080     return CURLE_BAD_FUNCTION_ARGUMENT;
1081   }
1082 
1083   data->state.prefer_ascii = data->set.prefer_ascii;
1084 #ifdef CURL_LIST_ONLY_PROTOCOL
1085   data->state.list_only = data->set.list_only;
1086 #endif
1087   data->state.httpreq = data->set.method;
1088   data->state.url = data->set.str[STRING_SET_URL];
1089 
1090   /* Init the SSL session ID cache here. We do it here since we want to do it
1091      after the *_setopt() calls (that could specify the size of the cache) but
1092      before any transfer takes place. */
1093   result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
1094   if(result)
1095     return result;
1096 
1097   data->state.requests = 0;
1098   data->state.followlocation = 0; /* reset the location-follow counter */
1099   data->state.this_is_a_follow = FALSE; /* reset this */
1100   data->state.errorbuf = FALSE; /* no error has occurred */
1101   data->state.httpwant = data->set.httpwant;
1102   data->state.httpversion = 0;
1103   data->state.authproblem = FALSE;
1104   data->state.authhost.want = data->set.httpauth;
1105   data->state.authproxy.want = data->set.proxyauth;
1106   Curl_safefree(data->info.wouldredirect);
1107   Curl_data_priority_clear_state(data);
1108 
1109   if(data->state.httpreq == HTTPREQ_PUT)
1110     data->state.infilesize = data->set.filesize;
1111   else if((data->state.httpreq != HTTPREQ_GET) &&
1112           (data->state.httpreq != HTTPREQ_HEAD)) {
1113     data->state.infilesize = data->set.postfieldsize;
1114     if(data->set.postfields && (data->state.infilesize == -1))
1115       data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
1116   }
1117   else
1118     data->state.infilesize = 0;
1119 
1120   /* If there is a list of cookie files to read, do it now! */
1121   Curl_cookie_loadfiles(data);
1122 
1123   /* If there is a list of host pairs to deal with */
1124   if(data->state.resolve)
1125     result = Curl_loadhostpairs(data);
1126 
1127   /* If there is a list of hsts files to read */
1128   Curl_hsts_loadfiles(data);
1129 
1130   if(!result) {
1131     /* Allow data->set.use_port to set which port to use. This needs to be
1132      * disabled for example when we follow Location: headers to URLs using
1133      * different ports! */
1134     data->state.allow_port = TRUE;
1135 
1136 #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
1137     /*************************************************************
1138      * Tell signal handler to ignore SIGPIPE
1139      *************************************************************/
1140     if(!data->set.no_signal)
1141       data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
1142 #endif
1143 
1144     Curl_initinfo(data); /* reset session-specific information "variables" */
1145     Curl_pgrsResetTransferSizes(data);
1146     Curl_pgrsStartNow(data);
1147 
1148     /* In case the handle is reused and an authentication method was picked
1149        in the session we need to make sure we only use the one(s) we now
1150        consider to be fine */
1151     data->state.authhost.picked &= data->state.authhost.want;
1152     data->state.authproxy.picked &= data->state.authproxy.want;
1153 
1154 #ifndef CURL_DISABLE_FTP
1155     data->state.wildcardmatch = data->set.wildcard_enabled;
1156     if(data->state.wildcardmatch) {
1157       struct WildcardData *wc;
1158       if(!data->wildcard) {
1159         data->wildcard = calloc(1, sizeof(struct WildcardData));
1160         if(!data->wildcard)
1161           return CURLE_OUT_OF_MEMORY;
1162       }
1163       wc = data->wildcard;
1164       if(wc->state < CURLWC_INIT) {
1165         if(wc->ftpwc)
1166           wc->dtor(wc->ftpwc);
1167         Curl_safefree(wc->pattern);
1168         Curl_safefree(wc->path);
1169         result = Curl_wildcard_init(wc); /* init wildcard structures */
1170         if(result)
1171           return CURLE_OUT_OF_MEMORY;
1172       }
1173     }
1174 #endif
1175     result = Curl_hsts_loadcb(data, data->hsts);
1176   }
1177 
1178   /*
1179    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
1180    * basically anything through an HTTP proxy we can't limit this based on
1181    * protocol.
1182    */
1183   if(data->set.str[STRING_USERAGENT]) {
1184     Curl_safefree(data->state.aptr.uagent);
1185     data->state.aptr.uagent =
1186       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
1187     if(!data->state.aptr.uagent)
1188       return CURLE_OUT_OF_MEMORY;
1189   }
1190 
1191   if(!result)
1192     result = Curl_setstropt(&data->state.aptr.user,
1193                             data->set.str[STRING_USERNAME]);
1194   if(!result)
1195     result = Curl_setstropt(&data->state.aptr.passwd,
1196                             data->set.str[STRING_PASSWORD]);
1197   if(!result)
1198     result = Curl_setstropt(&data->state.aptr.proxyuser,
1199                             data->set.str[STRING_PROXYUSERNAME]);
1200   if(!result)
1201     result = Curl_setstropt(&data->state.aptr.proxypasswd,
1202                             data->set.str[STRING_PROXYPASSWORD]);
1203 
1204   data->req.headerbytecount = 0;
1205   Curl_headers_cleanup(data);
1206   return result;
1207 }
1208 
1209 /*
1210  * Curl_posttransfer() is called immediately after a transfer ends
1211  */
Curl_posttransfer(struct Curl_easy * data)1212 CURLcode Curl_posttransfer(struct Curl_easy *data)
1213 {
1214 #if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
1215   /* restore the signal handler for SIGPIPE before we get back */
1216   if(!data->set.no_signal)
1217     signal(SIGPIPE, data->state.prev_signal);
1218 #else
1219   (void)data; /* unused parameter */
1220 #endif
1221 
1222   return CURLE_OK;
1223 }
1224 
1225 /*
1226  * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
1227  * as given by the remote server and set up the new URL to request.
1228  *
1229  * This function DOES NOT FREE the given url.
1230  */
Curl_follow(struct Curl_easy * data,char * newurl,followtype type)1231 CURLcode Curl_follow(struct Curl_easy *data,
1232                      char *newurl,    /* the Location: string */
1233                      followtype type) /* see transfer.h */
1234 {
1235 #ifdef CURL_DISABLE_HTTP
1236   (void)data;
1237   (void)newurl;
1238   (void)type;
1239   /* Location: following will not happen when HTTP is disabled */
1240   return CURLE_TOO_MANY_REDIRECTS;
1241 #else
1242 
1243   /* Location: redirect */
1244   bool disallowport = FALSE;
1245   bool reachedmax = FALSE;
1246   CURLUcode uc;
1247 
1248   DEBUGASSERT(type != FOLLOW_NONE);
1249 
1250   if(type != FOLLOW_FAKE)
1251     data->state.requests++; /* count all real follows */
1252   if(type == FOLLOW_REDIR) {
1253     if((data->set.maxredirs != -1) &&
1254        (data->state.followlocation >= data->set.maxredirs)) {
1255       reachedmax = TRUE;
1256       type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
1257                              to URL */
1258     }
1259     else {
1260       data->state.followlocation++; /* count redirect-followings, including
1261                                        auth reloads */
1262 
1263       if(data->set.http_auto_referer) {
1264         CURLU *u;
1265         char *referer = NULL;
1266 
1267         /* We are asked to automatically set the previous URL as the referer
1268            when we get the next URL. We pick the ->url field, which may or may
1269            not be 100% correct */
1270 
1271         if(data->state.referer_alloc) {
1272           Curl_safefree(data->state.referer);
1273           data->state.referer_alloc = FALSE;
1274         }
1275 
1276         /* Make a copy of the URL without credentials and fragment */
1277         u = curl_url();
1278         if(!u)
1279           return CURLE_OUT_OF_MEMORY;
1280 
1281         uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
1282         if(!uc)
1283           uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
1284         if(!uc)
1285           uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
1286         if(!uc)
1287           uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
1288         if(!uc)
1289           uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
1290 
1291         curl_url_cleanup(u);
1292 
1293         if(uc || !referer)
1294           return CURLE_OUT_OF_MEMORY;
1295 
1296         data->state.referer = referer;
1297         data->state.referer_alloc = TRUE; /* yes, free this later */
1298       }
1299     }
1300   }
1301 
1302   if((type != FOLLOW_RETRY) &&
1303      (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
1304      Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
1305     /* If this is not redirect due to a 401 or 407 response and an absolute
1306        URL: don't allow a custom port number */
1307     disallowport = TRUE;
1308   }
1309 
1310   DEBUGASSERT(data->state.uh);
1311   uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
1312                     (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
1313                     ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
1314                     CURLU_ALLOW_SPACE |
1315                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1316   if(uc) {
1317     if(type != FOLLOW_FAKE) {
1318       failf(data, "The redirect target URL could not be parsed: %s",
1319             curl_url_strerror(uc));
1320       return Curl_uc_to_curlcode(uc);
1321     }
1322 
1323     /* the URL could not be parsed for some reason, but since this is FAKE
1324        mode, just duplicate the field as-is */
1325     newurl = strdup(newurl);
1326     if(!newurl)
1327       return CURLE_OUT_OF_MEMORY;
1328   }
1329   else {
1330     uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
1331     if(uc)
1332       return Curl_uc_to_curlcode(uc);
1333 
1334     /* Clear auth if this redirects to a different port number or protocol,
1335        unless permitted */
1336     if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
1337       char *portnum;
1338       int port;
1339       bool clear = FALSE;
1340 
1341       if(data->set.use_port && data->state.allow_port)
1342         /* a custom port is used */
1343         port = (int)data->set.use_port;
1344       else {
1345         uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
1346                           CURLU_DEFAULT_PORT);
1347         if(uc) {
1348           free(newurl);
1349           return Curl_uc_to_curlcode(uc);
1350         }
1351         port = atoi(portnum);
1352         free(portnum);
1353       }
1354       if(port != data->info.conn_remote_port) {
1355         infof(data, "Clear auth, redirects to port from %u to %u",
1356               data->info.conn_remote_port, port);
1357         clear = TRUE;
1358       }
1359       else {
1360         char *scheme;
1361         const struct Curl_handler *p;
1362         uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
1363         if(uc) {
1364           free(newurl);
1365           return Curl_uc_to_curlcode(uc);
1366         }
1367 
1368         p = Curl_get_scheme_handler(scheme);
1369         if(p && (p->protocol != data->info.conn_protocol)) {
1370           infof(data, "Clear auth, redirects scheme from %s to %s",
1371                 data->info.conn_scheme, scheme);
1372           clear = TRUE;
1373         }
1374         free(scheme);
1375       }
1376       if(clear) {
1377         Curl_safefree(data->state.aptr.user);
1378         Curl_safefree(data->state.aptr.passwd);
1379       }
1380     }
1381   }
1382 
1383   if(type == FOLLOW_FAKE) {
1384     /* we're only figuring out the new url if we would've followed locations
1385        but now we're done so we can get out! */
1386     data->info.wouldredirect = newurl;
1387 
1388     if(reachedmax) {
1389       failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
1390       return CURLE_TOO_MANY_REDIRECTS;
1391     }
1392     return CURLE_OK;
1393   }
1394 
1395   if(disallowport)
1396     data->state.allow_port = FALSE;
1397 
1398   if(data->state.url_alloc)
1399     Curl_safefree(data->state.url);
1400 
1401   data->state.url = newurl;
1402   data->state.url_alloc = TRUE;
1403 
1404   infof(data, "Issue another request to this URL: '%s'", data->state.url);
1405 
1406   /*
1407    * We get here when the HTTP code is 300-399 (and 401). We need to perform
1408    * differently based on exactly what return code there was.
1409    *
1410    * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
1411    * an HTTP (proxy-) authentication scheme other than Basic.
1412    */
1413   switch(data->info.httpcode) {
1414     /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
1415        Authorization: XXXX header in the HTTP request code snippet */
1416     /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
1417        Proxy-Authorization: XXXX header in the HTTP request code snippet */
1418     /* 300 - Multiple Choices */
1419     /* 306 - Not used */
1420     /* 307 - Temporary Redirect */
1421   default:  /* for all above (and the unknown ones) */
1422     /* Some codes are explicitly mentioned since I've checked RFC2616 and they
1423      * seem to be OK to POST to.
1424      */
1425     break;
1426   case 301: /* Moved Permanently */
1427     /* (quote from RFC7231, section 6.4.2)
1428      *
1429      * Note: For historical reasons, a user agent MAY change the request
1430      * method from POST to GET for the subsequent request.  If this
1431      * behavior is undesired, the 307 (Temporary Redirect) status code
1432      * can be used instead.
1433      *
1434      * ----
1435      *
1436      * Many webservers expect this, so these servers often answers to a POST
1437      * request with an error page. To be sure that libcurl gets the page that
1438      * most user agents would get, libcurl has to force GET.
1439      *
1440      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
1441      * can be overridden with CURLOPT_POSTREDIR.
1442      */
1443     if((data->state.httpreq == HTTPREQ_POST
1444         || data->state.httpreq == HTTPREQ_POST_FORM
1445         || data->state.httpreq == HTTPREQ_POST_MIME)
1446        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
1447       infof(data, "Switch from POST to GET");
1448       data->state.httpreq = HTTPREQ_GET;
1449     }
1450     break;
1451   case 302: /* Found */
1452     /* (quote from RFC7231, section 6.4.3)
1453      *
1454      * Note: For historical reasons, a user agent MAY change the request
1455      * method from POST to GET for the subsequent request.  If this
1456      * behavior is undesired, the 307 (Temporary Redirect) status code
1457      * can be used instead.
1458      *
1459      * ----
1460      *
1461      * Many webservers expect this, so these servers often answers to a POST
1462      * request with an error page. To be sure that libcurl gets the page that
1463      * most user agents would get, libcurl has to force GET.
1464      *
1465      * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
1466      * can be overridden with CURLOPT_POSTREDIR.
1467      */
1468     if((data->state.httpreq == HTTPREQ_POST
1469         || data->state.httpreq == HTTPREQ_POST_FORM
1470         || data->state.httpreq == HTTPREQ_POST_MIME)
1471        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
1472       infof(data, "Switch from POST to GET");
1473       data->state.httpreq = HTTPREQ_GET;
1474     }
1475     break;
1476 
1477   case 303: /* See Other */
1478     /* 'See Other' location is not the resource but a substitute for the
1479      * resource. In this case we switch the method to GET/HEAD, unless the
1480      * method is POST and the user specified to keep it as POST.
1481      * https://github.com/curl/curl/issues/5237#issuecomment-614641049
1482      */
1483     if(data->state.httpreq != HTTPREQ_GET &&
1484        ((data->state.httpreq != HTTPREQ_POST &&
1485          data->state.httpreq != HTTPREQ_POST_FORM &&
1486          data->state.httpreq != HTTPREQ_POST_MIME) ||
1487         !(data->set.keep_post & CURL_REDIR_POST_303))) {
1488       data->state.httpreq = HTTPREQ_GET;
1489       infof(data, "Switch to %s",
1490             data->req.no_body?"HEAD":"GET");
1491     }
1492     break;
1493   case 304: /* Not Modified */
1494     /* 304 means we did a conditional request and it was "Not modified".
1495      * We shouldn't get any Location: header in this response!
1496      */
1497     break;
1498   case 305: /* Use Proxy */
1499     /* (quote from RFC2616, section 10.3.6):
1500      * "The requested resource MUST be accessed through the proxy given
1501      * by the Location field. The Location field gives the URI of the
1502      * proxy.  The recipient is expected to repeat this single request
1503      * via the proxy. 305 responses MUST only be generated by origin
1504      * servers."
1505      */
1506     break;
1507   }
1508   Curl_pgrsTime(data, TIMER_REDIRECT);
1509   Curl_pgrsResetTransferSizes(data);
1510 
1511   return CURLE_OK;
1512 #endif /* CURL_DISABLE_HTTP */
1513 }
1514 
1515 /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
1516 
1517    NOTE: that the *url is malloc()ed. */
Curl_retry_request(struct Curl_easy * data,char ** url)1518 CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
1519 {
1520   struct connectdata *conn = data->conn;
1521   bool retry = FALSE;
1522   *url = NULL;
1523 
1524   /* if we're talking upload, we can't do the checks below, unless the protocol
1525      is HTTP as when uploading over HTTP we will still get a response */
1526   if(data->state.upload &&
1527      !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
1528     return CURLE_OK;
1529 
1530   if((data->req.bytecount + data->req.headerbytecount == 0) &&
1531      conn->bits.reuse &&
1532      (!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP))
1533 #ifndef CURL_DISABLE_RTSP
1534      && (data->set.rtspreq != RTSPREQ_RECEIVE)
1535 #endif
1536     )
1537     /* We got no data, we attempted to reuse a connection. For HTTP this
1538        can be a retry so we try again regardless if we expected a body.
1539        For other protocols we only try again only if we expected a body.
1540 
1541        This might happen if the connection was left alive when we were
1542        done using it before, but that was closed when we wanted to read from
1543        it again. Bad luck. Retry the same request on a fresh connect! */
1544     retry = TRUE;
1545   else if(data->state.refused_stream &&
1546           (data->req.bytecount + data->req.headerbytecount == 0) ) {
1547     /* This was sent on a refused stream, safe to rerun. A refused stream
1548        error can typically only happen on HTTP/2 level if the stream is safe
1549        to issue again, but the nghttp2 API can deliver the message to other
1550        streams as well, which is why this adds the check the data counters
1551        too. */
1552     infof(data, "REFUSED_STREAM, retrying a fresh connect");
1553     data->state.refused_stream = FALSE; /* clear again */
1554     retry = TRUE;
1555   }
1556   if(retry) {
1557 #define CONN_MAX_RETRIES 5
1558     if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
1559       failf(data, "Connection died, tried %d times before giving up",
1560             CONN_MAX_RETRIES);
1561       data->state.retrycount = 0;
1562       return CURLE_SEND_ERROR;
1563     }
1564     infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
1565           data->state.retrycount);
1566     *url = strdup(data->state.url);
1567     if(!*url)
1568       return CURLE_OUT_OF_MEMORY;
1569 
1570     connclose(conn, "retry"); /* close this connection */
1571     conn->bits.retry = TRUE; /* mark this as a connection we're about
1572                                 to retry. Marking it this way should
1573                                 prevent i.e HTTP transfers to return
1574                                 error just because nothing has been
1575                                 transferred! */
1576 
1577 
1578     if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
1579        data->req.writebytecount) {
1580       data->state.rewindbeforesend = TRUE;
1581       infof(data, "state.rewindbeforesend = TRUE");
1582     }
1583   }
1584   return CURLE_OK;
1585 }
1586 
1587 /*
1588  * Curl_setup_transfer() is called to setup some basic properties for the
1589  * upcoming transfer.
1590  */
1591 void
Curl_setup_transfer(struct Curl_easy * data,int sockindex,curl_off_t size,bool getheader,int writesockindex)1592 Curl_setup_transfer(
1593   struct Curl_easy *data,   /* transfer */
1594   int sockindex,            /* socket index to read from or -1 */
1595   curl_off_t size,          /* -1 if unknown at this point */
1596   bool getheader,           /* TRUE if header parsing is wanted */
1597   int writesockindex        /* socket index to write to, it may very well be
1598                                the same we read from. -1 disables */
1599   )
1600 {
1601   struct SingleRequest *k = &data->req;
1602   struct connectdata *conn = data->conn;
1603   struct HTTP *http = data->req.p.http;
1604   bool httpsending;
1605 
1606   DEBUGASSERT(conn != NULL);
1607   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
1608 
1609   httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
1610                  (http->sending == HTTPSEND_REQUEST));
1611 
1612   if(conn->bits.multiplex || conn->httpversion >= 20 || httpsending) {
1613     /* when multiplexing, the read/write sockets need to be the same! */
1614     conn->sockfd = sockindex == -1 ?
1615       ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
1616       conn->sock[sockindex];
1617     conn->writesockfd = conn->sockfd;
1618     if(httpsending)
1619       /* special and very HTTP-specific */
1620       writesockindex = FIRSTSOCKET;
1621   }
1622   else {
1623     conn->sockfd = sockindex == -1 ?
1624       CURL_SOCKET_BAD : conn->sock[sockindex];
1625     conn->writesockfd = writesockindex == -1 ?
1626       CURL_SOCKET_BAD:conn->sock[writesockindex];
1627   }
1628   k->getheader = getheader;
1629 
1630   k->size = size;
1631 
1632   /* The code sequence below is placed in this function just because all
1633      necessary input is not always known in do_complete() as this function may
1634      be called after that */
1635 
1636   if(!k->getheader) {
1637     k->header = FALSE;
1638     if(size > 0)
1639       Curl_pgrsSetDownloadSize(data, size);
1640   }
1641   /* we want header and/or body, if neither then don't do this! */
1642   if(k->getheader || !data->req.no_body) {
1643 
1644     if(sockindex != -1)
1645       k->keepon |= KEEP_RECV;
1646 
1647     if(writesockindex != -1) {
1648       /* HTTP 1.1 magic:
1649 
1650          Even if we require a 100-return code before uploading data, we might
1651          need to write data before that since the REQUEST may not have been
1652          finished sent off just yet.
1653 
1654          Thus, we must check if the request has been sent before we set the
1655          state info where we wait for the 100-return code
1656       */
1657       if((data->state.expect100header) &&
1658          (conn->handler->protocol&PROTO_FAMILY_HTTP) &&
1659          (http->sending == HTTPSEND_BODY)) {
1660         /* wait with write until we either got 100-continue or a timeout */
1661         k->exp100 = EXP100_AWAITING_CONTINUE;
1662         k->start100 = Curl_now();
1663 
1664         /* Set a timeout for the multi interface. Add the inaccuracy margin so
1665            that we don't fire slightly too early and get denied to run. */
1666         Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
1667       }
1668       else {
1669         if(data->state.expect100header)
1670           /* when we've sent off the rest of the headers, we must await a
1671              100-continue but first finish sending the request */
1672           k->exp100 = EXP100_SENDING_REQUEST;
1673 
1674         /* enable the write bit when we're not waiting for continue */
1675         k->keepon |= KEEP_SEND;
1676       }
1677     } /* if(writesockindex != -1) */
1678   } /* if(k->getheader || !data->req.no_body) */
1679 
1680 }
1681 
Curl_xfer_write_resp(struct Curl_easy * data,char * buf,size_t blen,bool is_eos,bool * done)1682 CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
1683                               char *buf, size_t blen,
1684                               bool is_eos, bool *done)
1685 {
1686   CURLcode result = CURLE_OK;
1687 
1688   if(data->conn->handler->write_resp) {
1689     /* protocol handlers offering this function take full responsibility
1690      * for writing all received download data to the client. */
1691     result = data->conn->handler->write_resp(data, buf, blen, is_eos, done);
1692   }
1693   else {
1694     /* No special handling by protocol handler, write all received data
1695      * as BODY to the client. */
1696     if(blen || is_eos) {
1697       int cwtype = CLIENTWRITE_BODY;
1698       if(is_eos)
1699         cwtype |= CLIENTWRITE_EOS;
1700 
1701 #ifndef CURL_DISABLE_POP3
1702       if(blen && data->conn->handler->protocol & PROTO_FAMILY_POP3) {
1703         result = data->req.ignorebody? CURLE_OK :
1704                  Curl_pop3_write(data, buf, blen);
1705       }
1706       else
1707 #endif /* CURL_DISABLE_POP3 */
1708         result = Curl_client_write(data, cwtype, buf, blen);
1709     }
1710   }
1711 
1712   if(!result && is_eos) {
1713     /* If we wrote the EOS, we are definitely done */
1714     data->req.eos_written = TRUE;
1715     data->req.download_done = TRUE;
1716   }
1717   return result;
1718 }
1719