• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
27 #endif
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
33 #endif
34 #ifdef HAVE_NET_IF_H
35 #include <net/if.h>
36 #endif
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
39 #endif
40 
41 #ifdef HAVE_SYS_PARAM_H
42 #include <sys/param.h>
43 #endif
44 
45 #ifdef __VMS
46 #include <in.h>
47 #include <inet.h>
48 #endif
49 
50 #ifdef HAVE_SYS_UN_H
51 #include <sys/un.h>
52 #endif
53 
54 #ifndef HAVE_SOCKET
55 #error "We can't compile without socket() support!"
56 #endif
57 
58 #include <limits.h>
59 
60 #ifdef USE_LIBIDN2
61 #include <idn2.h>
62 
63 #elif defined(USE_WIN32_IDN)
64 /* prototype for curl_win32_idn_to_ascii() */
65 bool curl_win32_idn_to_ascii(const char *in, char **out);
66 #endif  /* USE_LIBIDN2 */
67 
68 #include "urldata.h"
69 #include "netrc.h"
70 
71 #include "formdata.h"
72 #include "mime.h"
73 #include "vtls/vtls.h"
74 #include "hostip.h"
75 #include "transfer.h"
76 #include "sendf.h"
77 #include "progress.h"
78 #include "cookie.h"
79 #include "strcase.h"
80 #include "strerror.h"
81 #include "escape.h"
82 #include "strtok.h"
83 #include "share.h"
84 #include "content_encoding.h"
85 #include "http_digest.h"
86 #include "http_negotiate.h"
87 #include "select.h"
88 #include "multiif.h"
89 #include "easyif.h"
90 #include "speedcheck.h"
91 #include "warnless.h"
92 #include "non-ascii.h"
93 #include "inet_pton.h"
94 #include "getinfo.h"
95 #include "urlapi-int.h"
96 
97 /* And now for the protocols */
98 #include "ftp.h"
99 #include "dict.h"
100 #include "telnet.h"
101 #include "tftp.h"
102 #include "http.h"
103 #include "http2.h"
104 #include "file.h"
105 #include "curl_ldap.h"
106 #include "ssh.h"
107 #include "imap.h"
108 #include "url.h"
109 #include "connect.h"
110 #include "inet_ntop.h"
111 #include "http_ntlm.h"
112 #include "curl_ntlm_wb.h"
113 #include "socks.h"
114 #include "curl_rtmp.h"
115 #include "gopher.h"
116 #include "http_proxy.h"
117 #include "conncache.h"
118 #include "multihandle.h"
119 #include "pipeline.h"
120 #include "dotdot.h"
121 #include "strdup.h"
122 #include "setopt.h"
123 #include "altsvc.h"
124 
125 /* The last 3 #include files should be in this order */
126 #include "curl_printf.h"
127 #include "curl_memory.h"
128 #include "memdebug.h"
129 
130 static void conn_free(struct connectdata *conn);
131 static void free_idnconverted_hostname(struct hostname *host);
132 static unsigned int get_protocol_family(unsigned int protocol);
133 
134 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
135  * more than just a few bytes to play with. Don't let it become too small or
136  * bad things will happen.
137  */
138 #if READBUFFER_SIZE < READBUFFER_MIN
139 # error READBUFFER_SIZE is too small
140 #endif
141 
142 
143 /*
144  * Protocol table.
145  */
146 
147 static const struct Curl_handler * const protocols[] = {
148 
149 #ifndef CURL_DISABLE_HTTP
150   &Curl_handler_http,
151 #endif
152 
153 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
154   &Curl_handler_https,
155 #endif
156 
157 #ifndef CURL_DISABLE_FTP
158   &Curl_handler_ftp,
159 #endif
160 
161 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
162   &Curl_handler_ftps,
163 #endif
164 
165 #ifndef CURL_DISABLE_TELNET
166   &Curl_handler_telnet,
167 #endif
168 
169 #ifndef CURL_DISABLE_DICT
170   &Curl_handler_dict,
171 #endif
172 
173 #ifndef CURL_DISABLE_LDAP
174   &Curl_handler_ldap,
175 #if !defined(CURL_DISABLE_LDAPS) && \
176     ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
177      (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
178   &Curl_handler_ldaps,
179 #endif
180 #endif
181 
182 #ifndef CURL_DISABLE_FILE
183   &Curl_handler_file,
184 #endif
185 
186 #ifndef CURL_DISABLE_TFTP
187   &Curl_handler_tftp,
188 #endif
189 
190 #if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
191   &Curl_handler_scp,
192 #endif
193 
194 #if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
195   &Curl_handler_sftp,
196 #endif
197 
198 #ifndef CURL_DISABLE_IMAP
199   &Curl_handler_imap,
200 #ifdef USE_SSL
201   &Curl_handler_imaps,
202 #endif
203 #endif
204 
205 #ifndef CURL_DISABLE_POP3
206   &Curl_handler_pop3,
207 #ifdef USE_SSL
208   &Curl_handler_pop3s,
209 #endif
210 #endif
211 
212 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
213    (CURL_SIZEOF_CURL_OFF_T > 4) && \
214    (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
215   &Curl_handler_smb,
216 #ifdef USE_SSL
217   &Curl_handler_smbs,
218 #endif
219 #endif
220 
221 #ifndef CURL_DISABLE_SMTP
222   &Curl_handler_smtp,
223 #ifdef USE_SSL
224   &Curl_handler_smtps,
225 #endif
226 #endif
227 
228 #ifndef CURL_DISABLE_RTSP
229   &Curl_handler_rtsp,
230 #endif
231 
232 #ifndef CURL_DISABLE_GOPHER
233   &Curl_handler_gopher,
234 #endif
235 
236 #ifdef USE_LIBRTMP
237   &Curl_handler_rtmp,
238   &Curl_handler_rtmpt,
239   &Curl_handler_rtmpe,
240   &Curl_handler_rtmpte,
241   &Curl_handler_rtmps,
242   &Curl_handler_rtmpts,
243 #endif
244 
245   (struct Curl_handler *) NULL
246 };
247 
248 /*
249  * Dummy handler for undefined protocol schemes.
250  */
251 
252 static const struct Curl_handler Curl_handler_dummy = {
253   "<no protocol>",                      /* scheme */
254   ZERO_NULL,                            /* setup_connection */
255   ZERO_NULL,                            /* do_it */
256   ZERO_NULL,                            /* done */
257   ZERO_NULL,                            /* do_more */
258   ZERO_NULL,                            /* connect_it */
259   ZERO_NULL,                            /* connecting */
260   ZERO_NULL,                            /* doing */
261   ZERO_NULL,                            /* proto_getsock */
262   ZERO_NULL,                            /* doing_getsock */
263   ZERO_NULL,                            /* domore_getsock */
264   ZERO_NULL,                            /* perform_getsock */
265   ZERO_NULL,                            /* disconnect */
266   ZERO_NULL,                            /* readwrite */
267   ZERO_NULL,                            /* connection_check */
268   0,                                    /* defport */
269   0,                                    /* protocol */
270   PROTOPT_NONE                          /* flags */
271 };
272 
Curl_freeset(struct Curl_easy * data)273 void Curl_freeset(struct Curl_easy *data)
274 {
275   /* Free all dynamic strings stored in the data->set substructure. */
276   enum dupstring i;
277   for(i = (enum dupstring)0; i < STRING_LAST; i++) {
278     Curl_safefree(data->set.str[i]);
279   }
280 
281   if(data->change.referer_alloc) {
282     Curl_safefree(data->change.referer);
283     data->change.referer_alloc = FALSE;
284   }
285   data->change.referer = NULL;
286   if(data->change.url_alloc) {
287     Curl_safefree(data->change.url);
288     data->change.url_alloc = FALSE;
289   }
290   data->change.url = NULL;
291 
292   Curl_mime_cleanpart(&data->set.mimepost);
293 }
294 
295 /* free the URL pieces */
up_free(struct Curl_easy * data)296 static void up_free(struct Curl_easy *data)
297 {
298   struct urlpieces *up = &data->state.up;
299   Curl_safefree(up->scheme);
300   Curl_safefree(up->hostname);
301   Curl_safefree(up->port);
302   Curl_safefree(up->user);
303   Curl_safefree(up->password);
304   Curl_safefree(up->options);
305   Curl_safefree(up->path);
306   Curl_safefree(up->query);
307   if(data->set.uh != data->state.uh)
308     curl_url_cleanup(data->state.uh);
309   data->state.uh = NULL;
310 }
311 
312 /*
313  * This is the internal function curl_easy_cleanup() calls. This should
314  * cleanup and free all resources associated with this sessionhandle.
315  *
316  * NOTE: if we ever add something that attempts to write to a socket or
317  * similar here, we must ignore SIGPIPE first. It is currently only done
318  * when curl_easy_perform() is invoked.
319  */
320 
Curl_close(struct Curl_easy * data)321 CURLcode Curl_close(struct Curl_easy *data)
322 {
323   struct Curl_multi *m;
324 
325   if(!data)
326     return CURLE_OK;
327 
328   Curl_expire_clear(data); /* shut off timers */
329 
330   m = data->multi;
331   if(m)
332     /* This handle is still part of a multi handle, take care of this first
333        and detach this handle from there. */
334     curl_multi_remove_handle(data->multi, data);
335 
336   if(data->multi_easy) {
337     /* when curl_easy_perform() is used, it creates its own multi handle to
338        use and this is the one */
339     curl_multi_cleanup(data->multi_easy);
340     data->multi_easy = NULL;
341   }
342 
343   /* Destroy the timeout list that is held in the easy handle. It is
344      /normally/ done by curl_multi_remove_handle() but this is "just in
345      case" */
346   Curl_llist_destroy(&data->state.timeoutlist, NULL);
347 
348   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
349                       the multi handle, since that function uses the magic
350                       field! */
351 
352   if(data->state.rangestringalloc)
353     free(data->state.range);
354 
355   /* freed here just in case DONE wasn't called */
356   Curl_free_request_state(data);
357 
358   /* Close down all open SSL info and sessions */
359   Curl_ssl_close_all(data);
360   Curl_safefree(data->state.first_host);
361   Curl_safefree(data->state.scratch);
362   Curl_ssl_free_certinfo(data);
363 
364   /* Cleanup possible redirect junk */
365   free(data->req.newurl);
366   data->req.newurl = NULL;
367 
368   if(data->change.referer_alloc) {
369     Curl_safefree(data->change.referer);
370     data->change.referer_alloc = FALSE;
371   }
372   data->change.referer = NULL;
373 
374   up_free(data);
375   Curl_safefree(data->state.buffer);
376   Curl_safefree(data->state.headerbuff);
377   Curl_safefree(data->state.ulbuf);
378   Curl_flush_cookies(data, 1);
379 #ifdef USE_ALTSVC
380   Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]);
381   Curl_altsvc_cleanup(data->asi);
382   data->asi = NULL;
383 #endif
384   Curl_digest_cleanup(data);
385   Curl_safefree(data->info.contenttype);
386   Curl_safefree(data->info.wouldredirect);
387 
388   /* this destroys the channel and we cannot use it anymore after this */
389   Curl_resolver_cleanup(data->state.resolver);
390 
391   Curl_http2_cleanup_dependencies(data);
392   Curl_convert_close(data);
393 
394   /* No longer a dirty share, if it exists */
395   if(data->share) {
396     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
397     data->share->dirty--;
398     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
399   }
400 
401   /* destruct wildcard structures if it is needed */
402   Curl_wildcard_dtor(&data->wildcard);
403   Curl_freeset(data);
404   free(data);
405   return CURLE_OK;
406 }
407 
408 /*
409  * Initialize the UserDefined fields within a Curl_easy.
410  * This may be safely called on a new or existing Curl_easy.
411  */
Curl_init_userdefined(struct Curl_easy * data)412 CURLcode Curl_init_userdefined(struct Curl_easy *data)
413 {
414   struct UserDefined *set = &data->set;
415   CURLcode result = CURLE_OK;
416 
417   set->out = stdout; /* default output to stdout */
418   set->in_set = stdin;  /* default input from stdin */
419   set->err  = stderr;  /* default stderr to stderr */
420 
421   /* use fwrite as default function to store output */
422   set->fwrite_func = (curl_write_callback)fwrite;
423 
424   /* use fread as default function to read input */
425   set->fread_func_set = (curl_read_callback)fread;
426   set->is_fread_set = 0;
427   set->is_fwrite_set = 0;
428 
429   set->seek_func = ZERO_NULL;
430   set->seek_client = ZERO_NULL;
431 
432   /* conversion callbacks for non-ASCII hosts */
433   set->convfromnetwork = ZERO_NULL;
434   set->convtonetwork   = ZERO_NULL;
435   set->convfromutf8    = ZERO_NULL;
436 
437   set->filesize = -1;        /* we don't know the size */
438   set->postfieldsize = -1;   /* unknown size */
439   set->maxredirs = -1;       /* allow any amount by default */
440 
441   set->httpreq = HTTPREQ_GET; /* Default HTTP request */
442   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
443   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
444   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
445   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
446   set->ftp_filemethod = FTPFILE_MULTICWD;
447 
448   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
449 
450   /* Set the default size of the SSL session ID cache */
451   set->general_ssl.max_ssl_sessions = 5;
452 
453   set->proxyport = 0;
454   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
455   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
456   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
457 
458   /* SOCKS5 proxy auth defaults to username/password + GSS-API */
459   set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
460 
461   /* make libcurl quiet by default: */
462   set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
463 
464   Curl_mime_initpart(&set->mimepost, data);
465 
466   /*
467    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
468    * switched off unless wanted.
469    */
470   set->ssl.primary.verifypeer = TRUE;
471   set->ssl.primary.verifyhost = TRUE;
472 #ifdef USE_TLS_SRP
473   set->ssl.authtype = CURL_TLSAUTH_NONE;
474 #endif
475   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
476                                                       type */
477   set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
478                                         default */
479   set->proxy_ssl = set->ssl;
480 
481   set->new_file_perms = 0644;    /* Default permissions */
482   set->new_directory_perms = 0755; /* Default permissions */
483 
484   /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
485      define since we internally only use the lower 16 bits for the passed
486      in bitmask to not conflict with the private bits */
487   set->allowed_protocols = CURLPROTO_ALL;
488   set->redir_protocols = CURLPROTO_ALL &  /* All except FILE, SCP and SMB */
489                           ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
490                             CURLPROTO_SMBS);
491 
492 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
493   /*
494    * disallow unprotected protection negotiation NEC reference implementation
495    * seem not to follow rfc1961 section 4.3/4.4
496    */
497   set->socks5_gssapi_nec = FALSE;
498 #endif
499 
500   /* Set the default CA cert bundle/path detected/specified at build time.
501    *
502    * If Schannel is the selected SSL backend then these locations are
503    * ignored. We allow setting CA location for schannel only when explicitly
504    * specified by the user via CURLOPT_CAINFO / --cacert.
505    */
506   if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
507 #if defined(CURL_CA_BUNDLE)
508     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
509     if(result)
510       return result;
511 
512     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
513                             CURL_CA_BUNDLE);
514     if(result)
515       return result;
516 #endif
517 #if defined(CURL_CA_PATH)
518     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
519     if(result)
520       return result;
521 
522     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
523     if(result)
524       return result;
525 #endif
526   }
527 
528   set->wildcard_enabled = FALSE;
529   set->chunk_bgn      = ZERO_NULL;
530   set->chunk_end      = ZERO_NULL;
531   set->tcp_keepalive = FALSE;
532   set->tcp_keepintvl = 60;
533   set->tcp_keepidle = 60;
534   set->tcp_fastopen = FALSE;
535   set->tcp_nodelay = TRUE;
536   set->ssl_enable_npn = TRUE;
537   set->ssl_enable_alpn = TRUE;
538   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
539   set->sep_headers = TRUE; /* separated header lists by default */
540   set->buffer_size = READBUFFER_SIZE;
541   set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
542   set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
543   set->fnmatch = ZERO_NULL;
544   set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
545   set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
546   set->http09_allowed = TRUE;
547   set->httpversion =
548 #ifdef USE_NGHTTP2
549     CURL_HTTP_VERSION_2TLS
550 #else
551     CURL_HTTP_VERSION_1_1
552 #endif
553     ;
554   Curl_http2_init_userset(set);
555   return result;
556 }
557 
558 /**
559  * Curl_open()
560  *
561  * @param curl is a pointer to a sessionhandle pointer that gets set by this
562  * function.
563  * @return CURLcode
564  */
565 
Curl_open(struct Curl_easy ** curl)566 CURLcode Curl_open(struct Curl_easy **curl)
567 {
568   CURLcode result;
569   struct Curl_easy *data;
570 
571   /* Very simple start-up: alloc the struct, init it with zeroes and return */
572   data = calloc(1, sizeof(struct Curl_easy));
573   if(!data) {
574     /* this is a very serious error */
575     DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
576     return CURLE_OUT_OF_MEMORY;
577   }
578 
579   data->magic = CURLEASY_MAGIC_NUMBER;
580 
581   result = Curl_resolver_init(data, &data->state.resolver);
582   if(result) {
583     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
584     free(data);
585     return result;
586   }
587 
588   /* We do some initial setup here, all those fields that can't be just 0 */
589 
590   data->state.buffer = malloc(READBUFFER_SIZE + 1);
591   if(!data->state.buffer) {
592     DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
593     result = CURLE_OUT_OF_MEMORY;
594   }
595   else {
596     data->state.headerbuff = malloc(HEADERSIZE);
597     if(!data->state.headerbuff) {
598       DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
599       result = CURLE_OUT_OF_MEMORY;
600     }
601     else {
602       result = Curl_init_userdefined(data);
603 
604       data->state.headersize = HEADERSIZE;
605       Curl_convert_init(data);
606       Curl_initinfo(data);
607 
608       /* most recent connection is not yet defined */
609       data->state.lastconnect = NULL;
610 
611       data->progress.flags |= PGRS_HIDE;
612       data->state.current_speed = -1; /* init to negative == impossible */
613 
614       Curl_http2_init_state(&data->state);
615     }
616   }
617 
618   if(result) {
619     Curl_resolver_cleanup(data->state.resolver);
620     free(data->state.buffer);
621     free(data->state.headerbuff);
622     Curl_freeset(data);
623     free(data);
624     data = NULL;
625   }
626   else
627     *curl = data;
628 
629   return result;
630 }
631 
632 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
conn_reset_postponed_data(struct connectdata * conn,int num)633 static void conn_reset_postponed_data(struct connectdata *conn, int num)
634 {
635   struct postponed_data * const psnd = &(conn->postponed[num]);
636   if(psnd->buffer) {
637     DEBUGASSERT(psnd->allocated_size > 0);
638     DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
639     DEBUGASSERT(psnd->recv_size ?
640                 (psnd->recv_processed < psnd->recv_size) :
641                 (psnd->recv_processed == 0));
642     DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
643     free(psnd->buffer);
644     psnd->buffer = NULL;
645     psnd->allocated_size = 0;
646     psnd->recv_size = 0;
647     psnd->recv_processed = 0;
648 #ifdef DEBUGBUILD
649     psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
650 #endif /* DEBUGBUILD */
651   }
652   else {
653     DEBUGASSERT(psnd->allocated_size == 0);
654     DEBUGASSERT(psnd->recv_size == 0);
655     DEBUGASSERT(psnd->recv_processed == 0);
656     DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
657   }
658 }
659 
conn_reset_all_postponed_data(struct connectdata * conn)660 static void conn_reset_all_postponed_data(struct connectdata *conn)
661 {
662   conn_reset_postponed_data(conn, 0);
663   conn_reset_postponed_data(conn, 1);
664 }
665 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
666 /* Use "do-nothing" macro instead of function when workaround not used */
667 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
668 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
669 
670 
conn_shutdown(struct connectdata * conn)671 static void conn_shutdown(struct connectdata *conn)
672 {
673   if(!conn)
674     return;
675 
676   infof(conn->data, "Closing connection %ld\n", conn->connection_id);
677   DEBUGASSERT(conn->data);
678 
679   /* possible left-overs from the async name resolvers */
680   Curl_resolver_cancel(conn);
681 
682   /* close the SSL stuff before we close any sockets since they will/may
683      write to the sockets */
684   Curl_ssl_close(conn, FIRSTSOCKET);
685   Curl_ssl_close(conn, SECONDARYSOCKET);
686 
687   /* close possibly still open sockets */
688   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
689     Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
690   if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
691     Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
692   if(CURL_SOCKET_BAD != conn->tempsock[0])
693     Curl_closesocket(conn, conn->tempsock[0]);
694   if(CURL_SOCKET_BAD != conn->tempsock[1])
695     Curl_closesocket(conn, conn->tempsock[1]);
696 
697 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
698     defined(NTLM_WB_ENABLED)
699   Curl_ntlm_wb_cleanup(conn);
700 #endif
701 
702   /* unlink ourselves. this should be called last since other shutdown
703      procedures need a valid conn->data and this may clear it. */
704   Curl_conncache_remove_conn(conn->data, conn, TRUE);
705 }
706 
conn_free(struct connectdata * conn)707 static void conn_free(struct connectdata *conn)
708 {
709   if(!conn)
710     return;
711 
712   free_idnconverted_hostname(&conn->host);
713   free_idnconverted_hostname(&conn->conn_to_host);
714   free_idnconverted_hostname(&conn->http_proxy.host);
715   free_idnconverted_hostname(&conn->socks_proxy.host);
716 
717   Curl_safefree(conn->user);
718   Curl_safefree(conn->passwd);
719   Curl_safefree(conn->oauth_bearer);
720   Curl_safefree(conn->options);
721   Curl_safefree(conn->http_proxy.user);
722   Curl_safefree(conn->socks_proxy.user);
723   Curl_safefree(conn->http_proxy.passwd);
724   Curl_safefree(conn->socks_proxy.passwd);
725   Curl_safefree(conn->allocptr.proxyuserpwd);
726   Curl_safefree(conn->allocptr.uagent);
727   Curl_safefree(conn->allocptr.userpwd);
728   Curl_safefree(conn->allocptr.accept_encoding);
729   Curl_safefree(conn->allocptr.te);
730   Curl_safefree(conn->allocptr.rangeline);
731   Curl_safefree(conn->allocptr.ref);
732   Curl_safefree(conn->allocptr.host);
733   Curl_safefree(conn->allocptr.cookiehost);
734   Curl_safefree(conn->allocptr.rtsp_transport);
735   Curl_safefree(conn->trailer);
736   Curl_safefree(conn->host.rawalloc); /* host name buffer */
737   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
738   Curl_safefree(conn->hostname_resolve);
739   Curl_safefree(conn->secondaryhostname);
740   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
741   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
742   Curl_safefree(conn->master_buffer);
743   Curl_safefree(conn->connect_state);
744 
745   conn_reset_all_postponed_data(conn);
746 
747   Curl_llist_destroy(&conn->send_pipe, NULL);
748   Curl_llist_destroy(&conn->recv_pipe, NULL);
749 
750   Curl_safefree(conn->localdev);
751   Curl_free_primary_ssl_config(&conn->ssl_config);
752   Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
753 
754 #ifdef USE_UNIX_SOCKETS
755   Curl_safefree(conn->unix_domain_socket);
756 #endif
757 
758 #ifdef USE_SSL
759   Curl_safefree(conn->ssl_extra);
760 #endif
761   free(conn); /* free all the connection oriented data */
762 }
763 
764 /*
765  * Disconnects the given connection. Note the connection may not be the
766  * primary connection, like when freeing room in the connection cache or
767  * killing of a dead old connection.
768  *
769  * A connection needs an easy handle when closing down. We support this passed
770  * in separately since the connection to get closed here is often already
771  * disassociated from an easy handle.
772  *
773  * This function MUST NOT reset state in the Curl_easy struct if that
774  * isn't strictly bound to the life-time of *this* particular connection.
775  *
776  */
777 
Curl_disconnect(struct Curl_easy * data,struct connectdata * conn,bool dead_connection)778 CURLcode Curl_disconnect(struct Curl_easy *data,
779                          struct connectdata *conn, bool dead_connection)
780 {
781   if(!conn)
782     return CURLE_OK; /* this is closed and fine already */
783 
784   if(!data) {
785     DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
786     return CURLE_OK;
787   }
788 
789   /*
790    * If this connection isn't marked to force-close, leave it open if there
791    * are other users of it
792    */
793   if(CONN_INUSE(conn) && !dead_connection) {
794     DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
795     return CURLE_OK;
796   }
797 
798   if(conn->dns_entry != NULL) {
799     Curl_resolv_unlock(data, conn->dns_entry);
800     conn->dns_entry = NULL;
801   }
802 
803   Curl_hostcache_prune(data); /* kill old DNS cache entries */
804 
805 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
806   /* Cleanup NTLM connection-related data */
807   Curl_http_ntlm_cleanup(conn);
808 #endif
809 #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
810   /* Cleanup NEGOTIATE connection-related data */
811   Curl_cleanup_negotiate(conn);
812 #endif
813 
814   /* the protocol specific disconnect handler and conn_shutdown need a transfer
815      for the connection! */
816   conn->data = data;
817 
818   if(conn->handler->disconnect)
819     /* This is set if protocol-specific cleanups should be made */
820     conn->handler->disconnect(conn, dead_connection);
821 
822   conn_shutdown(conn);
823   conn_free(conn);
824   return CURLE_OK;
825 }
826 
827 /*
828  * This function should return TRUE if the socket is to be assumed to
829  * be dead. Most commonly this happens when the server has closed the
830  * connection due to inactivity.
831  */
SocketIsDead(curl_socket_t sock)832 static bool SocketIsDead(curl_socket_t sock)
833 {
834   int sval;
835   bool ret_val = TRUE;
836 
837   sval = SOCKET_READABLE(sock, 0);
838   if(sval == 0)
839     /* timeout */
840     ret_val = FALSE;
841 
842   return ret_val;
843 }
844 
845 /*
846  * IsPipeliningPossible()
847  *
848  * Return a bitmask with the available pipelining and multiplexing options for
849  * the given requested connection.
850  */
IsPipeliningPossible(const struct Curl_easy * handle,const struct connectdata * conn)851 static int IsPipeliningPossible(const struct Curl_easy *handle,
852                                 const struct connectdata *conn)
853 {
854   int avail = 0;
855 
856   /* If a HTTP protocol and pipelining is enabled */
857   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
858      (!conn->bits.protoconnstart || !conn->bits.close)) {
859 
860     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
861        (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
862        (handle->set.httpreq == HTTPREQ_GET ||
863         handle->set.httpreq == HTTPREQ_HEAD))
864       /* didn't ask for HTTP/1.0 and a GET or HEAD */
865       avail |= CURLPIPE_HTTP1;
866 
867     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
868        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
869       /* allows HTTP/2 */
870       avail |= CURLPIPE_MULTIPLEX;
871   }
872   return avail;
873 }
874 
875 /* Returns non-zero if a handle was removed */
Curl_removeHandleFromPipeline(struct Curl_easy * handle,struct curl_llist * pipeline)876 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
877                                   struct curl_llist *pipeline)
878 {
879   if(pipeline) {
880     struct curl_llist_element *curr;
881 
882     curr = pipeline->head;
883     while(curr) {
884       if(curr->ptr == handle) {
885         Curl_llist_remove(pipeline, curr, NULL);
886         return 1; /* we removed a handle */
887       }
888       curr = curr->next;
889     }
890   }
891 
892   return 0;
893 }
894 
895 #if 0 /* this code is saved here as it is useful for debugging purposes */
896 static void Curl_printPipeline(struct curl_llist *pipeline)
897 {
898   struct curl_llist_element *curr;
899 
900   curr = pipeline->head;
901   while(curr) {
902     struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
903     infof(data, "Handle in pipeline: %s\n", data->state.path);
904     curr = curr->next;
905   }
906 }
907 #endif
908 
gethandleathead(struct curl_llist * pipeline)909 static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
910 {
911   struct curl_llist_element *curr = pipeline->head;
912 #ifdef DEBUGBUILD
913   {
914     struct curl_llist_element *p = pipeline->head;
915     while(p) {
916       struct Curl_easy *e = p->ptr;
917       DEBUGASSERT(GOOD_EASY_HANDLE(e));
918       p = p->next;
919     }
920   }
921 #endif
922   if(curr) {
923     return (struct Curl_easy *) curr->ptr;
924   }
925 
926   return NULL;
927 }
928 
929 /* remove the specified connection from all (possible) pipelines and related
930    queues */
Curl_getoff_all_pipelines(struct Curl_easy * data,struct connectdata * conn)931 void Curl_getoff_all_pipelines(struct Curl_easy *data,
932                                struct connectdata *conn)
933 {
934   if(!conn->bundle)
935     return;
936   if(conn->bundle->multiuse == BUNDLE_PIPELINING) {
937     bool recv_head = (conn->readchannel_inuse &&
938                       Curl_recvpipe_head(data, conn));
939     bool send_head = (conn->writechannel_inuse &&
940                       Curl_sendpipe_head(data, conn));
941 
942     if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
943       Curl_pipeline_leave_read(conn);
944     if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
945       Curl_pipeline_leave_write(conn);
946   }
947   else {
948     (void)Curl_removeHandleFromPipeline(data, &conn->recv_pipe);
949     (void)Curl_removeHandleFromPipeline(data, &conn->send_pipe);
950   }
951 }
952 
953 static bool
proxy_info_matches(const struct proxy_info * data,const struct proxy_info * needle)954 proxy_info_matches(const struct proxy_info* data,
955                    const struct proxy_info* needle)
956 {
957   if((data->proxytype == needle->proxytype) &&
958      (data->port == needle->port) &&
959      Curl_safe_strcasecompare(data->host.name, needle->host.name))
960     return TRUE;
961 
962   return FALSE;
963 }
964 
965 /*
966  * This function checks if the given connection is dead and extracts it from
967  * the connection cache if so.
968  *
969  * When this is called as a Curl_conncache_foreach() callback, the connection
970  * cache lock is held!
971  *
972  * Returns TRUE if the connection was dead and extracted.
973  */
extract_if_dead(struct connectdata * conn,struct Curl_easy * data)974 static bool extract_if_dead(struct connectdata *conn,
975                             struct Curl_easy *data)
976 {
977   size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
978   if(!pipeLen && !CONN_INUSE(conn) && !conn->data) {
979     /* The check for a dead socket makes sense only if there are no
980        handles in pipeline and the connection isn't already marked in
981        use */
982     bool dead;
983     if(conn->handler->connection_check) {
984       /* The protocol has a special method for checking the state of the
985          connection. Use it to check if the connection is dead. */
986       unsigned int state;
987       struct Curl_easy *olddata = conn->data;
988       conn->data = data; /* use this transfer for now */
989       state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
990       conn->data = olddata;
991       dead = (state & CONNRESULT_DEAD);
992     }
993     else {
994       /* Use the general method for determining the death of a connection */
995       dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
996     }
997 
998     if(dead) {
999       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
1000       Curl_conncache_remove_conn(data, conn, FALSE);
1001       return TRUE;
1002     }
1003   }
1004   return FALSE;
1005 }
1006 
1007 struct prunedead {
1008   struct Curl_easy *data;
1009   struct connectdata *extracted;
1010 };
1011 
1012 /*
1013  * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
1014  *
1015  */
call_extract_if_dead(struct connectdata * conn,void * param)1016 static int call_extract_if_dead(struct connectdata *conn, void *param)
1017 {
1018   struct prunedead *p = (struct prunedead *)param;
1019   if(extract_if_dead(conn, p->data)) {
1020     /* stop the iteration here, pass back the connection that was extracted */
1021     p->extracted = conn;
1022     return 1;
1023   }
1024   return 0; /* continue iteration */
1025 }
1026 
1027 /*
1028  * This function scans the connection cache for half-open/dead connections,
1029  * closes and removes them.
1030  * The cleanup is done at most once per second.
1031  */
prune_dead_connections(struct Curl_easy * data)1032 static void prune_dead_connections(struct Curl_easy *data)
1033 {
1034   struct curltime now = Curl_now();
1035   time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup);
1036 
1037   if(elapsed >= 1000L) {
1038     struct prunedead prune;
1039     prune.data = data;
1040     prune.extracted = NULL;
1041     while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
1042                                  call_extract_if_dead)) {
1043       /* disconnect it */
1044       (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
1045     }
1046     data->state.conn_cache->last_cleanup = now;
1047   }
1048 }
1049 
1050 
max_pipeline_length(struct Curl_multi * multi)1051 static size_t max_pipeline_length(struct Curl_multi *multi)
1052 {
1053   return multi ? multi->max_pipeline_length : 0;
1054 }
1055 
1056 
1057 /*
1058  * Given one filled in connection struct (named needle), this function should
1059  * detect if there already is one that has all the significant details
1060  * exactly the same and thus should be used instead.
1061  *
1062  * If there is a match, this function returns TRUE - and has marked the
1063  * connection as 'in-use'. It must later be called with ConnectionDone() to
1064  * return back to 'idle' (unused) state.
1065  *
1066  * The force_reuse flag is set if the connection must be used, even if
1067  * the pipelining strategy wants to open a new connection instead of reusing.
1068  */
1069 static bool
ConnectionExists(struct Curl_easy * data,struct connectdata * needle,struct connectdata ** usethis,bool * force_reuse,bool * waitpipe)1070 ConnectionExists(struct Curl_easy *data,
1071                  struct connectdata *needle,
1072                  struct connectdata **usethis,
1073                  bool *force_reuse,
1074                  bool *waitpipe)
1075 {
1076   struct connectdata *check;
1077   struct connectdata *chosen = 0;
1078   bool foundPendingCandidate = FALSE;
1079   int canpipe = IsPipeliningPossible(data, needle);
1080   struct connectbundle *bundle;
1081 
1082 #ifdef USE_NTLM
1083   bool wantNTLMhttp = ((data->state.authhost.want &
1084                       (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1085                       (needle->handler->protocol & PROTO_FAMILY_HTTP));
1086   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
1087                            ((data->state.authproxy.want &
1088                            (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1089                            (needle->handler->protocol & PROTO_FAMILY_HTTP)));
1090 #endif
1091 
1092   *force_reuse = FALSE;
1093   *waitpipe = FALSE;
1094 
1095   /* We can't pipeline if the site is blacklisted */
1096   if((canpipe & CURLPIPE_HTTP1) &&
1097      Curl_pipeline_site_blacklisted(data, needle))
1098     canpipe &= ~ CURLPIPE_HTTP1;
1099 
1100   /* Look up the bundle with all the connections to this particular host.
1101      Locks the connection cache, beware of early returns! */
1102   bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
1103   if(bundle) {
1104     /* Max pipe length is zero (unlimited) for multiplexed connections */
1105     size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
1106       max_pipeline_length(data->multi):0;
1107     size_t best_pipe_len = max_pipe_len;
1108     struct curl_llist_element *curr;
1109 
1110     infof(data, "Found bundle for host %s: %p [%s]\n",
1111           (needle->bits.conn_to_host ? needle->conn_to_host.name :
1112            needle->host.name), (void *)bundle,
1113           (bundle->multiuse == BUNDLE_PIPELINING ?
1114            "can pipeline" :
1115            (bundle->multiuse == BUNDLE_MULTIPLEX ?
1116             "can multiplex" : "serially")));
1117 
1118     /* We can't pipeline if we don't know anything about the server */
1119     if(canpipe) {
1120       if(bundle->multiuse <= BUNDLE_UNKNOWN) {
1121         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
1122           infof(data, "Server doesn't support multi-use yet, wait\n");
1123           *waitpipe = TRUE;
1124           Curl_conncache_unlock(data);
1125           return FALSE; /* no re-use */
1126         }
1127 
1128         infof(data, "Server doesn't support multi-use (yet)\n");
1129         canpipe = 0;
1130       }
1131       if((bundle->multiuse == BUNDLE_PIPELINING) &&
1132          !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
1133         /* not asked for, switch off */
1134         infof(data, "Could pipeline, but not asked to!\n");
1135         canpipe = 0;
1136       }
1137       else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
1138               !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
1139         infof(data, "Could multiplex, but not asked to!\n");
1140         canpipe = 0;
1141       }
1142     }
1143 
1144     curr = bundle->conn_list.head;
1145     while(curr) {
1146       bool match = FALSE;
1147       size_t pipeLen;
1148 
1149       /*
1150        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
1151        * check connections to that proxy and not to the actual remote server.
1152        */
1153       check = curr->ptr;
1154       curr = curr->next;
1155 
1156       if(check->bits.connect_only)
1157         /* connect-only connections will not be reused */
1158         continue;
1159 
1160       if(extract_if_dead(check, data)) {
1161         /* disconnect it */
1162         (void)Curl_disconnect(data, check, /* dead_connection */TRUE);
1163         continue;
1164       }
1165 
1166       pipeLen = check->send_pipe.size + check->recv_pipe.size;
1167 
1168       if(canpipe) {
1169         if(check->bits.protoconnstart && check->bits.close)
1170           continue;
1171 
1172         if(!check->bits.multiplex) {
1173           /* If not multiplexing, make sure the connection is fine for HTTP/1
1174              pipelining */
1175           struct Curl_easy* sh = gethandleathead(&check->send_pipe);
1176           struct Curl_easy* rh = gethandleathead(&check->recv_pipe);
1177           if(sh) {
1178             if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1))
1179               continue;
1180           }
1181           else if(rh) {
1182             if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1))
1183               continue;
1184           }
1185         }
1186       }
1187       else {
1188         if(pipeLen > 0) {
1189           /* can only happen within multi handles, and means that another easy
1190              handle is using this connection */
1191           continue;
1192         }
1193 
1194         if(Curl_resolver_asynch()) {
1195           /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
1196              completed yet and until then we don't re-use this connection */
1197           if(!check->ip_addr_str[0]) {
1198             infof(data,
1199                   "Connection #%ld is still name resolving, can't reuse\n",
1200                   check->connection_id);
1201             continue;
1202           }
1203         }
1204 
1205         if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
1206            check->bits.close) {
1207           if(!check->bits.close)
1208             foundPendingCandidate = TRUE;
1209           /* Don't pick a connection that hasn't connected yet or that is going
1210              to get closed. */
1211           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
1212                 check->connection_id);
1213 #ifdef DEBUGBUILD
1214           if(check->recv_pipe.size > 0) {
1215             infof(data,
1216                   "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
1217                   check->connection_id);
1218           }
1219 #endif
1220           continue;
1221         }
1222       }
1223 
1224 #ifdef USE_UNIX_SOCKETS
1225       if(needle->unix_domain_socket) {
1226         if(!check->unix_domain_socket)
1227           continue;
1228         if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
1229           continue;
1230         if(needle->abstract_unix_socket != check->abstract_unix_socket)
1231           continue;
1232       }
1233       else if(check->unix_domain_socket)
1234         continue;
1235 #endif
1236 
1237       if((needle->handler->flags&PROTOPT_SSL) !=
1238          (check->handler->flags&PROTOPT_SSL))
1239         /* don't do mixed SSL and non-SSL connections */
1240         if(get_protocol_family(check->handler->protocol) !=
1241            needle->handler->protocol || !check->tls_upgraded)
1242           /* except protocols that have been upgraded via TLS */
1243           continue;
1244 
1245       if(needle->bits.httpproxy != check->bits.httpproxy ||
1246          needle->bits.socksproxy != check->bits.socksproxy)
1247         continue;
1248 
1249       if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
1250                                                         &check->socks_proxy))
1251         continue;
1252 
1253       if(needle->bits.conn_to_host != check->bits.conn_to_host)
1254         /* don't mix connections that use the "connect to host" feature and
1255          * connections that don't use this feature */
1256         continue;
1257 
1258       if(needle->bits.conn_to_port != check->bits.conn_to_port)
1259         /* don't mix connections that use the "connect to port" feature and
1260          * connections that don't use this feature */
1261         continue;
1262 
1263       if(needle->bits.httpproxy) {
1264         if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
1265           continue;
1266 
1267         if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
1268           continue;
1269 
1270         if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
1271           /* use https proxy */
1272           if(needle->handler->flags&PROTOPT_SSL) {
1273             /* use double layer ssl */
1274             if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
1275                                         &check->proxy_ssl_config))
1276               continue;
1277             if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
1278               continue;
1279           }
1280           else {
1281             if(!Curl_ssl_config_matches(&needle->ssl_config,
1282                                         &check->ssl_config))
1283               continue;
1284             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
1285               continue;
1286           }
1287         }
1288       }
1289 
1290       if(!canpipe && check->data)
1291         /* this request can't be pipelined but the checked connection is
1292            already in use so we skip it */
1293         continue;
1294 
1295       if(CONN_INUSE(check) && check->data &&
1296          (check->data->multi != needle->data->multi))
1297         /* this could be subject for pipeline/multiplex use, but only if they
1298            belong to the same multi handle */
1299         continue;
1300 
1301       if(needle->localdev || needle->localport) {
1302         /* If we are bound to a specific local end (IP+port), we must not
1303            re-use a random other one, although if we didn't ask for a
1304            particular one we can reuse one that was bound.
1305 
1306            This comparison is a bit rough and too strict. Since the input
1307            parameters can be specified in numerous ways and still end up the
1308            same it would take a lot of processing to make it really accurate.
1309            Instead, this matching will assume that re-uses of bound connections
1310            will most likely also re-use the exact same binding parameters and
1311            missing out a few edge cases shouldn't hurt anyone very much.
1312         */
1313         if((check->localport != needle->localport) ||
1314            (check->localportrange != needle->localportrange) ||
1315            (needle->localdev &&
1316             (!check->localdev || strcmp(check->localdev, needle->localdev))))
1317           continue;
1318       }
1319 
1320       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
1321         /* This protocol requires credentials per connection,
1322            so verify that we're using the same name and password as well */
1323         if(strcmp(needle->user, check->user) ||
1324            strcmp(needle->passwd, check->passwd)) {
1325           /* one of them was different */
1326           continue;
1327         }
1328       }
1329 
1330       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
1331          needle->bits.tunnel_proxy) {
1332         /* The requested connection does not use a HTTP proxy or it uses SSL or
1333            it is a non-SSL protocol tunneled or it is a non-SSL protocol which
1334            is allowed to be upgraded via TLS */
1335 
1336         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
1337             (get_protocol_family(check->handler->protocol) ==
1338              needle->handler->protocol && check->tls_upgraded)) &&
1339            (!needle->bits.conn_to_host || strcasecompare(
1340             needle->conn_to_host.name, check->conn_to_host.name)) &&
1341            (!needle->bits.conn_to_port ||
1342              needle->conn_to_port == check->conn_to_port) &&
1343            strcasecompare(needle->host.name, check->host.name) &&
1344            needle->remote_port == check->remote_port) {
1345           /* The schemes match or the the protocol family is the same and the
1346              previous connection was TLS upgraded, and the hostname and host
1347              port match */
1348           if(needle->handler->flags & PROTOPT_SSL) {
1349             /* This is a SSL connection so verify that we're using the same
1350                SSL options as well */
1351             if(!Curl_ssl_config_matches(&needle->ssl_config,
1352                                         &check->ssl_config)) {
1353               DEBUGF(infof(data,
1354                            "Connection #%ld has different SSL parameters, "
1355                            "can't reuse\n",
1356                            check->connection_id));
1357               continue;
1358             }
1359             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
1360               foundPendingCandidate = TRUE;
1361               DEBUGF(infof(data,
1362                            "Connection #%ld has not started SSL connect, "
1363                            "can't reuse\n",
1364                            check->connection_id));
1365               continue;
1366             }
1367           }
1368           match = TRUE;
1369         }
1370       }
1371       else {
1372         /* The requested connection is using the same HTTP proxy in normal
1373            mode (no tunneling) */
1374         match = TRUE;
1375       }
1376 
1377       if(match) {
1378 #if defined(USE_NTLM)
1379         /* If we are looking for an HTTP+NTLM connection, check if this is
1380            already authenticating with the right credentials. If not, keep
1381            looking so that we can reuse NTLM connections if
1382            possible. (Especially we must not reuse the same connection if
1383            partway through a handshake!) */
1384         if(wantNTLMhttp) {
1385           if(strcmp(needle->user, check->user) ||
1386              strcmp(needle->passwd, check->passwd))
1387             continue;
1388         }
1389         else if(check->ntlm.state != NTLMSTATE_NONE) {
1390           /* Connection is using NTLM auth but we don't want NTLM */
1391           continue;
1392         }
1393 
1394         /* Same for Proxy NTLM authentication */
1395         if(wantProxyNTLMhttp) {
1396           /* Both check->http_proxy.user and check->http_proxy.passwd can be
1397            * NULL */
1398           if(!check->http_proxy.user || !check->http_proxy.passwd)
1399             continue;
1400 
1401           if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
1402              strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
1403             continue;
1404         }
1405         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
1406           /* Proxy connection is using NTLM auth but we don't want NTLM */
1407           continue;
1408         }
1409 
1410         if(wantNTLMhttp || wantProxyNTLMhttp) {
1411           /* Credentials are already checked, we can use this connection */
1412           chosen = check;
1413 
1414           if((wantNTLMhttp &&
1415              (check->ntlm.state != NTLMSTATE_NONE)) ||
1416               (wantProxyNTLMhttp &&
1417                (check->proxyntlm.state != NTLMSTATE_NONE))) {
1418             /* We must use this connection, no other */
1419             *force_reuse = TRUE;
1420             break;
1421           }
1422 
1423           /* Continue look up for a better connection */
1424           continue;
1425         }
1426 #endif
1427         if(canpipe) {
1428           /* We can pipeline if we want to. Let's continue looking for
1429              the optimal connection to use, i.e the shortest pipe that is not
1430              blacklisted. */
1431 
1432           if(pipeLen == 0) {
1433             /* We have the optimal connection. Let's stop looking. */
1434             chosen = check;
1435             break;
1436           }
1437 
1438           /* We can't use the connection if the pipe is full */
1439           if(max_pipe_len && (pipeLen >= max_pipe_len)) {
1440             infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
1441             continue;
1442           }
1443 #ifdef USE_NGHTTP2
1444           /* If multiplexed, make sure we don't go over concurrency limit */
1445           if(check->bits.multiplex) {
1446             /* Multiplexed connections can only be HTTP/2 for now */
1447             struct http_conn *httpc = &check->proto.httpc;
1448             if(pipeLen >= httpc->settings.max_concurrent_streams) {
1449               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
1450                     pipeLen);
1451               continue;
1452             }
1453           }
1454 #endif
1455           /* We can't use the connection if the pipe is penalized */
1456           if(Curl_pipeline_penalized(data, check)) {
1457             infof(data, "Penalized, skip\n");
1458             continue;
1459           }
1460 
1461           if(max_pipe_len) {
1462             if(pipeLen < best_pipe_len) {
1463               /* This connection has a shorter pipe so far. We'll pick this
1464                  and continue searching */
1465               chosen = check;
1466               best_pipe_len = pipeLen;
1467               continue;
1468             }
1469           }
1470           else {
1471             /* When not pipelining (== multiplexed), we have a match here! */
1472             chosen = check;
1473             infof(data, "Multiplexed connection found!\n");
1474             break;
1475           }
1476         }
1477         else {
1478           /* We have found a connection. Let's stop searching. */
1479           chosen = check;
1480           break;
1481         }
1482       }
1483     }
1484   }
1485 
1486   if(chosen) {
1487     /* mark it as used before releasing the lock */
1488     chosen->data = data; /* own it! */
1489     Curl_conncache_unlock(data);
1490     *usethis = chosen;
1491     return TRUE; /* yes, we found one to use! */
1492   }
1493   Curl_conncache_unlock(data);
1494 
1495   if(foundPendingCandidate && data->set.pipewait) {
1496     infof(data,
1497           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
1498     *waitpipe = TRUE;
1499   }
1500 
1501   return FALSE; /* no matching connecting exists */
1502 }
1503 
1504 /* after a TCP connection to the proxy has been verified, this function does
1505    the next magic step.
1506 
1507    Note: this function's sub-functions call failf()
1508 
1509 */
Curl_connected_proxy(struct connectdata * conn,int sockindex)1510 CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
1511 {
1512   CURLcode result = CURLE_OK;
1513 
1514   if(conn->bits.socksproxy) {
1515 #ifndef CURL_DISABLE_PROXY
1516     /* for the secondary socket (FTP), use the "connect to host"
1517      * but ignore the "connect to port" (use the secondary port)
1518      */
1519     const char * const host = conn->bits.httpproxy ?
1520                               conn->http_proxy.host.name :
1521                               conn->bits.conn_to_host ?
1522                               conn->conn_to_host.name :
1523                               sockindex == SECONDARYSOCKET ?
1524                               conn->secondaryhostname : conn->host.name;
1525     const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port :
1526                      sockindex == SECONDARYSOCKET ? conn->secondary_port :
1527                      conn->bits.conn_to_port ? conn->conn_to_port :
1528                      conn->remote_port;
1529     conn->bits.socksproxy_connecting = TRUE;
1530     switch(conn->socks_proxy.proxytype) {
1531     case CURLPROXY_SOCKS5:
1532     case CURLPROXY_SOCKS5_HOSTNAME:
1533       result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
1534                          host, port, sockindex, conn);
1535       break;
1536 
1537     case CURLPROXY_SOCKS4:
1538     case CURLPROXY_SOCKS4A:
1539       result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
1540                            conn);
1541       break;
1542 
1543     default:
1544       failf(conn->data, "unknown proxytype option given");
1545       result = CURLE_COULDNT_CONNECT;
1546     } /* switch proxytype */
1547     conn->bits.socksproxy_connecting = FALSE;
1548 #else
1549   (void)sockindex;
1550 #endif /* CURL_DISABLE_PROXY */
1551   }
1552 
1553   return result;
1554 }
1555 
1556 /*
1557  * verboseconnect() displays verbose information after a connect
1558  */
1559 #ifndef CURL_DISABLE_VERBOSE_STRINGS
Curl_verboseconnect(struct connectdata * conn)1560 void Curl_verboseconnect(struct connectdata *conn)
1561 {
1562   if(conn->data->set.verbose)
1563     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
1564           conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
1565           conn->bits.httpproxy ? conn->http_proxy.host.dispname :
1566           conn->bits.conn_to_host ? conn->conn_to_host.dispname :
1567           conn->host.dispname,
1568           conn->ip_addr_str, conn->port, conn->connection_id);
1569 }
1570 #endif
1571 
Curl_protocol_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)1572 int Curl_protocol_getsock(struct connectdata *conn,
1573                           curl_socket_t *socks,
1574                           int numsocks)
1575 {
1576   if(conn->handler->proto_getsock)
1577     return conn->handler->proto_getsock(conn, socks, numsocks);
1578   /* Backup getsock logic. Since there is a live socket in use, we must wait
1579      for it or it will be removed from watching when the multi_socket API is
1580      used. */
1581   socks[0] = conn->sock[FIRSTSOCKET];
1582   return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
1583 }
1584 
Curl_doing_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)1585 int Curl_doing_getsock(struct connectdata *conn,
1586                        curl_socket_t *socks,
1587                        int numsocks)
1588 {
1589   if(conn && conn->handler->doing_getsock)
1590     return conn->handler->doing_getsock(conn, socks, numsocks);
1591   return GETSOCK_BLANK;
1592 }
1593 
1594 /*
1595  * We are doing protocol-specific connecting and this is being called over and
1596  * over from the multi interface until the connection phase is done on
1597  * protocol layer.
1598  */
1599 
Curl_protocol_connecting(struct connectdata * conn,bool * done)1600 CURLcode Curl_protocol_connecting(struct connectdata *conn,
1601                                   bool *done)
1602 {
1603   CURLcode result = CURLE_OK;
1604 
1605   if(conn && conn->handler->connecting) {
1606     *done = FALSE;
1607     result = conn->handler->connecting(conn, done);
1608   }
1609   else
1610     *done = TRUE;
1611 
1612   return result;
1613 }
1614 
1615 /*
1616  * We are DOING this is being called over and over from the multi interface
1617  * until the DOING phase is done on protocol layer.
1618  */
1619 
Curl_protocol_doing(struct connectdata * conn,bool * done)1620 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
1621 {
1622   CURLcode result = CURLE_OK;
1623 
1624   if(conn && conn->handler->doing) {
1625     *done = FALSE;
1626     result = conn->handler->doing(conn, done);
1627   }
1628   else
1629     *done = TRUE;
1630 
1631   return result;
1632 }
1633 
1634 /*
1635  * We have discovered that the TCP connection has been successful, we can now
1636  * proceed with some action.
1637  *
1638  */
Curl_protocol_connect(struct connectdata * conn,bool * protocol_done)1639 CURLcode Curl_protocol_connect(struct connectdata *conn,
1640                                bool *protocol_done)
1641 {
1642   CURLcode result = CURLE_OK;
1643 
1644   *protocol_done = FALSE;
1645 
1646   if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
1647     /* We already are connected, get back. This may happen when the connect
1648        worked fine in the first call, like when we connect to a local server
1649        or proxy. Note that we don't know if the protocol is actually done.
1650 
1651        Unless this protocol doesn't have any protocol-connect callback, as
1652        then we know we're done. */
1653     if(!conn->handler->connecting)
1654       *protocol_done = TRUE;
1655 
1656     return CURLE_OK;
1657   }
1658 
1659   if(!conn->bits.protoconnstart) {
1660 
1661     result = Curl_proxy_connect(conn, FIRSTSOCKET);
1662     if(result)
1663       return result;
1664 
1665     if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1666       /* wait for HTTPS proxy SSL initialization to complete */
1667       return CURLE_OK;
1668 
1669     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
1670        Curl_connect_ongoing(conn))
1671       /* when using an HTTP tunnel proxy, await complete tunnel establishment
1672          before proceeding further. Return CURLE_OK so we'll be called again */
1673       return CURLE_OK;
1674 
1675     if(conn->handler->connect_it) {
1676       /* is there a protocol-specific connect() procedure? */
1677 
1678       /* Call the protocol-specific connect function */
1679       result = conn->handler->connect_it(conn, protocol_done);
1680     }
1681     else
1682       *protocol_done = TRUE;
1683 
1684     /* it has started, possibly even completed but that knowledge isn't stored
1685        in this bit! */
1686     if(!result)
1687       conn->bits.protoconnstart = TRUE;
1688   }
1689 
1690   return result; /* pass back status */
1691 }
1692 
1693 /*
1694  * Helpers for IDNA conversions.
1695  */
is_ASCII_name(const char * hostname)1696 static bool is_ASCII_name(const char *hostname)
1697 {
1698   const unsigned char *ch = (const unsigned char *)hostname;
1699 
1700   while(*ch) {
1701     if(*ch++ & 0x80)
1702       return FALSE;
1703   }
1704   return TRUE;
1705 }
1706 
1707 /*
1708  * Strip single trailing dot in the hostname,
1709  * primarily for SNI and http host header.
1710  */
strip_trailing_dot(struct hostname * host)1711 static void strip_trailing_dot(struct hostname *host)
1712 {
1713   size_t len;
1714   if(!host || !host->name)
1715     return;
1716   len = strlen(host->name);
1717   if(len && (host->name[len-1] == '.'))
1718     host->name[len-1] = 0;
1719 }
1720 
1721 /*
1722  * Perform any necessary IDN conversion of hostname
1723  */
idnconvert_hostname(struct connectdata * conn,struct hostname * host)1724 static CURLcode idnconvert_hostname(struct connectdata *conn,
1725                                     struct hostname *host)
1726 {
1727   struct Curl_easy *data = conn->data;
1728 
1729 #ifndef USE_LIBIDN2
1730   (void)data;
1731   (void)conn;
1732 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
1733   (void)conn;
1734 #endif
1735 
1736   /* set the name we use to display the host name */
1737   host->dispname = host->name;
1738 
1739   /* Check name for non-ASCII and convert hostname to ACE form if we can */
1740   if(!is_ASCII_name(host->name)) {
1741 #ifdef USE_LIBIDN2
1742     if(idn2_check_version(IDN2_VERSION)) {
1743       char *ace_hostname = NULL;
1744 #if IDN2_VERSION_NUMBER >= 0x00140000
1745       /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
1746          IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
1747          processing. */
1748       int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
1749 #else
1750       int flags = IDN2_NFC_INPUT;
1751 #endif
1752       int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
1753       if(rc == IDN2_OK) {
1754         host->encalloc = (char *)ace_hostname;
1755         /* change the name pointer to point to the encoded hostname */
1756         host->name = host->encalloc;
1757       }
1758       else {
1759         failf(data, "Failed to convert %s to ACE; %s\n", host->name,
1760               idn2_strerror(rc));
1761         return CURLE_URL_MALFORMAT;
1762       }
1763     }
1764 #elif defined(USE_WIN32_IDN)
1765     char *ace_hostname = NULL;
1766 
1767     if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
1768       host->encalloc = ace_hostname;
1769       /* change the name pointer to point to the encoded hostname */
1770       host->name = host->encalloc;
1771     }
1772     else {
1773       failf(data, "Failed to convert %s to ACE;\n", host->name);
1774       return CURLE_URL_MALFORMAT;
1775     }
1776 #else
1777     infof(data, "IDN support not present, can't parse Unicode domains\n");
1778 #endif
1779   }
1780   return CURLE_OK;
1781 }
1782 
1783 /*
1784  * Frees data allocated by idnconvert_hostname()
1785  */
free_idnconverted_hostname(struct hostname * host)1786 static void free_idnconverted_hostname(struct hostname *host)
1787 {
1788 #if defined(USE_LIBIDN2)
1789   if(host->encalloc) {
1790     idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
1791                                  allocated by libidn */
1792     host->encalloc = NULL;
1793   }
1794 #elif defined(USE_WIN32_IDN)
1795   free(host->encalloc); /* must be freed with free() since this was
1796                            allocated by curl_win32_idn_to_ascii */
1797   host->encalloc = NULL;
1798 #else
1799   (void)host;
1800 #endif
1801 }
1802 
llist_dtor(void * user,void * element)1803 static void llist_dtor(void *user, void *element)
1804 {
1805   (void)user;
1806   (void)element;
1807   /* Do nothing */
1808 }
1809 
1810 /*
1811  * Allocate and initialize a new connectdata object.
1812  */
allocate_conn(struct Curl_easy * data)1813 static struct connectdata *allocate_conn(struct Curl_easy *data)
1814 {
1815   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
1816   if(!conn)
1817     return NULL;
1818 
1819 #ifdef USE_SSL
1820   /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
1821      a separate array to ensure suitable alignment.
1822      Note that these backend pointers can be swapped by vtls (eg ssl backend
1823      data becomes proxy backend data). */
1824   {
1825     size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
1826     char *ssl = calloc(4, sslsize);
1827     if(!ssl) {
1828       free(conn);
1829       return NULL;
1830     }
1831     conn->ssl_extra = ssl;
1832     conn->ssl[0].backend = (void *)ssl;
1833     conn->ssl[1].backend = (void *)(ssl + sslsize);
1834     conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
1835     conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
1836   }
1837 #endif
1838 
1839   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
1840                                            already from start to avoid NULL
1841                                            situations and checks */
1842 
1843   /* and we setup a few fields in case we end up actually using this struct */
1844 
1845   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
1846   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1847   conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
1848   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
1849   conn->connection_id = -1;    /* no ID */
1850   conn->port = -1; /* unknown at this point */
1851   conn->remote_port = -1; /* unknown at this point */
1852 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
1853   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1854   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1855 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
1856 
1857   /* Default protocol-independent behavior doesn't support persistent
1858      connections, so we set this to force-close. Protocols that support
1859      this need to set this to FALSE in their "curl_do" functions. */
1860   connclose(conn, "Default to force-close");
1861 
1862   /* Store creation time to help future close decision making */
1863   conn->created = Curl_now();
1864 
1865   /* Store current time to give a baseline to keepalive connection times. */
1866   conn->keepalive = Curl_now();
1867 
1868   /* Store off the configured connection upkeep time. */
1869   conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
1870 
1871   conn->data = data; /* Setup the association between this connection
1872                         and the Curl_easy */
1873 
1874   conn->http_proxy.proxytype = data->set.proxytype;
1875   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
1876 
1877 #ifdef CURL_DISABLE_PROXY
1878 
1879   conn->bits.proxy = FALSE;
1880   conn->bits.httpproxy = FALSE;
1881   conn->bits.socksproxy = FALSE;
1882   conn->bits.proxy_user_passwd = FALSE;
1883   conn->bits.tunnel_proxy = FALSE;
1884 
1885 #else /* CURL_DISABLE_PROXY */
1886 
1887   /* note that these two proxy bits are now just on what looks to be
1888      requested, they may be altered down the road */
1889   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
1890                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
1891   conn->bits.httpproxy = (conn->bits.proxy &&
1892                           (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
1893                            conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
1894                            conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
1895                            TRUE : FALSE;
1896   conn->bits.socksproxy = (conn->bits.proxy &&
1897                            !conn->bits.httpproxy) ? TRUE : FALSE;
1898 
1899   if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
1900     conn->bits.proxy = TRUE;
1901     conn->bits.socksproxy = TRUE;
1902   }
1903 
1904   conn->bits.proxy_user_passwd =
1905     (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
1906   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
1907 
1908 #endif /* CURL_DISABLE_PROXY */
1909 
1910   conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
1911   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
1912   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
1913 
1914   conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
1915   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
1916   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
1917   conn->proxy_ssl_config.verifystatus =
1918     data->set.proxy_ssl.primary.verifystatus;
1919   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
1920   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
1921   conn->ip_version = data->set.ipver;
1922   conn->bits.connect_only = data->set.connect_only;
1923 
1924 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
1925     defined(NTLM_WB_ENABLED)
1926   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1927   conn->ntlm_auth_hlpr_pid = 0;
1928   conn->challenge_header = NULL;
1929   conn->response_header = NULL;
1930 #endif
1931 
1932   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
1933      !conn->master_buffer) {
1934     /* Allocate master_buffer to be used for HTTP/1 pipelining */
1935     conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char));
1936     if(!conn->master_buffer)
1937       goto error;
1938   }
1939 
1940   /* Initialize the pipeline lists */
1941   Curl_llist_init(&conn->send_pipe, (curl_llist_dtor) llist_dtor);
1942   Curl_llist_init(&conn->recv_pipe, (curl_llist_dtor) llist_dtor);
1943 
1944 #ifdef HAVE_GSSAPI
1945   conn->data_prot = PROT_CLEAR;
1946 #endif
1947 
1948   /* Store the local bind parameters that will be used for this connection */
1949   if(data->set.str[STRING_DEVICE]) {
1950     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
1951     if(!conn->localdev)
1952       goto error;
1953   }
1954   conn->localportrange = data->set.localportrange;
1955   conn->localport = data->set.localport;
1956 
1957   /* the close socket stuff needs to be copied to the connection struct as
1958      it may live on without (this specific) Curl_easy */
1959   conn->fclosesocket = data->set.fclosesocket;
1960   conn->closesocket_client = data->set.closesocket_client;
1961 
1962   return conn;
1963   error:
1964 
1965   Curl_llist_destroy(&conn->send_pipe, NULL);
1966   Curl_llist_destroy(&conn->recv_pipe, NULL);
1967 
1968   free(conn->master_buffer);
1969   free(conn->localdev);
1970 #ifdef USE_SSL
1971   free(conn->ssl_extra);
1972 #endif
1973   free(conn);
1974   return NULL;
1975 }
1976 
1977 /* returns the handler if the given scheme is built-in */
Curl_builtin_scheme(const char * scheme)1978 const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
1979 {
1980   const struct Curl_handler * const *pp;
1981   const struct Curl_handler *p;
1982   /* Scan protocol handler table and match against 'scheme'. The handler may
1983      be changed later when the protocol specific setup function is called. */
1984   for(pp = protocols; (p = *pp) != NULL; pp++)
1985     if(strcasecompare(p->scheme, scheme))
1986       /* Protocol found in table. Check if allowed */
1987       return p;
1988   return NULL; /* not found */
1989 }
1990 
1991 
findprotocol(struct Curl_easy * data,struct connectdata * conn,const char * protostr)1992 static CURLcode findprotocol(struct Curl_easy *data,
1993                              struct connectdata *conn,
1994                              const char *protostr)
1995 {
1996   const struct Curl_handler *p = Curl_builtin_scheme(protostr);
1997 
1998   if(p && /* Protocol found in table. Check if allowed */
1999      (data->set.allowed_protocols & p->protocol)) {
2000 
2001     /* it is allowed for "normal" request, now do an extra check if this is
2002        the result of a redirect */
2003     if(data->state.this_is_a_follow &&
2004        !(data->set.redir_protocols & p->protocol))
2005       /* nope, get out */
2006       ;
2007     else {
2008       /* Perform setup complement if some. */
2009       conn->handler = conn->given = p;
2010 
2011       /* 'port' and 'remote_port' are set in setup_connection_internals() */
2012       return CURLE_OK;
2013     }
2014   }
2015 
2016   /* The protocol was not found in the table, but we don't have to assign it
2017      to anything since it is already assigned to a dummy-struct in the
2018      create_conn() function when the connectdata struct is allocated. */
2019   failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
2020         protostr);
2021 
2022   return CURLE_UNSUPPORTED_PROTOCOL;
2023 }
2024 
2025 
Curl_uc_to_curlcode(CURLUcode uc)2026 CURLcode Curl_uc_to_curlcode(CURLUcode uc)
2027 {
2028   switch(uc) {
2029   default:
2030     return CURLE_URL_MALFORMAT;
2031   case CURLUE_UNSUPPORTED_SCHEME:
2032     return CURLE_UNSUPPORTED_PROTOCOL;
2033   case CURLUE_OUT_OF_MEMORY:
2034     return CURLE_OUT_OF_MEMORY;
2035   case CURLUE_USER_NOT_ALLOWED:
2036     return CURLE_LOGIN_DENIED;
2037   }
2038 }
2039 
2040 /*
2041  * Parse URL and fill in the relevant members of the connection struct.
2042  */
parseurlandfillconn(struct Curl_easy * data,struct connectdata * conn)2043 static CURLcode parseurlandfillconn(struct Curl_easy *data,
2044                                     struct connectdata *conn)
2045 {
2046   CURLcode result;
2047   CURLU *uh;
2048   CURLUcode uc;
2049   char *hostname;
2050 
2051   up_free(data); /* cleanup previous leftovers first */
2052 
2053   /* parse the URL */
2054   if(data->set.uh) {
2055     uh = data->state.uh = data->set.uh;
2056   }
2057   else {
2058     uh = data->state.uh = curl_url();
2059   }
2060 
2061   if(!uh)
2062     return CURLE_OUT_OF_MEMORY;
2063 
2064   if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
2065      !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
2066     char *url;
2067     if(data->change.url_alloc)
2068       free(data->change.url);
2069     url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
2070                   data->change.url);
2071     if(!url)
2072       return CURLE_OUT_OF_MEMORY;
2073     data->change.url = url;
2074     data->change.url_alloc = TRUE;
2075   }
2076 
2077   if(!data->set.uh) {
2078     uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
2079                     CURLU_GUESS_SCHEME |
2080                     CURLU_NON_SUPPORT_SCHEME |
2081                     (data->set.disallow_username_in_url ?
2082                      CURLU_DISALLOW_USER : 0) |
2083                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
2084     if(uc) {
2085       DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
2086       return Curl_uc_to_curlcode(uc);
2087     }
2088   }
2089 
2090   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
2091   if(uc)
2092     return Curl_uc_to_curlcode(uc);
2093 
2094   result = findprotocol(data, conn, data->state.up.scheme);
2095   if(result)
2096     return result;
2097 
2098   uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
2099                     CURLU_URLDECODE);
2100   if(!uc) {
2101     conn->user = strdup(data->state.up.user);
2102     if(!conn->user)
2103       return CURLE_OUT_OF_MEMORY;
2104     conn->bits.user_passwd = TRUE;
2105   }
2106   else if(uc != CURLUE_NO_USER)
2107     return Curl_uc_to_curlcode(uc);
2108 
2109   uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
2110                     CURLU_URLDECODE);
2111   if(!uc) {
2112     conn->passwd = strdup(data->state.up.password);
2113     if(!conn->passwd)
2114       return CURLE_OUT_OF_MEMORY;
2115     conn->bits.user_passwd = TRUE;
2116   }
2117   else if(uc != CURLUE_NO_PASSWORD)
2118     return Curl_uc_to_curlcode(uc);
2119 
2120   uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
2121                     CURLU_URLDECODE);
2122   if(!uc) {
2123     conn->options = strdup(data->state.up.options);
2124     if(!conn->options)
2125       return CURLE_OUT_OF_MEMORY;
2126   }
2127   else if(uc != CURLUE_NO_OPTIONS)
2128     return Curl_uc_to_curlcode(uc);
2129 
2130   uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
2131   if(uc) {
2132     if(!strcasecompare("file", data->state.up.scheme))
2133       return CURLE_OUT_OF_MEMORY;
2134   }
2135 
2136   uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
2137   if(uc)
2138     return Curl_uc_to_curlcode(uc);
2139 
2140   uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
2141                     CURLU_DEFAULT_PORT);
2142   if(uc) {
2143     if(!strcasecompare("file", data->state.up.scheme))
2144       return CURLE_OUT_OF_MEMORY;
2145   }
2146   else {
2147     unsigned long port = strtoul(data->state.up.port, NULL, 10);
2148     conn->remote_port = curlx_ultous(port);
2149   }
2150 
2151   (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
2152 
2153   hostname = data->state.up.hostname;
2154   if(!hostname)
2155     /* this is for file:// transfers, get a dummy made */
2156     hostname = (char *)"";
2157 
2158   if(hostname[0] == '[') {
2159     /* This looks like an IPv6 address literal.  See if there is an address
2160        scope. */
2161     char *percent = strchr(++hostname, '%');
2162     conn->bits.ipv6_ip = TRUE;
2163     if(percent) {
2164       unsigned int identifier_offset = 3;
2165       char *endp;
2166       unsigned long scope;
2167       if(strncmp("%25", percent, 3) != 0) {
2168         infof(data,
2169               "Please URL encode %% as %%25, see RFC 6874.\n");
2170         identifier_offset = 1;
2171       }
2172       scope = strtoul(percent + identifier_offset, &endp, 10);
2173       if(*endp == ']') {
2174         /* The address scope was well formed.  Knock it out of the
2175            hostname. */
2176         memmove(percent, endp, strlen(endp) + 1);
2177         conn->scope_id = (unsigned int)scope;
2178       }
2179       else {
2180         /* Zone identifier is not numeric */
2181 #if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
2182         char ifname[IFNAMSIZ + 2];
2183         char *square_bracket;
2184         unsigned int scopeidx = 0;
2185         strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
2186         /* Ensure nullbyte termination */
2187         ifname[IFNAMSIZ + 1] = '\0';
2188         square_bracket = strchr(ifname, ']');
2189         if(square_bracket) {
2190           /* Remove ']' */
2191           *square_bracket = '\0';
2192           scopeidx = if_nametoindex(ifname);
2193           if(scopeidx == 0) {
2194             infof(data, "Invalid network interface: %s; %s\n", ifname,
2195                   strerror(errno));
2196           }
2197         }
2198         if(scopeidx > 0) {
2199           char *p = percent + identifier_offset + strlen(ifname);
2200 
2201           /* Remove zone identifier from hostname */
2202           memmove(percent, p, strlen(p) + 1);
2203           conn->scope_id = scopeidx;
2204         }
2205         else
2206 #endif /* HAVE_NET_IF_H && IFNAMSIZ */
2207           infof(data, "Invalid IPv6 address format\n");
2208       }
2209     }
2210     percent = strchr(hostname, ']');
2211     if(percent)
2212       /* terminate IPv6 numerical at end bracket */
2213       *percent = 0;
2214   }
2215 
2216   /* make sure the connect struct gets its own copy of the host name */
2217   conn->host.rawalloc = strdup(hostname);
2218   if(!conn->host.rawalloc)
2219     return CURLE_OUT_OF_MEMORY;
2220   conn->host.name = conn->host.rawalloc;
2221 
2222   if(data->set.scope_id)
2223     /* Override any scope that was set above.  */
2224     conn->scope_id = data->set.scope_id;
2225 
2226   return CURLE_OK;
2227 }
2228 
2229 
2230 /*
2231  * If we're doing a resumed transfer, we need to setup our stuff
2232  * properly.
2233  */
setup_range(struct Curl_easy * data)2234 static CURLcode setup_range(struct Curl_easy *data)
2235 {
2236   struct UrlState *s = &data->state;
2237   s->resume_from = data->set.set_resume_from;
2238   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
2239     if(s->rangestringalloc)
2240       free(s->range);
2241 
2242     if(s->resume_from)
2243       s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
2244     else
2245       s->range = strdup(data->set.str[STRING_SET_RANGE]);
2246 
2247     s->rangestringalloc = (s->range) ? TRUE : FALSE;
2248 
2249     if(!s->range)
2250       return CURLE_OUT_OF_MEMORY;
2251 
2252     /* tell ourselves to fetch this range */
2253     s->use_range = TRUE;        /* enable range download */
2254   }
2255   else
2256     s->use_range = FALSE; /* disable range download */
2257 
2258   return CURLE_OK;
2259 }
2260 
2261 
2262 /*
2263  * setup_connection_internals() -
2264  *
2265  * Setup connection internals specific to the requested protocol in the
2266  * Curl_easy. This is inited and setup before the connection is made but
2267  * is about the particular protocol that is to be used.
2268  *
2269  * This MUST get called after proxy magic has been figured out.
2270  */
setup_connection_internals(struct connectdata * conn)2271 static CURLcode setup_connection_internals(struct connectdata *conn)
2272 {
2273   const struct Curl_handler * p;
2274   CURLcode result;
2275   conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
2276 
2277   /* Perform setup complement if some. */
2278   p = conn->handler;
2279 
2280   if(p->setup_connection) {
2281     result = (*p->setup_connection)(conn);
2282 
2283     if(result)
2284       return result;
2285 
2286     p = conn->handler;              /* May have changed. */
2287   }
2288 
2289   if(conn->port < 0)
2290     /* we check for -1 here since if proxy was detected already, this
2291        was very likely already set to the proxy port */
2292     conn->port = p->defport;
2293 
2294   return CURLE_OK;
2295 }
2296 
2297 /*
2298  * Curl_free_request_state() should free temp data that was allocated in the
2299  * Curl_easy for this single request.
2300  */
2301 
Curl_free_request_state(struct Curl_easy * data)2302 void Curl_free_request_state(struct Curl_easy *data)
2303 {
2304   Curl_safefree(data->req.protop);
2305   Curl_safefree(data->req.newurl);
2306 }
2307 
2308 
2309 #ifndef CURL_DISABLE_PROXY
2310 /****************************************************************
2311 * Checks if the host is in the noproxy list. returns true if it matches
2312 * and therefore the proxy should NOT be used.
2313 ****************************************************************/
check_noproxy(const char * name,const char * no_proxy)2314 static bool check_noproxy(const char *name, const char *no_proxy)
2315 {
2316   /* no_proxy=domain1.dom,host.domain2.dom
2317    *   (a comma-separated list of hosts which should
2318    *   not be proxied, or an asterisk to override
2319    *   all proxy variables)
2320    */
2321   if(no_proxy && no_proxy[0]) {
2322     size_t tok_start;
2323     size_t tok_end;
2324     const char *separator = ", ";
2325     size_t no_proxy_len;
2326     size_t namelen;
2327     char *endptr;
2328     if(strcasecompare("*", no_proxy)) {
2329       return TRUE;
2330     }
2331 
2332     /* NO_PROXY was specified and it wasn't just an asterisk */
2333 
2334     no_proxy_len = strlen(no_proxy);
2335     if(name[0] == '[') {
2336       /* IPv6 numerical address */
2337       endptr = strchr(name, ']');
2338       if(!endptr)
2339         return FALSE;
2340       name++;
2341       namelen = endptr - name;
2342     }
2343     else
2344       namelen = strlen(name);
2345 
2346     for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
2347       while(tok_start < no_proxy_len &&
2348             strchr(separator, no_proxy[tok_start]) != NULL) {
2349         /* Look for the beginning of the token. */
2350         ++tok_start;
2351       }
2352 
2353       if(tok_start == no_proxy_len)
2354         break; /* It was all trailing separator chars, no more tokens. */
2355 
2356       for(tok_end = tok_start; tok_end < no_proxy_len &&
2357             strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
2358         /* Look for the end of the token. */
2359         ;
2360 
2361       /* To match previous behaviour, where it was necessary to specify
2362        * ".local.com" to prevent matching "notlocal.com", we will leave
2363        * the '.' off.
2364        */
2365       if(no_proxy[tok_start] == '.')
2366         ++tok_start;
2367 
2368       if((tok_end - tok_start) <= namelen) {
2369         /* Match the last part of the name to the domain we are checking. */
2370         const char *checkn = name + namelen - (tok_end - tok_start);
2371         if(strncasecompare(no_proxy + tok_start, checkn,
2372                            tok_end - tok_start)) {
2373           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
2374             /* We either have an exact match, or the previous character is a .
2375              * so it is within the same domain, so no proxy for this host.
2376              */
2377             return TRUE;
2378           }
2379         }
2380       } /* if((tok_end - tok_start) <= namelen) */
2381     } /* for(tok_start = 0; tok_start < no_proxy_len;
2382          tok_start = tok_end + 1) */
2383   } /* NO_PROXY was specified and it wasn't just an asterisk */
2384 
2385   return FALSE;
2386 }
2387 
2388 #ifndef CURL_DISABLE_HTTP
2389 /****************************************************************
2390 * Detect what (if any) proxy to use. Remember that this selects a host
2391 * name and is not limited to HTTP proxies only.
2392 * The returned pointer must be freed by the caller (unless NULL)
2393 ****************************************************************/
detect_proxy(struct connectdata * conn)2394 static char *detect_proxy(struct connectdata *conn)
2395 {
2396   char *proxy = NULL;
2397 
2398   /* If proxy was not specified, we check for default proxy environment
2399    * variables, to enable i.e Lynx compliance:
2400    *
2401    * http_proxy=http://some.server.dom:port/
2402    * https_proxy=http://some.server.dom:port/
2403    * ftp_proxy=http://some.server.dom:port/
2404    * no_proxy=domain1.dom,host.domain2.dom
2405    *   (a comma-separated list of hosts which should
2406    *   not be proxied, or an asterisk to override
2407    *   all proxy variables)
2408    * all_proxy=http://some.server.dom:port/
2409    *   (seems to exist for the CERN www lib. Probably
2410    *   the first to check for.)
2411    *
2412    * For compatibility, the all-uppercase versions of these variables are
2413    * checked if the lowercase versions don't exist.
2414    */
2415   char proxy_env[128];
2416   const char *protop = conn->handler->scheme;
2417   char *envp = proxy_env;
2418   char *prox;
2419 
2420   /* Now, build <protocol>_proxy and check for such a one to use */
2421   while(*protop)
2422     *envp++ = (char)tolower((int)*protop++);
2423 
2424   /* append _proxy */
2425   strcpy(envp, "_proxy");
2426 
2427   /* read the protocol proxy: */
2428   prox = curl_getenv(proxy_env);
2429 
2430   /*
2431    * We don't try the uppercase version of HTTP_PROXY because of
2432    * security reasons:
2433    *
2434    * When curl is used in a webserver application
2435    * environment (cgi or php), this environment variable can
2436    * be controlled by the web server user by setting the
2437    * http header 'Proxy:' to some value.
2438    *
2439    * This can cause 'internal' http/ftp requests to be
2440    * arbitrarily redirected by any external attacker.
2441    */
2442   if(!prox && !strcasecompare("http_proxy", proxy_env)) {
2443     /* There was no lowercase variable, try the uppercase version: */
2444     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2445     prox = curl_getenv(proxy_env);
2446   }
2447 
2448   envp = proxy_env;
2449   if(prox) {
2450     proxy = prox; /* use this */
2451   }
2452   else {
2453     envp = (char *)"all_proxy";
2454     proxy = curl_getenv(envp); /* default proxy to use */
2455     if(!proxy) {
2456       envp = (char *)"ALL_PROXY";
2457       proxy = curl_getenv(envp);
2458     }
2459   }
2460   if(proxy)
2461     infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
2462 
2463   return proxy;
2464 }
2465 #endif /* CURL_DISABLE_HTTP */
2466 
2467 /*
2468  * If this is supposed to use a proxy, we need to figure out the proxy
2469  * host name, so that we can re-use an existing connection
2470  * that may exist registered to the same proxy host.
2471  */
parse_proxy(struct Curl_easy * data,struct connectdata * conn,char * proxy,curl_proxytype proxytype)2472 static CURLcode parse_proxy(struct Curl_easy *data,
2473                             struct connectdata *conn, char *proxy,
2474                             curl_proxytype proxytype)
2475 {
2476   char *prox_portno;
2477   char *endofprot;
2478 
2479   /* We use 'proxyptr' to point to the proxy name from now on... */
2480   char *proxyptr;
2481   char *portptr;
2482   char *atsign;
2483   long port = -1;
2484   char *proxyuser = NULL;
2485   char *proxypasswd = NULL;
2486   bool sockstype;
2487 
2488   /* We do the proxy host string parsing here. We want the host name and the
2489    * port name. Accept a protocol:// prefix
2490    */
2491 
2492   /* Parse the protocol part if present */
2493   endofprot = strstr(proxy, "://");
2494   if(endofprot) {
2495     proxyptr = endofprot + 3;
2496     if(checkprefix("https", proxy))
2497       proxytype = CURLPROXY_HTTPS;
2498     else if(checkprefix("socks5h", proxy))
2499       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2500     else if(checkprefix("socks5", proxy))
2501       proxytype = CURLPROXY_SOCKS5;
2502     else if(checkprefix("socks4a", proxy))
2503       proxytype = CURLPROXY_SOCKS4A;
2504     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
2505       proxytype = CURLPROXY_SOCKS4;
2506     else if(checkprefix("http:", proxy))
2507       ; /* leave it as HTTP or HTTP/1.0 */
2508     else {
2509       /* Any other xxx:// reject! */
2510       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2511       return CURLE_COULDNT_CONNECT;
2512     }
2513   }
2514   else
2515     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
2516 
2517 #ifdef USE_SSL
2518   if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
2519 #endif
2520     if(proxytype == CURLPROXY_HTTPS) {
2521       failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2522                   "HTTPS-proxy support.", proxy);
2523       return CURLE_NOT_BUILT_IN;
2524     }
2525 
2526   sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
2527               proxytype == CURLPROXY_SOCKS5 ||
2528               proxytype == CURLPROXY_SOCKS4A ||
2529               proxytype == CURLPROXY_SOCKS4;
2530 
2531   /* Is there a username and password given in this proxy url? */
2532   atsign = strchr(proxyptr, '@');
2533   if(atsign) {
2534     CURLcode result =
2535       Curl_parse_login_details(proxyptr, atsign - proxyptr,
2536                                &proxyuser, &proxypasswd, NULL);
2537     if(result)
2538       return result;
2539     proxyptr = atsign + 1;
2540   }
2541 
2542   /* start scanning for port number at this point */
2543   portptr = proxyptr;
2544 
2545   /* detect and extract RFC6874-style IPv6-addresses */
2546   if(*proxyptr == '[') {
2547     char *ptr = ++proxyptr; /* advance beyond the initial bracket */
2548     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
2549       ptr++;
2550     if(*ptr == '%') {
2551       /* There might be a zone identifier */
2552       if(strncmp("%25", ptr, 3))
2553         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
2554       ptr++;
2555       /* Allow unreserved characters as defined in RFC 3986 */
2556       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
2557                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
2558         ptr++;
2559     }
2560     if(*ptr == ']')
2561       /* yeps, it ended nicely with a bracket as well */
2562       *ptr++ = 0;
2563     else
2564       infof(data, "Invalid IPv6 address format\n");
2565     portptr = ptr;
2566     /* Note that if this didn't end with a bracket, we still advanced the
2567      * proxyptr first, but I can't see anything wrong with that as no host
2568      * name nor a numeric can legally start with a bracket.
2569      */
2570   }
2571 
2572   /* Get port number off proxy.server.com:1080 */
2573   prox_portno = strchr(portptr, ':');
2574   if(prox_portno) {
2575     char *endp = NULL;
2576 
2577     *prox_portno = 0x0; /* cut off number from host name */
2578     prox_portno ++;
2579     /* now set the local port number */
2580     port = strtol(prox_portno, &endp, 10);
2581     if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
2582        (port < 0) || (port > 65535)) {
2583       /* meant to detect for example invalid IPv6 numerical addresses without
2584          brackets: "2a00:fac0:a000::7:13". Accept a trailing slash only
2585          because we then allow "URL style" with the number followed by a
2586          slash, used in curl test cases already. Space is also an acceptable
2587          terminating symbol. */
2588       infof(data, "No valid port number in proxy string (%s)\n",
2589             prox_portno);
2590     }
2591     else
2592       conn->port = port;
2593   }
2594   else {
2595     if(proxyptr[0]=='/') {
2596       /* If the first character in the proxy string is a slash, fail
2597          immediately. The following code will otherwise clear the string which
2598          will lead to code running as if no proxy was set! */
2599       Curl_safefree(proxyuser);
2600       Curl_safefree(proxypasswd);
2601       return CURLE_COULDNT_RESOLVE_PROXY;
2602     }
2603 
2604     /* without a port number after the host name, some people seem to use
2605        a slash so we strip everything from the first slash */
2606     atsign = strchr(proxyptr, '/');
2607     if(atsign)
2608       *atsign = '\0'; /* cut off path part from host name */
2609 
2610     if(data->set.proxyport)
2611       /* None given in the proxy string, then get the default one if it is
2612          given */
2613       port = data->set.proxyport;
2614     else {
2615       if(proxytype == CURLPROXY_HTTPS)
2616         port = CURL_DEFAULT_HTTPS_PROXY_PORT;
2617       else
2618         port = CURL_DEFAULT_PROXY_PORT;
2619     }
2620   }
2621 
2622   if(*proxyptr) {
2623     struct proxy_info *proxyinfo =
2624       sockstype ? &conn->socks_proxy : &conn->http_proxy;
2625     proxyinfo->proxytype = proxytype;
2626 
2627     if(proxyuser) {
2628       /* found user and password, rip them out.  note that we are unescaping
2629          them, as there is otherwise no way to have a username or password
2630          with reserved characters like ':' in them. */
2631       Curl_safefree(proxyinfo->user);
2632       proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
2633       Curl_safefree(proxyuser);
2634 
2635       if(!proxyinfo->user) {
2636         Curl_safefree(proxypasswd);
2637         return CURLE_OUT_OF_MEMORY;
2638       }
2639 
2640       Curl_safefree(proxyinfo->passwd);
2641       if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
2642         proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
2643       else
2644         proxyinfo->passwd = strdup("");
2645       Curl_safefree(proxypasswd);
2646 
2647       if(!proxyinfo->passwd)
2648         return CURLE_OUT_OF_MEMORY;
2649 
2650       conn->bits.proxy_user_passwd = TRUE; /* enable it */
2651     }
2652 
2653     if(port >= 0) {
2654       proxyinfo->port = port;
2655       if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
2656         conn->port = port;
2657     }
2658 
2659     /* now, clone the cleaned proxy host name */
2660     Curl_safefree(proxyinfo->host.rawalloc);
2661     proxyinfo->host.rawalloc = strdup(proxyptr);
2662     proxyinfo->host.name = proxyinfo->host.rawalloc;
2663 
2664     if(!proxyinfo->host.rawalloc)
2665       return CURLE_OUT_OF_MEMORY;
2666   }
2667 
2668   Curl_safefree(proxyuser);
2669   Curl_safefree(proxypasswd);
2670 
2671   return CURLE_OK;
2672 }
2673 
2674 /*
2675  * Extract the user and password from the authentication string
2676  */
parse_proxy_auth(struct Curl_easy * data,struct connectdata * conn)2677 static CURLcode parse_proxy_auth(struct Curl_easy *data,
2678                                  struct connectdata *conn)
2679 {
2680   char proxyuser[MAX_CURL_USER_LENGTH]="";
2681   char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
2682   CURLcode result;
2683 
2684   if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
2685     strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
2686             MAX_CURL_USER_LENGTH);
2687     proxyuser[MAX_CURL_USER_LENGTH-1] = '\0';   /*To be on safe side*/
2688   }
2689   if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
2690     strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
2691             MAX_CURL_PASSWORD_LENGTH);
2692     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
2693   }
2694 
2695   result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
2696                           FALSE);
2697   if(!result)
2698     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
2699                             NULL, FALSE);
2700   return result;
2701 }
2702 
2703 /* create_conn helper to parse and init proxy values. to be called after unix
2704    socket init but before any proxy vars are evaluated. */
create_conn_helper_init_proxy(struct connectdata * conn)2705 static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
2706 {
2707   char *proxy = NULL;
2708   char *socksproxy = NULL;
2709   char *no_proxy = NULL;
2710   CURLcode result = CURLE_OK;
2711   struct Curl_easy *data = conn->data;
2712 
2713   /*************************************************************
2714    * Extract the user and password from the authentication string
2715    *************************************************************/
2716   if(conn->bits.proxy_user_passwd) {
2717     result = parse_proxy_auth(data, conn);
2718     if(result)
2719       goto out;
2720   }
2721 
2722   /*************************************************************
2723    * Detect what (if any) proxy to use
2724    *************************************************************/
2725   if(data->set.str[STRING_PROXY]) {
2726     proxy = strdup(data->set.str[STRING_PROXY]);
2727     /* if global proxy is set, this is it */
2728     if(NULL == proxy) {
2729       failf(data, "memory shortage");
2730       result = CURLE_OUT_OF_MEMORY;
2731       goto out;
2732     }
2733   }
2734 
2735   if(data->set.str[STRING_PRE_PROXY]) {
2736     socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2737     /* if global socks proxy is set, this is it */
2738     if(NULL == socksproxy) {
2739       failf(data, "memory shortage");
2740       result = CURLE_OUT_OF_MEMORY;
2741       goto out;
2742     }
2743   }
2744 
2745   if(!data->set.str[STRING_NOPROXY]) {
2746     const char *p = "no_proxy";
2747     no_proxy = curl_getenv(p);
2748     if(!no_proxy) {
2749       p = "NO_PROXY";
2750       no_proxy = curl_getenv(p);
2751     }
2752     if(no_proxy) {
2753       infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
2754     }
2755   }
2756 
2757   if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2758       data->set.str[STRING_NOPROXY] : no_proxy)) {
2759     Curl_safefree(proxy);
2760     Curl_safefree(socksproxy);
2761   }
2762 #ifndef CURL_DISABLE_HTTP
2763   else if(!proxy && !socksproxy)
2764     /* if the host is not in the noproxy list, detect proxy. */
2765     proxy = detect_proxy(conn);
2766 #endif /* CURL_DISABLE_HTTP */
2767 
2768   Curl_safefree(no_proxy);
2769 
2770 #ifdef USE_UNIX_SOCKETS
2771   /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2772   if(proxy && conn->unix_domain_socket) {
2773     free(proxy);
2774     proxy = NULL;
2775   }
2776 #endif
2777 
2778   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2779     free(proxy);  /* Don't bother with an empty proxy string or if the
2780                      protocol doesn't work with network */
2781     proxy = NULL;
2782   }
2783   if(socksproxy && (!*socksproxy ||
2784                     (conn->handler->flags & PROTOPT_NONETWORK))) {
2785     free(socksproxy);  /* Don't bother with an empty socks proxy string or if
2786                           the protocol doesn't work with network */
2787     socksproxy = NULL;
2788   }
2789 
2790   /***********************************************************************
2791    * If this is supposed to use a proxy, we need to figure out the proxy host
2792    * name, proxy type and port number, so that we can re-use an existing
2793    * connection that may exist registered to the same proxy host.
2794    ***********************************************************************/
2795   if(proxy || socksproxy) {
2796     if(proxy) {
2797       result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
2798       Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2799       if(result)
2800         goto out;
2801     }
2802 
2803     if(socksproxy) {
2804       result = parse_proxy(data, conn, socksproxy,
2805                            conn->socks_proxy.proxytype);
2806       /* parse_proxy copies the socks proxy string */
2807       Curl_safefree(socksproxy);
2808       if(result)
2809         goto out;
2810     }
2811 
2812     if(conn->http_proxy.host.rawalloc) {
2813 #ifdef CURL_DISABLE_HTTP
2814       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
2815       result = CURLE_UNSUPPORTED_PROTOCOL;
2816       goto out;
2817 #else
2818       /* force this connection's protocol to become HTTP if compatible */
2819       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2820         if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2821            !conn->bits.tunnel_proxy)
2822           conn->handler = &Curl_handler_http;
2823         else
2824           /* if not converting to HTTP over the proxy, enforce tunneling */
2825           conn->bits.tunnel_proxy = TRUE;
2826       }
2827       conn->bits.httpproxy = TRUE;
2828 #endif
2829     }
2830     else {
2831       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
2832       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2833     }
2834 
2835     if(conn->socks_proxy.host.rawalloc) {
2836       if(!conn->http_proxy.host.rawalloc) {
2837         /* once a socks proxy */
2838         if(!conn->socks_proxy.user) {
2839           conn->socks_proxy.user = conn->http_proxy.user;
2840           conn->http_proxy.user = NULL;
2841           Curl_safefree(conn->socks_proxy.passwd);
2842           conn->socks_proxy.passwd = conn->http_proxy.passwd;
2843           conn->http_proxy.passwd = NULL;
2844         }
2845       }
2846       conn->bits.socksproxy = TRUE;
2847     }
2848     else
2849       conn->bits.socksproxy = FALSE; /* not a socks proxy */
2850   }
2851   else {
2852     conn->bits.socksproxy = FALSE;
2853     conn->bits.httpproxy = FALSE;
2854   }
2855   conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2856 
2857   if(!conn->bits.proxy) {
2858     /* we aren't using the proxy after all... */
2859     conn->bits.proxy = FALSE;
2860     conn->bits.httpproxy = FALSE;
2861     conn->bits.socksproxy = FALSE;
2862     conn->bits.proxy_user_passwd = FALSE;
2863     conn->bits.tunnel_proxy = FALSE;
2864   }
2865 
2866 out:
2867 
2868   free(socksproxy);
2869   free(proxy);
2870   return result;
2871 }
2872 #endif /* CURL_DISABLE_PROXY */
2873 
2874 /*
2875  * Curl_parse_login_details()
2876  *
2877  * This is used to parse a login string for user name, password and options in
2878  * the following formats:
2879  *
2880  *   user
2881  *   user:password
2882  *   user:password;options
2883  *   user;options
2884  *   user;options:password
2885  *   :password
2886  *   :password;options
2887  *   ;options
2888  *   ;options:password
2889  *
2890  * Parameters:
2891  *
2892  * login    [in]     - The login string.
2893  * len      [in]     - The length of the login string.
2894  * userp    [in/out] - The address where a pointer to newly allocated memory
2895  *                     holding the user will be stored upon completion.
2896  * passwdp  [in/out] - The address where a pointer to newly allocated memory
2897  *                     holding the password will be stored upon completion.
2898  * optionsp [in/out] - The address where a pointer to newly allocated memory
2899  *                     holding the options will be stored upon completion.
2900  *
2901  * Returns CURLE_OK on success.
2902  */
Curl_parse_login_details(const char * login,const size_t len,char ** userp,char ** passwdp,char ** optionsp)2903 CURLcode Curl_parse_login_details(const char *login, const size_t len,
2904                                   char **userp, char **passwdp,
2905                                   char **optionsp)
2906 {
2907   CURLcode result = CURLE_OK;
2908   char *ubuf = NULL;
2909   char *pbuf = NULL;
2910   char *obuf = NULL;
2911   const char *psep = NULL;
2912   const char *osep = NULL;
2913   size_t ulen;
2914   size_t plen;
2915   size_t olen;
2916 
2917   /* Attempt to find the password separator */
2918   if(passwdp) {
2919     psep = strchr(login, ':');
2920 
2921     /* Within the constraint of the login string */
2922     if(psep >= login + len)
2923       psep = NULL;
2924   }
2925 
2926   /* Attempt to find the options separator */
2927   if(optionsp) {
2928     osep = strchr(login, ';');
2929 
2930     /* Within the constraint of the login string */
2931     if(osep >= login + len)
2932       osep = NULL;
2933   }
2934 
2935   /* Calculate the portion lengths */
2936   ulen = (psep ?
2937           (size_t)(osep && psep > osep ? osep - login : psep - login) :
2938           (osep ? (size_t)(osep - login) : len));
2939   plen = (psep ?
2940           (osep && osep > psep ? (size_t)(osep - psep) :
2941                                  (size_t)(login + len - psep)) - 1 : 0);
2942   olen = (osep ?
2943           (psep && psep > osep ? (size_t)(psep - osep) :
2944                                  (size_t)(login + len - osep)) - 1 : 0);
2945 
2946   /* Allocate the user portion buffer */
2947   if(userp && ulen) {
2948     ubuf = malloc(ulen + 1);
2949     if(!ubuf)
2950       result = CURLE_OUT_OF_MEMORY;
2951   }
2952 
2953   /* Allocate the password portion buffer */
2954   if(!result && passwdp && plen) {
2955     pbuf = malloc(plen + 1);
2956     if(!pbuf) {
2957       free(ubuf);
2958       result = CURLE_OUT_OF_MEMORY;
2959     }
2960   }
2961 
2962   /* Allocate the options portion buffer */
2963   if(!result && optionsp && olen) {
2964     obuf = malloc(olen + 1);
2965     if(!obuf) {
2966       free(pbuf);
2967       free(ubuf);
2968       result = CURLE_OUT_OF_MEMORY;
2969     }
2970   }
2971 
2972   if(!result) {
2973     /* Store the user portion if necessary */
2974     if(ubuf) {
2975       memcpy(ubuf, login, ulen);
2976       ubuf[ulen] = '\0';
2977       Curl_safefree(*userp);
2978       *userp = ubuf;
2979     }
2980 
2981     /* Store the password portion if necessary */
2982     if(pbuf) {
2983       memcpy(pbuf, psep + 1, plen);
2984       pbuf[plen] = '\0';
2985       Curl_safefree(*passwdp);
2986       *passwdp = pbuf;
2987     }
2988 
2989     /* Store the options portion if necessary */
2990     if(obuf) {
2991       memcpy(obuf, osep + 1, olen);
2992       obuf[olen] = '\0';
2993       Curl_safefree(*optionsp);
2994       *optionsp = obuf;
2995     }
2996   }
2997 
2998   return result;
2999 }
3000 
3001 /*************************************************************
3002  * Figure out the remote port number and fix it in the URL
3003  *
3004  * No matter if we use a proxy or not, we have to figure out the remote
3005  * port number of various reasons.
3006  *
3007  * The port number embedded in the URL is replaced, if necessary.
3008  *************************************************************/
parse_remote_port(struct Curl_easy * data,struct connectdata * conn)3009 static CURLcode parse_remote_port(struct Curl_easy *data,
3010                                   struct connectdata *conn)
3011 {
3012 
3013   if(data->set.use_port && data->state.allow_port) {
3014     /* if set, we use this instead of the port possibly given in the URL */
3015     char portbuf[16];
3016     CURLUcode uc;
3017     conn->remote_port = (unsigned short)data->set.use_port;
3018     msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
3019     uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
3020     if(uc)
3021       return CURLE_OUT_OF_MEMORY;
3022   }
3023 
3024   return CURLE_OK;
3025 }
3026 
3027 /*
3028  * Override the login details from the URL with that in the CURLOPT_USERPWD
3029  * option or a .netrc file, if applicable.
3030  */
override_login(struct Curl_easy * data,struct connectdata * conn,char ** userp,char ** passwdp,char ** optionsp)3031 static CURLcode override_login(struct Curl_easy *data,
3032                                struct connectdata *conn,
3033                                char **userp, char **passwdp, char **optionsp)
3034 {
3035   bool user_changed = FALSE;
3036   bool passwd_changed = FALSE;
3037   CURLUcode uc;
3038 
3039   if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
3040     /* ignore user+password in the URL */
3041     if(*userp) {
3042       Curl_safefree(*userp);
3043       user_changed = TRUE;
3044     }
3045     if(*passwdp) {
3046       Curl_safefree(*passwdp);
3047       passwd_changed = TRUE;
3048     }
3049     conn->bits.user_passwd = FALSE; /* disable user+password */
3050   }
3051 
3052   if(data->set.str[STRING_USERNAME]) {
3053     free(*userp);
3054     *userp = strdup(data->set.str[STRING_USERNAME]);
3055     if(!*userp)
3056       return CURLE_OUT_OF_MEMORY;
3057     conn->bits.user_passwd = TRUE; /* enable user+password */
3058     user_changed = TRUE;
3059   }
3060 
3061   if(data->set.str[STRING_PASSWORD]) {
3062     free(*passwdp);
3063     *passwdp = strdup(data->set.str[STRING_PASSWORD]);
3064     if(!*passwdp)
3065       return CURLE_OUT_OF_MEMORY;
3066     conn->bits.user_passwd = TRUE; /* enable user+password */
3067     passwd_changed = TRUE;
3068   }
3069 
3070   if(data->set.str[STRING_OPTIONS]) {
3071     free(*optionsp);
3072     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
3073     if(!*optionsp)
3074       return CURLE_OUT_OF_MEMORY;
3075   }
3076 
3077   conn->bits.netrc = FALSE;
3078   if(data->set.use_netrc != CURL_NETRC_IGNORED &&
3079       (!*userp || !**userp || !*passwdp || !**passwdp)) {
3080     bool netrc_user_changed = FALSE;
3081     bool netrc_passwd_changed = FALSE;
3082     int ret;
3083 
3084     ret = Curl_parsenetrc(conn->host.name,
3085                           userp, passwdp,
3086                           &netrc_user_changed, &netrc_passwd_changed,
3087                           data->set.str[STRING_NETRC_FILE]);
3088     if(ret > 0) {
3089       infof(data, "Couldn't find host %s in the "
3090             DOT_CHAR "netrc file; using defaults\n",
3091             conn->host.name);
3092     }
3093     else if(ret < 0) {
3094       return CURLE_OUT_OF_MEMORY;
3095     }
3096     else {
3097       /* set bits.netrc TRUE to remember that we got the name from a .netrc
3098          file, so that it is safe to use even if we followed a Location: to a
3099          different host or similar. */
3100       conn->bits.netrc = TRUE;
3101       conn->bits.user_passwd = TRUE; /* enable user+password */
3102 
3103       if(netrc_user_changed) {
3104         user_changed = TRUE;
3105       }
3106       if(netrc_passwd_changed) {
3107         passwd_changed = TRUE;
3108       }
3109     }
3110   }
3111 
3112   /* for updated strings, we update them in the URL */
3113   if(user_changed) {
3114     uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
3115     if(uc)
3116       return Curl_uc_to_curlcode(uc);
3117   }
3118   if(passwd_changed) {
3119     uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
3120     if(uc)
3121       return Curl_uc_to_curlcode(uc);
3122   }
3123   return CURLE_OK;
3124 }
3125 
3126 /*
3127  * Set the login details so they're available in the connection
3128  */
set_login(struct connectdata * conn)3129 static CURLcode set_login(struct connectdata *conn)
3130 {
3131   CURLcode result = CURLE_OK;
3132   const char *setuser = CURL_DEFAULT_USER;
3133   const char *setpasswd = CURL_DEFAULT_PASSWORD;
3134 
3135   /* If our protocol needs a password and we have none, use the defaults */
3136   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
3137     ;
3138   else {
3139     setuser = "";
3140     setpasswd = "";
3141   }
3142   /* Store the default user */
3143   if(!conn->user) {
3144     conn->user = strdup(setuser);
3145     if(!conn->user)
3146       return CURLE_OUT_OF_MEMORY;
3147   }
3148 
3149   /* Store the default password */
3150   if(!conn->passwd) {
3151     conn->passwd = strdup(setpasswd);
3152     if(!conn->passwd)
3153       result = CURLE_OUT_OF_MEMORY;
3154   }
3155 
3156   /* if there's a user without password, consider password blank */
3157   if(conn->user && !conn->passwd) {
3158     conn->passwd = strdup("");
3159     if(!conn->passwd)
3160       result = CURLE_OUT_OF_MEMORY;
3161   }
3162 
3163   return result;
3164 }
3165 
3166 /*
3167  * Parses a "host:port" string to connect to.
3168  * The hostname and the port may be empty; in this case, NULL is returned for
3169  * the hostname and -1 for the port.
3170  */
parse_connect_to_host_port(struct Curl_easy * data,const char * host,char ** hostname_result,int * port_result)3171 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
3172                                            const char *host,
3173                                            char **hostname_result,
3174                                            int *port_result)
3175 {
3176   char *host_dup;
3177   char *hostptr;
3178   char *host_portno;
3179   char *portptr;
3180   int port = -1;
3181 
3182 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
3183   (void) data;
3184 #endif
3185 
3186   *hostname_result = NULL;
3187   *port_result = -1;
3188 
3189   if(!host || !*host)
3190     return CURLE_OK;
3191 
3192   host_dup = strdup(host);
3193   if(!host_dup)
3194     return CURLE_OUT_OF_MEMORY;
3195 
3196   hostptr = host_dup;
3197 
3198   /* start scanning for port number at this point */
3199   portptr = hostptr;
3200 
3201   /* detect and extract RFC6874-style IPv6-addresses */
3202   if(*hostptr == '[') {
3203 #ifdef ENABLE_IPV6
3204     char *ptr = ++hostptr; /* advance beyond the initial bracket */
3205     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
3206       ptr++;
3207     if(*ptr == '%') {
3208       /* There might be a zone identifier */
3209       if(strncmp("%25", ptr, 3))
3210         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
3211       ptr++;
3212       /* Allow unreserved characters as defined in RFC 3986 */
3213       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
3214                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
3215         ptr++;
3216     }
3217     if(*ptr == ']')
3218       /* yeps, it ended nicely with a bracket as well */
3219       *ptr++ = '\0';
3220     else
3221       infof(data, "Invalid IPv6 address format\n");
3222     portptr = ptr;
3223     /* Note that if this didn't end with a bracket, we still advanced the
3224      * hostptr first, but I can't see anything wrong with that as no host
3225      * name nor a numeric can legally start with a bracket.
3226      */
3227 #else
3228     failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
3229     free(host_dup);
3230     return CURLE_NOT_BUILT_IN;
3231 #endif
3232   }
3233 
3234   /* Get port number off server.com:1080 */
3235   host_portno = strchr(portptr, ':');
3236   if(host_portno) {
3237     char *endp = NULL;
3238     *host_portno = '\0'; /* cut off number from host name */
3239     host_portno++;
3240     if(*host_portno) {
3241       long portparse = strtol(host_portno, &endp, 10);
3242       if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
3243         infof(data, "No valid port number in connect to host string (%s)\n",
3244               host_portno);
3245         hostptr = NULL;
3246         port = -1;
3247       }
3248       else
3249         port = (int)portparse; /* we know it will fit */
3250     }
3251   }
3252 
3253   /* now, clone the cleaned host name */
3254   if(hostptr) {
3255     *hostname_result = strdup(hostptr);
3256     if(!*hostname_result) {
3257       free(host_dup);
3258       return CURLE_OUT_OF_MEMORY;
3259     }
3260   }
3261 
3262   *port_result = port;
3263 
3264   free(host_dup);
3265   return CURLE_OK;
3266 }
3267 
3268 /*
3269  * Parses one "connect to" string in the form:
3270  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
3271  */
parse_connect_to_string(struct Curl_easy * data,struct connectdata * conn,const char * conn_to_host,char ** host_result,int * port_result)3272 static CURLcode parse_connect_to_string(struct Curl_easy *data,
3273                                         struct connectdata *conn,
3274                                         const char *conn_to_host,
3275                                         char **host_result,
3276                                         int *port_result)
3277 {
3278   CURLcode result = CURLE_OK;
3279   const char *ptr = conn_to_host;
3280   int host_match = FALSE;
3281   int port_match = FALSE;
3282 
3283   *host_result = NULL;
3284   *port_result = -1;
3285 
3286   if(*ptr == ':') {
3287     /* an empty hostname always matches */
3288     host_match = TRUE;
3289     ptr++;
3290   }
3291   else {
3292     /* check whether the URL's hostname matches */
3293     size_t hostname_to_match_len;
3294     char *hostname_to_match = aprintf("%s%s%s",
3295                                       conn->bits.ipv6_ip ? "[" : "",
3296                                       conn->host.name,
3297                                       conn->bits.ipv6_ip ? "]" : "");
3298     if(!hostname_to_match)
3299       return CURLE_OUT_OF_MEMORY;
3300     hostname_to_match_len = strlen(hostname_to_match);
3301     host_match = strncasecompare(ptr, hostname_to_match,
3302                                  hostname_to_match_len);
3303     free(hostname_to_match);
3304     ptr += hostname_to_match_len;
3305 
3306     host_match = host_match && *ptr == ':';
3307     ptr++;
3308   }
3309 
3310   if(host_match) {
3311     if(*ptr == ':') {
3312       /* an empty port always matches */
3313       port_match = TRUE;
3314       ptr++;
3315     }
3316     else {
3317       /* check whether the URL's port matches */
3318       char *ptr_next = strchr(ptr, ':');
3319       if(ptr_next) {
3320         char *endp = NULL;
3321         long port_to_match = strtol(ptr, &endp, 10);
3322         if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
3323           port_match = TRUE;
3324           ptr = ptr_next + 1;
3325         }
3326       }
3327     }
3328   }
3329 
3330   if(host_match && port_match) {
3331     /* parse the hostname and port to connect to */
3332     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
3333   }
3334 
3335   return result;
3336 }
3337 
3338 /*
3339  * Processes all strings in the "connect to" slist, and uses the "connect
3340  * to host" and "connect to port" of the first string that matches.
3341  */
parse_connect_to_slist(struct Curl_easy * data,struct connectdata * conn,struct curl_slist * conn_to_host)3342 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
3343                                        struct connectdata *conn,
3344                                        struct curl_slist *conn_to_host)
3345 {
3346   CURLcode result = CURLE_OK;
3347   char *host = NULL;
3348   int port = -1;
3349 
3350   while(conn_to_host && !host && port == -1) {
3351     result = parse_connect_to_string(data, conn, conn_to_host->data,
3352                                      &host, &port);
3353     if(result)
3354       return result;
3355 
3356     if(host && *host) {
3357       conn->conn_to_host.rawalloc = host;
3358       conn->conn_to_host.name = host;
3359       conn->bits.conn_to_host = TRUE;
3360 
3361       infof(data, "Connecting to hostname: %s\n", host);
3362     }
3363     else {
3364       /* no "connect to host" */
3365       conn->bits.conn_to_host = FALSE;
3366       Curl_safefree(host);
3367     }
3368 
3369     if(port >= 0) {
3370       conn->conn_to_port = port;
3371       conn->bits.conn_to_port = TRUE;
3372       infof(data, "Connecting to port: %d\n", port);
3373     }
3374     else {
3375       /* no "connect to port" */
3376       conn->bits.conn_to_port = FALSE;
3377       port = -1;
3378     }
3379 
3380     conn_to_host = conn_to_host->next;
3381   }
3382 
3383 #ifdef USE_ALTSVC
3384   if(data->asi && !host && (port == -1) &&
3385      (conn->handler->protocol == CURLPROTO_HTTPS)) {
3386     /* no connect_to match, try alt-svc! */
3387     const char *nhost;
3388     int nport;
3389     enum alpnid nalpnid;
3390     bool hit;
3391     host = conn->host.rawalloc;
3392     hit = Curl_altsvc_lookup(data->asi,
3393                              ALPN_h1, host, conn->remote_port, /* from */
3394                              &nalpnid, &nhost, &nport /* to */);
3395     if(hit) {
3396       char *hostd = strdup((char *)nhost);
3397       if(!hostd)
3398         return CURLE_OUT_OF_MEMORY;
3399       conn->conn_to_host.rawalloc = hostd;
3400       conn->conn_to_host.name = hostd;
3401       conn->bits.conn_to_host = TRUE;
3402       conn->conn_to_port = nport;
3403       conn->bits.conn_to_port = TRUE;
3404       infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
3405             Curl_alpnid2str(ALPN_h1), host, conn->remote_port,
3406             Curl_alpnid2str(nalpnid), hostd, nport);
3407     }
3408   }
3409 #endif
3410 
3411   return result;
3412 }
3413 
3414 /*************************************************************
3415  * Resolve the address of the server or proxy
3416  *************************************************************/
resolve_server(struct Curl_easy * data,struct connectdata * conn,bool * async)3417 static CURLcode resolve_server(struct Curl_easy *data,
3418                                struct connectdata *conn,
3419                                bool *async)
3420 {
3421   CURLcode result = CURLE_OK;
3422   timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3423 
3424   DEBUGASSERT(conn);
3425   DEBUGASSERT(data);
3426   /*************************************************************
3427    * Resolve the name of the server or proxy
3428    *************************************************************/
3429   if(conn->bits.reuse)
3430     /* We're reusing the connection - no need to resolve anything, and
3431        idnconvert_hostname() was called already in create_conn() for the re-use
3432        case. */
3433     *async = FALSE;
3434 
3435   else {
3436     /* this is a fresh connect */
3437     int rc;
3438     struct Curl_dns_entry *hostaddr;
3439 
3440 #ifdef USE_UNIX_SOCKETS
3441     if(conn->unix_domain_socket) {
3442       /* Unix domain sockets are local. The host gets ignored, just use the
3443        * specified domain socket address. Do not cache "DNS entries". There is
3444        * no DNS involved and we already have the filesystem path available */
3445       const char *path = conn->unix_domain_socket;
3446 
3447       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
3448       if(!hostaddr)
3449         result = CURLE_OUT_OF_MEMORY;
3450       else {
3451         bool longpath = FALSE;
3452         hostaddr->addr = Curl_unix2addr(path, &longpath,
3453                                         conn->abstract_unix_socket);
3454         if(hostaddr->addr)
3455           hostaddr->inuse++;
3456         else {
3457           /* Long paths are not supported for now */
3458           if(longpath) {
3459             failf(data, "Unix socket path too long: '%s'", path);
3460             result = CURLE_COULDNT_RESOLVE_HOST;
3461           }
3462           else
3463             result = CURLE_OUT_OF_MEMORY;
3464           free(hostaddr);
3465           hostaddr = NULL;
3466         }
3467       }
3468     }
3469     else
3470 #endif
3471     if(!conn->bits.proxy) {
3472       struct hostname *connhost;
3473       if(conn->bits.conn_to_host)
3474         connhost = &conn->conn_to_host;
3475       else
3476         connhost = &conn->host;
3477 
3478       /* If not connecting via a proxy, extract the port from the URL, if it is
3479        * there, thus overriding any defaults that might have been set above. */
3480       if(conn->bits.conn_to_port)
3481         conn->port = conn->conn_to_port;
3482       else
3483         conn->port = conn->remote_port;
3484 
3485       /* Resolve target host right on */
3486       conn->hostname_resolve = strdup(connhost->name);
3487       if(!conn->hostname_resolve)
3488         return CURLE_OUT_OF_MEMORY;
3489       rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3490                                &hostaddr, timeout_ms);
3491       if(rc == CURLRESOLV_PENDING)
3492         *async = TRUE;
3493 
3494       else if(rc == CURLRESOLV_TIMEDOUT)
3495         result = CURLE_OPERATION_TIMEDOUT;
3496 
3497       else if(!hostaddr) {
3498         failf(data, "Couldn't resolve host '%s'", connhost->dispname);
3499         result =  CURLE_COULDNT_RESOLVE_HOST;
3500         /* don't return yet, we need to clean up the timeout first */
3501       }
3502     }
3503     else {
3504       /* This is a proxy that hasn't been resolved yet. */
3505 
3506       struct hostname * const host = conn->bits.socksproxy ?
3507         &conn->socks_proxy.host : &conn->http_proxy.host;
3508 
3509       /* resolve proxy */
3510       conn->hostname_resolve = strdup(host->name);
3511       if(!conn->hostname_resolve)
3512         return CURLE_OUT_OF_MEMORY;
3513       rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3514                                &hostaddr, timeout_ms);
3515 
3516       if(rc == CURLRESOLV_PENDING)
3517         *async = TRUE;
3518 
3519       else if(rc == CURLRESOLV_TIMEDOUT)
3520         result = CURLE_OPERATION_TIMEDOUT;
3521 
3522       else if(!hostaddr) {
3523         failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3524         result = CURLE_COULDNT_RESOLVE_PROXY;
3525         /* don't return yet, we need to clean up the timeout first */
3526       }
3527     }
3528     DEBUGASSERT(conn->dns_entry == NULL);
3529     conn->dns_entry = hostaddr;
3530   }
3531 
3532   return result;
3533 }
3534 
3535 /*
3536  * Cleanup the connection just allocated before we can move along and use the
3537  * previously existing one.  All relevant data is copied over and old_conn is
3538  * ready for freeing once this function returns.
3539  */
reuse_conn(struct connectdata * old_conn,struct connectdata * conn)3540 static void reuse_conn(struct connectdata *old_conn,
3541                        struct connectdata *conn)
3542 {
3543   free_idnconverted_hostname(&old_conn->http_proxy.host);
3544   free_idnconverted_hostname(&old_conn->socks_proxy.host);
3545 
3546   free(old_conn->http_proxy.host.rawalloc);
3547   free(old_conn->socks_proxy.host.rawalloc);
3548 
3549   /* free the SSL config struct from this connection struct as this was
3550      allocated in vain and is targeted for destruction */
3551   Curl_free_primary_ssl_config(&old_conn->ssl_config);
3552   Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
3553 
3554   conn->data = old_conn->data;
3555 
3556   /* get the user+password information from the old_conn struct since it may
3557    * be new for this request even when we re-use an existing connection */
3558   conn->bits.user_passwd = old_conn->bits.user_passwd;
3559   if(conn->bits.user_passwd) {
3560     /* use the new user name and password though */
3561     Curl_safefree(conn->user);
3562     Curl_safefree(conn->passwd);
3563     conn->user = old_conn->user;
3564     conn->passwd = old_conn->passwd;
3565     old_conn->user = NULL;
3566     old_conn->passwd = NULL;
3567   }
3568 
3569   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
3570   if(conn->bits.proxy_user_passwd) {
3571     /* use the new proxy user name and proxy password though */
3572     Curl_safefree(conn->http_proxy.user);
3573     Curl_safefree(conn->socks_proxy.user);
3574     Curl_safefree(conn->http_proxy.passwd);
3575     Curl_safefree(conn->socks_proxy.passwd);
3576     conn->http_proxy.user = old_conn->http_proxy.user;
3577     conn->socks_proxy.user = old_conn->socks_proxy.user;
3578     conn->http_proxy.passwd = old_conn->http_proxy.passwd;
3579     conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
3580     old_conn->http_proxy.user = NULL;
3581     old_conn->socks_proxy.user = NULL;
3582     old_conn->http_proxy.passwd = NULL;
3583     old_conn->socks_proxy.passwd = NULL;
3584   }
3585 
3586   /* host can change, when doing keepalive with a proxy or if the case is
3587      different this time etc */
3588   free_idnconverted_hostname(&conn->host);
3589   free_idnconverted_hostname(&conn->conn_to_host);
3590   Curl_safefree(conn->host.rawalloc);
3591   Curl_safefree(conn->conn_to_host.rawalloc);
3592   conn->host = old_conn->host;
3593   conn->conn_to_host = old_conn->conn_to_host;
3594   conn->conn_to_port = old_conn->conn_to_port;
3595   conn->remote_port = old_conn->remote_port;
3596   Curl_safefree(conn->hostname_resolve);
3597 
3598   conn->hostname_resolve = old_conn->hostname_resolve;
3599   old_conn->hostname_resolve = NULL;
3600 
3601   /* persist connection info in session handle */
3602   Curl_persistconninfo(conn);
3603 
3604   conn_reset_all_postponed_data(old_conn); /* free buffers */
3605 
3606   /* re-use init */
3607   conn->bits.reuse = TRUE; /* yes, we're re-using here */
3608 
3609   Curl_safefree(old_conn->user);
3610   Curl_safefree(old_conn->passwd);
3611   Curl_safefree(old_conn->options);
3612   Curl_safefree(old_conn->http_proxy.user);
3613   Curl_safefree(old_conn->socks_proxy.user);
3614   Curl_safefree(old_conn->http_proxy.passwd);
3615   Curl_safefree(old_conn->socks_proxy.passwd);
3616   Curl_safefree(old_conn->localdev);
3617 
3618   Curl_llist_destroy(&old_conn->send_pipe, NULL);
3619   Curl_llist_destroy(&old_conn->recv_pipe, NULL);
3620 
3621   Curl_safefree(old_conn->master_buffer);
3622 
3623 #ifdef USE_UNIX_SOCKETS
3624   Curl_safefree(old_conn->unix_domain_socket);
3625 #endif
3626 }
3627 
3628 /**
3629  * create_conn() sets up a new connectdata struct, or re-uses an already
3630  * existing one, and resolves host name.
3631  *
3632  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
3633  * response will be coming asynchronously. If *async is FALSE, the name is
3634  * already resolved.
3635  *
3636  * @param data The sessionhandle pointer
3637  * @param in_connect is set to the next connection data pointer
3638  * @param async is set TRUE when an async DNS resolution is pending
3639  * @see Curl_setup_conn()
3640  *
3641  * *NOTE* this function assigns the conn->data pointer!
3642  */
3643 
create_conn(struct Curl_easy * data,struct connectdata ** in_connect,bool * async)3644 static CURLcode create_conn(struct Curl_easy *data,
3645                             struct connectdata **in_connect,
3646                             bool *async)
3647 {
3648   CURLcode result = CURLE_OK;
3649   struct connectdata *conn;
3650   struct connectdata *conn_temp = NULL;
3651   bool reuse;
3652   bool connections_available = TRUE;
3653   bool force_reuse = FALSE;
3654   bool waitpipe = FALSE;
3655   size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3656   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3657 
3658   *async = FALSE;
3659   *in_connect = NULL;
3660 
3661   /*************************************************************
3662    * Check input data
3663    *************************************************************/
3664   if(!data->change.url) {
3665     result = CURLE_URL_MALFORMAT;
3666     goto out;
3667   }
3668 
3669   /* First, split up the current URL in parts so that we can use the
3670      parts for checking against the already present connections. In order
3671      to not have to modify everything at once, we allocate a temporary
3672      connection data struct and fill in for comparison purposes. */
3673   conn = allocate_conn(data);
3674 
3675   if(!conn) {
3676     result = CURLE_OUT_OF_MEMORY;
3677     goto out;
3678   }
3679 
3680   /* We must set the return variable as soon as possible, so that our
3681      parent can cleanup any possible allocs we may have done before
3682      any failure */
3683   *in_connect = conn;
3684 
3685   result = parseurlandfillconn(data, conn);
3686   if(result)
3687     goto out;
3688 
3689   if(data->set.str[STRING_BEARER]) {
3690     conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
3691     if(!conn->oauth_bearer) {
3692       result = CURLE_OUT_OF_MEMORY;
3693       goto out;
3694     }
3695   }
3696 
3697 #ifdef USE_UNIX_SOCKETS
3698   if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3699     conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3700     if(conn->unix_domain_socket == NULL) {
3701       result = CURLE_OUT_OF_MEMORY;
3702       goto out;
3703     }
3704     conn->abstract_unix_socket = data->set.abstract_unix_socket;
3705   }
3706 #endif
3707 
3708   /* After the unix socket init but before the proxy vars are used, parse and
3709      initialize the proxy vars */
3710 #ifndef CURL_DISABLE_PROXY
3711   result = create_conn_helper_init_proxy(conn);
3712   if(result)
3713     goto out;
3714 #endif
3715 
3716   /*************************************************************
3717    * If the protocol is using SSL and HTTP proxy is used, we set
3718    * the tunnel_proxy bit.
3719    *************************************************************/
3720   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3721     conn->bits.tunnel_proxy = TRUE;
3722 
3723   /*************************************************************
3724    * Figure out the remote port number and fix it in the URL
3725    *************************************************************/
3726   result = parse_remote_port(data, conn);
3727   if(result)
3728     goto out;
3729 
3730   /* Check for overridden login details and set them accordingly so they
3731      they are known when protocol->setup_connection is called! */
3732   result = override_login(data, conn, &conn->user, &conn->passwd,
3733                           &conn->options);
3734   if(result)
3735     goto out;
3736 
3737   result = set_login(conn); /* default credentials */
3738   if(result)
3739     goto out;
3740 
3741   /*************************************************************
3742    * Process the "connect to" linked list of hostname/port mappings.
3743    * Do this after the remote port number has been fixed in the URL.
3744    *************************************************************/
3745   result = parse_connect_to_slist(data, conn, data->set.connect_to);
3746   if(result)
3747     goto out;
3748 
3749   /*************************************************************
3750    * IDN-convert the hostnames
3751    *************************************************************/
3752   result = idnconvert_hostname(conn, &conn->host);
3753   if(result)
3754     goto out;
3755   if(conn->bits.conn_to_host) {
3756     result = idnconvert_hostname(conn, &conn->conn_to_host);
3757     if(result)
3758       goto out;
3759   }
3760   if(conn->bits.httpproxy) {
3761     result = idnconvert_hostname(conn, &conn->http_proxy.host);
3762     if(result)
3763       goto out;
3764   }
3765   if(conn->bits.socksproxy) {
3766     result = idnconvert_hostname(conn, &conn->socks_proxy.host);
3767     if(result)
3768       goto out;
3769   }
3770 
3771   /*************************************************************
3772    * Check whether the host and the "connect to host" are equal.
3773    * Do this after the hostnames have been IDN-converted.
3774    *************************************************************/
3775   if(conn->bits.conn_to_host &&
3776      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3777     conn->bits.conn_to_host = FALSE;
3778   }
3779 
3780   /*************************************************************
3781    * Check whether the port and the "connect to port" are equal.
3782    * Do this after the remote port number has been fixed in the URL.
3783    *************************************************************/
3784   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3785     conn->bits.conn_to_port = FALSE;
3786   }
3787 
3788   /*************************************************************
3789    * If the "connect to" feature is used with an HTTP proxy,
3790    * we set the tunnel_proxy bit.
3791    *************************************************************/
3792   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3793       conn->bits.httpproxy)
3794     conn->bits.tunnel_proxy = TRUE;
3795 
3796   /*************************************************************
3797    * Setup internals depending on protocol. Needs to be done after
3798    * we figured out what/if proxy to use.
3799    *************************************************************/
3800   result = setup_connection_internals(conn);
3801   if(result)
3802     goto out;
3803 
3804   conn->recv[FIRSTSOCKET] = Curl_recv_plain;
3805   conn->send[FIRSTSOCKET] = Curl_send_plain;
3806   conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
3807   conn->send[SECONDARYSOCKET] = Curl_send_plain;
3808 
3809   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3810 
3811   /***********************************************************************
3812    * file: is a special case in that it doesn't need a network connection
3813    ***********************************************************************/
3814 #ifndef CURL_DISABLE_FILE
3815   if(conn->handler->flags & PROTOPT_NONETWORK) {
3816     bool done;
3817     /* this is supposed to be the connect function so we better at least check
3818        that the file is present here! */
3819     DEBUGASSERT(conn->handler->connect_it);
3820     Curl_persistconninfo(conn);
3821     result = conn->handler->connect_it(conn, &done);
3822 
3823     /* Setup a "faked" transfer that'll do nothing */
3824     if(!result) {
3825       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
3826 
3827       result = Curl_conncache_add_conn(data->state.conn_cache, conn);
3828       if(result)
3829         goto out;
3830 
3831       /*
3832        * Setup whatever necessary for a resumed transfer
3833        */
3834       result = setup_range(data);
3835       if(result) {
3836         DEBUGASSERT(conn->handler->done);
3837         /* we ignore the return code for the protocol-specific DONE */
3838         (void)conn->handler->done(conn, result, FALSE);
3839         goto out;
3840       }
3841       Curl_attach_connnection(data, conn);
3842       Curl_setup_transfer(data, -1, -1, FALSE, -1);
3843     }
3844 
3845     /* since we skip do_init() */
3846     Curl_init_do(data, conn);
3847 
3848     goto out;
3849   }
3850 #endif
3851 
3852   /* Get a cloned copy of the SSL config situation stored in the
3853      connection struct. But to get this going nicely, we must first make
3854      sure that the strings in the master copy are pointing to the correct
3855      strings in the session handle strings array!
3856 
3857      Keep in mind that the pointers in the master copy are pointing to strings
3858      that will be freed as part of the Curl_easy struct, but all cloned
3859      copies will be separately allocated.
3860   */
3861   data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
3862   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
3863   data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
3864   data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
3865   data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
3866   data->set.proxy_ssl.primary.random_file =
3867     data->set.str[STRING_SSL_RANDOM_FILE];
3868   data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3869   data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3870   data->set.ssl.primary.cipher_list =
3871     data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
3872   data->set.proxy_ssl.primary.cipher_list =
3873     data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
3874   data->set.ssl.primary.cipher_list13 =
3875     data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
3876   data->set.proxy_ssl.primary.cipher_list13 =
3877     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
3878 
3879   data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
3880   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
3881   data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
3882   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
3883   data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
3884   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
3885   data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
3886   data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
3887   data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
3888   data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
3889   data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
3890   data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
3891   data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
3892   data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
3893   data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
3894   data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
3895 #ifdef USE_TLS_SRP
3896   data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
3897   data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
3898   data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
3899   data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
3900 #endif
3901 
3902   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
3903      &conn->ssl_config)) {
3904     result = CURLE_OUT_OF_MEMORY;
3905     goto out;
3906   }
3907 
3908   if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
3909                                     &conn->proxy_ssl_config)) {
3910     result = CURLE_OUT_OF_MEMORY;
3911     goto out;
3912   }
3913 
3914   prune_dead_connections(data);
3915 
3916   /*************************************************************
3917    * Check the current list of connections to see if we can
3918    * re-use an already existing one or if we have to create a
3919    * new one.
3920    *************************************************************/
3921 
3922   DEBUGASSERT(conn->user);
3923   DEBUGASSERT(conn->passwd);
3924 
3925   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
3926      we only acknowledge this option if this is not a re-used connection
3927      already (which happens due to follow-location or during a HTTP
3928      authentication phase). CONNECT_ONLY transfers also refuse reuse. */
3929   if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
3930      data->set.connect_only)
3931     reuse = FALSE;
3932   else
3933     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
3934 
3935   /* If we found a reusable connection that is now marked as in use, we may
3936      still want to open a new connection if we are pipelining. */
3937   if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
3938     size_t pipelen = conn_temp->send_pipe.size + conn_temp->recv_pipe.size;
3939     if(pipelen > 0) {
3940       infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
3941             conn_temp->connection_id, pipelen);
3942 
3943       if(Curl_conncache_bundle_size(conn_temp) < max_host_connections &&
3944          Curl_conncache_size(data) < max_total_connections) {
3945         /* We want a new connection anyway */
3946         reuse = FALSE;
3947 
3948         infof(data, "We can reuse, but we want a new connection anyway\n");
3949         Curl_conncache_return_conn(conn_temp);
3950       }
3951     }
3952   }
3953 
3954   if(reuse) {
3955     /*
3956      * We already have a connection for this, we got the former connection
3957      * in the conn_temp variable and thus we need to cleanup the one we
3958      * just allocated before we can move along and use the previously
3959      * existing one.
3960      */
3961     reuse_conn(conn, conn_temp);
3962 #ifdef USE_SSL
3963     free(conn->ssl_extra);
3964 #endif
3965     free(conn);          /* we don't need this anymore */
3966     conn = conn_temp;
3967     *in_connect = conn;
3968 
3969     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
3970           conn->connection_id,
3971           conn->bits.proxy?"proxy":"host",
3972           conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3973           conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3974                                        conn->host.dispname);
3975   }
3976   else {
3977     /* We have decided that we want a new connection. However, we may not
3978        be able to do that if we have reached the limit of how many
3979        connections we are allowed to open. */
3980 
3981     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
3982       /* The protocol wants it, so set the bits if enabled in the easy handle
3983          (default) */
3984       if(data->set.ssl_enable_alpn)
3985         conn->bits.tls_enable_alpn = TRUE;
3986       if(data->set.ssl_enable_npn)
3987         conn->bits.tls_enable_npn = TRUE;
3988     }
3989 
3990     if(waitpipe)
3991       /* There is a connection that *might* become usable for pipelining
3992          "soon", and we wait for that */
3993       connections_available = FALSE;
3994     else {
3995       /* this gets a lock on the conncache */
3996       struct connectbundle *bundle =
3997         Curl_conncache_find_bundle(conn, data->state.conn_cache);
3998 
3999       if(max_host_connections > 0 && bundle &&
4000          (bundle->num_connections >= max_host_connections)) {
4001         struct connectdata *conn_candidate;
4002 
4003         /* The bundle is full. Extract the oldest connection. */
4004         conn_candidate = Curl_conncache_extract_bundle(data, bundle);
4005         Curl_conncache_unlock(data);
4006 
4007         if(conn_candidate)
4008           (void)Curl_disconnect(data, conn_candidate,
4009                                 /* dead_connection */ FALSE);
4010         else {
4011           infof(data, "No more connections allowed to host: %zu\n",
4012                 max_host_connections);
4013           connections_available = FALSE;
4014         }
4015       }
4016       else
4017         Curl_conncache_unlock(data);
4018 
4019     }
4020 
4021     if(connections_available &&
4022        (max_total_connections > 0) &&
4023        (Curl_conncache_size(data) >= max_total_connections)) {
4024       struct connectdata *conn_candidate;
4025 
4026       /* The cache is full. Let's see if we can kill a connection. */
4027       conn_candidate = Curl_conncache_extract_oldest(data);
4028       if(conn_candidate)
4029         (void)Curl_disconnect(data, conn_candidate,
4030                               /* dead_connection */ FALSE);
4031       else {
4032         infof(data, "No connections available in cache\n");
4033         connections_available = FALSE;
4034       }
4035     }
4036 
4037     if(!connections_available) {
4038       infof(data, "No connections available.\n");
4039 
4040       conn_free(conn);
4041       *in_connect = NULL;
4042 
4043       result = CURLE_NO_CONNECTION_AVAILABLE;
4044       goto out;
4045     }
4046     else {
4047       /*
4048        * This is a brand new connection, so let's store it in the connection
4049        * cache of ours!
4050        */
4051       result = Curl_conncache_add_conn(data->state.conn_cache, conn);
4052       if(result)
4053         goto out;
4054     }
4055 
4056 #if defined(USE_NTLM)
4057     /* If NTLM is requested in a part of this connection, make sure we don't
4058        assume the state is fine as this is a fresh connection and NTLM is
4059        connection based. */
4060     if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
4061        data->state.authhost.done) {
4062       infof(data, "NTLM picked AND auth done set, clear picked!\n");
4063       data->state.authhost.picked = CURLAUTH_NONE;
4064       data->state.authhost.done = FALSE;
4065     }
4066 
4067     if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
4068        data->state.authproxy.done) {
4069       infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
4070       data->state.authproxy.picked = CURLAUTH_NONE;
4071       data->state.authproxy.done = FALSE;
4072     }
4073 #endif
4074   }
4075 
4076   /* Setup and init stuff before DO starts, in preparing for the transfer. */
4077   Curl_init_do(data, conn);
4078 
4079   /*
4080    * Setup whatever necessary for a resumed transfer
4081    */
4082   result = setup_range(data);
4083   if(result)
4084     goto out;
4085 
4086   /* Continue connectdata initialization here. */
4087 
4088   /*
4089    * Inherit the proper values from the urldata struct AFTER we have arranged
4090    * the persistent connection stuff
4091    */
4092   conn->seek_func = data->set.seek_func;
4093   conn->seek_client = data->set.seek_client;
4094 
4095   /*************************************************************
4096    * Resolve the address of the server or proxy
4097    *************************************************************/
4098   result = resolve_server(data, conn, async);
4099 
4100   /* Strip trailing dots. resolve_server copied the name. */
4101   strip_trailing_dot(&conn->host);
4102   if(conn->bits.httpproxy)
4103     strip_trailing_dot(&conn->http_proxy.host);
4104   if(conn->bits.socksproxy)
4105     strip_trailing_dot(&conn->socks_proxy.host);
4106   if(conn->bits.conn_to_host)
4107     strip_trailing_dot(&conn->conn_to_host);
4108 
4109 out:
4110   return result;
4111 }
4112 
4113 /* Curl_setup_conn() is called after the name resolve initiated in
4114  * create_conn() is all done.
4115  *
4116  * Curl_setup_conn() also handles reused connections
4117  *
4118  * conn->data MUST already have been setup fine (in create_conn)
4119  */
4120 
Curl_setup_conn(struct connectdata * conn,bool * protocol_done)4121 CURLcode Curl_setup_conn(struct connectdata *conn,
4122                          bool *protocol_done)
4123 {
4124   CURLcode result = CURLE_OK;
4125   struct Curl_easy *data = conn->data;
4126 
4127   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
4128 
4129   if(conn->handler->flags & PROTOPT_NONETWORK) {
4130     /* nothing to setup when not using a network */
4131     *protocol_done = TRUE;
4132     return result;
4133   }
4134   *protocol_done = FALSE; /* default to not done */
4135 
4136   /* set proxy_connect_closed to false unconditionally already here since it
4137      is used strictly to provide extra information to a parent function in the
4138      case of proxy CONNECT failures and we must make sure we don't have it
4139      lingering set from a previous invoke */
4140   conn->bits.proxy_connect_closed = FALSE;
4141 
4142   /*
4143    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
4144    * basically anything through a http proxy we can't limit this based on
4145    * protocol.
4146    */
4147   if(data->set.str[STRING_USERAGENT]) {
4148     Curl_safefree(conn->allocptr.uagent);
4149     conn->allocptr.uagent =
4150       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
4151     if(!conn->allocptr.uagent)
4152       return CURLE_OUT_OF_MEMORY;
4153   }
4154 
4155   data->req.headerbytecount = 0;
4156 
4157 #ifdef CURL_DO_LINEEND_CONV
4158   data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
4159 #endif /* CURL_DO_LINEEND_CONV */
4160 
4161   /* set start time here for timeout purposes in the connect procedure, it
4162      is later set again for the progress meter purpose */
4163   conn->now = Curl_now();
4164 
4165   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
4166     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
4167     result = Curl_connecthost(conn, conn->dns_entry);
4168     if(result)
4169       return result;
4170   }
4171   else {
4172     Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
4173     Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
4174     conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
4175     *protocol_done = TRUE;
4176     Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
4177     Curl_verboseconnect(conn);
4178   }
4179 
4180   conn->now = Curl_now(); /* time this *after* the connect is done, we set
4181                              this here perhaps a second time */
4182   return result;
4183 }
4184 
Curl_connect(struct Curl_easy * data,bool * asyncp,bool * protocol_done)4185 CURLcode Curl_connect(struct Curl_easy *data,
4186                       bool *asyncp,
4187                       bool *protocol_done)
4188 {
4189   CURLcode result;
4190   struct connectdata *conn;
4191 
4192   *asyncp = FALSE; /* assume synchronous resolves by default */
4193 
4194   /* init the single-transfer specific data */
4195   Curl_free_request_state(data);
4196   memset(&data->req, 0, sizeof(struct SingleRequest));
4197   data->req.maxdownload = -1;
4198 
4199   /* call the stuff that needs to be called */
4200   result = create_conn(data, &conn, asyncp);
4201 
4202   if(!result) {
4203     if(CONN_INUSE(conn))
4204       /* pipelining */
4205       *protocol_done = TRUE;
4206     else if(!*asyncp) {
4207       /* DNS resolution is done: that's either because this is a reused
4208          connection, in which case DNS was unnecessary, or because DNS
4209          really did finish already (synch resolver/fast async resolve) */
4210       result = Curl_setup_conn(conn, protocol_done);
4211     }
4212   }
4213 
4214   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
4215     return result;
4216   }
4217   else if(result && conn) {
4218     /* We're not allowed to return failure with memory left allocated in the
4219        connectdata struct, free those here */
4220     Curl_disconnect(data, conn, TRUE);
4221   }
4222   else if(!data->conn)
4223     /* FILE: transfers already have the connection attached */
4224     Curl_attach_connnection(data, conn);
4225 
4226   return result;
4227 }
4228 
4229 /*
4230  * Curl_init_do() inits the readwrite session. This is inited each time (in
4231  * the DO function before the protocol-specific DO functions are invoked) for
4232  * a transfer, sometimes multiple times on the same Curl_easy. Make sure
4233  * nothing in here depends on stuff that are setup dynamically for the
4234  * transfer.
4235  *
4236  * Allow this function to get called with 'conn' set to NULL.
4237  */
4238 
Curl_init_do(struct Curl_easy * data,struct connectdata * conn)4239 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
4240 {
4241   struct SingleRequest *k = &data->req;
4242 
4243   if(conn) {
4244     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
4245                                    use */
4246     /* if the protocol used doesn't support wildcards, switch it off */
4247     if(data->state.wildcardmatch &&
4248        !(conn->handler->flags & PROTOPT_WILDCARD))
4249       data->state.wildcardmatch = FALSE;
4250   }
4251 
4252   data->state.done = FALSE; /* *_done() is not called yet */
4253   data->state.expect100header = FALSE;
4254 
4255 
4256   if(data->set.opt_no_body)
4257     /* in HTTP lingo, no body means using the HEAD request... */
4258     data->set.httpreq = HTTPREQ_HEAD;
4259   else if(HTTPREQ_HEAD == data->set.httpreq)
4260     /* ... but if unset there really is no perfect method that is the
4261        "opposite" of HEAD but in reality most people probably think GET
4262        then. The important thing is that we can't let it remain HEAD if the
4263        opt_no_body is set FALSE since then we'll behave wrong when getting
4264        HTTP. */
4265     data->set.httpreq = HTTPREQ_GET;
4266 
4267   k->start = Curl_now(); /* start time */
4268   k->now = k->start;   /* current time is now */
4269   k->header = TRUE; /* assume header */
4270 
4271   k->bytecount = 0;
4272 
4273   k->buf = data->state.buffer;
4274   k->hbufp = data->state.headerbuff;
4275   k->ignorebody = FALSE;
4276 
4277   Curl_speedinit(data);
4278 
4279   Curl_pgrsSetUploadCounter(data, 0);
4280   Curl_pgrsSetDownloadCounter(data, 0);
4281 
4282   return CURLE_OK;
4283 }
4284 
4285 /*
4286 * get_protocol_family()
4287 *
4288 * This is used to return the protocol family for a given protocol.
4289 *
4290 * Parameters:
4291 *
4292 * protocol  [in]  - A single bit protocol identifier such as HTTP or HTTPS.
4293 *
4294 * Returns the family as a single bit protocol identifier.
4295 */
4296 
get_protocol_family(unsigned int protocol)4297 static unsigned int get_protocol_family(unsigned int protocol)
4298 {
4299   unsigned int family;
4300 
4301   switch(protocol) {
4302   case CURLPROTO_HTTP:
4303   case CURLPROTO_HTTPS:
4304     family = CURLPROTO_HTTP;
4305     break;
4306 
4307   case CURLPROTO_FTP:
4308   case CURLPROTO_FTPS:
4309     family = CURLPROTO_FTP;
4310     break;
4311 
4312   case CURLPROTO_SCP:
4313     family = CURLPROTO_SCP;
4314     break;
4315 
4316   case CURLPROTO_SFTP:
4317     family = CURLPROTO_SFTP;
4318     break;
4319 
4320   case CURLPROTO_TELNET:
4321     family = CURLPROTO_TELNET;
4322     break;
4323 
4324   case CURLPROTO_LDAP:
4325   case CURLPROTO_LDAPS:
4326     family = CURLPROTO_LDAP;
4327     break;
4328 
4329   case CURLPROTO_DICT:
4330     family = CURLPROTO_DICT;
4331     break;
4332 
4333   case CURLPROTO_FILE:
4334     family = CURLPROTO_FILE;
4335     break;
4336 
4337   case CURLPROTO_TFTP:
4338     family = CURLPROTO_TFTP;
4339     break;
4340 
4341   case CURLPROTO_IMAP:
4342   case CURLPROTO_IMAPS:
4343     family = CURLPROTO_IMAP;
4344     break;
4345 
4346   case CURLPROTO_POP3:
4347   case CURLPROTO_POP3S:
4348     family = CURLPROTO_POP3;
4349     break;
4350 
4351   case CURLPROTO_SMTP:
4352   case CURLPROTO_SMTPS:
4353       family = CURLPROTO_SMTP;
4354       break;
4355 
4356   case CURLPROTO_RTSP:
4357     family = CURLPROTO_RTSP;
4358     break;
4359 
4360   case CURLPROTO_RTMP:
4361   case CURLPROTO_RTMPS:
4362     family = CURLPROTO_RTMP;
4363     break;
4364 
4365   case CURLPROTO_RTMPT:
4366   case CURLPROTO_RTMPTS:
4367     family = CURLPROTO_RTMPT;
4368     break;
4369 
4370   case CURLPROTO_RTMPE:
4371     family = CURLPROTO_RTMPE;
4372     break;
4373 
4374   case CURLPROTO_RTMPTE:
4375     family = CURLPROTO_RTMPTE;
4376     break;
4377 
4378   case CURLPROTO_GOPHER:
4379     family = CURLPROTO_GOPHER;
4380     break;
4381 
4382   case CURLPROTO_SMB:
4383   case CURLPROTO_SMBS:
4384     family = CURLPROTO_SMB;
4385     break;
4386 
4387   default:
4388       family = 0;
4389       break;
4390   }
4391 
4392   return family;
4393 }
4394 
4395 
4396 /*
4397  * Wrapper to call functions in Curl_conncache_foreach()
4398  *
4399  * Returns always 0.
4400  */
conn_upkeep(struct connectdata * conn,void * param)4401 static int conn_upkeep(struct connectdata *conn,
4402                        void *param)
4403 {
4404   /* Param is unused. */
4405   (void)param;
4406 
4407   if(conn->handler->connection_check) {
4408     /* Do a protocol-specific keepalive check on the connection. */
4409     conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
4410   }
4411 
4412   return 0; /* continue iteration */
4413 }
4414 
Curl_upkeep(struct conncache * conn_cache,void * data)4415 CURLcode Curl_upkeep(struct conncache *conn_cache,
4416                           void *data)
4417 {
4418   /* Loop over every connection and make connection alive. */
4419   Curl_conncache_foreach(data,
4420                          conn_cache,
4421                          data,
4422                          conn_upkeep);
4423   return CURLE_OK;
4424 }
4425